aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-07 14:17:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-07 14:17:26 -0400
commit78438ce18f26dbcaa8993bb45d20ffb0cec3bc3e (patch)
tree2f6fe2eb05296a410a44ee7d602cafe2d202467b /fs/dcache.c
parent168e153d5ebbdd6a3fa85db1cc4879ed4b7030e0 (diff)
parentce285c267a003acbf607f3540ff71287f82e5282 (diff)
Merge branch 'stable-fodder' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs stable fodder fixes from Al Viro: - acct_on() fix for deadlock caught by overlayfs folks - autofs RCU use-after-free SNAFU (->d_manage() can be called locklessly, so we need to RCU-delay freeing the objects it looks at) - (hopefully) the end of "do we need freeing this dentry RCU-delayed" whack-a-mole. * 'stable-fodder' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: autofs: fix use-after-free in lockless ->d_manage() dcache: sort the freeing-without-RCU-delay mess for good. acct_on(): don't mess with freeze protection
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index aac41adf4743..c663c602f9ef 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -344,7 +344,7 @@ static void dentry_free(struct dentry *dentry)
344 } 344 }
345 } 345 }
346 /* if dentry was never visible to RCU, immediate free is OK */ 346 /* if dentry was never visible to RCU, immediate free is OK */
347 if (!(dentry->d_flags & DCACHE_RCUACCESS)) 347 if (dentry->d_flags & DCACHE_NORCU)
348 __d_free(&dentry->d_u.d_rcu); 348 __d_free(&dentry->d_u.d_rcu);
349 else 349 else
350 call_rcu(&dentry->d_u.d_rcu, __d_free); 350 call_rcu(&dentry->d_u.d_rcu, __d_free);
@@ -1701,7 +1701,6 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
1701 struct dentry *dentry = __d_alloc(parent->d_sb, name); 1701 struct dentry *dentry = __d_alloc(parent->d_sb, name);
1702 if (!dentry) 1702 if (!dentry)
1703 return NULL; 1703 return NULL;
1704 dentry->d_flags |= DCACHE_RCUACCESS;
1705 spin_lock(&parent->d_lock); 1704 spin_lock(&parent->d_lock);
1706 /* 1705 /*
1707 * don't need child lock because it is not subject 1706 * don't need child lock because it is not subject
@@ -1726,7 +1725,7 @@ struct dentry *d_alloc_cursor(struct dentry * parent)
1726{ 1725{
1727 struct dentry *dentry = d_alloc_anon(parent->d_sb); 1726 struct dentry *dentry = d_alloc_anon(parent->d_sb);
1728 if (dentry) { 1727 if (dentry) {
1729 dentry->d_flags |= DCACHE_RCUACCESS | DCACHE_DENTRY_CURSOR; 1728 dentry->d_flags |= DCACHE_DENTRY_CURSOR;
1730 dentry->d_parent = dget(parent); 1729 dentry->d_parent = dget(parent);
1731 } 1730 }
1732 return dentry; 1731 return dentry;
@@ -1739,10 +1738,17 @@ struct dentry *d_alloc_cursor(struct dentry * parent)
1739 * 1738 *
1740 * For a filesystem that just pins its dentries in memory and never 1739 * For a filesystem that just pins its dentries in memory and never
1741 * performs lookups at all, return an unhashed IS_ROOT dentry. 1740 * performs lookups at all, return an unhashed IS_ROOT dentry.
1741 * This is used for pipes, sockets et.al. - the stuff that should
1742 * never be anyone's children or parents. Unlike all other
1743 * dentries, these will not have RCU delay between dropping the
1744 * last reference and freeing them.
1742 */ 1745 */
1743struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name) 1746struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
1744{ 1747{
1745 return __d_alloc(sb, name); 1748 struct dentry *dentry = __d_alloc(sb, name);
1749 if (likely(dentry))
1750 dentry->d_flags |= DCACHE_NORCU;
1751 return dentry;
1746} 1752}
1747EXPORT_SYMBOL(d_alloc_pseudo); 1753EXPORT_SYMBOL(d_alloc_pseudo);
1748 1754
@@ -1911,12 +1917,10 @@ struct dentry *d_make_root(struct inode *root_inode)
1911 1917
1912 if (root_inode) { 1918 if (root_inode) {
1913 res = d_alloc_anon(root_inode->i_sb); 1919 res = d_alloc_anon(root_inode->i_sb);
1914 if (res) { 1920 if (res)
1915 res->d_flags |= DCACHE_RCUACCESS;
1916 d_instantiate(res, root_inode); 1921 d_instantiate(res, root_inode);
1917 } else { 1922 else
1918 iput(root_inode); 1923 iput(root_inode);
1919 }
1920 } 1924 }
1921 return res; 1925 return res;
1922} 1926}
@@ -2781,9 +2785,7 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
2781 copy_name(dentry, target); 2785 copy_name(dentry, target);
2782 target->d_hash.pprev = NULL; 2786 target->d_hash.pprev = NULL;
2783 dentry->d_parent->d_lockref.count++; 2787 dentry->d_parent->d_lockref.count++;
2784 if (dentry == old_parent) 2788 if (dentry != old_parent) /* wasn't IS_ROOT */
2785 dentry->d_flags |= DCACHE_RCUACCESS;
2786 else
2787 WARN_ON(!--old_parent->d_lockref.count); 2789 WARN_ON(!--old_parent->d_lockref.count);
2788 } else { 2790 } else {
2789 target->d_parent = old_parent; 2791 target->d_parent = old_parent;