From: songweibin Date: Sat, 24 Feb 2018 02:39:42 +0000 (+0800) Subject: cls_rbd: add group rename operations to cls_rbd X-Git-Tag: v13.0.2~165^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=164b4da8888693017db68a56b25c9115d1d02eef;p=ceph.git cls_rbd: add group rename operations to cls_rbd Signed-off-by: songweibin --- diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 0cb447f43547..21e05b2a590a 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -5107,6 +5107,86 @@ int mirror_image_map_remove(cls_method_context_t hctx, bufferlist *in, return 0; } +/*********************** methods for rbd_group_directory ***********************/ + +int dir_add(cls_method_context_t hctx, + const string &name, const string &id, + bool check_for_unique_id) +{ + if (!name.size() || !is_valid_id(id)) { + CLS_ERR("invalid group name '%s' or id '%s'", + name.c_str(), id.c_str()); + return -EINVAL; + } + + CLS_LOG(20, "dir_add name=%s id=%s", name.c_str(), id.c_str()); + + string name_key = dir_key_for_name(name); + string id_key = dir_key_for_id(id); + string tmp; + int r = read_key(hctx, name_key, &tmp); + if (r != -ENOENT) { + CLS_LOG(10, "name already exists"); + return -EEXIST; + } + r = read_key(hctx, id_key, &tmp); + if (r != -ENOENT && check_for_unique_id) { + CLS_LOG(10, "id already exists"); + return -EBADF; + } + bufferlist id_bl, name_bl; + encode(id, id_bl); + encode(name, name_bl); + map omap_vals; + omap_vals[name_key] = id_bl; + omap_vals[id_key] = name_bl; + return cls_cxx_map_set_vals(hctx, &omap_vals); +} + +int dir_remove(cls_method_context_t hctx, + const string &name, const string &id) +{ + CLS_LOG(20, "dir_remove name=%s id=%s", name.c_str(), id.c_str()); + + string name_key = dir_key_for_name(name); + string id_key = dir_key_for_id(id); + string stored_name, stored_id; + + int r = read_key(hctx, name_key, &stored_id); + if (r < 0) { + if (r != -ENOENT) + CLS_ERR("error reading name to id mapping: %s", cpp_strerror(r).c_str()); + return r; + } + r = read_key(hctx, id_key, &stored_name); + if (r < 0) { + if (r != -ENOENT) + CLS_ERR("error reading id to name mapping: %s", cpp_strerror(r).c_str()); + return r; + } + + // check if this op raced with a rename + if (stored_name != name || stored_id != id) { + CLS_ERR("stored name '%s' and id '%s' do not match args '%s' and '%s'", + stored_name.c_str(), stored_id.c_str(), name.c_str(), id.c_str()); + return -ESTALE; + } + + r = cls_cxx_map_remove_key(hctx, name_key); + if (r < 0) { + CLS_ERR("error removing name: %s", cpp_strerror(r).c_str()); + return r; + } + + r = cls_cxx_map_remove_key(hctx, id_key); + if (r < 0) { + CLS_ERR("error removing id: %s", cpp_strerror(r).c_str()); + return r; + } + + return 0; +} + /** * List groups from the directory. * @@ -5199,34 +5279,37 @@ int group_dir_add(cls_method_context_t hctx, bufferlist *in, bufferlist *out) return -EINVAL; } - if (!name.size() || !is_valid_id(id)) { - CLS_ERR("invalid group name '%s' or id '%s'", - name.c_str(), id.c_str()); + return dir_add(hctx, name, id, true); +} + +/** + * Rename a group to the directory. + * + * Input: + * @param src original name of the group (std::string) + * @param dest new name of the group (std::string) + * @param id the id of the group (std::string) + * + * Output: + * @return 0 on success, negative error code on failure + */ +int group_dir_rename(cls_method_context_t hctx, bufferlist *in, bufferlist *out) +{ + string src, dest, id; + try { + bufferlist::iterator iter = in->begin(); + decode(src, iter); + decode(dest, iter); + decode(id, iter); + } catch (const buffer::error &err) { return -EINVAL; } - CLS_LOG(20, "group_dir_add name=%s id=%s", name.c_str(), id.c_str()); + int r = dir_remove(hctx, src, id); + if (r < 0) + return r; - string tmp; - string name_key = dir_key_for_name(name); - string id_key = dir_key_for_id(id); - r = read_key(hctx, name_key, &tmp); - if (r != -ENOENT) { - CLS_LOG(10, "name already exists"); - return -EEXIST; - } - r = read_key(hctx, id_key, &tmp); - if (r != -ENOENT) { - CLS_LOG(10, "id already exists"); - return -EBADF; - } - bufferlist id_bl, name_bl; - encode(id, id_bl); - encode(name, name_bl); - map omap_vals; - omap_vals[name_key] = id_bl; - omap_vals[id_key] = name_bl; - return cls_cxx_map_set_vals(hctx, &omap_vals); + return dir_add(hctx, dest, id, false); } /** @@ -5250,45 +5333,7 @@ int group_dir_remove(cls_method_context_t hctx, bufferlist *in, bufferlist *out) return -EINVAL; } - CLS_LOG(20, "group_dir_remove name=%s id=%s", name.c_str(), id.c_str()); - - string stored_name, stored_id; - string name_key = dir_key_for_name(name); - string id_key = dir_key_for_id(id); - - int r = read_key(hctx, name_key, &stored_id); - if (r < 0) { - if (r != -ENOENT) - CLS_ERR("error reading name to id mapping: %s", cpp_strerror(r).c_str()); - return r; - } - r = read_key(hctx, id_key, &stored_name); - if (r < 0) { - if (r != -ENOENT) - CLS_ERR("error reading id to name mapping: %s", cpp_strerror(r).c_str()); - return r; - } - - // check if this op raced with a rename - if (stored_name != name || stored_id != id) { - CLS_ERR("stored name '%s' and id '%s' do not match args '%s' and '%s'", - stored_name.c_str(), stored_id.c_str(), name.c_str(), id.c_str()); - return -ESTALE; - } - - r = cls_cxx_map_remove_key(hctx, name_key); - if (r < 0) { - CLS_ERR("error removing name: %s", cpp_strerror(r).c_str()); - return r; - } - - r = cls_cxx_map_remove_key(hctx, id_key); - if (r < 0) { - CLS_ERR("error removing id: %s", cpp_strerror(r).c_str()); - return r; - } - - return 0; + return dir_remove(hctx, name, id); } /** @@ -6119,6 +6164,7 @@ CLS_INIT(rbd) cls_method_handle_t h_group_dir_list; cls_method_handle_t h_group_dir_add; cls_method_handle_t h_group_dir_remove; + cls_method_handle_t h_group_dir_rename; cls_method_handle_t h_group_image_remove; cls_method_handle_t h_group_image_list; cls_method_handle_t h_group_image_set; @@ -6407,6 +6453,9 @@ CLS_INIT(rbd) cls_register_cxx_method(h_class, "group_dir_remove", CLS_METHOD_RD | CLS_METHOD_WR, group_dir_remove, &h_group_dir_remove); + cls_register_cxx_method(h_class, "group_dir_rename", + CLS_METHOD_RD | CLS_METHOD_WR, + group_dir_rename, &h_group_dir_rename); cls_register_cxx_method(h_class, "group_image_remove", CLS_METHOD_RD | CLS_METHOD_WR, group_image_remove, &h_group_image_remove); diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index 67cc5f8e1d16..c3de9266a0ca 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -2127,8 +2127,8 @@ namespace librbd { // Consistency groups functions int group_dir_list(librados::IoCtx *ioctx, const std::string &oid, - const std::string &start, uint64_t max_return, - map *cgs) + const std::string &start, uint64_t max_return, + map *cgs) { bufferlist in, out; encode(start, in); @@ -2148,7 +2148,7 @@ namespace librbd { } int group_dir_add(librados::IoCtx *ioctx, const std::string &oid, - const std::string &name, const std::string &id) + const std::string &name, const std::string &id) { bufferlist in, out; encode(name, in); @@ -2156,8 +2156,19 @@ namespace librbd { return ioctx->exec(oid, "rbd", "group_dir_add", in, out); } + int group_dir_rename(librados::IoCtx *ioctx, const std::string &oid, + const std::string &src, const std::string &dest, + const std::string &id) + { + bufferlist in, out; + encode(src, in); + encode(dest, in); + encode(id, in); + return ioctx->exec(oid, "rbd", "group_dir_rename", in, out); + } + int group_dir_remove(librados::IoCtx *ioctx, const std::string &oid, - const std::string &name, const std::string &id) + const std::string &name, const std::string &id) { bufferlist in, out; encode(name, in); diff --git a/src/cls/rbd/cls_rbd_client.h b/src/cls/rbd/cls_rbd_client.h index 4d5ba7c5792c..7cedcb6197a8 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -446,12 +446,15 @@ namespace librbd { // Consistency groups functions int group_dir_list(librados::IoCtx *ioctx, const std::string &oid, - const std::string &start, uint64_t max_return, - map *groups); + const std::string &start, uint64_t max_return, + map *groups); int group_dir_add(librados::IoCtx *ioctx, const std::string &oid, - const std::string &name, const std::string &id); + const std::string &name, const std::string &id); + int group_dir_rename(librados::IoCtx *ioctx, const std::string &oid, + const std::string &src, const std::string &dest, + const std::string &id); int group_dir_remove(librados::IoCtx *ioctx, const std::string &oid, - const std::string &name, const std::string &id); + const std::string &name, const std::string &id); int group_image_remove(librados::IoCtx *ioctx, const std::string &oid, const cls::rbd::GroupImageSpec &spec); int group_image_list(librados::IoCtx *ioctx, const std::string &oid, diff --git a/src/test/cls_rbd/test_cls_rbd.cc b/src/test/cls_rbd/test_cls_rbd.cc index 3f6383a7cfbf..8558c97f88c8 100644 --- a/src/test/cls_rbd/test_cls_rbd.cc +++ b/src/test/cls_rbd/test_cls_rbd.cc @@ -1966,6 +1966,34 @@ TEST_F(TestClsRbd, dir_add_already_existing) { ASSERT_EQ(-EEXIST, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id)); } +TEST_F(TestClsRbd, group_dir_rename) { + librados::IoCtx ioctx; + ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx)); + ioctx.remove(RBD_GROUP_DIRECTORY); + + string group_id = "cgid"; + string src_name = "cgnamesrc"; + string dest_name = "cgnamedest"; + add_group_to_dir(ioctx, group_id, src_name); + + ASSERT_EQ(0, group_dir_rename(&ioctx, RBD_GROUP_DIRECTORY, + src_name, dest_name, group_id)); + map cgs; + ASSERT_EQ(0, group_dir_list(&ioctx, RBD_GROUP_DIRECTORY, "", 10, &cgs)); + ASSERT_EQ(1U, cgs.size()); + auto it = cgs.begin(); + ASSERT_EQ(group_id, it->second); + ASSERT_EQ(dest_name, it->first); + + // destination group name existing + ASSERT_EQ(-EEXIST, group_dir_rename(&ioctx, RBD_GROUP_DIRECTORY, + dest_name, dest_name, group_id)); + ASSERT_EQ(0, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, dest_name, group_id)); + // source group name missing + ASSERT_EQ(-ENOENT, group_dir_rename(&ioctx, RBD_GROUP_DIRECTORY, + dest_name, src_name, group_id)); +} + TEST_F(TestClsRbd, group_dir_remove) { librados::IoCtx ioctx; ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));