At Tue, 3 Apr 2012 16:03:57 +0800, Liu Yuan wrote: > > From: Liu Yuan <tailai.ly at taobao.com> > > 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..84bffc2 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); Hmm, does this work well when multiple write requests arrive at the same time? I cannot come up with a better approach, though. BTW, do we really need to split a object cache into 4 MB files? It looks simpler and faster to use a single large and sparse file for the object caches (the file has the same size and content with the virtual disk) since we can avoid extra open/close calls. Thanks, Kazutaka |