dirp->offset, dentry_off_lt());
string dn_name;
- while (true) {
+ for (unsigned idx = pd - dir->readdir_cache.begin();
+ idx < dir->readdir_cache.size();
+ ++idx) {
int mask = caps;
if (!dirp->inode->is_complete_and_ordered())
return -EAGAIN;
- if (pd == dir->readdir_cache.end())
- break;
- Dentry *dn = *pd;
+ Dentry *dn = dir->readdir_cache[idx];
if (dn->inode == NULL) {
ldout(cct, 15) << " skipping null '" << dn->name << "'" << dendl;
- ++pd;
continue;
}
if (dn->cap_shared_gen != dir->parent_inode->shared_gen) {
ldout(cct, 15) << " skipping mismatch shared gen '" << dn->name << "'" << dendl;
- ++pd;
continue;
}
- int idx = pd - dir->readdir_cache.begin();
if (dn->inode->is_dir() && cct->_conf->client_dirsize_rbytes) {
mask |= CEPH_STAT_RSTAT;
}
return -EAGAIN;
}
- // 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)
+ // the content of readdir_cache may change after _getattr()
+ if (idx >= dir->readdir_cache.size() || dir->readdir_cache[idx] != dn)
return -EAGAIN;
struct ceph_statx stx;
uint64_t next_off = dn->offset + 1;
auto dname = _unwrap_name(*diri, dn->name, dn->alternate_name);
fill_dirent(&de, dname.c_str(), stx.stx_mode, stx.stx_ino, next_off);
- ++pd;
- if (pd == dir->readdir_cache.end())
+ if (idx + 1 == dir->readdir_cache.size())
next_off = dir_result_t::END;
Inode *in = NULL;
dn_name = dn->name; // fill in name while we have lock
+ // the content of readdir_cache may change after unlocking
client_lock.unlock();
r = cb(p, &de, &stx, next_off, in); // _next_ offset
client_lock.lock();