From: "J. R. Okajima" <hooanon05g@gmail.com>
To: Al Viro <viro@ZenIV.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Subject: Re: Q. hlist_bl_add_head_rcu() in d_alloc_parallel()
Date: Sun, 19 Jun 2016 14:24:44 +0900 [thread overview]
Message-ID: <2123.1466313884@jrobl> (raw)
In-Reply-To: <20160617221614.GE14480@ZenIV.linux.org.uk>
Al Viro:
> Huh? If you have two processes reaching that insertion into the in-lookup
> hash, whoever gets the hlist_bl_lock() first wins; the loser will find
> the instance added by the winner and bugger off with it. RCU is completely
> unrelated to that. It's about the search in *primary* hash.
Ok, forget about rcu_barrier.
----------------------------------------
> look for match in in-lookup hash
> if found
> unlock the chain
> wait for the match to cease being in-lookup
> drop the match
> goto retry [see below]
> insert new into in-lookup hash
The actual matching test which corresponds to above pseudo-code (if
found) is this (from v4.7-rc3).
dentry->d_name.hash != hash
dentry->d_parent != parent
d_unhashed(dentry)
name (length and string)
I am afraid this d_unhashed() test is racy.
Here is what I am guessing.
- two processes try opening the same file
- the both enter the hlist_bl_lock protected loop in d_alloc_parallel()
- the winner puts the new dentry into in-lookup hash
+ here d_unhashed(dentry) would still return true.
- then the winner process will call ->atomic_open or ->lookup. finally
d_add() and rehash will be called and the dentry will be moved to the
primary hash.
+ here d_unhashed(dentry) would return false.
As soon as the winner calls hlist_bl_unlock(), the looser starts
d_in_lookup_hash loop and find the dentry which the winner added.
- the looser (or we should call processB) do the tests
dentry->d_name.hash != hash
dentry->d_parent != parent
d_unhashed(dentry)
- if processA has already called d_add and rehash, then this
d_unhashed() test would return false, and processB will throw away his
own 'new' dentry and return the found one.
- if processA has NOT called d_add and rehash yet (due to the schedule
timing), then this d_unhashed() test would return true, and processB
will simply skip the found dentry.
in this case, processB will add his own 'new' dentry into in-lookup
hash and return it.
Finally this race between these two
- d_add and rehash via ->atomic_open or ->lookup
- d_unhashed test in d_alloc_parallel
leads to the duplicated dentries (same named dentry under the same
parent).
Do you think it can happen?
J. R. Okajima
next prev parent reply other threads:[~2016-06-19 5:24 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-17 20:50 Q. hlist_bl_add_head_rcu() in d_alloc_parallel() J. R. Okajima
2016-06-17 22:16 ` Al Viro
2016-06-17 22:56 ` Al Viro
2016-06-19 5:24 ` J. R. Okajima [this message]
2016-06-19 16:55 ` Al Viro
2016-06-20 4:34 ` J. R. Okajima
2016-06-20 5:35 ` Al Viro
2016-06-20 14:51 ` Al Viro
2016-06-20 17:14 ` [git pull] vfs fixes Al Viro
2016-06-23 1:19 ` Q. hlist_bl_add_head_rcu() in d_alloc_parallel() J. R. Okajima
2016-06-23 2:58 ` Al Viro
2016-06-24 5:57 ` Linus Torvalds
2016-06-25 22:54 ` Al Viro
2016-06-26 1:25 ` Linus Torvalds
2016-06-29 8:17 ` Al Viro
2016-06-29 9:22 ` Hekuang
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=2123.1466313884@jrobl \
--to=hooanon05g@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=viro@ZenIV.linux.org.uk \
/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.