diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-07-24 23:36:04 +0300 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-07-24 23:36:04 +0300 |
commit | 17648b871d3cecf310f55ce8c6ce5821d135f6ec (patch) | |
tree | e4c43b59acdd43d9d68ec553016e08042899a0d7 /fs/dcache.c | |
parent | f4fdace94722cd4ca60bf72816de01ab911c45d8 (diff) | |
parent | 550dce01dd606c88a837138aa448ccd367fb0cbb (diff) | |
download | linux-17648b871d3cecf310f55ce8c6ce5821d135f6ec.tar.xz |
Merge branch 'test.d_iput' into work.misc
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 45 |
1 files changed, 10 insertions, 35 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 484a52db99ba..d5beef01cdfc 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -334,44 +334,21 @@ static inline void dentry_rcuwalk_invalidate(struct dentry *dentry) /* * Release the dentry's inode, using the filesystem - * d_iput() operation if defined. Dentry has no refcount - * and is unhashed. - */ -static void dentry_iput(struct dentry * dentry) - __releases(dentry->d_lock) - __releases(dentry->d_inode->i_lock) -{ - struct inode *inode = dentry->d_inode; - if (inode) { - __d_clear_type_and_inode(dentry); - hlist_del_init(&dentry->d_u.d_alias); - spin_unlock(&dentry->d_lock); - spin_unlock(&inode->i_lock); - if (!inode->i_nlink) - fsnotify_inoderemove(inode); - if (dentry->d_op && dentry->d_op->d_iput) - dentry->d_op->d_iput(dentry, inode); - else - iput(inode); - } else { - spin_unlock(&dentry->d_lock); - } -} - -/* - * Release the dentry's inode, using the filesystem - * d_iput() operation if defined. dentry remains in-use. + * d_iput() operation if defined. */ static void dentry_unlink_inode(struct dentry * dentry) __releases(dentry->d_lock) __releases(dentry->d_inode->i_lock) { struct inode *inode = dentry->d_inode; + bool hashed = !d_unhashed(dentry); - raw_write_seqcount_begin(&dentry->d_seq); + if (hashed) + raw_write_seqcount_begin(&dentry->d_seq); __d_clear_type_and_inode(dentry); hlist_del_init(&dentry->d_u.d_alias); - raw_write_seqcount_end(&dentry->d_seq); + if (hashed) + raw_write_seqcount_end(&dentry->d_seq); spin_unlock(&dentry->d_lock); spin_unlock(&inode->i_lock); if (!inode->i_nlink) @@ -572,12 +549,10 @@ static void __dentry_kill(struct dentry *dentry) dentry_unlist(dentry, parent); if (parent) spin_unlock(&parent->d_lock); - dentry_iput(dentry); - /* - * dentry_iput drops the locks, at which point nobody (except - * transient RCU lookups) can reach this dentry. - */ - BUG_ON(dentry->d_lockref.count > 0); + if (dentry->d_inode) + dentry_unlink_inode(dentry); + else + spin_unlock(&dentry->d_lock); this_cpu_dec(nr_dentry); if (dentry->d_op && dentry->d_op->d_release) dentry->d_op->d_release(dentry); |