aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/porting5
-rw-r--r--fs/autofs/autofs_i.h1
-rw-r--r--fs/autofs/inode.c2
-rw-r--r--fs/dcache.c24
-rw-r--r--fs/internal.h2
-rw-r--r--fs/nsfs.c3
-rw-r--r--include/linux/dcache.h2
-rw-r--r--include/linux/mount.h2
-rw-r--r--kernel/acct.c4
9 files changed, 26 insertions, 19 deletions
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index b8d3ddd8b8db..d392d4b0c393 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -663,3 +663,8 @@ in your dentry operations instead.
663 there, but that's it. Freeing memory in the callback is fine; doing 663 there, but that's it. Freeing memory in the callback is fine; doing
664 more than that is possible, but requires a lot of care and is best 664 more than that is possible, but requires a lot of care and is best
665 avoided. 665 avoided.
666--
667[mandatory]
668 DCACHE_RCUACCESS is gone; having an RCU delay on dentry freeing is the
669 default. DCACHE_NORCU opts out, and only d_alloc_pseudo() has any
670 business doing so.
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 70c132acdab1..e1091312abe1 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -71,6 +71,7 @@ struct autofs_info {
71 71
72 kuid_t uid; 72 kuid_t uid;
73 kgid_t gid; 73 kgid_t gid;
74 struct rcu_head rcu;
74}; 75};
75 76
76#define AUTOFS_INF_EXPIRING (1<<0) /* dentry in the process of expiring */ 77#define AUTOFS_INF_EXPIRING (1<<0) /* dentry in the process of expiring */
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index 80597b88718b..fb0225f21c12 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -36,7 +36,7 @@ void autofs_clean_ino(struct autofs_info *ino)
36 36
37void autofs_free_ino(struct autofs_info *ino) 37void autofs_free_ino(struct autofs_info *ino)
38{ 38{
39 kfree(ino); 39 kfree_rcu(ino, rcu);
40} 40}
41 41
42void autofs_kill_sb(struct super_block *sb) 42void autofs_kill_sb(struct super_block *sb)
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;
diff --git a/fs/internal.h b/fs/internal.h
index 6a8b71643af4..2e7362837a6e 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -89,9 +89,7 @@ extern int sb_prepare_remount_readonly(struct super_block *);
89 89
90extern void __init mnt_init(void); 90extern void __init mnt_init(void);
91 91
92extern int __mnt_want_write(struct vfsmount *);
93extern int __mnt_want_write_file(struct file *); 92extern int __mnt_want_write_file(struct file *);
94extern void __mnt_drop_write(struct vfsmount *);
95extern void __mnt_drop_write_file(struct file *); 93extern void __mnt_drop_write_file(struct file *);
96 94
97/* 95/*
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 60702d677bd4..30d150a4f0c6 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -85,13 +85,12 @@ slow:
85 inode->i_fop = &ns_file_operations; 85 inode->i_fop = &ns_file_operations;
86 inode->i_private = ns; 86 inode->i_private = ns;
87 87
88 dentry = d_alloc_pseudo(mnt->mnt_sb, &empty_name); 88 dentry = d_alloc_anon(mnt->mnt_sb);
89 if (!dentry) { 89 if (!dentry) {
90 iput(inode); 90 iput(inode);
91 return ERR_PTR(-ENOMEM); 91 return ERR_PTR(-ENOMEM);
92 } 92 }
93 d_instantiate(dentry, inode); 93 d_instantiate(dentry, inode);
94 dentry->d_flags |= DCACHE_RCUACCESS;
95 dentry->d_fsdata = (void *)ns->ops; 94 dentry->d_fsdata = (void *)ns->ops;
96 d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry); 95 d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry);
97 if (d) { 96 if (d) {
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 60996e64c579..6e1e8e6602c6 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -176,7 +176,6 @@ struct dentry_operations {
176 * typically using d_splice_alias. */ 176 * typically using d_splice_alias. */
177 177
178#define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */ 178#define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */
179#define DCACHE_RCUACCESS 0x00000080 /* Entry has ever been RCU-visible */
180 179
181#define DCACHE_CANT_MOUNT 0x00000100 180#define DCACHE_CANT_MOUNT 0x00000100
182#define DCACHE_GENOCIDE 0x00000200 181#define DCACHE_GENOCIDE 0x00000200
@@ -217,6 +216,7 @@ struct dentry_operations {
217 216
218#define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ 217#define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */
219#define DCACHE_DENTRY_CURSOR 0x20000000 218#define DCACHE_DENTRY_CURSOR 0x20000000
219#define DCACHE_NORCU 0x40000000 /* No RCU delay for freeing */
220 220
221extern seqlock_t rename_lock; 221extern seqlock_t rename_lock;
222 222
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 9197ddbf35fb..bf8cc4108b8f 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -87,6 +87,8 @@ extern bool mnt_may_suid(struct vfsmount *mnt);
87 87
88struct path; 88struct path;
89extern struct vfsmount *clone_private_mount(const struct path *path); 89extern struct vfsmount *clone_private_mount(const struct path *path);
90extern int __mnt_want_write(struct vfsmount *);
91extern void __mnt_drop_write(struct vfsmount *);
90 92
91struct file_system_type; 93struct file_system_type;
92extern struct vfsmount *fc_mount(struct fs_context *fc); 94extern struct vfsmount *fc_mount(struct fs_context *fc);
diff --git a/kernel/acct.c b/kernel/acct.c
index addf7732fb56..81f9831a7859 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -227,7 +227,7 @@ static int acct_on(struct filename *pathname)
227 filp_close(file, NULL); 227 filp_close(file, NULL);
228 return PTR_ERR(internal); 228 return PTR_ERR(internal);
229 } 229 }
230 err = mnt_want_write(internal); 230 err = __mnt_want_write(internal);
231 if (err) { 231 if (err) {
232 mntput(internal); 232 mntput(internal);
233 kfree(acct); 233 kfree(acct);
@@ -252,7 +252,7 @@ static int acct_on(struct filename *pathname)
252 old = xchg(&ns->bacct, &acct->pin); 252 old = xchg(&ns->bacct, &acct->pin);
253 mutex_unlock(&acct->lock); 253 mutex_unlock(&acct->lock);
254 pin_kill(old); 254 pin_kill(old);
255 mnt_drop_write(mnt); 255 __mnt_drop_write(mnt);
256 mntput(mnt); 256 mntput(mnt);
257 return 0; 257 return 0;
258} 258}