ceph: introduce a new inode flag indicating if cached dentries are ordered
After creating/deleting/renaming file, offsets of sibling dentries may change. So we can not use cached dentries to satisfy readdir. But we can still use the cached dentries to conclude -ENOENT for lookup. This patch introduces a new inode flag indicating if child dentries are ordered. The flag is set at the same time marking a directory complete. After creating/deleting/renaming file, we clear the flag on directory inode. This prevents ceph_readdir() from using cached dentries to satisfy readdir syscall. Signed-off-by: Yan, Zheng <zyan@redhat.com>
This commit is contained in:
@@ -389,6 +389,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
|
||||
ci->i_version = 0;
|
||||
ci->i_time_warp_seq = 0;
|
||||
ci->i_ceph_flags = 0;
|
||||
ci->i_ordered_count = 0;
|
||||
atomic_set(&ci->i_release_count, 1);
|
||||
atomic_set(&ci->i_complete_count, 0);
|
||||
ci->i_symlink = NULL;
|
||||
@@ -845,7 +846,8 @@ static int fill_inode(struct inode *inode,
|
||||
(issued & CEPH_CAP_FILE_EXCL) == 0 &&
|
||||
!__ceph_dir_is_complete(ci)) {
|
||||
dout(" marking %p complete (empty)\n", inode);
|
||||
__ceph_dir_set_complete(ci, atomic_read(&ci->i_release_count));
|
||||
__ceph_dir_set_complete(ci, atomic_read(&ci->i_release_count),
|
||||
ci->i_ordered_count);
|
||||
}
|
||||
|
||||
/* were we issued a capability? */
|
||||
@@ -1206,8 +1208,8 @@ retry_lookup:
|
||||
ceph_invalidate_dentry_lease(dn);
|
||||
|
||||
/* d_move screws up sibling dentries' offsets */
|
||||
ceph_dir_clear_complete(dir);
|
||||
ceph_dir_clear_complete(olddir);
|
||||
ceph_dir_clear_ordered(dir);
|
||||
ceph_dir_clear_ordered(olddir);
|
||||
|
||||
dout("dn %p gets new offset %lld\n", req->r_old_dentry,
|
||||
ceph_dentry(req->r_old_dentry)->offset);
|
||||
@@ -1219,6 +1221,7 @@ retry_lookup:
|
||||
if (!rinfo->head->is_target) {
|
||||
dout("fill_trace null dentry\n");
|
||||
if (dn->d_inode) {
|
||||
ceph_dir_clear_ordered(dir);
|
||||
dout("d_delete %p\n", dn);
|
||||
d_delete(dn);
|
||||
} else {
|
||||
@@ -1235,7 +1238,7 @@ retry_lookup:
|
||||
|
||||
/* attach proper inode */
|
||||
if (!dn->d_inode) {
|
||||
ceph_dir_clear_complete(dir);
|
||||
ceph_dir_clear_ordered(dir);
|
||||
ihold(in);
|
||||
dn = splice_dentry(dn, in, &have_lease);
|
||||
if (IS_ERR(dn)) {
|
||||
@@ -1265,7 +1268,7 @@ retry_lookup:
|
||||
BUG_ON(!dir);
|
||||
BUG_ON(ceph_snap(dir) != CEPH_SNAPDIR);
|
||||
dout(" linking snapped dir %p to dn %p\n", in, dn);
|
||||
ceph_dir_clear_complete(dir);
|
||||
ceph_dir_clear_ordered(dir);
|
||||
ihold(in);
|
||||
dn = splice_dentry(dn, in, NULL);
|
||||
if (IS_ERR(dn)) {
|
||||
|
Reference in New Issue
Block a user