[Parted-commits] GNU Parted Official Repository: Changes to 'master'
Jim Meyering
meyering at alioth.debian.org
Mon Oct 29 20:55:55 UTC 2012
NEWS | 6
libparted/arch/linux.c | 507 ++++++++++++------------
tests/Makefile.am | 2
tests/t2310-dos-extended-2-sector-min-offset.sh | 3
tests/t6002-dm-busy.sh | 92 ++++
tests/t6003-dm-hide.sh | 67 +++
6 files changed, 429 insertions(+), 248 deletions(-)
New commits:
commit 2224076fef1a54391cf090149ba9308ae90067eb
Author: Jim Meyering <jim at meyering.net>
Date: Fri Oct 19 18:09:19 2012 +0200
tests: make t6003-dm-hide work reliably on F17
* tests/t6003-dm-hide.sh: Adjust to work reliably on Fedora 17.
diff --git a/tests/t6003-dm-hide.sh b/tests/t6003-dm-hide.sh
index 3cfdc43..59baae9 100644
--- a/tests/t6003-dm-hide.sh
+++ b/tests/t6003-dm-hide.sh
@@ -19,7 +19,6 @@
. "${srcdir=.}/init.sh"; path_prepend_ ../parted
require_root_
-lvm_init_root_dir_
test "x$ENABLE_DEVICE_MAPPER" = xyes \
|| skip_ "no device-mapper support"
@@ -32,7 +31,10 @@ d1=
f1=
dev=
cleanup_fn_() {
- dmsetup remove $linear_
+ # Insist. Sometimes the initial removal fails (race?).
+ # When that happens, a second removal appears to be sufficient.
+ dmsetup remove $linear_ || dmsetup remove $linear_
+
test -n "$d1" && losetup -d "$d1"
rm -f "$f1"
}
@@ -41,20 +43,25 @@ f1=$(pwd)/1; d1=$(loop_setup_ "$f1") \
|| fail=1
# setup: create a mapping
-echo "0 2048 linear $d1 0" | dmsetup create $linear_ || fail=1
-dev="$DM_DEV_DIR/mapper/$linear_"
-
-# device should not show up
+echo 0 2048 linear $d1 0 | dmsetup create $linear_ || fail=1
+dev=/dev/mapper/$linear_
+# No "DMRAID-" UUID prefix, hence the device should not show up.
parted -l >out 2>&1
-! grep $linear_ out || fail=1
+grep "^Disk $dev:" out && fail=1
+# Unless we perform both dmsetup-remove *and* losetup -d,
+# the following dmsetup-create would fail with EBUSY.
dmsetup remove $linear_
-echo "0 2048 linear $d1 0" | dmsetup create $linear_ -u "DMRAID-fake" || fail=1
+losetup -d "$d1" || fail=1
+# Reopen (or get new) loop device.
+d1=$(loop_setup_ "$f1") || fail=1
-# device should now show up
+# This time, use a fake UUID.
+echo 0 2048 linear $d1 0 | dmsetup create $linear_ -u "DMRAID-fake-$$" || fail=1
+# Thus, the device should now show up.
parted -l >out 2>&1
-grep $linear_ out || fail=1
+grep "^Disk $dev:" out || fail=1
Exit $fail
commit 3cb820632a13a91e0c2e579aedbe8e86b4f0040e
Author: Phillip Susi <psusi at ubuntu.com>
Date: Fri Oct 19 17:32:00 2012 +0200
libparted: don't probe every dm device in probe_all
We were probing every dm device. Only probe dmraid whole disk
(non-partition) devices instead. This removes the clutter of
LVM logical volumes, and dmraid partitions from the list, which
usually do not make sense to partition.
* NEWS (Changes in behavior): Mention it.
* libparted/arch/linux.c (_is_dmraid_device): New function.
(_dm_is_part): Likewise.
(_probe_dm_devices): Use the latter.
* tests/t6003-dm-hide.sh: New test.
* tests/Makefile.am (TESTS): Add it.
diff --git a/NEWS b/NEWS
index a40d69b..89541fd 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,9 @@ GNU parted NEWS -*- outline -*-
** Changes in behavior
+ parted -l no longer lists device-mapper devices other than
+ dmraid whole disks.
+
Added new Linux-specific partition GUID type code
(0FC63DAF-8483-4772-8E79-3D69D8477DE4) for Linux filesystem data on GPT
disks. This type code is now assigned as the default partition type code
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index 5721d4b..083591f 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -65,6 +65,8 @@
# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
#endif
+#define STRPREFIX(a, b) (strncmp (a, b, strlen (b)) == 0)
+
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#ifndef __NR__llseek
@@ -478,6 +480,82 @@ bad:
return r;
}
+/* Return nonzero if device-mapper device, DEVPATH, is part of a dmraid
+ array. Use the heuristic of checking for the string "DMRAID-" at the
+ start of its UUID. */
+static int
+_is_dmraid_device (const char *devpath)
+{
+ int rc = 0;
+
+ char const *dm_name = strrchr (devpath, '/');
+ char const *dm_basename = dm_name && *(++dm_name) ? dm_name : devpath;
+ struct dm_task *task = dm_task_create (DM_DEVICE_DEPS);
+ if (!task)
+ return 0;
+
+ dm_task_set_name (task, dm_basename);
+ if (!dm_task_run (task))
+ goto err;
+
+ const char *dmraid_uuid = dm_task_get_uuid (task);
+ if (STRPREFIX (dmraid_uuid, "DMRAID-"))
+ rc = 1;
+
+err:
+ dm_task_destroy (task);
+ return rc;
+}
+
+/* We consider a dm device that is a linear mapping with a *
+ * single target that also is a dm device to be a partition */
+
+static int
+_dm_is_part (const char *path)
+{
+ int rc = 0;
+ struct dm_task *task = dm_task_create (DM_DEVICE_DEPS);
+ if (!task)
+ return 0;
+
+ dm_task_set_name(task, path);
+ if (!dm_task_run(task))
+ goto err;
+
+ struct dm_info *info = alloca (sizeof *info);
+ memset(info, '\0', sizeof *info);
+ dm_task_get_info (task, info);
+ if (!info->exists)
+ goto err;
+
+ struct dm_deps *deps = dm_task_get_deps (task);
+ if (!deps)
+ goto err;
+
+ if (deps->count != 1)
+ goto err;
+ if (!_is_dm_major (major (deps->device[0])))
+ goto err;
+ dm_task_destroy (task);
+ if (!(task = dm_task_create (DM_DEVICE_TABLE)))
+ return 0;
+ dm_task_set_name (task, path);
+ if (!dm_task_run (task))
+ goto err;
+
+ char *target_type = NULL;
+ char *params = NULL;
+ uint64_t start, length;
+
+ dm_get_next_target (task, NULL, &start, &length, &target_type, ¶ms);
+ if (strcmp (target_type, "linear"))
+ goto err;
+ rc = 1;
+
+err:
+ dm_task_destroy(task);
+ return rc;
+}
static int
_probe_dm_devices ()
@@ -504,7 +582,8 @@ _probe_dm_devices ()
if (stat (buf, &st) != 0)
continue;
- if (_is_dm_major(major(st.st_rdev)))
+ if (_is_dm_major(major(st.st_rdev)) && _is_dmraid_device (buf)
+ && !_dm_is_part(buf))
_ped_device_probe (buf);
}
closedir (mapper_dir);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4649c0a..4ec08da 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -59,6 +59,7 @@ TESTS = \
t6000-dm.sh \
t6001-psep.sh \
t6002-dm-busy.sh \
+ t6003-dm-hide.sh \
t6100-mdraid-partitions.sh \
t7000-scripting.sh \
t8000-loop.sh \
diff --git a/tests/t6003-dm-hide.sh b/tests/t6003-dm-hide.sh
new file mode 100644
index 0000000..3cfdc43
--- /dev/null
+++ b/tests/t6003-dm-hide.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+# ensure that parted -l only shows dmraid device-mapper devices
+
+# Copyright (C) 2008-2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../parted
+
+require_root_
+lvm_init_root_dir_
+
+test "x$ENABLE_DEVICE_MAPPER" = xyes \
+ || skip_ "no device-mapper support"
+
+# Device maps names - should be random to not conflict with existing ones on
+# the system
+linear_=plinear-$$
+
+d1=
+f1=
+dev=
+cleanup_fn_() {
+ dmsetup remove $linear_
+ test -n "$d1" && losetup -d "$d1"
+ rm -f "$f1"
+}
+
+f1=$(pwd)/1; d1=$(loop_setup_ "$f1") \
+ || fail=1
+
+# setup: create a mapping
+echo "0 2048 linear $d1 0" | dmsetup create $linear_ || fail=1
+dev="$DM_DEV_DIR/mapper/$linear_"
+
+# device should not show up
+
+parted -l >out 2>&1
+! grep $linear_ out || fail=1
+
+dmsetup remove $linear_
+echo "0 2048 linear $d1 0" | dmsetup create $linear_ -u "DMRAID-fake" || fail=1
+
+# device should now show up
+
+parted -l >out 2>&1
+grep $linear_ out || fail=1
+
+Exit $fail
commit f87ff28d1aa8eff085e737ab22d031b0519e5510
Author: Phillip Susi <psusi at ubuntu.com>
Date: Sun Oct 14 23:59:59 2012 -0400
libparted: remove extraneous blkpg add partition ped exception
_blkpg_add_partition was throwing an exception if it failed to add the
new partition, in addition to _disk_sync_part_table throwing one, and
then bailing out. Instead of bailing out, just log the error for
reporting later and continue.
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index 70b26a9..5721d4b 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -2407,18 +2407,7 @@ _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
if (!_blkpg_part_command (disk->dev, &linux_part,
BLKPG_ADD_PARTITION)) {
- return ped_exception_throw (
- PED_EXCEPTION_ERROR,
- PED_EXCEPTION_IGNORE_CANCEL,
- _("Error informing the kernel about modifications to "
- "partition %s -- %s. This means Linux won't know "
- "about any changes you made to %s until you reboot "
- "-- so you shouldn't mount it or use it in any way "
- "before rebooting."),
- linux_part.devname,
- strerror (errno),
- linux_part.devname)
- == PED_EXCEPTION_IGNORE;
+ return 0;
}
return 1;
@@ -2790,12 +2779,8 @@ _disk_sync_part_table (PedDisk* disk)
/* add the (possibly modified or new) partition */
if (!add_partition (disk, part)) {
- ped_exception_throw (
- PED_EXCEPTION_ERROR,
- PED_EXCEPTION_RETRY_CANCEL,
- _("Failed to add partition %d (%s)"),
- i, strerror (errno));
- goto cleanup;
+ ok[i - 1] = 0;
+ errnums[i - 1] = errno;
}
}
}
diff --git a/tests/t2310-dos-extended-2-sector-min-offset.sh b/tests/t2310-dos-extended-2-sector-min-offset.sh
index 89453ae..17c777c 100644
--- a/tests/t2310-dos-extended-2-sector-min-offset.sh
+++ b/tests/t2310-dos-extended-2-sector-min-offset.sh
@@ -39,8 +39,7 @@ $scsi_dev:2048s:scsi:512:512:msdos:Linux scsi_debug:;
EOF
cat <<EOF > err.exp || framework_failure
-Error: Error informing the kernel about modifications to partition $p5 -- Device or resource busy. This means Linux won't know about any changes you made to $p5 until you reboot -- so you shouldn't mount it or use it in any way before rebooting.
-Error: Failed to add partition 5 (Device or resource busy)
+Error: Partition(s) 5 on $scsi_dev have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use. As a result, the old partition(s) will remain in use. You should reboot now before making further changes.
EOF
# Create a DOS label with an extended partition starting at sector 64.
commit f0c0d53f998964e187f59de32ac92a2c0e2d5da9
Author: Phillip Susi <psusi at ubuntu.com>
Date: Sun Oct 14 23:59:58 2012 -0400
libparted: refactor device-mapper partition sync code
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.
diff --git a/NEWS b/NEWS
index 293f5e4..a40d69b 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ GNU parted NEWS -*- outline -*-
** Bug Fixes
+ libparted: Don't fail to manipulate partitions on dmraid disks that
+ have other partitions in use.
+
libparted: mac: a MAC partition table could have a block_size larger
than the one the kernel told us about. Upon reading that partition
table, libparted would ask if it's ok to use the larger block size.
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index e2c4139..70b26a9 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -285,7 +285,7 @@ struct blkdev_ioctl_param {
/* Maximum number of partitions supported by linux. */
#define MAX_NUM_PARTS 64
-static char* _device_get_part_path (PedDevice* dev, int num);
+static char* _device_get_part_path (PedDevice const *dev, int num);
static int _partition_is_mounted_by_path (const char* path);
static int
@@ -2225,28 +2225,53 @@ zasprintf (const char *format, ...)
return r < 0 ? NULL : resultp;
}
-static char*
-_device_get_part_path (PedDevice *dev, int num)
+static char *
+dm_canonical_path (PedDevice const *dev)
{
- size_t path_len = strlen (dev->path);
+ LinuxSpecific const *arch_specific = LINUX_SPECIFIC (dev);
+ /* Get map name from devicemapper */
+ struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
+ if (!task)
+ goto err;
+ if (!dm_task_set_major_minor (task, arch_specific->major,
+ arch_specific->minor, 0))
+ goto err;
+ if (!dm_task_run(task))
+ goto err;
+ char *dev_name = zasprintf ("/dev/mapper/%s", dm_task_get_name (task));
+ if (dev_name == NULL)
+ goto err;
+ dm_task_destroy (task);
+ return dev_name;
+err:
+ return NULL;
+}
+
+static char*
+_device_get_part_path (PedDevice const *dev, int num)
+{
+ char *devpath = (dev->type == PED_DEVICE_DM
+ ? dm_canonical_path (dev) : dev->path);
+ size_t path_len = strlen (devpath);
char *result;
/* Check for devfs-style /disc => /partN transformation
unconditionally; the system might be using udev with devfs rules,
and if not the test is harmless. */
- if (5 < path_len && !strcmp (dev->path + path_len - 5, "/disc")) {
+ if (5 < path_len && !strcmp (devpath + path_len - 5, "/disc")) {
/* replace /disc with /part%d */
result = zasprintf ("%.*s/part%d",
- (int) (path_len - 5), dev->path, num);
+ (int) (path_len - 5), devpath, num);
} else {
char const *p = (dev->type == PED_DEVICE_DAC960
|| dev->type == PED_DEVICE_CPQARRAY
|| dev->type == PED_DEVICE_ATARAID
- || isdigit (dev->path[path_len - 1])
+ || isdigit (devpath[path_len - 1])
? "p" : "");
- result = zasprintf ("%s%s%d", dev->path, p, num);
+ result = zasprintf ("%s%s%d", devpath, p, num);
}
-
+ if (dev->type == PED_DEVICE_DM)
+ free (devpath);
return result;
}
@@ -2530,6 +2555,8 @@ static unsigned int
_device_get_partition_range(PedDevice const* dev)
{
int range;
+ if (dev->type == PED_DEVICE_DM)
+ return MAX_NUM_PARTS;
bool ok = _sysfs_int_entry_from_dev(dev, "ext_range", &range);
if (!ok)
@@ -2538,6 +2565,128 @@ _device_get_partition_range(PedDevice const* dev)
return range > 1 ? range : 0;
}
+#ifdef ENABLE_DEVICE_MAPPER
+static int
+_dm_remove_partition(PedDisk* disk, int partno)
+{
+ 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);
+ struct dm_task *task = dm_task_create(DM_DEVICE_REMOVE);
+ 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 0;
+
+ return 1;
+}
+
+static bool
+_dm_get_partition_start_and_length(PedPartition const *part,
+ unsigned long long *start,
+ unsigned long long *length)
+{
+ struct dm_task* task = NULL;
+ int rc = 0;
+
+ if (!(task = dm_task_create(DM_DEVICE_TABLE)))
+ return 0;
+ char *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;
+
+ int major, minor;
+ char *params;
+ char *target_type;
+ 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 = 1;
+err:
+ free (path);
+ dm_task_destroy(task);
+ return rc;
+}
+
+
+static int
+_dm_add_partition (PedDisk* disk, const PedPartition* part)
+{
+ LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
+ char *params = NULL;
+ char *vol_name = NULL;
+
+ /* Get map name from devicemapper */
+ struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
+ if (!task)
+ goto err;
+
+ if (!dm_task_set_major_minor (task, arch_specific->major,
+ arch_specific->minor, 0))
+ goto err;
+
+ if (!dm_task_run(task))
+ goto err;
+
+ const char *dev_name = dm_task_get_name (task);
+ size_t name_len = strlen (dev_name);
+ vol_name = zasprintf ("%s%s%d",
+ dev_name,
+ isdigit (dev_name[name_len - 1]) ? "p" : "",
+ part->num);
+ if (vol_name == NULL)
+ goto err;
+
+ /* Caution: dm_task_destroy frees dev_name. */
+ dm_task_destroy (task);
+ task = NULL;
+ if ( ! (params = zasprintf ("%d:%d %lld", arch_specific->major,
+ arch_specific->minor, part->geom.start)))
+ goto err;
+
+ task = dm_task_create (DM_DEVICE_CREATE);
+ if (!task)
+ goto err;
+
+ dm_task_set_name (task, vol_name);
+ dm_task_add_target (task, 0, part->geom.length,
+ "linear", params);
+ if (dm_task_run (task)) {
+ dm_task_update_nodes ();
+ dm_task_destroy (task);
+ free (params);
+ free (vol_name);
+ return 1;
+ } else {
+ _dm_remove_partition (disk, part->num);
+ }
+err:
+ dm_task_update_nodes();
+ if (task)
+ dm_task_destroy (task);
+ free (params);
+ free (vol_name);
+ return 0;
+}
+#endif
+
/*
* Sync the partition table in two step process:
* 1. Remove all of the partitions from the kernel's tables, but do not attempt
@@ -2558,8 +2707,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 +2758,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 +2775,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 +2789,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,
@@ -2671,215 +2835,6 @@ _disk_sync_part_table (PedDisk* disk)
return ret;
}
-#ifdef ENABLE_DEVICE_MAPPER
-static int
-_dm_remove_map_name(char *name)
-{
- struct dm_task *task = NULL;
- int rc;
-
- task = dm_task_create(DM_DEVICE_REMOVE);
- if (!task)
- return 1;
-
- dm_task_set_name (task, name);
-
- rc = dm_task_run(task);
- dm_task_update_nodes();
- dm_task_destroy(task);
- if (!rc)
- return 1;
-
- return 0;
-}
-
-static int
-_dm_is_part (struct dm_info *this, char *name)
-{
- struct dm_task* task = NULL;
- struct dm_info* info = alloca(sizeof *info);
- struct dm_deps* deps = NULL;
- int rc = 0;
- unsigned int i;
-
- task = dm_task_create(DM_DEVICE_DEPS);
- if (!task)
- return 0;
-
- dm_task_set_name(task, name);
- if (!dm_task_run(task))
- goto err;
-
- memset(info, '\0', sizeof *info);
- dm_task_get_info(task, info);
- if (!info->exists)
- goto err;
-
- deps = dm_task_get_deps(task);
- if (!deps)
- goto err;
-
- for (i = 0; i < deps->count; i++) {
- unsigned int ma = major(deps->device[i]),
- mi = minor(deps->device[i]);
-
- if (ma == this->major && mi == this->minor)
- rc = 1;
- }
-
-err:
- dm_task_destroy(task);
- return rc;
-}
-
-static int
-_dm_remove_parts (PedDevice* dev)
-{
- 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;
-
- 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)
- 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;
-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;
-}
-
-static int
-_dm_add_partition (PedDisk* disk, PedPartition* part)
-{
- char* vol_name = NULL;
- const char* dev_name = NULL;
- char* params = NULL;
- LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
-
- /* Get map name from devicemapper */
- struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
- if (!task)
- goto err;
-
- if (!dm_task_set_major_minor (task, arch_specific->major,
- arch_specific->minor, 0))
- goto err;
-
- if (!dm_task_run(task))
- goto err;
-
- dev_name = dm_task_get_name (task);
-
- if (isdigit (dev_name[strlen (dev_name) - 1])) {
- if ( ! (vol_name = zasprintf ("%sp%d", dev_name, part->num)))
- goto err;
- } else if ( ! (vol_name = zasprintf ("%s%d", dev_name, part->num)))
- goto err;
-
- /* Caution: dm_task_destroy frees dev_name. */
- dm_task_destroy (task);
- task = NULL;
-
- if ( ! (params = zasprintf ("%d:%d %lld", arch_specific->major,
- arch_specific->minor, part->geom.start)))
- goto err;
-
- task = dm_task_create (DM_DEVICE_CREATE);
- if (!task)
- goto err;
-
- dm_task_set_name (task, vol_name);
- dm_task_add_target (task, 0, part->geom.length,
- "linear", params);
- if (dm_task_run (task)) {
- //printf("0 %ld linear %s\n", part->geom.length, params);
- dm_task_update_nodes();
- dm_task_destroy(task);
- free(params);
- free(vol_name);
- return 1;
- } else {
- _dm_remove_map_name(vol_name);
- }
-err:
- dm_task_update_nodes();
- if (task)
- dm_task_destroy (task);
- free (params);
- 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
_have_blkpg ()
{
@@ -2897,10 +2852,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,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cdc1c4b..4649c0a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -58,6 +58,7 @@ TESTS = \
t5000-tags.sh \
t6000-dm.sh \
t6001-psep.sh \
+ t6002-dm-busy.sh \
t6100-mdraid-partitions.sh \
t7000-scripting.sh \
t8000-loop.sh \
diff --git a/tests/t6002-dm-busy.sh b/tests/t6002-dm-busy.sh
new file mode 100644
index 0000000..9807b40
--- /dev/null
+++ b/tests/t6002-dm-busy.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+# ensure that parted can alter a partition on a dmraid disk
+# while another one is mounted
+
+# Copyright (C) 2008-2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../parted
+
+require_root_
+
+# We could make this work for arbitrary sector size, but I'm lazy.
+require_512_byte_sector_size_
+
+test "x$ENABLE_DEVICE_MAPPER" = xyes \
+ || skip_ "no device-mapper support"
+
+# Device maps names - should be random to not conflict with existing ones on
+# the system
+linear_=plinear-$$
+
+d1=
+f1=
+dev=
+cleanup_fn_() {
+ umount "${dev}p2" > /dev/null 2>&1
+ dmsetup remove ${linear_}p1
+ dmsetup remove ${linear_}p2
+ dmsetup remove $linear_
+ test -n "$d1" && losetup -d "$d1"
+ rm -f "$f1"
+}
+
+f1=$(pwd)/1; d1=$(loop_setup_ "$f1") \
+ || fail=1
+
+# setup: create a mapping
+n=204800
+echo "0 $n linear $d1 0" | dmsetup create $linear_ || fail=1
+dev="/dev/mapper/$linear_"
+
+# Create msdos partition table
+parted -s $dev mklabel msdos > out 2>&1 || fail=1
+compare /dev/null out || fail=1
+
+parted -s $dev -a none mkpart primary fat32 1s 1000s > out 2>&1 || fail=1
+compare /dev/null out || fail=1
+
+parted -s $dev -a none mkpart primary fat32 1001s 200000s > out 2>&1 || fail=1
+compare /dev/null out || fail=1
+
+# wait for new partition device to appear
+wait_for_dev_to_appear_ ${dev}p2 || fail_ ${dev}p2 did not appear
+
+mkfs.vfat -F 32 ${dev}p2 || fail_ mkfs.vfat failed
+
+mount_point=$(pwd)/mnt
+
+mkdir $mount_point || fail=1
+mount "${dev}p2" "$mount_point" || fail=1
+
+# Removal of unmounted partition must succeed.
+parted -s "$dev" rm 1 > /dev/null 2>&1 || fail=1
+
+# Removal of mounted partition must fail.
+parted -s "$dev" rm 2 > /dev/null 2>&1 && fail=1
+
+parted -m -s "$dev" u s print > out 2>&1 || fail=1
+sed "s,^$dev,DEV," out > k; mv k out
+
+# Create expected output file.
+cat <<EOF >> exp || fail=1
+BYT;
+DEV:${n}s:dm:512:512:msdos:Linux device-mapper (linear):;
+2:1001s:200000s:199000s:fat32::lba;
+EOF
+
+compare exp out || fail=1
+
+Exit $fail
More information about the Parted-commits
mailing list