]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cls_rbd: handle parent overlap
authorSage Weil <sage@inktank.com>
Sat, 16 Jun 2012 00:27:25 +0000 (17:27 -0700)
committerSage Weil <sage@inktank.com>
Tue, 19 Jun 2012 22:08:18 +0000 (15:08 -0700)
Two things:

 * when we set a parent, the overlap is the min of our size and the
   parent's size.
 * when we resize, our overlap may shrink.

Signed-off-by: Sage Weil <sage@inktank.com>
src/cls_rbd.cc
src/test/rbd/test_cls_rbd.cc

index e72f2f6d12b9c1d11d13eba863946ce5ea9fcfbc..1b0d57dc399cf6c64f50925da480715effa4fb71 100644 (file)
@@ -440,8 +440,6 @@ int set_size(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
     return -EINVAL;
   }
 
-  CLS_LOG(20, "set_size size=%llu", size);
-
   // check that size exists to make sure this is a header object
   // that was created correctly
   uint64_t orig_size;
@@ -451,15 +449,37 @@ int set_size(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
     return r;
   }
 
+  CLS_LOG(20, "set_size size=%llu orig_size=%llu", size);
+
   bufferlist sizebl;
   ::encode(size, sizebl);
-
   r = cls_cxx_map_set_val(hctx, "size", &sizebl);
   if (r < 0) {
     CLS_ERR("error writing snapshot metadata: %d", r);
     return r;
   }
 
+  // if we are shrinking, and have a parent, shrink our overlap with
+  // the parent, too.
+  if (size < orig_size) {
+    cls_rbd_parent parent;
+    r = read_key(hctx, "parent", &parent);
+    if (r == -ENOENT)
+      r = 0;
+    if (r < 0)
+      return r;
+    if (parent.exists() && parent.size > size) {
+      bufferlist parentbl;
+      parent.size = size;
+      ::encode(parent, parentbl);
+      r = cls_cxx_map_set_val(hctx, "parent", &parentbl);
+      if (r < 0) {
+       CLS_ERR("error writing parent: %d", r);
+       return r;
+      }
+    }
+  }
+
   return 0;
 }
 
@@ -819,6 +839,14 @@ int set_parent(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
     return -EEXIST;
   }
 
+  // our overlap is the min of our size and the parent's size.
+  uint64_t our_size;
+  r = read_key(hctx, "size", &our_size);
+  if (r < 0)
+    return r;
+  if (our_size < size)
+    size = our_size;
+
   bufferlist parentbl;
   parent.pool = pool;
   parent.id = id;
index 130bf97150d09de1246ece5577b51b5a2bc9426e..2cf91f316a8e88b7a6b3f3334cd29721faddbf08 100644 (file)
@@ -287,13 +287,13 @@ TEST(cls_rbd, parents)
   ASSERT_EQ(-ENOENT, get_parent(&ioctx, "doesnotexist", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
   
   // old image should fail
-  ASSERT_EQ(0, create_image(&ioctx, "old", 1000, 22, 0, "old_blk."));
+  ASSERT_EQ(0, create_image(&ioctx, "old", 33<<20, 22, 0, "old_blk."));
   ASSERT_EQ(-ENOEXEC, get_parent(&ioctx, "old", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
   ASSERT_EQ(-ENOEXEC, set_parent(&ioctx, "old", -1, "parent", 3, 10<<20));
   ASSERT_EQ(-ENOEXEC, remove_parent(&ioctx, "old"));
 
   // new image will work
-  ASSERT_EQ(0, create_image(&ioctx, "foo", 1000, 22, RBD_FEATURE_LAYERING, "foo."));
+  ASSERT_EQ(0, create_image(&ioctx, "foo", 33<<20, 22, RBD_FEATURE_LAYERING, "foo."));
 
   ASSERT_EQ(-ENOENT, get_parent(&ioctx, "foo", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
   ASSERT_EQ(-ENOENT, get_parent(&ioctx, "foo", 123, &pool, &parent, &snapid, &size));
@@ -353,6 +353,71 @@ TEST(cls_rbd, parents)
   ASSERT_EQ(size, 5ull<<20);
   ASSERT_EQ(-ENOENT, get_parent(&ioctx, "foo", 12, &pool, &parent, &snapid, &size));
 
+  // make sure set_parent takes min of our size and parent's size
+  ASSERT_EQ(0, set_parent(&ioctx, "foo", 1, "parent", 3, 1<<20));
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 1ull<<20);
+  ASSERT_EQ(0, remove_parent(&ioctx, "foo"));
+
+  ASSERT_EQ(0, set_parent(&ioctx, "foo", 1, "parent", 3, 100<<20));
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 33ull<<20);
+  ASSERT_EQ(0, remove_parent(&ioctx, "foo"));
+
+  // make sure resize adjust parent overlap
+  ASSERT_EQ(0, set_parent(&ioctx, "foo", 1, "parent", 3, 10<<20));
+
+  ASSERT_EQ(0, snapshot_add(&ioctx, "foo", 14, "snap4"));
+  ASSERT_EQ(0, set_size(&ioctx, "foo", 3 << 20));
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 3ull<<20);
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", 14, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 10ull<<20);
+
+  ASSERT_EQ(0, snapshot_add(&ioctx, "foo", 15, "snap5"));
+  ASSERT_EQ(0, set_size(&ioctx, "foo", 30 << 20));
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 3ull<<20);
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", 14, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 10ull<<20);
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", 15, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 3ull<<20);
+
+  ASSERT_EQ(0, set_size(&ioctx, "foo", 2 << 20));
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 2ull<<20);
+
+  ASSERT_EQ(0, snapshot_add(&ioctx, "foo", 16, "snap6"));
+  ASSERT_EQ(0, get_parent(&ioctx, "foo", 16, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(pool, 1);
+  ASSERT_EQ(parent, "parent");
+  ASSERT_EQ(snapid, snapid_t(3));
+  ASSERT_EQ(size, 2ull<<20);
+
   ioctx.close();
   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
 }