summaryrefslogtreecommitdiff
path: root/slabs.c
diff options
context:
space:
mode:
Diffstat (limited to 'slabs.c')
-rw-r--r--slabs.c63
1 files changed, 35 insertions, 28 deletions
diff --git a/slabs.c b/slabs.c
index b74617e..71202fd 100644
--- a/slabs.c
+++ b/slabs.c
@@ -498,7 +498,7 @@ static int slab_rebalance_start(void) {
}
enum move_status {
- MOVE_PASS=0, MOVE_DONE, MOVE_BUSY
+ MOVE_PASS=0, MOVE_DONE, MOVE_BUSY, MOVE_LOCKED
};
/* refcount == 0 is safe since nobody can incr while cache_lock is held.
@@ -522,36 +522,42 @@ static int slab_rebalance_move(void) {
item *it = slab_rebal.slab_pos;
status = MOVE_PASS;
if (it->slabs_clsid != 255) {
- refcount = refcount_incr(&it->refcount);
- if (refcount == 1) { /* item is unlinked, unused */
- if (it->it_flags & ITEM_SLABBED) {
- /* remove from slab freelist */
- if (s_cls->slots == it) {
- s_cls->slots = it->next;
+ uint32_t hv = hash(ITEM_key(it), it->nkey, 0);
+ if (item_trylock(hv) != 0) {
+ status = MOVE_LOCKED;
+ } else {
+ refcount = refcount_incr(&it->refcount);
+ if (refcount == 1) { /* item is unlinked, unused */
+ if (it->it_flags & ITEM_SLABBED) {
+ /* remove from slab freelist */
+ if (s_cls->slots == it) {
+ s_cls->slots = it->next;
+ }
+ if (it->next) it->next->prev = it->prev;
+ if (it->prev) it->prev->next = it->next;
+ s_cls->sl_curr--;
+ status = MOVE_DONE;
+ } else {
+ status = MOVE_BUSY;
+ }
+ } else if (refcount == 2) { /* item is linked but not busy */
+ if ((it->it_flags & ITEM_LINKED) != 0) {
+ do_item_unlink_nolock(it, hash(ITEM_key(it), it->nkey, 0));
+ status = MOVE_DONE;
+ } else {
+ /* refcount == 1 + !ITEM_LINKED means the item is being
+ * uploaded to, or was just unlinked but hasn't been freed
+ * yet. Let it bleed off on its own and try again later */
+ status = MOVE_BUSY;
}
- if (it->next) it->next->prev = it->prev;
- if (it->prev) it->prev->next = it->next;
- s_cls->sl_curr--;
- status = MOVE_DONE;
- } else {
- status = MOVE_BUSY;
- }
- } else if (refcount == 2) { /* item is linked but not busy */
- if ((it->it_flags & ITEM_LINKED) != 0) {
- do_item_unlink_nolock(it, hash(ITEM_key(it), it->nkey, 0));
- status = MOVE_DONE;
} else {
- /* refcount == 1 + !ITEM_LINKED means the item is being
- * uploaded to, or was just unlinked but hasn't been freed
- * yet. Let it bleed off on its own and try again later */
+ if (settings.verbose > 2) {
+ fprintf(stderr, "Slab reassign hit a busy item: refcount: %d (%d -> %d)\n",
+ it->refcount, slab_rebal.s_clsid, slab_rebal.d_clsid);
+ }
status = MOVE_BUSY;
}
- } else {
- if (settings.verbose > 2) {
- fprintf(stderr, "Slab reassign hit a busy item: refcount: %d (%d -> %d)\n",
- it->refcount, slab_rebal.s_clsid, slab_rebal.d_clsid);
- }
- status = MOVE_BUSY;
+ item_unlock(hv);
}
}
@@ -562,9 +568,10 @@ static int slab_rebalance_move(void) {
it->slabs_clsid = 255;
break;
case MOVE_BUSY:
+ refcount_decr(&it->refcount);
+ case MOVE_LOCKED:
slab_rebal.busy_items++;
was_busy++;
- refcount_decr(&it->refcount);
break;
case MOVE_PASS:
break;