From: Sage Weil Date: Thu, 11 Jan 2018 21:53:55 +0000 (-0600) Subject: Merge branch 'wip-names!-in!-space!' of git://github.com/adamemerson/ceph X-Git-Tag: v13.0.2~540 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=4da29a07cfc4c7c3e6fb499f4f7ddac307292ca0;p=ceph.git Merge branch 'wip-names!-in!-space!' of git://github.com/adamemerson/ceph Reviewed-by: Jesse Williamson # Conflicts: # src/cls/rbd/cls_rbd.cc # src/cls/rbd/cls_rbd_types.cc --- 4da29a07cfc4c7c3e6fb499f4f7ddac307292ca0 diff --cc src/cls/rbd/cls_rbd.cc index e4c6735f9635f,2177d86822803..e95c31c2f6508 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@@ -5075,240 -5097,6 +5075,240 @@@ int image_get_group(cls_method_context_ return 0; } + +namespace group { + +static int group_snap_list(cls_method_context_t hctx, + cls::rbd::GroupSnapshot start_after, + uint64_t max_return, + std::vector *group_snaps) +{ + int max_read = RBD_MAX_KEYS_READ; + std::map vals; + string last_read = snap_key(start_after.id); + + group_snaps->clear(); + + bool more; + do { + int r = cls_cxx_map_get_vals(hctx, last_read, + RBD_GROUP_SNAP_KEY_PREFIX, + max_read, &vals, &more); + if (r < 0) + return r; + + for (map::iterator it = vals.begin(); + it != vals.end() && group_snaps->size() < max_return; ++it) { + + bufferlist::iterator iter = it->second.begin(); + cls::rbd::GroupSnapshot snap; + try { - ::decode(snap, iter); ++ decode(snap, iter); + } catch (const buffer::error &err) { + CLS_ERR("error decoding snapshot: %s", it->first.c_str()); + return -EIO; + } + CLS_LOG(20, "Discovered snapshot %s %s", + snap.name.c_str(), + snap.id.c_str()); + group_snaps->push_back(snap); + } + + } while (more && (group_snaps->size() < max_return)); + + return 0; +} + +static int check_duplicate_snap_name(cls_method_context_t hctx, + std::string snap_name, + std::string snap_id) +{ + const int max_read = 1024; + cls::rbd::GroupSnapshot snap_last; + std::vector page; + + for (;;) { + int r = group_snap_list(hctx, snap_last, max_read, &page); + if (r < 0) { + return r; + } + for (auto& snap: page) { + if (snap.name == snap_name && snap.id != snap_id) { + return -EEXIST; + } + } + + if (page.size() < max_read) { + break; + } + + snap_last = *page.rbegin(); + } + + return 0; +} + +} + +/** + * Save initial snapshot record. + * + * Input: + * @param GroupSnapshot + * + * Output: + * @return 0 on success, negative error code on failure + */ +int group_snap_set(cls_method_context_t hctx, + bufferlist *in, bufferlist *out) +{ + CLS_LOG(20, "group_snap_set"); + cls::rbd::GroupSnapshot group_snap; + try { + bufferlist::iterator iter = in->begin(); - ::decode(group_snap, iter); ++ decode(group_snap, iter); + } catch (const buffer::error &err) { + return -EINVAL; + } + + if (group_snap.name.empty()) { + CLS_ERR("group snapshot name is empty"); + return -EINVAL; + } + if (group_snap.id.empty()) { + CLS_ERR("group snapshot id is empty"); + return -EINVAL; + } + + int r = group::check_duplicate_snap_name(hctx, group_snap.name, + group_snap.id); + if (r < 0) { + return r; + } + + std::string key = group::snap_key(group_snap.id); + if (group_snap.state == cls::rbd::GROUP_SNAPSHOT_STATE_INCOMPLETE) { + bufferlist snap_bl; + r = cls_cxx_map_get_val(hctx, key, &snap_bl); + if (r < 0 && r != -ENOENT) { + return r; + } else if (r >= 0) { + return -EEXIST; + } + } + + bufferlist obl; - ::encode(group_snap, obl); ++ encode(group_snap, obl); + r = cls_cxx_map_set_val(hctx, key, &obl); + return r; +} + +/** + * Remove snapshot record. + * + * Input: + * @param id Snapshot id + * + * Output: + * @return 0 on success, negative error code on failure + */ +int group_snap_remove(cls_method_context_t hctx, + bufferlist *in, bufferlist *out) +{ + CLS_LOG(20, "group_snap_remove"); + std::string snap_id; + try { + bufferlist::iterator iter = in->begin(); - ::decode(snap_id, iter); ++ decode(snap_id, iter); + } catch (const buffer::error &err) { + return -EINVAL; + } + + std::string snap_key = group::snap_key(snap_id); + + CLS_LOG(20, "removing snapshot with key %s", snap_key.c_str()); + int r = cls_cxx_map_remove_key(hctx, snap_key); + return r; +} + +/** + * Get consistency group's snapshot by id. + * + * Input: + * @param snapshot_id the id of the snapshot to look for. + * + * Output: + * @param GroupSnapshot the requested snapshot + * @return 0 on success, negative error code on failure + */ +int group_snap_get_by_id(cls_method_context_t hctx, + bufferlist *in, bufferlist *out) +{ + CLS_LOG(20, "group_snap_get_by_id"); + + std::string snap_id; + try { + bufferlist::iterator iter = in->begin(); - ::decode(snap_id, iter); ++ decode(snap_id, iter); + } catch (const buffer::error &err) { + return -EINVAL; + } + + bufferlist snapbl; + + int r = cls_cxx_map_get_val(hctx, group::snap_key(snap_id), &snapbl); + if (r < 0) { + return r; + } + + cls::rbd::GroupSnapshot group_snap; + bufferlist::iterator iter = snapbl.begin(); + try { - ::decode(group_snap, iter); ++ decode(group_snap, iter); + } catch (const buffer::error &err) { + CLS_ERR("error decoding snapshot: %s", snap_id.c_str()); + return -EIO; + } + - ::encode(group_snap, *out); ++ encode(group_snap, *out); + + return 0; +} + +/** + * List consistency group's snapshots. + * + * Input: + * @param start_after which name to begin listing after + * (use the empty string to start at the beginning) + * @param max_return the maximum number of snapshots to list + * + * Output: + * @param list of snapshots + * @return 0 on success, negative error code on failure + */ +int group_snap_list(cls_method_context_t hctx, + bufferlist *in, bufferlist *out) +{ + CLS_LOG(20, "group_snap_list"); + + cls::rbd::GroupSnapshot start_after; + uint64_t max_return; + try { + bufferlist::iterator iter = in->begin(); - ::decode(start_after, iter); - ::decode(max_return, iter); ++ decode(start_after, iter); ++ decode(max_return, iter); + } catch (const buffer::error &err) { + return -EINVAL; + } + std::vector group_snaps; + group::group_snap_list(hctx, start_after, max_return, &group_snaps); + - ::encode(group_snaps, *out); ++ encode(group_snaps, *out); + + return 0; +} + namespace trash { static const std::string IMAGE_KEY_PREFIX("id_"); diff --cc src/cls/rbd/cls_rbd_client.cc index 693d18bac732d,bdfb17892ac46..68a1d3dab19e1 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@@ -2064,70 -2071,6 +2064,73 @@@ namespace librbd return image_get_group_finish(&iter, group_spec); } + int group_snap_set(librados::IoCtx *ioctx, const std::string &oid, + const cls::rbd::GroupSnapshot &snapshot) + { - ++ using ceph::encode; + bufferlist inbl, outbl; - - ::encode(snapshot, inbl); ++ encode(snapshot, inbl); + int r = ioctx->exec(oid, "rbd", "group_snap_set", inbl, outbl); + return r; + } + + int group_snap_remove(librados::IoCtx *ioctx, const std::string &oid, + const std::string &snap_id) + { ++ using ceph::encode; + bufferlist inbl, outbl; - ::encode(snap_id, inbl); - ++ encode(snap_id, inbl); + return ioctx->exec(oid, "rbd", "group_snap_remove", inbl, outbl); + } + + int group_snap_get_by_id(librados::IoCtx *ioctx, const std::string &oid, + const std::string &snap_id, + cls::rbd::GroupSnapshot *snapshot) + { ++ using ceph::encode; ++ using ceph::decode; + bufferlist inbl, outbl; - ::encode(snap_id, inbl); + ++ encode(snap_id, inbl); + int r = ioctx->exec(oid, "rbd", "group_snap_get_by_id", inbl, outbl); + if (r < 0) { + return r; + } + + bufferlist::iterator iter = outbl.begin(); + try { - ::decode(*snapshot, iter); ++ decode(*snapshot, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + int group_snap_list(librados::IoCtx *ioctx, const std::string &oid, + const cls::rbd::GroupSnapshot &start, + uint64_t max_return, + std::vector *snapshots) + { ++ using ceph::encode; ++ using ceph::decode; + bufferlist inbl, outbl; - ::encode(start, inbl); - ::encode(max_return, inbl); ++ encode(start, inbl); ++ encode(max_return, inbl); + + int r = ioctx->exec(oid, "rbd", "group_snap_list", inbl, outbl); + if (r < 0) { + return r; + } + bufferlist::iterator iter = outbl.begin(); + try { - ::decode(*snapshots, iter); ++ decode(*snapshots, iter); + } catch (const buffer::error &err) { + return -EBADMSG; + } + + return 0; + } + // rbd_trash functions void trash_add(librados::ObjectWriteOperation *op, const std::string &id, diff --cc src/cls/rbd/cls_rbd_types.cc index cbd1aa7d16237,86a2a0d4da070..5c81754f3272b --- a/src/cls/rbd/cls_rbd_types.cc +++ b/src/cls/rbd/cls_rbd_types.cc @@@ -264,15 -264,10 +264,15 @@@ std::string GroupImageSpec::image_key( } } +void GroupImageSpec::generate_test_instances(std::list &o) { + o.push_back(new GroupImageSpec("10152ae8944a", 0)); + o.push_back(new GroupImageSpec("1018643c9869", 3)); +} + void GroupImageStatus::encode(bufferlist &bl) const { ENCODE_START(1, 1, bl); - ::encode(spec, bl); - ::encode(state, bl); + encode(spec, bl); + encode(state, bl); ENCODE_FINISH(bl); } @@@ -299,18 -294,10 +299,18 @@@ void GroupImageStatus::dump(Formatter * f->dump_string("state", state_to_string()); } +void GroupImageStatus::generate_test_instances(std::list &o) { + o.push_back(new GroupImageStatus(GroupImageSpec("10152ae8944a", 0), GROUP_IMAGE_LINK_STATE_ATTACHED)); + o.push_back(new GroupImageStatus(GroupImageSpec("1018643c9869", 3), GROUP_IMAGE_LINK_STATE_ATTACHED)); + o.push_back(new GroupImageStatus(GroupImageSpec("10152ae8944a", 0), GROUP_IMAGE_LINK_STATE_INCOMPLETE)); + o.push_back(new GroupImageStatus(GroupImageSpec("1018643c9869", 3), GROUP_IMAGE_LINK_STATE_INCOMPLETE)); +} + + void GroupSpec::encode(bufferlist &bl) const { ENCODE_START(1, 1, bl); - ::encode(pool_id, bl); - ::encode(group_id, bl); + encode(pool_id, bl); + encode(group_id, bl); ENCODE_FINISH(bl); } @@@ -330,21 -317,18 +330,23 @@@ bool GroupSpec::is_valid() const return (!group_id.empty()) && (pool_id != -1); } +void GroupSpec::generate_test_instances(std::list &o) { + o.push_back(new GroupSpec("10152ae8944a", 0)); + o.push_back(new GroupSpec("1018643c9869", 3)); +} + void GroupSnapshotNamespace::encode(bufferlist& bl) const { - ::encode(group_pool, bl); - ::encode(group_id, bl); - ::encode(group_snapshot_id, bl); + using ceph::encode; + encode(group_pool, bl); + encode(group_id, bl); - encode(snapshot_id, bl); ++ encode(group_snapshot_id, bl); } void GroupSnapshotNamespace::decode(bufferlist::iterator& it) { - ::decode(group_pool, it); - ::decode(group_id, it); - ::decode(group_snapshot_id, it); + using ceph::decode; + decode(group_pool, it); + decode(group_id, it); - decode(snapshot_id, it); ++ decode(group_snapshot_id, it); } void GroupSnapshotNamespace::dump(Formatter *f) const { @@@ -466,67 -451,12 +469,71 @@@ std::ostream& operator<<(std::ostream& return os; } +void ImageSnapshotSpec::encode(bufferlist& bl) const { ++ using ceph::encode; + ENCODE_START(1, 1, bl); - ::encode(pool, bl); - ::encode(image_id, bl); - ::encode(snap_id, bl); ++ encode(pool, bl); ++ encode(image_id, bl); ++ encode(snap_id, bl); + ENCODE_FINISH(bl); +} + +void ImageSnapshotSpec::decode(bufferlist::iterator& it) { ++ using ceph::decode; + DECODE_START(1, it); - ::decode(pool, it); - ::decode(image_id, it); - ::decode(snap_id, it); ++ decode(pool, it); ++ decode(image_id, it); ++ decode(snap_id, it); + DECODE_FINISH(it); +} + +void ImageSnapshotSpec::dump(Formatter *f) const { + f->dump_int("pool", pool); + f->dump_string("image_id", image_id); + f->dump_int("snap_id", snap_id); +} + +void ImageSnapshotSpec::generate_test_instances(std::list &o) { + o.push_back(new ImageSnapshotSpec(0, "myimage", 2)); + o.push_back(new ImageSnapshotSpec(1, "testimage", 7)); +} + +void GroupSnapshot::encode(bufferlist& bl) const { ++ using ceph::encode; + ENCODE_START(1, 1, bl); - ::encode(id, bl); - ::encode(name, bl); - ::encode(state, bl); - ::encode(snaps, bl); ++ encode(id, bl); ++ encode(name, bl); ++ encode(state, bl); ++ encode(snaps, bl); + ENCODE_FINISH(bl); +} + +void GroupSnapshot::decode(bufferlist::iterator& it) { ++ using ceph::decode; + DECODE_START(1, it); - ::decode(id, it); - ::decode(name, it); - ::decode(state, it); - ::decode(snaps, it); ++ decode(id, it); ++ decode(name, it); ++ decode(state, it); ++ decode(snaps, it); + DECODE_FINISH(it); +} + +void GroupSnapshot::dump(Formatter *f) const { + f->dump_string("id", id); + f->dump_string("name", name); + f->dump_int("state", state); +} + +void GroupSnapshot::generate_test_instances(std::list &o) { + o.push_back(new GroupSnapshot("10152ae8944a", "groupsnapshot1", GROUP_SNAPSHOT_STATE_INCOMPLETE)); + o.push_back(new GroupSnapshot("1018643c9869", "groupsnapshot2", GROUP_SNAPSHOT_STATE_COMPLETE)); +} void TrashImageSpec::encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); - ::encode(source, bl); - ::encode(name, bl); - ::encode(deletion_time, bl); - ::encode(deferment_end_time, bl); + encode(source, bl); + encode(name, bl); + encode(deletion_time, bl); + encode(deferment_end_time, bl); ENCODE_FINISH(bl); } diff --cc src/cls/rbd/cls_rbd_types.h index b77212d6435ce,266daac8c7843..ca536e83b2592 --- a/src/cls/rbd/cls_rbd_types.h +++ b/src/cls/rbd/cls_rbd_types.h @@@ -338,67 -332,6 +342,69 @@@ struct SnapshotNamespaceOnDisk }; WRITE_CLASS_ENCODER(SnapshotNamespaceOnDisk); +SnapshotNamespaceType get_snap_namespace_type(const SnapshotNamespace& snapshot_namespace); + +enum GroupSnapshotState { + GROUP_SNAPSHOT_STATE_INCOMPLETE = 0, + GROUP_SNAPSHOT_STATE_COMPLETE = 1, +}; + +inline void encode(const GroupSnapshotState &state, bufferlist& bl, uint64_t features=0) +{ - ::encode(static_cast(state), bl); ++ using ceph::encode; ++ encode(static_cast(state), bl); +} + +inline void decode(GroupSnapshotState &state, bufferlist::iterator& it) +{ ++ using ceph::decode; + uint8_t int_state; - ::decode(int_state, it); ++ decode(int_state, it); + state = static_cast(int_state); +} + +struct ImageSnapshotSpec { + int64_t pool; + string image_id; + snapid_t snap_id; + + ImageSnapshotSpec() {} + ImageSnapshotSpec(int64_t _pool, + string _image_id, + snapid_t _snap_id) : pool(_pool), + image_id(_image_id), + snap_id(_snap_id) {} + + void encode(bufferlist& bl) const; + void decode(bufferlist::iterator& it); + + void dump(Formatter *f) const; + + static void generate_test_instances(std::list &o); +}; +WRITE_CLASS_ENCODER(ImageSnapshotSpec); + +struct GroupSnapshot { + std::string id; + std::string name; + GroupSnapshotState state = GROUP_SNAPSHOT_STATE_INCOMPLETE; + + GroupSnapshot() {} + GroupSnapshot(std::string _id, + std::string _name, + GroupSnapshotState _state) : id(_id), + name(_name), + state(_state) {} + + vector snaps; + + void encode(bufferlist& bl) const; + void decode(bufferlist::iterator& it); + void dump(Formatter *f) const; + + static void generate_test_instances(std::list &o); +}; +WRITE_CLASS_ENCODER(GroupSnapshot); enum TrashImageSource { TRASH_IMAGE_SOURCE_USER = 0, TRASH_IMAGE_SOURCE_MIRRORING = 1