All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: Alexey Lyashkov <alexey.lyashkov@gmail.com>
Cc: linux-fsdevel@vger.kernel.org, Andreas Dilger <adilger@dilger.ca>,
	Andrew Perepechko <anserper@yandex.ru>, Jan Kara <jack@suse.cz>
Subject: Re: [PATCH 1/2] Re introduces a DCACHE_DENTRY_UNHASHED flag
Date: Tue, 13 Dec 2016 01:44:20 +0000	[thread overview]
Message-ID: <20161213014420.GA2940@ZenIV.linux.org.uk> (raw)
In-Reply-To: <148056588886.28852.15338791339456402291.stgit@alexeys-macbook-pro.local>

On Thu, Dec 01, 2016 at 07:18:26AM +0300, Alexey Lyashkov wrote:
> rehash process protected with d_seq and d_lock locks, but VFS have access to the
> d_hashed field without any locks sometimes. It produce errors with get cwd
> operations or fsnotify may report an unlink event sometimes. d_seq lock isn’t
> used to protect due possibility to sleep with holding locks, and d_lock is too
> hot to check a simple state, lets return a DCACHE_DENTRY_UNHASHED flag to
> ability to check a unhashed state without locks held.

>   *	Returns true if the dentry passed is not currently hashed.
> + *	hlist_bl_unhashed can't be used as race with d_move().
>   */
>   
>  static inline int d_unhashed(const struct dentry *dentry)
>  {
> -	return hlist_bl_unhashed(&dentry->d_hash);
> +	return dentry->d_flags & DCACHE_DENTRY_UNHASHED;
>  }

The real problem here is the unsafe use of d_unlinked().  You are papering
over that, and doing so in the wrong place.  Note that most of the callers
of d_unhashed() are either under ->d_lock on it or on parent or with
parent locked by ->i_rwsem, or in places where false positive is fine
since it only pushes us to slow path.  Excluding those, we are left with

fs/autofs4/expire.c:226:        if (!simple_positive(top))
fs/autofs4/expire.c:537:                if (d_unhashed(dentry))
fs/ceph/dir.c:649:              BUG_ON(!d_unhashed(dentry));
fs/ceph/inode.c:1074:   if (!d_unhashed(dn))
fs/ceph/inode.c:1322:                           if (have_lease && d_unhashed(dn))
fs/cifs/inode.c:945:            if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
fs/coredump.c:727:              if (d_unhashed(cprm.file->f_path.dentry))
fs/dcache.c:3202:       if (d_unlinked(path->dentry)) {
fs/dcache.c:3366:       if (d_unlinked(dentry)) {
fs/dcache.c:3423:       if (!d_unlinked(pwd.dentry)) {
fs/debugfs/file.c:77:   if (d_unlinked(dentry))
fs/namespace.c:3154:    if (d_unlinked(new.dentry))
fs/namespace.c:738:                     if (d_unlinked(dentry))
fs/notify/inotify/inotify_fsnotify.c:85:                if (d_unlinked(path->dentry))
security/apparmor/file.c:263:   if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0)
security/apparmor/path.c:149:   if (d_unlinked(path->dentry) && d_is_positive(path->dentry) &&

VFS part of that consists of
	* d_path() and friends, including getcwd().  Might bloody well turn
those into
	if (unlikely(d_unhashed(dentry))) {
		/* recheck under d_lock */
		spin_lock(&dentry->d_lock);
		if (d_unhashed(dentry))
			...
	* mount(2)/pivot_root(2) vs. rename(2) - userland race; after all,
had you called it just a bit later, you *would* have gotten that -ENOENT.
Nothing the kernel can actually do here.
	* do_coredump() bailing out on races with somebody moving the
coredump to be around.  Cry me a river...
	* idiotify playing with d_unlinked(); same story as with
d_path() et.al.

autofs ones are, AFAICS, harmless - you might spin a bit more (if that), but
no worse than that.  If they can be triggered at all, that is.
No idea about the ceph ones (i.e. whether they can race with d_move()
like that, whether it really cares, etc.).  debugfs looks like it can't race
with d_move() at all.  cifs... no idea, really.  Looks like we _might_
have an odd behaviour from server not spotted in some cases we would've
spotted it otherwise.  Not sure if we care.  Apparmor... you'll need to
ask apparmor folks.

NAK in that form.

  parent reply	other threads:[~2016-12-13  1:44 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-01  4:18 [PATCH v3 0/2] d_unhashed fixes and cleanup Alexey Lyashkov
2016-12-01  4:18 ` [PATCH 1/2] Re introduces a DCACHE_DENTRY_UNHASHED flag Alexey Lyashkov
2016-12-01  8:15   ` Amir Goldstein
2016-12-01 10:03     ` Alexey Lyashkov
2016-12-01 11:23       ` Amir Goldstein
2016-12-08  2:32   ` Oleg Drokin
2016-12-08  5:16     ` Alexey Lyashkov
2016-12-13  1:44   ` Al Viro [this message]
2016-12-01  4:18 ` [PATCH 2/2] cleanup of d_unhashed usage Alexey Lyashkov

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=20161213014420.GA2940@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=adilger@dilger.ca \
    --cc=alexey.lyashkov@gmail.com \
    --cc=anserper@yandex.ru \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.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.