diff options
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index bf1286588f26..e61de4f7b99d 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 | ||
@@ -841,13 +850,13 @@ static void ceph_set_dentry_offset(struct dentry *dn) | |||
841 | di->offset = ceph_inode(inode)->i_max_offset++; | 850 | di->offset = ceph_inode(inode)->i_max_offset++; |
842 | spin_unlock(&inode->i_lock); | 851 | spin_unlock(&inode->i_lock); |
843 | 852 | ||
844 | spin_lock(&dcache_lock); | 853 | spin_lock(&dir->d_lock); |
845 | spin_lock(&dn->d_lock); | 854 | spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED); |
846 | list_move(&dn->d_u.d_child, &dir->d_subdirs); | 855 | list_move(&dn->d_u.d_child, &dir->d_subdirs); |
847 | dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset, | 856 | dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset, |
848 | dn->d_u.d_child.prev, dn->d_u.d_child.next); | 857 | dn->d_u.d_child.prev, dn->d_u.d_child.next); |
849 | spin_unlock(&dn->d_lock); | 858 | spin_unlock(&dn->d_lock); |
850 | spin_unlock(&dcache_lock); | 859 | spin_unlock(&dir->d_lock); |
851 | } | 860 | } |
852 | 861 | ||
853 | /* | 862 | /* |
@@ -879,8 +888,8 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, | |||
879 | } else if (realdn) { | 888 | } else if (realdn) { |
880 | dout("dn %p (%d) spliced with %p (%d) " | 889 | dout("dn %p (%d) spliced with %p (%d) " |
881 | "inode %p ino %llx.%llx\n", | 890 | "inode %p ino %llx.%llx\n", |
882 | dn, atomic_read(&dn->d_count), | 891 | dn, dn->d_count, |
883 | realdn, atomic_read(&realdn->d_count), | 892 | realdn, realdn->d_count, |
884 | realdn->d_inode, ceph_vinop(realdn->d_inode)); | 893 | realdn->d_inode, ceph_vinop(realdn->d_inode)); |
885 | dput(dn); | 894 | dput(dn); |
886 | dn = realdn; | 895 | dn = realdn; |
@@ -1231,11 +1240,11 @@ retry_lookup: | |||
1231 | goto retry_lookup; | 1240 | goto retry_lookup; |
1232 | } else { | 1241 | } else { |
1233 | /* reorder parent's d_subdirs */ | 1242 | /* reorder parent's d_subdirs */ |
1234 | spin_lock(&dcache_lock); | 1243 | spin_lock(&parent->d_lock); |
1235 | spin_lock(&dn->d_lock); | 1244 | spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED); |
1236 | list_move(&dn->d_u.d_child, &parent->d_subdirs); | 1245 | list_move(&dn->d_u.d_child, &parent->d_subdirs); |
1237 | spin_unlock(&dn->d_lock); | 1246 | spin_unlock(&dn->d_lock); |
1238 | spin_unlock(&dcache_lock); | 1247 | spin_unlock(&parent->d_lock); |
1239 | } | 1248 | } |
1240 | 1249 | ||
1241 | di = dn->d_fsdata; | 1250 | di = dn->d_fsdata; |
@@ -1772,12 +1781,17 @@ int ceph_do_getattr(struct inode *inode, int mask) | |||
1772 | * Check inode permissions. We verify we have a valid value for | 1781 | * Check inode permissions. We verify we have a valid value for |
1773 | * the AUTH cap, then call the generic handler. | 1782 | * the AUTH cap, then call the generic handler. |
1774 | */ | 1783 | */ |
1775 | int ceph_permission(struct inode *inode, int mask) | 1784 | int ceph_permission(struct inode *inode, int mask, unsigned int flags) |
1776 | { | 1785 | { |
1777 | int err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED); | 1786 | int err; |
1787 | |||
1788 | if (flags & IPERM_FLAG_RCU) | ||
1789 | return -ECHILD; | ||
1790 | |||
1791 | err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED); | ||
1778 | 1792 | ||
1779 | if (!err) | 1793 | if (!err) |
1780 | err = generic_permission(inode, mask, NULL); | 1794 | err = generic_permission(inode, mask, flags, NULL); |
1781 | return err; | 1795 | return err; |
1782 | } | 1796 | } |
1783 | 1797 | ||