[parted-devel] [PATCH 2/3] libparted: improve support for partitions on loopback devices
Petr Uzel
petr.uzel at suse.cz
Thu Sep 29 13:14:23 UTC 2011
Since kernel 2.6.26, kernel allows partitions on loopback devices.
Implement support for this feature in parted.
* libparted/arch/linux.c (_sysfs_int_entry_from_dev): New function.
(_loop_get_partition_range): New function.
(_device_get_partition_range): Add special handling for loop devices.
* NEWS: Mention this change.
---
NEWS | 4 ++
libparted/arch/linux.c | 77 +++++++++++++++++++++++++++++++++++++++--------
2 files changed, 68 insertions(+), 13 deletions(-)
diff --git a/NEWS b/NEWS
index 6c55ec9..293dad8 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ GNU parted NEWS -*- outline -*-
* Noteworthy changes in release ?.? (????-??-??) [?]
+** New features
+
+ parted has improved support for partitionable loopback devices
+
** Bug fixes
libparted: no longer aborts (failed assertion) due to a nilfs2_probe bug
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index 8488b7f..ad3ee07 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -2429,31 +2429,82 @@ _blkpg_remove_partition (PedDisk* disk, int n)
}
/*
- * The number of partitions that a device can have depends on the kernel.
- * If we don't find this value in /sys/block/DEV/range, we will use our own
- * value.
+ * 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 unsigned int
-_device_get_partition_range(PedDevice* dev)
+static bool
+_sysfs_int_entry_from_dev(PedDevice const* dev, const char *entry, int *val)
{
- int range, r;
+ int r;
char path[128];
FILE* fp;
bool ok;
- r = snprintf(path, sizeof(path), "/sys/block/%s/range",
- last_component(dev->path));
+ r = snprintf(path, sizeof(path), "/sys/block/%s/%s",
+ last_component(dev->path), entry);
if (r < 0 || r >= sizeof(path))
- return MAX_NUM_PARTS;
+ return false;
fp = fopen(path, "r");
if (!fp)
- return MAX_NUM_PARTS;
+ return false;
- ok = fscanf(fp, "%d", &range) == 1;
+ ok = fscanf(fp, "%d", val) == 1;
fclose(fp);
- /* (range <= 0) is none sense.*/
+ return ok;
+}
+
+/*
+ * Returns maximum number of partitions that the loopback device can hold.
+ * First checks if the loop module exports max_part parameter (since kernel
+ * 3.0), if it does not succeed, it falls 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 = 0;
+
+ /* 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/range, we will use our own
+ * value.
+ */
+static unsigned int
+_device_get_partition_range(PedDevice const* dev)
+{
+ /* loop handling is special */
+ if (dev->type == PED_DEVICE_LOOP)
+ return _loop_get_partition_range(dev);
+
+ int range;
+ bool ok = _sysfs_int_entry_from_dev(dev, "range", &range);
+
return ok && range > 0 ? range : MAX_NUM_PARTS;
}
@@ -2478,7 +2529,7 @@ _disk_sync_part_table (PedDisk* disk)
PED_ASSERT(disk->dev != NULL);
int lpn;
- unsigned int part_range = _device_get_partition_range(disk->dev);
+ unsigned int part_range = _device_get_partition_range(disk->dev);
/* lpn = largest partition number. */
if (ped_disk_get_max_supported_partition_count(disk, &lpn))
--
1.7.3.4
More information about the parted-devel
mailing list