/* #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
*/
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 */
};
/*
#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"
*/
int loopcxt_init(struct loopdev_cxt *lc, int flags)
{
+ struct stat st;
+
if (!lc)
return -EINVAL;
*/
lc->flags |= LOOPDEV_FL_NOIOCTL;
+ if (!(lc->flags & LOOPDEV_FL_CONTROL) && !stat(_PATH_DEV_LOOPCTL, &st))
+ lc->flags |= LOOPDEV_FL_CONTROL;
+
return 0;
}
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;
}