about summary refs log tree commit homepage
path: root/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'dev.c')
-rw-r--r--dev.c60
1 files changed, 59 insertions, 1 deletions
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)