Messages in this thread Patch in this message | | | Subject | [PATCH] knfsd problmes (fwd) | Date | Wed, 27 Jan 1999 13:45:22 -0800 | From | "G. Allen Morris III" <> |
| |
This patch solves two problems with knfsd:
1. The Oops generated if a rename was done on a file that had been deleted on the sever (test odentry->d_inode).
2. rename and rmdir now test for a race condition (check_parent).
--- linux-2.2.0.orig/fs/nfsd/vfs.c Tue Jan 19 11:22:18 1999 +++ linux/fs/nfsd/vfs.c Wed Jan 27 13:19:17 1999 @@ -988,6 +988,20 @@ } /* + * We need to do a check-parent every time + * after we have locked the parent - to verify + * that the parent is still our parent and + * that we are still hashed onto it.. + * + * This is requied in case two processes race + * on removing (or moving) the same entry: the + * parent lock will serialize them, but the + * other process will be too late.. + */ +#define check_parent(dir, dentry) \ + ((dir) == (dentry)->d_parent->d_inode && !list_empty(&dentry->d_hash)) + +/* * This follows the model of double_lock() in the VFS. */ static inline void nfsd_double_down(struct semaphore *s1, struct semaphore *s2) @@ -1048,6 +1062,10 @@ if (IS_ERR(odentry)) goto out_nfserr; + err = -ENOENT; + if (!odentry->d_inode) + goto out_dput_old; + ndentry = lookup_dentry(tname, dget(tdentry), 0); err = PTR_ERR(ndentry); if (IS_ERR(ndentry)) @@ -1057,13 +1075,18 @@ * Lock the parent directories. */ nfsd_double_down(&tdir->i_sem, &fdir->i_sem); - /* N.B. check for parent changes after locking?? */ - - err = vfs_rename(fdir, odentry, tdir, ndentry); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - write_inode_now(fdir); - write_inode_now(tdir); - } + err = -ENOENT; + /* GAM3 check for parent changes after locking. */ + if (check_parent(fdir, odentry) && + check_parent(tdir, ndentry)) { + + err = vfs_rename(fdir, odentry, tdir, ndentry); + if (!err && EX_ISSYNC(tfhp->fh_export)) { + write_inode_now(fdir); + write_inode_now(tdir); + } + } else + dprintk("nfsd: Caught race in nfsd_rename"); DQUOT_DROP(fdir); DQUOT_DROP(tdir); @@ -1137,10 +1160,9 @@ if (!fhp->fh_pre_mtime) fhp->fh_pre_mtime = dirp->i_mtime; fhp->fh_locked = 1; - /* CHECKME: Should we do something with the child? */ err = -ENOENT; - if (rdentry->d_parent->d_inode == dirp) + if (check_parent(dirp, rdentry)) err = vfs_rmdir(dirp, rdentry); rdentry->d_count--; --------------------------------- G. Allen Morris III - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |