OPTION(rbd_cache_max_dirty, OPT_LONGLONG, 24<<20) // dirty limit in bytes - set to 0 for write-through caching
OPTION(rbd_cache_target_dirty, OPT_LONGLONG, 16<<20) // target dirty limit in bytes
OPTION(rbd_cache_max_dirty_age, OPT_FLOAT, 1.0) // seconds in cache before writeback starts
-OPTION(rbd_cache_max_dirty_object, OPT_INT, 0) // dirty limit for objects - set to 0 for auto calculate from rbd_cache_size
OPTION(rbd_cache_block_writes_upfront, OPT_BOOL, false) // whether to block writes to the cache before the aio_write call completes (true), or block before the aio completion is called (false)
OPTION(rbd_concurrent_management_ops, OPT_INT, 10) // how many operations can be in flight for a management operation like deleting or resizing an image
OPTION(rbd_balance_snap_reads, OPT_BOOL, false)
// size object cache appropriately
if (object_cacher) {
- uint64_t obj = cct->_conf->rbd_cache_max_dirty_object;
- if (!obj) {
- obj = cct->_conf->rbd_cache_size / (1ull << order);
- obj = obj * 4 + 10;
- }
+ uint64_t obj = cct->_conf->rbd_cache_size / (1ull << order);
ldout(cct, 10) << " cache bytes " << cct->_conf->rbd_cache_size << " order " << (int)order
<< " -> about " << obj << " objects" << dendl;
- object_cacher->set_max_objects(obj);
+ object_cacher->set_max_objects(obj * 4 + 10);
}
ldout(cct, 10) << "init_layout stripe_unit " << stripe_unit
cache_lock.Unlock();
if (unclean) {
lderr(cct) << "could not release all objects from cache: "
- << unclean << " bytes remain" << dendl;
+ << unclean << " bytes remain" << dendl;
return -EBUSY;
}
return r;
assert(bh_lru_rest.lru_get_size() == 0);
assert(bh_lru_dirty.lru_get_size() == 0);
assert(ob_lru.lru_get_size() == 0);
- assert(dirty_or_tx_bh.empty());
+ assert(dirty_bh.empty());
}
void ObjectCacher::perf_start()
// we'll need to wait for all objects to flush!
C_GatherBuilder gather(cct);
- set<Object*> waitfor_commit;
-
- set<BufferHead*>::iterator next, it;
- next = it = dirty_or_tx_bh.begin();
- while (it != dirty_or_tx_bh.end()) {
- next++;
- BufferHead *bh = *it;
- waitfor_commit.insert(bh->ob);
- bh_write(bh);
- it = next;
- }
- for (set<Object*>::iterator i = waitfor_commit.begin();
- i != waitfor_commit.end(); ++i) {
+ for (xlist<Object*>::iterator i = oset->objects.begin();
+ !i.end(); ++i) {
Object *ob = *i;
- // we'll need to gather...
- ldout(cct, 10) << "flush_set " << oset << " will wait for ack tid "
- << ob->last_write_tid
- << " on " << *ob
- << dendl;
- ob->waitfor_commit[ob->last_write_tid].push_back(gather.new_sub());
+ if (ob->dirty_or_tx == 0)
+ continue;
+
+ if (!flush(ob, 0, 0)) {
+ // we'll need to gather...
+ ldout(cct, 10) << "flush_set " << oset << " will wait for ack tid "
+ << ob->last_write_tid
+ << " on " << *ob
+ << dendl;
+ ob->waitfor_commit[ob->last_write_tid].push_back(gather.new_sub());
+ }
}
return _flush_set_finish(&gather, onfinish);
void ObjectCacher::bh_set_state(BufferHead *bh, int s)
{
assert(lock.is_locked());
- int state = bh->get_state();
// move between lru lists?
- if (s == BufferHead::STATE_DIRTY && state != BufferHead::STATE_DIRTY) {
+ if (s == BufferHead::STATE_DIRTY && bh->get_state() != BufferHead::STATE_DIRTY) {
bh_lru_rest.lru_remove(bh);
bh_lru_dirty.lru_insert_top(bh);
- } else if (s != BufferHead::STATE_DIRTY && state == BufferHead::STATE_DIRTY) {
+ dirty_bh.insert(bh);
+ }
+ if (s != BufferHead::STATE_DIRTY && bh->get_state() == BufferHead::STATE_DIRTY) {
bh_lru_dirty.lru_remove(bh);
bh_lru_rest.lru_insert_top(bh);
+ dirty_bh.erase(bh);
}
-
- if ((s == BufferHead::STATE_TX ||
- s == BufferHead::STATE_DIRTY) &&
- state != BufferHead::STATE_TX &&
- state != BufferHead::STATE_DIRTY) {
- dirty_or_tx_bh.insert(bh);
- } else if ((state == BufferHead::STATE_TX ||
- state == BufferHead::STATE_DIRTY) &&
- s != BufferHead::STATE_TX &&
- s != BufferHead::STATE_DIRTY) {
- dirty_or_tx_bh.erase(bh);
- }
-
if (s != BufferHead::STATE_ERROR && bh->get_state() == BufferHead::STATE_ERROR) {
bh->error = 0;
}
ob->add_bh(bh);
if (bh->is_dirty()) {
bh_lru_dirty.lru_insert_top(bh);
- dirty_or_tx_bh.insert(bh);
+ dirty_bh.insert(bh);
} else {
bh_lru_rest.lru_insert_top(bh);
}
-
- if (bh->is_tx()) {
- dirty_or_tx_bh.insert(bh);
- }
bh_stat_add(bh);
}
ob->remove_bh(bh);
if (bh->is_dirty()) {
bh_lru_dirty.lru_remove(bh);
- dirty_or_tx_bh.erase(bh);
+ dirty_bh.erase(bh);
} else {
bh_lru_rest.lru_remove(bh);
}
-
- if (bh->is_tx()) {
- dirty_or_tx_bh.erase(bh);
- }
bh_stat_sub(bh);
}