]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: invalidate cache when flattening
authorJosh Durgin <josh.durgin@inktank.com>
Sat, 9 Mar 2013 02:57:24 +0000 (18:57 -0800)
committerJosh Durgin <josh.durgin@inktank.com>
Mon, 11 Mar 2013 22:49:55 +0000 (15:49 -0700)
The cache stores which objects don't exist. Flatten bypasses the cache
when doing its copyups, so when it is done the -ENOENT from the cache
is treated as zeroes instead of 'need to read from parent'.

Clients that have the image open need to forgot about the cached
non-existent objects as well. Do this during ictx_refresh, while the
parent_lock is held exclusively so no new reads from the parent can
happen until the updated parent metadata is visible, so no new reads
from the parent will occur.

Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/internal.cc
src/test/pybind/test_rbd.py

index 99641ad54b46c3093fa7e790bc90a398887c002f..983aae251576a835e49ffcce3e71f1c87780cbc3 100644 (file)
@@ -533,6 +533,14 @@ namespace librbd {
       lderr(cct) << "could not release all objects from cache" << dendl;
   }
 
+  void ImageCtx::clear_nonexistence_cache() {
+    if (!object_cacher)
+      return;
+    cache_lock.Lock();
+    object_cacher->clear_nonexistence(object_set);
+    cache_lock.Unlock();
+  }
+
   int ImageCtx::register_watch() {
     assert(!wctx);
     wctx = new WatchCtx(this);
index 53f6f95e5befb5b36e94fa2cae1f42763aa20878..42910c86364c29305cc80382805efe5078475803 100644 (file)
@@ -132,6 +132,7 @@ namespace librbd {
     int flush_cache();
     void shutdown_cache();
     void invalidate_cache();
+    void clear_nonexistence_cache();
     int register_watch();
     void unregister_watch();
     size_t parent_io_len(uint64_t offset, size_t length,
index f9509435f8856bbf7b17ddcae0d2ec665e619d12..450e5d9bfe66db397815df0737a113642e8af5cf 100644 (file)
@@ -1546,6 +1546,7 @@ reprotect_and_return_err:
          ictx->get_parent_pool_id(ictx->snap_id) ||
          ictx->parent->id != ictx->get_parent_image_id(ictx->snap_id) ||
          ictx->parent->snap_id != ictx->get_parent_snap_id(ictx->snap_id)) {
+       ictx->clear_nonexistence_cache();
        close_image(ictx->parent);
        ictx->parent = NULL;
       }
index c8b399bbb24ce7bfe4a7add771eae8cafaf6716c..821d721ebf17faae57e17e20f743c2235bf18f04 100644 (file)
@@ -655,3 +655,23 @@ class TestClone(object):
 
     def test_flatten_larger_order(self):
         self.check_flatten_with_order(IMG_ORDER + 2)
+
+    def test_flatten_drops_cache(self):
+        global ioctx
+        global features
+        self.rbd.clone(ioctx, IMG_NAME, 'snap1', ioctx, 'clone2',
+                       features, IMG_ORDER)
+        with Image(ioctx, 'clone2') as clone:
+            with Image(ioctx, 'clone2') as clone2:
+                # cache object non-existence
+                data = clone.read(IMG_SIZE / 2, 256)
+                clone2_data = clone2.read(IMG_SIZE / 2, 256)
+                eq(data, clone2_data)
+                clone.flatten()
+                assert_raises(ImageNotFound, clone.parent_info)
+                assert_raises(ImageNotFound, clone2.parent_info)
+                after_flatten = clone.read(IMG_SIZE / 2, 256)
+                eq(data, after_flatten)
+                after_flatten = clone2.read(IMG_SIZE / 2, 256)
+                eq(data, after_flatten)
+        self.rbd.remove(ioctx, 'clone2')