]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
Implement loopcxt_check_conflict()
authorStanislav Brabec <sbrabec@suse.cz>
Thu, 14 Jul 2016 13:29:21 +0000 (15:29 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 3 Aug 2016 09:53:28 +0000 (11:53 +0200)
Add a function that searches for a possible conflicting (i. e. overlaying loop
device).

Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
include/loopdev.h
lib/loopdev.c

index 57fcc1b10de5e317e2b7c503a83f7491e90bec6f..706388e86a685ac26e9e56d4fa6291b8c5151cad 100644 (file)
@@ -188,6 +188,9 @@ extern int loopcxt_find_by_backing_file(struct loopdev_cxt *lc,
                                const char *filename,
                                uint64_t offset, uint64_t sizelimit,
                                int flags);
+extern int loopcxt_check_conflict(struct loopdev_cxt *lc,
+                                 const char *filename,
+                                 uint64_t offset, uint64_t sizelimit);
 
 extern int loopcxt_is_used(struct loopdev_cxt *lc,
                     struct stat *st,
index 2db80fc05a4c24766ec96379299e03d5d99d34a7..4606003634ff66437aacea559b5145caf2628348 100644 (file)
@@ -1565,6 +1565,61 @@ int loopcxt_find_by_backing_file(struct loopdev_cxt *lc, const char *filename,
        return rc;
 }
 
+/*
+ * Returns: 0 = conflict, < 0 error, 1 no conflicting device
+ */
+int loopcxt_check_conflict(struct loopdev_cxt *lc, const char *filename,
+                          uint64_t offset, uint64_t sizelimit)
+{
+       int rc, hasst;
+       struct stat st;
+
+       if (!filename)
+               return -EINVAL;
+
+       hasst = !stat(filename, &st);
+
+       rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED);
+       if (rc)
+               return rc;
+
+       while ((rc = loopcxt_next(lc)) == 0) {
+               uint64_t lc_sizelimit, lc_offset;
+
+               rc = loopcxt_is_used(lc, hasst ? &st : NULL,
+                                    filename, offset, sizelimit, 0);
+               if (!rc)
+                       continue;
+               if (rc != 1)
+                       break;
+               DBG(CXT, ul_debugobj(lc, "found %s backed by %s",
+                       loopcxt_get_device(lc), filename));
+               rc = loopcxt_get_offset(lc, &lc_offset);
+               if (rc) {
+                       DBG(CXT, ul_debugobj(lc, "failed to get offset for device %s",
+                               loopcxt_get_device(lc)));
+                       break;
+               }
+               rc = loopcxt_get_sizelimit(lc, &lc_sizelimit);
+               if (rc) {
+                       DBG(CXT, ul_debugobj(lc, "failed to get sizelimit for device %s",
+                               loopcxt_get_device(lc)));
+                       break;
+               }
+
+               if (lc_sizelimit != 0 && offset >= lc_offset + lc_sizelimit)
+                       continue;
+               if (sizelimit != 0 && offset + sizelimit <= lc_offset)
+                       continue;
+               DBG(CXT, ul_debugobj(lc, "overlapping loop device %s",
+                       loopcxt_get_device(lc)));
+                       rc = 0;
+                       break;
+       }
+       loopcxt_deinit_iterator(lc);
+       return rc;
+}
+
 /*
  * Returns allocated string with device name
  */