]> git-server-git.apps.pok.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>
Tue, 23 Apr 2013 18:33:17 +0000 (11:33 -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>
(cherry picked from commit 46e8fc00b2dc8eb17d8777b6ef5ad1cfcc389cea)

src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/internal.cc
src/test/pybind/test_rbd.py

index 17e7592f9470d67d7f8ca7692176e855684db7a8..db185c2dc0e2aabdd680abaf0d5a44d9f230c772 100644 (file)
@@ -543,6 +543,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 99a07a6bf1c57e08ce8c005f153aaebdc1b60a8d..90d815e69ea6b09053e55ce58680e5f130bff8da 100644 (file)
@@ -133,6 +133,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 6989a70c98ef2639c0f6ceb2ffe1c65562a3eb1c..fb4114e94f3918a626898ced097daf48954d1c47 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 cba267bddcaa88b262d51237765ac5ccba261fac..2d1a78431a93b4b105dde96de6eb5d84a5d85a54 100644 (file)
@@ -653,3 +653,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')