diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/Makefile | 2 | ||||
-rw-r--r-- | fs/nfs/cache.c | 63 | ||||
-rw-r--r-- | fs/nfs/dir.c | 41 | ||||
-rw-r--r-- | fs/nfs/file.c | 6 | ||||
-rw-r--r-- | fs/nfs/inode.c | 69 | ||||
-rw-r--r-- | fs/nfs/mmap.c | 15 | ||||
-rw-r--r-- | fs/nfs/proc.c | 6 | ||||
-rw-r--r-- | fs/nfs/sock.c | 10 | ||||
-rw-r--r-- | fs/nfs/symlink.c | 4 |
9 files changed, 175 insertions, 41 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 8610c95b1..eabf9f6f1 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -23,6 +23,8 @@ nfs.o: $(OBJS) dep: $(CPP) -M *.c > .depend +modules: nfs.o + # # include a dependency file if one exists # diff --git a/fs/nfs/cache.c b/fs/nfs/cache.c new file mode 100644 index 000000000..57f3cc411 --- /dev/null +++ b/fs/nfs/cache.c @@ -0,0 +1,63 @@ + +void nfs_bl_cache_invalidate(nfs_cache *nh) +{ + unsigned long flags; + save_flags(flags); + cli(); + if(nh->inuse) + nh->dead=1; + else + { + kfree_s(nh->data); + nh->data=NULL; + nh->free=1; + } +} + +void nfs_bl_cache_revalidate(nfs_cache *nh, struct fattr fa) +{ + nh->fattr=fattr; + nh->time=jiffies; +} + +/* + * Find a block in the cache. We know the cache is block sized in block + * aligned space. + */ + +nfs_cache *nfs_cache_find(struct inode *inode, off_t pos) +{ + nfs_cache *nh=&nfs_cache_slot[0]; + nfs_cache *ffree=NULL; + struct nfs_fattr fattr; + int ct=0; + while(ct<NH_CACHE_SIZE) + { + if(nh->inode_num==inode->i_no && !nh->dead&&!nh->free&&nh->file_pos==pos) + { + if(abs(jiffies-nh->time)<EXPIRE_CACHE) + return nh; + /* + * Revalidate + */ + + if(nfs_proc_getattr(NFS_SERVER(inode), NFS_FH(inode), &fattr)) + { + nfs_bl_cache_invalidate(nh); + continue; /* get attr failed */ + } + if(nh->fattr.modified!=fattr.modified) + { + nfs_bl_cache_invalidate(nh); + continue; /* cache is out of date */ + } + nfs_refresh_inode(inode, fattr); + nh->fattr=fattr; + nfs_bl_cache_revalidate(nh); + return nh; + } + if(nh->free) + ffree=nh; + } + return ffree; +} diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 62a3e0821..bdbe92d0f 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -6,6 +6,10 @@ * nfs directory handling functions */ +#ifdef MODULE +#include <linux/module.h> +#endif + #include <linux/sched.h> #include <linux/errno.h> #include <linux/stat.h> @@ -18,12 +22,9 @@ #include <asm/segment.h> /* for fs functions */ -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) -#define ROUND_UP(x) (((x)+3) & ~3) - static int nfs_dir_read(struct inode *, struct file *filp, char *buf, int count); -static int nfs_readdir(struct inode *, struct file *, struct dirent *, int); +static int nfs_readdir(struct inode *, struct file *, void *, filldir_t); static int nfs_lookup(struct inode *dir, const char *name, int len, struct inode **result); static int nfs_create(struct inode *dir, const char *name, int len, int mode, @@ -87,7 +88,7 @@ static int nfs_dir_read(struct inode *inode, struct file *filp, char *buf, */ static int nfs_readdir(struct inode *inode, struct file *filp, - struct dirent *dirent, int count) + void *dirent, filldir_t filldir) { static int c_dev = 0; static int c_ino; @@ -95,7 +96,7 @@ static int nfs_readdir(struct inode *inode, struct file *filp, static struct nfs_entry *c_entry = NULL; int result; - int i; + int i, index = 0; struct nfs_entry *entry; if (!inode || !S_ISDIR(inode->i_mode)) { @@ -125,7 +126,7 @@ static int nfs_readdir(struct inode *inode, struct file *filp, return 0; } else - entry = c_entry + i + 1; + entry = c_entry + (index = i + 1); break; } } @@ -144,19 +145,27 @@ static int nfs_readdir(struct inode *inode, struct file *filp, c_dev = inode->i_dev; c_ino = inode->i_ino; c_size = result; - entry = c_entry + 0; + entry = c_entry + (index = 0); } } /* if we found it in the cache or from an nfs call, return results */ - - if (entry) { - i = strlen(entry->name); - memcpy_tofs(dirent->d_name, entry->name, i + 1); - put_fs_long(entry->fileid, &dirent->d_ino); - put_fs_word(i, &dirent->d_reclen); - filp->f_pos = entry->cookie; - return ROUND_UP(NAME_OFFSET(dirent)+i+1); + if (!entry) + return 0; + while (index < c_size) { + int nextpos = entry->cookie; + if (filldir(dirent, entry->name, strlen(entry->name), filp->f_pos, entry->fileid) < 0) + break; + filp->f_pos = nextpos; + /* revalidate the cache if we slept in filldir() */ + if (inode->i_dev != c_dev) + break; + if (inode->i_ino != c_ino) + break; + if (nextpos != entry->cookie) + break; + index++; + entry++; } return 0; } diff --git a/fs/nfs/file.c b/fs/nfs/file.c index e71d29483..cf8fe83ce 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -14,6 +14,10 @@ * nfs regular file handling functions */ +#ifdef MODULE +#include <linux/module.h> +#endif + #include <asm/segment.h> #include <asm/system.h> @@ -119,7 +123,7 @@ static int nfs_file_read(struct inode *inode, struct file *file, char *buf, if ((cache[i].inode_num == inode->i_ino) && (cache[i].file_pos <= pos) && (cache[i].file_pos + cache[i].len >= pos + count) - && (abs(jiffies - cache[i].time) <= EXPIRE_CACHE)) + && (abs(jiffies - cache[i].time) < EXPIRE_CACHE)) break; if (i < READ_CACHE_SIZE) { ++cache[i].in_use; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 17f2cb6f0..94b4b4557 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -4,8 +4,19 @@ * Copyright (C) 1992 Rick Sladkey * * nfs inode and superblock handling functions + * + * Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some + * experimental NFS changes. Modularisation taken straight from SYS5 fs. */ +#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> @@ -18,12 +29,12 @@ #include <linux/errno.h> #include <linux/locks.h> -extern int close_fp(struct file *filp, unsigned int fd); +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_statfs(struct super_block *, struct statfs *); +static void nfs_statfs(struct super_block *, struct statfs *, int bufsiz); static struct super_operations nfs_sops = { NULL, /* read inode */ @@ -43,11 +54,11 @@ static void nfs_put_inode(struct inode * inode) void nfs_put_super(struct super_block *sb) { - /* No locks should be open on this, so 0 should be safe as a fd. */ - close_fp(sb->u.nfs_sb.s_server.file, 0); + close_fp(sb->u.nfs_sb.s_server.file); lock_super(sb); sb->s_dev = 0; unlock_super(sb); + MOD_DEC_USE_COUNT; } /* @@ -67,9 +78,11 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data, struct file *filp; dev_t dev = sb->s_dev; + MOD_INC_USE_COUNT; if (!data) { printk("nfs_read_super: missing data argument\n"); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } fd = data->fd; @@ -80,11 +93,13 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data, if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) { printk("nfs_read_super: invalid file descriptor\n"); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } if (!S_ISSOCK(filp->f_inode->i_mode)) { printk("nfs_read_super: not a socket\n"); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } filp->f_count++; @@ -121,32 +136,33 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data, if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) { sb->s_dev = 0; printk("nfs_read_super: get root inode failed\n"); + MOD_DEC_USE_COUNT; return NULL; } return sb; } -void nfs_statfs(struct super_block *sb, struct statfs *buf) +void nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { int error; struct nfs_fsinfo res; + struct statfs tmp; - put_fs_long(NFS_SUPER_MAGIC, &buf->f_type); error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root, &res); if (error) { printk("nfs_statfs: statfs error = %d\n", -error); res.bsize = res.blocks = res.bfree = res.bavail = 0; } - put_fs_long(res.bsize, &buf->f_bsize); - put_fs_long(res.blocks, &buf->f_blocks); - put_fs_long(res.bfree, &buf->f_bfree); - put_fs_long(res.bavail, &buf->f_bavail); - put_fs_long(0, &buf->f_files); - put_fs_long(0, &buf->f_ffree); - /* We should really try to interrogate the remote server to find - it's maximum name length here */ - put_fs_long(NAME_MAX, &buf->f_namelen); + tmp.f_type = NFS_SUPER_MAGIC; + tmp.f_bsize = res.bsize; + tmp.f_blocks = res.blocks; + tmp.f_bfree = res.bfree; + tmp.f_bavail = res.bavail; + tmp.f_files = 0; + tmp.f_ffree = 0; + tmp.f_namelen = NAME_MAX; + memcpy_tofs(buf, &tmp, bufsiz); } /* @@ -238,3 +254,26 @@ int nfs_notify_change(struct inode *inode, struct iattr *attr) inode->i_dirt = 0; 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 +}; + +int init_module(void) +{ + register_filesystem(&nfs_fs_type); + return 0; +} + +void cleanup_module(void) +{ + unregister_filesystem(&nfs_fs_type); +} + +#endif diff --git a/fs/nfs/mmap.c b/fs/nfs/mmap.c index 811176a69..30854469c 100644 --- a/fs/nfs/mmap.c +++ b/fs/nfs/mmap.c @@ -9,6 +9,10 @@ * Copyright (C) 1993 * */ +#ifdef MODULE +#include <linux/module.h> +#endif + #include <linux/stat.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -74,20 +78,25 @@ static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area, } return page; } + struct vm_operations_struct nfs_file_mmap = { NULL, /* open */ NULL, /* close */ + NULL, /* unmap */ + NULL, /* protect */ + NULL, /* sync */ + NULL, /* advise */ nfs_file_mmap_nopage, /* nopage */ NULL, /* wppage */ - NULL, /* share */ - NULL, /* unmap */ + NULL, /* swapout */ + NULL, /* swapin */ }; /* This is used for a general mmap of a nfs file */ int nfs_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) { - if (vma->vm_page_prot & PAGE_RW) /* only PAGE_COW or read-only supported now */ + if (vma->vm_flags & VM_SHARED) /* only PAGE_COW or read-only supported now */ return -EINVAL; if (!inode->i_sb || !S_ISREG(inode->i_mode)) return -EACCES; diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index fd01dad99..9aeb66751 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -33,7 +33,10 @@ #define NFS_PROC_DEBUG #endif -#include <linux/config.h> +#ifdef MODULE +#include <linux/module.h> +#endif + #include <linux/param.h> #include <linux/sched.h> #include <linux/mm.h> @@ -898,6 +901,7 @@ static struct { { NFSERR_NOENT, ENOENT }, { NFSERR_IO, errno_NFSERR_IO }, { NFSERR_NXIO, ENXIO }, + { NFSERR_EAGAIN, EAGAIN }, { NFSERR_ACCES, EACCES }, { NFSERR_EXIST, EEXIST }, { NFSERR_NODEV, ENODEV }, diff --git a/fs/nfs/sock.c b/fs/nfs/sock.c index 2455d938a..ea81f55af 100644 --- a/fs/nfs/sock.c +++ b/fs/nfs/sock.c @@ -18,7 +18,10 @@ * */ -#include <linux/config.h> +#ifdef MODULE +#include <linux/module.h> +#endif + #include <linux/sched.h> #include <linux/nfs_fs.h> #include <linux/errno.h> @@ -34,9 +37,6 @@ * ***FIXME*** should probably put this in nfs_fs.h */ #define NFS_SLACK_SPACE 1024 - -extern struct socket *socki_lookup(struct inode *inode); - #define _S(nr) (1<<((nr)-1)) /* @@ -78,7 +78,7 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int file = server->file; inode = file->f_inode; select = file->f_op->select; - sock = socki_lookup(inode); + sock = &inode->u.socket_i; if (!sock) { printk("nfs_rpc_call: socki_lookup failed\n"); return -EBADF; diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 4cbe631c6..85c40b495 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -8,6 +8,10 @@ * nfs symlink handling code */ +#ifdef MODULE +#include <linux/module.h> +#endif + #include <asm/segment.h> #include <linux/sched.h> |