integ/filesystem/parted/centos/patches/fix-dev-nodes-getting-remov...

495 lines
18 KiB
Diff

From 2fc5cefc48c294b25dbd5dc1e533c7d12508289a Mon Sep 17 00:00:00 2001
From: Phillip Susi <psusi@ubuntu.com>
Date: Sun, 14 Oct 2012 23:59:58 -0400
Subject: [PATCH] 'parted -s <dev_node> print' causes device nodes to be
deleted from /dev for ~100-300ms
The main problem is that, immediately after 'parted <dev_node> print', device
nodes for block devices that exist are deleted for brief moments of time then
are readded by udev. This causes commands accessing these nodes to fail.
Although probability of this happening is small (after mount, partitions no
longer disappear), it can cause critical error as we now believe to have
happened in CGTS-8785 (ceph tried to configure an OSD at exactly the moment
parted was gathering info).
To fix this the following commit where patched from upstream:
0. f0c0d53f998964e187f59de32ac92a2c0e2d5da9 libparted: refactor device-mapper partition sync code
1. 5910f1bc983fbab31f9ec86a7166feee4869c21a libparted: avoid disturbing partitions
2. 026736e9fed89ef00e6e6e84c7e422639ac2715c libparted: sync partitions > 16
3. 9e07d797b18609613c53ceb2dabbb5e69d961186 libparted: remove old partitions *first* before adding new ones
4. dfdd8b0dd99b7fa990f40a3d3a225c5b3ef13c57 libparted: remove all old partitions, even if new label allows less
5. 7feb3b452c5ae57e75e16f8c00f46c9aa564a4cc libparted: don't create partition on loop label
6. 7e87ca3c531228d35e13e802d2622006138b104c libparted/arch/linux.c: Compile without ENABLE_DEVICE_MAPPER
7. 7cde99849ed321da2712248bc27c14a954d6b481 libparted: give correct partition device name on loop labels
The most important is commit #1. Commit #0 is a prerequisite and the rest are bug fixes introduced by them.
Details:
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.
Conflicts:
NEWS
libparted/arch/linux.c
tests/Makefile.am
libparted: avoid disturbing partitions
The partition sync logic was first removing all
partitions, then trying to re-add them. This resulted in many
udev events triggering annoying behavior like auto mounting.
Refactor the code to avoid removing and re-adding unmodified
partitions.
Conflicts:
NEWS
libparted: sync partitions > 16
The linux partition sync code was hard coded to only flush
the first 16 partitions.
Conflicts:
NEWS
libparted/arch/linux.c
libparted: remove old partitions *first* before adding new ones
"libparted: avoid disturbing partitions" put the remove of the old
partition in second pass. If you simultaneously removed partitions 1
and 2, and created a new partition #1 that overlapped the previous second
partition, the sync would fail because it would try to create the new,
larger partition #1 before removing the old partition #2.
Conflicts:
libparted/arch/linux.c
libparted: remove all old partitions, even if new label allows less
We were limiting partition sync operations to the lesser number allowed
by the device, or the label. This meant that when creating a new label
over an old label that had more partitions than the new one allows, the
higher partitions would not be removed. Use the greater of the two values
for the remove pass, and the lesser for the add.
Conflicts:
NEWS
libparted: don't create partition on loop label
The loop label represents an unpartitioned disk, but creates
a dummy partition to represent the whole disk. This dummy partition
was actually being loaded into the kernel. Don't do that.
Conflicts:
NEWS
libparted/arch/linux.c: Compile without ENABLE_DEVICE_MAPPER
Signed-off-by: Brian C. Lane <bcl@redhat.com>
libparted: give correct partition device name on loop labels
ped_partition_get_path() was returning "/dev/foo1" instead of
"/dev/foo" on loop labels. This caused gparted to run tools like mkfs on
a device node that did not actually exist.
Conflicts:
NEWS
---
NEWS | 94 +++++++++++++++++++++++++++++++--
libparted/arch/linux.c | 24 +++++----
tests/Makefile.am | 2 +
tests/t1104-remove-and-add-partition.sh | 50 ++++++++++++++++++
tests/t6010-dm-busy.sh | 92 ++++++++++++++++++++++++++++++++
5 files changed, 249 insertions(+), 13 deletions(-)
create mode 100644 tests/t1104-remove-and-add-partition.sh
create mode 100644 tests/t6010-dm-busy.sh
diff --git a/NEWS b/NEWS
index 62d6381..c78ee9e 100644
--- a/NEWS
+++ b/NEWS
@@ -7,10 +7,98 @@ GNU parted NEWS -*- outline -*-
* Noteworthy changes in release 3.1-18 (2014-08-12) [RHEL7.1]
-** New features
+** New Features
+
+ You can now choose to ignore errors about partitions that overlap,
+ or are longer than the disk. This allows you to use parted to
+ repair the problem.
+
+** Bug Fixes
+
+ libparted: ped_partition_get_path() was returning "/dev/foo1" instead
+ of "/dev/foo" for loop labels.
+
+ partprobe: when called on a disk that has become a loop label,
+ remove any partitions left over from a previous label.
+
+ libparted: The loop label represents an unpartitioned disk, but creates
+ a dummy partition to represent the whole disk. This dummy partition
+ was actually being loaded into the kernel. Don't do that.
+
+ libparted: fix loop labels to not vanish if you don't create
+ a filesystem, and to not return an error syncing when you do.
+
+ libparted: remove all old partitions, even if new label does not allow
+ as many.
+
+ libparted: fat and ntfs boot sectors were misdetected as dos
+ partition tables instead of being treated as a loop label.
+
+ libparted: previously if you chose to ignore the warning about
+ the gpt thinking the disk was smaller than it appears to be on
+ on disk, subsequent warnings on other disks would be suppressed.
+ Now parted will warn once per disk.
+
+ Fix filesystem detection on non 512 byte sector sizes
+
+ Fix linux partition sync code to flush partitions > 16
+
+ Do not reject a FAT boot sector as invalid because it has no
+ system ID string.
+
+ libparted: /dev/md/ symlink can change after libparted dereferences it,
+ instead it should just use the symlink as given by the caller in the
+ same way we do with /dev/mapper/.
+
+ libparted: On multipath systems new partitions would sometimes not
+ appear, reporting 'device-mapper: create ioctl failed: Device or
+ resource busy' until the system was rebooted. Added dm_udev_wait
+ calls to synchronize parted with udev.
+
+ Fix help text for disk_{set,toggle} to show *disk* flags instead
+ of partition flags.
+
+ Fix gpt to correctly handle non ASCII charcters in partition names
+
+ If a drive was 100 times an even multiple of two, sizes specified as
+ a percentage would trigger the exact placement rule and refuse to round
+ to the nearest half percent.
+
+ Avoid generating udev add/remove events for all unmodified partitions
+ when writing a new table.
+
+ Fix cache coherency issue by flushing partition block devices.
+ This had been mistakenly disabled in parted 2.0, and resulted
+ in parted sometimes identifying the previous filesystem type
+ after running an mkfs to format a partition to a new type.
+
+ libparted: fix gpt end of disk handling. Previously if the backup
+ copy of the gpt was not at the end of the disk and you chose to
+ ignore this error, parted would move it to the end of the disk
+ anyhow. It will now leave the backup in the same location if
+ you chose to ignore this error.
+
+ libparted: handle logical partitions starting immediately after
+ the EBR. Creating a logical partition one sector after the EBR
+ used to cause parted to complain that it could not inform the
+ kernel of the changes, but after a reboot, everything was fine.
+ Parted will now correctly inform the kernel of the changes, but
+ only set the length of the extended partition to 1 sector instead
+ of two, which would cause it to overlap the logical partition.
+
+ parted: fix EOF and ctrl-c handling. parted used to refuse to exit
+ in response to ctrl-c and would get stuck in an infinite loop
+ prompting for more input when it reached EOF on stdin.
+
+ libparted: Don't fail to manipulate partitions on dmraid disks that
+ have other partitions in use.
- Add support for prep flag to GPT to select PowerPC Reference Platform
- boot partition type.
+ 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.
+ If you were to respond in the affirmative, libparted would read the
+ larger number of bytes into a buffer of the shorter length,
+ overrunning it.
* Noteworthy changes in release 3.1-16 (2014-01-22) [RHEL7]
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index 27f706b..de63118 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -48,6 +48,7 @@
#include "../architecture.h"
#include "dirname.h"
#include "xstrtol.h"
+#include "xalloc.h"
#if ENABLE_NLS
# include <libintl.h>
@@ -286,7 +287,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 unsigned int _device_get_partition_range(PedDevice const* dev);
static int _device_open (PedDevice* dev, int flags);
@@ -1521,8 +1522,8 @@ linux_is_busy (PedDevice* dev)
return 0;
}
-/* we need to flush the master device, and with kernel < 2.6 all the partition
- * devices, because there is no coherency between the caches with old kernels.
+/* we need to flush the master device, and all the partition devices,
+ * * because there is no coherency between the caches.
* We should only flush unmounted partition devices, because:
* - there is never a need to flush them (we're not doing IO there)
* - flushing a device that is mounted causes unnecessary IO, and can
@@ -1542,9 +1543,6 @@ _flush_cache (PedDevice* dev)
ioctl (arch_specific->fd, BLKFLSBUF);
/* With linux-2.6.0 and newer, we're done. */
- if (_have_kern26())
- return;
-
for (i = 1; i < lpn; i++) {
char* name;
int fd;
@@ -2318,7 +2316,7 @@ err:
#endif
static char*
-_device_get_part_path (PedDevice *dev, int num)
+_device_get_part_path (PedDevice const *dev, int num)
{
char *devpath;
size_t path_len;
@@ -2341,7 +2339,7 @@ _device_get_part_path (PedDevice *dev, int num)
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", devpath, p, num);
}
@@ -2355,6 +2353,10 @@ _device_get_part_path (PedDevice *dev, int num)
static char*
linux_partition_get_path (const PedPartition* part)
{
+ /* loop label means use the whole disk */
+ if (strcmp (part->disk->type->name, "loop") == 0)
+ return xstrdup (part->disk->dev->path);
+
return _device_get_part_path (part->disk->dev, part->num);
}
@@ -2423,6 +2425,8 @@ linux_partition_is_busy (const PedPartition* part)
PED_ASSERT (part != NULL);
+ if (strcmp (part->disk->type->name, "loop") == 0)
+ return linux_is_busy (part->disk->dev);
if (_partition_is_mounted (part))
return 1;
if (part->type == PED_PARTITION_EXTENDED) {
@@ -2602,7 +2606,7 @@ _sysfs_ull_entry_from_part(PedPartition const* part, const char *entry,
unsigned long long *val)
{
char path[128];
- char *part_name = linux_partition_get_path(part);
+ char *part_name = _device_get_part_path (part->disk->dev, part->num);
if (!part_name)
return false;
@@ -2637,7 +2641,7 @@ _kernel_get_partition_start_and_length(PedPartition const *part,
PED_ASSERT(start);
PED_ASSERT(length);
- char *dev_name = linux_partition_get_path (part);
+ char *dev_name = _device_get_part_path (part->disk->dev, part->num);
if (!dev_name)
return false;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 29fa280..ac8122b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -34,6 +34,7 @@ TESTS = \
t0501-duplicate.sh \
t1100-busy-label.sh \
t1101-busy-partition.sh \
+ t1104-remove-and-add-partition.sh \
t1700-probe-fs.sh \
t2200-dos-label-recog.sh \
t2201-pc98-label-recog.sh \
@@ -59,6 +60,7 @@ TESTS = \
t6002-dm-many-partitions.sh \
t6003-dm-uuid.sh \
t6004-dm-512b-sectors.sh \
+ t6010-dm-busy.sh \
t6100-mdraid-partitions.sh \
t7000-scripting.sh \
t8000-loop.sh \
diff --git a/tests/t1104-remove-and-add-partition.sh b/tests/t1104-remove-and-add-partition.sh
new file mode 100644
index 0000000..61cc392
--- /dev/null
+++ b/tests/t1104-remove-and-add-partition.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# make sure that removing a higher numbered partition and adding a lower
+# one using that space at the same time works
+
+# Copyright (C) 2014 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
+path_prepend_ ../partprobe
+require_root_
+ss=$sector_size_
+
+d1= f1=
+cleanup_fn_()
+{
+ test -n "$d1" && losetup -d "$d1"
+ rm -f "$f1"
+}
+
+f1=$(pwd)/1; d1=$(loop_setup_ "$f1") \
+ || skip_ "is this partition mounted with 'nodev'?"
+
+require_partitionable_loop_device_ $d1
+
+# create one big partition
+parted -s $d1 mklabel msdos mkpart primary ext2 1m 10m || fail=1
+
+# save this table
+dd if=$d1 of=saved count=1 || fail=1
+
+# create two small partitions
+parted -s $d1 mklabel msdos mkpart primary ext2 1m 5m mkpart primary ext2 5m 10m || fail=1
+
+# restore first table and make sure partprobe works
+dd if=saved of=$d1 || fail=1
+partprobe $d1 || fail=1
+
+Exit $fail
diff --git a/tests/t6010-dm-busy.sh b/tests/t6010-dm-busy.sh
new file mode 100644
index 0000000..9807b40
--- /dev/null
+++ b/tests/t6010-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
--
2.7.4