]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: handle no-op write with snapshot case 3183/head
authorSage Weil <sage@redhat.com>
Tue, 16 Dec 2014 01:04:32 +0000 (17:04 -0800)
committerSage Weil <sage@redhat.com>
Tue, 16 Dec 2014 01:04:32 +0000 (17:04 -0800)
If we have a transaction that does something to the object but it !exists
both before and after, we will continue through the write path.  If the
snapdir object already exists, and we try to create it again, we will
leak a snapdir obc and lock and later crash on an assert when the obc
is destroyed:

0> 2014-12-06 01:49:51.750163 7f08d6ade700 -1 osd/osd_types.h: In function 'ObjectContext::~ObjectContext()' thread 7f08d6ade700 time 2014-12-06 01:49:51.605411
osd/osd_types.h: 2944: FAILED assert(rwstate.empty())

Fix is to not recreated the snapdir if it already exists.

Fixes: #10262
Signed-off-by: Sage Weil <sage@redhat.com>
src/osd/ReplicatedPG.cc
src/test/librados/snapshots.cc

index 5f3a7117a8609aee5a720429fe4dc3f358969aff..841b488dac24a9620b1bb582d8138262c22807fa 100644 (file)
@@ -5539,7 +5539,8 @@ void ReplicatedPG::finish_ctx(OpContext *ctx, int log_op_type, bool maintain_ssc
        }
       }
     } else if (ctx->new_snapset.clones.size() &&
-              !ctx->cache_evict) {
+              !ctx->cache_evict &&
+              (!ctx->snapset_obc || !ctx->snapset_obc->obs.exists)) {
       // save snapset on _snap
       hobject_t snapoid(soid.oid, soid.get_key(), CEPH_SNAPDIR, soid.hash,
                        info.pgid.pool(), soid.get_namespace());
@@ -5550,7 +5551,8 @@ void ReplicatedPG::finish_ctx(OpContext *ctx, int log_op_type, bool maintain_ssc
                                        eversion_t(),
                                        0, osd_reqid_t(), ctx->mtime));
 
-      ctx->snapset_obc = get_object_context(snapoid, true);
+      if (!ctx->snapset_obc)
+       ctx->snapset_obc = get_object_context(snapoid, true);
       bool got = ctx->snapset_obc->get_write_greedy(ctx->op);
       assert(got);
       dout(20) << " got greedy write on snapset_obc " << *ctx->snapset_obc << dendl;
index e9c566a711d58bc7a2f65800273d107ae9382d68..2431495eee9543e60b31f27cab41b6758bbbde25 100644 (file)
@@ -145,6 +145,24 @@ TEST_F(LibRadosSnapshotsPP, SnapGetNamePP) {
   EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
 }
 
+TEST_F(LibRadosSnapshotsPP, SnapCreateRemovePP) {
+  // reproduces http://tracker.ceph.com/issues/10262
+  bufferlist bl;
+  bl.append("foo");
+  ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0));
+  ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
+  ASSERT_EQ(0, ioctx.remove("foo"));
+  ASSERT_EQ(0, ioctx.snap_create("snapbar"));
+
+  librados::ObjectWriteOperation *op = new librados::ObjectWriteOperation();
+  op->create(false);
+  op->remove();
+  ASSERT_EQ(0, ioctx.operate("foo", op));
+
+  EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
+  EXPECT_EQ(0, ioctx.snap_remove("snapbar"));
+}
+
 TEST_F(LibRadosSnapshotsSelfManaged, Snap) {
   std::vector<uint64_t> my_snaps;
   my_snaps.push_back(-2);