mirror of
https://github.com/ceph/ceph
synced 2025-02-21 01:47:25 +00:00
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 <sage@inktank.com>
This commit is contained in:
parent
bc398c0321
commit
a11940f56a
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
assert(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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -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) {}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user