diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 163 |
1 files changed, 131 insertions, 32 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 94b4b4557..e47227011 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -7,37 +7,43 @@ * * Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some * experimental NFS changes. Modularisation taken straight from SYS5 fs. + * + * Change to nfs_read_super() to permit NFS mounts to multi-homed hosts. + * J.S.Peatfield@damtp.cam.ac.uk + * */ -#ifdef MODULE #include <linux/module.h> -#include <linux/version.h> -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif - -#include <asm/system.h> -#include <asm/segment.h> #include <linux/sched.h> #include <linux/nfs_fs.h> +#include <linux/nfsiod.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/string.h> #include <linux/stat.h> #include <linux/errno.h> #include <linux/locks.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> + +#include <asm/system.h> +#include <asm/uaccess.h> + +/* This is for kernel_thread */ +#define __KERNEL_SYSCALLS__ +#include <linux/unistd.h> extern int close_fp(struct file *filp); static int nfs_notify_change(struct inode *, struct iattr *); static void nfs_put_inode(struct inode *); static void nfs_put_super(struct super_block *); +static void nfs_read_inode(struct inode *); static void nfs_statfs(struct super_block *, struct statfs *, int bufsiz); static struct super_operations nfs_sops = { - NULL, /* read inode */ + nfs_read_inode, /* read inode */ nfs_notify_change, /* notify change */ NULL, /* write inode */ nfs_put_inode, /* put inode */ @@ -47,14 +53,38 @@ static struct super_operations nfs_sops = { NULL }; +/* + * The "read_inode" function doesn't actually do anything: + * the real data is filled in later in nfs_fhget. Here we + * just mark the cache times invalid, and zero out i_mode + * (the latter makes "nfs_refresh_inode" do the right thing + * wrt pipe inodes) + */ +static void nfs_read_inode(struct inode * inode) +{ + int rsize = inode->i_sb->u.nfs_sb.s_server.rsize; + int size = inode->i_sb->u.nfs_sb.s_server.wsize; + + if (rsize > size) + size = rsize; + inode->i_blksize = size; + inode->i_mode = 0; + inode->i_op = NULL; + NFS_CACHEINV(inode); +} + static void nfs_put_inode(struct inode * inode) { - clear_inode(inode); + if (NFS_RENAMED_DIR(inode)) + nfs_sillyrename_cleanup(inode); + if (inode->i_pipe) + clear_inode(inode); } void nfs_put_super(struct super_block *sb) { close_fp(sb->u.nfs_sb.s_server.file); + rpc_closesock(sb->u.nfs_sb.s_server.rsock); lock_super(sb); sb->s_dev = 0; unlock_super(sb); @@ -65,7 +95,7 @@ void nfs_put_super(struct super_block *sb) * The way this works is that the mount process passes a structure * in the data argument which contains an open socket to the NFS * server and the root file handle obtained from the server's mount - * daemon. We stash theses away in the private superblock fields. + * daemon. We stash these away in the private superblock fields. * Later we can add other mount parameters like caching values. */ @@ -76,7 +106,8 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data, struct nfs_server *server; unsigned int fd; struct file *filp; - dev_t dev = sb->s_dev; + + kdev_t dev = sb->s_dev; MOD_INC_USE_COUNT; if (!data) { @@ -104,6 +135,7 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data, } filp->f_count++; lock_super(sb); + sb->s_blocksize = 1024; /* XXX */ sb->s_blocksize_bits = 10; sb->s_magic = NFS_SUPER_MAGIC; @@ -131,6 +163,38 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data, server->acdirmin = data->acdirmin*HZ; server->acdirmax = data->acdirmax*HZ; strcpy(server->hostname, data->hostname); + + /* Start of JSP NFS patch */ + /* Check if passed address in data->addr */ + if (data->addr.sin_addr.s_addr == INADDR_ANY) { /* No address passed */ + if (((struct sockaddr_in *)(&server->toaddr))->sin_addr.s_addr == INADDR_ANY) { + printk("NFS: Error passed unconnected socket and no address\n") ; + MOD_DEC_USE_COUNT; + return NULL ; + } else { + /* Need access to socket internals JSP */ + struct socket *sock; + int dummylen ; + + /* printk("NFS: using socket address\n") ;*/ + + sock = &((filp->f_inode)->u.socket_i); + + /* extract the other end of the socket into server->toaddr */ + sock->ops->getname(sock, &(server->toaddr), &dummylen, 1) ; + } + } else { + /* printk("NFS: copying passed addr to server->toaddr\n") ;*/ + memcpy((char *)&(server->toaddr),(char *)(&data->addr),sizeof(server->toaddr)); + } + /* End of JSP NFS patch */ + + if ((server->rsock = rpc_makesock(filp)) == NULL) { + printk("NFS: cannot create RPC socket.\n"); + MOD_DEC_USE_COUNT; + return NULL; + } + sb->u.nfs_sb.s_root = data->root; unlock_super(sb); if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) { @@ -162,7 +226,7 @@ void nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) tmp.f_files = 0; tmp.f_ffree = 0; tmp.f_namelen = NAME_MAX; - memcpy_tofs(buf, &tmp, bufsiz); + copy_to_user(buf, &tmp, bufsiz); } /* @@ -215,37 +279,34 @@ int nfs_notify_change(struct inode *inode, struct iattr *attr) struct nfs_fattr fattr; int error; + sattr.mode = (unsigned) -1; if (attr->ia_valid & ATTR_MODE) sattr.mode = attr->ia_mode; - else - sattr.mode = (unsigned) -1; + sattr.uid = (unsigned) -1; if (attr->ia_valid & ATTR_UID) sattr.uid = attr->ia_uid; - else - sattr.uid = (unsigned) -1; + sattr.gid = (unsigned) -1; if (attr->ia_valid & ATTR_GID) sattr.gid = attr->ia_gid; - else - sattr.gid = (unsigned) -1; + + sattr.size = (unsigned) -1; if (attr->ia_valid & ATTR_SIZE) sattr.size = S_ISREG(inode->i_mode) ? attr->ia_size : -1; - else - sattr.size = (unsigned) -1; + sattr.mtime.seconds = sattr.mtime.useconds = (unsigned) -1; if (attr->ia_valid & ATTR_MTIME) { sattr.mtime.seconds = attr->ia_mtime; sattr.mtime.useconds = 0; - } else - sattr.mtime.seconds = sattr.mtime.useconds = (unsigned) -1; + } + sattr.atime.seconds = sattr.atime.useconds = (unsigned) -1; if (attr->ia_valid & ATTR_ATIME) { sattr.atime.seconds = attr->ia_atime; sattr.atime.useconds = 0; - } else - sattr.atime.seconds = sattr.atime.useconds = (unsigned) -1; + } error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode), &sattr, &fattr); @@ -255,25 +316,63 @@ int nfs_notify_change(struct inode *inode, struct iattr *attr) return error; } -#ifdef MODULE - /* Every kernel module contains stuff like this. */ -char kernel_version[] = UTS_RELEASE; - static struct file_system_type nfs_fs_type = { nfs_read_super, "nfs", 0, NULL }; +/* + * Start up an nfsiod process. This is an awful hack, because when running + * as a module, we will keep insmod's memory. Besides, the current->comm + * hack won't work in this case + * The best would be to have a syscall for nfs client control that (among + * other things) forks biod's. + * Alternatively, we might want to have the idle task spawn biod's on demand. + */ +static int run_nfsiod(void *dummy) +{ + int ret; + +#ifdef __SMP__ + lock_kernel(); + syscall_count++; +#endif + + MOD_INC_USE_COUNT; + exit_mm(current); + current->session = 1; + current->pgrp = 1; + sprintf(current->comm, "nfsiod"); + ret = nfsiod(); + MOD_DEC_USE_COUNT; + return ret; +} + +int init_nfs_fs(void) +{ + /* Fork four biod's */ + kernel_thread(run_nfsiod, NULL, 0); + kernel_thread(run_nfsiod, NULL, 0); + kernel_thread(run_nfsiod, NULL, 0); + kernel_thread(run_nfsiod, NULL, 0); + return register_filesystem(&nfs_fs_type); +} + +#ifdef MODULE int init_module(void) { - register_filesystem(&nfs_fs_type); - return 0; + int status; + + if ((status = init_nfs_fs()) == 0) + register_symtab(0); + return status; } void cleanup_module(void) { unregister_filesystem(&nfs_fs_type); + nfs_kfree_cache(); } #endif |