Index: parted-2.4/NEWS =================================================================== --- parted-2.4.orig/NEWS +++ parted-2.4/NEWS @@ -2,6 +2,10 @@ GNU parted NEWS * Noteworthy changes in release 2.4 (2011-05-18) [stable] +** New features + + parted has improved support for partitionable loopback devices + ** Bug fixes parted no longer allows the modification of certain in-use partitions. Index: parted-2.4/include/parted/device.h =================================================================== --- parted-2.4.orig/include/parted/device.h +++ parted-2.4/include/parted/device.h @@ -48,7 +48,8 @@ typedef enum { PED_DEVICE_SDMMC = 14, PED_DEVICE_VIRTBLK = 15, PED_DEVICE_AOE = 16, - PED_DEVICE_MD = 17 + PED_DEVICE_MD = 17, + PED_DEVICE_LOOP = 18 } PedDeviceType; typedef struct _PedDevice PedDevice; Index: parted-2.4/libparted/arch/linux.c =================================================================== --- parted-2.4.orig/libparted/arch/linux.c +++ parted-2.4/libparted/arch/linux.c @@ -586,7 +586,7 @@ _device_probe_type (PedDevice* dev) } else if (_is_virtblk_major(dev_major)) { dev->type = PED_DEVICE_VIRTBLK; } else if (dev_major == LOOP_MAJOR) { - dev->type = PED_DEVICE_FILE; + dev->type = PED_DEVICE_LOOP; } else if (dev_major == MD_MAJOR) { dev->type = PED_DEVICE_MD; } else { @@ -1376,6 +1376,11 @@ linux_new (const char* path) goto error_free_arch_specific; break; + case PED_DEVICE_LOOP: + if (!init_generic (dev, _("Loopback device"))) + goto error_free_arch_specific; + break; + case PED_DEVICE_DM: { char* type; @@ -2411,6 +2416,61 @@ _blkpg_remove_partition (PedDisk* disk, BLKPG_DEL_PARTITION); } +/* Read the integer from /sys/block/DEV_BASE/ENTRY and set *VAL + to that value, where DEV_BASE is the last component of DEV->path. + Upon success, return true. Otherwise, return false. */ +static bool +_sysfs_int_entry_from_dev(PedDevice const* dev, const char *entry, int *val) +{ + char path[128]; + int r = snprintf(path, sizeof(path), "/sys/block/%s/%s", + last_component(dev->path), entry); + if (r < 0 || r >= sizeof(path)) + return false; + + FILE *fp = fopen(path, "r"); + if (!fp) + return false; + + bool ok = fscanf(fp, "%d", val) == 1; + fclose(fp); + + return ok; +} + +/* Return the maximum number of partitions that the loopback device can hold. + First, check the loop-module-exported max_part parameter (since linux-3.0). + If that is not available, fall back to checking ext_range, which seems to + have (for some reason) different semantics compared to other devices; + specifically, ext_range <= 1 means that the loopback device does + not support partitions. */ +static unsigned int +_loop_get_partition_range(PedDevice const* dev) +{ + int max_part; + bool ok = false; + + /* max_part module param is exported since kernel 3.0 */ + FILE *fp = fopen("/sys/module/loop/parameters/max_part", "r"); + if (fp) { + ok = fscanf(fp, "%d", &max_part) == 1; + fclose(fp); + } + + if (ok) + return max_part > 0 ? max_part : 0; + + /* + * max_part is not exported - check ext_range; + * device supports partitions if ext_range > 1 + */ + int range; + ok = _sysfs_int_entry_from_dev(dev, "range", &range); + + return ok && range > 1 ? range : 0; +} + + /* * The number of partitions that a device can have depends on the kernel. * If we don't find this value in /sys/block/DEV/ext_range, we will use our own @@ -2419,22 +2479,12 @@ _blkpg_remove_partition (PedDisk* disk, static unsigned int _device_get_partition_range(PedDevice* dev) { - int range, r; - char path[128]; - FILE* fp; - bool ok; - - r = snprintf(path, sizeof(path), "/sys/block/%s/ext_range", - last_component(dev->path)); - if (r < 0 || r >= sizeof(path)) - return MAX_NUM_PARTS; + /* loop handling is special */ + if (dev->type == PED_DEVICE_LOOP) + return _loop_get_partition_range(dev); - fp = fopen(path, "r"); - if (!fp) - return MAX_NUM_PARTS; - - ok = fscanf(fp, "%d", &range) == 1; - fclose(fp); + int range; + bool ok = _sysfs_int_entry_from_dev(dev, "ext_range", &range); /* (range <= 0) is none sense.*/ return ok && range > 0 ? range : MAX_NUM_PARTS; Index: parted-2.4/parted/parted.c =================================================================== --- parted-2.4.orig/parted/parted.c +++ parted-2.4/parted/parted.c @@ -1464,7 +1464,7 @@ _print_disk_info (const PedDevice *dev, "cpqarray", "file", "ataraid", "i2o", "ubd", "dasd", "viodasd", "sx8", "dm", "xvd", "sd/mmc", "virtblk", "aoe", - "md"}; + "md", "loopback"}; char* start = ped_unit_format (dev, 0); PedUnit default_unit = ped_unit_get_default ();