diff options
author | Eric Wong <normalperson@yhbt.net> | 2013-06-15 11:22:11 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-06-15 11:22:11 +0000 |
commit | 526b74a42392715e72634faf51a5e92314c01c6a (patch) | |
tree | e4d417af533d81d16df429844f19888306959c4f | |
parent | df5a65a089c82659ab5e2636d140822ea18674b8 (diff) | |
download | cmogstored-526b74a42392715e72634faf51a5e92314c01c6a.tar.gz |
This will allow us to lookup devices for per-(mog)device I/O queues.
-rw-r--r-- | cmogstored.h | 6 | ||||
-rw-r--r-- | dev.c | 60 | ||||
-rw-r--r-- | svc.c | 5 | ||||
-rw-r--r-- | 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); @@ -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) @@ -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: @@ -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); |