Hi Neil and ReiserFS Team,
I'm having problems with stale file handles on failover testing using
2.4.6 servers with ReiserFS and 2.2.19 clients mounting with NFS V2.  I
do not get stale file handles mounting with NFS V3.  The problem seems
to be because the NFS V2 file handle size NFS_FHSIZE of 32 is too short
for the parent directory generation number field set in
reiserfs_dentry_to_fh().  It appears that the same issue exists in
2.4.9, but I haven't tested it yet.

First, I have a question about the maxsize, or, length parameter being
passed to _fh_update() and on to dentry_to_fh().  In _fh_update() and
reiserfs_dentry_to_fh(), the maxsize passed appears to be treated as the
number of __u32 file handle fields available.  But, fh_compose() and
fh_update() appear to be passing number of bytes.  (So,
reiserfs_dentry_to_fh() thinks it has more file handle room than what
gets sent back to the clients.)  Changing the calls to _fh_update(),
means that reiserfs_dentry_to_fh() only has 5 fields to work with for
NFS V2.  I think I remember from discussions on this list that the
directory information is needed to uniquely identify the file, so I
didn't want NFS V2 to only get the type 3 file handles.  I thought it
would be safe to have a type 5 file handle that leaves off the directory
generation number when only 5 fields are available.  Since
reiserfs_fh_to_dentry() first checks the file's generation number and
that has matched successfully before going on to the directory, would it
be safe to skip the generation check for the directory?

Here is a change that I've successfully tested with NFS V2 and NFS V3
mounts from 2.2.19 clients to 2.4.6 NFS + ReiserFS servers.  Would you
please let me know if this fix is in error?  I'll be glad to test your
official fix!

Thanks for any help!
Anne

diff -ur linux-2.4.6-orig/fs/nfsd/nfsfh.c linux-2.4.6-cv/fs/nfsd/nfsfh.c
--- linux-2.4.6-orig/fs/nfsd/nfsfh.c    Mon Jul  2 17:14:59 2001
+++ linux-2.4.6-cv/fs/nfsd/nfsfh.c      Mon Aug 27 18:05:46 2001 
@@ -811,7 +814,7 @@
                *datap++ = ino_t_to_u32(exp->ex_ino);
                if (inode)
                        fhp->fh_handle.fh_fileid_type =
-                               _fh_update(dentry, exp, &datap,
fhp->fh_maxsize-3);
+                               _fh_update(dentry, exp, &datap,
fhp->fh_maxsize/4 -3);
                fhp->fh_handle.fh_size =
(datap-fhp->fh_handle.fh_auth+1)*4;
        }

@@ -845,7 +848,8 @@
                datap = fhp->fh_handle.fh_auth+
                        fhp->fh_handle.fh_size/4 -1;
                fhp->fh_handle.fh_fileid_type =
-                       _fh_update(dentry, fhp->fh_export, &datap,
fhp->fh_maxsize-fhp->fh_handle.fh_size);
+                       _fh_update(dentry, fhp->fh_export, &datap,
+                                 
(fhp->fh_maxsize-fhp->fh_handle.fh_size)/4);
                fhp->fh_handle.fh_size =
(datap-fhp->fh_handle.fh_auth+1)*4;
        }
 out: 

diff -ur linux-2.4.6-orig/fs/reiserfs/inode.c
linux-2.4.6-cv/fs/reiserfs/inode.c
--- linux-2.4.6-orig/fs/reiserfs/inode.c        Mon Jul  2 17:48:43 2001
+++ linux-2.4.6-cv/fs/reiserfs/inode.c  Mon Aug 27 18:06:11 2001    
@@ -1216,14 +1216,14 @@
            key.on_disk_key.k_objectid = data[0] ;
            key.on_disk_key.k_dir_id = data[1] ;
            inode = reiserfs_iget(sb, &key) ;
-           if (inode && (fhtype == 3 || fhtype == 6) &&
+           if (inode && (fhtype == 3 || fhtype >= 5) &&
                data[2] != inode->i_generation) {
                    iput(inode) ;
                    inode = NULL ;
            }
     } else {
-           key.on_disk_key.k_objectid = data[fhtype==6?3:2] ;
-           key.on_disk_key.k_dir_id = data[fhtype==6?4:3] ;
+           key.on_disk_key.k_objectid = data[fhtype>=5?3:2] ;
+           key.on_disk_key.k_dir_id = data[fhtype>=5?4:3] ;
            inode = reiserfs_iget(sb, &key) ;
            if (inode && fhtype == 6 &&
                data[5] != inode->i_generation) {
@@ -1272,12 +1272,16 @@
     data[2] = inode->i_generation ;
     *lenp = 3;
     /* no room for directory info? return what we've stored so far */
-    if (maxlen < 6 || ! need_parent)
+    if (maxlen < 5 || ! need_parent)   
         return 3;

     inode = dentry->d_parent->d_inode ;
     data[3] = inode->i_ino ;
     data[4] = le32_to_cpu(INODE_PKEY (inode)->k_dir_id) ;
+    if (maxlen == 5) {
+       *lenp = 5;
+       return 5;
+    }
     data[5] = inode->i_generation ;
     *lenp = 6;
     return 6;

Reply via email to