diff options
author | Igor Fedotov <ifedotov@croit.io> | 2021-06-24 13:27:53 +0200 |
---|---|---|
committer | Igor Fedotov <igor.fedotov@croit.io> | 2023-04-10 14:38:40 +0200 |
commit | e04b10f3f282a3eebc7223e76249fe2d1224eabc (patch) | |
tree | b07588eaf5eed7bfbf5949a0d50d7f7c3a788ed7 /src/libcephfs.cc | |
parent | Merge pull request #50829 from zdover23/wip-doc-2023-04-02-rados-operations-h... (diff) | |
download | ceph-e04b10f3f282a3eebc7223e76249fe2d1224eabc.tar.xz ceph-e04b10f3f282a3eebc7223e76249fe2d1224eabc.zip |
cephfs: imlplement readdir_snapdiff API
Signed-off-by: Denis Barahtanov <denis.barahtanov@croit.io>
Signed-off-by: Igor Fedotov <igor.fedotov@croit.io>
Diffstat (limited to 'src/libcephfs.cc')
-rw-r--r-- | src/libcephfs.cc | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/libcephfs.cc b/src/libcephfs.cc index 99da0c5c5c8..51e73efdb65 100644 --- a/src/libcephfs.cc +++ b/src/libcephfs.cc @@ -19,6 +19,7 @@ #include "auth/Crypto.h" #include "client/Client.h" +#include "client/Inode.h" #include "librados/RadosClient.h" #include "common/async/context_pool.h" #include "common/ceph_argparse.h" @@ -28,6 +29,7 @@ #include "mon/MonClient.h" #include "include/str_list.h" #include "include/stringify.h" +#include "include/object.h" #include "messages/MMonMap.h" #include "msg/Messenger.h" #include "include/ceph_assert.h" @@ -687,6 +689,124 @@ extern "C" int ceph_readdirplus_r(struct ceph_mount_info *cmount, struct ceph_di return cmount->get_client()->readdirplus_r(reinterpret_cast<dir_result_t*>(dirp), de, stx, want, flags, out); } +extern "C" int ceph_open_snapdiff(struct ceph_mount_info* cmount, + const char* root_path, + const char* rel_path, + const char* snap1, + const char* snap2, + struct ceph_snapdiff_info* out) +{ + if (!cmount->is_mounted()) { + /* we set errno to signal errors. */ + errno = ENOTCONN; + return -errno; + } + if (!out || !root_path || !rel_path || + !snap1 || !*snap1 || !snap2 || !*snap2) { + errno = EINVAL; + return -errno; + } + out->cmount = cmount; + out->dir1 = out->dir_aux = nullptr; + + char full_path1[PATH_MAX]; + char snapdir[PATH_MAX]; + cmount->conf_get("client_snapdir", snapdir, sizeof(snapdir) - 1); + int n = snprintf(full_path1, PATH_MAX, + "%s/%s/%s/%s", root_path, snapdir, snap1, rel_path); + if (n < 0 || n == PATH_MAX) { + errno = ENAMETOOLONG; + return -errno; + } + char full_path2[PATH_MAX]; + n = snprintf(full_path2, PATH_MAX, + "%s/%s/%s/%s", root_path, snapdir, snap2, rel_path); + if (n < 0 || n == PATH_MAX) { + errno = ENAMETOOLONG; + return -errno; + } + + int r = ceph_opendir(cmount, full_path1, &(out->dir1)); + if (r != 0) { + //it's OK to have one of the snap paths absent - attempting another one + r = ceph_opendir(cmount, full_path2, &(out->dir1)); + if (r != 0) { + // both snaps are absent, giving up + errno = ENOENT; + return -errno; + } + std::swap(snap1, snap2); // will use snap1 to learn snap_other below + } else { + // trying to open second snapshot to learn snapid and + // get the entry loaded into the client cache if any. + r = ceph_opendir(cmount, full_path2, &(out->dir_aux)); + //paranoic, rely on this value below + out->dir_aux = r == 0 ? out->dir_aux : nullptr; + } + if (!out->dir_aux) { + // now trying to learn the second snapshot's id by using snapshot's root + n = snprintf(full_path2, PATH_MAX, + "%s/%s/%s", root_path, snapdir, snap2); + ceph_assert(n > 0 && n < PATH_MAX); //we've already checked above + //that longer string fits. + // Hence unlikely to assert + r = ceph_opendir(cmount, full_path2, &(out->dir_aux)); + if (r != 0) { + goto close_err; + } + } + return 0; + +close_err: + ceph_close_snapdiff(out); + return r; +} + +extern "C" int ceph_readdir_snapdiff(struct ceph_snapdiff_info* snapdiff, + struct ceph_snapdiff_entry_t* out) +{ + if (!snapdiff->cmount->is_mounted()) { + /* also sets errno to signal errors. */ + errno = ENOTCONN; + return -errno; + } + dir_result_t* d1 = reinterpret_cast<dir_result_t*>(snapdiff->dir1); + dir_result_t* d2 = reinterpret_cast<dir_result_t*>(snapdiff->dir_aux); + if (!d1 || !d2 || !d1->inode || !d2->inode) { + errno = EINVAL; + return -errno; + } + snapid_t snapid; + int r = snapdiff->cmount->get_client()->readdir_snapdiff( + d1, + d2->inode->snapid, + &(out->dir_entry), + &snapid); + if (r >= 0) { + // converting snapid_t to uint64_t to avoid snapid_t exposure + out->snapid = snapid; + } + return r; +} + +extern "C" int ceph_close_snapdiff(struct ceph_snapdiff_info* snapdiff) +{ + if (!snapdiff->cmount || !snapdiff->cmount->is_mounted()) { + /* also sets errno to signal errors. */ + errno = ENOTCONN; + return -errno; + } + if (snapdiff->dir_aux) { + ceph_closedir(snapdiff->cmount, snapdiff->dir_aux); + } + if (snapdiff->dir1) { + ceph_closedir(snapdiff->cmount, snapdiff->dir1); + } + snapdiff->cmount = nullptr; + snapdiff->dir1 = snapdiff->dir_aux = nullptr; + return 0; +} + extern "C" int ceph_getdents(struct ceph_mount_info *cmount, struct ceph_dir_result *dirp, char *buf, int buflen) { |