]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: handle no-op write with snapshot case
authorSage Weil <sage@redhat.com>
Tue, 16 Dec 2014 01:04:32 +0000 (17:04 -0800)
committerSamuel Just <sjust@redhat.com>
Wed, 28 Jan 2015 22:55:39 +0000 (14:55 -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>
(cherry picked from commit 02fae9fc54c10b5a932102bac43f32199d4cb612)

src/osd/ReplicatedPG.cc
src/test/librados/snapshots.cc

index b90f1c0d618e26ddfd2864028feb191867fa962b..2fd1b563fef0b42cae76f97aed1a3e9c95e0cdfd 100644 (file)
@@ -5388,7 +5388,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());
@@ -5399,7 +5400,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 020af111ddf97de72cae83aa7e67cf2c16ce2fce..01ab62e970c04b032dead080badd27dd2e7b8f20 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);