diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2013-03-13 07:44:32 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-05-02 00:17:07 -0400 |
commit | 2f276c511137d97e56b19e29865e1e6569315ccb (patch) | |
tree | f29a8088a6f312ec40f03b96d96b34e69154627a /fs/ceph/dir.c | |
parent | 8a166d05369f6a0369bb194a795e6e3928ac6e34 (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.c | 25 |
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 | /* |