aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/dir.c28
-rw-r--r--fs/ceph/inode.c38
-rw-r--r--fs/ceph/mds_client.c2
-rw-r--r--fs/ceph/super.h2
4 files changed, 46 insertions, 24 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 6bfaa6a4ec47..f0aef787a102 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -42,11 +42,11 @@ int ceph_init_dentry(struct dentry *dentry)
42 42
43 if (dentry->d_parent == NULL || /* nfs fh_to_dentry */ 43 if (dentry->d_parent == NULL || /* nfs fh_to_dentry */
44 ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) 44 ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
45 dentry->d_op = &ceph_dentry_ops; 45 d_set_d_op(dentry, &ceph_dentry_ops);
46 else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR) 46 else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
47 dentry->d_op = &ceph_snapdir_dentry_ops; 47 d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
48 else 48 else
49 dentry->d_op = &ceph_snap_dentry_ops; 49 d_set_d_op(dentry, &ceph_snap_dentry_ops);
50 50
51 di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO); 51 di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO);
52 if (!di) 52 if (!di)
@@ -113,7 +113,7 @@ static int __dcache_readdir(struct file *filp,
113 dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos, 113 dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos,
114 last); 114 last);
115 115
116 spin_lock(&dcache_lock); 116 spin_lock(&parent->d_lock);
117 117
118 /* start at beginning? */ 118 /* start at beginning? */
119 if (filp->f_pos == 2 || last == NULL || 119 if (filp->f_pos == 2 || last == NULL ||
@@ -137,6 +137,7 @@ more:
137 fi->at_end = 1; 137 fi->at_end = 1;
138 goto out_unlock; 138 goto out_unlock;
139 } 139 }
140 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
140 if (!d_unhashed(dentry) && dentry->d_inode && 141 if (!d_unhashed(dentry) && dentry->d_inode &&
141 ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && 142 ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
142 ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && 143 ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
@@ -146,13 +147,15 @@ more:
146 dentry->d_name.len, dentry->d_name.name, di->offset, 147 dentry->d_name.len, dentry->d_name.name, di->offset,
147 filp->f_pos, d_unhashed(dentry) ? " unhashed" : "", 148 filp->f_pos, d_unhashed(dentry) ? " unhashed" : "",
148 !dentry->d_inode ? " null" : ""); 149 !dentry->d_inode ? " null" : "");
150 spin_unlock(&dentry->d_lock);
149 p = p->prev; 151 p = p->prev;
150 dentry = list_entry(p, struct dentry, d_u.d_child); 152 dentry = list_entry(p, struct dentry, d_u.d_child);
151 di = ceph_dentry(dentry); 153 di = ceph_dentry(dentry);
152 } 154 }
153 155
154 atomic_inc(&dentry->d_count); 156 dget_dlock(dentry);
155 spin_unlock(&dcache_lock); 157 spin_unlock(&dentry->d_lock);
158 spin_unlock(&parent->d_lock);
156 159
157 dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos, 160 dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos,
158 dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); 161 dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
@@ -178,19 +181,19 @@ more:
178 181
179 filp->f_pos++; 182 filp->f_pos++;
180 183
181 /* make sure a dentry wasn't dropped while we didn't have dcache_lock */ 184 /* make sure a dentry wasn't dropped while we didn't have parent lock */
182 if (!ceph_i_test(dir, CEPH_I_COMPLETE)) { 185 if (!ceph_i_test(dir, CEPH_I_COMPLETE)) {
183 dout(" lost I_COMPLETE on %p; falling back to mds\n", dir); 186 dout(" lost I_COMPLETE on %p; falling back to mds\n", dir);
184 err = -EAGAIN; 187 err = -EAGAIN;
185 goto out; 188 goto out;
186 } 189 }
187 190
188 spin_lock(&dcache_lock); 191 spin_lock(&parent->d_lock);
189 p = p->prev; /* advance to next dentry */ 192 p = p->prev; /* advance to next dentry */
190 goto more; 193 goto more;
191 194
192out_unlock: 195out_unlock:
193 spin_unlock(&dcache_lock); 196 spin_unlock(&parent->d_lock);
194out: 197out:
195 if (last) 198 if (last)
196 dput(last); 199 dput(last);
@@ -988,7 +991,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
988 */ 991 */
989static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) 992static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
990{ 993{
991 struct inode *dir = dentry->d_parent->d_inode; 994 struct inode *dir;
995
996 if (nd->flags & LOOKUP_RCU)
997 return -ECHILD;
998
999 dir = dentry->d_parent->d_inode;
992 1000
993 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, 1001 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
994 dentry->d_name.len, dentry->d_name.name, dentry->d_inode, 1002 dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 50001de66c69..5625463aa479 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -370,6 +370,15 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
370 return &ci->vfs_inode; 370 return &ci->vfs_inode;
371} 371}
372 372
373static void ceph_i_callback(struct rcu_head *head)
374{
375 struct inode *inode = container_of(head, struct inode, i_rcu);
376 struct ceph_inode_info *ci = ceph_inode(inode);
377
378 INIT_LIST_HEAD(&inode->i_dentry);
379 kmem_cache_free(ceph_inode_cachep, ci);
380}
381
373void ceph_destroy_inode(struct inode *inode) 382void ceph_destroy_inode(struct inode *inode)
374{ 383{
375 struct ceph_inode_info *ci = ceph_inode(inode); 384 struct ceph_inode_info *ci = ceph_inode(inode);
@@ -409,7 +418,7 @@ void ceph_destroy_inode(struct inode *inode)
409 if (ci->i_xattrs.prealloc_blob) 418 if (ci->i_xattrs.prealloc_blob)
410 ceph_buffer_put(ci->i_xattrs.prealloc_blob); 419 ceph_buffer_put(ci->i_xattrs.prealloc_blob);
411 420
412 kmem_cache_free(ceph_inode_cachep, ci); 421 call_rcu(&inode->i_rcu, ceph_i_callback);
413} 422}
414 423
415 424
@@ -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 */
1775int ceph_permission(struct inode *inode, int mask) 1784int 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
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index a6949cc7c69a..a1ee8fa3a8e7 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1502,7 +1502,7 @@ retry:
1502 *base = ceph_ino(temp->d_inode); 1502 *base = ceph_ino(temp->d_inode);
1503 *plen = len; 1503 *plen = len;
1504 dout("build_path on %p %d built %llx '%.*s'\n", 1504 dout("build_path on %p %d built %llx '%.*s'\n",
1505 dentry, atomic_read(&dentry->d_count), *base, len, path); 1505 dentry, dentry->d_count, *base, len, path);
1506 return path; 1506 return path;
1507} 1507}
1508 1508
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index c01aa646b407..88fcaa21b801 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -667,7 +667,7 @@ extern void ceph_queue_invalidate(struct inode *inode);
667extern void ceph_queue_writeback(struct inode *inode); 667extern void ceph_queue_writeback(struct inode *inode);
668 668
669extern int ceph_do_getattr(struct inode *inode, int mask); 669extern int ceph_do_getattr(struct inode *inode, int mask);
670extern int ceph_permission(struct inode *inode, int mask); 670extern int ceph_permission(struct inode *inode, int mask, unsigned int flags);
671extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); 671extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
672extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, 672extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
673 struct kstat *stat); 673 struct kstat *stat);