From b09ce15993eb1651fab5d5e371539a7cacda9a7c Mon Sep 17 00:00:00 2001 From: huanwen ren Date: Thu, 8 Aug 2019 00:49:23 +0800 Subject: [PATCH] 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) --- src/client/Client.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/client/Client.cc b/src/client/Client.cc index e9e862d37cdbe..f3a9380179909 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -7819,9 +7819,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; -- 2.39.5