PATCH(prerelease) - knfsd fix

From: Neil Brown (neilb@cse.unsw.edu.au)
Date: Wed Jan 03 2001 - 19:25:35 EST


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 majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Jan 07 2001 - 21:00:17 EST