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