]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib,loopdev: add LOOP_CTL_GET_FREE support
authorKarel Zak <kzak@redhat.com>
Mon, 7 Nov 2011 15:45:11 +0000 (16:45 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 7 Nov 2011 15:45:11 +0000 (16:45 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
include/loopdev.h
include/pathnames.h
lib/loopdev.c

index 2c8db17f8af6b9c5c166e3ca0054d06a1dfb3d47..e675dab91ba75dab75d9790cee025cc40901c29f 100644 (file)
 /* #define LOOP_CHANGE_FD      0x4C06 */
 #define LOOP_SET_CAPACITY      0x4C07
 
+/* /dev/loop-control interface */
+#ifndef LOOP_CTL_ADD
+# define LOOP_CTL_ADD          0x4C80
+# define LOOP_CTL_REMOVE       0x4C81
+# define LOOP_CTL_GET_FREE     0x4C82
+#endif
+
 /*
  * loop_info.lo_flags
  */
@@ -104,7 +111,8 @@ enum {
        LOOPDEV_FL_OFFSET       = (1 << 4),
        LOOPDEV_FL_NOSYSFS      = (1 << 5),
        LOOPDEV_FL_NOIOCTL      = (1 << 6),
-       LOOPDEV_FL_DEVSUBDIR    = (1 << 7)
+       LOOPDEV_FL_DEVSUBDIR    = (1 << 7),
+       LOOPDEV_FL_CONTROL      = (1 << 8),     /* system with /dev/loop-control */
 };
 
 /*
index 07912bc595e6598e4d59d8669ba9678b2747eff3..e6e3d1957534be208dc3f697d54d146430f8ae05 100644 (file)
 #endif
 
 #define _PATH_DEV_LOOP         "/dev/loop"
+#define _PATH_DEV_LOOPCTL      "/dev/loop-control"
 #define _PATH_DEV_TTY          "/dev/tty"
 
+
 /* udev paths */
 #define _PATH_DEV_BYLABEL      "/dev/disk/by-label"
 #define _PATH_DEV_BYUUID       "/dev/disk/by-uuid"
index f83a443a0c6c0e1ed224a6eed97d6c2e1fb5ece0..3dfa78a400b36cc14952096128024787fcc88af5 100644 (file)
@@ -139,6 +139,8 @@ int loopcxt_set_device(struct loopdev_cxt *lc, const char *device)
  */
 int loopcxt_init(struct loopdev_cxt *lc, int flags)
 {
+       struct stat st;
+
        if (!lc)
                return -EINVAL;
 
@@ -153,6 +155,9 @@ int loopcxt_init(struct loopdev_cxt *lc, int flags)
                 */
                lc->flags |= LOOPDEV_FL_NOIOCTL;
 
+       if (!(lc->flags & LOOPDEV_FL_CONTROL) && !stat(_PATH_DEV_LOOPCTL, &st))
+               lc->flags |= LOOPDEV_FL_CONTROL;
+
        return 0;
 }
 
@@ -917,18 +922,35 @@ int loopcxt_delete_device(struct loopdev_cxt *lc)
 
 int loopcxt_find_unused(struct loopdev_cxt *lc)
 {
-       int rc;
+       int rc = -1;
 
        DBG(lc, loopdev_debug("find_unused requested"));
 
-       rc = loopcxt_init_iterator(lc, LOOPITER_FL_FREE);
-       if (rc)
-               return rc;
+       if (lc->flags & LOOPDEV_FL_CONTROL) {
+               int ctl = open(_PATH_DEV_LOOPCTL, O_RDWR);
 
-       rc = loopcxt_next(lc);
-       loopcxt_deinit_iterator(lc);
+               if (ctl >= 0)
+                       rc = ioctl(ctl, LOOP_CTL_GET_FREE);
+               if (rc >= 0) {
+                       char name[16];
+                       snprintf(name, sizeof(name), "loop%d", rc);
+
+                       rc = loopiter_set_device(lc, name);
+               }
+               if (ctl >= 0)
+                       close(ctl);
+               DBG(lc, loopdev_debug("find_unused by loop-control [rc=%d]", rc));
+       }
 
-       DBG(lc, loopdev_debug("find_unused done [rc=%d]", rc));
+       if (rc < 0) {
+               rc = loopcxt_init_iterator(lc, LOOPITER_FL_FREE);
+               if (rc)
+                       return rc;
+
+               rc = loopcxt_next(lc);
+               loopcxt_deinit_iterator(lc);
+               DBG(lc, loopdev_debug("find_unused by scan [rc=%d]", rc));
+       }
        return rc;
 }