| 10467 | } |
| 10468 | |
| 10469 | int Client::readdir_snapdiff(dir_result_t* d1, snapid_t snap2, |
| 10470 | struct dirent* out_de, |
| 10471 | snapid_t* out_snap) |
| 10472 | { |
| 10473 | if (!d1 || !d1->inode || d1->inode->snapid == snap2) { |
| 10474 | lderr(cct) << __func__ << " invalid parameters: " |
| 10475 | << " d1:" << d1 |
| 10476 | << " d1->inode:" << (d1 ? d1->inode : nullptr) |
| 10477 | << " snap2 id :" << snap2 |
| 10478 | << dendl; |
| 10479 | errno = EINVAL; |
| 10480 | return -errno; |
| 10481 | } |
| 10482 | |
| 10483 | auto& de = d1->de; |
| 10484 | ceph_statx stx; |
| 10485 | single_readdir sr; |
| 10486 | sr.de = &de; |
| 10487 | sr.stx = &stx; |
| 10488 | sr.inode = NULL; |
| 10489 | sr.full = false; |
| 10490 | |
| 10491 | auto fill_snapdiff_cb = [&](dir_result_t* dirp, |
| 10492 | MetaRequest* req, |
| 10493 | InodeRef& diri, |
| 10494 | frag_t fg) { |
| 10495 | filepath path; |
| 10496 | diri->make_nosnap_relative_path(path); |
| 10497 | req->set_filepath(path); |
| 10498 | req->set_inode(diri.get()); |
| 10499 | req->head.args.snapdiff.snap_other = snap2; |
| 10500 | req->head.args.snapdiff.frag = fg; |
| 10501 | req->head.args.snapdiff.flags = CEPH_READDIR_REPLY_BITFLAGS; |
| 10502 | if (dirp->last_name.length()) { |
| 10503 | req->path2.set_path(dirp->last_name); |
| 10504 | } else if (dirp->hash_order()) { |
| 10505 | req->head.args.snapdiff.offset_hash = dirp->offset_high(); |
| 10506 | } |
| 10507 | req->dirp = dirp; |
| 10508 | }; |
| 10509 | |
| 10510 | // our callback fills the dirent and sets sr.full=true on first |
| 10511 | // call, and returns -1 the second time around. |
| 10512 | int ret = _readdir_r_cb(CEPH_MDS_OP_READDIR_SNAPDIFF, |
| 10513 | d1, |
| 10514 | _readdir_single_dirent_cb, |
| 10515 | fill_snapdiff_cb, |
| 10516 | (void*)&sr, |
| 10517 | 0, |
| 10518 | AT_STATX_DONT_SYNC, |
| 10519 | false, |
| 10520 | true); |
| 10521 | if (ret < -1) { |
| 10522 | lderr(cct) << __func__ << " error: " |
| 10523 | << cpp_strerror(ret) |
| 10524 | << dendl; |
| 10525 | errno = -ret; // this sucks. |
| 10526 | return ret; |
no test coverage detected