mirror of
https://github.com/ceph/ceph
synced 2025-01-20 18:21:57 +00:00
librbd: prevent copyup during image shrink operations
If a cloned image was shrunk, it was possible for a copyup to be performed on objects outside of the new image range. Resize now pre-shrinks the parent overlap to disable copyup when removing objects. Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
parent
fbcde04a38
commit
8d61c39658
@ -249,15 +249,18 @@ namespace librbd {
|
||||
protected:
|
||||
virtual void add_write_ops(librados::ObjectWriteOperation *wr) {
|
||||
if (has_parent()) {
|
||||
m_object_state = OBJECT_EXISTS;
|
||||
wr->truncate(0);
|
||||
} else {
|
||||
m_object_state = OBJECT_PENDING;
|
||||
wr->remove();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void pre_object_map_update(uint8_t *new_state) {
|
||||
if (has_parent()) {
|
||||
m_object_state = OBJECT_EXISTS;
|
||||
} else {
|
||||
m_object_state = OBJECT_PENDING;
|
||||
}
|
||||
*new_state = m_object_state;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,12 @@ bool AsyncResizeRequest::should_complete(int r)
|
||||
if (m_image_ctx.size == m_new_size) {
|
||||
m_image_ctx.size = m_original_size;
|
||||
}
|
||||
|
||||
RWLock::WLocker l2(m_image_ctx.parent_lock);
|
||||
if (m_image_ctx.parent != NULL &&
|
||||
m_image_ctx.parent_md.overlap == m_new_parent_overlap) {
|
||||
m_image_ctx.parent_md.overlap = m_original_parent_overlap;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -92,6 +98,13 @@ void AsyncResizeRequest::send_trim_image() {
|
||||
// update in-memory size to clip concurrent IO operations
|
||||
RWLock::WLocker l(m_image_ctx.md_lock);
|
||||
m_image_ctx.size = m_new_size;
|
||||
|
||||
RWLock::WLocker l2(m_image_ctx.parent_lock);
|
||||
if (m_image_ctx.parent != NULL) {
|
||||
m_original_parent_overlap = m_image_ctx.parent_md.overlap;
|
||||
m_new_parent_overlap = MIN(m_new_size, m_original_parent_overlap);
|
||||
m_image_ctx.parent_md.overlap = m_new_parent_overlap;
|
||||
}
|
||||
}
|
||||
|
||||
AsyncTrimRequest *req = new AsyncTrimRequest(m_image_ctx,
|
||||
|
@ -19,7 +19,8 @@ public:
|
||||
ProgressContext &prog_ctx)
|
||||
: AsyncRequest(image_ctx, on_finish),
|
||||
m_original_size(original_size), m_new_size(new_size),
|
||||
m_prog_ctx(prog_ctx)
|
||||
m_prog_ctx(prog_ctx), m_original_parent_overlap(0),
|
||||
m_new_parent_overlap(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -60,6 +61,8 @@ protected:
|
||||
uint64_t m_original_size;
|
||||
uint64_t m_new_size;
|
||||
ProgressContext &m_prog_ctx;
|
||||
uint64_t m_original_parent_overlap;
|
||||
uint64_t m_new_parent_overlap;
|
||||
|
||||
virtual bool should_complete(int r);
|
||||
|
||||
|
@ -187,6 +187,9 @@ bool ObjectMap::aio_update(uint64_t start_object_no, uint64_t end_object_no,
|
||||
assert(start_object_no < end_object_no);
|
||||
|
||||
CephContext *cct = m_image_ctx.cct;
|
||||
ldout(cct, 20) << &m_image_ctx << " aio_update: start=" << start_object_no
|
||||
<< ", end=" << end_object_no << ", new_state="
|
||||
<< static_cast<uint32_t>(new_state) << dendl;
|
||||
if (end_object_no > object_map.size()) {
|
||||
ldout(cct, 20) << "skipping update of invalid object map" << dendl;
|
||||
return false;
|
||||
@ -319,7 +322,8 @@ void ObjectMap::UpdateRequest::send() {
|
||||
|
||||
ldout(cct, 20) << &m_image_ctx << " updating on-disk object map: ["
|
||||
<< m_start_object_no << "," << m_end_object_no << ") = "
|
||||
<< (m_current_state ? stringify(*m_current_state) : "")
|
||||
<< (m_current_state ?
|
||||
stringify(static_cast<uint32_t>(*m_current_state)) : "")
|
||||
<< "->" << static_cast<uint32_t>(m_new_state)
|
||||
<< dendl;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user