]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/ReplicatedPG: create whiteout on promote ENOENT
authorSage Weil <sage@inktank.com>
Tue, 22 Oct 2013 23:14:00 +0000 (16:14 -0700)
committerSage Weil <sage@inktank.com>
Sat, 14 Dec 2013 00:35:53 +0000 (16:35 -0800)
If we try to fetch an object from the base tier and it is not present, we
can create a whiteout object.

Signed-off-by: Sage Weil <sage@inktank.com>
src/osd/ReplicatedPG.cc
src/test/librados/tier.cc

index 9155a90a84901834f23b3f4bc92b94fd19513ca9..b6e80160a47d2be08e441fa7ba40547ff9d1a7c7 100644 (file)
@@ -4611,7 +4611,17 @@ void ReplicatedPG::finish_promote(int r, OpRequestRef op,
                                  CopyResults *results, ObjectContextRef obc,
                                   hobject_t& temp_obj)
 {
-  if (r < 0) {
+  dout(10) << __func__ << " " << obc->obs.oi.soid << " r=" << r << dendl;
+
+  bool whiteout = false;
+  if (r == -ENOENT &&
+      (pool.info.cache_mode == pg_pool_t::CACHEMODE_WRITEBACK ||
+       pool.info.cache_mode == pg_pool_t::CACHEMODE_READONLY)) {
+    dout(10) << __func__ << " whiteout " << obc->obs.oi.soid << dendl;
+    whiteout = true;
+  }
+
+  if (r < 0 && !whiteout) {
     // we need to get rid of the op in the blocked queue
     map<hobject_t,list<OpRequestRef> >::iterator blocked_iter =
       waiting_for_blocked_object.find(obc->obs.oi.soid);
@@ -4629,20 +4639,26 @@ void ReplicatedPG::finish_promote(int r, OpRequestRef op,
 
   RepGather *repop = simple_repop_create(obc);
   OpContext *tctx = repop->ctx;
-  tctx->op_t.swap(results->final_tx);
-  if (results->started_temp_obj) {
-    tctx->discard_temp_oid = temp_obj;
-  }
 
   object_stat_sum_t delta;
   ++delta.num_objects;
   obc->obs.exists = true;
-  delta.num_bytes += results->object_size;
-  obc->obs.oi.category = results->category;
+  if (whiteout) {
+    // create a whiteout
+    tctx->op_t.touch(coll, obc->obs.oi.soid);
+    obc->obs.oi.set_flag(object_info_t::FLAG_WHITEOUT);
+  } else {
+    tctx->op_t.swap(results->final_tx);
+    if (results->started_temp_obj) {
+      tctx->discard_temp_oid = temp_obj;
+    }
+    delta.num_bytes += results->object_size;
+    obc->obs.oi.category = results->category;
+    tctx->user_at_version = results->user_version;
+  }
   info.stats.stats.add(delta, obc->obs.oi.category);
   tctx->at_version.epoch = get_osdmap()->get_epoch();
   tctx->at_version.version = pg_log.get_head().version + 1;
-  tctx->user_at_version = results->user_version;
 
   tctx->log.push_back(pg_log_entry_t(
          pg_log_entry_t::MODIFY,
index 7dc34af8c0867820894fbbb178554cf3f6862dc3..33f183ca6c6bf52390757d373d252a75d17e4ec1 100644 (file)
@@ -127,11 +127,20 @@ TEST(LibRadosTier, Promote) {
     ASSERT_EQ(1, base_ioctx.read("foo", bl, 1, 0));
   }
 
+  // read, trigger a whiteout
+  {
+    bufferlist bl;
+    ASSERT_EQ(-ENOENT, base_ioctx.read("bar", bl, 1, 0));
+    ASSERT_EQ(-ENOENT, base_ioctx.read("bar", bl, 1, 0));
+  }
+
   // verify the object is present in the cache tier
   {
     ObjectIterator it = cache_ioctx.objects_begin();
     ASSERT_TRUE(it != cache_ioctx.objects_end());
-    ASSERT_EQ(it->first, string("foo"));
+    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ++it;
+    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
     ++it;
     ASSERT_TRUE(it == cache_ioctx.objects_end());
   }