[sheepdog] [PATCH 6/6] object cache: delay reclaimer for a newly pulled object
Liu Yuan
namei.unix at gmail.com
Mon Jan 21 13:32:31 CET 2013
From: Liu Yuan <tailai.ly at taobao.com>
We try to delay reclaim objects to avoid object ping-pong because the pulled
object is clean and likely to be reclaimed in a cache over high watermark. We
can't simply pass without waking up reclaimer because the cache is easy to be
filled full with a read storm.
Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
sheep/object_cache.c | 36 +++++++++++++++++++++++++-----------
sheep/ops.c | 2 +-
sheep/sheep_priv.h | 2 +-
3 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/sheep/object_cache.c b/sheep/object_cache.c
index bd0ea98..70f6f56 100644
--- a/sheep/object_cache.c
+++ b/sheep/object_cache.c
@@ -448,12 +448,21 @@ static void do_reclaim_object(struct object_cache *oc)
pthread_yield();
}
+struct reclaim_work {
+ struct work work;
+ int delay;
+};
+
static void do_reclaim(struct work *work)
{
+ struct reclaim_work *rw = container_of(work, struct reclaim_work,
+ work);
struct object_cache *cache;
struct hlist_node *node;
int i, j;
+ if (rw->delay)
+ sleep(rw->delay);
/* We choose a random victim to avoid reclaim the same one every time */
j = random();
for (i = 0; i < HASH_SIZE; i++) {
@@ -540,9 +549,9 @@ out:
return cache;
}
-void object_cache_try_to_reclaim(void)
+void object_cache_try_to_reclaim(int delay)
{
- struct work *work;
+ struct reclaim_work *rw;
if (!sys->object_cache_size)
return;
@@ -554,10 +563,11 @@ void object_cache_try_to_reclaim(void)
/* the cache is already in reclaim, */
return;
- work = xzalloc(sizeof(struct work));
- work->fn = do_reclaim;
- work->done = reclaim_done;
- queue_work(sys->reclaim_wqueue, work);
+ rw = xzalloc(sizeof(struct reclaim_work));
+ rw->delay = delay;
+ rw->work.fn = do_reclaim;
+ rw->work.done = reclaim_done;
+ queue_work(sys->reclaim_wqueue, &rw->work);
}
static inline struct object_cache_entry *
@@ -631,7 +641,7 @@ static int object_cache_lookup(struct object_cache *oc, uint32_t idx,
ret = SD_RES_EIO;
} else {
add_to_lru_cache(oc, idx, writeback);
- object_cache_try_to_reclaim();
+ object_cache_try_to_reclaim(0);
}
close(fd);
@@ -733,14 +743,18 @@ static int object_cache_pull(struct object_cache *oc, uint32_t idx)
ret = create_cache_object(oc, idx, buf, rsp->data_length,
rsp->obj.offset, data_length);
/*
- * We don't try to reclaim objects to avoid object ping-pong
+ * We try to delay reclaim objects to avoid object ping-pong
* because the pulled object is clean and likely to be reclaimed
- * in a full cache.
+ * in a cache over high watermark. We can't simply pass without
+ * waking up reclaimer because the cache is easy to be filled
+ * full with a read storm.
*/
- if (ret == SD_RES_SUCCESS)
+ if (ret == SD_RES_SUCCESS) {
add_to_lru_cache(oc, idx, false);
- else if (ret == SD_RES_OID_EXIST)
+ object_cache_try_to_reclaim(1);
+ } else if (ret == SD_RES_OID_EXIST) {
ret = SD_RES_SUCCESS;
+ }
}
free(buf);
out:
diff --git a/sheep/ops.c b/sheep/ops.c
index f3e68a9..3cdadfb 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -642,7 +642,7 @@ static int local_set_cache_size(const struct sd_req *req, struct sd_rsp *rsp,
uatomic_set(&sys->object_cache_size, cache_size);
dprintf("Max cache size set to %dM\n", cache_size);
- object_cache_try_to_reclaim();
+ object_cache_try_to_reclaim(0);
return SD_RES_SUCCESS;
}
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index 44380fc..b6a703f 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -383,7 +383,7 @@ void object_cache_format(void);
bool bypass_object_cache(const struct request *req);
bool object_is_cached(uint64_t oid);
-void object_cache_try_to_reclaim(void);
+void object_cache_try_to_reclaim(int);
int object_cache_handle_request(struct request *req);
int object_cache_write(uint64_t oid, char *data, unsigned int datalen,
uint64_t offset, uint16_t flags, bool create);
--
1.7.9.5
More information about the sheepdog
mailing list