summaryrefslogtreecommitdiffstats
path: root/src/cls
diff options
context:
space:
mode:
authorxinxin shu <xinxin.shu@intel.com>2015-08-20 07:38:34 +0200
committerxinxin shu <xinxin.shu@intel.com>2015-09-01 09:50:11 +0200
commitbd80473405fe139cdf65b8c76d7a4067de63d098 (patch)
treef70f2b25e135b9501afc4057263a67fe8cd40d53 /src/cls
parentMerge pull request #5493 from dachary/wip-10887-shec (diff)
downloadceph-bd80473405fe139cdf65b8c76d7a4067de63d098.tar.xz
ceph-bd80473405fe139cdf65b8c76d7a4067de63d098.zip
add snapshot rename methods in cls_rbd
Signed-off-by: xinxin shu <xinxin.shu@intel.com>
Diffstat (limited to 'src/cls')
-rw-r--r--src/cls/rbd/cls_rbd.cc181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc
index 74af0a27329..5e98d3ff4f7 100644
--- a/src/cls/rbd/cls_rbd.cc
+++ b/src/cls/rbd/cls_rbd.cc
@@ -85,6 +85,7 @@ cls_method_handle_t h_get_object_prefix;
cls_method_handle_t h_get_snapshot_name;
cls_method_handle_t h_snapshot_add;
cls_method_handle_t h_snapshot_remove;
+cls_method_handle_t h_snapshot_rename;
cls_method_handle_t h_get_all_features;
cls_method_handle_t h_copyup;
cls_method_handle_t h_get_id;
@@ -108,6 +109,7 @@ cls_method_handle_t h_metadata_get;
cls_method_handle_t h_old_snapshots_list;
cls_method_handle_t h_old_snapshot_add;
cls_method_handle_t h_old_snapshot_remove;
+cls_method_handle_t h_old_snapshot_rename;
#define RBD_MAX_KEYS_READ 64
#define RBD_SNAP_KEY_PREFIX "snapshot_"
@@ -1560,6 +1562,83 @@ int snapshot_add(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
return 0;
}
+
+/**
+ * rename snapshot .
+ *
+ * Input:
+ * @param src_snap_id old snap id of the snapshot (snapid_t)
+ * @param dst_snap_name new name of the snapshot (string)
+ *
+ * Output:
+ * @returns 0 on success, negative error code on failure.
+ */
+int snapshot_rename(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+ bufferlist snap_namebl, snap_idbl;
+ snapid_t src_snap_id;
+ string src_snap_key,dst_snap_name;
+ cls_rbd_snap snap_meta;
+ int r;
+
+ try {
+ bufferlist::iterator iter = in->begin();
+ ::decode(src_snap_id, iter);
+ ::decode(dst_snap_name, iter);
+ } catch (const buffer::error &err) {
+ return -EINVAL;
+ }
+
+ CLS_LOG(20, "snapshot_rename id=%llu dst_name=%s", (unsigned long long)src_snap_id.val,
+ dst_snap_name.c_str());
+
+ int max_read = RBD_MAX_KEYS_READ;
+ string last_read = RBD_SNAP_KEY_PREFIX;
+ do {
+ map<string, bufferlist> vals;
+ r = cls_cxx_map_get_vals(hctx, last_read, RBD_SNAP_KEY_PREFIX,
+ max_read, &vals);
+ if (r < 0)
+ return r;
+
+ for (map<string, bufferlist>::iterator it = vals.begin();
+ it != vals.end(); ++it) {
+ bufferlist::iterator iter = it->second.begin();
+ try {
+ ::decode(snap_meta, iter);
+ } catch (const buffer::error &err) {
+ CLS_ERR("error decoding snapshot metadata for snap : %s",
+ dst_snap_name.c_str());
+ return -EIO;
+ }
+ if (dst_snap_name == snap_meta.name) {
+ CLS_LOG(20, "snap_name %s matches existing snap with snap id = %llu ",
+ dst_snap_name.c_str(), (unsigned long long)snap_meta.id.val);
+ return -EEXIST;
+ }
+ }
+ if (!vals.empty())
+ last_read = vals.rbegin()->first;
+ } while (r == RBD_MAX_KEYS_READ);
+
+ key_from_snap_id(src_snap_id, &src_snap_key);
+ r = read_key(hctx, src_snap_key, &snap_meta);
+ if (r == -ENOENT) {
+ CLS_LOG(20, "cannot find existing snap with snap id = %llu ", (unsigned long long)src_snap_id);
+ return r;
+ }
+ snap_meta.name = dst_snap_name;
+ bufferlist snap_metabl;
+ ::encode(snap_meta, snap_metabl);
+
+ r = cls_cxx_map_set_val(hctx, src_snap_key, &snap_metabl);
+ if (r < 0) {
+ CLS_ERR("error writing snapshot metadata: %d", r);
+ return r;
+ }
+
+ return 0;
+}
/**
* Removes a snapshot from an rbd header.
*
@@ -2721,6 +2800,102 @@ int old_snapshot_remove(cls_method_context_t hctx, bufferlist *in, bufferlist *o
return 0;
}
+/**
+ * rename snapshot of old format.
+ *
+ * Input:
+ * @param src_snap_id old snap id of the snapshot (snapid_t)
+ * @param dst_snap_name new name of the snapshot (string)
+ *
+ * Output:
+ * @returns 0 on success, negative error code on failure.
+*/
+int old_snapshot_rename(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+ bufferlist bl;
+ struct rbd_obj_header_ondisk *header;
+ bufferlist newbl;
+ bufferptr header_bp(sizeof(*header));
+ snapid_t src_snap_id;
+ const char *dst_snap_name;
+ string dst;
+
+ int rc = snap_read_header(hctx, bl);
+ if (rc < 0)
+ return rc;
+
+ header = (struct rbd_obj_header_ondisk *)bl.c_str();
+
+ int snaps_id_ofs = sizeof(*header);
+ int names_ofs = snaps_id_ofs + sizeof(rbd_obj_snap_ondisk) * header->snap_count;
+ const char *snap_names = ((char *)header) + names_ofs;
+ const char *orig_names = snap_names;
+ const char *end = snap_names + header->snap_names_len;
+ bufferlist::iterator iter = in->begin();
+ unsigned i;
+ bool found = false;
+
+ try {
+ ::decode(src_snap_id, iter);
+ ::decode(dst, iter);
+ } catch (const buffer::error &err) {
+ return -EINVAL;
+ }
+ dst_snap_name = dst.c_str();
+
+ const char *cur_snap_name;
+ for (cur_snap_name = snap_names; cur_snap_name < end;
+ cur_snap_name += strlen(cur_snap_name) + 1) {
+ if (strcmp(cur_snap_name, dst_snap_name) == 0)
+ return -EEXIST;
+ }
+ if (cur_snap_name > end)
+ return -EIO;
+ for (i = 0; i < header->snap_count; i++) {
+ if (src_snap_id == header->snaps[i].id) {
+ found = true;
+ break;
+ }
+ snap_names += strlen(snap_names) + 1;
+ }
+ if (!found) {
+ CLS_ERR("couldn't find snap %llu\n", (unsigned long long)src_snap_id.val);
+ return -ENOENT;
+ }
+
+ CLS_LOG(20, "rename snap with snap id %llu to dest name %s", (unsigned long long)src_snap_id.val, dst_snap_name);
+ header->snap_names_len = header->snap_names_len - strlen(snap_names) + dst.length();
+
+ bufferptr new_names_bp(header->snap_names_len);
+ bufferptr new_snaps_bp(sizeof(header->snaps[0]) * header->snap_count);
+
+ if (header->snap_count) {
+ int names_len = 0;
+ CLS_LOG(20, "i=%d\n", i);
+ if (i > 0) {
+ names_len = snap_names - orig_names;
+ memcpy(new_names_bp.c_str(), orig_names, names_len);
+ }
+ strcpy(new_names_bp.c_str() + names_len, dst_snap_name);
+ names_len += strlen(dst_snap_name) + 1;
+ snap_names += strlen(snap_names) + 1;
+ if (i < header->snap_count) {
+ memcpy(new_names_bp.c_str() + names_len, snap_names , end - snap_names);
+ }
+ memcpy(new_snaps_bp.c_str(), header->snaps, sizeof(header->snaps[0]) * header->snap_count);
+ }
+
+ memcpy(header_bp.c_str(), header, sizeof(*header));
+ newbl.push_back(header_bp);
+ newbl.push_back(new_snaps_bp);
+ newbl.push_back(new_names_bp);
+
+ rc = cls_cxx_write_full(hctx, &newbl);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
void __cls_init()
{
@@ -2757,6 +2932,9 @@ void __cls_init()
cls_register_cxx_method(h_class, "snapshot_remove",
CLS_METHOD_RD | CLS_METHOD_WR,
snapshot_remove, &h_snapshot_remove);
+ cls_register_cxx_method(h_class, "snapshot_rename",
+ CLS_METHOD_RD | CLS_METHOD_WR,
+ snapshot_rename, &h_snapshot_rename);
cls_register_cxx_method(h_class, "get_all_features",
CLS_METHOD_RD,
get_all_features, &h_get_all_features);
@@ -2872,6 +3050,9 @@ void __cls_init()
cls_register_cxx_method(h_class, "snap_remove",
CLS_METHOD_RD | CLS_METHOD_WR,
old_snapshot_remove, &h_old_snapshot_remove);
+ cls_register_cxx_method(h_class, "snap_rename",
+ CLS_METHOD_RD | CLS_METHOD_WR,
+ old_snapshot_rename, &h_old_snapshot_rename);
return;
}