From 3948e0690ee5e5b9e4b8bfadb2120b9bb5e82480 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 15 Jun 2012 17:27:25 -0700 Subject: [PATCH] cls_rbd: handle parent overlap 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 --- src/cls_rbd.cc | 34 ++++++++++++++++-- src/test/rbd/test_cls_rbd.cc | 69 ++++++++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/src/cls_rbd.cc b/src/cls_rbd.cc index e72f2f6d12b9c..1b0d57dc399cf 100644 --- a/src/cls_rbd.cc +++ b/src/cls_rbd.cc @@ -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; diff --git a/src/test/rbd/test_cls_rbd.cc b/src/test/rbd/test_cls_rbd.cc index 130bf97150d09..2cf91f316a8e8 100644 --- a/src/test/rbd/test_cls_rbd.cc +++ b/src/test/rbd/test_cls_rbd.cc @@ -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)); } -- 2.39.5