diff options
author | Karel Zak | 2011-11-07 16:45:11 +0100 |
---|---|---|
committer | Karel Zak | 2011-11-07 16:45:11 +0100 |
commit | 0b14bf7af1f13b9bb0f3952af264c114bac83665 (patch) | |
tree | 5cdd9c72591d9e16a408f53d6d75a612391da3a3 | |
parent | docs: add note about config-gen purpose (diff) | |
download | kernel-qcow2-util-linux-0b14bf7af1f13b9bb0f3952af264c114bac83665.tar.gz kernel-qcow2-util-linux-0b14bf7af1f13b9bb0f3952af264c114bac83665.tar.xz kernel-qcow2-util-linux-0b14bf7af1f13b9bb0f3952af264c114bac83665.zip |
lib,loopdev: add LOOP_CTL_GET_FREE support
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r-- | include/loopdev.h | 10 | ||||
-rw-r--r-- | include/pathnames.h | 2 | ||||
-rw-r--r-- | lib/loopdev.c | 36 |
3 files changed, 40 insertions, 8 deletions
diff --git a/include/loopdev.h b/include/loopdev.h index 2c8db17f8..e675dab91 100644 --- a/include/loopdev.h +++ b/include/loopdev.h @@ -24,6 +24,13 @@ /* #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 */ }; /* diff --git a/include/pathnames.h b/include/pathnames.h index 07912bc59..e6e3d1957 100644 --- a/include/pathnames.h +++ b/include/pathnames.h @@ -121,8 +121,10 @@ #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" diff --git a/lib/loopdev.c b/lib/loopdev.c index f83a443a0..3dfa78a40 100644 --- a/lib/loopdev.c +++ b/lib/loopdev.c @@ -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; } |