Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+23 -10
+6
fs/inode.c
··· 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));
+5 -1
fs/pipe.c
··· 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 ··· 1266 1262 static struct dentry *pipefs_mount(struct file_system_type *fs_type, 1267 1263 int flags, const char *dev_name, void *data) 1268 1264 { 1269 - return mount_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC); 1265 + return mount_pseudo(fs_type, "pipe:", &pipefs_ops, PIPEFS_MAGIC); 1270 1266 } 1271 1267 1272 1268 static struct file_system_type pipe_fs_type = {
+1
include/linux/fs.h
··· 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
+1
include/linux/net.h
··· 120 120 struct socket_wq { 121 121 wait_queue_head_t wait; 122 122 struct fasync_struct *fasync_list; 123 + struct rcu_head rcu; 123 124 } ____cacheline_aligned_in_smp; 124 125 125 126 /**
+10 -9
net/socket.c
··· 262 262 } 263 263 264 264 265 - static void sock_free_rcu(struct rcu_head *head) 266 - { 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); 270 265 271 - kfree(ei->socket.wq); 272 - INIT_LIST_HEAD(&inode->i_dentry); 273 - kmem_cache_free(sock_inode_cachep, ei); 266 + static void wq_free_rcu(struct rcu_head *head) 267 + { 268 + struct socket_wq *wq = container_of(head, struct socket_wq, rcu); 269 + 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)