diff options
author | Karel Zak | 2011-11-15 12:35:23 +0100 |
---|---|---|
committer | Karel Zak | 2012-01-09 23:28:43 +0100 |
commit | 59d749c33136b85fc4a51a0af6c48cc97e3d1b31 (patch) | |
tree | baed45bc190086fc3351684d35dce1eeae770416 | |
parent | sfdisk: use is_blkdev (diff) | |
download | kernel-qcow2-util-linux-59d749c33136b85fc4a51a0af6c48cc97e3d1b31.tar.gz kernel-qcow2-util-linux-59d749c33136b85fc4a51a0af6c48cc97e3d1b31.tar.xz kernel-qcow2-util-linux-59d749c33136b85fc4a51a0af6c48cc97e3d1b31.zip |
loopdev: support LO_FLAGS_PARTSCAN flag (kernel 3.2)
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r-- | include/loopdev.h | 3 | ||||
-rw-r--r-- | lib/loopdev.c | 64 | ||||
-rw-r--r-- | partx/partx.c | 28 |
3 files changed, 72 insertions, 23 deletions
diff --git a/include/loopdev.h b/include/loopdev.h index 7c7880e1b..238b308fe 100644 --- a/include/loopdev.h +++ b/include/loopdev.h @@ -120,6 +120,8 @@ enum { /* * High-level */ +extern int loopmod_supports_partscan(void); + extern int is_loopdev(const char *device); extern int loopdev_is_autoclear(const char *device); @@ -173,6 +175,7 @@ extern int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type); extern const char *loopcxt_get_crypt_name(struct loopdev_cxt *lc); extern int loopcxt_is_autoclear(struct loopdev_cxt *lc); extern int loopcxt_is_readonly(struct loopdev_cxt *lc); +extern int loopcxt_is_partscan(struct loopdev_cxt *lc); extern int loopcxt_find_by_backing_file(struct loopdev_cxt *lc, const char *filename, uint64_t offset, int flags); diff --git a/lib/loopdev.c b/lib/loopdev.c index e0467abaa..d83124032 100644 --- a/lib/loopdev.c +++ b/lib/loopdev.c @@ -735,9 +735,63 @@ int loopcxt_get_backing_inode(struct loopdev_cxt *lc, ino_t *ino) } /* + * Check if the kernel supports partitioned loop devices. + * + * Notes: + * - kernels < 3.2 support partitioned loop devices and PT scanning + * only if max_part= module paremeter is non-zero + * + * - kernels >= 3.2 always support partitioned loop devices + * + * - kernels >= 3.2 always support BLKPG_{ADD,DEL}_PARTITION ioctls + * + * - kernels >= 3.2 enable PT scanner only if max_part= is non-zero or if the + * LO_FLAGS_PARTSCAN flag is set for the device. The PT scanner is disabled + * by default. + * + * See kernel commit e03c8dd14915fabc101aa495828d58598dc5af98. + */ +int loopmod_supports_partscan(void) +{ + int rc, ret = 0; + FILE *f; + + if (get_linux_version() >= KERNEL_VERSION(3,2,0)) + return 1; + + f = fopen("/sys/module/loop/parameters/max_part", "r"); + if (!f) + return 0; + rc = fscanf(f, "%d", &ret); + fclose(f); + return rc = 1 ? ret : 0; +} + +/* * @lc: context * - * Returns: 1 of the autoclear flags is set. + * Returns: 1 if the partscan flags is set *or* (for old kernels) partitions + * scannig is enabled for all loop devices. + */ +int loopcxt_is_partscan(struct loopdev_cxt *lc) +{ + struct sysfs_cxt *sysfs = loopcxt_get_sysfs(lc); + + if (sysfs) { + /* kernel >= 3.2 */ + int fl; + if (sysfs_read_int(sysfs, "loop/partscan", &fl) == 0) + return fl; + } + + /* old kernels (including kernels without loopN/loop/<flags> directory */ + return loopmod_supports_partscan(); +} + +/* + * @lc: context + * + * Returns: 1 if the autoclear flags is set. */ int loopcxt_is_autoclear(struct loopdev_cxt *lc) { @@ -760,7 +814,7 @@ int loopcxt_is_autoclear(struct loopdev_cxt *lc) /* * @lc: context * - * Returns: 1 of the readonly flags is set. + * Returns: 1 if the readonly flags is set. */ int loopcxt_is_readonly(struct loopdev_cxt *lc) { @@ -1076,6 +1130,12 @@ int loopcxt_delete_device(struct loopdev_cxt *lc) return 0; } +/* + * 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. + * + * See kernel commit 770fe30a46a12b6fb6b63fbe1737654d28e8484. + */ int loopcxt_find_unused(struct loopdev_cxt *lc) { int rc = -1; diff --git a/partx/partx.c b/partx/partx.c index b4a3af7a2..befc0d027 100644 --- a/partx/partx.c +++ b/partx/partx.c @@ -94,23 +94,6 @@ static int partx_flags; static struct loopdev_cxt lc; static int loopdev; -/* - * Check if the kernel supports partitioned loop devices. - * In a near future (around linux 3.2, hopefully) this will come - * always out of the box, until then we need to check. - */ -static int loopmod_supports_parts(void) -{ - int rc, ret = 0; - FILE *f = fopen("/sys/module/loop/parameters/max_part", "r"); - - if (!f) - return 0; - rc = fscanf(f, "%d", &ret); - fclose(f); - return rc = 1 ? ret : 0; -} - static void assoc_loopdev(const char *fname) { int rc; @@ -392,9 +375,12 @@ static int add_parts(int fd, const char *device, if (errfirst) add_parts_warnx(device, errfirst, errlast); - /* the kernel adds *all* loopdev partitions, so we should delete - any extra, unwanted ones, when the -n option is passed */ - if (loopdev && (lower || upper)) { + /* + * The kernel with enabled partitions scanner for loop devices add *all* + * partitions, so we should delete any extra, unwanted ones, when the -n + * option is passed. + */ + if (loopdev && loopcxt_is_partscan(&lc) && (lower || upper)) { for (i = 0; i < nparts; i++) { blkid_partition par = blkid_partlist_get_partition(ls, i); int n = blkid_partition_get_partno(par); @@ -841,7 +827,7 @@ int main(int argc, char **argv) if (what == ACT_DELETE) errx(EXIT_FAILURE, _("%s: cannot delete partitions"), wholedisk); - if (!loopmod_supports_parts()) + if (!loopmod_supports_partscan()) errx(EXIT_FAILURE, _("%s: partitioned loop devices unsupported"), wholedisk); assoc_loopdev(wholedisk); |