Skip to content

Commit

Permalink
make sure that __dentry_kill() always invalidates d_seq, unhashed or not
Browse files Browse the repository at this point in the history
commit 4c0d7cd upstream.

RCU pathwalk relies upon the assumption that anything that changes
->d_inode of a dentry will invalidate its ->d_seq.  That's almost
true - the one exception is that the final dput() of already unhashed
dentry does *not* touch ->d_seq at all.  Unhashing does, though,
so for anything we'd found by RCU dcache lookup we are fine.
Unfortunately, we can *start* with an unhashed dentry or jump into
it.

We could try and be careful in the (few) places where that could
happen.  Or we could just make the final dput() invalidate the damn
thing, unhashed or not.  The latter is much simpler and easier to
backport, so let's do it that way.

Reported-by: "Dae R. Jeong" <[email protected]>
Cc: [email protected]
Signed-off-by: Al Viro <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Al Viro authored and gregkh committed Aug 15, 2018
1 parent abfc0ec commit d5426a3
Showing 1 changed file with 2 additions and 5 deletions.
7 changes: 2 additions & 5 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,14 +357,11 @@ static void dentry_unlink_inode(struct dentry * dentry)
__releases(dentry->d_inode->i_lock)
{
struct inode *inode = dentry->d_inode;
bool hashed = !d_unhashed(dentry);

if (hashed)
raw_write_seqcount_begin(&dentry->d_seq);
raw_write_seqcount_begin(&dentry->d_seq);
__d_clear_type_and_inode(dentry);
hlist_del_init(&dentry->d_u.d_alias);
if (hashed)
raw_write_seqcount_end(&dentry->d_seq);
raw_write_seqcount_end(&dentry->d_seq);
spin_unlock(&dentry->d_lock);
spin_unlock(&inode->i_lock);
if (!inode->i_nlink)
Expand Down

0 comments on commit d5426a3

Please sign in to comment.