NFS Client patch

From: Craig Soules (soules@happyplace.pdl.cmu.edu)
Date: Mon Jul 09 2001 - 12:28:41 EST


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;
 }
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Jul 15 2001 - 21:00:09 EST