diff mbox

[1/5] exportfs: clear DISCONNECTED on all parents sooner

Message ID 1381869574-10662-2-git-send-email-bfields@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Bruce Fields Oct. 15, 2013, 8:39 p.m. UTC
From: "J. Bruce Fields" <bfields@redhat.com>

Once we've found any connected parent, we know all our parents are
connected--that's true even if there's a concurrent rename.  May as well
clear them all at once.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
---
 fs/exportfs/expfs.c |   24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

Comments

Christoph Hellwig Oct. 16, 2013, 7:13 a.m. UTC | #1
On Tue, Oct 15, 2013 at 04:39:29PM -0400, J. Bruce Fields wrote:
> From: "J. Bruce Fields" <bfields@redhat.com>
> 
> Once we've found any connected parent, we know all our parents are
> connected--that's true even if there's a concurrent rename.  May as well
> clear them all at once.
> 
> Signed-off-by: J. Bruce Fields <bfields@redhat.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

>  		if (!IS_ROOT(pd)) {
>  			/* must have found a connected parent - great */
> -			spin_lock(&pd->d_lock);
> -			pd->d_flags &= ~DCACHE_DISCONNECTED;
> -			spin_unlock(&pd->d_lock);
> +			clear_disconnected(target_dir);
>  			noprogress = 0;
>  		} else if (pd == mnt->mnt_sb->s_root) {
>  			printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");

You might as well throw a patch in to make this condition a BUG_ON, it
would indicate a nasty bug in the dcache and has never triggered in the
last 10 years as far as I know.

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bruce Fields Oct. 16, 2013, 1:56 p.m. UTC | #2
On Wed, Oct 16, 2013 at 12:13:43AM -0700, Christoph Hellwig wrote:
> On Tue, Oct 15, 2013 at 04:39:29PM -0400, J. Bruce Fields wrote:
> > From: "J. Bruce Fields" <bfields@redhat.com>
> > 
> > Once we've found any connected parent, we know all our parents are
> > connected--that's true even if there's a concurrent rename.  May as well
> > clear them all at once.
> > 
> > Signed-off-by: J. Bruce Fields <bfields@redhat.com>
> 
> Looks good,
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> 
> >  		if (!IS_ROOT(pd)) {
> >  			/* must have found a connected parent - great */
> > -			spin_lock(&pd->d_lock);
> > -			pd->d_flags &= ~DCACHE_DISCONNECTED;
> > -			spin_unlock(&pd->d_lock);
> > +			clear_disconnected(target_dir);
> >  			noprogress = 0;
> >  		} else if (pd == mnt->mnt_sb->s_root) {
> >  			printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
> 
> You might as well throw a patch in to make this condition a BUG_ON, it
> would indicate a nasty bug in the dcache and has never triggered in the
> last 10 years as far as I know.

We've seen some ugly crashes made uglier by unnecessary BUG()s.  I guess
that wouldn't be the case here as we're not holding any critical locks
and all we're going to kill is an nfsd thread or open_by_handle caller.
And like you say it's a very unlikely case anyway.

So, OK, I'll turn this case into a BUG_ON in a separate patch.

--b.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index c43fe9b..455b0bb 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -90,6 +90,22 @@  find_disconnected_root(struct dentry *dentry)
 	return dentry;
 }
 
+static void clear_disconnected(struct dentry *dentry)
+{
+	dget(dentry);
+	while (dentry->d_flags & DCACHE_DISCONNECTED) {
+		struct dentry *parent = dget_parent(dentry);
+
+		spin_lock(&dentry->d_lock);
+		dentry->d_flags &= ~DCACHE_DISCONNECTED;
+		spin_unlock(&dentry->d_lock);
+
+		dput(dentry);
+		dentry = parent;
+	}
+	dput(dentry);
+}
+
 /*
  * Make sure target_dir is fully connected to the dentry tree.
  *
@@ -114,15 +130,11 @@  reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf)
 
 		if (!IS_ROOT(pd)) {
 			/* must have found a connected parent - great */
-			spin_lock(&pd->d_lock);
-			pd->d_flags &= ~DCACHE_DISCONNECTED;
-			spin_unlock(&pd->d_lock);
+			clear_disconnected(target_dir);
 			noprogress = 0;
 		} else if (pd == mnt->mnt_sb->s_root) {
 			printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
-			spin_lock(&pd->d_lock);
-			pd->d_flags &= ~DCACHE_DISCONNECTED;
-			spin_unlock(&pd->d_lock);
+			clear_disconnected(target_dir);
 			noprogress = 0;
 		} else {
 			/*