diff --git a/SOURCES/0043-Add-support-for-NVMe-devices.patch b/SOURCES/0043-Add-support-for-NVMe-devices.patch new file mode 100644 index 0000000..e9b4113 --- /dev/null +++ b/SOURCES/0043-Add-support-for-NVMe-devices.patch @@ -0,0 +1,122 @@ +From 62cb6416f112dda0b0b969c1247cbc0f98314182 Mon Sep 17 00:00:00 2001 +From: Petr Uzel +Date: Tue, 14 Jun 2016 13:17:00 +0200 +Subject: [PATCH] Add support for NVMe devices + +Recognize NVMe Devices, so "parted -s /dev/nvme0n1" now prints +"NVMe Device (nvme)" instead of "Model: Unknown (unknown)". + +In order for a device to be recognized as NVMe, it has to +have a 'blkext' major number. But since this major can be +used also by other device types, we also check the device +path contains 'nvme' as a substring. + +* NEWS: Mention the change +* include/parted/device.h.in(PedDeviceType): Add PED_DEVICE_NVME +* libparted/arch/linux.c(BLKEXT_MAJOR): New define. +* libparted/arch/linux.c(_is_blkext_major): New function. +* libparted/arch/linux.c(_device_probe_type): Recognize NVMe devices. +* libparted/arch/linux.c(linux_new): Handle NVMe devices. +* parted/parted.c(do_print): Add "nvme" to list of transports. + +Signed-off-by: Brian C. Lane +(cherry picked from commit e4ae4330f3e33201aeeed3b7ca88e15d98d03e13) + +Resolves: rhbz#1316239 +--- + NEWS | 4 ++++ + include/parted/device.in.h | 3 ++- + libparted/arch/linux.c | 14 ++++++++++++++ + parted/parted.c | 2 +- + 4 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/NEWS b/NEWS +index d1ab2a6..d1a6f58 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,5 +1,9 @@ + GNU parted NEWS -*- outline -*- + ++* Noteworthy changes in release 3.1-29 (2017-04-11) [RHEL7.4] ++ ++ Parted now recognizes NVMe devices ++ + * Noteworthy changes in release 3.1-18 (2014-08-12) [RHEL7.1] + + ** New features +diff --git a/include/parted/device.in.h b/include/parted/device.in.h +index a3d1737..b0aa1f2 100644 +--- a/include/parted/device.in.h ++++ b/include/parted/device.in.h +@@ -49,7 +49,8 @@ typedef enum { + PED_DEVICE_VIRTBLK = 15, + PED_DEVICE_AOE = 16, + PED_DEVICE_MD = 17, +- PED_DEVICE_LOOP = 18 ++ PED_DEVICE_LOOP = 18, ++ PED_DEVICE_NVME = 19 + } PedDeviceType; + + typedef struct _PedDevice PedDevice; +diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c +index 341bbbb..fa329f4 100644 +--- a/libparted/arch/linux.c ++++ b/libparted/arch/linux.c +@@ -275,6 +275,7 @@ struct blkdev_ioctl_param { + #define SDMMC_MAJOR 179 + #define LOOP_MAJOR 7 + #define MD_MAJOR 9 ++#define BLKEXT_MAJOR 259 + + #define SCSI_BLK_MAJOR(M) ( \ + (M) == SCSI_DISK0_MAJOR \ +@@ -437,6 +438,12 @@ _is_virtblk_major (int major) + return _major_type_in_devices (major, "virtblk"); + } + ++static int ++_is_blkext_major (int major) ++{ ++ return _major_type_in_devices (major, "blkext"); ++} ++ + #ifdef ENABLE_DEVICE_MAPPER + static int + _is_dm_major (int major) +@@ -600,6 +607,8 @@ _device_probe_type (PedDevice* dev) + dev->type = PED_DEVICE_LOOP; + } else if (dev_major == MD_MAJOR) { + dev->type = PED_DEVICE_MD; ++ } else if (_is_blkext_major(dev_major) && dev->path && strstr(dev->path, "nvme")) { ++ dev->type = PED_DEVICE_NVME; + } else { + dev->type = PED_DEVICE_UNKNOWN; + } +@@ -1372,6 +1381,11 @@ linux_new (const char* path) + goto error_free_arch_specific; + break; + ++ case PED_DEVICE_NVME: ++ if (!init_generic (dev, _("NVMe Device"))) ++ goto error_free_arch_specific; ++ break; ++ + case PED_DEVICE_ATARAID: + if (!init_generic (dev, _("ATARAID Controller"))) + goto error_free_arch_specific; +diff --git a/parted/parted.c b/parted/parted.c +index 789030a..957789a 100644 +--- a/parted/parted.c ++++ b/parted/parted.c +@@ -947,7 +947,7 @@ _print_disk_info (const PedDevice *dev, const PedDisk *disk) + "cpqarray", "file", "ataraid", "i2o", + "ubd", "dasd", "viodasd", "sx8", "dm", + "xvd", "sd/mmc", "virtblk", "aoe", +- "md", "loopback"}; ++ "md", "loopback", "nvme"}; + + char* start = ped_unit_format (dev, 0); + PedUnit default_unit = ped_unit_get_default (); +-- +2.9.4 + diff --git a/SOURCES/0044-Document-resizepart-command.patch b/SOURCES/0044-Document-resizepart-command.patch new file mode 100644 index 0000000..80b921f --- /dev/null +++ b/SOURCES/0044-Document-resizepart-command.patch @@ -0,0 +1,65 @@ +From c051e9f7eaae007940a73be1509257bd52c569de Mon Sep 17 00:00:00 2001 +From: Phillip Susi +Date: Sun, 25 May 2014 14:43:39 -0400 +Subject: [PATCH 44/48] Document resizepart command + +(cherry picked from commit 5c793853fe5cb0718d895c3394fb909c73c6fa1e) + +Related: rhbz#1423357 +--- + doc/C/parted.8 | 4 ++++ + doc/parted.texi | 16 ++++++++++++++++ + 2 files changed, 20 insertions(+) + +diff --git a/doc/C/parted.8 b/doc/C/parted.8 +index 03bb3a5..5a24c94 100644 +--- a/doc/C/parted.8 ++++ b/doc/C/parted.8 +@@ -95,6 +95,10 @@ Rescue a lost partition that was located somewhere between \fIstart\fP and + \fIend\fP. If a partition is found, \fBparted\fP will ask if you want to + create an entry for it in the partition table. + .TP ++.B resizepart \fIpartition\fP \fIend\fP ++Change the \fIend\fP position of \fIpartition\fP. Note that this does not ++modify any filesystem present in the partition. ++.TP + .B rm \fIpartition\fP + Delete \fIpartition\fP. + .TP +diff --git a/doc/parted.texi b/doc/parted.texi +index f10d5e1..d498367 100644 +--- a/doc/parted.texi ++++ b/doc/parted.texi +@@ -423,6 +423,7 @@ GNU Parted provides the following commands: + * print:: + * quit:: + * rescue:: ++* resizepart:: + * rm:: + * select:: + * set:: +@@ -715,6 +716,21 @@ It's back! :) + + @end deffn + ++@node resizepart ++@subsection resizepart ++@cindex resizepart, command description ++@cindex command description, resizepart ++ ++@deffn Command resizepart @var{number} @var{end} ++ ++Moves the @var{end} position of partition @var{number}. Note that this ++does not modify any filesystem present in the partition. If you wish to ++do this, you will need to use external tools, such as @command{resize2fs}. ++ ++When growing a partition you will want to grow the filesystem afterwards, ++but when shrinking, you need to shrink the filesystem before the partition. ++@end deffn ++ + @node rm + @subsection rm + @cindex rm, command description +-- +2.9.4 + diff --git a/SOURCES/0045-parted-Add-stub-resize-command-for-backward-compatib.patch b/SOURCES/0045-parted-Add-stub-resize-command-for-backward-compatib.patch new file mode 100644 index 0000000..d77d797 --- /dev/null +++ b/SOURCES/0045-parted-Add-stub-resize-command-for-backward-compatib.patch @@ -0,0 +1,62 @@ +From 575b286502bd7338bfeeafbfc5e6ae6718b269f9 Mon Sep 17 00:00:00 2001 +From: Phillip Susi +Date: Tue, 8 Jan 2013 19:40:35 -0500 +Subject: [PATCH 45/48] parted: Add stub resize command for backward + compatibility + +To make sure that older scripts trying to use the resize command do not +accidentally run the new resizepart command by mistake, this undocumented +stub command will throw an error if called. + +(cherry picked from commit 56bfbe21ecca0cb6466c78baed192dc2e5401676) + +Related: rhbz#1423357 +--- + parted/parted.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/parted/parted.c b/parted/parted.c +index 957789a..d4a397b 100644 +--- a/parted/parted.c ++++ b/parted/parted.c +@@ -1478,6 +1478,16 @@ error: + } + + static int ++do_resize (PedDevice **dev, PedDisk** diskp) ++{ ++ ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_CANCEL, ++ _("The resize command has been removed in parted 3.0")); ++ return 0; ++} ++ ++static int + do_rm (PedDevice** dev) + { + PedDisk* disk; +@@ -1891,6 +1901,20 @@ NULL), + str_list_create (_(start_end_msg), NULL), 1)); + + command_register (commands, command_create ( ++ str_list_create_unique ("resize", _("resize"), NULL), ++ do_resize, ++ NULL, ++ str_list_create (_(N_("The resize command was removed in parted 3.0\n")), NULL), 1)); ++ ++command_register (commands, command_create ( ++ str_list_create_unique ("resizepart", _("resizepart"), NULL), ++ do_resizepart, ++ str_list_create ( ++_("resizepart NUMBER END resize partition NUMBER"), ++NULL), ++ str_list_create (_(number_msg), _(end_msg), NULL), 1)); ++ ++command_register (commands, command_create ( + str_list_create_unique ("rm", _("rm"), NULL), + do_rm, + str_list_create ( +-- +2.9.4 + diff --git a/SOURCES/0046-libparted-Backport-partition-resize-code.patch b/SOURCES/0046-libparted-Backport-partition-resize-code.patch new file mode 100644 index 0000000..5b054ce --- /dev/null +++ b/SOURCES/0046-libparted-Backport-partition-resize-code.patch @@ -0,0 +1,842 @@ +From 31ab97cfe0233191a73a1dd9cb7cd193451491da Mon Sep 17 00:00:00 2001 +From: "Brian C. Lane" +Date: Fri, 11 Aug 2017 08:37:11 -0700 +Subject: [PATCH 46/48] libparted: Backport partition resize code + +This adds _blkpg_resize_partition, _dm_resize_partition, and adjust the +current code to support it. Changes are somewhat extensive, since they +also touch _disk_sync_part_table. + +This is based on code from commit f09ca967a0bc443b869a6fad5b5ffe8e95c3fe9a + +Related: rhbz#1423357 +--- + libparted/arch/linux.c | 673 +++++++++++++++++++++++++++++-------------------- + 1 file changed, 403 insertions(+), 270 deletions(-) + +diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c +index fa329f4..6e78faf 100644 +--- a/libparted/arch/linux.c ++++ b/libparted/arch/linux.c +@@ -288,6 +288,7 @@ struct blkdev_ioctl_param { + + static char* _device_get_part_path (PedDevice* dev, int num); + static int _partition_is_mounted_by_path (const char* path); ++static unsigned int _device_get_partition_range(PedDevice const* dev); + static int _device_open (PedDevice* dev, int flags); + static int _device_open_ro (PedDevice* dev); + static int _device_close (PedDevice* dev); +@@ -446,6 +447,17 @@ _is_blkext_major (int major) + + #ifdef ENABLE_DEVICE_MAPPER + static int ++_dm_task_run_wait (struct dm_task *task, uint32_t cookie) ++{ ++ int rc = 0; ++ ++ rc = dm_task_run (task); ++ dm_udev_wait (cookie); ++ ++ return rc; ++} ++ ++static int + _is_dm_major (int major) + { + return _major_type_in_devices (major, "device-mapper"); +@@ -1521,6 +1533,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; +@@ -1532,7 +1545,7 @@ _flush_cache (PedDevice* dev) + if (_have_kern26()) + return; + +- for (i = 1; i < 16; i++) { ++ for (i = 1; i < lpn; i++) { + char* name; + int fd; + +@@ -2268,28 +2281,63 @@ zasprintf (const char *format, ...) + return r < 0 ? NULL : resultp; + } + ++#ifdef ENABLE_DEVICE_MAPPER ++static char * ++dm_canonical_path (PedDevice const *dev) ++{ ++ 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 *dev, int num) + { +- size_t path_len = strlen (dev->path); +- ++ 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]) + ? "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; + } + +@@ -2438,6 +2486,62 @@ _blkpg_add_partition (PedDisk* disk, const PedPartition *part) + + if (!_blkpg_part_command (disk->dev, &linux_part, + BLKPG_ADD_PARTITION)) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int ++_blkpg_remove_partition (PedDisk* disk, int n) ++{ ++ struct blkpg_partition linux_part; ++ ++ memset (&linux_part, 0, sizeof (linux_part)); ++ linux_part.pno = n; ++ return _blkpg_part_command (disk->dev, &linux_part, ++ BLKPG_DEL_PARTITION); ++} ++ ++#ifdef BLKPG_RESIZE_PARTITION ++static int _blkpg_resize_partition (PedDisk* disk, const PedPartition *part) ++{ ++ struct blkpg_partition linux_part; ++ char* dev_name; ++ ++ PED_ASSERT(disk != NULL); ++ PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0); ++ ++ dev_name = _device_get_part_path (disk->dev, part->num); ++ if (!dev_name) ++ return 0; ++ memset (&linux_part, 0, sizeof (linux_part)); ++ linux_part.start = part->geom.start * disk->dev->sector_size; ++ /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */ ++ if (part->type & PED_PARTITION_EXTENDED) { ++ if (disk->dev->sector_size == 512) { ++ linux_part.length = 2; ++ PedPartition *walk; ++ /* if the second sector is claimed by a logical partition, ++ then there's just no room for lilo, so don't try to use it */ ++ for (walk = part->part_list; walk; walk = walk->next) { ++ if (walk->geom.start == part->geom.start+1) ++ linux_part.length = 1; ++ } ++ } else { ++ linux_part.length = 1; ++ } ++ linux_part.length *= disk->dev->sector_size; ++ } ++ else ++ linux_part.length = part->geom.length * disk->dev->sector_size; ++ linux_part.pno = part->num; ++ strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH); ++ ++ free (dev_name); ++ ++ if (!_blkpg_part_command (disk->dev, &linux_part, ++ BLKPG_RESIZE_PARTITION)) { + return ped_exception_throw ( + PED_EXCEPTION_ERROR, + PED_EXCEPTION_IGNORE_CANCEL, +@@ -2454,17 +2558,7 @@ _blkpg_add_partition (PedDisk* disk, const PedPartition *part) + + return 1; + } +- +-static int +-_blkpg_remove_partition (PedDisk* disk, int n) +-{ +- struct blkpg_partition linux_part; +- +- memset (&linux_part, 0, sizeof (linux_part)); +- linux_part.pno = n; +- return _blkpg_part_command (disk->dev, &linux_part, +- BLKPG_DEL_PARTITION); +-} ++#endif + + /* Read the integer from /sys/block/DEV_BASE/ENTRY and set *VAL + to that value, where DEV_BASE is the last component of DEV->path. +@@ -2586,6 +2680,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) +@@ -2594,264 +2690,78 @@ _device_get_partition_range(PedDevice const* dev) + return range > 1 ? range : 0; + } + +-/* +- * Sync the partition table in two step process: +- * 1. Remove all of the partitions from the kernel's tables, but do not attempt +- * removal of any partition for which the corresponding ioctl call fails. +- * 2. Add all the partitions that we hold in disk, throwing a warning +- * if we cannot because step 1 failed to remove it and it is not being +- * added back with the same start and length. +- * +- * To achieve this two step process we must calculate the minimum number of +- * maximum possible partitions between what linux supports and what the label +- * type supports. EX: +- * +- * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables) +- */ +-static int +-_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); +- +- /* lpn = largest partition number. */ +- if (ped_disk_get_max_supported_partition_count(disk, &lpn)) +- lpn = PED_MIN(lpn, part_range); +- else +- lpn = part_range; +- +- /* Its not possible to support largest_partnum < 0. +- * largest_partnum == 0 would mean does not support partitions. +- * */ +- if (lpn < 1) +- return 0; +- int ret = 0; +- int *ok = calloc (lpn, sizeof *ok); +- if (!ok) +- return 0; +- int *errnums = ped_malloc(sizeof(int) * lpn); +- 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; +- } +- +- 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. */ +- 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; +- } +- } +- } +- +- char *bad_part_list = NULL; +- /* now warn about any errors */ +- for (i = 1; i <= lpn; i++) { +- if (ok[i - 1] || errnums[i - 1] == ENXIO) +- continue; +- if (bad_part_list == NULL) { +- bad_part_list = malloc (lpn * 5); +- if (!bad_part_list) +- goto cleanup; +- bad_part_list[0] = 0; +- } +- sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i); +- } +- if (bad_part_list == NULL) +- ret = 1; +- else { +- bad_part_list[strlen (bad_part_list) - 2] = 0; +- if (ped_exception_throw ( +- PED_EXCEPTION_ERROR, +- PED_EXCEPTION_IGNORE_CANCEL, +- _("Partition(s) %s on %s 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."), +- bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE) +- ret = 1; +- free (bad_part_list); +- } +- cleanup: +- free (errnums); +- free (ok); +- return ret; +-} +- + #ifdef ENABLE_DEVICE_MAPPER + static int +-_dm_remove_map_name(char *name) ++_dm_remove_partition(PedDisk* disk, int partno) + { +- struct dm_task *task = NULL; + int rc = 0; + uint32_t cookie = 0; ++ char *part_name = _device_get_part_path (disk->dev, partno); + +- task = dm_task_create(DM_DEVICE_REMOVE); ++ 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 */ ++ goto err; ++ } ++ close (fd); ++ struct dm_task *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); ++ goto err; ++ dm_task_set_name (task, part_name); ++ if (!dm_task_set_cookie (task, &cookie, 0)) ++ goto err; ++ rc = _dm_task_run_wait (task, cookie); + dm_task_update_nodes(); +-err: + dm_task_destroy(task); +- if (!rc) +- return 1; +- +- return 0; ++err: ++ free (part_name); ++ return rc; + } + +-static int +-_dm_is_part (struct dm_info *this, char *name) ++static bool ++_dm_get_partition_start_and_length(PedPartition const *part, ++ unsigned long long *start, ++ unsigned long long *length) + { + struct dm_task* task = NULL; +- struct dm_info* info = alloca(sizeof *info); +- struct dm_deps* deps = NULL; + int rc = 0; +- unsigned int i; + +- task = dm_task_create(DM_DEVICE_DEPS); +- if (!task) ++ if (!(task = dm_task_create(DM_DEVICE_TABLE))) + return 0; +- +- dm_task_set_name(task, name); +- if (!dm_task_run(task)) ++ 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; +- +- memset(info, '\0', sizeof *info); +- dm_task_get_info(task, info); +- if (!info->exists) ++ dm_task_set_name(task, path); ++ if (!dm_task_run(task)) + goto err; + +- deps = dm_task_get_deps(task); +- if (!deps) ++ 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; + +- 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; +- } +- ++ /* device-mapper uses 512b units, make sure we return length and start in terms of the device's ++ * sector size. ++ */ ++ *start /= (part->disk->dev->sector_size / PED_SECTOR_SIZE_DEFAULT); ++ *length /= (part->disk->dev->sector_size / PED_SECTOR_SIZE_DEFAULT); + err: ++ free (path); + 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) ++_dm_add_partition (PedDisk* disk, const PedPartition* part) + { + char* vol_name = NULL; + const char* dev_name = NULL; +@@ -2908,9 +2818,8 @@ _dm_add_partition (PedDisk* disk, PedPartition* part) + "linear", params); + if (!dm_task_set_cookie(task, &cookie, 0)) + goto err; +- if (dm_task_run (task)) { ++ if (_dm_task_run_wait (task, cookie)) { + //printf("0 %ld linear %s\n", part->geom.length, params); +- dm_udev_wait(cookie); + dm_task_update_nodes(); + dm_task_destroy(task); + free(params); +@@ -2918,8 +2827,7 @@ _dm_add_partition (PedDisk* disk, PedPartition* part) + free(vol_name); + return 1; + } else { +- dm_udev_wait(cookie); +- _dm_remove_map_name(vol_name); ++ _dm_remove_partition (disk, part->num); + } + err: + dm_task_update_nodes(); +@@ -2932,30 +2840,259 @@ err: + } + + static int +-_dm_reread_part_table (PedDisk* disk) ++_dm_resize_partition (PedDisk* disk, const PedPartition* part) + { +- int largest_partnum = ped_disk_get_last_partition_num (disk); +- int rc = 1; +- int i; ++ LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev); ++ char* params = NULL; ++ char* vol_name = NULL; ++ const char* dev_name = NULL; ++ uint32_t cookie = 0; ++ int rc = 0; + +- sync(); +- if (!_dm_remove_parts(disk->dev)) +- rc = 0; ++ /* Get map name from devicemapper */ ++ struct dm_task *task = dm_task_create (DM_DEVICE_INFO); ++ if (!task) ++ goto err; + +- for (i = 1; i <= largest_partnum; i++) { +- PedPartition* part; ++ if (!dm_task_set_major_minor (task, arch_specific->major, ++ arch_specific->minor, 0)) ++ goto err; + +- part = ped_disk_get_partition (disk, i); +- if (!part) +- continue; ++ if (!dm_task_run(task)) ++ goto err; ++ ++ 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; ++ ++ /* 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_RELOAD); ++ if (!task) ++ goto err; + +- if (!_dm_add_partition (disk, part)) +- rc = 0; ++ dm_task_set_name (task, vol_name); ++ /* 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); ++ /* NOTE: DM_DEVICE_RELOAD doesn't generate udev events, so no cookie is needed (it will freeze). ++ * DM_DEVICE_RESUME does, so get a cookie and synchronize with udev. ++ */ ++ if (dm_task_run (task)) { ++ dm_task_destroy (task); ++ task = dm_task_create (DM_DEVICE_RESUME); ++ if (!task) ++ goto err; ++ dm_task_set_name (task, vol_name); ++ if (!dm_task_set_cookie (task, &cookie, 0)) ++ goto err; ++ if (_dm_task_run_wait (task, cookie)) { ++ rc = 1; ++ } + } ++err: ++ dm_task_update_nodes(); ++ if (task) ++ dm_task_destroy (task); ++ free (params); ++ free (vol_name); + return rc; + } ++ + #endif + ++/* ++ * Sync the partition table in two step process: ++ * 1. Remove all of the partitions from the kernel's tables, but do not attempt ++ * removal of any partition for which the corresponding ioctl call fails. ++ * 2. Add all the partitions that we hold in disk, throwing a warning ++ * if we cannot because step 1 failed to remove it and it is not being ++ * added back with the same start and length. ++ * ++ * To achieve this two step process we must calculate the minimum number of ++ * maximum possible partitions between what linux supports and what the label ++ * type supports. EX: ++ * ++ * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables) ++ */ ++static int ++_disk_sync_part_table (PedDisk* disk) ++{ ++ PED_ASSERT(disk != NULL); ++ PED_ASSERT(disk->dev != NULL); ++ int lpn, lpn2; ++ unsigned int part_range = _device_get_partition_range(disk->dev); ++ int (*add_partition)(PedDisk* disk, const PedPartition *part); ++ int (*resize_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); ++ ++ ++#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 ++#endif ++ { ++ add_partition = _blkpg_add_partition; ++ remove_partition = _blkpg_remove_partition; ++#ifdef BLKPG_RESIZE_PARTITION ++ resize_partition = _blkpg_resize_partition; ++#else ++ resize_partition = NULL; ++#endif ++ 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_MAX(lpn, part_range); ++ else ++ lpn = part_range; ++ /* for add pass, use lesser of device or label limit */ ++ if (ped_disk_get_max_supported_partition_count(disk, &lpn2)) ++ lpn2 = PED_MIN(lpn2, part_range); ++ else ++ lpn2 = part_range; ++ /* Its not possible to support largest_partnum < 0. ++ * largest_partnum == 0 would mean does not support partitions. ++ * */ ++ if (lpn < 1) ++ return 0; ++ int ret = 0; ++ int *ok = calloc (lpn, sizeof *ok); ++ if (!ok) ++ return 0; ++ int *errnums = ped_malloc(sizeof(int) * lpn); ++ if (!errnums) ++ goto cleanup; ++ ++ int i; ++ /* remove old partitions first */ ++ for (i = 1; i <= lpn; i++) { ++ PedPartition *part = ped_disk_get_partition (disk, i); ++ if (part) { ++ 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 ++ || (resize_partition && part->num < lpn2))) ++ { ++ /* partition is unchanged, or will be resized so nothing to do */ ++ ok[i - 1] = 1; ++ continue; ++ } ++ } ++ /* 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 = lpn2; ++ /* 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) ++ { ++ if (length == part->geom.length) { ++ ok[i - 1] = 1; ++ /* partition is unchanged, so nothing to do */ ++ continue; ++ } ++ if (resize_partition ++ && start == part->geom.start) ++ { ++ /* try to resize */ ++ if (resize_partition (disk, part)) { ++ ok[i - 1] = 1; ++ continue; ++ } ++ } ++ } ++ /* add the (possibly modified or new) partition */ ++ if (!add_partition (disk, part)) { ++ ok[i - 1] = 0; ++ errnums[i - 1] = errno; ++ } ++ } ++ ++ char *bad_part_list = NULL; ++ /* now warn about any errors */ ++ for (i = 1; i <= lpn; i++) { ++ if (ok[i - 1] || errnums[i - 1] == ENXIO) ++ continue; ++ if (bad_part_list == NULL) { ++ bad_part_list = malloc (lpn * 5); ++ if (!bad_part_list) ++ goto cleanup; ++ bad_part_list[0] = 0; ++ } ++ sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i); ++ } ++ if (bad_part_list == NULL) ++ ret = 1; ++ else { ++ bad_part_list[strlen (bad_part_list) - 2] = 0; ++ if (ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_IGNORE_CANCEL, ++ _("Partition(s) %s on %s 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."), ++ bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE) ++ ret = 1; ++ free (bad_part_list); ++ } ++ cleanup: ++ free (errnums); ++ free (ok); ++ return ret; ++} ++ + static int + _have_blkpg () + { +@@ -2973,10 +3110,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, +-- +2.9.4 + diff --git a/SOURCES/0047-tests-excersise-resize-command.patch b/SOURCES/0047-tests-excersise-resize-command.patch new file mode 100644 index 0000000..c8e2932 --- /dev/null +++ b/SOURCES/0047-tests-excersise-resize-command.patch @@ -0,0 +1,124 @@ +From f1711f8bd420315a01b2df6d4339646c96169558 Mon Sep 17 00:00:00 2001 +From: Petr Uzel +Date: Tue, 27 Sep 2011 09:11:29 +0200 +Subject: [PATCH 47/48] tests: excersise resize command + +a lot of TODOs + +(cherry picked from commit 33fd692cb14045fdc13306cd57cfe2040328daa8) +--- + tests/Makefile.am | 1 + + tests/t3200-resize-partition.sh | 89 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 90 insertions(+) + create mode 100755 tests/t3200-resize-partition.sh + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 1cf859c..29fa280 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -42,6 +42,7 @@ TESTS = \ + t2400-dos-hfs-partition-type.sh \ + t2500-probe-corrupt-hfs.sh \ + t3000-resize-fs.sh \ ++ t3200-resize-partition.sh \ + t3200-type-change.sh \ + t3300-palo-prep.sh \ + t3310-flags.sh \ +diff --git a/tests/t3200-resize-partition.sh b/tests/t3200-resize-partition.sh +new file mode 100755 +index 0000000..251b545 +--- /dev/null ++++ b/tests/t3200-resize-partition.sh +@@ -0,0 +1,89 @@ ++#!/bin/sh ++# exercise the resize sub-command ++# based on t3000-resize-fs.sh test ++ ++# Copyright (C) 2009-2011 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 . ++ ++. "${srcdir=.}/init.sh"; path_prepend_ ../parted ++ ++require_root_ ++require_scsi_debug_module_ ++ ++ss=$sector_size_ ++ ++default_start=1024s ++default_end=2048s ++ ++# create memory-backed device ++scsi_debug_setup_ dev_size_mb=5 > dev-name || ++ skip_ 'failed to create scsi_debug device' ++dev=$(cat dev-name) ++ ++# TODO test simple shrink ++# TODO test expand past end of the disk ++# TODO test expand past begin of next partition ++# TODO test shrink before start ++# TODO test everything with GPT ++# TODO more tests with extended/logical partitions ++ ++parted -s $dev mklabel msdos > out 2> err || fail=1 ++# expect no output ++compare /dev/null out || fail=1 ++compare /dev/null err || fail=1 ++ ++# ensure that the disk is large enough ++dev_n_sectors=$(parted -s $dev u s p|sed -n '2s/.* \([0-9]*\)s$/\1/p') ++device_sectors_required=$(echo $default_end | sed 's/s$//') ++# Ensure that $dev is large enough for this test ++test $device_sectors_required -le $dev_n_sectors || fail=1 ++ ++# create an empty partition ++parted -a minimal -s $dev mkpart primary $default_start $default_end > out 2>&1 || fail=1 ++compare /dev/null out || fail=1 ++ ++# print partition table ++parted -m -s $dev u s p > out 2>&1 || fail=1 ++ ++# FIXME: check expected output ++ ++# wait for new partition device to appear ++wait_for_dev_to_appear_ ${dev}1 || { warn_ "${dev}1 did not appear" fail=1; } ++sleep 1 ++ ++ ++# extend the filesystem to end on sector 4096 ++new_end=4096s ++parted -s $dev resizepart 1 $new_end > out 2> err || fail=1 ++# expect no output ++compare /dev/null out || fail=1 ++compare /dev/null err || fail=1 ++ ++# print partition table ++parted -m -s $dev u s p > out 2>&1 || fail=1 ++ ++sed -n 3p out > k && mv k out || fail=1 ++printf "1:$default_start:$new_end:3073s:::$ms;\n" > exp || fail=1 ++compare exp out || fail=1 ++ ++# Remove the partition explicitly, so that mklabel doesn't evoke a warning. ++parted -s $dev rm 1 || fail=1 ++ ++# Create a clean partition table for the next iteration. ++parted -s $dev mklabel msdos > out 2>&1 || fail=1 ++# expect no output ++compare /dev/null out || fail=1 ++ ++Exit $fail +-- +2.9.4 + diff --git a/SOURCES/0048-parted-add-resizepart-command.patch b/SOURCES/0048-parted-add-resizepart-command.patch new file mode 100644 index 0000000..689111a --- /dev/null +++ b/SOURCES/0048-parted-add-resizepart-command.patch @@ -0,0 +1,140 @@ +From 109a5a35d8482f43c7d779df3b7d10bf16d5f31b Mon Sep 17 00:00:00 2001 +From: Petr Uzel +Date: Mon, 26 Sep 2011 17:21:01 +0200 +Subject: [PATCH 48/48] parted: add resizepart command + +Add resizepart command to resize ( change the end position ) an existing +partition. Note that it does nothing to a filesystem in the partition. + +(cherry picked from commit 21c58e17c473ea8ef31a18d03348eb2381c0f36c) + +Resolves: rhbz#1423357 +--- + NEWS | 1 + + parted/parted.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 77 insertions(+), 1 deletion(-) + +diff --git a/NEWS b/NEWS +index d1a6f58..62d6381 100644 +--- a/NEWS ++++ b/NEWS +@@ -3,6 +3,7 @@ GNU parted NEWS -*- outline -*- + * Noteworthy changes in release 3.1-29 (2017-04-11) [RHEL7.4] + + Parted now recognizes NVMe devices ++ Add resizepart command to resize a partition + + * Noteworthy changes in release 3.1-18 (2014-08-12) [RHEL7.1] + +diff --git a/parted/parted.c b/parted/parted.c +index d4a397b..d64b0b8 100644 +--- a/parted/parted.c ++++ b/parted/parted.c +@@ -152,6 +152,9 @@ static const char* fs_type_msg_start = N_("FS-TYPE is one of: "); + static const char* start_end_msg = N_("START and END are disk locations, such as " + "4GB or 10%. Negative values count from the end of the disk. " + "For example, -1s specifies exactly the last sector.\n"); ++static const char* end_msg = N_("END is disk location, such as " ++ "4GB or 10%. Negative value counts from the end of the disk. " ++ "For example, -1s specifies exactly the last sector.\n"); + static const char* state_msg = N_("STATE is one of: on, off\n"); + static const char* device_msg = N_("DEVICE is usually /dev/hda or /dev/sda\n"); + static const char* name_msg = N_("NAME is any word you want\n"); +@@ -435,6 +438,21 @@ constraint_from_start_end (PedDevice* dev, PedGeometry* range_start, + range_start, range_end, 1, dev->length); + } + ++ ++static PedConstraint* ++constraint_from_start_end_fixed_start (PedDevice* dev, PedSector start_sector, ++ PedGeometry* range_end) ++{ ++ PedGeometry range_start; ++ range_start.dev = dev; ++ range_start.start = start_sector; ++ range_start.end = start_sector; ++ range_start.length = 1; ++ ++ return ped_constraint_new (ped_alignment_any, ped_alignment_any, ++ &range_start, range_end, 1, dev->length); ++} ++ + void + help_on (char* topic) + { +@@ -1478,7 +1496,7 @@ error: + } + + static int +-do_resize (PedDevice **dev, PedDisk** diskp) ++do_resize (PedDevice **dev) + { + ped_exception_throw ( + PED_EXCEPTION_ERROR, +@@ -1488,6 +1506,63 @@ do_resize (PedDevice **dev, PedDisk** diskp) + } + + static int ++do_resizepart (PedDevice** dev) ++{ ++ PedDisk *disk; ++ PedPartition *part = NULL; ++ PedSector start, end, oldend; ++ PedGeometry *range_end = NULL; ++ PedConstraint* constraint; ++ int rc = 0; ++ ++ disk = ped_disk_new (*dev); ++ if (!disk) ++ goto error; ++ ++ if (ped_disk_is_flag_available(disk, PED_DISK_CYLINDER_ALIGNMENT)) ++ if (!ped_disk_set_flag(disk, PED_DISK_CYLINDER_ALIGNMENT, ++ alignment == ALIGNMENT_CYLINDER)) ++ goto error; ++ ++ if (!command_line_get_partition (_("Partition number?"), disk, &part)) ++ goto error; ++ if (!_partition_warn_busy (part)) ++ goto error; ++ ++ start = part->geom.start; ++ end = oldend = part->geom.end; ++ if (!command_line_get_sector (_("End?"), *dev, &end, &range_end, NULL)) ++ goto error; ++ /* Do not move start of the partition */ ++ constraint = constraint_from_start_end_fixed_start (*dev, start, range_end); ++ if (!ped_disk_set_partition_geom (disk, part, constraint, ++ start, end)) ++ goto error_destroy_constraint; ++ /* warn when shrinking partition - might lose data */ ++ if (part->geom.end < oldend) ++ if (ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_YES_NO, ++ _("Shrinking a partition can cause data loss, " \ ++ "are you sure you want to continue?")) != PED_EXCEPTION_YES) ++ goto error_destroy_constraint; ++ ped_disk_commit (disk); ++ ++ if ((*dev)->type != PED_DEVICE_FILE) ++ disk_is_modified = 1; ++ ++ rc = 1; ++ ++error_destroy_constraint: ++ ped_constraint_destroy (constraint); ++error: ++ if (range_end != NULL) ++ ped_geometry_destroy (range_end); ++ return rc; ++} ++ ++ ++static int + do_rm (PedDevice** dev) + { + PedDisk* disk; +-- +2.9.4 + diff --git a/SPECS/parted.spec b/SPECS/parted.spec index 749687f..1f453cb 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: 29%{?dist} License: GPLv3+ Group: Applications/System URL: http://www.gnu.org/software/parted @@ -58,6 +58,12 @@ Patch39: 0039-docs-Add-list-of-filesystems-for-fs-type-1311596.patch 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 +Patch43: 0043-Add-support-for-NVMe-devices.patch +Patch44: 0044-Document-resizepart-command.patch +Patch45: 0045-parted-Add-stub-resize-command-for-backward-compatib.patch +Patch46: 0046-libparted-Backport-partition-resize-code.patch +Patch47: 0047-tests-excersise-resize-command.patch +Patch48: 0048-parted-add-resizepart-command.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: e2fsprogs-devel @@ -74,6 +80,7 @@ BuildRequires: git BuildRequires: autoconf automake BuildRequires: e2fsprogs BuildRequires: dosfstools +BuildRequires: bc Requires(post): /sbin/ldconfig Requires(post): /sbin/install-info @@ -193,6 +200,12 @@ fi %changelog +* Thu Aug 10 2017 Brian C. Lane - 3.1-29 +- Add support for NVMe devices + Resolves: rhbz#1316239 +- Backport partition resize command + Resolves: rhbz#1423357 + * Fri Aug 26 2016 Brian C. Lane - 3.1-28 - tests: Set optimal blocks to 64 for scsi_debug devices Resolves: rhbz#1359682