]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: check return code and error out if invalidate_cache fails
authorJosh Durgin <josh.durgin@inktank.com>
Thu, 24 Apr 2014 21:43:35 +0000 (14:43 -0700)
committerJosh Durgin <josh.durgin@inktank.com>
Mon, 28 Apr 2014 22:14:47 +0000 (15:14 -0700)
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 <josh.durgin@inktank.com>
src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/internal.cc

index 6477e8dfd048b2e610be5960b8ea71ba283a4817..d2f0a4a96b19377cbfe70900225f2540cf7d1811 100644 (file)
@@ -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() {
index 026a3e05a453764e713aafeb759dcdce48a2ee85..83ed0449904a3eed9ff093c29fa25e18b2d68130 100644 (file)
@@ -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();
index 127be38cf34682a55eda15d997a339d6bafd700b..b13ff97cd9aeb095f14b0624deee18968ce49564 100644 (file)
@@ -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;