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: fix deep copy a child-image #20099
Conversation
@Songweibin Nice catch, thanks. I think Thinking about this some more, I did open a new feature tracker ticket to add optional support to "flatten" an image upon deep-copy, but that would require tweaking the object copy state machine to read from the parent if no snapshots and the object is missing. |
In deep_copy case we are allowed to copy from the head. Should we create a (temporal) snapshot on the source in this case before cloning? This might be weird and do not work when copying from the ro pool? |
@trociny In this case, the source image is already a clone so we know the parent snapshot already exists and is protected, so we should be OK to chain a second clone off the parent. |
046671c
to
8987656
Compare
@dillaman Done, please have a look. |
src/librbd/api/Image.cc
Outdated
@@ -158,7 +160,50 @@ int Image<I>::deep_copy(I *src, librados::IoCtx& dest_md_ctx, | |||
return -ENOSYS; | |||
} | |||
|
|||
int r = create(dest_md_ctx, destname, "", src_size, opts, "", "", false); | |||
int r; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will need to do something like this to determine if the source image is linked to a parent image:
{
RWLock::RLocker snap_locker(src->snap_lock);
RWLock::RLocker parent_locker(src->parent_lock);
// use oldest snapshot or HEAD for parent spec
if (!src->snap_info.empty()) {
parent_spec = src->snap_info.begin()->second.parent.spec;
} else {
parent_spec = src->parent_md.spec;
}
}
src/librbd/api/Image.cc
Outdated
} else { | ||
std::string snap_name; | ||
src->parent->snap_lock.get_read(); | ||
r = src->parent->get_snap_name(src->parent_md.spec.snap_id, &snap_name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: src->parent
might be nullptr
so resolve the snap name after opening the parent image below and then just run src_parent_image_ctx->state->snap_set(XYZ)
. In a perfect world we should be able to internally set the snap by id.
src/librbd/api/Image.cc
Outdated
@@ -158,7 +160,50 @@ int Image<I>::deep_copy(I *src, librados::IoCtx& dest_md_ctx, | |||
return -ENOSYS; | |||
} | |||
|
|||
int r = create(dest_md_ctx, destname, "", src_size, opts, "", "", false); | |||
int r; | |||
if (src->parent_md.spec.pool_id == -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: use cached parent_spec
from code snippet above throughout
src/librbd/api/Image.cc
Outdated
ImageCtx *src_parent_image_ctx = | ||
new ImageCtx("", src->parent_md.spec.image_id, | ||
snap_name.c_str(), parent_io_ctx, true); | ||
r = src_parent_image_ctx->state->open(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: you can pass true
here to skip opening the parent of the parent
8987656
to
9d1e247
Compare
@dillaman Updated, thank you very much.
|
src/librbd/internal.cc
Outdated
@@ -1989,6 +1989,39 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) | |||
return 0; | |||
} | |||
|
|||
int snap_set(ImageCtx *ictx, const cls::rbd::SnapshotNamespace &snap_namespace, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed -- what I was implying was to add a new overload to ImageState::snap_set
that just takes the snap_id, but it doesn't need to be part of this PR. In general, I am trying to (slowly) remove code from internal.cc
.
ccf6f59
to
37009a7
Compare
@dillaman Updated and add tests, thanks. |
src/librbd/api/Image.cc
Outdated
{ | ||
RWLock::RLocker parent_snap_locker(src_parent_image_ctx->snap_lock); | ||
auto it = src_parent_image_ctx->snap_info.find(parent_spec.snap_id); | ||
if (it != src_parent_image_ctx->snap_info.end()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return -ENOENT
if the snapshot doesn't exist -- an empty snap_name
implies setting the snapshot to the HEAD revision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dillaman Done, thank you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: can you tweak it to the following for clarity:
if (it == src_parent_image_ctx->snap_info.end()) {
return -ENOENT;
}
snap_name = it->second.name;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dillaman Done, thanks.
qa/workunits/rbd/cli_generic.sh
Outdated
# deep copy clone-image | ||
rbd snap rm testimg4@snap1 | ||
rbd rm testimg4 | ||
rbd rm testimg5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the test fails here since testimg5
has a snapshot named snap1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh sorry, i mistakenly thought rbd deep copy testimg1 --snap=snap1 testimg5
only copied snapshot just like copy
.
37009a7
to
2161644
Compare
* tweak create a cloned image when the source image is a clone (or at least one of its snapshots is a clone). Signed-off-by: songweibin <song.weibin@zte.com.cn>
2161644
to
c3e119d
Compare
This pull request (1)fix failed to set parent when deep copying a child-image which has snapshot(s) (2)update rbd_children object when deep copying a child-image.
I'm not sure if this is the right way to fix these issues, and the unittest still needs to be fixed.
@dillaman @trociny Please help to have a look, thank you in advance.