Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

librbd: add support for snapshot namespaces #11160

Merged
merged 4 commits into from Oct 24, 2016

Conversation

VictorDenisov
Copy link
Contributor

No description provided.

@@ -1488,6 +1489,34 @@ int get_snapshot_name(cls_method_context_t hctx, bufferlist *in, bufferlist *out
return 0;
}

int get_snapshot_namespace(cls_method_context_t hctx, bufferlist *in, bufferlist *out)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: add block comment describing expected in/out params


CLS_LOG(20, "get_snapshot_namespace snap_id=%llu", (unsigned long long)snap_id);

if (snap_id == CEPH_NOSNAP)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: wrap in braces

string snapshot_key;
key_from_snap_id(snap_id, &snapshot_key);
int r = read_key(hctx, snapshot_key, &snap);
if (r < 0)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: same here

return -EINVAL;
}

CLS_LOG(20, "get_snapshot_namespace snap_id=%llu", (unsigned long long)snap_id);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: you can use PRIu64 to directly encode snap_id

::encode(snap_id, bl2);
op->exec("rbd", "get_size", bl2);
::encode(snap_id, bl2);
op->exec("rbd", "get_snapshot_namespace", bl2);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this cls method won't exist on older OSDs, unfortunately, until we get to the point of only supporting Kraken+, you need to retrieve the snapshot namespaces as part of an individual OSD op in case it errors out with -EOPNOTSUPP (which you could then ignore)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Too bad I didn't think about it.


