| 9883 | }; |
| 9884 | |
| 9885 | int Client::_readdir_cache_cb(dir_result_t *dirp, add_dirent_cb_t cb, void *p, |
| 9886 | int caps, bool getref) |
| 9887 | { |
| 9888 | ceph_assert(ceph_mutex_is_locked_by_me(client_lock)); |
| 9889 | ldout(cct, 10) << __func__ << " " << dirp << " on " << dirp->inode->ino |
| 9890 | << " last_name " << dirp->last_name |
| 9891 | << " offset " << hex << dirp->offset << dec |
| 9892 | << dendl; |
| 9893 | auto& diri = dirp->inode; |
| 9894 | Dir *dir = diri->dir; |
| 9895 | |
| 9896 | if (!dir) { |
| 9897 | ldout(cct, 10) << __func__ << " dir is empty" << dendl; |
| 9898 | dirp->set_end(); |
| 9899 | return 0; |
| 9900 | } |
| 9901 | |
| 9902 | vector<Dentry*>::iterator pd = std::lower_bound(dir->readdir_cache.begin(), |
| 9903 | dir->readdir_cache.end(), |
| 9904 | dirp->offset, dentry_off_lt()); |
| 9905 | |
| 9906 | string dn_name; |
| 9907 | for (unsigned idx = pd - dir->readdir_cache.begin(); |
| 9908 | idx < dir->readdir_cache.size(); |
| 9909 | ++idx) { |
| 9910 | int mask = caps; |
| 9911 | if (!dirp->inode->is_complete_and_ordered()) |
| 9912 | return -EAGAIN; |
| 9913 | Dentry *dn = dir->readdir_cache[idx]; |
| 9914 | if (dn->inode == NULL) { |
| 9915 | ldout(cct, 15) << " skipping null '" << dn->name << "'" << dendl; |
| 9916 | continue; |
| 9917 | } |
| 9918 | if (dn->cap_shared_gen != dir->parent_inode->shared_gen) { |
| 9919 | ldout(cct, 15) << " skipping mismatch shared gen '" << dn->name << "'" << dendl; |
| 9920 | continue; |
| 9921 | } |
| 9922 | |
| 9923 | if (dn->inode->is_dir() && cct->_conf->client_dirsize_rbytes) { |
| 9924 | mask |= CEPH_STAT_RSTAT; |
| 9925 | } |
| 9926 | int r = _getattr(dn->inode, mask, dirp->perms); |
| 9927 | if (r < 0) |
| 9928 | return r; |
| 9929 | |
| 9930 | /* fix https://tracker.ceph.com/issues/56288 */ |
| 9931 | if (dirp->inode->dir == NULL) { |
| 9932 | ldout(cct, 0) << " dir is closed, so we should return" << dendl; |
| 9933 | return -EAGAIN; |
| 9934 | } |
| 9935 | |
| 9936 | // the content of readdir_cache may change after _getattr() |
| 9937 | if (idx >= dir->readdir_cache.size() || dir->readdir_cache[idx] != dn) |
| 9938 | return -EAGAIN; |
| 9939 | |
| 9940 | struct ceph_statx stx; |
| 9941 | struct dirent de; |
| 9942 | fill_statx(dn->inode, caps, &stx); |
nothing calls this directly
no test coverage detected