[parted-devel] [PATCH 1/4] libparted: refactor device-mapper partition sync code
Phillip Susi
phillsusi at gmail.com
Sun Jan 8 17:38:59 UTC 2012
The device-mapper partition sync code was still using the remove all
partitions, then add new partitions method. Refactor to use the same
algorithm as regular disks: try to remove all, and ignore any that could
not be removed but have not changed.
---
NEWS | 2 +
libparted/arch/linux.c | 166 ++++++++++++++++++++----------------------------
2 files changed, 72 insertions(+), 96 deletions(-)
diff --git a/NEWS b/NEWS
index 58a5f89..4fede6c 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ GNU parted NEWS -*- outline -*-
parted has improved support for partitionable loopback devices
** Bug fixes
+ libparted: Don't fail to manipulate partitions on dmraid disks that
+ have other partitions in use.
parted now exits nonzero for certain failures already diagnosed as "Error".
For example, before this change, parted would exit successfully in spite
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index e2c4139..3991adb 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -287,6 +287,14 @@ struct blkdev_ioctl_param {
static char* _device_get_part_path (PedDevice* dev, int num);
static int _partition_is_mounted_by_path (const char* path);
+static int
+_dm_add_partition (PedDisk* disk, const PedPartition* part);
+static int
+_dm_remove_partition(PedDisk* disk, int partno);
+static bool
+_dm_get_partition_start_and_length(PedPartition const *part,
+ unsigned long long *start,
+ unsigned long long *length);
static int
_read_fd (int fd, char **buf)
@@ -2558,8 +2566,23 @@ _disk_sync_part_table (PedDisk* disk)
PED_ASSERT(disk != NULL);
PED_ASSERT(disk->dev != NULL);
int lpn;
-
unsigned int part_range = _device_get_partition_range(disk->dev);
+ int (*add_partition)(PedDisk* disk, const PedPartition *part);
+ int (*remove_partition)(PedDisk* disk, int partno);
+ bool (*get_partition_start_and_length)(PedPartition const *part,
+ unsigned long long *start,
+ unsigned long long *length);
+
+
+ if (disk->dev->type == PED_DEVICE_DM) {
+ add_partition = _dm_add_partition;
+ remove_partition = _dm_remove_partition;
+ get_partition_start_and_length = _dm_get_partition_start_and_length;
+ } else {
+ add_partition = _blkpg_add_partition;
+ remove_partition = _blkpg_remove_partition;
+ get_partition_start_and_length = _kernel_get_partition_start_and_length;
+ }
/* lpn = largest partition number. */
if (ped_disk_get_max_supported_partition_count(disk, &lpn))
@@ -2594,7 +2617,7 @@ _disk_sync_part_table (PedDisk* disk)
int j;
for (j = 0; j < lpn; j++) {
if (!ok[j]) {
- ok[j] = _blkpg_remove_partition (disk, j + 1);
+ ok[j] = remove_partition (disk, j + 1);
errnums[j] = errno;
if (!ok[j] && errnums[j] == EBUSY)
busy = true;
@@ -2611,8 +2634,8 @@ _disk_sync_part_table (PedDisk* disk)
unsigned long long length;
unsigned long long start;
/* get start and length of existing partition */
- if (!_kernel_get_partition_start_and_length(part,
- &start, &length))
+ if (!get_partition_start_and_length(part,
+ &start, &length))
goto cleanup;
if (start == part->geom.start
&& length == part->geom.length)
@@ -2625,7 +2648,7 @@ _disk_sync_part_table (PedDisk* disk)
}
/* add the (possibly modified or new) partition */
- if (!_blkpg_add_partition (disk, part)) {
+ if (!add_partition (disk, part)) {
ped_exception_throw (
PED_EXCEPTION_ERROR,
PED_EXCEPTION_RETRY_CANCEL,
@@ -2673,24 +2696,34 @@ _disk_sync_part_table (PedDisk* disk)
#ifdef ENABLE_DEVICE_MAPPER
static int
-_dm_remove_map_name(char *name)
+_dm_remove_partition(PedDisk* disk, int partno)
{
struct dm_task *task = NULL;
int rc;
+ char *part_name = _device_get_part_path (disk->dev, partno);
+ int fd = open (part_name, O_RDONLY | O_EXCL);
+ if (fd == -1) {
+ if (errno == ENOENT)
+ errno = ENXIO; /* nothing to remove, device already doesn't exist */
+ free (part_name);
+ return 0;
+ }
+ close (fd);
task = dm_task_create(DM_DEVICE_REMOVE);
- if (!task)
- return 1;
-
- dm_task_set_name (task, name);
-
+ if (!task) {
+ free (part_name);
+ return 0;
+ }
+ dm_task_set_name (task, part_name);
rc = dm_task_run(task);
dm_task_update_nodes();
dm_task_destroy(task);
+ free (part_name);
if (!rc)
- return 1;
+ return 0;
- return 0;
+ return 1;
}
static int
@@ -2732,65 +2765,38 @@ err:
return rc;
}
-static int
-_dm_remove_parts (PedDevice* dev)
+static bool
+_dm_get_partition_start_and_length(PedPartition const *part,
+ unsigned long long *start,
+ unsigned long long *length)
{
- struct dm_task* task = NULL;
- struct dm_info* info = alloca(sizeof *info);
- struct dm_names* names = NULL;
- unsigned int next = 0;
- int rc;
- LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
-
- task = dm_task_create(DM_DEVICE_LIST);
- if (!task)
- goto err;
-
- if (!dm_task_set_major_minor (task, arch_specific->major,
- arch_specific->minor, 0))
- goto err;
+ struct dm_task* task = NULL;
+ int rc = 0;
+ char *target_type = NULL;
+ char *params;
+ char *path;
+ int major, minor;
+ if (!(task = dm_task_create(DM_DEVICE_TABLE)))
+ return 0;
+ path = _device_get_part_path (part->disk->dev, part->num);
+ PED_ASSERT(path);
+ dm_task_set_name(task, path);
if (!dm_task_run(task))
goto err;
-
- memset(info, '\0', sizeof *info);
- dm_task_get_info(task, info);
- if (!info->exists)
- goto err;
-
- names = dm_task_get_names(task);
- if (!names)
+ dm_get_next_target(task, NULL, (uint64_t *)start, (uint64_t *)length, &target_type, ¶ms);
+ if (sscanf (params, "%d:%d %Ld", &major, &minor, start) != 3)
goto err;
-
- rc = 0;
- do {
- names = (void *) ((char *) names + next);
-
- if (_dm_is_part(info, names->name))
- rc += _dm_remove_map_name(names->name);
-
- next = names->next;
- } while (next);
-
- dm_task_update_nodes();
- dm_task_destroy(task);
- task = NULL;
-
- if (!rc)
- return 1;
+ rc = 1;
err:
- if (task)
- dm_task_destroy(task);
- ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
- _("parted was unable to re-read the partition "
- "table on %s (%s). This means Linux won't know "
- "anything about the modifications you made. "),
- dev->path, strerror (errno));
- return 0;
+ free (path);
+ dm_task_destroy(task);
+ return rc;
}
+
static int
-_dm_add_partition (PedDisk* disk, PedPartition* part)
+_dm_add_partition (PedDisk* disk, const PedPartition* part)
{
char* vol_name = NULL;
const char* dev_name = NULL;
@@ -2840,7 +2846,7 @@ _dm_add_partition (PedDisk* disk, PedPartition* part)
free(vol_name);
return 1;
} else {
- _dm_remove_map_name(vol_name);
+ _dm_remove_partition (disk, part->num);
}
err:
dm_task_update_nodes();
@@ -2850,34 +2856,6 @@ err:
free (vol_name);
return 0;
}
-
-static int
-_dm_reread_part_table (PedDisk* disk)
-{
- int largest_partnum = ped_disk_get_last_partition_num (disk);
- if (largest_partnum <= 0)
- return 1;
-
- int rc = 1;
- int last = PED_MIN (largest_partnum, 16);
- int i;
-
- sync();
- if (!_dm_remove_parts(disk->dev))
- rc = 0;
-
- for (i = 1; i <= last; i++) {
- PedPartition* part;
-
- part = ped_disk_get_partition (disk, i);
- if (!part)
- continue;
-
- if (!_dm_add_partition (disk, part))
- rc = 0;
- }
- return rc;
-}
#endif
static int
@@ -2897,10 +2875,6 @@ _have_blkpg ()
static int
linux_disk_commit (PedDisk* disk)
{
-#ifdef ENABLE_DEVICE_MAPPER
- if (disk->dev->type == PED_DEVICE_DM)
- return _dm_reread_part_table (disk);
-#endif
if (disk->dev->type != PED_DEVICE_FILE) {
/* We now require BLKPG support. If this assertion fails,
--
1.7.5.4
More information about the parted-devel
mailing list