From: huanwen ren Date: Wed, 7 Aug 2019 16:49:23 +0000 (+0800) Subject: client: _readdir_cache_cb() may use the readdir_cache already clear X-Git-Tag: v13.2.7~34^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4ea7c6cf5e7491c45e6a806e219857a1ece39605;p=ceph.git client: _readdir_cache_cb() may use the readdir_cache already clear 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 (cherry picked from commit 404c06784e46016703104db59ea73f36d09b578b) --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 35642d2f8787..8199b0cfca98 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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;