From 02c9baa147ccb6988f7d6b14d30fc159047e1b04 Mon Sep 17 00:00:00 2001
From: Scott Little <scott.little@windriver.com>
Date: Wed, 1 Aug 2018 15:39:27 -0400
Subject: [PATCH] Relocate parted to stx-integ/filesystem/parted

Move content from stx-gplv3 into stx-integ

Packages will be relocated to

stx-integ:
    base/
        anaconda
        crontabs
        dnsmasq
        rsync

    database/
        python-psycopg2

    filesystem/
        parted

    grub/
        grub2

    security/
        python-keyring

Change-Id: I567380cf4f84d31c2bd07f0b89b77a452f7cbc90
Story: 2002801
Task: 22687
Signed-off-by: Scott Little <scott.little@windriver.com>
---
 centos_pkg_dirs                               |    1 +
 filesystem/parted/PKG-INFO                    |   14 +
 filesystem/parted/centos/build_srpm.data      |    3 +
 ...te-package-versioning-for-TIS-format.patch |   25 +
 ...tting-removed-for-100-to-300-ms-on-p.patch |   33 +
 .../parted/centos/meta_patches/PATCH_ORDER    |    3 +
 .../parted/centos/meta_patches/syscalls.patch |   63 +
 ...ed-for-100-to-300-ms-on-parted-print.patch | 1103 +++++++++++++++++
 .../parted/centos/patches/syscalls.patch      |   42 +
 filesystem/parted/centos/srpm_path            |    1 +
 filesystem/parted/files/Makefile              |  285 +++++
 .../files/fix-compile-failure-while-dis.patch |   57 +
 filesystem/parted/files/fix-doc-mandir.patch  |   20 +
 filesystem/parted/files/no_check.patch        |   20 +
 filesystem/parted/files/resizepart.sh         |   24 +
 filesystem/parted/files/run-ptest             |    3 +
 filesystem/parted/files/syscalls.patch        |   55 +
 17 files changed, 1752 insertions(+)
 create mode 100644 filesystem/parted/PKG-INFO
 create mode 100644 filesystem/parted/centos/build_srpm.data
 create mode 100644 filesystem/parted/centos/meta_patches/0001-Update-package-versioning-for-TIS-format.patch
 create mode 100644 filesystem/parted/centos/meta_patches/0003-fix-dev-nodes-getting-removed-for-100-to-300-ms-on-p.patch
 create mode 100644 filesystem/parted/centos/meta_patches/PATCH_ORDER
 create mode 100644 filesystem/parted/centos/meta_patches/syscalls.patch
 create mode 100644 filesystem/parted/centos/patches/fix-dev-nodes-getting-removed-for-100-to-300-ms-on-parted-print.patch
 create mode 100644 filesystem/parted/centos/patches/syscalls.patch
 create mode 100644 filesystem/parted/centos/srpm_path
 create mode 100644 filesystem/parted/files/Makefile
 create mode 100644 filesystem/parted/files/fix-compile-failure-while-dis.patch
 create mode 100644 filesystem/parted/files/fix-doc-mandir.patch
 create mode 100644 filesystem/parted/files/no_check.patch
 create mode 100644 filesystem/parted/files/resizepart.sh
 create mode 100644 filesystem/parted/files/run-ptest
 create mode 100644 filesystem/parted/files/syscalls.patch

diff --git a/centos_pkg_dirs b/centos_pkg_dirs
index 1a9c87074..bf9468238 100644
--- a/centos_pkg_dirs
+++ b/centos_pkg_dirs
@@ -143,3 +143,4 @@ database/python-psycopg2
 base/crontabs
 base/dnsmasq
 base/rsync
