]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
2.6.29: drop i_mutex readdir patch, doesn't apply
authorChris Wright <chrisw@sous-sol.org>
Wed, 22 Apr 2009 00:40:22 +0000 (17:40 -0700)
committerChris Wright <chrisw@sous-sol.org>
Wed, 22 Apr 2009 00:40:22 +0000 (17:40 -0700)
queue-2.6.29/fix-i_mutex-vs.-readdir-handling-in-nfsd.patch [deleted file]
queue-2.6.29/series

diff --git a/queue-2.6.29/fix-i_mutex-vs.-readdir-handling-in-nfsd.patch b/queue-2.6.29/fix-i_mutex-vs.-readdir-handling-in-nfsd.patch
deleted file mode 100644 (file)
index db3cb3d..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-From stable-bounces@linux.kernel.org  Tue Apr 21 21:20:16 2009
-Date: Tue, 21 Apr 2009 21:20:10 GMT
-Message-Id: <200904212120.n3LLKAO9024993@hera.kernel.org>
-From: David Woodhouse <dwmw2@infradead.org>
-To: jejb@kernel.org, stable@kernel.org
-Subject: Fix i_mutex vs. readdir handling in nfsd
-
-upstream commit: 2f9092e1020246168b1309b35e085ecd7ff9ff72
-
-Commit 14f7dd63 ("Copy XFS readdir hack into nfsd code") introduced a
-bug to generic code which had been extant for a long time in the XFS
-version -- it started to call through into lookup_one_len() and hence
-into the file systems' ->lookup() methods without i_mutex held on the
-directory.
-
-This patch fixes it by locking the directory's i_mutex again before
-calling the filldir functions. The original deadlocks which commit
-14f7dd63 was designed to avoid are still avoided, because they were due
-to fs-internal locking, not i_mutex.
-
-While we're at it, fix the return type of nfsd_buffered_readdir() which
-should be a __be32 not an int -- it's an NFS errno, not a Linux errno.
-And return nfserrno(-ENOMEM) when allocation fails, not just -ENOMEM.
-Sparse would have caught that, if it wasn't so busy bitching about
-__cold__.
-
-Commit 05f4f678 ("nfsd4: don't do lookup within readdir in recovery
-code") introduced a similar problem with calling lookup_one_len()
-without i_mutex, which this patch also addresses. To fix that, it was
-necessary to fix the called functions so that they expect i_mutex to be
-held; that part was done by J. Bruce Fields.
-
-Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-Umm-I-can-live-with-that-by: Al Viro <viro@zeniv.linux.org.uk>
-Reported-by: J. R. Okajima <hooanon05@yahoo.co.jp>
-Tested-by: J. Bruce Fields <bfields@citi.umich.edu>
-LKML-Reference: <8036.1237474444@jrobl>
-Cc: stable@kernel.org
-Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-Signed-off-by: Chris Wright <chrisw@sous-sol.org>
----
- fs/namei.c            |    2 ++
- fs/nfsd/nfs4recover.c |   46 +++++++++-------------------------------------
- fs/nfsd/vfs.c         |   25 +++++++++++++++++++------
- 3 files changed, 30 insertions(+), 43 deletions(-)
-
-diff --git a/fs/namei.c b/fs/namei.c
-index b8433eb..78f253c 100644
---- a/fs/namei.c
-+++ b/fs/namei.c
-@@ -1248,6 +1248,8 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
-       int err;
-       struct qstr this;
-+      WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex));
-+
-       err = __lookup_one_len(name, &this, base, len);
-       if (err)
-               return ERR_PTR(err);
-diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
-index 3444c00..5275097 100644
---- a/fs/nfsd/nfs4recover.c
-+++ b/fs/nfsd/nfs4recover.c
-@@ -229,21 +229,23 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
-               goto out;
-       status = vfs_readdir(filp, nfsd4_build_namelist, &names);
-       fput(filp);
-+      mutex_lock(&dir->d_inode->i_mutex);
-       while (!list_empty(&names)) {
-               entry = list_entry(names.next, struct name_list, list);
-               dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
-               if (IS_ERR(dentry)) {
-                       status = PTR_ERR(dentry);
--                      goto out;
-+                      break;
-               }
-               status = f(dir, dentry);
-               dput(dentry);
-               if (status)
--                      goto out;
-+                      break;
-               list_del(&entry->list);
-               kfree(entry);
-       }
-+      mutex_unlock(&dir->d_inode->i_mutex);
- out:
-       while (!list_empty(&names)) {
-               entry = list_entry(names.next, struct name_list, list);
-@@ -255,36 +257,6 @@ out:
- }
- static int
--nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
--{
--      int status;
--
--      if (!S_ISREG(dir->d_inode->i_mode)) {
--              printk("nfsd4: non-file found in client recovery directory\n");
--              return -EINVAL;
--      }
--      mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
--      status = vfs_unlink(dir->d_inode, dentry);
--      mutex_unlock(&dir->d_inode->i_mutex);
--      return status;
--}
--
--static int
--nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
--{
--      int status;
--
--      /* For now this directory should already be empty, but we empty it of
--       * any regular files anyway, just in case the directory was created by
--       * a kernel from the future.... */
--      nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
--      mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
--      status = vfs_rmdir(dir->d_inode, dentry);
--      mutex_unlock(&dir->d_inode->i_mutex);
--      return status;
--}
--
--static int
- nfsd4_unlink_clid_dir(char *name, int namlen)
- {
-       struct dentry *dentry;
-@@ -294,18 +266,18 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
-       mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
-       dentry = lookup_one_len(name, rec_dir.dentry, namlen);
--      mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
-       if (IS_ERR(dentry)) {
-               status = PTR_ERR(dentry);
--              return status;
-+              goto out_unlock;
-       }
-       status = -ENOENT;
-       if (!dentry->d_inode)
-               goto out;
--
--      status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
-+      status = vfs_rmdir(rec_dir.dentry->d_inode, dentry);
- out:
-       dput(dentry);
-+out_unlock:
-+      mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
-       return status;
- }
-@@ -348,7 +320,7 @@ purge_old(struct dentry *parent, struct dentry *child)
-       if (nfs4_has_reclaimed_state(child->d_name.name, false))
-               return 0;
--      status = nfsd4_clear_clid_dir(parent, child);
-+      status = vfs_rmdir(parent->d_inode, child);
-       if (status)
-               printk("failed to remove client recovery directory %s\n",
-                               child->d_name.name);
-diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
-index 46e6bd2..6c68ffd 100644
---- a/fs/nfsd/vfs.c
-+++ b/fs/nfsd/vfs.c
-@@ -1890,8 +1890,8 @@ static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen,
-       return 0;
- }
--static int nfsd_buffered_readdir(struct file *file, filldir_t func,
--                               struct readdir_cd *cdp, loff_t *offsetp)
-+static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func,
-+                                  struct readdir_cd *cdp, loff_t *offsetp)
- {
-       struct readdir_data buf;
-       struct buffered_dirent *de;
-@@ -1901,11 +1901,12 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
-       buf.dirent = (void *)__get_free_page(GFP_KERNEL);
-       if (!buf.dirent)
--              return -ENOMEM;
-+              return nfserrno(-ENOMEM);
-       offset = *offsetp;
-       while (1) {
-+              struct inode *dir_inode = file->f_path.dentry->d_inode;
-               unsigned int reclen;
-               cdp->err = nfserr_eof; /* will be cleared on successful read */
-@@ -1924,26 +1925,38 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
-               if (!size)
-                       break;
-+              /*
-+               * Various filldir functions may end up calling back into
-+               * lookup_one_len() and the file system's ->lookup() method.
-+               * These expect i_mutex to be held, as it would within readdir.
-+               */
-+              host_err = mutex_lock_killable(&dir_inode->i_mutex);
-+              if (host_err)
-+                      break;
-+
-               de = (struct buffered_dirent *)buf.dirent;
-               while (size > 0) {
-                       offset = de->offset;
-                       if (func(cdp, de->name, de->namlen, de->offset,
-                                de->ino, de->d_type))
--                              goto done;
-+                              break;
-                       if (cdp->err != nfs_ok)
--                              goto done;
-+                              break;
-                       reclen = ALIGN(sizeof(*de) + de->namlen,
-                                      sizeof(u64));
-                       size -= reclen;
-                       de = (struct buffered_dirent *)((char *)de + reclen);
-               }
-+              mutex_unlock(&dir_inode->i_mutex);
-+              if (size > 0) /* We bailed out early */
-+                      break;
-+
-               offset = vfs_llseek(file, 0, SEEK_CUR);
-       }
-- done:
-       free_page((unsigned long)(buf.dirent));
-       if (host_err)
index f1efdf83c28ccdeea9e09ebd7bf532b57f6accad..bb08fdadd33a3882ed23221b47d8db83f7181406 100644 (file)
@@ -101,4 +101,3 @@ gso-fix-support-for-linear-packets.patch
 nfs-fix-the-xdr-iovec-calculation-in-nfs3_xdr_setaclargs.patch
 hugetlbfs-return-negative-error-code-for-bad-mount-option.patch
 scsi-mpt-suppress-debugobjects-warning.patch
-fix-i_mutex-vs.-readdir-handling-in-nfsd.patch