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)
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;