return ret;
}
+int Client::get_snap_info(const char *path, const UserPerm &perms, SnapInfo *snap_info) {
+ RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
+ if (!mref_reader.is_state_satisfied()) {
+ return -ENOTCONN;
+ }
+
+ std::unique_lock locker(client_lock);
+ InodeRef in;
+ int r = Client::path_walk(path, &in, perms, true);
+ if (r < 0) {
+ return r;
+ }
+
+ if (in->snapid == CEPH_NOSNAP) {
+ return -EINVAL;
+ }
+
+ snap_info->id = in->snapid;
+ snap_info->metadata = in->snap_metadata;
+ return 0;
+}
+
int Client::ll_statfs(Inode *in, struct statvfs *stbuf, const UserPerm& perms)
{
/* Since the only thing this does is wrap a call to statfs, and
Client *m_client;
};
+ // snapshot info returned via get_snap_info(). nothing to do
+ // with SnapInfo on the MDS.
+ struct SnapInfo {
+ snapid_t id;
+ std::map<std::string, std::string> metadata;
+ };
+
Client(Messenger *m, MonClient *mc, Objecter *objecter_);
Client(const Client&) = delete;
Client(const Client&&) = delete;
int sync_fs();
int64_t drop_caches();
+ int get_snap_info(const char *path, const UserPerm &perms, SnapInfo *snap_info);
+
// hpc lazyio
int lazyio(int fd, int enable);
int lazyio_propagate(int fd, loff_t offset, size_t count);
struct ceph_mount_info;
struct ceph_dir_result;
+// user supplied key,value pair to be associated with a snapshot.
+// callers can supply an array of this struct via ceph_mksnap().
+struct snap_metadata {
+ const char *key;
+ const char *value;
+};
+
+struct snap_info {
+ uint64_t id;
+ size_t nr_snap_metadata;
+ struct snap_metadata *snap_metadata;
+};
+
/* setattr mask bits */
#ifndef CEPH_SETATTR_MODE
# define CEPH_SETATTR_MODE 1
*/
int ceph_mkdir(struct ceph_mount_info *cmount, const char *path, mode_t mode);
+/**
+ * Create a snapshot
+ *
+ * @param cmount the ceph mount handle to use for making the directory.
+ * @param path the path of the directory to create snapshot. This must be either an
+ * absolute path or a relative path off of the current working directory.
+ * @param name snapshot name
+ * @param mode the permissions the directory should have once created.
+ * @param snap_metadata array of snap metadata structs
+ * @param nr_snap_metadata number of snap metadata struct entries
+ * @returns 0 on success or a negative return code on error.
+ */
+int ceph_mksnap(struct ceph_mount_info *cmount, const char *path, const char *name,
+ mode_t mode, struct snap_metadata *snap_metadata, size_t nr_snap_metadata);
+
+/**
+ * Remove a snapshot
+ *
+ * @param cmount the ceph mount handle to use for making the directory.
+ * @param path the path of the directory to create snapshot. This must be either an
+ * absolute path or a relative path off of the current working directory.
+ * @param name snapshot name
+ * @returns 0 on success or a negative return code on error.
+ */
+int ceph_rmsnap(struct ceph_mount_info *cmount, const char *path, const char *name);
+
/**
* Create multiple directories at once.
*
*/
void ceph_ll_register_callbacks(struct ceph_mount_info *cmount,
struct ceph_client_callback_args *args);
+
+/**
+ * Get snapshot info
+ *
+ * @param cmount the ceph mount handle to use for making the directory.
+ * @param path the path of the snapshot. This must be either an
+ * absolute path or a relative path off of the current working directory.
+ * @returns 0 on success or a negative return code on error.
+ */
+int ceph_get_snap_info(struct ceph_mount_info *cmount,
+ const char *path, struct snap_info *snap_info);
+
+/**
+ * Free snapshot info buffers
+ *
+ * @param snap_info snapshot info struct (fetched via call to ceph_get_snap_info()).
+ */
+void ceph_free_snap_info_buffer(struct snap_info *snap_info);
#ifdef __cplusplus
}
#endif
return cmount->get_client()->mkdir(path, mode, cmount->default_perms);
}
+extern "C" int ceph_mksnap(struct ceph_mount_info *cmount, const char *path, const char *name,
+ mode_t mode, struct snap_metadata *snap_metadata, size_t nr_snap_metadata)
+{
+ if (!cmount->is_mounted())
+ return -ENOTCONN;
+ size_t i = 0;
+ std::map<std::string, std::string> metadata;
+ while (i < nr_snap_metadata) {
+ metadata.emplace(snap_metadata[i].key, snap_metadata[i].value);
+ ++i;
+ }
+ return cmount->get_client()->mksnap(path, name, cmount->default_perms, mode, metadata);
+}
+
+extern "C" int ceph_rmsnap(struct ceph_mount_info *cmount, const char *path, const char *name)
+{
+ if (!cmount->is_mounted())
+ return -ENOTCONN;
+ return cmount->get_client()->rmsnap(path, name, cmount->default_perms);
+}
+
extern "C" int ceph_mkdirs(struct ceph_mount_info *cmount, const char *path, mode_t mode)
{
if (!cmount->is_mounted())
struct ceph_client_callback_args *args)
{
cmount->get_client()->ll_register_callbacks(args);
+
+}
+
+
+extern "C" int ceph_get_snap_info(struct ceph_mount_info *cmount,
+ const char *path, struct snap_info *snap_info) {
+ Client::SnapInfo info;
+ int r = cmount->get_client()->get_snap_info(path, cmount->default_perms, &info);
+ if (r < 0) {
+ return r;
+ }
+
+ size_t i = 0;
+ auto nr_metadata = info.metadata.size();
+
+ snap_info->id = info.id.val;
+ snap_info->nr_snap_metadata = nr_metadata;
+ if (nr_metadata) {
+ snap_info->snap_metadata = (struct snap_metadata *)calloc(nr_metadata, sizeof(struct snap_metadata));
+ if (!snap_info->snap_metadata) {
+ return -ENOMEM;
+ }
+
+ // fill with key, value pairs
+ for (auto &[key, value] : info.metadata) {
+ // len(key) + '\0' + len(value) + '\0'
+ char *kvp = (char *)malloc(key.size() + value.size() + 2);
+ if (!kvp) {
+ break;
+ }
+ char *_key = kvp;
+ char *_value = kvp + key.size() + 1;
+
+ memcpy(_key, key.c_str(), key.size());
+ _key[key.size()] = '\0';
+ memcpy(_value, value.c_str(), value.size());
+ _value[value.size()] = '\0';
+
+ snap_info->snap_metadata[i].key = _key;
+ snap_info->snap_metadata[i].value = _value;
+ ++i;
+ }
+ }
+
+ if (nr_metadata && i != nr_metadata) {
+ ceph_free_snap_info_buffer(snap_info);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+extern "C" void ceph_free_snap_info_buffer(struct snap_info *snap_info) {
+ for (size_t i = 0; i < snap_info->nr_snap_metadata; ++i) {
+ free((void *)snap_info->snap_metadata[i].key); // malloc'd memory is key+value composite
+ }
+ free(snap_info->snap_metadata);
}