]> bbs.cooldavid.org Git - net-next-2.6.git/blame - fs/hostfs/hostfs_kern.c
uml: make hostfs_setattr() support operations on unlinked open files
[net-next-2.6.git] / fs / hostfs / hostfs_kern.c
CommitLineData
1da177e4
LT
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 *
5 * Ported the filesystem routines to 2.5.
6 * 2003-02-10 Petr Baudis <pasky@ucw.cz>
7 */
8
9#include <linux/stddef.h>
10#include <linux/fs.h>
1da177e4
LT
11#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/slab.h>
14#include <linux/pagemap.h>
15#include <linux/blkdev.h>
16#include <linux/list.h>
1da177e4
LT
17#include <linux/statfs.h>
18#include <linux/kdev_t.h>
19#include <asm/uaccess.h>
20#include "hostfs.h"
21#include "kern_util.h"
22#include "kern.h"
1da177e4
LT
23#include "init.h"
24
25struct hostfs_inode_info {
26 char *host_filename;
27 int fd;
28 int mode;
29 struct inode vfs_inode;
30};
31
32static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
33{
34 return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
35}
36
680b0da9 37#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode)
1da177e4
LT
38
39int hostfs_d_delete(struct dentry *dentry)
40{
41 return(1);
42}
43
44struct dentry_operations hostfs_dentry_ops = {
45 .d_delete = hostfs_d_delete,
46};
47
48/* Changed in hostfs_args before the kernel starts running */
a6eb0be6 49static char *root_ino = "";
1da177e4
LT
50static int append = 0;
51
52#define HOSTFS_SUPER_MAGIC 0x00c0ffee
53
92e1d5be
AV
54static const struct inode_operations hostfs_iops;
55static const struct inode_operations hostfs_dir_iops;
f5e54d6e 56static const struct address_space_operations hostfs_link_aops;
1da177e4
LT
57
58#ifndef MODULE
59static int __init hostfs_args(char *options, int *add)
60{
61 char *ptr;
62
63 ptr = strchr(options, ',');
64 if(ptr != NULL)
65 *ptr++ = '\0';
66 if(*options != '\0')
67 root_ino = options;
68
69 options = ptr;
70 while(options){
71 ptr = strchr(options, ',');
72 if(ptr != NULL)
73 *ptr++ = '\0';
74 if(*options != '\0'){
75 if(!strcmp(options, "append"))
76 append = 1;
77 else printf("hostfs_args - unsupported option - %s\n",
78 options);
79 }
80 options = ptr;
81 }
82 return(0);
83}
84
85__uml_setup("hostfs=", hostfs_args,
86"hostfs=<root dir>,<flags>,...\n"
87" This is used to set hostfs parameters. The root directory argument\n"
88" is used to confine all hostfs mounts to within the specified directory\n"
89" tree on the host. If this isn't specified, then a user inside UML can\n"
90" mount anything on the host that's accessible to the user that's running\n"
91" it.\n"
92" The only flag currently supported is 'append', which specifies that all\n"
93" files opened by hostfs will be opened in append mode.\n\n"
94);
95#endif
96
97static char *dentry_name(struct dentry *dentry, int extra)
98{
99 struct dentry *parent;
100 char *root, *name;
101 int len;
102
103 len = 0;
104 parent = dentry;
105 while(parent->d_parent != parent){
106 len += parent->d_name.len + 1;
107 parent = parent->d_parent;
108 }
109
110 root = HOSTFS_I(parent->d_inode)->host_filename;
111 len += strlen(root);
112 name = kmalloc(len + extra + 1, GFP_KERNEL);
113 if(name == NULL) return(NULL);
114
115 name[len] = '\0';
116 parent = dentry;
117 while(parent->d_parent != parent){
118 len -= parent->d_name.len + 1;
119 name[len] = '/';
120 strncpy(&name[len + 1], parent->d_name.name,
121 parent->d_name.len);
122 parent = parent->d_parent;
123 }
124 strncpy(name, root, strlen(root));
125 return(name);
126}
127
128static char *inode_name(struct inode *ino, int extra)
129{
130 struct dentry *dentry;
131
132 dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
133 return(dentry_name(dentry, extra));
134}
135
136static int read_name(struct inode *ino, char *name)
137{
138 /* The non-int inode fields are copied into ints by stat_file and
139 * then copied into the inode because passing the actual pointers
140 * in and having them treated as int * breaks on big-endian machines
141 */
142 int err;
143 int i_mode, i_nlink, i_blksize;
144 unsigned long long i_size;
145 unsigned long long i_ino;
146 unsigned long long i_blocks;
147
148 err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid,
149 &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime,
5822b7fa 150 &ino->i_ctime, &i_blksize, &i_blocks, -1);
1da177e4
LT
151 if(err)
152 return(err);
153
154 ino->i_ino = i_ino;
155 ino->i_mode = i_mode;
156 ino->i_nlink = i_nlink;
157 ino->i_size = i_size;
1da177e4 158 ino->i_blocks = i_blocks;
1da177e4
LT
159 return(0);
160}
161
162static char *follow_link(char *link)
163{
164 int len, n;
165 char *name, *resolved, *end;
166
167 len = 64;
168 while(1){
169 n = -ENOMEM;
170 name = kmalloc(len, GFP_KERNEL);
171 if(name == NULL)
172 goto out;
173
174 n = do_readlink(link, name, len);
175 if(n < len)
176 break;
177 len *= 2;
178 kfree(name);
179 }
180 if(n < 0)
181 goto out_free;
182
183 if(*name == '/')
184 return(name);
185
186 end = strrchr(link, '/');
187 if(end == NULL)
188 return(name);
189
190 *(end + 1) = '\0';
191 len = strlen(link) + strlen(name) + 1;
192
193 resolved = kmalloc(len, GFP_KERNEL);
194 if(resolved == NULL){
195 n = -ENOMEM;
196 goto out_free;
197 }
198
199 sprintf(resolved, "%s%s", link, name);
200 kfree(name);
201 kfree(link);
202 return(resolved);
203
204 out_free:
205 kfree(name);
206 out:
207 return(ERR_PTR(n));
208}
209
210static int read_inode(struct inode *ino)
211{
212 char *name;
213 int err = 0;
214
215 /* Unfortunately, we are called from iget() when we don't have a dentry
216 * allocated yet.
217 */
218 if(list_empty(&ino->i_dentry))
219 goto out;
220
221 err = -ENOMEM;
222 name = inode_name(ino, 0);
223 if(name == NULL)
224 goto out;
225
226 if(file_type(name, NULL, NULL) == OS_TYPE_SYMLINK){
227 name = follow_link(name);
228 if(IS_ERR(name)){
229 err = PTR_ERR(name);
230 goto out;
231 }
232 }
233
234 err = read_name(ino, name);
235 kfree(name);
236 out:
237 return(err);
238}
239
726c3342 240int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
1da177e4
LT
241{
242 /* do_statfs uses struct statfs64 internally, but the linux kernel
243 * struct statfs still has 32-bit versions for most of these fields,
244 * so we convert them here
245 */
246 int err;
247 long long f_blocks;
248 long long f_bfree;
249 long long f_bavail;
250 long long f_files;
251 long long f_ffree;
252
726c3342 253 err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename,
1da177e4
LT
254 &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
255 &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
256 &sf->f_namelen, sf->f_spare);
257 if(err) return(err);
258 sf->f_blocks = f_blocks;
259 sf->f_bfree = f_bfree;
260 sf->f_bavail = f_bavail;
261 sf->f_files = f_files;
262 sf->f_ffree = f_ffree;
263 sf->f_type = HOSTFS_SUPER_MAGIC;
264 return(0);
265}
266
267static struct inode *hostfs_alloc_inode(struct super_block *sb)
268{
269 struct hostfs_inode_info *hi;
270
271 hi = kmalloc(sizeof(*hi), GFP_KERNEL);
272 if(hi == NULL)
273 return(NULL);
274
275 *hi = ((struct hostfs_inode_info) { .host_filename = NULL,
276 .fd = -1,
277 .mode = 0 });
278 inode_init_once(&hi->vfs_inode);
279 return(&hi->vfs_inode);
280}
281
282static void hostfs_delete_inode(struct inode *inode)
283{
fef26658 284 truncate_inode_pages(&inode->i_data, 0);
1da177e4
LT
285 if(HOSTFS_I(inode)->fd != -1) {
286 close_file(&HOSTFS_I(inode)->fd);
287 HOSTFS_I(inode)->fd = -1;
288 }
289 clear_inode(inode);
290}
291
292static void hostfs_destroy_inode(struct inode *inode)
293{
f99d49ad 294 kfree(HOSTFS_I(inode)->host_filename);
1da177e4
LT
295
296 /*XXX: This should not happen, probably. The check is here for
297 * additional safety.*/
298 if(HOSTFS_I(inode)->fd != -1) {
299 close_file(&HOSTFS_I(inode)->fd);
300 printk(KERN_DEBUG "Closing host fd in .destroy_inode\n");
301 }
302
303 kfree(HOSTFS_I(inode));
304}
305
306static void hostfs_read_inode(struct inode *inode)
307{
308 read_inode(inode);
309}
310
ee9b6d61 311static const struct super_operations hostfs_sbops = {
1da177e4
LT
312 .alloc_inode = hostfs_alloc_inode,
313 .drop_inode = generic_delete_inode,
314 .delete_inode = hostfs_delete_inode,
315 .destroy_inode = hostfs_destroy_inode,
316 .read_inode = hostfs_read_inode,
317 .statfs = hostfs_statfs,
318};
319
320int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
321{
322 void *dir;
323 char *name;
324 unsigned long long next, ino;
325 int error, len;
326
680b0da9 327 name = dentry_name(file->f_path.dentry, 0);
1da177e4
LT
328 if(name == NULL) return(-ENOMEM);
329 dir = open_dir(name, &error);
330 kfree(name);
331 if(dir == NULL) return(-error);
332 next = file->f_pos;
333 while((name = read_dir(dir, &next, &ino, &len)) != NULL){
334 error = (*filldir)(ent, name, len, file->f_pos,
335 ino, DT_UNKNOWN);
336 if(error) break;
337 file->f_pos = next;
338 }
339 close_dir(dir);
340 return(0);
341}
342
343int hostfs_file_open(struct inode *ino, struct file *file)
344{
345 char *name;
346 int mode = 0, r = 0, w = 0, fd;
347
348 mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
349 if((mode & HOSTFS_I(ino)->mode) == mode)
350 return(0);
351
352 /* The file may already have been opened, but with the wrong access,
353 * so this resets things and reopens the file with the new access.
354 */
355 if(HOSTFS_I(ino)->fd != -1){
356 close_file(&HOSTFS_I(ino)->fd);
357 HOSTFS_I(ino)->fd = -1;
358 }
359
360 HOSTFS_I(ino)->mode |= mode;
361 if(HOSTFS_I(ino)->mode & FMODE_READ)
362 r = 1;
363 if(HOSTFS_I(ino)->mode & FMODE_WRITE)
364 w = 1;
365 if(w)
366 r = 1;
367
680b0da9 368 name = dentry_name(file->f_path.dentry, 0);
1da177e4
LT
369 if(name == NULL)
370 return(-ENOMEM);
371
372 fd = open_file(name, r, w, append);
373 kfree(name);
374 if(fd < 0) return(fd);
375 FILE_HOSTFS_I(file)->fd = fd;
376
377 return(0);
378}
379
380int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
381{
a2d76bd8 382 return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync);
1da177e4
LT
383}
384
4b6f5d20 385static const struct file_operations hostfs_file_fops = {
1da177e4 386 .llseek = generic_file_llseek,
543ade1f 387 .read = do_sync_read,
1da177e4
LT
388 .sendfile = generic_file_sendfile,
389 .aio_read = generic_file_aio_read,
390 .aio_write = generic_file_aio_write,
543ade1f 391 .write = do_sync_write,
1da177e4
LT
392 .mmap = generic_file_mmap,
393 .open = hostfs_file_open,
394 .release = NULL,
395 .fsync = hostfs_fsync,
396};
397
4b6f5d20 398static const struct file_operations hostfs_dir_fops = {
1da177e4
LT
399 .llseek = generic_file_llseek,
400 .readdir = hostfs_readdir,
401 .read = generic_read_dir,
402};
403
404int hostfs_writepage(struct page *page, struct writeback_control *wbc)
405{
406 struct address_space *mapping = page->mapping;
407 struct inode *inode = mapping->host;
408 char *buffer;
409 unsigned long long base;
410 int count = PAGE_CACHE_SIZE;
411 int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
412 int err;
413
414 if (page->index >= end_index)
415 count = inode->i_size & (PAGE_CACHE_SIZE-1);
416
417 buffer = kmap(page);
418 base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
419
420 err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
421 if(err != count){
422 ClearPageUptodate(page);
423 goto out;
424 }
425
426 if (base > inode->i_size)
427 inode->i_size = base;
428
429 if (PageError(page))
430 ClearPageError(page);
431 err = 0;
432
433 out:
434 kunmap(page);
435
436 unlock_page(page);
437 return err;
438}
439
440int hostfs_readpage(struct file *file, struct page *page)
441{
442 char *buffer;
443 long long start;
444 int err = 0;
445
446 start = (long long) page->index << PAGE_CACHE_SHIFT;
447 buffer = kmap(page);
448 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
449 PAGE_CACHE_SIZE);
450 if(err < 0) goto out;
451
452 memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
453
454 flush_dcache_page(page);
455 SetPageUptodate(page);
456 if (PageError(page)) ClearPageError(page);
457 err = 0;
458 out:
459 kunmap(page);
460 unlock_page(page);
461 return(err);
462}
463
464int hostfs_prepare_write(struct file *file, struct page *page,
465 unsigned int from, unsigned int to)
466{
467 char *buffer;
468 long long start, tmp;
469 int err;
470
471 start = (long long) page->index << PAGE_CACHE_SHIFT;
472 buffer = kmap(page);
473 if(from != 0){
474 tmp = start;
475 err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer,
476 from);
477 if(err < 0) goto out;
478 }
479 if(to != PAGE_CACHE_SIZE){
480 start += to;
481 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to,
482 PAGE_CACHE_SIZE - to);
483 if(err < 0) goto out;
484 }
485 err = 0;
486 out:
487 kunmap(page);
488 return(err);
489}
490
491int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
492 unsigned to)
493{
494 struct address_space *mapping = page->mapping;
495 struct inode *inode = mapping->host;
496 char *buffer;
497 long long start;
498 int err = 0;
499
30f04a4e 500 start = (((long long) page->index) << PAGE_CACHE_SHIFT) + from;
1da177e4
LT
501 buffer = kmap(page);
502 err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
503 to - from);
504 if(err > 0) err = 0;
30f04a4e
PBG
505
506 /* Actually, if !err, write_file has added to-from to start, so, despite
507 * the appearance, we are comparing i_size against the _last_ written
508 * location, as we should. */
509
1da177e4
LT
510 if(!err && (start > inode->i_size))
511 inode->i_size = start;
512
513 kunmap(page);
514 return(err);
515}
516
f5e54d6e 517static const struct address_space_operations hostfs_aops = {
1da177e4
LT
518 .writepage = hostfs_writepage,
519 .readpage = hostfs_readpage,
ffa0aea6 520 .set_page_dirty = __set_page_dirty_nobuffers,
1da177e4
LT
521 .prepare_write = hostfs_prepare_write,
522 .commit_write = hostfs_commit_write
523};
524
525static int init_inode(struct inode *inode, struct dentry *dentry)
526{
527 char *name;
528 int type, err = -ENOMEM;
529 int maj, min;
530 dev_t rdev = 0;
531
532 if(dentry){
533 name = dentry_name(dentry, 0);
534 if(name == NULL)
535 goto out;
536 type = file_type(name, &maj, &min);
537 /*Reencode maj and min with the kernel encoding.*/
538 rdev = MKDEV(maj, min);
539 kfree(name);
540 }
541 else type = OS_TYPE_DIR;
542
543 err = 0;
544 if(type == OS_TYPE_SYMLINK)
545 inode->i_op = &page_symlink_inode_operations;
546 else if(type == OS_TYPE_DIR)
547 inode->i_op = &hostfs_dir_iops;
548 else inode->i_op = &hostfs_iops;
549
550 if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
551 else inode->i_fop = &hostfs_file_fops;
552
553 if(type == OS_TYPE_SYMLINK)
554 inode->i_mapping->a_ops = &hostfs_link_aops;
555 else inode->i_mapping->a_ops = &hostfs_aops;
556
557 switch (type) {
558 case OS_TYPE_CHARDEV:
559 init_special_inode(inode, S_IFCHR, rdev);
560 break;
561 case OS_TYPE_BLOCKDEV:
562 init_special_inode(inode, S_IFBLK, rdev);
563 break;
564 case OS_TYPE_FIFO:
565 init_special_inode(inode, S_IFIFO, 0);
566 break;
567 case OS_TYPE_SOCK:
568 init_special_inode(inode, S_IFSOCK, 0);
569 break;
570 }
571 out:
572 return(err);
573}
574
575int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
576 struct nameidata *nd)
577{
578 struct inode *inode;
579 char *name;
580 int error, fd;
581
582 error = -ENOMEM;
583 inode = iget(dir->i_sb, 0);
584 if(inode == NULL) goto out;
585
586 error = init_inode(inode, dentry);
587 if(error)
588 goto out_put;
589
590 error = -ENOMEM;
591 name = dentry_name(dentry, 0);
592 if(name == NULL)
593 goto out_put;
594
595 fd = file_create(name,
596 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
597 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
598 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
599 if(fd < 0)
600 error = fd;
601 else error = read_name(inode, name);
602
603 kfree(name);
604 if(error)
605 goto out_put;
606
607 HOSTFS_I(inode)->fd = fd;
608 HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
609 d_instantiate(dentry, inode);
610 return(0);
611
612 out_put:
613 iput(inode);
614 out:
615 return(error);
616}
617
618struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
619 struct nameidata *nd)
620{
621 struct inode *inode;
622 char *name;
623 int err;
624
625 err = -ENOMEM;
626 inode = iget(ino->i_sb, 0);
627 if(inode == NULL)
628 goto out;
629
630 err = init_inode(inode, dentry);
631 if(err)
632 goto out_put;
633
634 err = -ENOMEM;
635 name = dentry_name(dentry, 0);
636 if(name == NULL)
637 goto out_put;
638
639 err = read_name(inode, name);
640 kfree(name);
641 if(err == -ENOENT){
642 iput(inode);
643 inode = NULL;
644 }
645 else if(err)
646 goto out_put;
647
648 d_add(dentry, inode);
649 dentry->d_op = &hostfs_dentry_ops;
650 return(NULL);
651
652 out_put:
653 iput(inode);
654 out:
655 return(ERR_PTR(err));
656}
657
658static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
659{
660 char *file;
661 int len;
662
663 file = inode_name(ino, dentry->d_name.len + 1);
664 if(file == NULL) return(NULL);
665 strcat(file, "/");
666 len = strlen(file);
667 strncat(file, dentry->d_name.name, dentry->d_name.len);
668 file[len + dentry->d_name.len] = '\0';
669 return(file);
670}
671
672int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
673{
674 char *from_name, *to_name;
675 int err;
676
677 if((from_name = inode_dentry_name(ino, from)) == NULL)
678 return(-ENOMEM);
679 to_name = dentry_name(to, 0);
680 if(to_name == NULL){
681 kfree(from_name);
682 return(-ENOMEM);
683 }
684 err = link_file(to_name, from_name);
685 kfree(from_name);
686 kfree(to_name);
687 return(err);
688}
689
690int hostfs_unlink(struct inode *ino, struct dentry *dentry)
691{
692 char *file;
693 int err;
694
695 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
696 if(append)
697 return(-EPERM);
698
699 err = unlink_file(file);
700 kfree(file);
701 return(err);
702}
703
704int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
705{
706 char *file;
707 int err;
708
709 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
710 err = make_symlink(file, to);
711 kfree(file);
712 return(err);
713}
714
715int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
716{
717 char *file;
718 int err;
719
720 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
721 err = do_mkdir(file, mode);
722 kfree(file);
723 return(err);
724}
725
726int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
727{
728 char *file;
729 int err;
730
731 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
732 err = do_rmdir(file);
733 kfree(file);
734 return(err);
735}
736
737int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
738{
739 struct inode *inode;
740 char *name;
741 int err = -ENOMEM;
742
743 inode = iget(dir->i_sb, 0);
744 if(inode == NULL)
745 goto out;
746
747 err = init_inode(inode, dentry);
748 if(err)
749 goto out_put;
750
751 err = -ENOMEM;
752 name = dentry_name(dentry, 0);
753 if(name == NULL)
754 goto out_put;
755
756 init_special_inode(inode, mode, dev);
88f6cd0c 757 err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
1da177e4
LT
758 if(err)
759 goto out_free;
760
761 err = read_name(inode, name);
762 kfree(name);
763 if(err)
764 goto out_put;
765
766 d_instantiate(dentry, inode);
767 return(0);
768
769 out_free:
770 kfree(name);
771 out_put:
772 iput(inode);
773 out:
774 return(err);
775}
776
777int hostfs_rename(struct inode *from_ino, struct dentry *from,
778 struct inode *to_ino, struct dentry *to)
779{
780 char *from_name, *to_name;
781 int err;
782
783 if((from_name = inode_dentry_name(from_ino, from)) == NULL)
784 return(-ENOMEM);
785 if((to_name = inode_dentry_name(to_ino, to)) == NULL){
786 kfree(from_name);
787 return(-ENOMEM);
788 }
789 err = rename_file(from_name, to_name);
790 kfree(from_name);
791 kfree(to_name);
792 return(err);
793}
794
1da177e4
LT
795int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
796{
797 char *name;
798 int r = 0, w = 0, x = 0, err;
799
800 if (desired & MAY_READ) r = 1;
801 if (desired & MAY_WRITE) w = 1;
802 if (desired & MAY_EXEC) x = 1;
803 name = inode_name(ino, 0);
804 if (name == NULL) return(-ENOMEM);
805
806 if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
807 S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
808 err = 0;
809 else
810 err = access_file(name, r, w, x);
811 kfree(name);
812 if(!err)
813 err = generic_permission(ino, desired, NULL);
814 return err;
815}
816
817int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
818{
819 struct hostfs_iattr attrs;
820 char *name;
821 int err;
822
5822b7fa
AB
823 int fd = HOSTFS_I(dentry->d_inode)->fd;
824
1da177e4
LT
825 err = inode_change_ok(dentry->d_inode, attr);
826 if (err)
827 return err;
828
829 if(append)
830 attr->ia_valid &= ~ATTR_SIZE;
831
832 attrs.ia_valid = 0;
833 if(attr->ia_valid & ATTR_MODE){
834 attrs.ia_valid |= HOSTFS_ATTR_MODE;
835 attrs.ia_mode = attr->ia_mode;
836 }
837 if(attr->ia_valid & ATTR_UID){
1da177e4
LT
838 attrs.ia_valid |= HOSTFS_ATTR_UID;
839 attrs.ia_uid = attr->ia_uid;
840 }
841 if(attr->ia_valid & ATTR_GID){
1da177e4
LT
842 attrs.ia_valid |= HOSTFS_ATTR_GID;
843 attrs.ia_gid = attr->ia_gid;
844 }
845 if(attr->ia_valid & ATTR_SIZE){
846 attrs.ia_valid |= HOSTFS_ATTR_SIZE;
847 attrs.ia_size = attr->ia_size;
848 }
849 if(attr->ia_valid & ATTR_ATIME){
850 attrs.ia_valid |= HOSTFS_ATTR_ATIME;
851 attrs.ia_atime = attr->ia_atime;
852 }
853 if(attr->ia_valid & ATTR_MTIME){
854 attrs.ia_valid |= HOSTFS_ATTR_MTIME;
855 attrs.ia_mtime = attr->ia_mtime;
856 }
857 if(attr->ia_valid & ATTR_CTIME){
858 attrs.ia_valid |= HOSTFS_ATTR_CTIME;
859 attrs.ia_ctime = attr->ia_ctime;
860 }
861 if(attr->ia_valid & ATTR_ATIME_SET){
862 attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
863 }
864 if(attr->ia_valid & ATTR_MTIME_SET){
865 attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
866 }
867 name = dentry_name(dentry, 0);
868 if(name == NULL) return(-ENOMEM);
5822b7fa 869 err = set_attr(name, &attrs, fd);
1da177e4
LT
870 kfree(name);
871 if(err)
872 return(err);
873
874 return(inode_setattr(dentry->d_inode, attr));
875}
876
877int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
878 struct kstat *stat)
879{
880 generic_fillattr(dentry->d_inode, stat);
881 return(0);
882}
883
92e1d5be 884static const struct inode_operations hostfs_iops = {
1da177e4
LT
885 .create = hostfs_create,
886 .link = hostfs_link,
887 .unlink = hostfs_unlink,
888 .symlink = hostfs_symlink,
889 .mkdir = hostfs_mkdir,
890 .rmdir = hostfs_rmdir,
891 .mknod = hostfs_mknod,
892 .rename = hostfs_rename,
1da177e4
LT
893 .permission = hostfs_permission,
894 .setattr = hostfs_setattr,
895 .getattr = hostfs_getattr,
896};
897
92e1d5be 898static const struct inode_operations hostfs_dir_iops = {
1da177e4
LT
899 .create = hostfs_create,
900 .lookup = hostfs_lookup,
901 .link = hostfs_link,
902 .unlink = hostfs_unlink,
903 .symlink = hostfs_symlink,
904 .mkdir = hostfs_mkdir,
905 .rmdir = hostfs_rmdir,
906 .mknod = hostfs_mknod,
907 .rename = hostfs_rename,
1da177e4
LT
908 .permission = hostfs_permission,
909 .setattr = hostfs_setattr,
910 .getattr = hostfs_getattr,
911};
912
913int hostfs_link_readpage(struct file *file, struct page *page)
914{
915 char *buffer, *name;
1da177e4
LT
916 int err;
917
1da177e4
LT
918 buffer = kmap(page);
919 name = inode_name(page->mapping->host, 0);
920 if(name == NULL) return(-ENOMEM);
921 err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
922 kfree(name);
923 if(err == PAGE_CACHE_SIZE)
924 err = -E2BIG;
925 else if(err > 0){
926 flush_dcache_page(page);
927 SetPageUptodate(page);
928 if (PageError(page)) ClearPageError(page);
929 err = 0;
930 }
931 kunmap(page);
932 unlock_page(page);
933 return(err);
934}
935
f5e54d6e 936static const struct address_space_operations hostfs_link_aops = {
1da177e4
LT
937 .readpage = hostfs_link_readpage,
938};
939
940static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
941{
942 struct inode *root_inode;
75e8defb 943 char *host_root_path, *req_root = d;
1da177e4
LT
944 int err;
945
946 sb->s_blocksize = 1024;
947 sb->s_blocksize_bits = 10;
948 sb->s_magic = HOSTFS_SUPER_MAGIC;
949 sb->s_op = &hostfs_sbops;
950
a6eb0be6 951 /* NULL is printed as <NULL> by sprintf: avoid that. */
75e8defb
PBG
952 if (req_root == NULL)
953 req_root = "";
1da177e4
LT
954
955 err = -ENOMEM;
75e8defb
PBG
956 host_root_path = kmalloc(strlen(root_ino) + 1
957 + strlen(req_root) + 1, GFP_KERNEL);
958 if(host_root_path == NULL)
1da177e4
LT
959 goto out;
960
75e8defb 961 sprintf(host_root_path, "%s/%s", root_ino, req_root);
1da177e4
LT
962
963 root_inode = iget(sb, 0);
964 if(root_inode == NULL)
965 goto out_free;
966
967 err = init_inode(root_inode, NULL);
968 if(err)
969 goto out_put;
970
75e8defb
PBG
971 HOSTFS_I(root_inode)->host_filename = host_root_path;
972 /* Avoid that in the error path, iput(root_inode) frees again
973 * host_root_path through hostfs_destroy_inode! */
974 host_root_path = NULL;
1da177e4
LT
975
976 err = -ENOMEM;
977 sb->s_root = d_alloc_root(root_inode);
978 if(sb->s_root == NULL)
979 goto out_put;
980
981 err = read_inode(root_inode);
51a14110
JD
982 if(err){
983 /* No iput in this case because the dput does that for us */
984 dput(sb->s_root);
985 sb->s_root = NULL;
bca27113 986 goto out;
51a14110 987 }
1da177e4
LT
988
989 return(0);
990
991 out_put:
51a14110 992 iput(root_inode);
1da177e4 993 out_free:
75e8defb 994 kfree(host_root_path);
1da177e4
LT
995 out:
996 return(err);
997}
998
454e2398
DH
999static int hostfs_read_sb(struct file_system_type *type,
1000 int flags, const char *dev_name,
1001 void *data, struct vfsmount *mnt)
1da177e4 1002{
454e2398 1003 return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt);
1da177e4
LT
1004}
1005
1006static struct file_system_type hostfs_type = {
1007 .owner = THIS_MODULE,
1008 .name = "hostfs",
1009 .get_sb = hostfs_read_sb,
1010 .kill_sb = kill_anon_super,
1011 .fs_flags = 0,
1012};
1013
1014static int __init init_hostfs(void)
1015{
1016 return(register_filesystem(&hostfs_type));
1017}
1018
1019static void __exit exit_hostfs(void)
1020{
1021 unregister_filesystem(&hostfs_type);
1022}
1023
1024module_init(init_hostfs)
1025module_exit(exit_hostfs)
1026MODULE_LICENSE("GPL");
1027
1028/*
1029 * Overrides for Emacs so that we follow Linus's tabbing style.
1030 * Emacs will notice this stuff at the end of the file and automatically
1031 * adjust the settings for this buffer only. This must remain at the end
1032 * of the file.
1033 * ---------------------------------------------------------------------------
1034 * Local variables:
1035 * c-file-style: "linux"
1036 * End:
1037 */