diff options
author | Zdenek Kabelac <zkabelac@redhat.com> | 2016-06-01 16:39:47 +0200 |
---|---|---|
committer | Zdenek Kabelac <zkabelac@redhat.com> | 2016-06-01 17:37:47 +0200 |
commit | d37a26b680f6c7ca9ec0bb1ce0cca189d19b525f (patch) | |
tree | 4ed3f0b97ed6940b04a2380959aff0903f503de3 | |
parent | 3d333e5a296eba8ba2858ca007699fe70ec8083e (diff) | |
download | lvm2-d37a26b680f6c7ca9ec0bb1ce0cca189d19b525f.tar.gz |
devices: handle partscan loop devices
Treat loop device created with 'losetup -P' as regular
partitioned device - so if it has partition table,
prevent its usage in commands like 'pvcreate'.
Before 'pvcreate /dev/loop0' could have erased and formated as PV,
after this patch, device is filtered out and cannot be used.
-rw-r--r-- | WHATS_NEW | 1 | ||||
-rw-r--r-- | lib/device/dev-type.c | 43 | ||||
-rw-r--r-- | lib/device/dev-type.h | 1 |
3 files changed, 45 insertions, 0 deletions
@@ -1,5 +1,6 @@ Version 2.02.155 - ================================ + Automatically filter out partitioned loop devices with partscan (losetup -P). Fix lvm devtypes internal error if -S used with field name from pvs/vgs/lvs. When reporting Data%,Snap%,Meta%,Cpy%Sync use single ioctl per LV. Add lvseg_percent_with_info_and_seg_status() for percent retrieval. diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c index f9f14188f..0246c09bf 100644 --- a/lib/device/dev-type.c +++ b/lib/device/dev-type.c @@ -125,6 +125,9 @@ struct dev_types *create_dev_types(const char *proc_dir, if (!strncmp("emcpower", line + i, 8) && isspace(*(line + i + 8))) dt->emcpower_major = line_maj; + if (!strncmp("loop", line + i, 4) && isspace(*(line + i + 4))) + dt->loop_major = line_maj; + if (!strncmp("power2", line + i, 6) && isspace(*(line + i + 6))) dt->power2_major = line_maj; @@ -246,6 +249,9 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev) if (MAJOR(dev->dev) == dt->blkext_major) return "BLKEXT"; + if (MAJOR(dev->dev) == dt->loop_major) + return "LOOP"; + return ""; } @@ -265,6 +271,38 @@ int major_is_scsi_device(struct dev_types *dt, int major) return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0; } + +static int _loop_is_with_partscan(struct device *dev) +{ + FILE *fp; + int partscan = 0; + char path[PATH_MAX]; + char buffer[64]; + + if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/loop/partscan", + dm_sysfs_dir(), + (int) MAJOR(dev->dev), + (int) MINOR(dev->dev)) < 0) { + log_warn("Sysfs path for partscan is too long."); + return 0; + } + + if (!(fp = fopen(path, "r"))) + return 0; /* not there -> no partscan */ + + if (!fgets(buffer, sizeof(buffer), fp)) { + log_warn("Failed to read %s.", path); + } else if (sscanf(buffer, "%d", &partscan) != 1) { + log_warn("Failed to parse %s '%s'.", path, buffer); + partscan = 0; + } + + if (fclose(fp)) + log_sys_debug("fclose", path); + + return partscan; +} + /* See linux/genhd.h and fs/partitions/msdos */ #define PART_MAGIC 0xAA55 #define PART_MAGIC_OFFSET UINT64_C(0x1FE) @@ -294,6 +332,11 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev) if (MAJOR(dev->dev) == dt->md_major) return 1; + /* All loop devices are partitionable via blkext (as of 3.2) */ + if ((MAJOR(dev->dev) == dt->loop_major) && + _loop_is_with_partscan(dev)) + return 1; + if ((parts <= 1) || (MINOR(dev->dev) % parts)) return 0; diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h index 6438b4462..267b79f6c 100644 --- a/lib/device/dev-type.h +++ b/lib/device/dev-type.h @@ -43,6 +43,7 @@ struct dev_types { int emcpower_major; int power2_major; int dasd_major; + int loop_major; struct dev_type_def dev_type_array[NUMBER_OF_MAJORS]; }; |