@@ -9505,25 +9505,22 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p,
95059505 dirp->offset , dentry_off_lt ());
95069506
95079507 string dn_name;
9508- while (true ) {
9508+ for (unsigned idx = pd - dir->readdir_cache .begin ();
9509+ idx < dir->readdir_cache .size ();
9510+ ++idx) {
95099511 int mask = caps;
95109512 if (!dirp->inode ->is_complete_and_ordered ())
95119513 return -EAGAIN;
9512- if (pd == dir->readdir_cache .end ())
9513- break ;
9514- Dentry *dn = *pd;
9514+ Dentry *dn = dir->readdir_cache [idx];
95159515 if (dn->inode == NULL ) {
95169516 ldout (cct, 15 ) << " skipping null '" << dn->name << " '" << dendl;
9517- ++pd;
95189517 continue ;
95199518 }
95209519 if (dn->cap_shared_gen != dir->parent_inode ->shared_gen ) {
95219520 ldout (cct, 15 ) << " skipping mismatch shared gen '" << dn->name << " '" << dendl;
9522- ++pd;
95239521 continue ;
95249522 }
95259523
9526- int idx = pd - dir->readdir_cache .begin ();
95279524 if (dn->inode ->is_dir () && cct->_conf ->client_dirsize_rbytes ) {
95289525 mask |= CEPH_STAT_RSTAT;
95299526 }
@@ -9537,9 +9534,8 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p,
95379534 return -EAGAIN;
95389535 }
95399536
9540- // the content of readdir_cache may change after _getattr(), so pd may be invalid iterator
9541- pd = dir->readdir_cache .begin () + idx;
9542- if (pd >= dir->readdir_cache .end () || *pd != dn)
9537+ // the content of readdir_cache may change after _getattr()
9538+ if (idx >= dir->readdir_cache .size () || dir->readdir_cache [idx] != dn)
95439539 return -EAGAIN;
95449540
95459541 struct ceph_statx stx;
@@ -9549,8 +9545,7 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p,
95499545 uint64_t next_off = dn->offset + 1 ;
95509546 auto dname = _unwrap_name (*diri, dn->name , dn->alternate_name );
95519547 fill_dirent (&de, dname.c_str (), stx.stx_mode , stx.stx_ino , next_off);
9552- ++pd;
9553- if (pd == dir->readdir_cache .end ())
9548+ if (idx + 1 == dir->readdir_cache .size ())
95549549 next_off = dir_result_t ::END;
95559550
95569551 Inode *in = NULL ;
@@ -9561,6 +9556,7 @@ int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p,
95619556
95629557 dn_name = dn->name ; // fill in name while we have lock
95639558
9559+ // the content of readdir_cache may change after unlocking
95649560 client_lock.unlock ();
95659561 r = cb (p, &de, &stx, next_off, in); // _next_ offset
95669562 client_lock.lock ();
0 commit comments