On 04/04/2012 01:19 AM, MORITA Kazutaka wrote: > Hmm, does this work well when multiple write requests arrive at the > same time? I cannot come up with a better approach, though. Hi Kazum, I give a second try, finding that Guest(RHEL 6) will wait after issue a write request till its completion at very eary bootup before 'login'. I didn't see concurrent IO from the log at that stage, so I recommend not do over-design without a practical real case that cause inconsistency. Here is the V2 path -V2 correct object_cache_lookup() usage >From a167146c55f0354a6f44fa7b28cd9a3a4e4ee089 Mon Sep 17 00:00:00 2001 From: Liu Yuan <tailai.ly at taobao.com> Date: Wed, 4 Apr 2012 17:11:45 +0800 Subject: [PATCH v2] object cache: add flush_and_delete operation If 1) VDI is opened without cache enabled and 2) we unfortunately have a cache for it previously, we should flush the cache then delete it. Signed-off-by: Liu Yuan <tailai.ly at taobao.com> --- sheep/object_cache.c | 42 ++++++++++++++++++++++++++++++++++++++++++ sheep/sheep_priv.h | 1 + sheep/store.c | 30 +++++++++++++++++++++--------- 3 files changed, 64 insertions(+), 9 deletions(-) diff --git a/sheep/object_cache.c b/sheep/object_cache.c index b59f8f7..e856be4 100644 --- a/sheep/object_cache.c +++ b/sheep/object_cache.c @@ -20,6 +20,7 @@ #include <pthread.h> #include <errno.h> #include <sys/file.h> +#include <dirent.h> #include "sheep_priv.h" #include "util.h" @@ -526,6 +527,47 @@ void object_cache_delete(uint32_t vid) } +int object_cache_flush_and_delete(struct object_cache *oc) +{ + DIR *dir; + struct dirent *d; + uint32_t vid = oc->vid; + uint32_t idx; + struct strbuf p; + int ret = 0; + + strbuf_init(&p, PATH_MAX); + strbuf_addstr(&p, cache_dir); + strbuf_addf(&p, "/%06"PRIx32, vid); + + dprintf("%"PRIx32"\n", vid); + dir = opendir(p.buf); + if (!dir) { + dprintf("%m\n"); + ret = -1; + goto out; + } + + while ((d = readdir(dir))) { + if (!strncmp(d->d_name, ".", 1)) + continue; + idx = strtoul(d->d_name, NULL, 16); + if (idx == ULLONG_MAX) + continue; + if (push_cache_object(vid, idx, 1) != SD_RES_SUCCESS) { + dprintf("failed to push %"PRIx64"\n", + idx_to_oid(vid, idx)); + ret = -1; + goto out; + } + } + + object_cache_delete(vid); +out: + strbuf_release(&p); + return ret; +} + int object_cache_init(const char *p) { int ret = 0; diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h index d687cc0..c01ee46 100644 --- a/sheep/sheep_priv.h +++ b/sheep/sheep_priv.h @@ -429,5 +429,6 @@ int object_cache_push(struct object_cache *oc); int object_cache_init(const char *p); int object_is_cached(uint64_t oid); void object_cache_delete(uint32_t vid); +int object_cache_flush_and_delete(struct object_cache *oc); #endif diff --git a/sheep/store.c b/sheep/store.c index 6661f13..d98d2b4 100644 --- a/sheep/store.c +++ b/sheep/store.c @@ -835,16 +835,28 @@ static int bypass_object_cache(struct sd_obj_req *hdr) { uint64_t oid = hdr->oid; - /* - * We assume the cached object is freshest, donot break it ever. - * This assumption is useful for non-cache requests from collie, - * which tries hard to get the newest data. - */ - if (object_is_cached(oid)) - return 0; + if (!(hdr->flags & SD_FLAG_CMD_CACHE)) { + uint32_t vid = oid_to_vid(oid); + struct object_cache *cache; - if (!(hdr->flags & SD_FLAG_CMD_CACHE)) - return 1; + cache = find_object_cache(vid, 0); + if (!cache) + return 1; + if (hdr->flags & SD_FLAG_CMD_WRITE) { + object_cache_flush_and_delete(cache); + return 1; + } else { + /* For read requet, we can read cache if any */ + uint32_t idx = data_oid_to_idx(oid); + if (is_vdi_obj(oid)) + idx |= 1 << CACHE_VDI_SHIFT; + + if (object_cache_lookup(cache, idx, 0) < 0) + return 1; + else + return 0; + } + } /* * For vmstate && vdi_attr object, we don't do caching -- 1.7.8.2 |