All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: "Drokin, Oleg" <oleg.drokin@intel.com>
Cc: "Dilger, Andreas" <andreas.dilger@intel.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	"<linux-fsdevel@vger.kernel.org>" <linux-fsdevel@vger.kernel.org>
Subject: Re: races in ll_splice_alias()
Date: Wed, 9 Mar 2016 00:34:19 +0000	[thread overview]
Message-ID: <20160309003416.GY17997@ZenIV.linux.org.uk> (raw)
In-Reply-To: <A5CA4682-77B1-4DF4-A784-7C7C2FAFC9AF@intel.com>

On Tue, Mar 08, 2016 at 11:18:09PM +0000, Drokin, Oleg wrote:
> Rename on server cannot get us to see the same directory in two places, or what's
> the scenario?
> In Lustre:
> thread1: lookup a directory on the server.
>          get a lock back
>          instantiate a dentry (guarded by the lock)
>          make a lock revocable (ll_lookup_finish_locks() in ll_lookup_it())
> thread2: rename the directory moving it somewhere else
>          server attempts to revoke the lock from thread1
>          node that runs thread1 drops the lock and marks all dentries for that
>               inode invalid
>          server completes rename and releases the lock it holds
> thread3: lookup the directory under new name on the server
>          this can only return from server when the rename has completed and the
>          dentry from thread1 marked invalid.

thread2 might run on another client; might or might not make any difference,
but in any case server going nuts shouldn't corrupt data structures on client...

> Ok, let me try my hand at that. Hopefully whatever complications are there would
> show themselves right away too.
> 
> > would always either inserted inode reference into a new dentry or dropped it.
> > I'm still trying to trace what does iput() in case of error in your current
> > code; I understand the one in do_statahead_enter(), but what does it in
> > ll_lookup_it_finish()?
> 
> You mean when ll_d_init() fails in ll_splice_alias()?
> Hm… It appears that we are indeed leaking the inode in that case, thanks.
> I'll try to address that too.
> Hm, in fact this was almost noticed, but I guess nobody retested it after
> fixing the initial crash we had with 7486bc06ab2c46d6957f0211d09bc549aaf9cc87

If that's the case, I'd try this (on top of the patch from upthread):

diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
index da5f443..bcc9841 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -320,81 +320,37 @@ void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2)
 }
 
 /*
- * try to reuse three types of dentry:
- * 1. unhashed alias, this one is unhashed by d_invalidate (but it may be valid
- *    by concurrent .revalidate).
- * 2. INVALID alias (common case for no valid ldlm lock held, but this flag may
- *    be cleared by others calling d_lustre_revalidate).
- * 3. DISCONNECTED alias.
- */
-static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry)
-{
-	struct dentry *alias, *discon_alias, *invalid_alias;
-
-	if (hlist_empty(&inode->i_dentry))
-		return NULL;
-
-	discon_alias = invalid_alias = NULL;
-
-	ll_lock_dcache(inode);
-	hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
-		LASSERT(alias != dentry);
-
-		spin_lock(&alias->d_lock);
-		if (alias->d_flags & DCACHE_DISCONNECTED)
-			/* LASSERT(last_discon == NULL); LU-405, bz 20055 */
-			discon_alias = alias;
-		else if (alias->d_parent == dentry->d_parent	     &&
-			 alias->d_name.hash == dentry->d_name.hash       &&
-			 alias->d_name.len == dentry->d_name.len	 &&
-			 memcmp(alias->d_name.name, dentry->d_name.name,
-				dentry->d_name.len) == 0)
-			invalid_alias = alias;
-		spin_unlock(&alias->d_lock);
-
-		if (invalid_alias)
-			break;
-	}
-	alias = invalid_alias ?: discon_alias ?: NULL;
-	if (alias) {
-		spin_lock(&alias->d_lock);
-		dget_dlock(alias);
-		spin_unlock(&alias->d_lock);
-	}
-	ll_unlock_dcache(inode);
-
-	return alias;
-}
-
-/*
  * Similar to d_splice_alias(), but lustre treats invalid alias
  * similar to DCACHE_DISCONNECTED, and tries to use it anyway.
  */
 struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
 {
-	struct dentry *new;
+	struct dentry *alias = NULL;
 	int rc;
 
 	if (inode) {
-		new = ll_find_alias(inode, de);
-		if (new) {
-			rc = ll_d_init(new);
-			if (rc < 0) {
-				dput(new);
-				return ERR_PTR(rc);
-			}
-			d_move(new, de);
+		alias = d_exact_alias(de, inode);
+		if (alias)
+			iput(inode);
+	}
+
+	if (!alias) {
+		rc = ll_d_init(de);
+		if (rc < 0) {
 			iput(inode);
-			CDEBUG(D_DENTRY,
-			       "Reuse dentry %p inode %p refc %d flags %#x\n",
-			      new, d_inode(new), d_count(new), new->d_flags);
-			return new;
+			return ERR_PTR(rc);
 		}
+		alias = d_splice_alias(inode, de);
+		if (IS_ERR(alias))
+			return alias;
+	}
+
+	if (alias) {
+		CDEBUG(D_DENTRY,
+		       "Reuse dentry %p inode %p refc %d flags %#x\n",
+		      alias, d_inode(alias), d_count(alias), alias->d_flags);
+		return alias;
 	}
-	rc = ll_d_init(de);
-	if (rc < 0)
-		return ERR_PTR(rc);
-	d_add(de, inode);
 	CDEBUG(D_DENTRY, "Add dentry %p inode %p refc %d flags %#x\n",
 	       de, d_inode(de), d_count(de), de->d_flags);
 	return de;
diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c
index 88ffd8e..6c64de0 100644
--- a/drivers/staging/lustre/lustre/llite/statahead.c
+++ b/drivers/staging/lustre/lustre/llite/statahead.c
@@ -1576,6 +1576,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 					alias = ll_splice_alias(inode,
 								   *dentryp);
 					if (IS_ERR(alias)) {
+						entry->se_inode = NULL;
 						ll_sai_unplug(sai, entry);
 						return PTR_ERR(alias);
 					}

  reply	other threads:[~2016-03-09  0:34 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-08 16:05 races in ll_splice_alias() Al Viro
2016-03-08 20:44 ` Drokin, Oleg
2016-03-08 21:11   ` Al Viro
2016-03-08 23:18     ` Drokin, Oleg
2016-03-09  0:34       ` Al Viro [this message]
2016-03-09  0:53         ` Drokin, Oleg
2016-03-09  1:26           ` Al Viro
2016-03-09  5:20             ` Drokin, Oleg
2016-03-09 23:47             ` Drokin, Oleg
2016-03-10  2:20               ` races in ll_splice_alias() and elsewhere (ext4, ocfs2) Al Viro
2016-03-10  2:59                 ` Al Viro
2016-03-10 23:55                   ` Theodore Ts'o
2016-03-11  3:18                     ` Al Viro
2016-03-11 15:42                       ` Theodore Ts'o
2016-03-10  3:08                 ` Drokin, Oleg
2016-03-10  3:34                   ` Al Viro
2016-03-10  3:46                     ` Drokin, Oleg
2016-03-10  4:22                       ` Drokin, Oleg
2016-03-10  4:43                       ` Al Viro
2016-03-10  5:15                         ` Al Viro
2016-03-11  3:47                           ` Drokin, Oleg
2016-03-10  5:47                         ` Drokin, Oleg
2016-03-10 19:59                 ` Al Viro
2016-03-10 20:34                   ` do we need that smp_wmb() in __d_alloc()? Al Viro
2016-03-10 21:17                     ` Al Viro
2016-03-10 21:22                   ` races in ll_splice_alias() and elsewhere (ext4, ocfs2) Drokin, Oleg
2016-03-10 23:23                     ` Al Viro
2016-03-11  3:25                       ` Drokin, Oleg
2016-03-12 17:22                         ` Al Viro
2016-03-13 14:35                           ` Sage Weil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160309003416.GY17997@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=andreas.dilger@intel.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=oleg.drokin@intel.com \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.