Linus/Alan,

please accept the following patch for knfsd in 2.4.0-prerelease.

What it does is extend the protection offered by  s_nfsd_free_path_sem
to cover the first call to nfsd_iget.
I had previously avoided this as I didn't think it was necessary and
it ment that the semaphore wasn't claimed at all on the common path.
However Chip Salzenberg managed to convince me that it is needed.
I think that his case-in-point is mentioned towards the end of

  http://www.cnn.com/2001/TECH/computing/01/03/linux.mission.idg/index.html

under "Taking the plunge".

There is actually more that I would like to do to this code, but I
don't think now is the right time.  This is the minimal change that
will fix a real bug.

NeilBrown


--- ./fs/nfsd/nfsfh.c   2001/01/04 00:09:13     1.1
+++ ./fs/nfsd/nfsfh.c   2001/01/04 00:09:37     1.2
@@ -346,7 +346,7 @@
        struct dentry *dentry, *result = NULL;
        struct dentry *tmp;
        int  found =0;
-       int err;
+       int err = -ESTALE;
        /* the sb->s_nfsd_free_path_sem semaphore is needed to make sure that only one 
unconnected (free)
         * dcache path ever exists, as otherwise two partial paths might get
         * joined together, which would be very confusing.
@@ -360,19 +360,18 @@
         * Attempt to find the inode.
         */
  retry:
+       down(&sb->s_nfsd_free_path_sem);
        result = nfsd_iget(sb, ino, generation);
-       err = PTR_ERR(result);
-       if (IS_ERR(result))
-               goto err_out;
-       err = -ESTALE;
-       if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED))
-               return result;
-
-       /* result is now an anonymous dentry, which may be adequate as it stands, or 
else
-        * will get spliced into the dcache tree */
-
-       if (!S_ISDIR(result->d_inode->i_mode) && ! needpath) {
-               nfsdstats.fh_anon++;
+       if (IS_ERR(result)
+           || !(result->d_flags & DCACHE_NFSD_DISCONNECTED)
+           || (!S_ISDIR(result->d_inode->i_mode) && ! needpath)) {
+               up(&sb->s_nfsd_free_path_sem);
+           
+               err = PTR_ERR(result);
+               if (IS_ERR(result))
+                       goto err_out;
+               if ((result->d_flags & DCACHE_NFSD_DISCONNECTED))
+                       nfsdstats.fh_anon++;
                return result;
        }
 
@@ -380,14 +379,6 @@
         * location in the tree.
         */
        dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino);
-       down(&sb->s_nfsd_free_path_sem);
-
-       /* claiming the semaphore might have allowed things to get fixed up */
-       if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
-               up(&sb->s_nfsd_free_path_sem);
-               return result;
-       }
-
 
        found = 0;
        if (!S_ISDIR(result->d_inode->i_mode)) {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to