From 526b74a42392715e72634faf51a5e92314c01c6a Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 15 Jun 2013 11:22:11 +0000 Subject: svc: implement top-level by_mog_devid hash This will allow us to lookup devices for per-(mog)device I/O queues. --- cmogstored.h | 6 +++++- dev.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- svc.c | 5 +++++ svc_dev.c | 25 ++++++++----------------- 4 files changed, 77 insertions(+), 19 deletions(-) diff --git a/cmogstored.h b/cmogstored.h index 2937049..d9e74fc 100644 --- a/cmogstored.h +++ b/cmogstored.h @@ -142,6 +142,8 @@ struct mog_svc { /* private */ DIR *dir; + pthread_mutex_t by_mog_devid_lock; + Hash_table *by_mog_devid; Hash_table *by_st_dev; pthread_mutex_t devstats_lock; struct mog_queue *queue; @@ -331,8 +333,10 @@ size_t mog_svc_each(Hash_processor processor, void *data); void mog_svc_upgrade_prepare(void); /* dev.c */ -struct mog_dev * mog_dev_new(struct mog_svc *, uint32_t mog_devid); +struct mog_dev * mog_dev_for(struct mog_svc *, uint32_t mog_devid); int mog_dev_mkusage(const struct mog_dev *, struct mog_svc *); +size_t mog_dev_hash(const void *, size_t tablesize); +bool mog_dev_cmp(const void *a, const void *b); /* valid_path.rl */ int mog_valid_path(const char *buf, size_t len); diff --git a/dev.c b/dev.c index aa915b9..7454b2d 100644 --- a/dev.c +++ b/dev.c @@ -4,7 +4,7 @@ */ #include "cmogstored.h" -struct mog_dev * mog_dev_new(struct mog_svc *svc, uint32_t mog_devid) +static struct mog_dev *mog_dev_new(struct mog_svc *svc, uint32_t mog_devid) { struct mog_dev *dev; struct stat sb; @@ -29,6 +29,64 @@ struct mog_dev * mog_dev_new(struct mog_svc *svc, uint32_t mog_devid) return dev; } +struct mog_dev *mog_dev_for(struct mog_svc *svc, uint32_t mog_devid) +{ + struct mog_dev finder; + struct mog_dev *ret; + + finder.devid = mog_devid; + + CHECK(int, 0, pthread_mutex_lock(&svc->by_mog_devid_lock)); + ret = hash_lookup(svc->by_mog_devid, &finder); + if (ret) { + struct stat sb; + + /* + * devXXX dir existed before, but is no longer readable + * Possible FS/device error, it could come back, so do + * not remove here. + */ + if (mog_stat(svc, ret->prefix, &sb) < 0) + goto out; + + /* st_dev may change due to remount, update if needed */ + ret->st_dev = sb.st_dev; + } else { /* create a new dev */ + ret = mog_dev_new(svc, mog_devid); + + if (!ret) + goto out; /* could not stat */ + + switch (hash_insert_if_absent(svc->by_mog_devid, ret, NULL)) { + case 0: + assert(0 && "mog_dev existed while adding"); + abort(); + case 1: break; /* OK, inserted */ + default: mog_oom(); + } + } +out: + CHECK(int, 0, pthread_mutex_unlock(&svc->by_mog_devid_lock)); + + return ret; +} + + +size_t mog_dev_hash(const void *x, size_t tablesize) +{ + const struct mog_dev *dev = x; + + return dev->devid % tablesize; +} + +bool mog_dev_cmp(const void *a, const void *b) +{ + const struct mog_dev *dev_a = a; + const struct mog_dev *dev_b = b; + + return dev_a->devid == dev_b->devid; +} + static int emit_usage( const struct mog_dev *dev, struct mog_svc *svc, int fd, struct statvfs *v) diff --git a/svc.c b/svc.c index 1bf0d45..6eea3e3 100644 --- a/svc.c +++ b/svc.c @@ -22,6 +22,8 @@ static void svc_free(void *ptr) mog_free(svc->docroot); if (svc->by_st_dev) hash_free(svc->by_st_dev); + if (svc->by_mog_devid) + hash_free(svc->by_mog_devid); free(svc); } @@ -93,6 +95,9 @@ struct mog_svc * mog_svc_new(const char *docroot) svc->mkcol_perms = (~mog_umask) & 0777; svc->idle_timeout = 5; CHECK(int, 0, pthread_mutex_init(&svc->devstats_lock, NULL)); + CHECK(int, 0, pthread_mutex_init(&svc->by_mog_devid_lock, NULL)); + svc->by_mog_devid = hash_initialize(7, NULL, mog_dev_hash, + mog_dev_cmp, free); switch (hash_insert_if_absent(by_docroot, svc, NULL)) { case 0: diff --git a/svc_dev.c b/svc_dev.c index 68d8e3b..d7e1dcd 100644 --- a/svc_dev.c +++ b/svc_dev.c @@ -38,28 +38,19 @@ static void devlist_free(void *x) free(devlist); } -static size_t devid_hash(const void *x, size_t tablesize) -{ - const struct mog_dev *dev = x; - - return dev->devid % tablesize; -} - -static bool devid_cmp(const void *a, const void *b) -{ - const struct mog_dev *dev_a = a; - const struct mog_dev *dev_b = b; - - return dev_a->devid == dev_b->devid; -} - static struct mog_devlist * mog_devlist_new(dev_t st_dev) { struct mog_devlist *devlist = xmalloc(sizeof(struct mog_devlist)); devlist->st_dev = st_dev; devlist->by_mogdevid = hash_initialize(7, NULL, - devid_hash, devid_cmp, free); + mog_dev_hash, mog_dev_cmp, + + /* + * elements are freed when + * svc->by_mog_devid is freed + */ + NULL); return devlist; } @@ -126,7 +117,7 @@ static int svc_scandev(struct mog_svc *svc, size_t *nr, mog_scandev_cb cb) if (*end != 0) continue; if (mog_devid > 0xffffff) continue; /* MEDIUMINT in DB */ - dev = mog_dev_new(svc, (uint32_t)mog_devid); + dev = mog_dev_for(svc, (uint32_t)mog_devid); if (!dev) continue; devlist = svc_devlist(svc, dev->st_dev); -- cgit v1.2.3-24-ge0c7