From 3cb2413b02ff01f535b82eb630bd4f157ed7b1c8 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 6 Aug 2013 11:04:35 +0200 Subject: [PATCH] losetup: use loop-control to explicitly ask for device Now we use LOOP_CTL_GET_FREE ioctl to ask for free device, for example losetup -f foo.img Unfortunately, losetup(8) allows to ask for specified device losetup /dev/loop100 foo.img and in this case we assume that the device already exists in the system. This is incorrect, we should be able to use loop-control LOOP_CTL_ADD ioctl to ask for the specified device. Signed-off-by: Karel Zak --- include/loopdev.h | 1 + lib/loopdev.c | 30 ++++++++++++++++++++++++++++++ sys-utils/losetup.c | 2 ++ 3 files changed, 33 insertions(+) diff --git a/include/loopdev.h b/include/loopdev.h index 9f199a086..eb328a080 100644 --- a/include/loopdev.h +++ b/include/loopdev.h @@ -149,6 +149,7 @@ extern void loopcxt_enable_debug(struct loopdev_cxt *lc, int enable); extern int loopcxt_set_device(struct loopdev_cxt *lc, const char *device) __attribute__ ((warn_unused_result)); extern int loopcxt_has_device(struct loopdev_cxt *lc); +extern int loopcxt_add_device(struct loopdev_cxt *lc); extern char *loopcxt_strdup_device(struct loopdev_cxt *lc); extern const char *loopcxt_get_device(struct loopdev_cxt *lc); extern struct sysfs_cxt *loopcxt_get_sysfs(struct loopdev_cxt *lc); diff --git a/lib/loopdev.c b/lib/loopdev.c index 9789feb88..27276bfab 100644 --- a/lib/loopdev.c +++ b/lib/loopdev.c @@ -1297,6 +1297,36 @@ int loopcxt_delete_device(struct loopdev_cxt *lc) return 0; } +int loopcxt_add_device(struct loopdev_cxt *lc) +{ + int rc = -EINVAL; + int ctl, nr = -1; + const char *p, *dev = loopcxt_get_device(lc); + + if (!dev) + goto done; + + if (!(lc->flags & LOOPDEV_FL_CONTROL)) { + rc = -ENOSYS; + goto done; + } + + p = strrchr(dev, '/'); + if (!p || (sscanf(p, "/loop%d", &nr) != 1 && sscanf(p, "/%d", &nr) != 1) + || nr < 0) + goto done; + + ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC); + if (ctl >= 0) { + DBG(lc, loopdev_debug("add_device %d", nr)); + rc = ioctl(ctl, LOOP_CTL_ADD, nr); + close(ctl); + } +done: + DBG(lc, loopdev_debug("add_device done [rc=%d]", rc)); + return rc; +} + /* * Note that LOOP_CTL_GET_FREE ioctl is supported since kernel 3.1. In older * kernels we have to check all loop devices to found unused one. diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c index c1166b039..234a15b0c 100644 --- a/sys-utils/losetup.c +++ b/sys-utils/losetup.c @@ -641,6 +641,8 @@ int main(int argc, char **argv) { int hasdev = loopcxt_has_device(&lc); + if (hasdev && !is_loopdev(loopcxt_get_device(&lc))) + loopcxt_add_device(&lc); do { const char *errpre;