blob: b82e3d9c879021ae9882158aa8df2080c73f144e [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;
159 ino->i_blksize = i_blksize;
160 ino->i_blocks = i_blocks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 return(0);
162}
163
164static char *follow_link(char *link)
165{
166 int len, n;
167 char *name, *resolved, *end;
168
169 len = 64;
170 while(1){
171 n = -ENOMEM;
172 name = kmalloc(len, GFP_KERNEL);
173 if(name == NULL)
174 goto out;
175
176 n = do_readlink(link, name, len);
177 if(n < len)
178 break;
179 len *= 2;
180 kfree(name);
181 }
182 if(n < 0)
183 goto out_free;
184
185 if(*name == '/')
186 return(name);
187
188 end = strrchr(link, '/');
189 if(end == NULL)
190 return(name);
191
192 *(end + 1) = '\0';
193 len = strlen(link) + strlen(name) + 1;
194
195 resolved = kmalloc(len, GFP_KERNEL);
196 if(resolved == NULL){
197 n = -ENOMEM;
198 goto out_free;
199 }
200
201 sprintf(resolved, "%s%s", link, name);
202 kfree(name);
203 kfree(link);
204 return(resolved);
205
206 out_free:
207 kfree(name);
208 out:
209 return(ERR_PTR(n));
210}
211
212static int read_inode(struct inode *ino)
213{
214 char *name;
215 int err = 0;
216
217 /* Unfortunately, we are called from iget() when we don't have a dentry
218 * allocated yet.
219 */
220 if(list_empty(&ino->i_dentry))
221 goto out;
222
223 err = -ENOMEM;
224 name = inode_name(ino, 0);
225 if(name == NULL)
226 goto out;
227
228 if(file_type(name, NULL, NULL) == OS_TYPE_SYMLINK){
229 name = follow_link(name);
230 if(IS_ERR(name)){
231 err = PTR_ERR(name);
232 goto out;
233 }
234 }
235
236 err = read_name(ino, name);
237 kfree(name);
238 out:
239 return(err);
240}
241
David Howells726c3342006-06-23 02:02:58 -0700242int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
244 /* do_statfs uses struct statfs64 internally, but the linux kernel
245 * struct statfs still has 32-bit versions for most of these fields,
246 * so we convert them here
247 */
248 int err;
249 long long f_blocks;
250 long long f_bfree;
251 long long f_bavail;
252 long long f_files;
253 long long f_ffree;
254
David Howells726c3342006-06-23 02:02:58 -0700255 err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
257 &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
258 &sf->f_namelen, sf->f_spare);
259 if(err) return(err);
260 sf->f_blocks = f_blocks;
261 sf->f_bfree = f_bfree;
262 sf->f_bavail = f_bavail;
263 sf->f_files = f_files;
264 sf->f_ffree = f_ffree;
265 sf->f_type = HOSTFS_SUPER_MAGIC;
266 return(0);
267}
268
269static struct inode *hostfs_alloc_inode(struct super_block *sb)
270{
271 struct hostfs_inode_info *hi;
272
273 hi = kmalloc(sizeof(*hi), GFP_KERNEL);
274 if(hi == NULL)
275 return(NULL);
276
277 *hi = ((struct hostfs_inode_info) { .host_filename = NULL,
278 .fd = -1,
279 .mode = 0 });
280 inode_init_once(&hi->vfs_inode);
281 return(&hi->vfs_inode);
282}
283
284static void hostfs_delete_inode(struct inode *inode)
285{
Mark Fashehfef26652005-09-09 13:01:31 -0700286 truncate_inode_pages(&inode->i_data, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 if(HOSTFS_I(inode)->fd != -1) {
288 close_file(&HOSTFS_I(inode)->fd);
289 HOSTFS_I(inode)->fd = -1;
290 }
291 clear_inode(inode);
292}
293
294static void hostfs_destroy_inode(struct inode *inode)
295{
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800296 kfree(HOSTFS_I(inode)->host_filename);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
298 /*XXX: This should not happen, probably. The check is here for
299 * additional safety.*/
300 if(HOSTFS_I(inode)->fd != -1) {
301 close_file(&HOSTFS_I(inode)->fd);
302 printk(KERN_DEBUG "Closing host fd in .destroy_inode\n");
303 }
304
305 kfree(HOSTFS_I(inode));
306}
307
308static void hostfs_read_inode(struct inode *inode)
309{
310 read_inode(inode);
311}
312
313static struct super_operations hostfs_sbops = {
314 .alloc_inode = hostfs_alloc_inode,
315 .drop_inode = generic_delete_inode,
316 .delete_inode = hostfs_delete_inode,
317 .destroy_inode = hostfs_destroy_inode,
318 .read_inode = hostfs_read_inode,
319 .statfs = hostfs_statfs,
320};
321
322int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
323{
324 void *dir;
325 char *name;
326 unsigned long long next, ino;
327 int error, len;
328
329 name = dentry_name(file->f_dentry, 0);
330 if(name == NULL) return(-ENOMEM);
331 dir = open_dir(name, &error);
332 kfree(name);
333 if(dir == NULL) return(-error);
334 next = file->f_pos;
335 while((name = read_dir(dir, &next, &ino, &len)) != NULL){
336 error = (*filldir)(ent, name, len, file->f_pos,
337 ino, DT_UNKNOWN);
338 if(error) break;
339 file->f_pos = next;
340 }
341 close_dir(dir);
342 return(0);
343}
344
345int hostfs_file_open(struct inode *ino, struct file *file)
346{
347 char *name;
348 int mode = 0, r = 0, w = 0, fd;
349
350 mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
351 if((mode & HOSTFS_I(ino)->mode) == mode)
352 return(0);
353
354 /* The file may already have been opened, but with the wrong access,
355 * so this resets things and reopens the file with the new access.
356 */
357 if(HOSTFS_I(ino)->fd != -1){
358 close_file(&HOSTFS_I(ino)->fd);
359 HOSTFS_I(ino)->fd = -1;
360 }
361
362 HOSTFS_I(ino)->mode |= mode;
363 if(HOSTFS_I(ino)->mode & FMODE_READ)
364 r = 1;
365 if(HOSTFS_I(ino)->mode & FMODE_WRITE)
366 w = 1;
367 if(w)
368 r = 1;
369
370 name = dentry_name(file->f_dentry, 0);
371 if(name == NULL)
372 return(-ENOMEM);
373
374 fd = open_file(name, r, w, append);
375 kfree(name);
376 if(fd < 0) return(fd);
377 FILE_HOSTFS_I(file)->fd = fd;
378
379 return(0);
380}
381
382int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
383{
Paolo 'Blaisorblade' Giarrussoa2d76bd2005-07-28 21:16:15 -0700384 return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385}
386
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800387static const struct file_operations hostfs_file_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 .llseek = generic_file_llseek,
389 .read = generic_file_read,
390 .sendfile = generic_file_sendfile,
391 .aio_read = generic_file_aio_read,
392 .aio_write = generic_file_aio_write,
393 .readv = generic_file_readv,
394 .writev = generic_file_writev,
395 .write = generic_file_write,
396 .mmap = generic_file_mmap,
397 .open = hostfs_file_open,
398 .release = NULL,
399 .fsync = hostfs_fsync,
400};
401
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800402static const struct file_operations hostfs_dir_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 .llseek = generic_file_llseek,
404 .readdir = hostfs_readdir,
405 .read = generic_read_dir,
406};
407
408int hostfs_writepage(struct page *page, struct writeback_control *wbc)
409{
410 struct address_space *mapping = page->mapping;
411 struct inode *inode = mapping->host;
412 char *buffer;
413 unsigned long long base;
414 int count = PAGE_CACHE_SIZE;
415 int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
416 int err;
417
418 if (page->index >= end_index)
419 count = inode->i_size & (PAGE_CACHE_SIZE-1);
420
421 buffer = kmap(page);
422 base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
423
424 err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
425 if(err != count){
426 ClearPageUptodate(page);
427 goto out;
428 }
429
430 if (base > inode->i_size)
431 inode->i_size = base;
432
433 if (PageError(page))
434 ClearPageError(page);
435 err = 0;
436
437 out:
438 kunmap(page);
439
440 unlock_page(page);
441 return err;
442}
443
444int hostfs_readpage(struct file *file, struct page *page)
445{
446 char *buffer;
447 long long start;
448 int err = 0;
449
450 start = (long long) page->index << PAGE_CACHE_SHIFT;
451 buffer = kmap(page);
452 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
453 PAGE_CACHE_SIZE);
454 if(err < 0) goto out;
455
456 memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
457
458 flush_dcache_page(page);
459 SetPageUptodate(page);
460 if (PageError(page)) ClearPageError(page);
461 err = 0;
462 out:
463 kunmap(page);
464 unlock_page(page);
465 return(err);
466}
467
468int hostfs_prepare_write(struct file *file, struct page *page,
469 unsigned int from, unsigned int to)
470{
471 char *buffer;
472 long long start, tmp;
473 int err;
474
475 start = (long long) page->index << PAGE_CACHE_SHIFT;
476 buffer = kmap(page);
477 if(from != 0){
478 tmp = start;
479 err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer,
480 from);
481 if(err < 0) goto out;
482 }
483 if(to != PAGE_CACHE_SIZE){
484 start += to;
485 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to,
486 PAGE_CACHE_SIZE - to);
487 if(err < 0) goto out;
488 }
489 err = 0;
490 out:
491 kunmap(page);
492 return(err);
493}
494
495int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
496 unsigned to)
497{
498 struct address_space *mapping = page->mapping;
499 struct inode *inode = mapping->host;
500 char *buffer;
501 long long start;
502 int err = 0;
503
Paolo 'Blaisorblade' Giarrusso30f04a42005-12-29 17:39:57 +0100504 start = (((long long) page->index) << PAGE_CACHE_SHIFT) + from;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 buffer = kmap(page);
506 err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
507 to - from);
508 if(err > 0) err = 0;
Paolo 'Blaisorblade' Giarrusso30f04a42005-12-29 17:39:57 +0100509
510 /* Actually, if !err, write_file has added to-from to start, so, despite
511 * the appearance, we are comparing i_size against the _last_ written
512 * location, as we should. */
513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 if(!err && (start > inode->i_size))
515 inode->i_size = start;
516
517 kunmap(page);
518 return(err);
519}
520
Christoph Hellwigf5e54d62006-06-28 04:26:44 -0700521static const struct address_space_operations hostfs_aops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 .writepage = hostfs_writepage,
523 .readpage = hostfs_readpage,
Paolo 'Blaisorblade' Giarrussoffa0aea2005-05-01 08:58:56 -0700524 .set_page_dirty = __set_page_dirty_nobuffers,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 .prepare_write = hostfs_prepare_write,
526 .commit_write = hostfs_commit_write
527};
528
529static int init_inode(struct inode *inode, struct dentry *dentry)
530{
531 char *name;
532 int type, err = -ENOMEM;
533 int maj, min;
534 dev_t rdev = 0;
535
536 if(dentry){
537 name = dentry_name(dentry, 0);
538 if(name == NULL)
539 goto out;
540 type = file_type(name, &maj, &min);
541 /*Reencode maj and min with the kernel encoding.*/
542 rdev = MKDEV(maj, min);
543 kfree(name);
544 }
545 else type = OS_TYPE_DIR;
546
547 err = 0;
548 if(type == OS_TYPE_SYMLINK)
549 inode->i_op = &page_symlink_inode_operations;
550 else if(type == OS_TYPE_DIR)
551 inode->i_op = &hostfs_dir_iops;
552 else inode->i_op = &hostfs_iops;
553
554 if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
555 else inode->i_fop = &hostfs_file_fops;
556
557 if(type == OS_TYPE_SYMLINK)
558 inode->i_mapping->a_ops = &hostfs_link_aops;
559 else inode->i_mapping->a_ops = &hostfs_aops;
560
561 switch (type) {
562 case OS_TYPE_CHARDEV:
563 init_special_inode(inode, S_IFCHR, rdev);
564 break;
565 case OS_TYPE_BLOCKDEV:
566 init_special_inode(inode, S_IFBLK, rdev);
567 break;
568 case OS_TYPE_FIFO:
569 init_special_inode(inode, S_IFIFO, 0);
570 break;
571 case OS_TYPE_SOCK:
572 init_special_inode(inode, S_IFSOCK, 0);
573 break;
574 }
575 out:
576 return(err);
577}
578
579int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
580 struct nameidata *nd)
581{
582 struct inode *inode;
583 char *name;
584 int error, fd;
585
586 error = -ENOMEM;
587 inode = iget(dir->i_sb, 0);
588 if(inode == NULL) goto out;
589
590 error = init_inode(inode, dentry);
591 if(error)
592 goto out_put;
593
594 error = -ENOMEM;
595 name = dentry_name(dentry, 0);
596 if(name == NULL)
597 goto out_put;
598
599 fd = file_create(name,
600 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
601 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
602 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
603 if(fd < 0)
604 error = fd;
605 else error = read_name(inode, name);
606
607 kfree(name);
608 if(error)
609 goto out_put;
610
611 HOSTFS_I(inode)->fd = fd;
612 HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
613 d_instantiate(dentry, inode);
614 return(0);
615
616 out_put:
617 iput(inode);
618 out:
619 return(error);
620}
621
622struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
623 struct nameidata *nd)
624{
625 struct inode *inode;
626 char *name;
627 int err;
628
629 err = -ENOMEM;
630 inode = iget(ino->i_sb, 0);
631 if(inode == NULL)
632 goto out;
633
634 err = init_inode(inode, dentry);
635 if(err)
636 goto out_put;
637
638 err = -ENOMEM;
639 name = dentry_name(dentry, 0);
640 if(name == NULL)
641 goto out_put;
642
643 err = read_name(inode, name);
644 kfree(name);
645 if(err == -ENOENT){
646 iput(inode);
647 inode = NULL;
648 }
649 else if(err)
650 goto out_put;
651
652 d_add(dentry, inode);
653 dentry->d_op = &hostfs_dentry_ops;
654 return(NULL);
655
656 out_put:
657 iput(inode);
658 out:
659 return(ERR_PTR(err));
660}
661
662static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
663{
664 char *file;
665 int len;
666
667 file = inode_name(ino, dentry->d_name.len + 1);
668 if(file == NULL) return(NULL);
669 strcat(file, "/");
670 len = strlen(file);
671 strncat(file, dentry->d_name.name, dentry->d_name.len);
672 file[len + dentry->d_name.len] = '\0';
673 return(file);
674}
675
676int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
677{
678 char *from_name, *to_name;
679 int err;
680
681 if((from_name = inode_dentry_name(ino, from)) == NULL)
682 return(-ENOMEM);
683 to_name = dentry_name(to, 0);
684 if(to_name == NULL){
685 kfree(from_name);
686 return(-ENOMEM);
687 }
688 err = link_file(to_name, from_name);
689 kfree(from_name);
690 kfree(to_name);
691 return(err);
692}
693
694int hostfs_unlink(struct inode *ino, struct dentry *dentry)
695{
696 char *file;
697 int err;
698
699 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
700 if(append)
701 return(-EPERM);
702
703 err = unlink_file(file);
704 kfree(file);
705 return(err);
706}
707
708int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
709{
710 char *file;
711 int err;
712
713 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
714 err = make_symlink(file, to);
715 kfree(file);
716 return(err);
717}
718
719int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
720{
721 char *file;
722 int err;
723
724 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
725 err = do_mkdir(file, mode);
726 kfree(file);
727 return(err);
728}
729
730int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
731{
732 char *file;
733 int err;
734
735 if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
736 err = do_rmdir(file);
737 kfree(file);
738 return(err);
739}
740
741int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
742{
743 struct inode *inode;
744 char *name;
745 int err = -ENOMEM;
746
747 inode = iget(dir->i_sb, 0);
748 if(inode == NULL)
749 goto out;
750
751 err = init_inode(inode, dentry);
752 if(err)
753 goto out_put;
754
755 err = -ENOMEM;
756 name = dentry_name(dentry, 0);
757 if(name == NULL)
758 goto out_put;
759
760 init_special_inode(inode, mode, dev);
761 err = do_mknod(name, mode, dev);
762 if(err)
763 goto out_free;
764
765 err = read_name(inode, name);
766 kfree(name);
767 if(err)
768 goto out_put;
769
770 d_instantiate(dentry, inode);
771 return(0);
772
773 out_free:
774 kfree(name);
775 out_put:
776 iput(inode);
777 out:
778 return(err);
779}
780
781int hostfs_rename(struct inode *from_ino, struct dentry *from,
782 struct inode *to_ino, struct dentry *to)
783{
784 char *from_name, *to_name;
785 int err;
786
787 if((from_name = inode_dentry_name(from_ino, from)) == NULL)
788 return(-ENOMEM);
789 if((to_name = inode_dentry_name(to_ino, to)) == NULL){
790 kfree(from_name);
791 return(-ENOMEM);
792 }
793 err = rename_file(from_name, to_name);
794 kfree(from_name);
795 kfree(to_name);
796 return(err);
797}
798
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
800{
801 char *name;
802 int r = 0, w = 0, x = 0, err;
803
804 if (desired & MAY_READ) r = 1;
805 if (desired & MAY_WRITE) w = 1;
806 if (desired & MAY_EXEC) x = 1;
807 name = inode_name(ino, 0);
808 if (name == NULL) return(-ENOMEM);
809
810 if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
811 S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
812 err = 0;
813 else
814 err = access_file(name, r, w, x);
815 kfree(name);
816 if(!err)
817 err = generic_permission(ino, desired, NULL);
818 return err;
819}
820
821int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
822{
823 struct hostfs_iattr attrs;
824 char *name;
825 int err;
826
827 err = inode_change_ok(dentry->d_inode, attr);
828 if (err)
829 return err;
830
831 if(append)
832 attr->ia_valid &= ~ATTR_SIZE;
833
834 attrs.ia_valid = 0;
835 if(attr->ia_valid & ATTR_MODE){
836 attrs.ia_valid |= HOSTFS_ATTR_MODE;
837 attrs.ia_mode = attr->ia_mode;
838 }
839 if(attr->ia_valid & ATTR_UID){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 attrs.ia_valid |= HOSTFS_ATTR_UID;
841 attrs.ia_uid = attr->ia_uid;
842 }
843 if(attr->ia_valid & ATTR_GID){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 attrs.ia_valid |= HOSTFS_ATTR_GID;
845 attrs.ia_gid = attr->ia_gid;
846 }
847 if(attr->ia_valid & ATTR_SIZE){
848 attrs.ia_valid |= HOSTFS_ATTR_SIZE;
849 attrs.ia_size = attr->ia_size;
850 }
851 if(attr->ia_valid & ATTR_ATIME){
852 attrs.ia_valid |= HOSTFS_ATTR_ATIME;
853 attrs.ia_atime = attr->ia_atime;
854 }
855 if(attr->ia_valid & ATTR_MTIME){
856 attrs.ia_valid |= HOSTFS_ATTR_MTIME;
857 attrs.ia_mtime = attr->ia_mtime;
858 }
859 if(attr->ia_valid & ATTR_CTIME){
860 attrs.ia_valid |= HOSTFS_ATTR_CTIME;
861 attrs.ia_ctime = attr->ia_ctime;
862 }
863 if(attr->ia_valid & ATTR_ATIME_SET){
864 attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
865 }
866 if(attr->ia_valid & ATTR_MTIME_SET){
867 attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
868 }
869 name = dentry_name(dentry, 0);
870 if(name == NULL) return(-ENOMEM);
871 err = set_attr(name, &attrs);
872 kfree(name);
873 if(err)
874 return(err);
875
876 return(inode_setattr(dentry->d_inode, attr));
877}
878
879int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
880 struct kstat *stat)
881{
882 generic_fillattr(dentry->d_inode, stat);
883 return(0);
884}
885
886static struct inode_operations hostfs_iops = {
887 .create = hostfs_create,
888 .link = hostfs_link,
889 .unlink = hostfs_unlink,
890 .symlink = hostfs_symlink,
891 .mkdir = hostfs_mkdir,
892 .rmdir = hostfs_rmdir,
893 .mknod = hostfs_mknod,
894 .rename = hostfs_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 .permission = hostfs_permission,
896 .setattr = hostfs_setattr,
897 .getattr = hostfs_getattr,
898};
899
900static struct inode_operations hostfs_dir_iops = {
901 .create = hostfs_create,
902 .lookup = hostfs_lookup,
903 .link = hostfs_link,
904 .unlink = hostfs_unlink,
905 .symlink = hostfs_symlink,
906 .mkdir = hostfs_mkdir,
907 .rmdir = hostfs_rmdir,
908 .mknod = hostfs_mknod,
909 .rename = hostfs_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 .permission = hostfs_permission,
911 .setattr = hostfs_setattr,
912 .getattr = hostfs_getattr,
913};
914
915int hostfs_link_readpage(struct file *file, struct page *page)
916{
917 char *buffer, *name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 int err;
919
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 buffer = kmap(page);
921 name = inode_name(page->mapping->host, 0);
922 if(name == NULL) return(-ENOMEM);
923 err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
924 kfree(name);
925 if(err == PAGE_CACHE_SIZE)
926 err = -E2BIG;
927 else if(err > 0){
928 flush_dcache_page(page);
929 SetPageUptodate(page);
930 if (PageError(page)) ClearPageError(page);
931 err = 0;
932 }
933 kunmap(page);
934 unlock_page(page);
935 return(err);
936}
937
Christoph Hellwigf5e54d62006-06-28 04:26:44 -0700938static const struct address_space_operations hostfs_link_aops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 .readpage = hostfs_link_readpage,
940};
941
942static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
943{
944 struct inode *root_inode;
945 char *name, *data = d;
946 int err;
947
948 sb->s_blocksize = 1024;
949 sb->s_blocksize_bits = 10;
950 sb->s_magic = HOSTFS_SUPER_MAGIC;
951 sb->s_op = &hostfs_sbops;
952
953 if((data == NULL) || (*data == '\0'))
954 data = root_ino;
955
956 err = -ENOMEM;
957 name = kmalloc(strlen(data) + 1, GFP_KERNEL);
958 if(name == NULL)
959 goto out;
960
961 strcpy(name, data);
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
971 HOSTFS_I(root_inode)->host_filename = name;
972
973 err = -ENOMEM;
974 sb->s_root = d_alloc_root(root_inode);
975 if(sb->s_root == NULL)
976 goto out_put;
977
978 err = read_inode(root_inode);
Jeff Dike51a14112005-05-05 16:15:34 -0700979 if(err){
980 /* No iput in this case because the dput does that for us */
981 dput(sb->s_root);
982 sb->s_root = NULL;
983 goto out_free;
984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
986 return(0);
987
988 out_put:
Jeff Dike51a14112005-05-05 16:15:34 -0700989 iput(root_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 out_free:
991 kfree(name);
992 out:
993 return(err);
994}
995
David Howells454e2392006-06-23 02:02:57 -0700996static int hostfs_read_sb(struct file_system_type *type,
997 int flags, const char *dev_name,
998 void *data, struct vfsmount *mnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999{
David Howells454e2392006-06-23 02:02:57 -07001000 return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001}
1002
1003static struct file_system_type hostfs_type = {
1004 .owner = THIS_MODULE,
1005 .name = "hostfs",
1006 .get_sb = hostfs_read_sb,
1007 .kill_sb = kill_anon_super,
1008 .fs_flags = 0,
1009};
1010
1011static int __init init_hostfs(void)
1012{
1013 return(register_filesystem(&hostfs_type));
1014}
1015
1016static void __exit exit_hostfs(void)
1017{
1018 unregister_filesystem(&hostfs_type);
1019}
1020
1021module_init(init_hostfs)
1022module_exit(exit_hostfs)
1023MODULE_LICENSE("GPL");
1024
1025/*
1026 * Overrides for Emacs so that we follow Linus's tabbing style.
1027 * Emacs will notice this stuff at the end of the file and automatically
1028 * adjust the settings for this buffer only. This must remain at the end
1029 * of the file.
1030 * ---------------------------------------------------------------------------
1031 * Local variables:
1032 * c-file-style: "linux"
1033 * End:
1034 */