diff options
Diffstat (limited to 'dev.c')
-rw-r--r-- | dev.c | 60 |
1 files changed, 59 insertions, 1 deletions
@@ -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) |