From f7dc58552a9ee228b7fa2a10094e962ed66fe8fd Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Thu, 24 Apr 2014 14:43:35 -0700 Subject: [PATCH] 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) --- src/librbd/ImageCtx.cc | 12 ++++++++---- src/librbd/ImageCtx.h | 2 +- src/librbd/internal.cc | 8 ++++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index 6477e8dfd048b..d2f0a4a96b193 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -573,9 +573,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(); @@ -585,8 +585,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 026a3e05a4537..83ed0449904a3 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -139,7 +139,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 127be38cf3468..b13ff97cd9aeb 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -1504,7 +1504,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); @@ -1847,7 +1849,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; -- 2.39.5