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: v9.0.2~9^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=eb81a6a7e391327ac993fd406443b206a7f7bffc;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 --- diff --git a/src/librbd/ObjectMap.cc b/src/librbd/ObjectMap.cc index 1aa6d7407968..d45bd65fe4e2 100644 --- a/src/librbd/ObjectMap.cc +++ b/src/librbd/ObjectMap.cc @@ -517,11 +517,23 @@ void ObjectMap::invalidate(uint64_t snap_id) { return; } + // 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 (snap_id == CEPH_NOSNAP) { + m_image_ctx.image_watcher->assert_header_locked(&op); + } cls_client::set_flags(&op, snap_id, flags, flags); r = m_image_ctx.md_ctx.operate(m_image_ctx.header_oid, &op); - if (r < 0) { + 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; } @@ -595,6 +607,7 @@ bool ObjectMap::Request::invalidate() { m_image_ctx.flags |= flags; librados::ObjectWriteOperation op; + m_image_ctx.image_watcher->assert_header_locked(&op); cls_client::set_flags(&op, CEPH_NOSNAP, flags, flags); librados::AioCompletion *rados_completion = create_callback_completion();