summaryrefslogtreecommitdiffstats
path: root/src/libcephfs.cc
diff options
context:
space:
mode:
authorIgor Fedotov <ifedotov@croit.io>2021-06-24 13:27:53 +0200
committerIgor Fedotov <igor.fedotov@croit.io>2023-04-10 14:38:40 +0200
commite04b10f3f282a3eebc7223e76249fe2d1224eabc (patch)
treeb07588eaf5eed7bfbf5949a0d50d7f7c3a788ed7 /src/libcephfs.cc
parentMerge pull request #50829 from zdover23/wip-doc-2023-04-02-rados-operations-h... (diff)
downloadceph-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.cc120
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)
{