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:
Jason Dillaman 2015-02-03 06:07:00 -05:00
parent fbcde04a38
commit 8d61c39658
4 changed files with 27 additions and 4 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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;