From: Josh Durgin Date: Thu, 24 Apr 2014 21:43:35 +0000 (-0700) Subject: librbd: check return code and error out if invalidate_cache fails X-Git-Tag: v0.67.10~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d93579514db74eed61580a6166c2787304a8a9fb;p=ceph.git librbd: check return code and error out if invalidate_cache fails This will only happen when shrinking or rolling back an image is done while other I/O is in flight to the same ImageCtx. This is unsafe, so return an error before performing the resize or rollback. Signed-off-by: Josh Durgin (cherry picked from commit e08b8b66c77be3a3d7f79d91c20b1619571149ee) --- diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index 41518b67698..025e5602c81 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -568,9 +568,9 @@ namespace librbd { object_cacher->stop(); } - void ImageCtx::invalidate_cache() { + int ImageCtx::invalidate_cache() { if (!object_cacher) - return; + return 0; cache_lock.Lock(); object_cacher->release_set(object_set); cache_lock.Unlock(); @@ -580,8 +580,12 @@ namespace librbd { cache_lock.Lock(); bool unclean = object_cacher->release_set(object_set); cache_lock.Unlock(); - if (unclean) - lderr(cct) << "could not release all objects from cache" << dendl; + if (unclean) { + lderr(cct) << "could not release all objects from cache: " + << unclean << " bytes remain" << dendl; + return -EBUSY; + } + return r; } void ImageCtx::clear_nonexistence_cache() { diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 29ca2f197ea..db4092463ff 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -136,7 +136,7 @@ namespace librbd { void flush_cache_aio(Context *onfinish); int flush_cache(); void shutdown_cache(); - void invalidate_cache(); + int invalidate_cache(); void clear_nonexistence_cache(); int register_watch(); void unregister_watch(); diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 68a9e571d2b..55d910ea2ba 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -1498,7 +1498,9 @@ reprotect_and_return_err: if (size < ictx->size && ictx->object_cacher) { // need to invalidate since we're deleting objects, and // ObjectCacher doesn't track non-existent objects - ictx->invalidate_cache(); + r = ictx->invalidate_cache(); + if (r < 0) + return r; } resize_helper(ictx, size, prog_ctx); @@ -1841,7 +1843,9 @@ reprotect_and_return_err: // need to flush any pending writes before resizing and rolling back - // writes might create new snapshots. Rolling back will replace // the current version, so we have to invalidate that too. - ictx->invalidate_cache(); + r = ictx->invalidate_cache(); + if (r < 0) + return r; ldout(cct, 2) << "resizing to snapshot size..." << dendl; NoOpProgressContext no_op;