Messages in this thread Patch in this message |  | | | Date | Thu, 13 Jul 2000 19:40:29 -0500 | | From | Jeff Epler <> | | Subject | zapping nfs file cache |
| |
I would like to see functionality in the kernel nfs client which permits userspace to request that any cached data (from previous reads) be dropped from memory. This is exactly what 'nfs_zap_caches(inode)' does in the kernel.
I'm in the process of porting a Unix application to Linux. We use a custom locking protocol on top of NFS. I'd originally been told that the only special thing we required from the NFS implementation was a way to turn off attribute caching, which is already available. However, after our locking test suite failed on Linux, someone remembered "the other" NFS hack we've had to make on our other ports, which involves the ability to request that any cached data from an NFS file (present due to previous reads) be dropped, so that a subsequent read will result in an NFS read request to the server.
Formerly we've overloaded fsync(), but after some discussion it was suggested to implement it as an ioctl(), rather than perverting the meaning of fsync(). Unfortunately, there doesn't seem to be any way to access this functionality from userspace without adding an ioctl or the like.
The attached patch adds this functionality. I'd like to hear any responses, including any problems with the patch, suggestions for alternate ways I could achieve the same thing, suggestions for how to make these changes available to our end-users in an easy-to-use and license-compliant fashion, and most wonderful of all being told that this kind of functionality would be included in a standard kernel somewhere down the road.
Jeff PS I don't understand the locking situation, but I'm the most linux-savvy of the people working on this project so I get to write this message. Apparently this problem crops up when a sequence like this occurs, due to the limited resolution of mtime: Client 1 Client 2 Write to file Read file -> NFS request Write to file again within 1 second Read file -> Timestamp matches, use cached (invalid) data -- Jeff Epler jepler@inetnebr.com --- fs/nfs.orig/file.c Thu Jul 13 18:51:06 2000 +++ fs/nfs/file.c Thu Jul 13 19:15:58 2000 @@ -37,6 +37,8 @@ static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *); static int nfs_file_flush(struct file *); static int nfs_fsync(struct file *, struct dentry *dentry); +static int nfs_file_ioctl(struct inode * inode, struct file *filp, + unsigned int cmd, unsigned long arg); static struct file_operations nfs_file_operations = { NULL, /* lseek - default */ @@ -44,7 +46,7 @@ nfs_file_write, /* write */ NULL, /* readdir - bad */ NULL, /* select - default */ - NULL, /* ioctl - default */ + nfs_file_ioctl, /* ioctl */ nfs_file_mmap, /* mmap */ nfs_open, /* open */ nfs_file_flush, /* flush */ @@ -118,6 +120,20 @@ if (!result) result = generic_file_read(file, buf, count, ppos); return result; +} + +static int +nfs_file_ioctl(struct inode * inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case NFS_IOC_ZAP_CACHES: + nfs_zap_caches(inode); + return 0; + break; + default: + return -EINVAL; + } } static int --- fs/nfs.orig/inode.c Thu Jul 13 18:51:06 2000 +++ fs/nfs/inode.c Thu Jul 13 19:08:03 2000 @@ -37,7 +37,6 @@ #define NFS_PARANOIA 1 static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *); -static void nfs_zap_caches(struct inode *); static void nfs_invalidate_inode(struct inode *); static void nfs_read_inode(struct inode *); @@ -432,7 +431,7 @@ /* * Invalidate the local caches */ -static void +void nfs_zap_caches(struct inode *inode) { NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); --- include/linux/nfs_fs.h.orig Thu Jul 13 19:03:21 2000 +++ include/linux/nfs_fs.h Thu Jul 13 19:09:47 2000 @@ -17,6 +17,8 @@ #include <linux/nfs.h> #include <linux/nfs_mount.h> +#include <linux/ioctl.h> + /* * Enable debugging support for nfs client. * Requires RPC_DEBUG. @@ -25,6 +27,8 @@ # define NFS_DEBUG #endif +#define NFS_IOC_ZAP_CACHES _IO('d', 0) + /* * NFS_MAX_DIRCACHE controls the number of simultaneously cached * directory chunks. Each chunk holds the list of nfs_entry's returned @@ -184,6 +188,7 @@ extern int nfs_open(struct inode *, struct file *); extern int nfs_release(struct inode *, struct file *); extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *); +extern void nfs_zap_caches(struct inode *inode); /* * linux/fs/nfs/file.c |  |