Messages in this thread Patch in this message | | | Date | Mon, 9 Jul 2001 13:28:41 -0400 (EDT) | From | Craig Soules <> | Subject | NFS Client patch |
| |
Hello,
I hope that I am sending this to the appropriate people. I have been working on a project known as Self-Securing Storage here at Carnegie Mellon University. We have developed our storage server to act as an NFSv2 server, and have been using the Linux NFSv2 client to do our benchmarking. I have run across a small problem with the 2.4 implementation of the Linux NFSv2 client.
The problem is in the readdir() operation. The current cookie for a given readdir operation is being stored in the file descriptor. The problem is that it is not being reset to 0 if a change has been made to the directory as is indicated in the NFSv2 spec. This problem is often seen when doing an operation such as rm -rf to a large directory tree due to the asynchronous remove operation that has been implemented.
This has not traditionally been a problem for Linux because in ext2 the cookie is the offset into the directory of the next entry. If a file is deleted in that directory during the readdir() operation, it has no effect since ext2 does lazy directory compaction.
Our system does automatic directory compaction through the use of a tree structure, and so the cookie needs to be invalidated. Also, any other file system whicih does immediate directory compaction would require this.
I have attached my proposed modifications to the end of this file. They have been tested under 2.4.5.
Please let me know if there is anything more I need to do, or if you have any questions. I would really like to get this proper behavior into the kernel.
Thanks, Craig Soules --- linux/include/linux/nfs_fs.h Fri May 25 21:02:11 2001 +++ /usr/src/linux/include/linux/nfs_fs.h Sun Jul 8 14:40:57 2001 @@ -160,13 +160,18 @@ static __inline__ struct rpc_cred * nfs_file_cred(struct file *file) { - struct rpc_cred *cred = (struct rpc_cred *)(file->private_data); + struct nfs_file_private *priv = + (struct nfs_file_private *)(file->private_data); + struct rpc_cred *cred = priv->cred; #ifdef RPC_DEBUG if (cred && cred->cr_magic != RPCAUTH_CRED_MAGIC) BUG(); #endif return cred; } + +#define NFS_FILE_LASTMOD(filep) \ + ((struct nfs_file_private *)((filep)->private_data))->lastmod /* * linux/fs/nfs/dir.c --- linux/include/linux/nfs_fs_i.h Mon Feb 19 20:13:00 2001 +++ /usr/src/linux/include/linux/nfs_fs_i.h Sun Jul 8 14:18:16 2001 @@ -98,4 +98,12 @@ */ #define NFS_LCK_GRANTED 0x0001 /* lock has been granted */ +/* + * NFS private data in the file descriptor + */ +struct nfs_file_private { + struct rpc_cred *cred; + unsigned long lastmod; +}; + #endif --- linux/fs/nfs/dir.c Sat May 19 21:02:45 2001 +++ /usr/src/linux/fs/nfs/dir.c Sun Jul 8 14:35:55 2001 @@ -384,6 +384,11 @@ memset(&my_entry, 0, sizeof(my_entry)); desc->file = filp; + + if(NFS_FILE_LASTMOD(filp) < NFS_ATTRTIMEO_UPDATE(inode)) { + filp->f_pos = 0; + NFS_FILE_LASTMOD(filp) = NFS_ATTRTIMEO_UPDATE(inode); + } desc->target = filp->f_pos; desc->entry = &my_entry; desc->decode = NFS_PROTO(inode)->decode_dirent; --- linux/fs/nfs/inode.c Sat May 19 21:14:38 2001 +++ /usr/src/linux/fs/nfs/inode.c Sun Jul 8 14:36:30 2001 @@ -799,13 +799,14 @@ */ int nfs_open(struct inode *inode, struct file *filp) { + struct nfs_file_private *priv; struct rpc_auth *auth; - struct rpc_cred *cred; lock_kernel(); + priv = kmalloc(sizeof(struct nfs_file_private), GFP_KERNEL); auth = NFS_CLIENT(inode)->cl_auth; - cred = rpcauth_lookupcred(auth, 0); - filp->private_data = cred; + priv->cred = rpcauth_lookupcred(auth, 0); + filp->private_data = priv; unlock_kernel(); return 0; } @@ -814,12 +815,17 @@ { struct rpc_auth *auth; struct rpc_cred *cred; + struct nfs_file_private *priv; lock_kernel(); - auth = NFS_CLIENT(inode)->cl_auth; - cred = nfs_file_cred(filp); - if (cred) - rpcauth_releasecred(auth, cred); + priv = filp->private_data; + if(priv) { + auth = NFS_CLIENT(inode)->cl_auth; + cred = nfs_file_cred(filp); + if (cred) + rpcauth_releasecred(auth, cred); + kfree(priv); + } unlock_kernel(); return 0; } | |