From: Jason Dillaman Date: Tue, 23 Jun 2015 15:14:51 +0000 (-0400) Subject: librbd: only update image flags when holding exclusive lock X-Git-Tag: v0.94.3~29^2~5 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=27c99ea972a7b218ea591b208d0d1dd51eef6f95;p=ceph.git librbd: only update image flags when holding exclusive lock It was possible for a client to open an image while another client was shrinking an image. This would result in the former invalidating the object map on-disk if it openned the image between updating the image header and resizing the object map. Fixes: #11791 Backport: hammer Signed-off-by: Jason Dillaman (cherry picked from commit eb81a6a7e391327ac993fd406443b206a7f7bffc) --- diff --git a/src/librbd/ObjectMap.cc b/src/librbd/ObjectMap.cc index 8099a9103847..67ff1a20e30c 100644 --- a/src/librbd/ObjectMap.cc +++ b/src/librbd/ObjectMap.cc @@ -338,13 +338,25 @@ void ObjectMap::invalidate() { m_image_ctx.update_flags(m_image_ctx.snap_id, RBD_FLAG_OBJECT_MAP_INVALID, true); + // do not update on-disk flags if not image owner + if (m_image_ctx.image_watcher->is_lock_supported(m_image_ctx.snap_lock) && + !m_image_ctx.image_watcher->is_lock_owner()) { + return; + } + librados::ObjectWriteOperation op; + if (m_image_ctx.snap_id == CEPH_NOSNAP) { + m_image_ctx.image_watcher->assert_header_locked(&op); + } cls_client::set_flags(&op, m_image_ctx.snap_id, m_image_ctx.flags, RBD_FLAG_OBJECT_MAP_INVALID); int r = m_image_ctx.md_ctx.operate(m_image_ctx.header_oid, &op); - if (r < 0) { - lderr(cct) << "failed to invalidate object map: " << cpp_strerror(r) + if (r == -EBUSY) { + ldout(cct, 5) << "skipping on-disk object map invalidation: " + << "image not locked by client" << dendl; + } else if (r < 0) { + lderr(cct) << "failed to invalidate on-disk object map: " << cpp_strerror(r) << dendl; } } @@ -403,6 +415,7 @@ bool ObjectMap::Request::invalidate() { m_image_ctx.flags |= RBD_FLAG_OBJECT_MAP_INVALID; librados::ObjectWriteOperation op; + m_image_ctx.image_watcher->assert_header_locked(&op); cls_client::set_flags(&op, CEPH_NOSNAP, m_image_ctx.flags, RBD_FLAG_OBJECT_MAP_INVALID);