diff options
author | Sage Weil <sage@newdream.net> | 2011-11-03 12:23:36 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2011-11-06 00:10:10 -0400 |
commit | c6ffe10015f4e6fba8a915318b319c43aed1836f (patch) | |
tree | dd39730aeb6d00713ca27a1bf34b116d31479151 /fs/ceph/dir.c | |
parent | b58dc4100b9190f2cb437f1f67ffcb9f9acc4923 (diff) |
ceph: use new D_COMPLETE dentry flag
We used to use a flag on the directory inode to track whether the dcache
contents for a directory were a complete cached copy. Switch to a dentry
flag CEPH_D_COMPLETE that is safely updated by ->d_prune().
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r-- | fs/ceph/dir.c | 59 |
1 files changed, 50 insertions, 9 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 97fb155b3242..2abd0dfad7f8 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -108,7 +108,7 @@ static unsigned fpos_off(loff_t p) | |||
108 | * falling back to a "normal" sync readdir if any dentries in the dir | 108 | * falling back to a "normal" sync readdir if any dentries in the dir |
109 | * are dropped. | 109 | * are dropped. |
110 | * | 110 | * |
111 | * I_COMPLETE tells indicates we have all dentries in the dir. It is | 111 | * D_COMPLETE tells indicates we have all dentries in the dir. It is |
112 | * defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by | 112 | * defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by |
113 | * the MDS if/when the directory is modified). | 113 | * the MDS if/when the directory is modified). |
114 | */ | 114 | */ |
@@ -199,8 +199,8 @@ more: | |||
199 | filp->f_pos++; | 199 | filp->f_pos++; |
200 | 200 | ||
201 | /* make sure a dentry wasn't dropped while we didn't have parent lock */ | 201 | /* make sure a dentry wasn't dropped while we didn't have parent lock */ |
202 | if (!ceph_i_test(dir, CEPH_I_COMPLETE)) { | 202 | if (!ceph_dir_test_complete(dir)) { |
203 | dout(" lost I_COMPLETE on %p; falling back to mds\n", dir); | 203 | dout(" lost D_COMPLETE on %p; falling back to mds\n", dir); |
204 | err = -EAGAIN; | 204 | err = -EAGAIN; |
205 | goto out; | 205 | goto out; |
206 | } | 206 | } |
@@ -285,7 +285,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
285 | if ((filp->f_pos == 2 || fi->dentry) && | 285 | if ((filp->f_pos == 2 || fi->dentry) && |
286 | !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && | 286 | !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && |
287 | ceph_snap(inode) != CEPH_SNAPDIR && | 287 | ceph_snap(inode) != CEPH_SNAPDIR && |
288 | (ci->i_ceph_flags & CEPH_I_COMPLETE) && | 288 | ceph_dir_test_complete(inode) && |
289 | __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { | 289 | __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { |
290 | spin_unlock(&inode->i_lock); | 290 | spin_unlock(&inode->i_lock); |
291 | err = __dcache_readdir(filp, dirent, filldir); | 291 | err = __dcache_readdir(filp, dirent, filldir); |
@@ -351,7 +351,7 @@ more: | |||
351 | 351 | ||
352 | if (!req->r_did_prepopulate) { | 352 | if (!req->r_did_prepopulate) { |
353 | dout("readdir !did_prepopulate"); | 353 | dout("readdir !did_prepopulate"); |
354 | fi->dir_release_count--; /* preclude I_COMPLETE */ | 354 | fi->dir_release_count--; /* preclude D_COMPLETE */ |
355 | } | 355 | } |
356 | 356 | ||
357 | /* note next offset and last dentry name */ | 357 | /* note next offset and last dentry name */ |
@@ -430,8 +430,7 @@ more: | |||
430 | */ | 430 | */ |
431 | spin_lock(&inode->i_lock); | 431 | spin_lock(&inode->i_lock); |
432 | if (ci->i_release_count == fi->dir_release_count) { | 432 | if (ci->i_release_count == fi->dir_release_count) { |
433 | dout(" marking %p complete\n", inode); | 433 | ceph_dir_set_complete(inode); |
434 | /* ci->i_ceph_flags |= CEPH_I_COMPLETE; */ | ||
435 | ci->i_max_offset = filp->f_pos; | 434 | ci->i_max_offset = filp->f_pos; |
436 | } | 435 | } |
437 | spin_unlock(&inode->i_lock); | 436 | spin_unlock(&inode->i_lock); |
@@ -614,7 +613,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
614 | fsc->mount_options->snapdir_name, | 613 | fsc->mount_options->snapdir_name, |
615 | dentry->d_name.len) && | 614 | dentry->d_name.len) && |
616 | !is_root_ceph_dentry(dir, dentry) && | 615 | !is_root_ceph_dentry(dir, dentry) && |
617 | (ci->i_ceph_flags & CEPH_I_COMPLETE) && | 616 | ceph_dir_test_complete(dir) && |
618 | (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) { | 617 | (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) { |
619 | spin_unlock(&dir->i_lock); | 618 | spin_unlock(&dir->i_lock); |
620 | dout(" dir %p complete, -ENOENT\n", dir); | 619 | dout(" dir %p complete, -ENOENT\n", dir); |
@@ -934,7 +933,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
934 | */ | 933 | */ |
935 | 934 | ||
936 | /* d_move screws up d_subdirs order */ | 935 | /* d_move screws up d_subdirs order */ |
937 | ceph_i_clear(new_dir, CEPH_I_COMPLETE); | 936 | ceph_dir_clear_complete(new_dir); |
938 | 937 | ||
939 | d_move(old_dentry, new_dentry); | 938 | d_move(old_dentry, new_dentry); |
940 | 939 | ||
@@ -1093,6 +1092,48 @@ static int ceph_snapdir_d_revalidate(struct dentry *dentry, | |||
1093 | } | 1092 | } |
1094 | 1093 | ||
1095 | /* | 1094 | /* |
1095 | * Set/clear/test dir complete flag on the dir's dentry. | ||
1096 | */ | ||
1097 | static struct dentry * __d_find_any_alias(struct inode *inode) | ||
1098 | { | ||
1099 | struct dentry *alias; | ||
1100 | |||
1101 | if (list_empty(&inode->i_dentry)) | ||
1102 | return NULL; | ||
1103 | alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias); | ||
1104 | return alias; | ||
1105 | } | ||
1106 | |||
1107 | void ceph_dir_set_complete(struct inode *inode) | ||
1108 | { | ||
1109 | struct dentry *dentry = __d_find_any_alias(inode); | ||
1110 | |||
1111 | if (dentry && ceph_dentry(dentry)) { | ||
1112 | dout(" marking %p (%p) complete\n", inode, dentry); | ||
1113 | set_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); | ||
1114 | } | ||
1115 | } | ||
1116 | |||
1117 | void ceph_dir_clear_complete(struct inode *inode) | ||
1118 | { | ||
1119 | struct dentry *dentry = __d_find_any_alias(inode); | ||
1120 | |||
1121 | if (dentry && ceph_dentry(dentry)) { | ||
1122 | dout(" marking %p (%p) NOT complete\n", inode, dentry); | ||
1123 | clear_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | bool ceph_dir_test_complete(struct inode *inode) | ||
1128 | { | ||
1129 | struct dentry *dentry = __d_find_any_alias(inode); | ||
1130 | |||
1131 | if (dentry && ceph_dentry(dentry)) | ||
1132 | return test_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); | ||
1133 | return false; | ||
1134 | } | ||
1135 | |||
1136 | /* | ||
1096 | * When the VFS prunes a dentry from the cache, we need to clear the | 1137 | * When the VFS prunes a dentry from the cache, we need to clear the |
1097 | * complete flag on the parent directory. | 1138 | * complete flag on the parent directory. |
1098 | * | 1139 | * |