diff options
| author | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:49:49 -0500 |
|---|---|---|
| committer | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:50:26 -0500 |
| commit | fa0d7e3de6d6fc5004ad9dea0dd6b286af8f03e9 (patch) | |
| tree | 203e0f73883e4c26b5597e36042386a1237dab35 | |
| parent | 77812a1ef139d84270d27faacc0630c887411013 (diff) | |
fs: icache RCU free inodes
RCU free the struct inode. This will allow:
- Subsequent store-free path walking patch. The inode must be consulted for
permissions when walking, so an RCU inode reference is a must.
- sb_inode_list_lock to be moved inside i_lock because sb list walkers who want
to take i_lock no longer need to take sb_inode_list_lock to walk the list in
the first place. This will simplify and optimize locking.
- Could remove some nested trylock loops in dcache code
- Could potentially simplify things a bit in VM land. Do not need to take the
page lock to follow page->mapping.
The downsides of this is the performance cost of using RCU. In a simple
creat/unlink microbenchmark, performance drops by about 10% due to inability to
reuse cache-hot slab objects. As iterations increase and RCU freeing starts
kicking over, this increases to about 20%.
In cases where inode lifetimes are longer (ie. many inodes may be allocated
during the average life span of a single inode), a lot of this cache reuse is
not applicable, so the regression caused by this patch is smaller.
The cache-hot regression could largely be avoided by using SLAB_DESTROY_BY_RCU,
however this adds some complexity to list walking and store-free path walking,
so I prefer to implement this at a later date, if it is shown to be a win in
real situations. I haven't found a regression in any non-micro benchmark so I
doubt it will be a problem.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
60 files changed, 490 insertions, 68 deletions
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 1eb76959d096..ccf0ce7866b9 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting | |||
| @@ -346,3 +346,17 @@ look at examples of other filesystems) for guidance. | |||
| 346 | for details of what locks to replace dcache_lock with in order to protect | 346 | for details of what locks to replace dcache_lock with in order to protect |
| 347 | particular things. Most of the time, a filesystem only needs ->d_lock, which | 347 | particular things. Most of the time, a filesystem only needs ->d_lock, which |
| 348 | protects *all* the dcache state of a given dentry. | 348 | protects *all* the dcache state of a given dentry. |
| 349 | |||
| 350 | -- | ||
| 351 | [mandatory] | ||
| 352 | |||
| 353 | Filesystems must RCU-free their inodes, if they can have been accessed | ||
| 354 | via rcu-walk path walk (basically, if the file can have had a path name in the | ||
| 355 | vfs namespace). | ||
| 356 | |||
| 357 | i_dentry and i_rcu share storage in a union, and the vfs expects | ||
| 358 | i_dentry to be reinitialized before it is freed, so an: | ||
| 359 | |||
| 360 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 361 | |||
| 362 | must be done in the RCU callback. | ||
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 03185de7cd4a..856e9c398068 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
| @@ -71,12 +71,18 @@ spufs_alloc_inode(struct super_block *sb) | |||
| 71 | return &ei->vfs_inode; | 71 | return &ei->vfs_inode; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static void | 74 | static void spufs_i_callback(struct rcu_head *head) |
| 75 | spufs_destroy_inode(struct inode *inode) | ||
| 76 | { | 75 | { |
| 76 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 77 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 77 | kmem_cache_free(spufs_inode_cache, SPUFS_I(inode)); | 78 | kmem_cache_free(spufs_inode_cache, SPUFS_I(inode)); |
| 78 | } | 79 | } |
| 79 | 80 | ||
| 81 | static void spufs_destroy_inode(struct inode *inode) | ||
| 82 | { | ||
| 83 | call_rcu(&inode->i_rcu, spufs_i_callback); | ||
| 84 | } | ||
| 85 | |||
| 80 | static void | 86 | static void |
| 81 | spufs_init_once(void *p) | 87 | spufs_init_once(void *p) |
| 82 | { | 88 | { |
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index 61685ccceda8..cc8d2840f9b6 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c | |||
| @@ -826,6 +826,13 @@ const struct address_space_operations pohmelfs_aops = { | |||
| 826 | .set_page_dirty = __set_page_dirty_nobuffers, | 826 | .set_page_dirty = __set_page_dirty_nobuffers, |
| 827 | }; | 827 | }; |
| 828 | 828 | ||
| 829 | static void pohmelfs_i_callback(struct rcu_head *head) | ||
| 830 | { | ||
| 831 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 832 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 833 | kmem_cache_free(pohmelfs_inode_cache, POHMELFS_I(inode)); | ||
| 834 | } | ||
| 835 | |||
| 829 | /* | 836 | /* |
| 830 | * ->detroy_inode() callback. Deletes inode from the caches | 837 | * ->detroy_inode() callback. Deletes inode from the caches |
| 831 | * and frees private data. | 838 | * and frees private data. |
| @@ -842,8 +849,8 @@ static void pohmelfs_destroy_inode(struct inode *inode) | |||
| 842 | 849 | ||
| 843 | dprintk("%s: pi: %p, inode: %p, ino: %llu.\n", | 850 | dprintk("%s: pi: %p, inode: %p, ino: %llu.\n", |
| 844 | __func__, pi, &pi->vfs_inode, pi->ino); | 851 | __func__, pi, &pi->vfs_inode, pi->ino); |
| 845 | kmem_cache_free(pohmelfs_inode_cache, pi); | ||
| 846 | atomic_long_dec(&psb->total_inodes); | 852 | atomic_long_dec(&psb->total_inodes); |
| 853 | call_rcu(&inode->i_rcu, pohmelfs_i_callback); | ||
| 847 | } | 854 | } |
| 848 | 855 | ||
| 849 | /* | 856 | /* |
diff --git a/drivers/staging/smbfs/inode.c b/drivers/staging/smbfs/inode.c index 540a984bb516..244319dc9702 100644 --- a/drivers/staging/smbfs/inode.c +++ b/drivers/staging/smbfs/inode.c | |||
| @@ -62,11 +62,18 @@ static struct inode *smb_alloc_inode(struct super_block *sb) | |||
| 62 | return &ei->vfs_inode; | 62 | return &ei->vfs_inode; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static void smb_destroy_inode(struct inode *inode) | 65 | static void smb_i_callback(struct rcu_head *head) |
| 66 | { | 66 | { |
| 67 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 68 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 67 | kmem_cache_free(smb_inode_cachep, SMB_I(inode)); | 69 | kmem_cache_free(smb_inode_cachep, SMB_I(inode)); |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 72 | static void smb_destroy_inode(struct inode *inode) | ||
| 73 | { | ||
| 74 | call_rcu(&inode->i_rcu, smb_i_callback); | ||
| 75 | } | ||
| 76 | |||
| 70 | static void init_once(void *foo) | 77 | static void init_once(void *foo) |
| 71 | { | 78 | { |
| 72 | struct smb_inode_info *ei = (struct smb_inode_info *) foo; | 79 | struct smb_inode_info *ei = (struct smb_inode_info *) foo; |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 1073bca8488c..f6f9081e6d2c 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -237,10 +237,17 @@ struct inode *v9fs_alloc_inode(struct super_block *sb) | |||
| 237 | * | 237 | * |
| 238 | */ | 238 | */ |
| 239 | 239 | ||
| 240 | void v9fs_destroy_inode(struct inode *inode) | 240 | static void v9fs_i_callback(struct rcu_head *head) |
| 241 | { | 241 | { |
| 242 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 243 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 242 | kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode)); | 244 | kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode)); |
| 243 | } | 245 | } |
| 246 | |||
| 247 | void v9fs_destroy_inode(struct inode *inode) | ||
| 248 | { | ||
| 249 | call_rcu(&inode->i_rcu, v9fs_i_callback); | ||
| 250 | } | ||
| 244 | #endif | 251 | #endif |
| 245 | 252 | ||
| 246 | /** | 253 | /** |
diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 959dbff2d42d..47dffc513a26 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c | |||
| @@ -240,11 +240,18 @@ static struct inode *adfs_alloc_inode(struct super_block *sb) | |||
| 240 | return &ei->vfs_inode; | 240 | return &ei->vfs_inode; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | static void adfs_destroy_inode(struct inode *inode) | 243 | static void adfs_i_callback(struct rcu_head *head) |
| 244 | { | 244 | { |
| 245 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 246 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 245 | kmem_cache_free(adfs_inode_cachep, ADFS_I(inode)); | 247 | kmem_cache_free(adfs_inode_cachep, ADFS_I(inode)); |
| 246 | } | 248 | } |
| 247 | 249 | ||
| 250 | static void adfs_destroy_inode(struct inode *inode) | ||
| 251 | { | ||
| 252 | call_rcu(&inode->i_rcu, adfs_i_callback); | ||
| 253 | } | ||
| 254 | |||
| 248 | static void init_once(void *foo) | 255 | static void init_once(void *foo) |
| 249 | { | 256 | { |
| 250 | struct adfs_inode_info *ei = (struct adfs_inode_info *) foo; | 257 | struct adfs_inode_info *ei = (struct adfs_inode_info *) foo; |
diff --git a/fs/affs/super.c b/fs/affs/super.c index 0cf7f4384cbd..4c18fcfb0a19 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
| @@ -95,11 +95,18 @@ static struct inode *affs_alloc_inode(struct super_block *sb) | |||
| 95 | return &i->vfs_inode; | 95 | return &i->vfs_inode; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static void affs_destroy_inode(struct inode *inode) | 98 | static void affs_i_callback(struct rcu_head *head) |
| 99 | { | 99 | { |
| 100 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 101 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 100 | kmem_cache_free(affs_inode_cachep, AFFS_I(inode)); | 102 | kmem_cache_free(affs_inode_cachep, AFFS_I(inode)); |
| 101 | } | 103 | } |
| 102 | 104 | ||
| 105 | static void affs_destroy_inode(struct inode *inode) | ||
| 106 | { | ||
| 107 | call_rcu(&inode->i_rcu, affs_i_callback); | ||
| 108 | } | ||
| 109 | |||
| 103 | static void init_once(void *foo) | 110 | static void init_once(void *foo) |
| 104 | { | 111 | { |
| 105 | struct affs_inode_info *ei = (struct affs_inode_info *) foo; | 112 | struct affs_inode_info *ei = (struct affs_inode_info *) foo; |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 27201cffece4..f901a9d7c111 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
| @@ -498,6 +498,14 @@ static struct inode *afs_alloc_inode(struct super_block *sb) | |||
| 498 | return &vnode->vfs_inode; | 498 | return &vnode->vfs_inode; |
| 499 | } | 499 | } |
| 500 | 500 | ||
| 501 | static void afs_i_callback(struct rcu_head *head) | ||
| 502 | { | ||
| 503 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 504 | struct afs_vnode *vnode = AFS_FS_I(inode); | ||
| 505 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 506 | kmem_cache_free(afs_inode_cachep, vnode); | ||
| 507 | } | ||
| 508 | |||
| 501 | /* | 509 | /* |
| 502 | * destroy an AFS inode struct | 510 | * destroy an AFS inode struct |
| 503 | */ | 511 | */ |
| @@ -511,7 +519,7 @@ static void afs_destroy_inode(struct inode *inode) | |||
| 511 | 519 | ||
| 512 | ASSERTCMP(vnode->server, ==, NULL); | 520 | ASSERTCMP(vnode->server, ==, NULL); |
| 513 | 521 | ||
| 514 | kmem_cache_free(afs_inode_cachep, vnode); | 522 | call_rcu(&inode->i_rcu, afs_i_callback); |
| 515 | atomic_dec(&afs_count_active_inodes); | 523 | atomic_dec(&afs_count_active_inodes); |
| 516 | } | 524 | } |
| 517 | 525 | ||
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index aa4e7c7ae3c6..de93581b79a2 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
| @@ -284,12 +284,18 @@ befs_alloc_inode(struct super_block *sb) | |||
| 284 | return &bi->vfs_inode; | 284 | return &bi->vfs_inode; |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | static void | 287 | static void befs_i_callback(struct rcu_head *head) |
| 288 | befs_destroy_inode(struct inode *inode) | ||
| 289 | { | 288 | { |
| 289 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 290 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 290 | kmem_cache_free(befs_inode_cachep, BEFS_I(inode)); | 291 | kmem_cache_free(befs_inode_cachep, BEFS_I(inode)); |
| 291 | } | 292 | } |
| 292 | 293 | ||
| 294 | static void befs_destroy_inode(struct inode *inode) | ||
| 295 | { | ||
| 296 | call_rcu(&inode->i_rcu, befs_i_callback); | ||
| 297 | } | ||
| 298 | |||
| 293 | static void init_once(void *foo) | 299 | static void init_once(void *foo) |
| 294 | { | 300 | { |
| 295 | struct befs_inode_info *bi = (struct befs_inode_info *) foo; | 301 | struct befs_inode_info *bi = (struct befs_inode_info *) foo; |
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 76db6d7d49bb..a8e37f81d097 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
| @@ -248,11 +248,18 @@ static struct inode *bfs_alloc_inode(struct super_block *sb) | |||
| 248 | return &bi->vfs_inode; | 248 | return &bi->vfs_inode; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | static void bfs_destroy_inode(struct inode *inode) | 251 | static void bfs_i_callback(struct rcu_head *head) |
| 252 | { | 252 | { |
| 253 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 254 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 253 | kmem_cache_free(bfs_inode_cachep, BFS_I(inode)); | 255 | kmem_cache_free(bfs_inode_cachep, BFS_I(inode)); |
| 254 | } | 256 | } |
| 255 | 257 | ||
| 258 | static void bfs_destroy_inode(struct inode *inode) | ||
| 259 | { | ||
| 260 | call_rcu(&inode->i_rcu, bfs_i_callback); | ||
| 261 | } | ||
| 262 | |||
| 256 | static void init_once(void *foo) | 263 | static void init_once(void *foo) |
| 257 | { | 264 | { |
| 258 | struct bfs_inode_info *bi = foo; | 265 | struct bfs_inode_info *bi = foo; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 4230252fd689..771f23527010 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -409,13 +409,20 @@ static struct inode *bdev_alloc_inode(struct super_block *sb) | |||
| 409 | return &ei->vfs_inode; | 409 | return &ei->vfs_inode; |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | static void bdev_destroy_inode(struct inode *inode) | 412 | static void bdev_i_callback(struct rcu_head *head) |
| 413 | { | 413 | { |
| 414 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 414 | struct bdev_inode *bdi = BDEV_I(inode); | 415 | struct bdev_inode *bdi = BDEV_I(inode); |
| 415 | 416 | ||
| 417 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 416 | kmem_cache_free(bdev_cachep, bdi); | 418 | kmem_cache_free(bdev_cachep, bdi); |
| 417 | } | 419 | } |
| 418 | 420 | ||
| 421 | static void bdev_destroy_inode(struct inode *inode) | ||
| 422 | { | ||
| 423 | call_rcu(&inode->i_rcu, bdev_i_callback); | ||
| 424 | } | ||
| 425 | |||
| 419 | static void init_once(void *foo) | 426 | static void init_once(void *foo) |
| 420 | { | 427 | { |
| 421 | struct bdev_inode *ei = (struct bdev_inode *) foo; | 428 | struct bdev_inode *ei = (struct bdev_inode *) foo; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7ce9f8932789..f9d2994a42a2 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -6495,6 +6495,13 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
| 6495 | return inode; | 6495 | return inode; |
| 6496 | } | 6496 | } |
| 6497 | 6497 | ||
| 6498 | static void btrfs_i_callback(struct rcu_head *head) | ||
| 6499 | { | ||
| 6500 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 6501 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 6502 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); | ||
| 6503 | } | ||
| 6504 | |||
| 6498 | void btrfs_destroy_inode(struct inode *inode) | 6505 | void btrfs_destroy_inode(struct inode *inode) |
| 6499 | { | 6506 | { |
| 6500 | struct btrfs_ordered_extent *ordered; | 6507 | struct btrfs_ordered_extent *ordered; |
| @@ -6564,7 +6571,7 @@ void btrfs_destroy_inode(struct inode *inode) | |||
| 6564 | inode_tree_del(inode); | 6571 | inode_tree_del(inode); |
| 6565 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); | 6572 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); |
| 6566 | free: | 6573 | free: |
| 6567 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); | 6574 | call_rcu(&inode->i_rcu, btrfs_i_callback); |
| 6568 | } | 6575 | } |
| 6569 | 6576 | ||
| 6570 | int btrfs_drop_inode(struct inode *inode) | 6577 | int btrfs_drop_inode(struct inode *inode) |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 2a48cafc174b..47f8c8baf3b5 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
| @@ -368,6 +368,15 @@ struct inode *ceph_alloc_inode(struct super_block *sb) | |||
| 368 | return &ci->vfs_inode; | 368 | return &ci->vfs_inode; |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | static void ceph_i_callback(struct rcu_head *head) | ||
| 372 | { | ||
| 373 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 374 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
| 375 | |||
| 376 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 377 | kmem_cache_free(ceph_inode_cachep, ci); | ||
| 378 | } | ||
| 379 | |||
| 371 | void ceph_destroy_inode(struct inode *inode) | 380 | void ceph_destroy_inode(struct inode *inode) |
| 372 | { | 381 | { |
| 373 | struct ceph_inode_info *ci = ceph_inode(inode); | 382 | struct ceph_inode_info *ci = ceph_inode(inode); |
| @@ -407,7 +416,7 @@ void ceph_destroy_inode(struct inode *inode) | |||
| 407 | if (ci->i_xattrs.prealloc_blob) | 416 | if (ci->i_xattrs.prealloc_blob) |
| 408 | ceph_buffer_put(ci->i_xattrs.prealloc_blob); | 417 | ceph_buffer_put(ci->i_xattrs.prealloc_blob); |
| 409 | 418 | ||
| 410 | kmem_cache_free(ceph_inode_cachep, ci); | 419 | call_rcu(&inode->i_rcu, ceph_i_callback); |
| 411 | } | 420 | } |
| 412 | 421 | ||
| 413 | 422 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3936aa7f2c22..223717dcc401 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -334,10 +334,17 @@ cifs_alloc_inode(struct super_block *sb) | |||
| 334 | return &cifs_inode->vfs_inode; | 334 | return &cifs_inode->vfs_inode; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static void cifs_i_callback(struct rcu_head *head) | ||
| 338 | { | ||
| 339 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 340 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 341 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | ||
| 342 | } | ||
| 343 | |||
| 337 | static void | 344 | static void |
| 338 | cifs_destroy_inode(struct inode *inode) | 345 | cifs_destroy_inode(struct inode *inode) |
| 339 | { | 346 | { |
| 340 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | 347 | call_rcu(&inode->i_rcu, cifs_i_callback); |
| 341 | } | 348 | } |
| 342 | 349 | ||
| 343 | static void | 350 | static void |
diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 5ea57c8c7f97..50dc7d189f56 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c | |||
| @@ -56,11 +56,18 @@ static struct inode *coda_alloc_inode(struct super_block *sb) | |||
| 56 | return &ei->vfs_inode; | 56 | return &ei->vfs_inode; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static void coda_destroy_inode(struct inode *inode) | 59 | static void coda_i_callback(struct rcu_head *head) |
| 60 | { | 60 | { |
| 61 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 62 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 61 | kmem_cache_free(coda_inode_cachep, ITOC(inode)); | 63 | kmem_cache_free(coda_inode_cachep, ITOC(inode)); |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 66 | static void coda_destroy_inode(struct inode *inode) | ||
| 67 | { | ||
| 68 | call_rcu(&inode->i_rcu, coda_i_callback); | ||
| 69 | } | ||
| 70 | |||
| 64 | static void init_once(void *foo) | 71 | static void init_once(void *foo) |
| 65 | { | 72 | { |
| 66 | struct coda_inode_info *ei = (struct coda_inode_info *) foo; | 73 | struct coda_inode_info *ei = (struct coda_inode_info *) foo; |
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 2720178b7718..3042fe123a34 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
| @@ -62,6 +62,16 @@ out: | |||
| 62 | return inode; | 62 | return inode; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static void ecryptfs_i_callback(struct rcu_head *head) | ||
| 66 | { | ||
| 67 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 68 | struct ecryptfs_inode_info *inode_info; | ||
| 69 | inode_info = ecryptfs_inode_to_private(inode); | ||
| 70 | |||
| 71 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 72 | kmem_cache_free(ecryptfs_inode_info_cache, inode_info); | ||
| 73 | } | ||
| 74 | |||
| 65 | /** | 75 | /** |
| 66 | * ecryptfs_destroy_inode | 76 | * ecryptfs_destroy_inode |
| 67 | * @inode: The ecryptfs inode | 77 | * @inode: The ecryptfs inode |
| @@ -88,7 +98,7 @@ static void ecryptfs_destroy_inode(struct inode *inode) | |||
| 88 | } | 98 | } |
| 89 | } | 99 | } |
| 90 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); | 100 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); |
| 91 | kmem_cache_free(ecryptfs_inode_info_cache, inode_info); | 101 | call_rcu(&inode->i_rcu, ecryptfs_i_callback); |
| 92 | } | 102 | } |
| 93 | 103 | ||
| 94 | /** | 104 | /** |
diff --git a/fs/efs/super.c b/fs/efs/super.c index 5073a07652cc..0f31acb0131c 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c | |||
| @@ -65,11 +65,18 @@ static struct inode *efs_alloc_inode(struct super_block *sb) | |||
| 65 | return &ei->vfs_inode; | 65 | return &ei->vfs_inode; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static void efs_destroy_inode(struct inode *inode) | 68 | static void efs_i_callback(struct rcu_head *head) |
| 69 | { | 69 | { |
| 70 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 71 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 70 | kmem_cache_free(efs_inode_cachep, INODE_INFO(inode)); | 72 | kmem_cache_free(efs_inode_cachep, INODE_INFO(inode)); |
| 71 | } | 73 | } |
| 72 | 74 | ||
| 75 | static void efs_destroy_inode(struct inode *inode) | ||
| 76 | { | ||
| 77 | call_rcu(&inode->i_rcu, efs_i_callback); | ||
| 78 | } | ||
| 79 | |||
| 73 | static void init_once(void *foo) | 80 | static void init_once(void *foo) |
| 74 | { | 81 | { |
| 75 | struct efs_inode_info *ei = (struct efs_inode_info *) foo; | 82 | struct efs_inode_info *ei = (struct efs_inode_info *) foo; |
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 79c3ae6e0456..8c6c4669b381 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
| @@ -150,12 +150,19 @@ static struct inode *exofs_alloc_inode(struct super_block *sb) | |||
| 150 | return &oi->vfs_inode; | 150 | return &oi->vfs_inode; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | static void exofs_i_callback(struct rcu_head *head) | ||
| 154 | { | ||
| 155 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 156 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 157 | kmem_cache_free(exofs_inode_cachep, exofs_i(inode)); | ||
| 158 | } | ||
| 159 | |||
| 153 | /* | 160 | /* |
| 154 | * Remove an inode from the cache | 161 | * Remove an inode from the cache |
| 155 | */ | 162 | */ |
| 156 | static void exofs_destroy_inode(struct inode *inode) | 163 | static void exofs_destroy_inode(struct inode *inode) |
| 157 | { | 164 | { |
| 158 | kmem_cache_free(exofs_inode_cachep, exofs_i(inode)); | 165 | call_rcu(&inode->i_rcu, exofs_i_callback); |
| 159 | } | 166 | } |
| 160 | 167 | ||
| 161 | /* | 168 | /* |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index d89e0b6a2d78..e0c6380ff992 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
| @@ -161,11 +161,18 @@ static struct inode *ext2_alloc_inode(struct super_block *sb) | |||
| 161 | return &ei->vfs_inode; | 161 | return &ei->vfs_inode; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static void ext2_destroy_inode(struct inode *inode) | 164 | static void ext2_i_callback(struct rcu_head *head) |
| 165 | { | 165 | { |
| 166 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 167 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 166 | kmem_cache_free(ext2_inode_cachep, EXT2_I(inode)); | 168 | kmem_cache_free(ext2_inode_cachep, EXT2_I(inode)); |
| 167 | } | 169 | } |
| 168 | 170 | ||
| 171 | static void ext2_destroy_inode(struct inode *inode) | ||
| 172 | { | ||
| 173 | call_rcu(&inode->i_rcu, ext2_i_callback); | ||
| 174 | } | ||
| 175 | |||
| 169 | static void init_once(void *foo) | 176 | static void init_once(void *foo) |
| 170 | { | 177 | { |
| 171 | struct ext2_inode_info *ei = (struct ext2_inode_info *) foo; | 178 | struct ext2_inode_info *ei = (struct ext2_inode_info *) foo; |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index acf8695fa8f0..77ce1616f725 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -479,6 +479,13 @@ static struct inode *ext3_alloc_inode(struct super_block *sb) | |||
| 479 | return &ei->vfs_inode; | 479 | return &ei->vfs_inode; |
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | static void ext3_i_callback(struct rcu_head *head) | ||
| 483 | { | ||
| 484 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 485 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 486 | kmem_cache_free(ext3_inode_cachep, EXT3_I(inode)); | ||
| 487 | } | ||
| 488 | |||
| 482 | static void ext3_destroy_inode(struct inode *inode) | 489 | static void ext3_destroy_inode(struct inode *inode) |
| 483 | { | 490 | { |
| 484 | if (!list_empty(&(EXT3_I(inode)->i_orphan))) { | 491 | if (!list_empty(&(EXT3_I(inode)->i_orphan))) { |
| @@ -489,7 +496,7 @@ static void ext3_destroy_inode(struct inode *inode) | |||
| 489 | false); | 496 | false); |
| 490 | dump_stack(); | 497 | dump_stack(); |
| 491 | } | 498 | } |
| 492 | kmem_cache_free(ext3_inode_cachep, EXT3_I(inode)); | 499 | call_rcu(&inode->i_rcu, ext3_i_callback); |
| 493 | } | 500 | } |
| 494 | 501 | ||
| 495 | static void init_once(void *foo) | 502 | static void init_once(void *foo) |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index fb15c9c0be74..cd37f9d5e447 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -841,6 +841,13 @@ static int ext4_drop_inode(struct inode *inode) | |||
| 841 | return drop; | 841 | return drop; |
| 842 | } | 842 | } |
| 843 | 843 | ||
| 844 | static void ext4_i_callback(struct rcu_head *head) | ||
| 845 | { | ||
| 846 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 847 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 848 | kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); | ||
| 849 | } | ||
| 850 | |||
| 844 | static void ext4_destroy_inode(struct inode *inode) | 851 | static void ext4_destroy_inode(struct inode *inode) |
| 845 | { | 852 | { |
| 846 | ext4_ioend_wait(inode); | 853 | ext4_ioend_wait(inode); |
| @@ -853,7 +860,7 @@ static void ext4_destroy_inode(struct inode *inode) | |||
| 853 | true); | 860 | true); |
| 854 | dump_stack(); | 861 | dump_stack(); |
| 855 | } | 862 | } |
| 856 | kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); | 863 | call_rcu(&inode->i_rcu, ext4_i_callback); |
| 857 | } | 864 | } |
| 858 | 865 | ||
| 859 | static void init_once(void *foo) | 866 | static void init_once(void *foo) |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index ad6998a92c30..8cccfebee180 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -514,11 +514,18 @@ static struct inode *fat_alloc_inode(struct super_block *sb) | |||
| 514 | return &ei->vfs_inode; | 514 | return &ei->vfs_inode; |
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | static void fat_destroy_inode(struct inode *inode) | 517 | static void fat_i_callback(struct rcu_head *head) |
| 518 | { | 518 | { |
| 519 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 520 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 519 | kmem_cache_free(fat_inode_cachep, MSDOS_I(inode)); | 521 | kmem_cache_free(fat_inode_cachep, MSDOS_I(inode)); |
| 520 | } | 522 | } |
| 521 | 523 | ||
| 524 | static void fat_destroy_inode(struct inode *inode) | ||
| 525 | { | ||
| 526 | call_rcu(&inode->i_rcu, fat_i_callback); | ||
| 527 | } | ||
| 528 | |||
| 522 | static void init_once(void *foo) | 529 | static void init_once(void *foo) |
| 523 | { | 530 | { |
| 524 | struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; | 531 | struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; |
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 8c04eac5079d..2ba6719ac612 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c | |||
| @@ -337,6 +337,13 @@ vxfs_iget(struct super_block *sbp, ino_t ino) | |||
| 337 | return ip; | 337 | return ip; |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | static void vxfs_i_callback(struct rcu_head *head) | ||
| 341 | { | ||
| 342 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 343 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 344 | kmem_cache_free(vxfs_inode_cachep, inode->i_private); | ||
| 345 | } | ||
| 346 | |||
| 340 | /** | 347 | /** |
| 341 | * vxfs_evict_inode - remove inode from main memory | 348 | * vxfs_evict_inode - remove inode from main memory |
| 342 | * @ip: inode to discard. | 349 | * @ip: inode to discard. |
| @@ -350,5 +357,5 @@ vxfs_evict_inode(struct inode *ip) | |||
| 350 | { | 357 | { |
| 351 | truncate_inode_pages(&ip->i_data, 0); | 358 | truncate_inode_pages(&ip->i_data, 0); |
| 352 | end_writeback(ip); | 359 | end_writeback(ip); |
| 353 | kmem_cache_free(vxfs_inode_cachep, ip->i_private); | 360 | call_rcu(&ip->i_rcu, vxfs_i_callback); |
| 354 | } | 361 | } |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index cfce3ad86a92..44e0a6c57e87 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -99,6 +99,13 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
| 99 | return inode; | 99 | return inode; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static void fuse_i_callback(struct rcu_head *head) | ||
| 103 | { | ||
| 104 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 105 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 106 | kmem_cache_free(fuse_inode_cachep, inode); | ||
| 107 | } | ||
| 108 | |||
| 102 | static void fuse_destroy_inode(struct inode *inode) | 109 | static void fuse_destroy_inode(struct inode *inode) |
| 103 | { | 110 | { |
| 104 | struct fuse_inode *fi = get_fuse_inode(inode); | 111 | struct fuse_inode *fi = get_fuse_inode(inode); |
| @@ -106,7 +113,7 @@ static void fuse_destroy_inode(struct inode *inode) | |||
| 106 | BUG_ON(!list_empty(&fi->queued_writes)); | 113 | BUG_ON(!list_empty(&fi->queued_writes)); |
| 107 | if (fi->forget_req) | 114 | if (fi->forget_req) |
| 108 | fuse_request_free(fi->forget_req); | 115 | fuse_request_free(fi->forget_req); |
| 109 | kmem_cache_free(fuse_inode_cachep, inode); | 116 | call_rcu(&inode->i_rcu, fuse_i_callback); |
| 110 | } | 117 | } |
| 111 | 118 | ||
| 112 | void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | 119 | void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 2b2c4997430b..16c2ecac7eb7 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
| @@ -1405,11 +1405,18 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb) | |||
| 1405 | return &ip->i_inode; | 1405 | return &ip->i_inode; |
| 1406 | } | 1406 | } |
| 1407 | 1407 | ||
| 1408 | static void gfs2_destroy_inode(struct inode *inode) | 1408 | static void gfs2_i_callback(struct rcu_head *head) |
| 1409 | { | 1409 | { |
| 1410 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 1411 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 1410 | kmem_cache_free(gfs2_inode_cachep, inode); | 1412 | kmem_cache_free(gfs2_inode_cachep, inode); |
| 1411 | } | 1413 | } |
| 1412 | 1414 | ||
| 1415 | static void gfs2_destroy_inode(struct inode *inode) | ||
| 1416 | { | ||
| 1417 | call_rcu(&inode->i_rcu, gfs2_i_callback); | ||
| 1418 | } | ||
| 1419 | |||
| 1413 | const struct super_operations gfs2_super_ops = { | 1420 | const struct super_operations gfs2_super_ops = { |
| 1414 | .alloc_inode = gfs2_alloc_inode, | 1421 | .alloc_inode = gfs2_alloc_inode, |
| 1415 | .destroy_inode = gfs2_destroy_inode, | 1422 | .destroy_inode = gfs2_destroy_inode, |
diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 4824c27cebb8..ef4ee5716abe 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c | |||
| @@ -167,11 +167,18 @@ static struct inode *hfs_alloc_inode(struct super_block *sb) | |||
| 167 | return i ? &i->vfs_inode : NULL; | 167 | return i ? &i->vfs_inode : NULL; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static void hfs_destroy_inode(struct inode *inode) | 170 | static void hfs_i_callback(struct rcu_head *head) |
| 171 | { | 171 | { |
| 172 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 173 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 172 | kmem_cache_free(hfs_inode_cachep, HFS_I(inode)); | 174 | kmem_cache_free(hfs_inode_cachep, HFS_I(inode)); |
| 173 | } | 175 | } |
| 174 | 176 | ||
| 177 | static void hfs_destroy_inode(struct inode *inode) | ||
| 178 | { | ||
| 179 | call_rcu(&inode->i_rcu, hfs_i_callback); | ||
| 180 | } | ||
| 181 | |||
| 175 | static const struct super_operations hfs_super_operations = { | 182 | static const struct super_operations hfs_super_operations = { |
| 176 | .alloc_inode = hfs_alloc_inode, | 183 | .alloc_inode = hfs_alloc_inode, |
| 177 | .destroy_inode = hfs_destroy_inode, | 184 | .destroy_inode = hfs_destroy_inode, |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 52cc746d3ba3..182e83a9079e 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
| @@ -488,11 +488,19 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb) | |||
| 488 | return i ? &i->vfs_inode : NULL; | 488 | return i ? &i->vfs_inode : NULL; |
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | static void hfsplus_destroy_inode(struct inode *inode) | 491 | static void hfsplus_i_callback(struct rcu_head *head) |
| 492 | { | 492 | { |
| 493 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 494 | |||
| 495 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 493 | kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode)); | 496 | kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode)); |
| 494 | } | 497 | } |
| 495 | 498 | ||
| 499 | static void hfsplus_destroy_inode(struct inode *inode) | ||
| 500 | { | ||
| 501 | call_rcu(&inode->i_rcu, hfsplus_i_callback); | ||
| 502 | } | ||
| 503 | |||
| 496 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) | 504 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) |
| 497 | 505 | ||
| 498 | static struct dentry *hfsplus_mount(struct file_system_type *fs_type, | 506 | static struct dentry *hfsplus_mount(struct file_system_type *fs_type, |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 39dc505ed273..861113fcfc88 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
| @@ -247,11 +247,18 @@ static void hostfs_evict_inode(struct inode *inode) | |||
| 247 | } | 247 | } |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | static void hostfs_destroy_inode(struct inode *inode) | 250 | static void hostfs_i_callback(struct rcu_head *head) |
| 251 | { | 251 | { |
| 252 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 253 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 252 | kfree(HOSTFS_I(inode)); | 254 | kfree(HOSTFS_I(inode)); |
| 253 | } | 255 | } |
| 254 | 256 | ||
| 257 | static void hostfs_destroy_inode(struct inode *inode) | ||
| 258 | { | ||
| 259 | call_rcu(&inode->i_rcu, hostfs_i_callback); | ||
| 260 | } | ||
| 261 | |||
| 255 | static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | 262 | static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs) |
| 256 | { | 263 | { |
| 257 | const char *root_path = vfs->mnt_sb->s_fs_info; | 264 | const char *root_path = vfs->mnt_sb->s_fs_info; |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 6c5f01597c3a..49935ba78db8 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
| @@ -177,11 +177,18 @@ static struct inode *hpfs_alloc_inode(struct super_block *sb) | |||
| 177 | return &ei->vfs_inode; | 177 | return &ei->vfs_inode; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | static void hpfs_destroy_inode(struct inode *inode) | 180 | static void hpfs_i_callback(struct rcu_head *head) |
| 181 | { | 181 | { |
| 182 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 183 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 182 | kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode)); | 184 | kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode)); |
| 183 | } | 185 | } |
| 184 | 186 | ||
| 187 | static void hpfs_destroy_inode(struct inode *inode) | ||
| 188 | { | ||
| 189 | call_rcu(&inode->i_rcu, hpfs_i_callback); | ||
| 190 | } | ||
| 191 | |||
| 185 | static void init_once(void *foo) | 192 | static void init_once(void *foo) |
| 186 | { | 193 | { |
| 187 | struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo; | 194 | struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo; |
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index f702b5f713fc..87ed48e0343d 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c | |||
| @@ -632,11 +632,18 @@ void hppfs_evict_inode(struct inode *ino) | |||
| 632 | mntput(ino->i_sb->s_fs_info); | 632 | mntput(ino->i_sb->s_fs_info); |
| 633 | } | 633 | } |
| 634 | 634 | ||
| 635 | static void hppfs_destroy_inode(struct inode *inode) | 635 | static void hppfs_i_callback(struct rcu_head *head) |
| 636 | { | 636 | { |
| 637 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 638 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 637 | kfree(HPPFS_I(inode)); | 639 | kfree(HPPFS_I(inode)); |
| 638 | } | 640 | } |
| 639 | 641 | ||
| 642 | static void hppfs_destroy_inode(struct inode *inode) | ||
| 643 | { | ||
| 644 | call_rcu(&inode->i_rcu, hppfs_i_callback); | ||
| 645 | } | ||
| 646 | |||
| 640 | static const struct super_operations hppfs_sbops = { | 647 | static const struct super_operations hppfs_sbops = { |
| 641 | .alloc_inode = hppfs_alloc_inode, | 648 | .alloc_inode = hppfs_alloc_inode, |
| 642 | .destroy_inode = hppfs_destroy_inode, | 649 | .destroy_inode = hppfs_destroy_inode, |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index a5fe68189eed..9885082b470f 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
| @@ -663,11 +663,18 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) | |||
| 663 | return &p->vfs_inode; | 663 | return &p->vfs_inode; |
| 664 | } | 664 | } |
| 665 | 665 | ||
| 666 | static void hugetlbfs_i_callback(struct rcu_head *head) | ||
| 667 | { | ||
| 668 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 669 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 670 | kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode)); | ||
| 671 | } | ||
| 672 | |||
| 666 | static void hugetlbfs_destroy_inode(struct inode *inode) | 673 | static void hugetlbfs_destroy_inode(struct inode *inode) |
| 667 | { | 674 | { |
| 668 | hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb)); | 675 | hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb)); |
| 669 | mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy); | 676 | mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy); |
| 670 | kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode)); | 677 | call_rcu(&inode->i_rcu, hugetlbfs_i_callback); |
| 671 | } | 678 | } |
| 672 | 679 | ||
| 673 | static const struct address_space_operations hugetlbfs_aops = { | 680 | static const struct address_space_operations hugetlbfs_aops = { |
diff --git a/fs/inode.c b/fs/inode.c index 5a0a898f55d1..6751dfe8cc06 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -272,6 +272,13 @@ void __destroy_inode(struct inode *inode) | |||
| 272 | } | 272 | } |
| 273 | EXPORT_SYMBOL(__destroy_inode); | 273 | EXPORT_SYMBOL(__destroy_inode); |
| 274 | 274 | ||
| 275 | static void i_callback(struct rcu_head *head) | ||
| 276 | { | ||
| 277 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 278 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 279 | kmem_cache_free(inode_cachep, inode); | ||
| 280 | } | ||
| 281 | |||
| 275 | static void destroy_inode(struct inode *inode) | 282 | static void destroy_inode(struct inode *inode) |
| 276 | { | 283 | { |
| 277 | BUG_ON(!list_empty(&inode->i_lru)); | 284 | BUG_ON(!list_empty(&inode->i_lru)); |
| @@ -279,7 +286,7 @@ static void destroy_inode(struct inode *inode) | |||
| 279 | if (inode->i_sb->s_op->destroy_inode) | 286 | if (inode->i_sb->s_op->destroy_inode) |
| 280 | inode->i_sb->s_op->destroy_inode(inode); | 287 | inode->i_sb->s_op->destroy_inode(inode); |
| 281 | else | 288 | else |
| 282 | kmem_cache_free(inode_cachep, (inode)); | 289 | call_rcu(&inode->i_rcu, i_callback); |
| 283 | } | 290 | } |
| 284 | 291 | ||
| 285 | /* | 292 | /* |
| @@ -432,6 +439,7 @@ void end_writeback(struct inode *inode) | |||
| 432 | BUG_ON(!(inode->i_state & I_FREEING)); | 439 | BUG_ON(!(inode->i_state & I_FREEING)); |
| 433 | BUG_ON(inode->i_state & I_CLEAR); | 440 | BUG_ON(inode->i_state & I_CLEAR); |
| 434 | inode_sync_wait(inode); | 441 | inode_sync_wait(inode); |
| 442 | /* don't need i_lock here, no concurrent mods to i_state */ | ||
| 435 | inode->i_state = I_FREEING | I_CLEAR; | 443 | inode->i_state = I_FREEING | I_CLEAR; |
| 436 | } | 444 | } |
| 437 | EXPORT_SYMBOL(end_writeback); | 445 | EXPORT_SYMBOL(end_writeback); |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index d204ee4235fd..d8f3a652243d 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
| @@ -81,11 +81,18 @@ static struct inode *isofs_alloc_inode(struct super_block *sb) | |||
| 81 | return &ei->vfs_inode; | 81 | return &ei->vfs_inode; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static void isofs_destroy_inode(struct inode *inode) | 84 | static void isofs_i_callback(struct rcu_head *head) |
| 85 | { | 85 | { |
| 86 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 87 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 86 | kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode)); | 88 | kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode)); |
| 87 | } | 89 | } |
| 88 | 90 | ||
| 91 | static void isofs_destroy_inode(struct inode *inode) | ||
| 92 | { | ||
| 93 | call_rcu(&inode->i_rcu, isofs_i_callback); | ||
| 94 | } | ||
| 95 | |||
| 89 | static void init_once(void *foo) | 96 | static void init_once(void *foo) |
| 90 | { | 97 | { |
| 91 | struct iso_inode_info *ei = foo; | 98 | struct iso_inode_info *ei = foo; |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index c86041b866a4..853b8e300084 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
| @@ -40,11 +40,18 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb) | |||
| 40 | return &f->vfs_inode; | 40 | return &f->vfs_inode; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static void jffs2_destroy_inode(struct inode *inode) | 43 | static void jffs2_i_callback(struct rcu_head *head) |
| 44 | { | 44 | { |
| 45 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 46 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 45 | kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); | 47 | kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); |
| 46 | } | 48 | } |
| 47 | 49 | ||
| 50 | static void jffs2_destroy_inode(struct inode *inode) | ||
| 51 | { | ||
| 52 | call_rcu(&inode->i_rcu, jffs2_i_callback); | ||
| 53 | } | ||
| 54 | |||
| 48 | static void jffs2_i_init_once(void *foo) | 55 | static void jffs2_i_init_once(void *foo) |
| 49 | { | 56 | { |
| 50 | struct jffs2_inode_info *f = foo; | 57 | struct jffs2_inode_info *f = foo; |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 0669fc1cc3bf..b715b0f7bdfd 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
| @@ -115,6 +115,14 @@ static struct inode *jfs_alloc_inode(struct super_block *sb) | |||
| 115 | return &jfs_inode->vfs_inode; | 115 | return &jfs_inode->vfs_inode; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static void jfs_i_callback(struct rcu_head *head) | ||
| 119 | { | ||
| 120 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 121 | struct jfs_inode_info *ji = JFS_IP(inode); | ||
| 122 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 123 | kmem_cache_free(jfs_inode_cachep, ji); | ||
| 124 | } | ||
| 125 | |||
| 118 | static void jfs_destroy_inode(struct inode *inode) | 126 | static void jfs_destroy_inode(struct inode *inode) |
| 119 | { | 127 | { |
| 120 | struct jfs_inode_info *ji = JFS_IP(inode); | 128 | struct jfs_inode_info *ji = JFS_IP(inode); |
| @@ -128,7 +136,7 @@ static void jfs_destroy_inode(struct inode *inode) | |||
| 128 | ji->active_ag = -1; | 136 | ji->active_ag = -1; |
| 129 | } | 137 | } |
| 130 | spin_unlock_irq(&ji->ag_lock); | 138 | spin_unlock_irq(&ji->ag_lock); |
| 131 | kmem_cache_free(jfs_inode_cachep, ji); | 139 | call_rcu(&inode->i_rcu, jfs_i_callback); |
| 132 | } | 140 | } |
| 133 | 141 | ||
| 134 | static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 142 | static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index d8c71ece098f..03b8c240aeda 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c | |||
| @@ -141,13 +141,20 @@ struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *is_cached) | |||
| 141 | return __logfs_iget(sb, ino); | 141 | return __logfs_iget(sb, ino); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | static void logfs_i_callback(struct rcu_head *head) | ||
| 145 | { | ||
| 146 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 147 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 148 | kmem_cache_free(logfs_inode_cache, logfs_inode(inode)); | ||
| 149 | } | ||
| 150 | |||
| 144 | static void __logfs_destroy_inode(struct inode *inode) | 151 | static void __logfs_destroy_inode(struct inode *inode) |
| 145 | { | 152 | { |
| 146 | struct logfs_inode *li = logfs_inode(inode); | 153 | struct logfs_inode *li = logfs_inode(inode); |
| 147 | 154 | ||
| 148 | BUG_ON(li->li_block); | 155 | BUG_ON(li->li_block); |
| 149 | list_del(&li->li_freeing_list); | 156 | list_del(&li->li_freeing_list); |
| 150 | kmem_cache_free(logfs_inode_cache, li); | 157 | call_rcu(&inode->i_rcu, logfs_i_callback); |
| 151 | } | 158 | } |
| 152 | 159 | ||
| 153 | static void logfs_destroy_inode(struct inode *inode) | 160 | static void logfs_destroy_inode(struct inode *inode) |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index fb2020858a34..ae0b83f476a6 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
| @@ -68,11 +68,18 @@ static struct inode *minix_alloc_inode(struct super_block *sb) | |||
| 68 | return &ei->vfs_inode; | 68 | return &ei->vfs_inode; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static void minix_destroy_inode(struct inode *inode) | 71 | static void minix_i_callback(struct rcu_head *head) |
| 72 | { | 72 | { |
| 73 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 74 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 73 | kmem_cache_free(minix_inode_cachep, minix_i(inode)); | 75 | kmem_cache_free(minix_inode_cachep, minix_i(inode)); |
| 74 | } | 76 | } |
| 75 | 77 | ||
| 78 | static void minix_destroy_inode(struct inode *inode) | ||
| 79 | { | ||
| 80 | call_rcu(&inode->i_rcu, minix_i_callback); | ||
| 81 | } | ||
| 82 | |||
| 76 | static void init_once(void *foo) | 83 | static void init_once(void *foo) |
| 77 | { | 84 | { |
| 78 | struct minix_inode_info *ei = (struct minix_inode_info *) foo; | 85 | struct minix_inode_info *ei = (struct minix_inode_info *) foo; |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 8fb93b604e73..60047dbeb38d 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
| @@ -58,11 +58,18 @@ static struct inode *ncp_alloc_inode(struct super_block *sb) | |||
| 58 | return &ei->vfs_inode; | 58 | return &ei->vfs_inode; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | static void ncp_destroy_inode(struct inode *inode) | 61 | static void ncp_i_callback(struct rcu_head *head) |
| 62 | { | 62 | { |
| 63 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 64 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 63 | kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); | 65 | kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); |
| 64 | } | 66 | } |
| 65 | 67 | ||
| 68 | static void ncp_destroy_inode(struct inode *inode) | ||
| 69 | { | ||
| 70 | call_rcu(&inode->i_rcu, ncp_i_callback); | ||
| 71 | } | ||
| 72 | |||
| 66 | static void init_once(void *foo) | 73 | static void init_once(void *foo) |
| 67 | { | 74 | { |
| 68 | struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; | 75 | struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e67e31c73416..017daa3bed38 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -1438,11 +1438,18 @@ struct inode *nfs_alloc_inode(struct super_block *sb) | |||
| 1438 | return &nfsi->vfs_inode; | 1438 | return &nfsi->vfs_inode; |
| 1439 | } | 1439 | } |
| 1440 | 1440 | ||
| 1441 | void nfs_destroy_inode(struct inode *inode) | 1441 | static void nfs_i_callback(struct rcu_head *head) |
| 1442 | { | 1442 | { |
| 1443 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 1444 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 1443 | kmem_cache_free(nfs_inode_cachep, NFS_I(inode)); | 1445 | kmem_cache_free(nfs_inode_cachep, NFS_I(inode)); |
| 1444 | } | 1446 | } |
| 1445 | 1447 | ||
| 1448 | void nfs_destroy_inode(struct inode *inode) | ||
| 1449 | { | ||
| 1450 | call_rcu(&inode->i_rcu, nfs_i_callback); | ||
| 1451 | } | ||
| 1452 | |||
| 1446 | static inline void nfs4_init_once(struct nfs_inode *nfsi) | 1453 | static inline void nfs4_init_once(struct nfs_inode *nfsi) |
| 1447 | { | 1454 | { |
| 1448 | #ifdef CONFIG_NFS_V4 | 1455 | #ifdef CONFIG_NFS_V4 |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index d36fc7ee615f..e2dcc9c733f7 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
| @@ -162,10 +162,13 @@ struct inode *nilfs_alloc_inode(struct super_block *sb) | |||
| 162 | return &ii->vfs_inode; | 162 | return &ii->vfs_inode; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | void nilfs_destroy_inode(struct inode *inode) | 165 | static void nilfs_i_callback(struct rcu_head *head) |
| 166 | { | 166 | { |
| 167 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 167 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); | 168 | struct nilfs_mdt_info *mdi = NILFS_MDT(inode); |
| 168 | 169 | ||
| 170 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 171 | |||
| 169 | if (mdi) { | 172 | if (mdi) { |
| 170 | kfree(mdi->mi_bgl); /* kfree(NULL) is safe */ | 173 | kfree(mdi->mi_bgl); /* kfree(NULL) is safe */ |
| 171 | kfree(mdi); | 174 | kfree(mdi); |
| @@ -173,6 +176,11 @@ void nilfs_destroy_inode(struct inode *inode) | |||
| 173 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); | 176 | kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); |
| 174 | } | 177 | } |
| 175 | 178 | ||
| 179 | void nilfs_destroy_inode(struct inode *inode) | ||
| 180 | { | ||
| 181 | call_rcu(&inode->i_rcu, nilfs_i_callback); | ||
| 182 | } | ||
| 183 | |||
| 176 | static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) | 184 | static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) |
| 177 | { | 185 | { |
| 178 | struct the_nilfs *nilfs = sbi->s_nilfs; | 186 | struct the_nilfs *nilfs = sbi->s_nilfs; |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 93622b175fc7..a627ed82c0a3 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
| @@ -332,6 +332,13 @@ struct inode *ntfs_alloc_big_inode(struct super_block *sb) | |||
| 332 | return NULL; | 332 | return NULL; |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | static void ntfs_i_callback(struct rcu_head *head) | ||
| 336 | { | ||
| 337 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 338 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 339 | kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode)); | ||
| 340 | } | ||
| 341 | |||
| 335 | void ntfs_destroy_big_inode(struct inode *inode) | 342 | void ntfs_destroy_big_inode(struct inode *inode) |
| 336 | { | 343 | { |
| 337 | ntfs_inode *ni = NTFS_I(inode); | 344 | ntfs_inode *ni = NTFS_I(inode); |
| @@ -340,7 +347,7 @@ void ntfs_destroy_big_inode(struct inode *inode) | |||
| 340 | BUG_ON(ni->page); | 347 | BUG_ON(ni->page); |
| 341 | if (!atomic_dec_and_test(&ni->count)) | 348 | if (!atomic_dec_and_test(&ni->count)) |
| 342 | BUG(); | 349 | BUG(); |
| 343 | kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode)); | 350 | call_rcu(&inode->i_rcu, ntfs_i_callback); |
| 344 | } | 351 | } |
| 345 | 352 | ||
| 346 | static inline ntfs_inode *ntfs_alloc_extent_inode(void) | 353 | static inline ntfs_inode *ntfs_alloc_extent_inode(void) |
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c index b2df490a19ed..8c5c0eddc365 100644 --- a/fs/ocfs2/dlmfs/dlmfs.c +++ b/fs/ocfs2/dlmfs/dlmfs.c | |||
| @@ -351,11 +351,18 @@ static struct inode *dlmfs_alloc_inode(struct super_block *sb) | |||
| 351 | return &ip->ip_vfs_inode; | 351 | return &ip->ip_vfs_inode; |
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | static void dlmfs_destroy_inode(struct inode *inode) | 354 | static void dlmfs_i_callback(struct rcu_head *head) |
| 355 | { | 355 | { |
| 356 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 357 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 356 | kmem_cache_free(dlmfs_inode_cache, DLMFS_I(inode)); | 358 | kmem_cache_free(dlmfs_inode_cache, DLMFS_I(inode)); |
| 357 | } | 359 | } |
| 358 | 360 | ||
| 361 | static void dlmfs_destroy_inode(struct inode *inode) | ||
| 362 | { | ||
| 363 | call_rcu(&inode->i_rcu, dlmfs_i_callback); | ||
| 364 | } | ||
| 365 | |||
| 359 | static void dlmfs_evict_inode(struct inode *inode) | 366 | static void dlmfs_evict_inode(struct inode *inode) |
| 360 | { | 367 | { |
| 361 | int status; | 368 | int status; |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index cfeab7ce3697..17ff46fa8a10 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
| @@ -569,11 +569,18 @@ static struct inode *ocfs2_alloc_inode(struct super_block *sb) | |||
| 569 | return &oi->vfs_inode; | 569 | return &oi->vfs_inode; |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | static void ocfs2_destroy_inode(struct inode *inode) | 572 | static void ocfs2_i_callback(struct rcu_head *head) |
| 573 | { | 573 | { |
| 574 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 575 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 574 | kmem_cache_free(ocfs2_inode_cachep, OCFS2_I(inode)); | 576 | kmem_cache_free(ocfs2_inode_cachep, OCFS2_I(inode)); |
| 575 | } | 577 | } |
| 576 | 578 | ||
| 579 | static void ocfs2_destroy_inode(struct inode *inode) | ||
| 580 | { | ||
| 581 | call_rcu(&inode->i_rcu, ocfs2_i_callback); | ||
| 582 | } | ||
| 583 | |||
| 577 | static unsigned long long ocfs2_max_file_offset(unsigned int bbits, | 584 | static unsigned long long ocfs2_max_file_offset(unsigned int bbits, |
| 578 | unsigned int cbits) | 585 | unsigned int cbits) |
| 579 | { | 586 | { |
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 911e61f348fc..a2a5bff774e3 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c | |||
| @@ -343,11 +343,18 @@ static struct inode *openprom_alloc_inode(struct super_block *sb) | |||
| 343 | return &oi->vfs_inode; | 343 | return &oi->vfs_inode; |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | static void openprom_destroy_inode(struct inode *inode) | 346 | static void openprom_i_callback(struct rcu_head *head) |
| 347 | { | 347 | { |
| 348 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 349 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 348 | kmem_cache_free(op_inode_cachep, OP_I(inode)); | 350 | kmem_cache_free(op_inode_cachep, OP_I(inode)); |
| 349 | } | 351 | } |
| 350 | 352 | ||
| 353 | static void openprom_destroy_inode(struct inode *inode) | ||
| 354 | { | ||
| 355 | call_rcu(&inode->i_rcu, openprom_i_callback); | ||
| 356 | } | ||
| 357 | |||
| 351 | static struct inode *openprom_iget(struct super_block *sb, ino_t ino) | 358 | static struct inode *openprom_iget(struct super_block *sb, ino_t ino) |
| 352 | { | 359 | { |
| 353 | struct inode *inode; | 360 | struct inode *inode; |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 3ddb6068177c..6bcb926b101b 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
| @@ -65,11 +65,18 @@ static struct inode *proc_alloc_inode(struct super_block *sb) | |||
| 65 | return inode; | 65 | return inode; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static void proc_destroy_inode(struct inode *inode) | 68 | static void proc_i_callback(struct rcu_head *head) |
| 69 | { | 69 | { |
| 70 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 71 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 70 | kmem_cache_free(proc_inode_cachep, PROC_I(inode)); | 72 | kmem_cache_free(proc_inode_cachep, PROC_I(inode)); |
| 71 | } | 73 | } |
| 72 | 74 | ||
| 75 | static void proc_destroy_inode(struct inode *inode) | ||
| 76 | { | ||
| 77 | call_rcu(&inode->i_rcu, proc_i_callback); | ||
| 78 | } | ||
| 79 | |||
| 73 | static void init_once(void *foo) | 80 | static void init_once(void *foo) |
| 74 | { | 81 | { |
| 75 | struct proc_inode *ei = (struct proc_inode *) foo; | 82 | struct proc_inode *ei = (struct proc_inode *) foo; |
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index fcada42f1aa3..e63b4171d583 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c | |||
| @@ -425,11 +425,18 @@ static struct inode *qnx4_alloc_inode(struct super_block *sb) | |||
| 425 | return &ei->vfs_inode; | 425 | return &ei->vfs_inode; |
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | static void qnx4_destroy_inode(struct inode *inode) | 428 | static void qnx4_i_callback(struct rcu_head *head) |
| 429 | { | 429 | { |
| 430 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 431 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 430 | kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode)); | 432 | kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode)); |
| 431 | } | 433 | } |
| 432 | 434 | ||
| 435 | static void qnx4_destroy_inode(struct inode *inode) | ||
| 436 | { | ||
| 437 | call_rcu(&inode->i_rcu, qnx4_i_callback); | ||
| 438 | } | ||
| 439 | |||
| 433 | static void init_once(void *foo) | 440 | static void init_once(void *foo) |
| 434 | { | 441 | { |
| 435 | struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo; | 442 | struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo; |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index b243117b8752..2575682a9ead 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
| @@ -529,11 +529,18 @@ static struct inode *reiserfs_alloc_inode(struct super_block *sb) | |||
| 529 | return &ei->vfs_inode; | 529 | return &ei->vfs_inode; |
| 530 | } | 530 | } |
| 531 | 531 | ||
| 532 | static void reiserfs_destroy_inode(struct inode *inode) | 532 | static void reiserfs_i_callback(struct rcu_head *head) |
| 533 | { | 533 | { |
| 534 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 535 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 534 | kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode)); | 536 | kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode)); |
| 535 | } | 537 | } |
| 536 | 538 | ||
| 539 | static void reiserfs_destroy_inode(struct inode *inode) | ||
| 540 | { | ||
| 541 | call_rcu(&inode->i_rcu, reiserfs_i_callback); | ||
| 542 | } | ||
| 543 | |||
| 537 | static void init_once(void *foo) | 544 | static void init_once(void *foo) |
| 538 | { | 545 | { |
| 539 | struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo; | 546 | struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo; |
diff --git a/fs/romfs/super.c b/fs/romfs/super.c index 6647f90e55cd..2305e3121cb1 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c | |||
| @@ -400,11 +400,18 @@ static struct inode *romfs_alloc_inode(struct super_block *sb) | |||
| 400 | /* | 400 | /* |
| 401 | * return a spent inode to the slab cache | 401 | * return a spent inode to the slab cache |
| 402 | */ | 402 | */ |
| 403 | static void romfs_destroy_inode(struct inode *inode) | 403 | static void romfs_i_callback(struct rcu_head *head) |
| 404 | { | 404 | { |
| 405 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 406 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 405 | kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode)); | 407 | kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode)); |
| 406 | } | 408 | } |
| 407 | 409 | ||
| 410 | static void romfs_destroy_inode(struct inode *inode) | ||
| 411 | { | ||
| 412 | call_rcu(&inode->i_rcu, romfs_i_callback); | ||
| 413 | } | ||
| 414 | |||
| 408 | /* | 415 | /* |
| 409 | * get filesystem statistics | 416 | * get filesystem statistics |
| 410 | */ | 417 | */ |
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 24de30ba34c1..20700b9f2b4c 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c | |||
| @@ -440,11 +440,18 @@ static struct inode *squashfs_alloc_inode(struct super_block *sb) | |||
| 440 | } | 440 | } |
| 441 | 441 | ||
| 442 | 442 | ||
| 443 | static void squashfs_destroy_inode(struct inode *inode) | 443 | static void squashfs_i_callback(struct rcu_head *head) |
| 444 | { | 444 | { |
| 445 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 446 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 445 | kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode)); | 447 | kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode)); |
| 446 | } | 448 | } |
| 447 | 449 | ||
| 450 | static void squashfs_destroy_inode(struct inode *inode) | ||
| 451 | { | ||
| 452 | call_rcu(&inode->i_rcu, squashfs_i_callback); | ||
| 453 | } | ||
| 454 | |||
| 448 | 455 | ||
| 449 | static struct file_system_type squashfs_fs_type = { | 456 | static struct file_system_type squashfs_fs_type = { |
| 450 | .owner = THIS_MODULE, | 457 | .owner = THIS_MODULE, |
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index de44d067b9e6..0630eb969a28 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
| @@ -333,11 +333,18 @@ static struct inode *sysv_alloc_inode(struct super_block *sb) | |||
| 333 | return &si->vfs_inode; | 333 | return &si->vfs_inode; |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | static void sysv_destroy_inode(struct inode *inode) | 336 | static void sysv_i_callback(struct rcu_head *head) |
| 337 | { | 337 | { |
| 338 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 339 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 338 | kmem_cache_free(sysv_inode_cachep, SYSV_I(inode)); | 340 | kmem_cache_free(sysv_inode_cachep, SYSV_I(inode)); |
| 339 | } | 341 | } |
| 340 | 342 | ||
| 343 | static void sysv_destroy_inode(struct inode *inode) | ||
| 344 | { | ||
| 345 | call_rcu(&inode->i_rcu, sysv_i_callback); | ||
| 346 | } | ||
| 347 | |||
| 341 | static void init_once(void *p) | 348 | static void init_once(void *p) |
| 342 | { | 349 | { |
| 343 | struct sysv_inode_info *si = (struct sysv_inode_info *)p; | 350 | struct sysv_inode_info *si = (struct sysv_inode_info *)p; |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 91fac54c70e3..6e11c2975dcf 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -272,12 +272,20 @@ static struct inode *ubifs_alloc_inode(struct super_block *sb) | |||
| 272 | return &ui->vfs_inode; | 272 | return &ui->vfs_inode; |
| 273 | }; | 273 | }; |
| 274 | 274 | ||
| 275 | static void ubifs_i_callback(struct rcu_head *head) | ||
| 276 | { | ||
| 277 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 278 | struct ubifs_inode *ui = ubifs_inode(inode); | ||
| 279 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 280 | kmem_cache_free(ubifs_inode_slab, ui); | ||
| 281 | } | ||
| 282 | |||
| 275 | static void ubifs_destroy_inode(struct inode *inode) | 283 | static void ubifs_destroy_inode(struct inode *inode) |
| 276 | { | 284 | { |
| 277 | struct ubifs_inode *ui = ubifs_inode(inode); | 285 | struct ubifs_inode *ui = ubifs_inode(inode); |
| 278 | 286 | ||
| 279 | kfree(ui->data); | 287 | kfree(ui->data); |
| 280 | kmem_cache_free(ubifs_inode_slab, inode); | 288 | call_rcu(&inode->i_rcu, ubifs_i_callback); |
| 281 | } | 289 | } |
| 282 | 290 | ||
| 283 | /* | 291 | /* |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 4a5c7c61836a..b539d53320fb 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -139,11 +139,18 @@ static struct inode *udf_alloc_inode(struct super_block *sb) | |||
| 139 | return &ei->vfs_inode; | 139 | return &ei->vfs_inode; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | static void udf_destroy_inode(struct inode *inode) | 142 | static void udf_i_callback(struct rcu_head *head) |
| 143 | { | 143 | { |
| 144 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 145 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 144 | kmem_cache_free(udf_inode_cachep, UDF_I(inode)); | 146 | kmem_cache_free(udf_inode_cachep, UDF_I(inode)); |
| 145 | } | 147 | } |
| 146 | 148 | ||
| 149 | static void udf_destroy_inode(struct inode *inode) | ||
| 150 | { | ||
| 151 | call_rcu(&inode->i_rcu, udf_i_callback); | ||
| 152 | } | ||
| 153 | |||
| 147 | static void init_once(void *foo) | 154 | static void init_once(void *foo) |
| 148 | { | 155 | { |
| 149 | struct udf_inode_info *ei = (struct udf_inode_info *)foo; | 156 | struct udf_inode_info *ei = (struct udf_inode_info *)foo; |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 2c47daed56da..2c61ac5d4e48 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
| @@ -1412,11 +1412,18 @@ static struct inode *ufs_alloc_inode(struct super_block *sb) | |||
| 1412 | return &ei->vfs_inode; | 1412 | return &ei->vfs_inode; |
| 1413 | } | 1413 | } |
| 1414 | 1414 | ||
| 1415 | static void ufs_destroy_inode(struct inode *inode) | 1415 | static void ufs_i_callback(struct rcu_head *head) |
| 1416 | { | 1416 | { |
| 1417 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 1418 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 1417 | kmem_cache_free(ufs_inode_cachep, UFS_I(inode)); | 1419 | kmem_cache_free(ufs_inode_cachep, UFS_I(inode)); |
| 1418 | } | 1420 | } |
| 1419 | 1421 | ||
| 1422 | static void ufs_destroy_inode(struct inode *inode) | ||
| 1423 | { | ||
| 1424 | call_rcu(&inode->i_rcu, ufs_i_callback); | ||
| 1425 | } | ||
| 1426 | |||
| 1420 | static void init_once(void *foo) | 1427 | static void init_once(void *foo) |
| 1421 | { | 1428 | { |
| 1422 | struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; | 1429 | struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 0cdd26932d8e..d7de5a3f7867 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
| @@ -91,6 +91,17 @@ xfs_inode_alloc( | |||
| 91 | return ip; | 91 | return ip; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | STATIC void | ||
| 95 | xfs_inode_free_callback( | ||
| 96 | struct rcu_head *head) | ||
| 97 | { | ||
| 98 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 99 | struct xfs_inode *ip = XFS_I(inode); | ||
| 100 | |||
| 101 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 102 | kmem_zone_free(xfs_inode_zone, ip); | ||
| 103 | } | ||
| 104 | |||
| 94 | void | 105 | void |
| 95 | xfs_inode_free( | 106 | xfs_inode_free( |
| 96 | struct xfs_inode *ip) | 107 | struct xfs_inode *ip) |
| @@ -134,7 +145,7 @@ xfs_inode_free( | |||
| 134 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | 145 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); |
| 135 | ASSERT(completion_done(&ip->i_flush)); | 146 | ASSERT(completion_done(&ip->i_flush)); |
| 136 | 147 | ||
| 137 | kmem_zone_free(xfs_inode_zone, ip); | 148 | call_rcu(&ip->i_vnode.i_rcu, xfs_inode_free_callback); |
| 138 | } | 149 | } |
| 139 | 150 | ||
| 140 | /* | 151 | /* |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 296cf2fde945..1ff4d0a33b25 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -737,7 +737,10 @@ struct inode { | |||
| 737 | struct list_head i_wb_list; /* backing dev IO list */ | 737 | struct list_head i_wb_list; /* backing dev IO list */ |
| 738 | struct list_head i_lru; /* inode LRU list */ | 738 | struct list_head i_lru; /* inode LRU list */ |
| 739 | struct list_head i_sb_list; | 739 | struct list_head i_sb_list; |
| 740 | struct list_head i_dentry; | 740 | union { |
| 741 | struct list_head i_dentry; | ||
| 742 | struct rcu_head i_rcu; | ||
| 743 | }; | ||
| 741 | unsigned long i_ino; | 744 | unsigned long i_ino; |
| 742 | atomic_t i_count; | 745 | atomic_t i_count; |
| 743 | unsigned int i_nlink; | 746 | unsigned int i_nlink; |
diff --git a/include/linux/net.h b/include/linux/net.h index 16faa130088c..06bde4908473 100644 --- a/include/linux/net.h +++ b/include/linux/net.h | |||
| @@ -120,7 +120,6 @@ enum sock_shutdown_cmd { | |||
| 120 | struct socket_wq { | 120 | struct socket_wq { |
| 121 | wait_queue_head_t wait; | 121 | wait_queue_head_t wait; |
| 122 | struct fasync_struct *fasync_list; | 122 | struct fasync_struct *fasync_list; |
| 123 | struct rcu_head rcu; | ||
| 124 | } ____cacheline_aligned_in_smp; | 123 | } ____cacheline_aligned_in_smp; |
| 125 | 124 | ||
| 126 | /** | 125 | /** |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 035f4399edbc..14fb6d67e6a3 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
| @@ -237,11 +237,18 @@ static struct inode *mqueue_alloc_inode(struct super_block *sb) | |||
| 237 | return &ei->vfs_inode; | 237 | return &ei->vfs_inode; |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | static void mqueue_destroy_inode(struct inode *inode) | 240 | static void mqueue_i_callback(struct rcu_head *head) |
| 241 | { | 241 | { |
| 242 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 243 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 242 | kmem_cache_free(mqueue_inode_cachep, MQUEUE_I(inode)); | 244 | kmem_cache_free(mqueue_inode_cachep, MQUEUE_I(inode)); |
| 243 | } | 245 | } |
| 244 | 246 | ||
| 247 | static void mqueue_destroy_inode(struct inode *inode) | ||
| 248 | { | ||
| 249 | call_rcu(&inode->i_rcu, mqueue_i_callback); | ||
| 250 | } | ||
| 251 | |||
| 245 | static void mqueue_evict_inode(struct inode *inode) | 252 | static void mqueue_evict_inode(struct inode *inode) |
| 246 | { | 253 | { |
| 247 | struct mqueue_inode_info *info; | 254 | struct mqueue_inode_info *info; |
diff --git a/mm/shmem.c b/mm/shmem.c index 47fdeeb9d636..5ee67c990602 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -2415,13 +2415,20 @@ static struct inode *shmem_alloc_inode(struct super_block *sb) | |||
| 2415 | return &p->vfs_inode; | 2415 | return &p->vfs_inode; |
| 2416 | } | 2416 | } |
| 2417 | 2417 | ||
| 2418 | static void shmem_i_callback(struct rcu_head *head) | ||
| 2419 | { | ||
| 2420 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 2421 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 2422 | kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode)); | ||
| 2423 | } | ||
| 2424 | |||
| 2418 | static void shmem_destroy_inode(struct inode *inode) | 2425 | static void shmem_destroy_inode(struct inode *inode) |
| 2419 | { | 2426 | { |
| 2420 | if ((inode->i_mode & S_IFMT) == S_IFREG) { | 2427 | if ((inode->i_mode & S_IFMT) == S_IFREG) { |
| 2421 | /* only struct inode is valid if it's an inline symlink */ | 2428 | /* only struct inode is valid if it's an inline symlink */ |
| 2422 | mpol_free_shared_policy(&SHMEM_I(inode)->policy); | 2429 | mpol_free_shared_policy(&SHMEM_I(inode)->policy); |
| 2423 | } | 2430 | } |
| 2424 | kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode)); | 2431 | call_rcu(&inode->i_rcu, shmem_i_callback); |
| 2425 | } | 2432 | } |
| 2426 | 2433 | ||
| 2427 | static void init_once(void *foo) | 2434 | static void init_once(void *foo) |
diff --git a/net/socket.c b/net/socket.c index 088fb3fd45e0..97fff3a4e72f 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -262,20 +262,20 @@ static struct inode *sock_alloc_inode(struct super_block *sb) | |||
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | 264 | ||
| 265 | static void wq_free_rcu(struct rcu_head *head) | 265 | static void sock_free_rcu(struct rcu_head *head) |
| 266 | { | 266 | { |
| 267 | struct socket_wq *wq = container_of(head, struct socket_wq, rcu); | 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 | 270 | ||
| 269 | kfree(wq); | 271 | kfree(ei->socket.wq); |
| 272 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 273 | kmem_cache_free(sock_inode_cachep, ei); | ||
| 270 | } | 274 | } |
| 271 | 275 | ||
| 272 | static void sock_destroy_inode(struct inode *inode) | 276 | static void sock_destroy_inode(struct inode *inode) |
| 273 | { | 277 | { |
| 274 | struct socket_alloc *ei; | 278 | call_rcu(&inode->i_rcu, sock_free_rcu); |
| 275 | |||
| 276 | ei = container_of(inode, struct socket_alloc, vfs_inode); | ||
| 277 | call_rcu(&ei->socket.wq->rcu, wq_free_rcu); | ||
| 278 | kmem_cache_free(sock_inode_cachep, ei); | ||
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | static void init_once(void *foo) | 281 | static void init_once(void *foo) |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a0dc1a86fcea..2899fe27f880 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -162,11 +162,19 @@ rpc_alloc_inode(struct super_block *sb) | |||
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static void | 164 | static void |
| 165 | rpc_destroy_inode(struct inode *inode) | 165 | rpc_i_callback(struct rcu_head *head) |
| 166 | { | 166 | { |
| 167 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 168 | INIT_LIST_HEAD(&inode->i_dentry); | ||
| 167 | kmem_cache_free(rpc_inode_cachep, RPC_I(inode)); | 169 | kmem_cache_free(rpc_inode_cachep, RPC_I(inode)); |
| 168 | } | 170 | } |
| 169 | 171 | ||
| 172 | static void | ||
| 173 | rpc_destroy_inode(struct inode *inode) | ||
| 174 | { | ||
| 175 | call_rcu(&inode->i_rcu, rpc_i_callback); | ||
| 176 | } | ||
| 177 | |||
| 170 | static int | 178 | static int |
| 171 | rpc_pipe_open(struct inode *inode, struct file *filp) | 179 | rpc_pipe_open(struct inode *inode, struct file *filp) |
| 172 | { | 180 | { |