+filesystem/parted
diff --git a/filesystem/parted/PKG-INFO b/filesystem/parted/PKG-INFO
new file mode 100644
index 000000000..c886bc56b
--- /dev/null
+++ b/filesystem/parted/PKG-INFO
@@ -0,0 +1,14 @@
+Metadata-Version: 1.1
+Name: parted
+Version: 2.0.21
+Summary: Disk partition editing/resizing utility
+Home-page: 
+Author:
+Author-email:
+License: GPLv3+
+
+Description:
+Disk partition editing/resizing utility
+
+        
+Platform: UNKNOWN
diff --git a/filesystem/parted/centos/build_srpm.data b/filesystem/parted/centos/build_srpm.data
new file mode 100644
index 000000000..b7ca4ec65
--- /dev/null
+++ b/filesystem/parted/centos/build_srpm.data
@@ -0,0 +1,3 @@
+COPY_LIST="files/resizepart.sh"
+TIS_PATCH_VER=3
+BUILD_IS_SLOW=5
diff --git a/filesystem/parted/centos/meta_patches/0001-Update-package-versioning-for-TIS-format.patch b/filesystem/parted/centos/meta_patches/0001-Update-package-versioning-for-TIS-format.patch
new file mode 100644
index 000000000..0c371843d
--- /dev/null
+++ b/filesystem/parted/centos/meta_patches/0001-Update-package-versioning-for-TIS-format.patch
@@ -0,0 +1,25 @@
+From 74ab16d7e0c23b933b3d6f42eac63d70d07ab62d Mon Sep 17 00:00:00 2001
+From: Don Penney <don.penney@windriver.com>
+Date: Tue, 27 Sep 2016 10:50:03 -0400
+Subject: [PATCH] Update package versioning for TIS format
+
+---
+ SPECS/parted.spec | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/SPECS/parted.spec b/SPECS/parted.spec
+index 644c2df..b79ca4a 100644
+--- a/SPECS/parted.spec
++++ b/SPECS/parted.spec
+@@ -4,7 +4,7 @@
+ Summary: The GNU disk partition manipulation program
+ Name:    parted
+ Version: 3.1
+-Release: 28%{?dist}
++Release: 28.el7%{?_tis_dist}.%{tis_patch_ver}
+ License: GPLv3+
+ Group:   Applications/System
+ URL:     http://www.gnu.org/software/parted
+-- 
+1.8.3.1
+
diff --git a/filesystem/parted/centos/meta_patches/0003-fix-dev-nodes-getting-removed-for-100-to-300-ms-on-p.patch b/filesystem/parted/centos/meta_patches/0003-fix-dev-nodes-getting-removed-for-100-to-300-ms-on-p.patch
new file mode 100644
index 000000000..de2d8b838
--- /dev/null
+++ b/filesystem/parted/centos/meta_patches/0003-fix-dev-nodes-getting-removed-for-100-to-300-ms-on-p.patch
@@ -0,0 +1,33 @@
+From cfa8f478bd19cf706f87c3c5a8baf54df7f2ea16 Mon Sep 17 00:00:00 2001
+From: Ovidiu Poncea <ovidiu.poncea@windriver.com>
+Date: Fri, 2 Mar 2018 17:22:52 +0200
+Subject: [PATCH] 
+ fix-dev-nodes-getting-removed-for-100-to-300-ms-on-parted-print.patch
+
+---
+ SPECS/parted.spec | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/SPECS/parted.spec b/SPECS/parted.spec
+index 6979b14..06a09f8 100644
+--- a/SPECS/parted.spec
++++ b/SPECS/parted.spec
+@@ -15,6 +15,7 @@ Source0: ftp://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz
+ Source1: ftp://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz.sig
+ Source2: pubkey.jim.meyering
+ Source3: resizepart.sh
++Source4: fix-dev-nodes-getting-removed-for-100-to-300-ms-on-parted-print.patch
+ 
+ Patch0: parted-3.0-libparted-copy-pmbr_boot-when-duplicating-GPT-disk.patch
+ Patch1: parted-3.1-libparted-check-PMBR-before-GPT-partition-table-8052.patch
+@@ -64,6 +65,7 @@ Patch42: 0042-tests-Set-optimal-blocks-to-64-for-scsi_debug-device.patch
+ 
+ # WRS
+ Patch43: syscalls.patch
++Patch44: fix-dev-nodes-getting-removed-for-100-to-300-ms-on-parted-print.patch
+ 
+ Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+ BuildRequires: e2fsprogs-devel
+-- 
+1.9.1
+
diff --git a/filesystem/parted/centos/meta_patches/PATCH_ORDER b/filesystem/parted/centos/meta_patches/PATCH_ORDER
new file mode 100644
index 000000000..3cd0fe8f5
--- /dev/null
+++ b/filesystem/parted/centos/meta_patches/PATCH_ORDER
@@ -0,0 +1,3 @@
+syscalls.patch
+0001-Update-package-versioning-for-TIS-format.patch
+0003-fix-dev-nodes-getting-removed-for-100-to-300-ms-on-p.patch
diff --git a/filesystem/parted/centos/meta_patches/syscalls.patch b/filesystem/parted/centos/meta_patches/syscalls.patch
new file mode 100644
index 000000000..1dd07c4dd
--- /dev/null
+++ b/filesystem/parted/centos/meta_patches/syscalls.patch
@@ -0,0 +1,63 @@
+From 4859fab94b298a4ca449216c3035b8b024c661a3 Mon Sep 17 00:00:00 2001
+From: Kristine Bujold <kristine.bujold@windriver.com>
+Date: Wed, 21 Dec 2016 15:28:53 -0500
+Subject: [PATCH 1/2] WRS: syscalls.patch
+
+---
+ SPECS/parted.spec | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/SPECS/parted.spec b/SPECS/parted.spec
+index 749687f..644c2df 100644
+--- a/SPECS/parted.spec
++++ b/SPECS/parted.spec
+@@ -12,6 +12,7 @@ URL:     http://www.gnu.org/software/parted
+ Source0: ftp://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz
+ Source1: ftp://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz.sig
+ Source2: pubkey.jim.meyering
++Source3: resizepart.sh
+ 
+ Patch0: parted-3.0-libparted-copy-pmbr_boot-when-duplicating-GPT-disk.patch
+ Patch1: parted-3.1-libparted-check-PMBR-before-GPT-partition-table-8052.patch
+@@ -59,6 +60,9 @@ Patch40: 0040-partprobe-Open-the-device-once-for-probing-1339705.patch
+ Patch41: 0041-tests-Stop-timing-t9040-1172675.patch
+ Patch42: 0042-tests-Set-optimal-blocks-to-64-for-scsi_debug-device.patch
+ 
++# WRS
++Patch43: syscalls.patch
++
+ Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+ BuildRequires: e2fsprogs-devel
+ BuildRequires: readline-devel
+@@ -121,7 +125,7 @@ git commit -a -m "run iconv"
+ autoreconf
+ autoconf
+ CFLAGS="$RPM_OPT_FLAGS -Wno-unused-but-set-variable"; export CFLAGS
+-%configure --enable-selinux --disable-static
++%configure --enable-selinux --disable-static --disable-device-mapper
+ # Don't use rpath!
+ %{__sed} -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
+ %{__sed} -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
+@@ -150,6 +154,9 @@ popd
+ 
+ %find_lang %{name}
+ 
++# WRS
++install -d %{buildroot}%{_sbindir}
++install -m 755 %{SOURCE3} %{buildroot}%{_sbindir}/resizepart.sh
+ 
+ %check
+ export LD_LIBRARY_PATH=$(pwd)/libparted/.libs
+@@ -185,6 +192,9 @@ fi
+ %{_libdir}/libparted-fs-resize.so*
+ %{_infodir}/parted.info.gz
+ 
++# WRS
++%{_sbindir}/resizepart.sh
++
+ %files devel
+ %defattr(-,root,root,-)
+ %{_includedir}/parted
+-- 
+1.8.3.1
+
diff --git a/filesystem/parted/centos/patches/fix-dev-nodes-getting-removed-for-100-to-300-ms-on-parted-print.patch b/filesystem/parted/centos/patches/fix-dev-nodes-getting-removed-for-100-to-300-ms-on-parted-print.patch
new file mode 100644
index 000000000..74cc157a3
--- /dev/null
+++ b/filesystem/parted/centos/patches/fix-dev-nodes-getting-removed-for-100-to-300-ms-on-parted-print.patch
@@ -0,0 +1,1103 @@
+From 9e7ad12a13665d975ddb9ee4669f781a1a695f8a 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                  | 565 +++++++++++++++-----------------
+ tests/Makefile.am                       |   2 +
+ tests/t1104-remove-and-add-partition.sh |  50 +++
+ tests/t6010-dm-busy.sh                  |  92 ++++++
+ 5 files changed, 499 insertions(+), 304 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 d1ab2a6..42ee12c 100644
+--- a/NEWS
++++ b/NEWS
+@@ -2,10 +2,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 67a5c2e..adb82f2 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>
+@@ -285,11 +286,12 @@ 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 _device_open (PedDevice* dev, int flags);
+ static int _device_open_ro (PedDevice* dev);
+ static int _device_close (PedDevice* dev);
++static unsigned int _device_get_partition_range(PedDevice const* dev);
+ 
+ static int
+ _read_fd (int fd, char **buf)
+@@ -1495,8 +1497,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
+@@ -1507,6 +1509,7 @@ _flush_cache (PedDevice* dev)
+ {
+         LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
+         int             i;
++	int             lpn = _device_get_partition_range(dev);
+ 
+         if (dev->read_only)
+                 return;
+@@ -1514,11 +1517,7 @@ _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 < 16; i++) {
++        for (i = 1; i < lpn; i++) {
+                 char*           name;
+                 int             fd;
+ 
+@@ -2265,34 +2264,72 @@ zasprintf (const char *format, ...)
+   return r < 0 ? NULL : resultp;
+ }
+ 
+-static char*
+-_device_get_part_path (PedDevice *dev, int num)
++#ifdef ENABLE_DEVICE_MAPPER
++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;
++}
++#endif
++
++static char*
++_device_get_part_path (PedDevice const *dev, int num)
++{
++        char *devpath;
++        size_t path_len;
+         char *result;
++#ifdef ENABLE_DEVICE_MAPPER
++        devpath = (dev->type == PED_DEVICE_DM
++                         ? dm_canonical_path (dev) : dev->path);
++#else
++        devpath = dev->path;
++#endif
++        path_len = strlen (devpath);
+         /* 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);
+         }
+-
++#ifdef ENABLE_DEVICE_MAPPER
++        if (dev->type == PED_DEVICE_DM)
++                free (devpath);
++#endif
+         return result;
+ }
+ 
+ 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);
+ }
+ 
+@@ -2361,6 +2398,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) {
+@@ -2494,7 +2533,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;
+ 
+@@ -2529,7 +2568,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;
+ 
+@@ -2583,6 +2622,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)
+@@ -2591,6 +2632,133 @@ _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);
++        /* libdevmapper likes to complain on stderr instead of quietly
++           returning ENOENT or ENXIO, so try to stat first */
++        struct stat st;
++        if (stat(path, &st))
++                goto err;
++        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, &params);
++        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
+@@ -2611,12 +2779,31 @@ _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);
++
+ 
+-        /* lpn = largest partition number. */
++#ifdef ENABLE_DEVICE_MAPPER
++        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
++#endif
++        {
++                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.
++         * for remove pass, use greater of device or label limit */
+         if (ped_disk_get_max_supported_partition_count(disk, &lpn))
+-                lpn = PED_MIN(lpn, part_range);
++                lpn = PED_MAX(lpn, part_range);
+         else
+                 lpn = part_range;
+ 
+@@ -2633,59 +2820,68 @@ _disk_sync_part_table (PedDisk* disk)
+         if (!errnums)
+                 goto cleanup;
+ 
+-        /* Attempt to remove each and every partition, retrying for
+-           up to max_sleep_seconds upon any failure due to EBUSY. */
+-        unsigned int sleep_microseconds = 10000;
+-        unsigned int max_sleep_seconds = 1;
+-        unsigned int n_sleep = (max_sleep_seconds
+-                                * 1000000 / sleep_microseconds);
+         int i;
+-        for (i = 0; i < n_sleep; i++) {
+-	    if (i)
+-		usleep (sleep_microseconds);
+-            bool busy = false;
+-            int j;
+-            for (j = 0; j < lpn; j++) {
+-                if (!ok[j]) {
+-                    ok[j] = _blkpg_remove_partition (disk, j + 1);
+-                    errnums[j] = errno;
+-                    if (!ok[j] && errnums[j] == EBUSY)
+-                        busy = true;
+-                }
+-            }
+-            if (!busy)
+-                break;
+-        }
+-
++        /* remove old partitions first */
+         for (i = 1; i <= lpn; i++) {
+                 PedPartition *part = ped_disk_get_partition (disk, i);
+                 if (part) {
+-                        if (!ok[i - 1] && errnums[i - 1] == EBUSY) {
+-                                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))
+-                                        goto cleanup;
+-                                if (start == part->geom.start
+-				    && length == part->geom.length)
+-                                        ok[i - 1] = 1;
+-                                /* If the new partition is unchanged and the
+-				   existing one was not removed because it was
+-				   in use, then reset the error flag and do not
+-				   try to add it since it is already there.  */
++                        unsigned long long length;
++                        unsigned long long start;
++                        /* get start and length of existing partition */
++                        if (get_partition_start_and_length(part,
++                                                           &start, &length)
++                            && start == part->geom.start
++                            && length == part->geom.length)
++                        {
++                                /* partition is unchanged, so nothing to do */
++                                ok[i - 1] = 1;
+                                 continue;
+                         }
+-
+-                        /* add the (possibly modified or new) partition */
+-                        if (!_blkpg_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;
+-                        }
++                }
++                /* Attempt to remove the partition, retrying for
++                   up to max_sleep_seconds upon any failure due to EBUSY. */
++                unsigned int sleep_microseconds = 10000;
++                unsigned int max_sleep_seconds = 1;
++                unsigned int n_sleep = (max_sleep_seconds
++                                        * 1000000 / sleep_microseconds);
++                do {
++                        ok[i - 1] = remove_partition (disk, i);
++                        errnums[i - 1] = errno;
++                        if (ok[i - 1] || errnums[i - 1] != EBUSY)
++                                break;
++                        usleep (sleep_microseconds);
++                } while (n_sleep--);
++                if (!ok[i - 1] && errnums[i - 1] == ENXIO)
++                        ok[i - 1] = 1; /* it already doesn't exist */
++	}
++        /* lpn = largest partition number.
++         * for add pass, use lesser of device or label limit */
++        if (ped_disk_get_max_supported_partition_count(disk, &lpn))
++                lpn = PED_MIN(lpn, part_range);
++        else
++                lpn = part_range;
++        /* don't actually add partitions for loop */
++        if (strcmp (disk->type->name, "loop") == 0)
++                lpn = 0;
++        for (i = 1; i <= lpn; i++) {
++                PedPartition *part = ped_disk_get_partition (disk, i);
++                if (!part)
++                        continue;
++                unsigned long long length;
++                unsigned long long start;
++                /* get start and length of existing partition */
++                if (get_partition_start_and_length(part,
++                                                   &start, &length)
++                    && start == part->geom.start
++                    && length == part->geom.length) {
++                        ok[i - 1] = 1;
++                        /* partition is unchanged, so nothing to do */
++                        continue;
++                }
++                /* add the (possibly modified or new) partition */
++                if (!add_partition (disk, part)) {
++                        ok[i - 1] = 0;
++                        errnums[i - 1] = errno;
+                 }
+         }
+ 
+@@ -2724,235 +2920,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 = 0;
+-        uint32_t        cookie = 0;
+-
+-        task = dm_task_create(DM_DEVICE_REMOVE);
+-        if (!task)
+-                return 1;
+-
+-        dm_task_set_name (task, name);
+-        if (!dm_task_set_cookie(task, &cookie, 0))
+-            goto err;
+-
+-        rc = dm_task_run(task);
+-        dm_udev_wait(cookie);
+-        dm_task_update_nodes();
+-err:
+-        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*           vol_uuid = NULL;
+-        const char*     dev_uuid = NULL;
+-        char*           params = NULL;
+-        LinuxSpecific*  arch_specific = LINUX_SPECIFIC (disk->dev);
+-        uint32_t        cookie = 0;
+-
+-        /* 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);
+-        dev_uuid = dm_task_get_uuid (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;
+-
+-        if ( dev_uuid && (strlen(dev_uuid) > 0) \
+-             && ! (vol_uuid = zasprintf ("part%d-%s", part->num, dev_uuid)))
+-                goto err;
+-
+-        /* Caution: dm_task_destroy frees dev_name.  */
+-        dm_task_destroy (task);
+-        task = NULL;
+-
+-        /* device-mapper uses 512b units, not the device's sector size */
+-        if ( ! (params = zasprintf ("%d:%d %lld", arch_specific->major,
+-                                    arch_specific->minor,
+-                                    part->geom.start * (disk->dev->sector_size / PED_SECTOR_SIZE_DEFAULT))))
+-                goto err;
+-
+-        task = dm_task_create (DM_DEVICE_CREATE);
+-        if (!task)
+-                goto err;
+-
+-        dm_task_set_name (task, vol_name);
+-        if (vol_uuid)
+-                dm_task_set_uuid (task, vol_uuid);
+-        /* device-mapper uses 512b units, not the device's sector size */
+-        dm_task_add_target (task, 0, part->geom.length * (disk->dev->sector_size / PED_SECTOR_SIZE_DEFAULT),
+-                "linear", params);
+-        if (!dm_task_set_cookie(task, &cookie, 0))
+-            goto err;
+-        if (dm_task_run (task)) {
+-                //printf("0 %ld linear %s\n", part->geom.length, params);
+-                dm_udev_wait(cookie);
+-                dm_task_update_nodes();
+-                dm_task_destroy(task);
+-                free(params);
+-                free(vol_uuid);
+-                free(vol_name);
+-                return 1;
+-        } else {
+-                dm_udev_wait(cookie);
+-                _dm_remove_map_name(vol_name);
+-        }
+-err:
+-        dm_task_update_nodes();
+-        if (task)
+-                dm_task_destroy (task);
+-        free (params);
+-        free (vol_uuid);
+-        free (vol_name);
+-        return 0;
+-}
+-
+-static int
+-_dm_reread_part_table (PedDisk* disk)
+-{
+-        int largest_partnum = ped_disk_get_last_partition_num (disk);
+-        int     rc = 1;
+-        int     i;
+-
+-        sync();
+-        if (!_dm_remove_parts(disk->dev))
+-                rc = 0;
+-
+-        for (i = 1; i <= largest_partnum; 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 ()
+ {
+@@ -2970,10 +2937,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 1cf859c..44518c8 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 \
+@@ -58,6 +59,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
+-- 
+1.9.1
+
diff --git a/filesystem/parted/centos/patches/syscalls.patch b/filesystem/parted/centos/patches/syscalls.patch
new file mode 100644
index 000000000..287a30553
--- /dev/null
+++ b/filesystem/parted/centos/patches/syscalls.patch
@@ -0,0 +1,42 @@
+From: "Allain Legacy" <allain.legacy@windriver.com>
+---
+Index: parted-3.1/libparted/arch/linux.c
+===================================================================
+--- parted-3.1.orig/libparted/arch/linux.c
++++ parted-3.1/libparted/arch/linux.c
+@@ -1646,12 +1646,14 @@ _device_close (PedDevice* dev)
+ 
+ #if SIZEOF_OFF_T < 8
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ static _syscall5(int,_llseek,
+                  unsigned int, fd,
+                  unsigned long, offset_high,
+                  unsigned long, offset_low,
+                  loff_t*, result,
+                  unsigned int, origin)
++#endif
+ 
+ loff_t
+ llseek (unsigned int fd, loff_t offset, unsigned int whence)
+@@ -1659,11 +1661,20 @@ llseek (unsigned int fd, loff_t offset,
+         loff_t result;
+         int retval;
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+         retval = _llseek(fd,
+                          ((unsigned long long)offset) >> 32,
+                          ((unsigned long long)offset) & 0xffffffff,
+                          &result,
+                          whence);
++#else
++        retval = syscall(__NR__llseek, fd,
++                         ((unsigned long long)offset) >> 32,
++                         ((unsigned long long)offset) & 0xffffffff,
++                         &result,
++                         whence);
++#endif
++
+         return (retval==-1 ? (loff_t) retval : result);
+ }
+ 
diff --git a/filesystem/parted/centos/srpm_path b/filesystem/parted/centos/srpm_path
new file mode 100644
index 000000000..97272a941
--- /dev/null
+++ b/filesystem/parted/centos/srpm_path
@@ -0,0 +1 @@
+mirror:Source/parted-3.1-28.el7.src.rpm
diff --git a/filesystem/parted/files/Makefile b/filesystem/parted/files/Makefile
new file mode 100644
index 000000000..ee90be081
--- /dev/null
+++ b/filesystem/parted/files/Makefile
@@ -0,0 +1,285 @@
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+
+am__tty_colors = \
+$(am__tty_colors_dummy); \
+test "X$(AM_COLOR_TESTS)" != Xno \
+&& test "X$$TERM" != Xdumb \
+&& { test "X$(AM_COLOR_TESTS)" = Xalways || test -t 1 2>/dev/null; } \
+&& { \
+  am__color_tests=yes; \
+  red=''; \
+  grn=''; \
+  lgn=''; \
+  blu=''; \
+  mgn=''; \
+  brg=''; \
+  std=''; \
+}
+
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+am__rst_section = { sed 'p;s/./=/g;' && echo; }
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+
+am__common_driver_flags = \
+  --color-tests "$$am__color_tests" \
+  --enable-hard-errors "$$am__enable_hard_errors" \
+  --expect-failure "$$am__expect_failure"
+am__check_pre = \
+$(am__sh_e_setup);					\
+$(am__vpath_adj_setup) $(am__vpath_adj)			\
+$(am__tty_colors);					\
+srcdir=$(srcdir); export srcdir;			\
+am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;		\
+test "x$$am__odir" = x. || $(MKDIR_P) "$$am__odir" || exit $$?;	\
+if test -f "./$$f"; then dir=./;			\
+elif test -f "$$f"; then dir=;				\
+else dir="$(srcdir)/"; fi;				\
+tst=$$dir$$f; log='$@'; 				\
+if test -n '$(DISABLE_HARD_ERRORS)'; then		\
+  am__enable_hard_errors=no; 				\
+else							\
+  am__enable_hard_errors=yes; 				\
+fi; 							\
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+
+am__set_TESTS_bases = \
+  bases='$(TEST_LOGS)'; \
+  bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+  bases=`echo $$bases`
+
+RECHECK_LOGS = $(TEST_LOGS)
+TEST_SUITE_LOG = test-suite.log
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:.log=.log)
+TEST_LOGS = $(am__test_logs2:.sh.log=.log)
+SH_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
+SH_LOG_COMPILE = $(SH_LOG_COMPILER)
+
+am__set_b = \
+  case '$@' in \
+    */*) \
+      case '$*' in \
+        */*) b='$*';; \
+          *) b=`echo '$@' | sed 's/\.log$$//'`; \
+       esac;; \
+    *) \
+      b='$*';; \
+  esac
+
+MKDIR_P = /bin/mkdir -p
+SHELL = /bin/bash
+VERSION = 3.1
+PACKAGE_STRING = GNU parted 3.1
+PACKAGE_BUGREPORT = bug-parted@gnu.org
+abs_srcdir = $(PWD)
+abs_top_builddir = $(PWD)/..
+abs_top_srcdir = $(PWD)/..
+srcdir = .
+top_srcdir = ..
+subdir = tests
+SH_LOG_COMPILER = $(SHELL)
+
+TESTS = \
+  help-version.sh \
+  t0000-basic.sh \
+  t0001-tiny.sh \
+  t0010-script-no-ctrl-chars.sh \
+  t0100-print.sh \
+  t0101-print-empty.sh \
+  t0200-gpt.sh \
+  t0201-gpt.sh \
+  t0202-gpt-pmbr.sh \
+  t0203-gpt-tiny-device-abort.sh \
+  t0203-gpt-shortened-device-primary-valid.sh \
+  t0205-gpt-list-clobbers-pmbr.sh \
+  t0206-gpt-print-with-corrupt-primary-clobbers-pmbr.sh \
+  t0207-IEC-binary-notation.sh \
+  t0208-mkpart-end-in-IEC.sh \
+  t0209-gpt-pmbr_boot.sh \
+  t0210-gpt-resized-partition-entry-array.sh \
+  t0211-gpt-rewrite-header.sh \
+  t0212-gpt-many-partitions.sh \
+  t0220-gpt-msftres.sh \
+  t0250-gpt.sh \
+  t0280-gpt-corrupt.sh \
+  t0300-dos-on-gpt.sh \
+  t0400-loop-clobber-infloop.sh \
+  t0500-dup-clobber.sh \
+  t0501-duplicate.sh \
+  t1100-busy-label.sh \
+  t1101-busy-partition.sh \
+  t1700-probe-fs.sh \
+  t2200-dos-label-recog.sh \
+  t2201-pc98-label-recog.sh \
+  t2300-dos-label-extended-bootcode.sh \
+  t2310-dos-extended-2-sector-min-offset.sh \
+  t2400-dos-hfs-partition-type.sh \
+  t2500-probe-corrupt-hfs.sh \
+  t3000-resize-fs.sh \
+  t3200-type-change.sh \
+  t3300-palo-prep.sh \
+  t3310-flags.sh \
+  t3400-whole-disk-FAT-partition.sh \
+  t4000-sun-raid-type.sh \
+  t4001-sun-vtoc.sh \
+  t4100-msdos-partition-limits.sh \
+  t4100-dvh-partition-limits.sh \
+  t4100-msdos-starting-sector.sh \
+  t4200-partprobe.sh \
+  t4300-nilfs2-tiny.sh \
+  t5000-tags.sh \
+  t6000-dm.sh \
+  t6001-psep.sh \
+  t6100-mdraid-partitions.sh \
+  t7000-scripting.sh \
+  t8000-loop.sh \
+  t8001-loop-blkpg.sh \
+  t9010-big-sector.sh \
+  t9020-alignment.sh \
+  t9021-maxima.sh \
+  t9022-one-unit-snap.sh \
+  t9023-value-lt-one.sh \
+  t9030-align-check.sh \
+  t9040-many-partitions.sh \
+  t9041-undetected-in-use-16th-partition.sh \
+  t9042-dos-partition-limit.sh \
+  t9050-partition-table-types.sh
+
+TESTS_ENVIRONMENT = \
+  export					\
+  abs_top_builddir='$(abs_top_builddir)'	\
+  abs_top_srcdir='$(abs_top_srcdir)'		\
+  abs_srcdir='$(abs_srcdir)'			\
+  built_programs=parted				\
+  srcdir='$(srcdir)'				\
+  top_srcdir='$(top_srcdir)'			\
+  VERSION=$(VERSION)				\
+  ; 9>&2
+
+.SUFFIXES: .log
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+	@$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+	ws='[ 	]'; \
+	results=`for b in $$bases; do echo $$b.trs; done`; \
+	test -n "$$results" || results=/dev/null; \
+	all=`  grep "^$$ws*:test-result:"           $$results | wc -l`; \
+	pass=` grep "^$$ws*:test-result:$$ws*PASS"  $$results | wc -l`; \
+	fail=` grep "^$$ws*:test-result:$$ws*FAIL"  $$results | wc -l`; \
+	skip=` grep "^$$ws*:test-result:$$ws*SKIP"  $$results | wc -l`; \
+	xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+	xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+	error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+	if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+	  success=true; \
+	else \
+	  success=false; \
+	fi; \
+	br='==================='; br=$$br$$br$$br$$br; \
+	result_count () \
+	{ \
+	    if test x"$$1" = x"--maybe-color"; then \
+	      maybe_colorize=yes; \
+	    elif test x"$$1" = x"--no-color"; then \
+	      maybe_colorize=no; \
+	    else \
+	      echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+	    fi; \
+	    shift; \
+	    desc=$$1 count=$$2; \
+	    if test $$maybe_colorize = yes && test $$count -gt 0; then \
+	      color_start=$$3 color_end=$$std; \
+	    else \
+	      color_start= color_end=; \
+	    fi; \
+	    echo "$${color_start}# $$desc $$count$${color_end}"; \
+	}; \
+	create_testsuite_report () \
+	{ \
+	  result_count $$1 "TOTAL:" $$all   "$$brg"; \
+	  result_count $$1 "PASS: " $$pass  "$$grn"; \
+	  result_count $$1 "SKIP: " $$skip  "$$blu"; \
+	  result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+	  result_count $$1 "FAIL: " $$fail  "$$red"; \
+	  result_count $$1 "XPASS:" $$xpass "$$red"; \
+	  result_count $$1 "ERROR:" $$error "$$mgn"; \
+	}; \
+	{								\
+	  echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" |	\
+	    $(am__rst_title);						\
+	  create_testsuite_report --no-color;				\
+	  echo;								\
+	  echo ".. contents:: :depth: 2";				\
+	  echo;								\
+	  for i in $$bases; do						\
+	    if grep "^$$ws*:copy-in-global-log:$$ws*no$$ws*$$" $$i.trs \
+	         >/dev/null; then continue; \
+	    fi; \
+	    glob_res=`sed -n -e "s/$$ws*$$//" \
+	                     -e "s/^$$ws*:global-test-result:$$ws*//p" \
+		        $$i.trs`; \
+	    test -n "$$glob_res" || glob_res=RUN; \
+	    echo "$$glob_res: $$i" | $(am__rst_section); \
+	    if test ! -r $$i.log; then \
+	      echo "fatal: making $@: $$i.log is unreadable" >&2; \
+	      exit 1; \
+	    fi; \
+	    cat $$i.log; echo; \
+	  done;	\
+	} >$(TEST_SUITE_LOG).tmp;					\
+	mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);			\
+	if $$success; then						\
+	  col="$$grn";							\
+	 else								\
+	  col="$$red";							\
+	  test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG);		\
+	fi;								\
+	echo "$${col}$$br$${std}"; 					\
+	echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}";	\
+	echo "$${col}$$br$${std}"; 					\
+	create_testsuite_report --maybe-color;				\
+	echo "$$col$$br$$std";						\
+	if $$success; then :; else					\
+	  echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}";		\
+	  if test -n "$(PACKAGE_BUGREPORT)"; then			\
+	    echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}";	\
+	  fi;								\
+	  echo "$$col$$br$$std";					\
+	fi;								\
+	$$success || exit 1
+
+check-TESTS:
+	@if test $@ != recheck; then \
+	   list='$(RECHECK_LOGS)'; \
+	   test -z "$$list" || rm -f $$list; \
+	 fi
+	@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+	@ws='[ 	]'; \
+	log_list='' trs_list=''; $(am__set_TESTS_bases); \
+	for i in $$bases; do \
+	  if test -z "$$log_list"; then \
+	    log_list="$$i.log"; \
+	  else \
+	    log_list="$$log_list $$i.log"; \
+	  fi; \
+	  if test -z "$$trs_list"; then \
+	    trs_list="$$i.trs"; \
+	  else \
+	    trs_list="$$trs_list $$i.trs"; \
+	  fi; \
+	done; \
+	$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"
+
+.sh.log:
+	@p='$<'; \
+	$(am__set_b); \
+	$(am__check_pre) $(SH_LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) -- $(SH_LOG_COMPILE) "$$tst"
diff --git a/filesystem/parted/files/fix-compile-failure-while-dis.patch b/filesystem/parted/files/fix-compile-failure-while-dis.patch
new file mode 100644
index 000000000..68ab715f3
--- /dev/null
+++ b/filesystem/parted/files/fix-compile-failure-while-dis.patch
@@ -0,0 +1,57 @@
+From 060e74354774d36d2c11ef08e3e7ea9b9b6e23fb Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Thu, 13 Nov 2014 11:29:33 +0800
+Subject: [PATCH] libparted/arch/linux.c: fix compile failure while
+ --disable-device-mapper
+
+While --disable-device-mapper, the MACRO ENABLE_DEVICE_MAPPER is
+undef, but it missed to scope some device mapper functions.
+
+Upstream-Status: Pending
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ libparted/arch/linux.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
+index 6fd73c5..2afa479 100644
+--- a/libparted/arch/linux.c
++++ b/libparted/arch/linux.c
+@@ -2320,6 +2320,7 @@ zasprintf (const char *format, ...)
+ static char *
+ dm_canonical_path (PedDevice const *dev)
+ {
++#ifdef ENABLE_DEVICE_MAPPER
+         LinuxSpecific const *arch_specific = LINUX_SPECIFIC (dev);
+ 
+         /* Get map name from devicemapper */
+@@ -2337,6 +2338,7 @@ dm_canonical_path (PedDevice const *dev)
+         dm_task_destroy (task);
+         return dev_name;
+ err:
++#endif
+         return NULL;
+ }
+ 
+@@ -2957,13 +2959,15 @@ _disk_sync_part_table (PedDisk* disk)
+                                                unsigned long long *start,
+                                                unsigned long long *length);
+ 
+-
++#ifdef ENABLE_DEVICE_MAPPER
+         if (disk->dev->type == PED_DEVICE_DM) {
+                 add_partition = _dm_add_partition;
+                 remove_partition = _dm_remove_partition;
+                 resize_partition = _dm_resize_partition;
+                 get_partition_start_and_length = _dm_get_partition_start_and_length;
+-        } else {
++        } else
++#endif
++        {
+                 add_partition = _blkpg_add_partition;
+                 remove_partition = _blkpg_remove_partition;
+ #ifdef BLKPG_RESIZE_PARTITION
+-- 
+1.9.1
+
diff --git a/filesystem/parted/files/fix-doc-mandir.patch b/filesystem/parted/files/fix-doc-mandir.patch
new file mode 100644
index 000000000..0711d4e29
--- /dev/null
+++ b/filesystem/parted/files/fix-doc-mandir.patch
@@ -0,0 +1,20 @@
+Upstream-Status: Submitted [bug-parted@gnu.org]
+
+| for po in `ls -1 ./*.pt_BR.po 2>/dev/null`; do \
+| 		make $(basename ${po%.pt_BR.po}); \
+| 	done
+| Makefile:904: *** Recursive variable `mandir' references itself (eventually).  Stop.
+
+Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
+
+--- parted-3.1/doc/po4a.mk.orig	2012-03-15 14:09:11.555831872 +0100
++++ parted-3.1/doc/po4a.mk	2012-03-15 14:10:44.243830985 +0100
+@@ -23,7 +23,7 @@
+ # threshold is 80%), it won't be distributed, and the build won't fail.
+ #
+ 
+-mandir = $(mandir)/$(lang)
++mandir := $(mandir)/$(lang)
+ 
+ # Inform automake that we want to install some man pages in section 1, 5
+ # and 8.
diff --git a/filesystem/parted/files/no_check.patch b/filesystem/parted/files/no_check.patch
new file mode 100644
index 000000000..58d8db442
--- /dev/null
+++ b/filesystem/parted/files/no_check.patch
@@ -0,0 +1,20 @@
+Upstream-Status: Inappropriate [configuration]
+
+If check is detected, it makes the builds non-determinstic so just force
+it to be disabled.
+
+RP - 4/11/08
+
+Index: parted-1.9.0/configure.ac
+===================================================================
+--- parted-1.9.0.orig/configure.ac	2009-07-23 18:52:08.000000000 +0100
++++ parted-1.9.0/configure.ac	2010-02-02 14:13:56.013905093 +0000
+@@ -477,7 +477,7 @@
+ AM_CONDITIONAL([BUILD_LINUX], [test "$OS" = linux])
+ 
+ dnl check for "check", unit testing library/header
+-PKG_CHECK_MODULES([CHECK], [check >= 0.9.3], have_check=yes, have_check=no)
++have_check=no
+ if test "$have_check" != "yes"; then
+     AC_MSG_RESULT([Unable to locate check version 0.9.3 or higher: not building])
+ fi
diff --git a/filesystem/parted/files/resizepart.sh b/filesystem/parted/files/resizepart.sh
new file mode 100644
index 000000000..29be2a0f2
--- /dev/null
+++ b/filesystem/parted/files/resizepart.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+################################################################################
+# Copyright (c) 2015 Wind River Systems, Inc.
+# 
+# SPDX-License-Identifier: Apache-2.0
+#
+################################################################################
+
+DEVICE=$1
+PARTITION=$2
+SIZE=$(blockdev --getsize64 ${DEVICE})
+SIZE_MB=$((SIZE / (1024*1024)))
+
+## This is a workaround to allow cloud-init to invoke parted without needing to
+## handle command prompts interactively.  Support for non-interactive parted
+## commands are not supported on mounted partitions.
+##
+/usr/sbin/parted ---pretend-input-tty ${DEVICE} resizepart ${PARTITION} << EOF
+yes
+${SIZE_MB}
+EOF
+
+exit $?
diff --git a/filesystem/parted/files/run-ptest b/filesystem/parted/files/run-ptest
new file mode 100644
index 000000000..695c5e8a7
--- /dev/null
+++ b/filesystem/parted/files/run-ptest
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+make -C tests check-TESTS
diff --git a/filesystem/parted/files/syscalls.patch b/filesystem/parted/files/syscalls.patch
new file mode 100644
index 000000000..e9bbe9a95
--- /dev/null
+++ b/filesystem/parted/files/syscalls.patch
@@ -0,0 +1,55 @@
+Upstream-Status: Pending
+
+---
+ libparted/arch/linux.c |   13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+Index: parted-1.9.0/libparted/arch/linux.c
+===================================================================
+--- parted-1.9.0.orig/libparted/arch/linux.c	2009-07-23 18:52:08.000000000 +0100
++++ parted-1.9.0/libparted/arch/linux.c	2010-02-02 14:14:16.523904768 +0000
+@@ -17,6 +17,8 @@
+ 
+ #define PROC_DEVICES_BUFSIZ 16384
+ 
++#include <linux/version.h>
++
+ #include <config.h>
+ #include <arch/linux.h>
+ 
+@@ -1477,12 +1479,14 @@
+ 
+ #if SIZEOF_OFF_T < 8
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ static _syscall5(int,_llseek,
+                  unsigned int, fd,
+                  unsigned long, offset_high,
+                  unsigned long, offset_low,
+                  loff_t*, result,
+                  unsigned int, origin)
++#endif
+ 
+ loff_t
+ llseek (unsigned int fd, loff_t offset, unsigned int whence)
+@@ -1490,11 +1494,20 @@
+         loff_t result;
+         int retval;
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+         retval = _llseek(fd,
+                          ((unsigned long long)offset) >> 32,
+                          ((unsigned long long)offset) & 0xffffffff,
+                          &result,
+                          whence);
++#else
++ 	retval = syscall(__NR__llseek, fd,
++			 ((unsigned long long)offset) >> 32,
++                         ((unsigned long long)offset) & 0xffffffff,
++                          &result,
++			 whence);
++#endif
++
+         return (retval==-1 ? (loff_t) retval : result);
+ }
+