]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osdc/ObjectCacher: only return ENOENT if ObjectSet is flagged
authorSage Weil <sage@inktank.com>
Mon, 12 Nov 2012 23:40:08 +0000 (15:40 -0800)
committerSage Weil <sage@inktank.com>
Mon, 12 Nov 2012 23:44:54 +0000 (15:44 -0800)
The fs client can't handle ENOENT from the cache, but librbd wants it.
Also, the fs client will send down multiple ObjectExtents per io, but that
is incompatible with the ENOENT behavior.

Indicate which behavior we want via the ObjectSet, and update librbd to
explicitly ask for it.  This fixes the fs client, which is currently
broken (it returns ENOENT on read).

Signed-off-by: Sage Weil <sage@inktank.com>
src/librbd/ImageCtx.cc
src/osdc/ObjectCacher.cc
src/osdc/ObjectCacher.h

index 065ce6b6c28eafd8693b06c97c790fb2c787dd97..69ad195f8515aee6d5dccb27afa977b5ca41b523 100644 (file)
@@ -78,6 +78,7 @@ namespace librbd {
                                       cct->_conf->rbd_cache_target_dirty,
                                       cct->_conf->rbd_cache_max_dirty_age);
       object_set = new ObjectCacher::ObjectSet(NULL, data_ctx.get_id(), 0);
+      object_set->return_enoent = true;
       object_cacher->start();
     }
   }
index 80679e018ecad7daa67d2530826bfee85cf350f4..48df3c3114f9c15dc2b30f465499d072566d4f99 100644 (file)
@@ -926,53 +926,52 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish,
     Object *o = get_object(soid, oset, ex_it->oloc);
 
     // does not exist and no hits?
-    if (!o->exists) {
+    if (oset->return_enoent && !o->exists) {
       // WARNING: we can only meaningfully return ENOENT if the read request
       // passed in a single ObjectExtent.  Any caller who wants ENOENT instead of
       // zeroed buffers needs to feed single extents into readx().
-      if (rd->extents.size() == 1) {
-       ldout(cct, 10) << "readx  object !exists, 1 extent..." << dendl;
-
-       // should we worry about COW underneaeth us?
-       if (writeback_handler.may_copy_on_write(soid.oid, ex_it->offset, ex_it->length, soid.snap)) {
-         ldout(cct, 20) << "readx  may copy on write" << dendl;
-         bool wait = false;
-         for (map<loff_t, BufferHead*>::iterator bh_it = o->data.begin();
-              bh_it != o->data.end();
-              bh_it++) {
-           BufferHead *bh = bh_it->second;
-           if (bh->is_dirty() || bh->is_tx()) {
-             ldout(cct, 10) << "readx  flushing " << *bh << dendl;
-             wait = true;
-             if (bh->is_dirty())
-               bh_write(bh);
-           }
-         }
-         if (wait) {
-           ldout(cct, 10) << "readx  waiting on tid " << o->last_write_tid << " on " << *o << dendl;
-           o->waitfor_commit[o->last_write_tid].push_back(new C_RetryRead(this, rd, oset, onfinish));
-           // FIXME: perfcounter!
-           return 0;
-         }
-       }
+      assert(rd->extents.size() == 1);
+      ldout(cct, 10) << "readx  object !exists, 1 extent..." << dendl;
 
-       // can we return ENOENT?
-       bool allzero = true;
+      // should we worry about COW underneaeth us?
+      if (writeback_handler.may_copy_on_write(soid.oid, ex_it->offset, ex_it->length, soid.snap)) {
+       ldout(cct, 20) << "readx  may copy on write" << dendl;
+       bool wait = false;
        for (map<loff_t, BufferHead*>::iterator bh_it = o->data.begin();
             bh_it != o->data.end();
             bh_it++) {
-         ldout(cct, 20) << "readx  ob has bh " << *bh_it->second << dendl;
-         if (!bh_it->second->is_zero() && !bh_it->second->is_rx()) {
-           allzero = false;
-           break;
+         BufferHead *bh = bh_it->second;
+         if (bh->is_dirty() || bh->is_tx()) {
+           ldout(cct, 10) << "readx  flushing " << *bh << dendl;
+           wait = true;
+           if (bh->is_dirty())
+             bh_write(bh);
          }
        }
-       if (allzero) {
-         ldout(cct, 10) << "readx  ob has all zero|rx, returning ENOENT" << dendl;
-         delete rd;
-         return -ENOENT;
+       if (wait) {
+         ldout(cct, 10) << "readx  waiting on tid " << o->last_write_tid << " on " << *o << dendl;
+         o->waitfor_commit[o->last_write_tid].push_back(new C_RetryRead(this, rd, oset, onfinish));
+         // FIXME: perfcounter!
+         return 0;
+       }
+      }
+
+      // can we return ENOENT?
+      bool allzero = true;
+      for (map<loff_t, BufferHead*>::iterator bh_it = o->data.begin();
+          bh_it != o->data.end();
+          bh_it++) {
+       ldout(cct, 20) << "readx  ob has bh " << *bh_it->second << dendl;
+       if (!bh_it->second->is_zero() && !bh_it->second->is_rx()) {
+         allzero = false;
+         break;
        }
       }
+      if (allzero) {
+       ldout(cct, 10) << "readx  ob has all zero|rx, returning ENOENT" << dendl;
+       delete rd;
+       return -ENOENT;
+      }
     }
 
     // map extent into bufferheads
index a45b7f7a01266739c55945bcfaf063c81539421f..4c56410bb54fe75150f4c8dfafb48088b99dac97 100644 (file)
@@ -300,10 +300,13 @@ class ObjectCacher {
     xlist<Object*> objects;
 
     int dirty_or_tx;
+    bool return_enoent;
 
     ObjectSet(void *p, int64_t _poolid, inodeno_t i)
       : parent(p), ino(i), truncate_seq(0),
-       truncate_size(0), poolid(_poolid), dirty_or_tx(0) {}
+       truncate_size(0), poolid(_poolid), dirty_or_tx(0),
+       return_enoent(false) {}
+
   };