|
|
2a8729 |
From 31ab97cfe0233191a73a1dd9cb7cd193451491da Mon Sep 17 00:00:00 2001
|
|
|
2a8729 |
From: "Brian C. Lane" <bcl@redhat.com>
|
|
|
2a8729 |
Date: Fri, 11 Aug 2017 08:37:11 -0700
|
|
|
2a8729 |
Subject: [PATCH 46/48] libparted: Backport partition resize code
|
|
|
2a8729 |
|
|
|
2a8729 |
This adds _blkpg_resize_partition, _dm_resize_partition, and adjust the
|
|
|
2a8729 |
current code to support it. Changes are somewhat extensive, since they
|
|
|
2a8729 |
also touch _disk_sync_part_table.
|
|
|
2a8729 |
|
|
|
2a8729 |
This is based on code from commit f09ca967a0bc443b869a6fad5b5ffe8e95c3fe9a
|
|
|
2a8729 |
|
|
|
2a8729 |
Related: rhbz#1423357
|
|
|
2a8729 |
---
|
|
|
2a8729 |
libparted/arch/linux.c | 673 +++++++++++++++++++++++++++++--------------------
|
|
|
2a8729 |
1 file changed, 403 insertions(+), 270 deletions(-)
|
|
|
2a8729 |
|
|
|
2a8729 |
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
|
|
|
2a8729 |
index fa329f4..6e78faf 100644
|
|
|
2a8729 |
--- a/libparted/arch/linux.c
|
|
|
2a8729 |
+++ b/libparted/arch/linux.c
|
|
|
2a8729 |
@@ -288,6 +288,7 @@ struct blkdev_ioctl_param {
|
|
|
2a8729 |
|
|
|
2a8729 |
static char* _device_get_part_path (PedDevice* dev, int num);
|
|
|
2a8729 |
static int _partition_is_mounted_by_path (const char* path);
|
|
|
2a8729 |
+static unsigned int _device_get_partition_range(PedDevice const* dev);
|
|
|
2a8729 |
static int _device_open (PedDevice* dev, int flags);
|
|
|
2a8729 |
static int _device_open_ro (PedDevice* dev);
|
|
|
2a8729 |
static int _device_close (PedDevice* dev);
|
|
|
2a8729 |
@@ -446,6 +447,17 @@ _is_blkext_major (int major)
|
|
|
2a8729 |
|
|
|
2a8729 |
#ifdef ENABLE_DEVICE_MAPPER
|
|
|
2a8729 |
static int
|
|
|
2a8729 |
+_dm_task_run_wait (struct dm_task *task, uint32_t cookie)
|
|
|
2a8729 |
+{
|
|
|
2a8729 |
+ int rc = 0;
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ rc = dm_task_run (task);
|
|
|
2a8729 |
+ dm_udev_wait (cookie);
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ return rc;
|
|
|
2a8729 |
+}
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+static int
|
|
|
2a8729 |
_is_dm_major (int major)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
return _major_type_in_devices (major, "device-mapper");
|
|
|
2a8729 |
@@ -1521,6 +1533,7 @@ _flush_cache (PedDevice* dev)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
|
|
|
2a8729 |
int i;
|
|
|
2a8729 |
+ int lpn = _device_get_partition_range(dev);
|
|
|
2a8729 |
|
|
|
2a8729 |
if (dev->read_only)
|
|
|
2a8729 |
return;
|
|
|
2a8729 |
@@ -1532,7 +1545,7 @@ _flush_cache (PedDevice* dev)
|
|
|
2a8729 |
if (_have_kern26())
|
|
|
2a8729 |
return;
|
|
|
2a8729 |
|
|
|
2a8729 |
- for (i = 1; i < 16; i++) {
|
|
|
2a8729 |
+ for (i = 1; i < lpn; i++) {
|
|
|
2a8729 |
char* name;
|
|
|
2a8729 |
int fd;
|
|
|
2a8729 |
|
|
|
2a8729 |
@@ -2268,28 +2281,63 @@ zasprintf (const char *format, ...)
|
|
|
2a8729 |
return r < 0 ? NULL : resultp;
|
|
|
2a8729 |
}
|
|
|
2a8729 |
|
|
|
2a8729 |
+#ifdef ENABLE_DEVICE_MAPPER
|
|
|
2a8729 |
+static char *
|
|
|
2a8729 |
+dm_canonical_path (PedDevice const *dev)
|
|
|
2a8729 |
+{
|
|
|
2a8729 |
+ LinuxSpecific const *arch_specific = LINUX_SPECIFIC (dev);
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ /* Get map name from devicemapper */
|
|
|
2a8729 |
+ struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
|
|
|
2a8729 |
+ if (!task)
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ if (!dm_task_set_major_minor (task, arch_specific->major,
|
|
|
2a8729 |
+ arch_specific->minor, 0))
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ if (!dm_task_run(task))
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ char *dev_name = zasprintf ("/dev/mapper/%s", dm_task_get_name (task));
|
|
|
2a8729 |
+ if (dev_name == NULL)
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ dm_task_destroy (task);
|
|
|
2a8729 |
+ return dev_name;
|
|
|
2a8729 |
+err:
|
|
|
2a8729 |
+ return NULL;
|
|
|
2a8729 |
+}
|
|
|
2a8729 |
+#endif
|
|
|
2a8729 |
+
|
|
|
2a8729 |
static char*
|
|
|
2a8729 |
_device_get_part_path (PedDevice *dev, int num)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
- size_t path_len = strlen (dev->path);
|
|
|
2a8729 |
-
|
|
|
2a8729 |
+ char *devpath;
|
|
|
2a8729 |
+ size_t path_len;
|
|
|
2a8729 |
char *result;
|
|
|
2a8729 |
+#ifdef ENABLE_DEVICE_MAPPER
|
|
|
2a8729 |
+ devpath = (dev->type == PED_DEVICE_DM
|
|
|
2a8729 |
+ ? dm_canonical_path (dev) : dev->path);
|
|
|
2a8729 |
+#else
|
|
|
2a8729 |
+ devpath = dev->path;
|
|
|
2a8729 |
+#endif
|
|
|
2a8729 |
+ path_len = strlen (devpath);
|
|
|
2a8729 |
/* Check for devfs-style /disc => /partN transformation
|
|
|
2a8729 |
unconditionally; the system might be using udev with devfs rules,
|
|
|
2a8729 |
and if not the test is harmless. */
|
|
|
2a8729 |
- if (5 < path_len && !strcmp (dev->path + path_len - 5, "/disc")) {
|
|
|
2a8729 |
+ if (5 < path_len && !strcmp (devpath + path_len - 5, "/disc")) {
|
|
|
2a8729 |
/* replace /disc with /part%d */
|
|
|
2a8729 |
result = zasprintf ("%.*s/part%d",
|
|
|
2a8729 |
- (int) (path_len - 5), dev->path, num);
|
|
|
2a8729 |
+ (int) (path_len - 5), devpath, num);
|
|
|
2a8729 |
} else {
|
|
|
2a8729 |
char const *p = (dev->type == PED_DEVICE_DAC960
|
|
|
2a8729 |
|| dev->type == PED_DEVICE_CPQARRAY
|
|
|
2a8729 |
|| dev->type == PED_DEVICE_ATARAID
|
|
|
2a8729 |
|| isdigit (dev->path[path_len - 1])
|
|
|
2a8729 |
? "p" : "");
|
|
|
2a8729 |
- result = zasprintf ("%s%s%d", dev->path, p, num);
|
|
|
2a8729 |
+ result = zasprintf ("%s%s%d", devpath, p, num);
|
|
|
2a8729 |
}
|
|
|
2a8729 |
-
|
|
|
2a8729 |
+#ifdef ENABLE_DEVICE_MAPPER
|
|
|
2a8729 |
+ if (dev->type == PED_DEVICE_DM)
|
|
|
2a8729 |
+ free (devpath);
|
|
|
2a8729 |
+#endif
|
|
|
2a8729 |
return result;
|
|
|
2a8729 |
}
|
|
|
2a8729 |
|
|
|
2a8729 |
@@ -2438,6 +2486,62 @@ _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
|
|
|
2a8729 |
|
|
|
2a8729 |
if (!_blkpg_part_command (disk->dev, &linux_part,
|
|
|
2a8729 |
BLKPG_ADD_PARTITION)) {
|
|
|
2a8729 |
+ return 0;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ return 1;
|
|
|
2a8729 |
+}
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+static int
|
|
|
2a8729 |
+_blkpg_remove_partition (PedDisk* disk, int n)
|
|
|
2a8729 |
+{
|
|
|
2a8729 |
+ struct blkpg_partition linux_part;
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ memset (&linux_part, 0, sizeof (linux_part));
|
|
|
2a8729 |
+ linux_part.pno = n;
|
|
|
2a8729 |
+ return _blkpg_part_command (disk->dev, &linux_part,
|
|
|
2a8729 |
+ BLKPG_DEL_PARTITION);
|
|
|
2a8729 |
+}
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+#ifdef BLKPG_RESIZE_PARTITION
|
|
|
2a8729 |
+static int _blkpg_resize_partition (PedDisk* disk, const PedPartition *part)
|
|
|
2a8729 |
+{
|
|
|
2a8729 |
+ struct blkpg_partition linux_part;
|
|
|
2a8729 |
+ char* dev_name;
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ PED_ASSERT(disk != NULL);
|
|
|
2a8729 |
+ PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ dev_name = _device_get_part_path (disk->dev, part->num);
|
|
|
2a8729 |
+ if (!dev_name)
|
|
|
2a8729 |
+ return 0;
|
|
|
2a8729 |
+ memset (&linux_part, 0, sizeof (linux_part));
|
|
|
2a8729 |
+ linux_part.start = part->geom.start * disk->dev->sector_size;
|
|
|
2a8729 |
+ /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
|
|
|
2a8729 |
+ if (part->type & PED_PARTITION_EXTENDED) {
|
|
|
2a8729 |
+ if (disk->dev->sector_size == 512) {
|
|
|
2a8729 |
+ linux_part.length = 2;
|
|
|
2a8729 |
+ PedPartition *walk;
|
|
|
2a8729 |
+ /* if the second sector is claimed by a logical partition,
|
|
|
2a8729 |
+ then there's just no room for lilo, so don't try to use it */
|
|
|
2a8729 |
+ for (walk = part->part_list; walk; walk = walk->next) {
|
|
|
2a8729 |
+ if (walk->geom.start == part->geom.start+1)
|
|
|
2a8729 |
+ linux_part.length = 1;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ } else {
|
|
|
2a8729 |
+ linux_part.length = 1;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ linux_part.length *= disk->dev->sector_size;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ else
|
|
|
2a8729 |
+ linux_part.length = part->geom.length * disk->dev->sector_size;
|
|
|
2a8729 |
+ linux_part.pno = part->num;
|
|
|
2a8729 |
+ strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ free (dev_name);
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ if (!_blkpg_part_command (disk->dev, &linux_part,
|
|
|
2a8729 |
+ BLKPG_RESIZE_PARTITION)) {
|
|
|
2a8729 |
return ped_exception_throw (
|
|
|
2a8729 |
PED_EXCEPTION_ERROR,
|
|
|
2a8729 |
PED_EXCEPTION_IGNORE_CANCEL,
|
|
|
2a8729 |
@@ -2454,17 +2558,7 @@ _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
|
|
|
2a8729 |
|
|
|
2a8729 |
return 1;
|
|
|
2a8729 |
}
|
|
|
2a8729 |
-
|
|
|
2a8729 |
-static int
|
|
|
2a8729 |
-_blkpg_remove_partition (PedDisk* disk, int n)
|
|
|
2a8729 |
-{
|
|
|
2a8729 |
- struct blkpg_partition linux_part;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- memset (&linux_part, 0, sizeof (linux_part));
|
|
|
2a8729 |
- linux_part.pno = n;
|
|
|
2a8729 |
- return _blkpg_part_command (disk->dev, &linux_part,
|
|
|
2a8729 |
- BLKPG_DEL_PARTITION);
|
|
|
2a8729 |
-}
|
|
|
2a8729 |
+#endif
|
|
|
2a8729 |
|
|
|
2a8729 |
/* Read the integer from /sys/block/DEV_BASE/ENTRY and set *VAL
|
|
|
2a8729 |
to that value, where DEV_BASE is the last component of DEV->path.
|
|
|
2a8729 |
@@ -2586,6 +2680,8 @@ static unsigned int
|
|
|
2a8729 |
_device_get_partition_range(PedDevice const* dev)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
int range;
|
|
|
2a8729 |
+ if (dev->type == PED_DEVICE_DM)
|
|
|
2a8729 |
+ return MAX_NUM_PARTS;
|
|
|
2a8729 |
bool ok = _sysfs_int_entry_from_dev(dev, "ext_range", &range);
|
|
|
2a8729 |
|
|
|
2a8729 |
if (!ok)
|
|
|
2a8729 |
@@ -2594,264 +2690,78 @@ _device_get_partition_range(PedDevice const* dev)
|
|
|
2a8729 |
return range > 1 ? range : 0;
|
|
|
2a8729 |
}
|
|
|
2a8729 |
|
|
|
2a8729 |
-/*
|
|
|
2a8729 |
- * Sync the partition table in two step process:
|
|
|
2a8729 |
- * 1. Remove all of the partitions from the kernel's tables, but do not attempt
|
|
|
2a8729 |
- * removal of any partition for which the corresponding ioctl call fails.
|
|
|
2a8729 |
- * 2. Add all the partitions that we hold in disk, throwing a warning
|
|
|
2a8729 |
- * if we cannot because step 1 failed to remove it and it is not being
|
|
|
2a8729 |
- * added back with the same start and length.
|
|
|
2a8729 |
- *
|
|
|
2a8729 |
- * To achieve this two step process we must calculate the minimum number of
|
|
|
2a8729 |
- * maximum possible partitions between what linux supports and what the label
|
|
|
2a8729 |
- * type supports. EX:
|
|
|
2a8729 |
- *
|
|
|
2a8729 |
- * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
|
|
|
2a8729 |
- */
|
|
|
2a8729 |
-static int
|
|
|
2a8729 |
-_disk_sync_part_table (PedDisk* disk)
|
|
|
2a8729 |
-{
|
|
|
2a8729 |
- PED_ASSERT(disk != NULL);
|
|
|
2a8729 |
- PED_ASSERT(disk->dev != NULL);
|
|
|
2a8729 |
- int lpn;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- unsigned int part_range = _device_get_partition_range(disk->dev);
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- /* lpn = largest partition number. */
|
|
|
2a8729 |
- if (ped_disk_get_max_supported_partition_count(disk, &lpn))
|
|
|
2a8729 |
- lpn = PED_MIN(lpn, part_range);
|
|
|
2a8729 |
- else
|
|
|
2a8729 |
- lpn = part_range;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- /* Its not possible to support largest_partnum < 0.
|
|
|
2a8729 |
- * largest_partnum == 0 would mean does not support partitions.
|
|
|
2a8729 |
- * */
|
|
|
2a8729 |
- if (lpn < 1)
|
|
|
2a8729 |
- return 0;
|
|
|
2a8729 |
- int ret = 0;
|
|
|
2a8729 |
- int *ok = calloc (lpn, sizeof *ok);
|
|
|
2a8729 |
- if (!ok)
|
|
|
2a8729 |
- return 0;
|
|
|
2a8729 |
- int *errnums = ped_malloc(sizeof(int) * lpn);
|
|
|
2a8729 |
- if (!errnums)
|
|
|
2a8729 |
- goto cleanup;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- /* Attempt to remove each and every partition, retrying for
|
|
|
2a8729 |
- up to max_sleep_seconds upon any failure due to EBUSY. */
|
|
|
2a8729 |
- unsigned int sleep_microseconds = 10000;
|
|
|
2a8729 |
- unsigned int max_sleep_seconds = 1;
|
|
|
2a8729 |
- unsigned int n_sleep = (max_sleep_seconds
|
|
|
2a8729 |
- * 1000000 / sleep_microseconds);
|
|
|
2a8729 |
- int i;
|
|
|
2a8729 |
- for (i = 0; i < n_sleep; i++) {
|
|
|
2a8729 |
- if (i)
|
|
|
2a8729 |
- usleep (sleep_microseconds);
|
|
|
2a8729 |
- bool busy = false;
|
|
|
2a8729 |
- int j;
|
|
|
2a8729 |
- for (j = 0; j < lpn; j++) {
|
|
|
2a8729 |
- if (!ok[j]) {
|
|
|
2a8729 |
- ok[j] = _blkpg_remove_partition (disk, j + 1);
|
|
|
2a8729 |
- errnums[j] = errno;
|
|
|
2a8729 |
- if (!ok[j] && errnums[j] == EBUSY)
|
|
|
2a8729 |
- busy = true;
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
- if (!busy)
|
|
|
2a8729 |
- break;
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- for (i = 1; i <= lpn; i++) {
|
|
|
2a8729 |
- PedPartition *part = ped_disk_get_partition (disk, i);
|
|
|
2a8729 |
- if (part) {
|
|
|
2a8729 |
- if (!ok[i - 1] && errnums[i - 1] == EBUSY) {
|
|
|
2a8729 |
- unsigned long long length;
|
|
|
2a8729 |
- unsigned long long start;
|
|
|
2a8729 |
- /* get start and length of existing partition */
|
|
|
2a8729 |
- if (!_kernel_get_partition_start_and_length(part,
|
|
|
2a8729 |
- &start, &length))
|
|
|
2a8729 |
- goto cleanup;
|
|
|
2a8729 |
- if (start == part->geom.start
|
|
|
2a8729 |
- && length == part->geom.length)
|
|
|
2a8729 |
- ok[i - 1] = 1;
|
|
|
2a8729 |
- /* If the new partition is unchanged and the
|
|
|
2a8729 |
- existing one was not removed because it was
|
|
|
2a8729 |
- in use, then reset the error flag and do not
|
|
|
2a8729 |
- try to add it since it is already there. */
|
|
|
2a8729 |
- continue;
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- /* add the (possibly modified or new) partition */
|
|
|
2a8729 |
- if (!_blkpg_add_partition (disk, part)) {
|
|
|
2a8729 |
- ped_exception_throw (
|
|
|
2a8729 |
- PED_EXCEPTION_ERROR,
|
|
|
2a8729 |
- PED_EXCEPTION_RETRY_CANCEL,
|
|
|
2a8729 |
- _("Failed to add partition %d (%s)"),
|
|
|
2a8729 |
- i, strerror (errno));
|
|
|
2a8729 |
- goto cleanup;
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- char *bad_part_list = NULL;
|
|
|
2a8729 |
- /* now warn about any errors */
|
|
|
2a8729 |
- for (i = 1; i <= lpn; i++) {
|
|
|
2a8729 |
- if (ok[i - 1] || errnums[i - 1] == ENXIO)
|
|
|
2a8729 |
- continue;
|
|
|
2a8729 |
- if (bad_part_list == NULL) {
|
|
|
2a8729 |
- bad_part_list = malloc (lpn * 5);
|
|
|
2a8729 |
- if (!bad_part_list)
|
|
|
2a8729 |
- goto cleanup;
|
|
|
2a8729 |
- bad_part_list[0] = 0;
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
- sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
- if (bad_part_list == NULL)
|
|
|
2a8729 |
- ret = 1;
|
|
|
2a8729 |
- else {
|
|
|
2a8729 |
- bad_part_list[strlen (bad_part_list) - 2] = 0;
|
|
|
2a8729 |
- if (ped_exception_throw (
|
|
|
2a8729 |
- PED_EXCEPTION_ERROR,
|
|
|
2a8729 |
- PED_EXCEPTION_IGNORE_CANCEL,
|
|
|
2a8729 |
- _("Partition(s) %s on %s have been written, but we have "
|
|
|
2a8729 |
- "been unable to inform the kernel of the change, "
|
|
|
2a8729 |
- "probably because it/they are in use. As a result, "
|
|
|
2a8729 |
- "the old partition(s) will remain in use. You "
|
|
|
2a8729 |
- "should reboot now before making further changes."),
|
|
|
2a8729 |
- bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE)
|
|
|
2a8729 |
- ret = 1;
|
|
|
2a8729 |
- free (bad_part_list);
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
- cleanup:
|
|
|
2a8729 |
- free (errnums);
|
|
|
2a8729 |
- free (ok);
|
|
|
2a8729 |
- return ret;
|
|
|
2a8729 |
-}
|
|
|
2a8729 |
-
|
|
|
2a8729 |
#ifdef ENABLE_DEVICE_MAPPER
|
|
|
2a8729 |
static int
|
|
|
2a8729 |
-_dm_remove_map_name(char *name)
|
|
|
2a8729 |
+_dm_remove_partition(PedDisk* disk, int partno)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
- struct dm_task *task = NULL;
|
|
|
2a8729 |
int rc = 0;
|
|
|
2a8729 |
uint32_t cookie = 0;
|
|
|
2a8729 |
+ char *part_name = _device_get_part_path (disk->dev, partno);
|
|
|
2a8729 |
|
|
|
2a8729 |
- task = dm_task_create(DM_DEVICE_REMOVE);
|
|
|
2a8729 |
+ int fd = open (part_name, O_RDONLY | O_EXCL);
|
|
|
2a8729 |
+ if (fd == -1) {
|
|
|
2a8729 |
+ if (errno == ENOENT)
|
|
|
2a8729 |
+ errno = ENXIO; /* nothing to remove, device already doesn't exist */
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ close (fd);
|
|
|
2a8729 |
+ struct dm_task *task = dm_task_create(DM_DEVICE_REMOVE);
|
|
|
2a8729 |
if (!task)
|
|
|
2a8729 |
- return 1;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- dm_task_set_name (task, name);
|
|
|
2a8729 |
- if (!dm_task_set_cookie(task, &cookie, 0))
|
|
|
2a8729 |
- goto err;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- rc = dm_task_run(task);
|
|
|
2a8729 |
- dm_udev_wait(cookie);
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ dm_task_set_name (task, part_name);
|
|
|
2a8729 |
+ if (!dm_task_set_cookie (task, &cookie, 0))
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ rc = _dm_task_run_wait (task, cookie);
|
|
|
2a8729 |
dm_task_update_nodes();
|
|
|
2a8729 |
-err:
|
|
|
2a8729 |
dm_task_destroy(task);
|
|
|
2a8729 |
- if (!rc)
|
|
|
2a8729 |
- return 1;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- return 0;
|
|
|
2a8729 |
+err:
|
|
|
2a8729 |
+ free (part_name);
|
|
|
2a8729 |
+ return rc;
|
|
|
2a8729 |
}
|
|
|
2a8729 |
|
|
|
2a8729 |
-static int
|
|
|
2a8729 |
-_dm_is_part (struct dm_info *this, char *name)
|
|
|
2a8729 |
+static bool
|
|
|
2a8729 |
+_dm_get_partition_start_and_length(PedPartition const *part,
|
|
|
2a8729 |
+ unsigned long long *start,
|
|
|
2a8729 |
+ unsigned long long *length)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
struct dm_task* task = NULL;
|
|
|
2a8729 |
- struct dm_info* info = alloca(sizeof *info);
|
|
|
2a8729 |
- struct dm_deps* deps = NULL;
|
|
|
2a8729 |
int rc = 0;
|
|
|
2a8729 |
- unsigned int i;
|
|
|
2a8729 |
|
|
|
2a8729 |
- task = dm_task_create(DM_DEVICE_DEPS);
|
|
|
2a8729 |
- if (!task)
|
|
|
2a8729 |
+ if (!(task = dm_task_create(DM_DEVICE_TABLE)))
|
|
|
2a8729 |
return 0;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- dm_task_set_name(task, name);
|
|
|
2a8729 |
- if (!dm_task_run(task))
|
|
|
2a8729 |
+ char *path = _device_get_part_path (part->disk->dev, part->num);
|
|
|
2a8729 |
+ PED_ASSERT(path);
|
|
|
2a8729 |
+ /* libdevmapper likes to complain on stderr instead of quietly
|
|
|
2a8729 |
+ returning ENOENT or ENXIO, so try to stat first */
|
|
|
2a8729 |
+ struct stat st;
|
|
|
2a8729 |
+ if (stat(path, &st))
|
|
|
2a8729 |
goto err;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- memset(info, '\0', sizeof *info);
|
|
|
2a8729 |
- dm_task_get_info(task, info);
|
|
|
2a8729 |
- if (!info->exists)
|
|
|
2a8729 |
+ dm_task_set_name(task, path);
|
|
|
2a8729 |
+ if (!dm_task_run(task))
|
|
|
2a8729 |
goto err;
|
|
|
2a8729 |
|
|
|
2a8729 |
- deps = dm_task_get_deps(task);
|
|
|
2a8729 |
- if (!deps)
|
|
|
2a8729 |
+ int major, minor;
|
|
|
2a8729 |
+ char *params;
|
|
|
2a8729 |
+ char *target_type;
|
|
|
2a8729 |
+ dm_get_next_target(task, NULL, (uint64_t *)start, (uint64_t *)length, &target_type, ¶ms);
|
|
|
2a8729 |
+ if (sscanf (params, "%d:%d %Ld", &major, &minor, start) != 3)
|
|
|
2a8729 |
goto err;
|
|
|
2a8729 |
+ rc = 1;
|
|
|
2a8729 |
|
|
|
2a8729 |
- for (i = 0; i < deps->count; i++) {
|
|
|
2a8729 |
- unsigned int ma = major(deps->device[i]),
|
|
|
2a8729 |
- mi = minor(deps->device[i]);
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- if (ma == this->major && mi == this->minor)
|
|
|
2a8729 |
- rc = 1;
|
|
|
2a8729 |
- }
|
|
|
2a8729 |
-
|
|
|
2a8729 |
+ /* device-mapper uses 512b units, make sure we return length and start in terms of the device's
|
|
|
2a8729 |
+ * sector size.
|
|
|
2a8729 |
+ */
|
|
|
2a8729 |
+ *start /= (part->disk->dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
|
|
|
2a8729 |
+ *length /= (part->disk->dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
|
|
|
2a8729 |
err:
|
|
|
2a8729 |
+ free (path);
|
|
|
2a8729 |
dm_task_destroy(task);
|
|
|
2a8729 |
return rc;
|
|
|
2a8729 |
}
|
|
|
2a8729 |
|
|
|
2a8729 |
-static int
|
|
|
2a8729 |
-_dm_remove_parts (PedDevice* dev)
|
|
|
2a8729 |
-{
|
|
|
2a8729 |
- struct dm_task* task = NULL;
|
|
|
2a8729 |
- struct dm_info* info = alloca(sizeof *info);
|
|
|
2a8729 |
- struct dm_names* names = NULL;
|
|
|
2a8729 |
- unsigned int next = 0;
|
|
|
2a8729 |
- int rc;
|
|
|
2a8729 |
- LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- task = dm_task_create(DM_DEVICE_LIST);
|
|
|
2a8729 |
- if (!task)
|
|
|
2a8729 |
- goto err;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- if (!dm_task_set_major_minor (task, arch_specific->major,
|
|
|
2a8729 |
- arch_specific->minor, 0))
|
|
|
2a8729 |
- goto err;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- if (!dm_task_run(task))
|
|
|
2a8729 |
- goto err;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- memset(info, '\0', sizeof *info);
|
|
|
2a8729 |
- dm_task_get_info(task, info);
|
|
|
2a8729 |
- if (!info->exists)
|
|
|
2a8729 |
- goto err;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- names = dm_task_get_names(task);
|
|
|
2a8729 |
- if (!names)
|
|
|
2a8729 |
- goto err;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- rc = 0;
|
|
|
2a8729 |
- do {
|
|
|
2a8729 |
- names = (void *) ((char *) names + next);
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- if (_dm_is_part(info, names->name))
|
|
|
2a8729 |
- rc += _dm_remove_map_name(names->name);
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- next = names->next;
|
|
|
2a8729 |
- } while (next);
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- dm_task_update_nodes();
|
|
|
2a8729 |
- dm_task_destroy(task);
|
|
|
2a8729 |
- task = NULL;
|
|
|
2a8729 |
-
|
|
|
2a8729 |
- if (!rc)
|
|
|
2a8729 |
- return 1;
|
|
|
2a8729 |
-err:
|
|
|
2a8729 |
- if (task)
|
|
|
2a8729 |
- dm_task_destroy(task);
|
|
|
2a8729 |
- ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
|
|
|
2a8729 |
- _("parted was unable to re-read the partition "
|
|
|
2a8729 |
- "table on %s (%s). This means Linux won't know "
|
|
|
2a8729 |
- "anything about the modifications you made. "),
|
|
|
2a8729 |
- dev->path, strerror (errno));
|
|
|
2a8729 |
- return 0;
|
|
|
2a8729 |
-}
|
|
|
2a8729 |
|
|
|
2a8729 |
static int
|
|
|
2a8729 |
-_dm_add_partition (PedDisk* disk, PedPartition* part)
|
|
|
2a8729 |
+_dm_add_partition (PedDisk* disk, const PedPartition* part)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
char* vol_name = NULL;
|
|
|
2a8729 |
const char* dev_name = NULL;
|
|
|
2a8729 |
@@ -2908,9 +2818,8 @@ _dm_add_partition (PedDisk* disk, PedPartition* part)
|
|
|
2a8729 |
"linear", params);
|
|
|
2a8729 |
if (!dm_task_set_cookie(task, &cookie, 0))
|
|
|
2a8729 |
goto err;
|
|
|
2a8729 |
- if (dm_task_run (task)) {
|
|
|
2a8729 |
+ if (_dm_task_run_wait (task, cookie)) {
|
|
|
2a8729 |
//printf("0 %ld linear %s\n", part->geom.length, params);
|
|
|
2a8729 |
- dm_udev_wait(cookie);
|
|
|
2a8729 |
dm_task_update_nodes();
|
|
|
2a8729 |
dm_task_destroy(task);
|
|
|
2a8729 |
free(params);
|
|
|
2a8729 |
@@ -2918,8 +2827,7 @@ _dm_add_partition (PedDisk* disk, PedPartition* part)
|
|
|
2a8729 |
free(vol_name);
|
|
|
2a8729 |
return 1;
|
|
|
2a8729 |
} else {
|
|
|
2a8729 |
- dm_udev_wait(cookie);
|
|
|
2a8729 |
- _dm_remove_map_name(vol_name);
|
|
|
2a8729 |
+ _dm_remove_partition (disk, part->num);
|
|
|
2a8729 |
}
|
|
|
2a8729 |
err:
|
|
|
2a8729 |
dm_task_update_nodes();
|
|
|
2a8729 |
@@ -2932,30 +2840,259 @@ err:
|
|
|
2a8729 |
}
|
|
|
2a8729 |
|
|
|
2a8729 |
static int
|
|
|
2a8729 |
-_dm_reread_part_table (PedDisk* disk)
|
|
|
2a8729 |
+_dm_resize_partition (PedDisk* disk, const PedPartition* part)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
- int largest_partnum = ped_disk_get_last_partition_num (disk);
|
|
|
2a8729 |
- int rc = 1;
|
|
|
2a8729 |
- int i;
|
|
|
2a8729 |
+ LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
|
|
|
2a8729 |
+ char* params = NULL;
|
|
|
2a8729 |
+ char* vol_name = NULL;
|
|
|
2a8729 |
+ const char* dev_name = NULL;
|
|
|
2a8729 |
+ uint32_t cookie = 0;
|
|
|
2a8729 |
+ int rc = 0;
|
|
|
2a8729 |
|
|
|
2a8729 |
- sync();
|
|
|
2a8729 |
- if (!_dm_remove_parts(disk->dev))
|
|
|
2a8729 |
- rc = 0;
|
|
|
2a8729 |
+ /* Get map name from devicemapper */
|
|
|
2a8729 |
+ struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
|
|
|
2a8729 |
+ if (!task)
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
|
|
|
2a8729 |
- for (i = 1; i <= largest_partnum; i++) {
|
|
|
2a8729 |
- PedPartition* part;
|
|
|
2a8729 |
+ if (!dm_task_set_major_minor (task, arch_specific->major,
|
|
|
2a8729 |
+ arch_specific->minor, 0))
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
|
|
|
2a8729 |
- part = ped_disk_get_partition (disk, i);
|
|
|
2a8729 |
- if (!part)
|
|
|
2a8729 |
- continue;
|
|
|
2a8729 |
+ if (!dm_task_run(task))
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ dev_name = dm_task_get_name (task);
|
|
|
2a8729 |
+ size_t name_len = strlen (dev_name);
|
|
|
2a8729 |
+ vol_name = zasprintf ("%s%s%d",
|
|
|
2a8729 |
+ dev_name,
|
|
|
2a8729 |
+ isdigit (dev_name[name_len - 1]) ? "p" : "",
|
|
|
2a8729 |
+ part->num);
|
|
|
2a8729 |
+ if (vol_name == NULL)
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ /* Caution: dm_task_destroy frees dev_name. */
|
|
|
2a8729 |
+ dm_task_destroy (task);
|
|
|
2a8729 |
+ task = NULL;
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ /* device-mapper uses 512b units, not the device's sector size */
|
|
|
2a8729 |
+ if ( ! (params = zasprintf ("%d:%d %lld", arch_specific->major,
|
|
|
2a8729 |
+ arch_specific->minor,
|
|
|
2a8729 |
+ part->geom.start * (disk->dev->sector_size / PED_SECTOR_SIZE_DEFAULT))))
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ task = dm_task_create (DM_DEVICE_RELOAD);
|
|
|
2a8729 |
+ if (!task)
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
|
|
|
2a8729 |
- if (!_dm_add_partition (disk, part))
|
|
|
2a8729 |
- rc = 0;
|
|
|
2a8729 |
+ dm_task_set_name (task, vol_name);
|
|
|
2a8729 |
+ /* device-mapper uses 512b units, not the device's sector size */
|
|
|
2a8729 |
+ dm_task_add_target (task, 0, part->geom.length * (disk->dev->sector_size / PED_SECTOR_SIZE_DEFAULT),
|
|
|
2a8729 |
+ "linear", params);
|
|
|
2a8729 |
+ /* NOTE: DM_DEVICE_RELOAD doesn't generate udev events, so no cookie is needed (it will freeze).
|
|
|
2a8729 |
+ * DM_DEVICE_RESUME does, so get a cookie and synchronize with udev.
|
|
|
2a8729 |
+ */
|
|
|
2a8729 |
+ if (dm_task_run (task)) {
|
|
|
2a8729 |
+ dm_task_destroy (task);
|
|
|
2a8729 |
+ task = dm_task_create (DM_DEVICE_RESUME);
|
|
|
2a8729 |
+ if (!task)
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ dm_task_set_name (task, vol_name);
|
|
|
2a8729 |
+ if (!dm_task_set_cookie (task, &cookie, 0))
|
|
|
2a8729 |
+ goto err;
|
|
|
2a8729 |
+ if (_dm_task_run_wait (task, cookie)) {
|
|
|
2a8729 |
+ rc = 1;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
}
|
|
|
2a8729 |
+err:
|
|
|
2a8729 |
+ dm_task_update_nodes();
|
|
|
2a8729 |
+ if (task)
|
|
|
2a8729 |
+ dm_task_destroy (task);
|
|
|
2a8729 |
+ free (params);
|
|
|
2a8729 |
+ free (vol_name);
|
|
|
2a8729 |
return rc;
|
|
|
2a8729 |
}
|
|
|
2a8729 |
+
|
|
|
2a8729 |
#endif
|
|
|
2a8729 |
|
|
|
2a8729 |
+/*
|
|
|
2a8729 |
+ * Sync the partition table in two step process:
|
|
|
2a8729 |
+ * 1. Remove all of the partitions from the kernel's tables, but do not attempt
|
|
|
2a8729 |
+ * removal of any partition for which the corresponding ioctl call fails.
|
|
|
2a8729 |
+ * 2. Add all the partitions that we hold in disk, throwing a warning
|
|
|
2a8729 |
+ * if we cannot because step 1 failed to remove it and it is not being
|
|
|
2a8729 |
+ * added back with the same start and length.
|
|
|
2a8729 |
+ *
|
|
|
2a8729 |
+ * To achieve this two step process we must calculate the minimum number of
|
|
|
2a8729 |
+ * maximum possible partitions between what linux supports and what the label
|
|
|
2a8729 |
+ * type supports. EX:
|
|
|
2a8729 |
+ *
|
|
|
2a8729 |
+ * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
|
|
|
2a8729 |
+ */
|
|
|
2a8729 |
+static int
|
|
|
2a8729 |
+_disk_sync_part_table (PedDisk* disk)
|
|
|
2a8729 |
+{
|
|
|
2a8729 |
+ PED_ASSERT(disk != NULL);
|
|
|
2a8729 |
+ PED_ASSERT(disk->dev != NULL);
|
|
|
2a8729 |
+ int lpn, lpn2;
|
|
|
2a8729 |
+ unsigned int part_range = _device_get_partition_range(disk->dev);
|
|
|
2a8729 |
+ int (*add_partition)(PedDisk* disk, const PedPartition *part);
|
|
|
2a8729 |
+ int (*resize_partition)(PedDisk* disk, const PedPartition *part);
|
|
|
2a8729 |
+ int (*remove_partition)(PedDisk* disk, int partno);
|
|
|
2a8729 |
+ bool (*get_partition_start_and_length)(PedPartition const *part,
|
|
|
2a8729 |
+ unsigned long long *start,
|
|
|
2a8729 |
+ unsigned long long *length);
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+#ifdef ENABLE_DEVICE_MAPPER
|
|
|
2a8729 |
+ if (disk->dev->type == PED_DEVICE_DM) {
|
|
|
2a8729 |
+ add_partition = _dm_add_partition;
|
|
|
2a8729 |
+ remove_partition = _dm_remove_partition;
|
|
|
2a8729 |
+ resize_partition = _dm_resize_partition;
|
|
|
2a8729 |
+ get_partition_start_and_length = _dm_get_partition_start_and_length;
|
|
|
2a8729 |
+ } else
|
|
|
2a8729 |
+#endif
|
|
|
2a8729 |
+ {
|
|
|
2a8729 |
+ add_partition = _blkpg_add_partition;
|
|
|
2a8729 |
+ remove_partition = _blkpg_remove_partition;
|
|
|
2a8729 |
+#ifdef BLKPG_RESIZE_PARTITION
|
|
|
2a8729 |
+ resize_partition = _blkpg_resize_partition;
|
|
|
2a8729 |
+#else
|
|
|
2a8729 |
+ resize_partition = NULL;
|
|
|
2a8729 |
+#endif
|
|
|
2a8729 |
+ get_partition_start_and_length = _kernel_get_partition_start_and_length;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ /* lpn = largest partition number.
|
|
|
2a8729 |
+ * for remove pass, use greater of device or label limit */
|
|
|
2a8729 |
+ if (ped_disk_get_max_supported_partition_count(disk, &lpn))
|
|
|
2a8729 |
+ lpn = PED_MAX(lpn, part_range);
|
|
|
2a8729 |
+ else
|
|
|
2a8729 |
+ lpn = part_range;
|
|
|
2a8729 |
+ /* for add pass, use lesser of device or label limit */
|
|
|
2a8729 |
+ if (ped_disk_get_max_supported_partition_count(disk, &lpn2))
|
|
|
2a8729 |
+ lpn2 = PED_MIN(lpn2, part_range);
|
|
|
2a8729 |
+ else
|
|
|
2a8729 |
+ lpn2 = part_range;
|
|
|
2a8729 |
+ /* Its not possible to support largest_partnum < 0.
|
|
|
2a8729 |
+ * largest_partnum == 0 would mean does not support partitions.
|
|
|
2a8729 |
+ * */
|
|
|
2a8729 |
+ if (lpn < 1)
|
|
|
2a8729 |
+ return 0;
|
|
|
2a8729 |
+ int ret = 0;
|
|
|
2a8729 |
+ int *ok = calloc (lpn, sizeof *ok);
|
|
|
2a8729 |
+ if (!ok)
|
|
|
2a8729 |
+ return 0;
|
|
|
2a8729 |
+ int *errnums = ped_malloc(sizeof(int) * lpn);
|
|
|
2a8729 |
+ if (!errnums)
|
|
|
2a8729 |
+ goto cleanup;
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ int i;
|
|
|
2a8729 |
+ /* remove old partitions first */
|
|
|
2a8729 |
+ for (i = 1; i <= lpn; i++) {
|
|
|
2a8729 |
+ PedPartition *part = ped_disk_get_partition (disk, i);
|
|
|
2a8729 |
+ if (part) {
|
|
|
2a8729 |
+ unsigned long long length;
|
|
|
2a8729 |
+ unsigned long long start;
|
|
|
2a8729 |
+ /* get start and length of existing partition */
|
|
|
2a8729 |
+ if (get_partition_start_and_length(part,
|
|
|
2a8729 |
+ &start, &length)
|
|
|
2a8729 |
+ && start == part->geom.start
|
|
|
2a8729 |
+ && (length == part->geom.length
|
|
|
2a8729 |
+ || (resize_partition && part->num < lpn2)))
|
|
|
2a8729 |
+ {
|
|
|
2a8729 |
+ /* partition is unchanged, or will be resized so nothing to do */
|
|
|
2a8729 |
+ ok[i - 1] = 1;
|
|
|
2a8729 |
+ continue;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ /* Attempt to remove the partition, retrying for
|
|
|
2a8729 |
+ up to max_sleep_seconds upon any failure due to EBUSY. */
|
|
|
2a8729 |
+ unsigned int sleep_microseconds = 10000;
|
|
|
2a8729 |
+ unsigned int max_sleep_seconds = 1;
|
|
|
2a8729 |
+ unsigned int n_sleep = (max_sleep_seconds
|
|
|
2a8729 |
+ * 1000000 / sleep_microseconds);
|
|
|
2a8729 |
+ do {
|
|
|
2a8729 |
+ ok[i - 1] = remove_partition (disk, i);
|
|
|
2a8729 |
+ errnums[i - 1] = errno;
|
|
|
2a8729 |
+ if (ok[i - 1] || errnums[i - 1] != EBUSY)
|
|
|
2a8729 |
+ break;
|
|
|
2a8729 |
+ usleep (sleep_microseconds);
|
|
|
2a8729 |
+ } while (n_sleep--);
|
|
|
2a8729 |
+ if (!ok[i - 1] && errnums[i - 1] == ENXIO)
|
|
|
2a8729 |
+ ok[i - 1] = 1; /* it already doesn't exist */
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ lpn = lpn2;
|
|
|
2a8729 |
+ /* don't actually add partitions for loop */
|
|
|
2a8729 |
+ if (strcmp (disk->type->name, "loop") == 0)
|
|
|
2a8729 |
+ lpn = 0;
|
|
|
2a8729 |
+ for (i = 1; i <= lpn; i++) {
|
|
|
2a8729 |
+ PedPartition *part = ped_disk_get_partition (disk, i);
|
|
|
2a8729 |
+ if (!part)
|
|
|
2a8729 |
+ continue;
|
|
|
2a8729 |
+ unsigned long long length;
|
|
|
2a8729 |
+ unsigned long long start;
|
|
|
2a8729 |
+ /* get start and length of existing partition */
|
|
|
2a8729 |
+ if (get_partition_start_and_length(part,
|
|
|
2a8729 |
+ &start, &length)
|
|
|
2a8729 |
+ && start == part->geom.start)
|
|
|
2a8729 |
+ {
|
|
|
2a8729 |
+ if (length == part->geom.length) {
|
|
|
2a8729 |
+ ok[i - 1] = 1;
|
|
|
2a8729 |
+ /* partition is unchanged, so nothing to do */
|
|
|
2a8729 |
+ continue;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ if (resize_partition
|
|
|
2a8729 |
+ && start == part->geom.start)
|
|
|
2a8729 |
+ {
|
|
|
2a8729 |
+ /* try to resize */
|
|
|
2a8729 |
+ if (resize_partition (disk, part)) {
|
|
|
2a8729 |
+ ok[i - 1] = 1;
|
|
|
2a8729 |
+ continue;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ /* add the (possibly modified or new) partition */
|
|
|
2a8729 |
+ if (!add_partition (disk, part)) {
|
|
|
2a8729 |
+ ok[i - 1] = 0;
|
|
|
2a8729 |
+ errnums[i - 1] = errno;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+
|
|
|
2a8729 |
+ char *bad_part_list = NULL;
|
|
|
2a8729 |
+ /* now warn about any errors */
|
|
|
2a8729 |
+ for (i = 1; i <= lpn; i++) {
|
|
|
2a8729 |
+ if (ok[i - 1] || errnums[i - 1] == ENXIO)
|
|
|
2a8729 |
+ continue;
|
|
|
2a8729 |
+ if (bad_part_list == NULL) {
|
|
|
2a8729 |
+ bad_part_list = malloc (lpn * 5);
|
|
|
2a8729 |
+ if (!bad_part_list)
|
|
|
2a8729 |
+ goto cleanup;
|
|
|
2a8729 |
+ bad_part_list[0] = 0;
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ if (bad_part_list == NULL)
|
|
|
2a8729 |
+ ret = 1;
|
|
|
2a8729 |
+ else {
|
|
|
2a8729 |
+ bad_part_list[strlen (bad_part_list) - 2] = 0;
|
|
|
2a8729 |
+ if (ped_exception_throw (
|
|
|
2a8729 |
+ PED_EXCEPTION_ERROR,
|
|
|
2a8729 |
+ PED_EXCEPTION_IGNORE_CANCEL,
|
|
|
2a8729 |
+ _("Partition(s) %s on %s have been written, but we have "
|
|
|
2a8729 |
+ "been unable to inform the kernel of the change, "
|
|
|
2a8729 |
+ "probably because it/they are in use. As a result, "
|
|
|
2a8729 |
+ "the old partition(s) will remain in use. You "
|
|
|
2a8729 |
+ "should reboot now before making further changes."),
|
|
|
2a8729 |
+ bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE)
|
|
|
2a8729 |
+ ret = 1;
|
|
|
2a8729 |
+ free (bad_part_list);
|
|
|
2a8729 |
+ }
|
|
|
2a8729 |
+ cleanup:
|
|
|
2a8729 |
+ free (errnums);
|
|
|
2a8729 |
+ free (ok);
|
|
|
2a8729 |
+ return ret;
|
|
|
2a8729 |
+}
|
|
|
2a8729 |
+
|
|
|
2a8729 |
static int
|
|
|
2a8729 |
_have_blkpg ()
|
|
|
2a8729 |
{
|
|
|
2a8729 |
@@ -2973,10 +3110,6 @@ _have_blkpg ()
|
|
|
2a8729 |
static int
|
|
|
2a8729 |
linux_disk_commit (PedDisk* disk)
|
|
|
2a8729 |
{
|
|
|
2a8729 |
-#ifdef ENABLE_DEVICE_MAPPER
|
|
|
2a8729 |
- if (disk->dev->type == PED_DEVICE_DM)
|
|
|
2a8729 |
- return _dm_reread_part_table (disk);
|
|
|
2a8729 |
-#endif
|
|
|
2a8729 |
if (disk->dev->type != PED_DEVICE_FILE) {
|
|
|
2a8729 |
|
|
|
2a8729 |
/* We now require BLKPG support. If this assertion fails,
|
|
|
2a8729 |
--
|
|
|
2a8729 |
2.9.4
|
|
|
2a8729 |
|