From: Sage Weil Date: Mon, 12 Nov 2012 23:40:08 +0000 (-0800) Subject: osdc/ObjectCacher: only return ENOENT if ObjectSet is flagged X-Git-Tag: v0.55~121 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a11940f56ae9a00f679c0b49136d4bbac28713c3;p=ceph.git osdc/ObjectCacher: only return ENOENT if ObjectSet is flagged 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 --- diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index 065ce6b6c28e..69ad195f8515 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -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(); } } diff --git a/src/osdc/ObjectCacher.cc b/src/osdc/ObjectCacher.cc index 80679e018eca..48df3c3114f9 100644 --- a/src/osdc/ObjectCacher.cc +++ b/src/osdc/ObjectCacher.cc @@ -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::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::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::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 diff --git a/src/osdc/ObjectCacher.h b/src/osdc/ObjectCacher.h index a45b7f7a0126..4c56410bb54f 100644 --- a/src/osdc/ObjectCacher.h +++ b/src/osdc/ObjectCacher.h @@ -300,10 +300,13 @@ class ObjectCacher { xlist 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) {} + };