]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: _readdir_cache_cb() may use the readdir_cache already clear 30933/head
authorhuanwen ren <ren.huanwen@zte.com.cn>
Wed, 7 Aug 2019 16:49:23 +0000 (00:49 +0800)
committerNathan Cutler <ncutler@suse.com>
Tue, 15 Oct 2019 09:37:41 +0000 (11:37 +0200)
Calling function _readdir_cache_cb() means to get dir information from the cache, but in the while loop,
the contents of readdir_cache are not static.

For example, _getattr() will trigger insert_trace to update readdir_cache, such as:
1. insert_trace()->clear_dir_complete_and_ordered() or
2. insert_trace()->add_update_inode()->add_update_cap()-> check_cap_issue()->clear_dir_complete_and_ordered()
So, there is a possibility that dn is empty after the _getattr() call.

Fixes: http://tracker.ceph.com/issues/41148
Signed-off-by: huanwen ren <ren.huanwen@zte.com.cn>
(cherry picked from commit 404c06784e46016703104db59ea73f36d09b578b)

src/client/Client.cc

index 35642d2f878758f266919d32b8e310ec2a7cbd30..8199b0cfca9842cb4fc38f9620428566cf57dab1 100644 (file)
@@ -7793,9 +7793,15 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p,
       continue;
     }
 
+    int idx = pd - dir->readdir_cache.begin();
     int r = _getattr(dn->inode, caps, dirp->perms);
     if (r < 0)
       return r;
+    
+    // the content of readdir_cache may change after _getattr(), so pd may be invalid iterator    
+    pd = dir->readdir_cache.begin() + idx;
+    if (pd >= dir->readdir_cache.end() || *pd != dn)
+      return -EAGAIN;
 
     struct ceph_statx stx;
     struct dirent de;