Commit ff0c7d15f9787b7e8c601533c015295cc68329f8
1 parent
fa0d7e3de6
Exists in
master
and in
4 other branches
fs: avoid inode RCU freeing for pseudo fs
Pseudo filesystems that don't put inode on RCU list or reachable by rcu-walk dentries do not need to RCU free their inodes. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Showing 5 changed files with 22 additions and 9 deletions Side-by-side Diff
fs/inode.c
... | ... | @@ -257,6 +257,12 @@ |
257 | 257 | return inode; |
258 | 258 | } |
259 | 259 | |
260 | +void free_inode_nonrcu(struct inode *inode) | |
261 | +{ | |
262 | + kmem_cache_free(inode_cachep, inode); | |
263 | +} | |
264 | +EXPORT_SYMBOL(free_inode_nonrcu); | |
265 | + | |
260 | 266 | void __destroy_inode(struct inode *inode) |
261 | 267 | { |
262 | 268 | BUG_ON(inode_has_buffers(inode)); |
fs/pipe.c
... | ... | @@ -1253,6 +1253,10 @@ |
1253 | 1253 | return ret; |
1254 | 1254 | } |
1255 | 1255 | |
1256 | +static const struct super_operations pipefs_ops = { | |
1257 | + .destroy_inode = free_inode_nonrcu, | |
1258 | +}; | |
1259 | + | |
1256 | 1260 | /* |
1257 | 1261 | * pipefs should _never_ be mounted by userland - too much of security hassle, |
1258 | 1262 | * no real gain from having the whole whorehouse mounted. So we don't need |
... | ... | @@ -1262,7 +1266,7 @@ |
1262 | 1266 | static struct dentry *pipefs_mount(struct file_system_type *fs_type, |
1263 | 1267 | int flags, const char *dev_name, void *data) |
1264 | 1268 | { |
1265 | - return mount_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC); | |
1269 | + return mount_pseudo(fs_type, "pipe:", &pipefs_ops, PIPEFS_MAGIC); | |
1266 | 1270 | } |
1267 | 1271 | |
1268 | 1272 | static struct file_system_type pipe_fs_type = { |
include/linux/fs.h
... | ... | @@ -2233,6 +2233,7 @@ |
2233 | 2233 | extern void end_writeback(struct inode *); |
2234 | 2234 | extern void __destroy_inode(struct inode *); |
2235 | 2235 | extern struct inode *new_inode(struct super_block *); |
2236 | +extern void free_inode_nonrcu(struct inode *inode); | |
2236 | 2237 | extern int should_remove_suid(struct dentry *); |
2237 | 2238 | extern int file_remove_suid(struct file *); |
2238 | 2239 |
include/linux/net.h
net/socket.c
... | ... | @@ -262,20 +262,21 @@ |
262 | 262 | } |
263 | 263 | |
264 | 264 | |
265 | -static void sock_free_rcu(struct rcu_head *head) | |
265 | + | |
266 | +static void wq_free_rcu(struct rcu_head *head) | |
266 | 267 | { |
267 | - struct inode *inode = container_of(head, struct inode, i_rcu); | |
268 | - struct socket_alloc *ei = container_of(inode, struct socket_alloc, | |
269 | - vfs_inode); | |
268 | + struct socket_wq *wq = container_of(head, struct socket_wq, rcu); | |
270 | 269 | |
271 | - kfree(ei->socket.wq); | |
272 | - INIT_LIST_HEAD(&inode->i_dentry); | |
273 | - kmem_cache_free(sock_inode_cachep, ei); | |
270 | + kfree(wq); | |
274 | 271 | } |
275 | 272 | |
276 | 273 | static void sock_destroy_inode(struct inode *inode) |
277 | 274 | { |
278 | - call_rcu(&inode->i_rcu, sock_free_rcu); | |
275 | + struct socket_alloc *ei; | |
276 | + | |
277 | + ei = container_of(inode, struct socket_alloc, vfs_inode); | |
278 | + call_rcu(&ei->socket.wq->rcu, wq_free_rcu); | |
279 | + kmem_cache_free(sock_inode_cachep, ei); | |
279 | 280 | } |
280 | 281 | |
281 | 282 | static void init_once(void *foo) |