std::ostream& operator<<(std::ostream& os, const GroupSnapshotNamespace& ns) {
os << "[group]";
return os;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: dump fields?

string snapshot_id;

void encode(bufferlist& bl) const {
::encode(group_pool, bl);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: move the implementation into the cc file


inline void encode(const SnapshotNamespace &c, bufferlist &bl, uint64_t features=0)
{
ENCODE_DUMP_PRE();
Copy link

@dillaman dillaman Sep 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is doing what you are expecting -- this for for creating the binary file dump records, which leads to the next comment ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this comment. Are you talking about ENCODE_DUMP_PRE(); specifically? I see that WRITE_CLASS_ENCODER is used in order to create encode and decode functions for MirrorImageStatus. WRITE_CLASS_ENCODER adds ENCODE_DUMP_PRE and ENCODE_DUMP post inside encode function it generates.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the code for ENCODE_DUMP_PRE -- most of the time it's a no-op. The only time it actually does something is within the dencoder test where it writes the binary encoding format out to a file. I think you were looking for ENCODE_START/ENCODE_FINISH which add version control.


void encode(bufferlist& bl) const {}
void decode(bufferlist::iterator& it) {}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the new types should have generate_test_instances and dump methods so that they can be registered with the dencoder test case.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... might be either to create a new SnapshotNamespace struct that just inherits from boost::variant. That would allow you to create the necessary generate_test_instances static member function for use with dencoder. Then you wouldn't need generate_test_instances for each individual type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to implement it using inheritance and couldn't reconcile all types of constructors that are provided by boost::variant. It looks like the solution is to have a wrapper type like NotifyMessage wraps Payload and EventEntry wraps Event type. Those wrappers implement all the required methods.

@VictorDenisov VictorDenisov force-pushed the consistency_groups_namespaces branch 2 times, most recently from 09e2514 to db5bf5d Compare September 22, 2016 01:07
@VictorDenisov
Copy link
Contributor Author

not ready yet. will update when done with addressing comments

@dillaman
Copy link

... all internal plumbing changes, no doc updates required

@VictorDenisov VictorDenisov force-pushed the consistency_groups_namespaces branch 2 times, most recently from 4ab1798 to 0b7f89f Compare September 24, 2016 01:01
@VictorDenisov
Copy link
Contributor Author

@dillaman could you please take a look if you like this version at all. In the mean time I'll look into what happened to the tests.

@VictorDenisov VictorDenisov force-pushed the consistency_groups_namespaces branch 3 times, most recently from 81ffdb0 to 142d4fc Compare September 25, 2016 03:52
@@ -316,5 +317,138 @@ bool GroupSpec::is_valid() const {
return (!group_id.empty()) && (pool_id != -1);
}

void GroupSnapshotNamespace::encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: probably no need to encode another version here since it's already wrapped in a versioned struct

}

void SnapshotNamespaceEntry::generate_test_instances(std::list<SnapshotNamespaceEntry *> &o) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: append a UserSnapshotNamespace and GroupSnapshotNamespace example to the list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should GroupSnapshotNamespace have any meaningful ids in it or any random values are enough?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Random but valid is fine -- it's to help ensure that the format isn't unintentionally broken by future changes.


};

WRITE_CLASS_ENCODER(UserSnapshotNamespace);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: since these will always be encoded via SnapshotNamespaceEntry, no need to create encode/decode free functions for these types.

@@ -230,6 +231,8 @@ namespace librbd {
const SnapInfo* get_snap_info(librados::snap_t in_snap_id) const;
int get_snap_name(librados::snap_t in_snap_id,
std::string *out_snap_name) const;
int get_snap_namespace(librados::snap_t in_snap_id,
cls::rbd::SnapshotNamespaceEntry *out_snap_namespace) const;
Copy link

@dillaman dillaman Sep 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: could directly use SnapshotNamespace variant since SnapshotNamespaceEntry is only used for encode/decode and requires an indirection. Perhaps rename SnapshotNamespaceEntry to SnapshotNamespaceOnDisk and hide its use outside of "cls/rbd"

@@ -135,9 +136,10 @@ struct SnapCreateEvent : public SnapEventBase {

SnapCreateEvent() {
}
SnapCreateEvent(uint64_t op_tid, const std::string &snap_name)
: SnapEventBase(op_tid, snap_name) {
SnapCreateEvent(uint64_t op_tid, const std::string &snap_name, const cls::rbd::SnapshotNamespaceEntry &_snap_namespace)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would there be a need to journal group snapshot create events? It seems like the group actions would be journaled via a group journal (eventually). If group snap create events are recorded with the image, they wouldn't be properly associated with a group and you wouldn't be able to remove them (perhaps). Therefore, perhaps this should wait until after group actions can be journaled and replayed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then I don't have any info about snapshots namespace and in case of replay I can't recreate the snapshot with required namespace. So, far all it does - keeps this information. Nobody in the code creates namespaces other than UserSnapshotNamespace. If I remove this then all replayed snapshots should be in UserSnapshotNamespace by default.

@@ -140,6 +140,11 @@ Context *RefreshRequest<I>::handle_v1_get_snapshots(int *result) {
return m_on_finish;
}

int n = m_snap_names.size();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: could just use m_snap_namespaces = {m_snap_names.size(), cls::rbd::UserSnapshotNamespace()};

send_v2_get_mutable_metadata();
return nullptr;
} else if (*result == -EOPNOTSUPP) {
m_snap_namespaces.resize(m_snapc.snaps.size());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: default to cls::rbd::UserSnapshotNamespace?

@@ -354,8 +368,23 @@ void SnapshotCopyRequest<I>::send_snap_protect() {
librados::snap_t remote_snap_id = *snap_id_it;

m_remote_image_ctx->snap_lock.get_read();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: I don't think you'll need this for the unprotect/protect states since only user snapshots should be protected -- but I think you need to skip over non-user snapshots in the remove state machine for now.

@VictorDenisov VictorDenisov force-pushed the consistency_groups_namespaces branch 5 times, most recently from db1b6c0 to c800c9c Compare October 13, 2016 23:35
@VictorDenisov
Copy link
Contributor Author

@dillaman done. it looks like those test failures are unrelated. every time I push different tests sigfault.

@@ -239,6 +240,26 @@ void SnapPayloadBase::dump(Formatter *f) const {
f->dump_string("snap_name", snap_name);
}

void SnapCreatePayload::encode(bufferlist &bl) const {
::encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
Copy link

@dillaman dillaman Oct 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All additions need to be added to the end of the structure. Move the encode/decode of the namespace to the end of the function

@VictorDenisov
Copy link
Contributor Author

@dillaman fixed.

@VictorDenisov
Copy link
Contributor Author

ok. looking into it.

@@ -1678,7 +1678,8 @@ int snapshot_add(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
(unsigned long long)snap_id.val);
return -EIO;
}
if (snap_meta.name == old_meta.name || snap_meta.id == old_meta.id) {
if ((snap_meta.name == old_meta.name || snap_meta.id == old_meta.id)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snap id should be unique regardless of the namespace -- so the check should be:

if (snap_meta.id == old_meta.id ||
    (snap_meta.name == old_meta.name &&
     snap_meta.snapshot_namespace == old_meta.snapshot_namespace)) {

@VictorDenisov
Copy link
Contributor Author

done

@@ -1678,7 +1678,9 @@ int snapshot_add(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
(unsigned long long)snap_id.val);
return -EIO;
}
if (snap_meta.name == old_meta.name || snap_meta.id == old_meta.id) {
if ((snap_meta.name == old_meta.name
&& snap_meta.snapshot_namespace == old_meta.snapshot_namespace)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: the conditionals should go at the end of the line and not the start of a new line:

if ((snap_meta.name == old_meta.name &&
     snap_meta.snapshot_namespace == old_meta.snapshot_namespace) ||
    snap_meta.id == old_meta.id) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops. sorry. too much haskell before this commit. fixed.

@VictorDenisov VictorDenisov force-pushed the consistency_groups_namespaces branch 2 times, most recently from ccf117b to 7d4350b Compare October 21, 2016 21:46
Signed-off-by: Victor Denisov <denisovenator@gmail.com>
Signed-off-by: Victor Denisov <denisovenator@gmail.com>
Signed-off-by: Victor Denisov <denisovenator@gmail.com>
Signed-off-by: Victor Denisov <denisovenator@gmail.com>
@dillaman dillaman changed the title librbd: Consistency groups, snapshot namespaces librbd: add support for snapshot namespaces Oct 24, 2016
@dillaman dillaman merged commit e7da810 into ceph:master Oct 24, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants