| From: Al Viro <viro@zeniv.linux.org.uk> |
| Date: Mon, 6 Aug 2018 09:03:58 -0400 |
| Subject: root dentries need RCU-delayed freeing |
| |
| commit 90bad5e05bcdb0308cfa3d3a60f5c0b9c8e2efb3 upstream. |
| |
| Since mountpoint crossing can happen without leaving lazy mode, |
| root dentries do need the same protection against having their |
| memory freed without RCU delay as everything else in the tree. |
| |
| It's partially hidden by RCU delay between detaching from the |
| mount tree and dropping the vfsmount reference, but the starting |
| point of pathwalk can be on an already detached mount, in which |
| case umount-caused RCU delay has already passed by the time the |
| lazy pathwalk grabs rcu_read_lock(). If the starting point |
| happens to be at the root of that vfsmount *and* that vfsmount |
| covers the entire filesystem, we get trouble. |
| |
| Fixes: 48a066e72d97 ("RCU'd vsfmounts") |
| Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| fs/dcache.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/fs/dcache.c |
| +++ b/fs/dcache.c |
| @@ -1812,10 +1812,12 @@ struct dentry *d_make_root(struct inode |
| static const struct qstr name = QSTR_INIT("/", 1); |
| |
| res = __d_alloc(root_inode->i_sb, &name); |
| - if (res) |
| + if (res) { |
| + res->d_flags |= DCACHE_RCUACCESS; |
| d_instantiate(res, root_inode); |
| - else |
| + } else { |
| iput(root_inode); |
| + } |
| } |
| return res; |
| } |