diff options
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/net/socket.c b/net/socket.c index 769c386bd428..371eaf092a31 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -263,12 +263,19 @@ static struct inode *sock_alloc_inode(struct super_block *sb) | |||
| 263 | return &ei->vfs_inode; | 263 | return &ei->vfs_inode; |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | static void sock_destroy_inode(struct inode *inode) | 266 | static void sock_i_callback(struct rcu_head *head) |
| 267 | { | 267 | { |
| 268 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 269 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 268 | kmem_cache_free(sock_inode_cachep, | 270 | kmem_cache_free(sock_inode_cachep, |
| 269 | container_of(inode, struct socket_alloc, vfs_inode)); | 271 | container_of(inode, struct socket_alloc, vfs_inode)); |
| 270 | } | 272 | } |
| 271 | 273 | ||
| 274 | static void sock_destroy_inode(struct inode *inode) | ||
| 275 | { | ||
| 276 | call_rcu(&inode->i_rcu, sock_i_callback); | ||
| 277 | } | ||
| 278 | |||
| 272 | static void init_once(void *foo) | 279 | static void init_once(void *foo) |
| 273 | { | 280 | { |
| 274 | struct socket_alloc *ei = (struct socket_alloc *)foo; | 281 | struct socket_alloc *ei = (struct socket_alloc *)foo; |
| @@ -368,7 +375,9 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags) | |||
| 368 | &socket_file_ops); | 375 | &socket_file_ops); |
| 369 | if (unlikely(!file)) { | 376 | if (unlikely(!file)) { |
| 370 | /* drop dentry, keep inode */ | 377 | /* drop dentry, keep inode */ |
| 371 | atomic_inc(&path.dentry->d_inode->i_count); | 378 | spin_lock(&path.dentry->d_inode->i_lock); |
| 379 | path.dentry->d_inode->i_count++; | ||
| 380 | spin_unlock(&path.dentry->d_inode->i_lock); | ||
| 372 | path_put(&path); | 381 | path_put(&path); |
| 373 | put_unused_fd(fd); | 382 | put_unused_fd(fd); |
| 374 | return -ENFILE; | 383 | return -ENFILE; |
