2 * Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
6 #include <linux/stddef.h>
8 #include <linux/version.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/slab.h>
12 #include <linux/pagemap.h>
13 #include <linux/blkdev.h>
14 #include <linux/statfs.h>
15 #include <asm/uaccess.h>
17 #include "kern_util.h"
19 #include "user_util.h"
20 #include "2_5compat.h"
22 #include "filehandle.h"
25 struct list_head list;
26 struct externfs_mount_ops *mount_ops;
27 struct file_system_type type;
30 static inline struct externfs_inode *EXTERNFS_I(struct inode *inode)
32 return(container_of(inode, struct externfs_inode, vfs_inode));
35 #define file_externfs_i(file) EXTERNFS_I((file)->f_dentry->d_inode)
37 int externfs_d_delete(struct dentry *dentry)
42 struct dentry_operations externfs_dentry_ops = {
45 #define EXTERNFS_SUPER_MAGIC 0x00c0ffee
47 static struct inode_operations externfs_iops;
48 static struct inode_operations externfs_dir_iops;
49 static struct address_space_operations externfs_link_aops;
51 static char *dentry_name(struct dentry *dentry, int extra)
53 struct dentry *parent;
59 while(parent->d_parent != parent){
60 len += parent->d_name.len + 1;
61 parent = parent->d_parent;
64 name = kmalloc(len + extra + 1, GFP_KERNEL);
65 if(name == NULL) return(NULL);
69 while(parent->d_parent != parent){
70 len -= parent->d_name.len + 1;
72 strncpy(&name[len + 1], parent->d_name.name,
74 parent = parent->d_parent;
80 char *inode_name(struct inode *ino, int extra)
82 struct dentry *dentry;
84 dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
85 return(dentry_name(dentry, extra));
88 char *inode_name_prefix(struct inode *inode, char *prefix)
94 name = inode_name(inode, len);
98 memmove(&name[len], name, strlen(name) + 1);
99 memcpy(name, prefix, strlen(prefix));
103 static int read_name(struct inode *ino, char *name)
105 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
106 /* The non-int inode fields are copied into ints by stat_file and
107 * then copied into the inode because passing the actual pointers
108 * in and having them treated as int * breaks on big-endian machines
112 int i_mode, i_nlink, i_blksize;
113 unsigned long atime, mtime, ctime;
114 unsigned long long i_size;
115 unsigned long long i_ino;
116 unsigned long long i_blocks;
118 err = (*ops->stat_file)(name, ino->i_sb->s_fs_info, &i_rdev, &i_ino,
119 &i_mode, &i_nlink, &ino->i_uid, &ino->i_gid,
120 &i_size, &atime, &mtime, &ctime, &i_blksize,
124 ino->i_atime.tv_sec = atime;
125 ino->i_atime.tv_nsec = 0;
127 ino->i_ctime.tv_sec = ctime;
128 ino->i_ctime.tv_nsec = 0;
130 ino->i_mtime.tv_sec = mtime;
131 ino->i_mtime.tv_nsec = 0;
134 ino->i_rdev = i_rdev;
135 ino->i_mode = i_mode;
136 ino->i_nlink = i_nlink;
137 ino->i_size = i_size;
138 ino->i_blksize = i_blksize;
139 ino->i_blocks = i_blocks;
143 static char *follow_link(char *link,
144 int (*do_read_link)(char *path, int uid, int gid,
146 struct externfs_data *ed),
147 int uid, int gid, struct externfs_data *ed)
150 char *name, *resolved, *end;
155 name = kmalloc(len, GFP_KERNEL);
159 n = (*do_read_link)(link, uid, gid, name, len, ed);
171 end = strrchr(link, '/');
176 len = strlen(link) + strlen(name) + 1;
178 resolved = kmalloc(len, GFP_KERNEL);
179 if(resolved == NULL){
184 sprintf(resolved, "%s%s", link, name);
194 static int read_inode(struct inode *ino)
196 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
197 struct externfs_data *ed = ino->i_sb->s_fs_info;
201 /* Unfortunately, we are called from iget() when we don't have a dentry
204 if(list_empty(&ino->i_dentry))
208 name = inode_name(ino, 0);
212 type = (*ops->file_type)(name, NULL, ed);
218 if(type == OS_TYPE_SYMLINK){
219 new = follow_link(name, ops->read_link, current->fsuid,
229 err = read_name(ino, name);
236 int externfs_statfs(struct super_block *sb, struct kstatfs *sf)
238 /* do_statfs uses struct statfs64 internally, but the linux kernel
239 * struct statfs still has 32-bit versions for most of these fields,
240 * so we convert them here
248 struct externfs_data *ed = sb->s_fs_info;
250 err = (*ed->file_ops->statfs)(&sf->f_bsize, &f_blocks, &f_bfree,
251 &f_bavail, &f_files, &f_ffree,
252 &sf->f_fsid, sizeof(sf->f_fsid),
253 &sf->f_namelen, sf->f_spare, ed);
257 sf->f_blocks = f_blocks;
258 sf->f_bfree = f_bfree;
259 sf->f_bavail = f_bavail;
260 sf->f_files = f_files;
261 sf->f_ffree = f_ffree;
262 sf->f_type = EXTERNFS_SUPER_MAGIC;
266 static struct inode *externfs_alloc_inode(struct super_block *sb)
268 struct externfs_data *ed = sb->s_fs_info;
269 struct externfs_inode *ext;
271 ext = (*ed->mount_ops->init_file)(ed);
275 *ext = ((struct externfs_inode) { .ops = ed->file_ops });
277 inode_init_once(&ext->vfs_inode);
278 return(&ext->vfs_inode);
281 static void externfs_destroy_inode(struct inode *inode)
283 struct externfs_inode *ext = EXTERNFS_I(inode);
285 (*ext->ops->close_file)(ext, inode->i_size);
288 static void externfs_read_inode(struct inode *inode)
293 static struct super_operations externfs_sbops = {
294 .alloc_inode = externfs_alloc_inode,
295 .destroy_inode = externfs_destroy_inode,
296 .read_inode = externfs_read_inode,
297 .statfs = externfs_statfs,
300 int externfs_readdir(struct file *file, void *ent, filldir_t filldir)
304 unsigned long long next, ino;
306 struct externfs_file_ops *ops = file_externfs_i(file)->ops;
307 struct externfs_data *ed = file->f_dentry->d_inode->i_sb->s_fs_info;
309 name = dentry_name(file->f_dentry, 0);
313 dir = (*ops->open_dir)(name, current->fsuid, current->fsgid, ed);
316 return(PTR_ERR(dir));
319 while((name = (*ops->read_dir)(dir, &next, &ino, &len, ed)) != NULL){
320 error = (*filldir)(ent, name, len, file->f_pos, ino,
326 (*ops->close_dir)(dir, ed);
330 int externfs_file_open(struct inode *ino, struct file *file)
336 int externfs_fsync(struct file *file, struct dentry *dentry, int datasync)
338 struct externfs_file_ops *ops = file_externfs_i(file)->ops;
339 struct inode *inode = dentry->d_inode;
340 struct externfs_data *ed = inode->i_sb->s_fs_info;
342 return((*ops->truncate_file)(EXTERNFS_I(inode), inode->i_size, ed));
345 static struct file_operations externfs_file_fops = {
346 .llseek = generic_file_llseek,
347 .read = generic_file_read,
348 .write = generic_file_write,
349 .mmap = generic_file_mmap,
350 .open = externfs_file_open,
352 .fsync = externfs_fsync,
355 static struct file_operations externfs_dir_fops = {
356 .readdir = externfs_readdir,
357 .read = generic_read_dir,
363 unsigned long long start;
364 unsigned long long size;
365 int (*truncate)(struct externfs_inode *ext, __u64 size,
366 struct externfs_data *ed);
367 struct externfs_inode *ei;
368 struct externfs_data *ed;
371 static void externfs_finish_writepage(char *buffer, int res, void *arg)
373 struct wp_info *wp = arg;
375 if(res == wp->count){
376 ClearPageError(wp->page);
377 if(wp->start + res > wp->size)
378 (*wp->truncate)(wp->ei, wp->size, wp->ed);
381 SetPageError(wp->page);
382 ClearPageUptodate(wp->page);
386 unlock_page(wp->page);
390 int externfs_writepage(struct page *page, struct writeback_control *wbc)
392 struct address_space *mapping = page->mapping;
393 struct inode *inode = mapping->host;
394 struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops;
396 struct externfs_data *ed = inode->i_sb->s_fs_info;
398 unsigned long long base;
399 int count = PAGE_CACHE_SIZE;
400 int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
403 base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
405 /* If we are entirely outside the file, then return an error */
407 offset = inode->i_size & (PAGE_CACHE_SIZE-1);
408 if (page->index > end_index ||
409 ((page->index == end_index) && !offset))
413 wp = kmalloc(sizeof(*wp), GFP_KERNEL);
417 *wp = ((struct wp_info) { .page = page,
420 .size = inode->i_size,
421 .truncate = ops->truncate_file,
422 .ei = EXTERNFS_I(inode),
426 err = (*ops->write_file)(EXTERNFS_I(inode), base, buffer, 0,
427 count, externfs_finish_writepage, wp, ed);
436 static void externfs_finish_readpage(char *buffer, int res, void *arg)
438 struct page *page = arg;
446 inode = page->mapping->host;
447 if(inode->i_size >> PAGE_CACHE_SHIFT == page->index)
448 res = inode->i_size % PAGE_CACHE_SIZE;
450 memset(&buffer[res], 0, PAGE_CACHE_SIZE - res);
452 flush_dcache_page(page);
453 SetPageUptodate(page);
455 ClearPageError(page);
461 static int externfs_readpage(struct file *file, struct page *page)
463 struct inode *ino = page->mapping->host;
464 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
465 struct externfs_data *ed = ino->i_sb->s_fs_info;
470 start = (long long) page->index << PAGE_CACHE_SHIFT;
473 if(ops->map_file_page != NULL){
474 /* XXX What happens when PAGE_SIZE != PAGE_CACHE_SIZE? */
475 err = (*ops->map_file_page)(file_externfs_i(file), start,
476 buffer, file->f_mode & FMODE_WRITE,
479 err = PAGE_CACHE_SIZE;
481 else err = (*ops->read_file)(file_externfs_i(file), start, buffer,
482 PAGE_CACHE_SIZE, 0, 0,
483 externfs_finish_readpage, page, ed);
490 struct writepage_info {
491 struct semaphore sem;
495 static void externfs_finish_prepare(char *buffer, int res, void *arg)
497 struct writepage_info *wp = arg;
503 int externfs_prepare_write(struct file *file, struct page *page,
504 unsigned int from, unsigned int to)
506 struct address_space *mapping = page->mapping;
507 struct inode *inode = mapping->host;
508 struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops;
509 struct externfs_data *ed = inode->i_sb->s_fs_info;
513 struct writepage_info wp;
515 if(PageUptodate(page))
518 start = (long long) page->index << PAGE_CACHE_SHIFT;
521 if(ops->map_file_page != NULL){
522 err = (*ops->map_file_page)(file_externfs_i(file), start,
523 buffer, file->f_mode & FMODE_WRITE,
529 init_MUTEX_LOCKED(&wp.sem);
530 err = (*ops->read_file)(file_externfs_i(file), start, buffer,
531 PAGE_CACHE_SIZE, from, to,
532 externfs_finish_prepare, &wp, ed);
542 memset(buffer, 0, from);
543 if(to < PAGE_CACHE_SIZE)
544 memset(buffer + to, 0, PAGE_CACHE_SIZE - to);
546 SetPageUptodate(page);
553 static int externfs_commit_write(struct file *file, struct page *page,
554 unsigned from, unsigned to)
556 struct address_space *mapping = page->mapping;
557 struct inode *inode = mapping->host;
558 struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops;
559 unsigned long long size;
563 start = (long long) (page->index << PAGE_CACHE_SHIFT);
565 if(ops->map_file_page != NULL)
569 if(size > inode->i_size){
570 inode->i_size = size;
571 mark_inode_dirty(inode);
575 set_page_dirty(page);
579 static int externfs_removepage(struct page *page, int gfpmask)
581 physmem_remove_mapping(page_address(page));
585 static struct address_space_operations externfs_aops = {
586 .writepage = externfs_writepage,
587 .readpage = externfs_readpage,
588 .releasepage = externfs_removepage,
589 /* .set_page_dirty = __set_page_dirty_nobuffers, */
590 .prepare_write = externfs_prepare_write,
591 .commit_write = externfs_commit_write
594 static int init_inode(struct inode *inode, struct dentry *dentry)
597 int type, err = -ENOMEM, rdev;
598 struct externfs_inode *ext = EXTERNFS_I(inode);
599 struct externfs_file_ops *ops = ext->ops;
600 struct externfs_data *ed = inode->i_sb->s_fs_info;
603 name = dentry_name(dentry, 0);
606 type = (*ops->file_type)(name, &rdev, ed);
608 else type = OS_TYPE_DIR;
611 if(type == OS_TYPE_SYMLINK)
612 inode->i_op = &page_symlink_inode_operations;
613 else if(type == OS_TYPE_DIR)
614 inode->i_op = &externfs_dir_iops;
615 else inode->i_op = &externfs_iops;
617 if(type == OS_TYPE_DIR) inode->i_fop = &externfs_dir_fops;
618 else inode->i_fop = &externfs_file_fops;
620 if(type == OS_TYPE_SYMLINK)
621 inode->i_mapping->a_ops = &externfs_link_aops;
622 else inode->i_mapping->a_ops = &externfs_aops;
625 case OS_TYPE_CHARDEV:
626 init_special_inode(inode, S_IFCHR, rdev);
628 case OS_TYPE_BLOCKDEV:
629 init_special_inode(inode, S_IFBLK, rdev);
632 init_special_inode(inode, S_IFIFO, 0);
635 init_special_inode(inode, S_IFSOCK, 0);
637 case OS_TYPE_SYMLINK:
638 inode->i_mode = S_IFLNK | S_IRWXUGO;
641 err = (*ops->open_file)(ext, name, current->fsuid, current->fsgid,
643 if((err != -EISDIR) && (err != -ENOENT) && (err != -ENXIO))
658 int externfs_create(struct inode *dir, struct dentry *dentry, int mode,
659 struct nameidata *nd)
661 struct externfs_inode *ext = EXTERNFS_I(dir);
662 struct externfs_file_ops *ops = ext->ops;
664 struct externfs_data *ed = dir->i_sb->s_fs_info;
668 inode = iget(dir->i_sb, 0);
672 err = init_inode(inode, dentry);
677 name = dentry_name(dentry, 0);
681 err = (*ops->create_file)(ext, name, mode, current->fsuid,
682 current->fsuid, inode, ed);
686 err = read_name(inode, name);
691 d_instantiate(dentry, inode);
697 (*ops->unlink_file)(name, ed);
706 struct dentry *externfs_lookup(struct inode *ino, struct dentry *dentry,
707 struct nameidata *nd)
713 inode = iget(ino->i_sb, 0);
717 err = init_inode(inode, dentry);
722 name = dentry_name(dentry, 0);
726 err = read_name(inode, name);
736 d_add(dentry, inode);
737 dentry->d_op = &externfs_dentry_ops;
744 return(ERR_PTR(err));
747 static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
752 file = inode_name(ino, dentry->d_name.len + 1);
753 if(file == NULL) return(NULL);
756 strncat(file, dentry->d_name.name, dentry->d_name.len);
757 file[len + dentry->d_name.len] = '\0';
761 int externfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
763 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
764 struct externfs_data *ed = ino->i_sb->s_fs_info;
765 char *from_name, *to_name;
768 from_name = inode_dentry_name(ino, from);
769 if(from_name == NULL)
772 to_name = dentry_name(to, 0);
776 err = (*ops->link_file)(to_name, from_name, current->fsuid,
781 d_instantiate(from, to->d_inode);
782 to->d_inode->i_nlink++;
783 atomic_inc(&to->d_inode->i_count);
793 int externfs_unlink(struct inode *ino, struct dentry *dentry)
796 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
797 struct externfs_data *ed = ino->i_sb->s_fs_info;
801 file = inode_dentry_name(ino, dentry);
805 inode = dentry->d_inode;
806 if((inode->i_nlink == 1) && (ops->invisible != NULL))
807 (*ops->invisible)(EXTERNFS_I(inode));
809 err = (*ops->unlink_file)(file, ed);
817 int externfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
819 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
821 struct externfs_data *ed = ino->i_sb->s_fs_info;
825 file = inode_dentry_name(ino, dentry);
828 err = (*ops->make_symlink)(file, to, current->fsuid, current->fsgid,
835 inode = iget(ino->i_sb, 0);
839 err = init_inode(inode, dentry);
843 d_instantiate(dentry, inode);
853 int externfs_make_dir(struct inode *ino, struct dentry *dentry, int mode)
855 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
857 struct externfs_data *ed = ino->i_sb->s_fs_info;
861 file = inode_dentry_name(ino, dentry);
864 err = (*ops->make_dir)(file, mode, current->fsuid, current->fsgid, ed);
867 inode = iget(ino->i_sb, 0);
871 err = init_inode(inode, dentry);
875 err = read_name(inode, file);
880 d_instantiate(dentry, inode);
882 inode->i_mode = S_IFDIR | mode;
895 int externfs_remove_dir(struct inode *ino, struct dentry *dentry)
897 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
898 struct externfs_data *ed = ino->i_sb->s_fs_info;
902 file = inode_dentry_name(ino, dentry);
905 err = (*ops->remove_dir)(file, current->fsuid, current->fsgid, ed);
908 dentry->d_inode->i_nlink = 0;
913 int externfs_make_node(struct inode *dir, struct dentry *dentry, int mode,
916 struct externfs_file_ops *ops = EXTERNFS_I(dir)->ops;
917 struct externfs_data *ed = dir->i_sb->s_fs_info;
922 inode = iget(dir->i_sb, 0);
926 err = init_inode(inode, dentry);
931 name = dentry_name(dentry, 0);
935 init_special_inode(inode, mode, dev);
936 err = (*ops->make_node)(name, mode & S_IRWXUGO, current->fsuid,
937 current->fsgid, mode & S_IFMT, MAJOR(dev),
942 err = read_name(inode, name);
947 d_instantiate(dentry, inode);
953 (*ops->unlink_file)(name, ed);
962 int externfs_rename(struct inode *from_ino, struct dentry *from,
963 struct inode *to_ino, struct dentry *to)
965 struct externfs_file_ops *ops = EXTERNFS_I(from_ino)->ops;
966 struct externfs_data *ed = from_ino->i_sb->s_fs_info;
967 char *from_name, *to_name;
970 from_name = inode_dentry_name(from_ino, from);
971 if(from_name == NULL)
973 to_name = inode_dentry_name(to_ino, to);
978 err = (*ops->rename_file)(from_name, to_name, ed);
987 void externfs_truncate(struct inode *ino)
989 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
990 struct externfs_data *ed = ino->i_sb->s_fs_info;
992 (*ops->truncate_file)(EXTERNFS_I(ino), ino->i_size, ed);
995 int externfs_permission(struct inode *ino, int desired, struct nameidata *nd)
997 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
998 struct externfs_data *ed = ino->i_sb->s_fs_info;
1000 int r = 0, w = 0, x = 0, err;
1002 if(ops->access_file == NULL)
1003 return(vfs_permission(ino, desired));
1005 if(desired & MAY_READ) r = 1;
1006 if(desired & MAY_WRITE) w = 1;
1007 if(desired & MAY_EXEC) x = 1;
1008 name = inode_name(ino, 0);
1012 err = (*ops->access_file)(name, r, w, x, current->fsuid,
1013 current->fsgid, ed);
1017 err = vfs_permission(ino, desired);
1021 int externfs_setattr(struct dentry *dentry, struct iattr *attr)
1023 struct externfs_file_ops *ops = EXTERNFS_I(dentry->d_inode)->ops;
1024 struct externfs_data *ed = dentry->d_inode->i_sb->s_fs_info;
1025 struct externfs_iattr attrs;
1030 if(attr->ia_valid & ATTR_MODE){
1031 attrs.ia_valid |= EXTERNFS_ATTR_MODE;
1032 attrs.ia_mode = attr->ia_mode;
1034 if(attr->ia_valid & ATTR_UID){
1035 attrs.ia_valid |= EXTERNFS_ATTR_UID;
1036 attrs.ia_uid = attr->ia_uid;
1038 if(attr->ia_valid & ATTR_GID){
1039 attrs.ia_valid |= EXTERNFS_ATTR_GID;
1040 attrs.ia_gid = attr->ia_gid;
1042 if(attr->ia_valid & ATTR_SIZE){
1043 attrs.ia_valid |= EXTERNFS_ATTR_SIZE;
1044 attrs.ia_size = attr->ia_size;
1046 if(attr->ia_valid & ATTR_ATIME){
1047 attrs.ia_valid |= EXTERNFS_ATTR_ATIME;
1048 attrs.ia_atime = attr->ia_atime.tv_sec;
1050 if(attr->ia_valid & ATTR_MTIME){
1051 attrs.ia_valid |= EXTERNFS_ATTR_MTIME;
1052 attrs.ia_mtime = attr->ia_mtime.tv_sec;
1054 if(attr->ia_valid & ATTR_CTIME){
1055 attrs.ia_valid |= EXTERNFS_ATTR_CTIME;
1056 attrs.ia_ctime = attr->ia_ctime.tv_sec;
1058 if(attr->ia_valid & ATTR_ATIME_SET){
1059 attrs.ia_valid |= EXTERNFS_ATTR_ATIME_SET;
1060 attrs.ia_atime = attr->ia_atime.tv_sec;
1062 if(attr->ia_valid & ATTR_MTIME_SET){
1063 attrs.ia_valid |= EXTERNFS_ATTR_MTIME_SET;
1065 name = dentry_name(dentry, 0);
1068 err = (*ops->set_attr)(name, &attrs, ed);
1073 return(inode_setattr(dentry->d_inode, attr));
1076 int externfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1079 generic_fillattr(dentry->d_inode, stat);
1083 static struct inode_operations externfs_iops = {
1084 .create = externfs_create,
1085 .link = externfs_link,
1086 .unlink = externfs_unlink,
1087 .symlink = externfs_symlink,
1088 .mkdir = externfs_make_dir,
1089 .rmdir = externfs_remove_dir,
1090 .mknod = externfs_make_node,
1091 .rename = externfs_rename,
1092 .truncate = externfs_truncate,
1093 .permission = externfs_permission,
1094 .setattr = externfs_setattr,
1095 .getattr = externfs_getattr,
1098 static struct inode_operations externfs_dir_iops = {
1099 .create = externfs_create,
1100 .lookup = externfs_lookup,
1101 .link = externfs_link,
1102 .unlink = externfs_unlink,
1103 .symlink = externfs_symlink,
1104 .mkdir = externfs_make_dir,
1105 .rmdir = externfs_remove_dir,
1106 .mknod = externfs_make_node,
1107 .rename = externfs_rename,
1108 .truncate = externfs_truncate,
1109 .permission = externfs_permission,
1110 .setattr = externfs_setattr,
1111 .getattr = externfs_getattr,
1114 int externfs_link_readpage(struct file *file, struct page *page)
1116 struct inode *ino = page->mapping->host;
1117 struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops;
1118 struct externfs_data *ed = ino->i_sb->s_fs_info;
1119 char *buffer, *name;
1123 start = page->index << PAGE_CACHE_SHIFT;
1124 buffer = kmap(page);
1125 name = inode_name(ino, 0);
1129 err = (*ops->read_link)(name, current->fsuid, current->fsgid, buffer,
1130 PAGE_CACHE_SIZE, ed);
1133 if(err == PAGE_CACHE_SIZE)
1136 flush_dcache_page(page);
1137 SetPageUptodate(page);
1138 if (PageError(page)) ClearPageError(page);
1146 static int externfs_flushpage(struct page *page, unsigned long offset)
1148 return(externfs_writepage(page, NULL));
1151 struct externfs_data *inode_externfs_info(struct inode *inode)
1153 return(inode->i_sb->s_fs_info);
1156 static struct address_space_operations externfs_link_aops = {
1157 .readpage = externfs_link_readpage,
1158 .releasepage = externfs_removepage,
1159 .invalidatepage = externfs_flushpage,
1162 DECLARE_MUTEX(externfs_sem);
1163 struct list_head externfses = LIST_HEAD_INIT(externfses);
1165 static struct externfs *find_externfs(struct file_system_type *type)
1167 struct list_head *ele;
1168 struct externfs *fs;
1170 down(&externfs_sem);
1171 list_for_each(ele, &externfses){
1172 fs = list_entry(ele, struct externfs, list);
1173 if(&fs->type == type)
1182 #define DEFAULT_ROOT "/"
1184 char *host_root_filename(char *mount_arg)
1186 char *root = DEFAULT_ROOT;
1188 if((mount_arg != NULL) && (*mount_arg != '\0'))
1191 return(uml_strdup(root));
1194 static int externfs_fill_sb(struct super_block *sb, void *data, int silent)
1196 struct externfs *fs;
1197 struct inode *root_inode;
1198 struct externfs_data *sb_data;
1201 sb->s_blocksize = 1024;
1202 sb->s_blocksize_bits = 10;
1203 sb->s_magic = EXTERNFS_SUPER_MAGIC;
1204 sb->s_op = &externfs_sbops;
1206 fs = find_externfs(sb->s_type);
1208 printk("Couldn't find externfs for filesystem '%s'\n",
1213 sb_data = (*fs->mount_ops->mount)(data);
1214 if(IS_ERR(sb_data)){
1215 err = PTR_ERR(sb_data);
1219 sb->s_fs_info = sb_data;
1220 sb_data->mount_ops = fs->mount_ops;
1222 root_inode = iget(sb, 0);
1223 if(root_inode == NULL)
1226 err = init_inode(root_inode, NULL);
1231 sb->s_root = d_alloc_root(root_inode);
1232 if(sb->s_root == NULL)
1235 err = read_inode(root_inode);
1247 struct super_block *externfs_read_super(struct file_system_type *type,
1248 int flags, const char *dev_name,
1251 return(get_sb_nodev(type, flags, data, externfs_fill_sb));
1254 void init_externfs(struct externfs_data *ed, struct externfs_file_ops *ops)
1259 int register_externfs(char *name, struct externfs_mount_ops *mount_ops)
1261 struct externfs *new;
1264 new = kmalloc(sizeof(*new), GFP_KERNEL);
1268 memset(new, 0, sizeof(*new));
1269 *new = ((struct externfs) { .list = LIST_HEAD_INIT(new->list),
1270 .mount_ops = mount_ops,
1271 .type = { .name = name,
1272 .get_sb = externfs_read_super,
1273 .kill_sb = kill_anon_super,
1275 .owner = THIS_MODULE } });
1276 list_add(&new->list, &externfses);
1278 err = register_filesystem(&new->type);
1284 list_del(&new->list);
1290 void unregister_externfs(char *name)
1292 struct list_head *ele;
1293 struct externfs *fs;
1295 down(&externfs_sem);
1296 list_for_each(ele, &externfses){
1297 fs = list_entry(ele, struct externfs, list);
1298 if(!strcmp(fs->type.name, name)){
1305 printk("Unregister_externfs - filesystem '%s' not found\n", name);
1309 * Overrides for Emacs so that we follow Linus's tabbing style.
1310 * Emacs will notice this stuff at the end of the file and automatically
1311 * adjust the settings for this buffer only. This must remain at the end
1313 * ---------------------------------------------------------------------------
1315 * c-file-style: "linux"