aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/dir.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-03-13 07:44:32 -0400
committerSage Weil <sage@inktank.com>2013-05-02 00:17:07 -0400
commit2f276c511137d97e56b19e29865e1e6569315ccb (patch)
treef29a8088a6f312ec40f03b96d96b34e69154627a /fs/ceph/dir.c
parent8a166d05369f6a0369bb194a795e6e3928ac6e34 (diff)
ceph: use i_release_count to indicate dir's completeness
Current ceph code tracks directory's completeness in two places. ceph_readdir() checks i_release_count to decide if it can set the I_COMPLETE flag in i_ceph_flags. All other places check the I_COMPLETE flag. This indirection introduces locking complexity. This patch adds a new variable i_complete_count to ceph_inode_info. Set i_release_count's value to it when marking a directory complete. By comparing the two variables, we know if a directory is complete Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r--fs/ceph/dir.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 0c369ac62c07..f02d82b7933e 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -107,7 +107,7 @@ static unsigned fpos_off(loff_t p)
107 * falling back to a "normal" sync readdir if any dentries in the dir 107 * falling back to a "normal" sync readdir if any dentries in the dir
108 * are dropped. 108 * are dropped.
109 * 109 *
110 * I_COMPLETE tells indicates we have all dentries in the dir. It is 110 * Complete dir indicates that we have all dentries in the dir. It is
111 * defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by 111 * defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by
112 * the MDS if/when the directory is modified). 112 * the MDS if/when the directory is modified).
113 */ 113 */
@@ -198,8 +198,8 @@ more:
198 filp->f_pos++; 198 filp->f_pos++;
199 199
200 /* make sure a dentry wasn't dropped while we didn't have parent lock */ 200 /* make sure a dentry wasn't dropped while we didn't have parent lock */
201 if (!ceph_i_test(dir, CEPH_I_COMPLETE)) { 201 if (!ceph_dir_is_complete(dir)) {
202 dout(" lost I_COMPLETE on %p; falling back to mds\n", dir); 202 dout(" lost dir complete on %p; falling back to mds\n", dir);
203 err = -EAGAIN; 203 err = -EAGAIN;
204 goto out; 204 goto out;
205 } 205 }
@@ -258,7 +258,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
258 if (filp->f_pos == 0) { 258 if (filp->f_pos == 0) {
259 /* note dir version at start of readdir so we can tell 259 /* note dir version at start of readdir so we can tell
260 * if any dentries get dropped */ 260 * if any dentries get dropped */
261 fi->dir_release_count = ci->i_release_count; 261 fi->dir_release_count = atomic_read(&ci->i_release_count);
262 262
263 dout("readdir off 0 -> '.'\n"); 263 dout("readdir off 0 -> '.'\n");
264 if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0), 264 if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0),
@@ -284,7 +284,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
284 if ((filp->f_pos == 2 || fi->dentry) && 284 if ((filp->f_pos == 2 || fi->dentry) &&
285 !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && 285 !ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
286 ceph_snap(inode) != CEPH_SNAPDIR && 286 ceph_snap(inode) != CEPH_SNAPDIR &&
287 (ci->i_ceph_flags & CEPH_I_COMPLETE) && 287 __ceph_dir_is_complete(ci) &&
288 __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { 288 __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) {
289 spin_unlock(&ci->i_ceph_lock); 289 spin_unlock(&ci->i_ceph_lock);
290 err = __dcache_readdir(filp, dirent, filldir); 290 err = __dcache_readdir(filp, dirent, filldir);
@@ -350,7 +350,8 @@ more:
350 350
351 if (!req->r_did_prepopulate) { 351 if (!req->r_did_prepopulate) {
352 dout("readdir !did_prepopulate"); 352 dout("readdir !did_prepopulate");
353 fi->dir_release_count--; /* preclude I_COMPLETE */ 353 /* preclude from marking dir complete */
354 fi->dir_release_count--;
354 } 355 }
355 356
356 /* note next offset and last dentry name */ 357 /* note next offset and last dentry name */
@@ -428,9 +429,9 @@ more:
428 * the complete dir contents in our cache. 429 * the complete dir contents in our cache.
429 */ 430 */
430 spin_lock(&ci->i_ceph_lock); 431 spin_lock(&ci->i_ceph_lock);
431 if (ci->i_release_count == fi->dir_release_count) { 432 if (atomic_read(&ci->i_release_count) == fi->dir_release_count) {
432 dout(" marking %p complete\n", inode); 433 dout(" marking %p complete\n", inode);
433 ci->i_ceph_flags |= CEPH_I_COMPLETE; 434 __ceph_dir_set_complete(ci, fi->dir_release_count);
434 ci->i_max_offset = filp->f_pos; 435 ci->i_max_offset = filp->f_pos;
435 } 436 }
436 spin_unlock(&ci->i_ceph_lock); 437 spin_unlock(&ci->i_ceph_lock);
@@ -605,7 +606,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
605 fsc->mount_options->snapdir_name, 606 fsc->mount_options->snapdir_name,
606 dentry->d_name.len) && 607 dentry->d_name.len) &&
607 !is_root_ceph_dentry(dir, dentry) && 608 !is_root_ceph_dentry(dir, dentry) &&
608 (ci->i_ceph_flags & CEPH_I_COMPLETE) && 609 __ceph_dir_is_complete(ci) &&
609 (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) { 610 (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) {
610 spin_unlock(&ci->i_ceph_lock); 611 spin_unlock(&ci->i_ceph_lock);
611 dout(" dir %p complete, -ENOENT\n", dir); 612 dout(" dir %p complete, -ENOENT\n", dir);
@@ -909,7 +910,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
909 */ 910 */
910 911
911 /* d_move screws up d_subdirs order */ 912 /* d_move screws up d_subdirs order */
912 ceph_i_clear(new_dir, CEPH_I_COMPLETE); 913 ceph_dir_clear_complete(new_dir);
913 914
914 d_move(old_dentry, new_dentry); 915 d_move(old_dentry, new_dentry);
915 916
@@ -1079,7 +1080,7 @@ static void ceph_d_prune(struct dentry *dentry)
1079 if (IS_ROOT(dentry)) 1080 if (IS_ROOT(dentry))
1080 return; 1081 return;
1081 1082
1082 /* if we are not hashed, we don't affect I_COMPLETE */ 1083 /* if we are not hashed, we don't affect dir's completeness */
1083 if (d_unhashed(dentry)) 1084 if (d_unhashed(dentry))
1084 return; 1085 return;
1085 1086
@@ -1087,7 +1088,7 @@ static void ceph_d_prune(struct dentry *dentry)
1087 * we hold d_lock, so d_parent is stable, and d_fsdata is never 1088 * we hold d_lock, so d_parent is stable, and d_fsdata is never
1088 * cleared until d_release 1089 * cleared until d_release
1089 */ 1090 */
1090 ceph_i_clear(dentry->d_parent->d_inode, CEPH_I_COMPLETE); 1091 ceph_dir_clear_complete(dentry->d_parent->d_inode);
1091} 1092}
1092 1093
1093/* 1094/*