[parted-devel] [PATCH] parted: Fix resizepart command
Arvin Schnell
aschnell at suse.com
Thu Sep 16 16:30:22 BST 2021
Hi,
here is another patch for master. It was already presented on
this mailing list about four years ago ([1] - [3]). In short, in
script mode the resizepart warning about the busy partition is
shown and thus parted fails.
>From my understanding a test case was the only thing missing. I
have now updated the patch and added such a test case.
Thanks,
Arvin
[1] https://alioth-lists.debian.net/pipermail/parted-devel/2017-September/005110.html
[2] https://alioth-lists.debian.net/pipermail/parted-devel/2017-September/005105.html
[3] https://alioth-lists.debian.net/pipermail/parted-devel/2017-November/005134.html
---
NEWS | 4 ++
doc/C/parted.8 | 3 ++
doc/parted.texi | 3 ++
parted/parted.c | 62 ++++++++++++++++++++++------
tests/Makefile.am | 1 +
tests/t-lib-helpers.sh | 5 +++
tests/t3210-resize-partition-busy.sh | 58 ++++++++++++++++++++++++++
7 files changed, 124 insertions(+), 12 deletions(-)
create mode 100755 tests/t3210-resize-partition-busy.sh
diff --git a/NEWS b/NEWS
index 408a4f3..f659702 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ GNU parted NEWS -*- outline -*-
* Noteworthy changes in release ?.? (????-??-??) [?]
+** Bug Fixes
+
+ Allow enforcing shrinking or removing busy partitions in script
+ mode.
* Noteworthy changes in release 3.4 (2021-01-27) [stable]
diff --git a/doc/C/parted.8 b/doc/C/parted.8
index 46b30ad..dbf0713 100644
--- a/doc/C/parted.8
+++ b/doc/C/parted.8
@@ -33,6 +33,9 @@ never prompts for user intervention
.B -f, --fix
automatically answer "fix" to exceptions in script mode
.TP
+.B --ignore-busy
+perform the requested action in script mode although a partition is busy
+.TP
.B -v, --version
displays the version
.TP
diff --git a/doc/parted.texi b/doc/parted.texi
index 57ceb55..dcf921c 100644
--- a/doc/parted.texi
+++ b/doc/parted.texi
@@ -420,6 +420,9 @@ automatically answer exceptions with "fix" in script mode, whcih is useful for:
GPT header not including full disk size; moving the backup GPT table to the end of the disk;
MAC fix missing partition map entry; etc.
+ at item --ignore-busy
+perform the requested action in script mode although a partition is busy
+
@item -a alignment-type
@itemx --align alignment-type
Set alignment for newly created partitions, valid alignment types are:
diff --git a/parted/parted.c b/parted/parted.c
index 975700c..37ef7a6 100644
--- a/parted/parted.c
+++ b/parted/parted.c
@@ -78,6 +78,7 @@ static int MEGABYTE_SECTORS (PedDevice* dev)
enum
{
PRETEND_INPUT_TTY = CHAR_MAX + 1,
+ IGNORE_BUSY
};
/* Output modes */
@@ -119,6 +120,9 @@ typedef struct {
time_t predicted_time_left;
} TimerContext;
+/* Note: The order of entries in options and options_help must be identical, see code in
+ print_options_help(). */
+
static struct option const options[] = {
/* name, has-arg, string-return-val, char-return-val */
{"help", 0, NULL, 'h'},
@@ -129,6 +133,7 @@ static struct option const options[] = {
{"fix", 0, NULL, 'f'},
{"version", 0, NULL, 'v'},
{"align", required_argument, NULL, 'a'},
+ {"ignore-busy", no_argument, NULL, IGNORE_BUSY},
{"-pretend-input-tty", 0, NULL, PRETEND_INPUT_TTY},
{NULL, 0, NULL, 0}
};
@@ -142,6 +147,7 @@ static const char *const options_help [][2] = {
{"fix", N_("in script mode, fix instead of abort when asked")},
{"version", N_("displays the version")},
{"align=[none|cyl|min|opt]", N_("alignment for new partitions")},
+ {"ignore-busy", N_("perform action although partition is busy")},
{NULL, NULL}
};
@@ -152,6 +158,7 @@ int opt_output_mode = HUMAN;
int disk_is_modified = 0;
int is_toggle_mode = 0;
int alignment = ALIGNMENT_OPTIMAL;
+int ignore_busy = 0;
static const char* number_msg = N_(
"NUMBER is the partition number used by Linux. On MS-DOS disk labels, the "
@@ -236,13 +243,19 @@ _timer_handler (PedTimer* timer, void* context)
}
static int
-_partition_warn_busy (PedPartition* part)
+_partition_warn_busy (PedPartition* part, bool dangerous)
{
char* path;
if (ped_partition_is_busy (part)) {
path = ped_partition_get_path (part);
- if (ped_exception_throw (
+ if (opt_script_mode && (!dangerous || ignore_busy)) {
+ ped_exception_throw (
+ PED_EXCEPTION_WARNING,
+ PED_EXCEPTION_UNHANDLED,
+ _("Partition %s is being used, continuing anyway."),
+ path);
+ } else if (ped_exception_throw (
PED_EXCEPTION_WARNING,
PED_EXCEPTION_YES_NO,
_("Partition %s is being used. Are you sure you " \
@@ -502,8 +515,11 @@ print_options_help ()
int i;
for (i=0; options_help [i][0]; i++) {
- printf (" -%c, --%-25.25s %s\n",
- options_help [i][0][0],
+ if (options[i].val < CHAR_MAX + 1)
+ printf (" -%c, ", options [i].val);
+ else
+ printf (" ");
+ printf ("--%-25.25s %s\n",
options_help [i][0],
_(options_help [i][1]));
}
@@ -1729,6 +1745,11 @@ do_resizepart (PedDevice** dev, PedDisk** diskp)
PedSector start, end, oldend;
PedGeometry *range_end = NULL;
PedConstraint* constraint;
+ int cmdline_words = command_line_get_word_count();
+ /* update this if adding/removing arguments to/from this command */
+ const int part_idx = 1;
+ const int end_idx = 2;
+ const bool danger_if_busy = false;
int rc = 0;
char* end_input = NULL;
char* end_size = NULL;
@@ -1755,7 +1776,8 @@ do_resizepart (PedDevice** dev, PedDisk** diskp)
}
/* If the partition is busy this may clear the command_line and prompt the user */
- if (!_partition_warn_busy (part))
+ /* warn early if the partition end is not provided on cmdline */
+ if (cmdline_words <= part_idx && !_partition_warn_busy (part, danger_if_busy))
goto error;
/* Push the End value back onto the command_line, if it exists */
@@ -1768,6 +1790,8 @@ do_resizepart (PedDevice** dev, PedDisk** diskp)
if (!command_line_get_sector (_("End?"), *dev, &end, &range_end, &end_input))
goto error;
_adjust_end_if_iec(&start, &end, range_end, end_input);
+ if (cmdline_words >= end_idx && !_partition_warn_busy (part, danger_if_busy))
+ goto error;
/* Do not move start of the partition */
constraint = constraint_from_start_end_fixed_start (*dev, start, range_end);
@@ -1775,13 +1799,23 @@ do_resizepart (PedDevice** dev, PedDisk** diskp)
start, end))
goto error_destroy_constraint;
/* warn when shrinking partition - might lose data */
- if (part->geom.end < oldend)
- if (ped_exception_throw (
+ if (part->geom.end < oldend) {
+ if (opt_script_mode && (!ped_partition_is_busy (part) || ignore_busy)) {
+ char *path = ped_partition_get_path (part);
+ 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_EXCEPTION_UNHANDLED,
+ _("Shrinking partition %s, data loss possible."), path);
+ free(path);
+ } else 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)
@@ -1805,6 +1839,7 @@ static int
do_rm (PedDevice** dev, PedDisk** diskp)
{
PedPartition* part = NULL;
+ const bool danger_if_busy = true;
if (!*diskp)
*diskp = ped_disk_new (*dev);
@@ -1813,7 +1848,7 @@ do_rm (PedDevice** dev, PedDisk** diskp)
if (!command_line_get_partition (_("Partition number?"), *diskp, &part))
goto error;
- if (!_partition_warn_busy (part))
+ if (!_partition_warn_busy (part, danger_if_busy))
goto error;
if (!ped_disk_delete_partition (*diskp, part))
@@ -2394,6 +2429,9 @@ while (1)
alignment = XARGMATCH ("--align", optarg,
align_args, align_types);
break;
+ case IGNORE_BUSY:
+ ignore_busy = 1;
+ break;
case PRETEND_INPUT_TTY:
pretend_input_tty = 1;
break;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f9340aa..974c032 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -59,6 +59,7 @@ TESTS = \
t3000-resize-fs.sh \
t3200-resize-partition.sh \
t3200-type-change.sh \
+ t3210-resize-partition-busy.sh \
t3300-palo-prep.sh \
t3310-flags.sh \
t3400-whole-disk-FAT-partition.sh \
diff --git a/tests/t-lib-helpers.sh b/tests/t-lib-helpers.sh
index 33151bb..97a5fc6 100644
--- a/tests/t-lib-helpers.sh
+++ b/tests/t-lib-helpers.sh
@@ -362,6 +362,11 @@ require_xfs_()
mkfs.xfs -V || skip_ "this test requires XFS support"
}
+require_btrfs_()
+{
+ mkfs.btrfs -V || skip_ "this test requires btrfs support"
+}
+
require_dvhtool_()
{
dvhtool --help \
diff --git a/tests/t3210-resize-partition-busy.sh b/tests/t3210-resize-partition-busy.sh
new file mode 100755
index 0000000..53550f5
--- /dev/null
+++ b/tests/t3210-resize-partition-busy.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+# Test shrinking and growing a mounted partition
+
+# Copyright (C) 2021 SUSE LLC
+
+# 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_
+require_scsi_debug_module_
+require_btrfs_
+
+# create memory-backed device
+scsi_debug_setup_ dev_size_mb=300 > dev-name ||
+ skip_ 'failed to create scsi_debug device'
+dev=$(cat dev-name)
+
+# create GPT and partition
+parted --script "$dev" mklabel gpt > out 2> err || fail=1
+parted --script "$dev" mkpart "test1" ext4 0% 100% > out 2>&1 || fail=1
+
+# wait for new partition device to appear
+wait_for_dev_to_appear_ "${dev}1" || { warn_ "${dev}1 did not appear" fail=1; }
+
+# create btrfs
+mkfs.btrfs "${dev}1" || skip_ mkfs.btrfs failed
+
+# mount btrfs
+mount_point="$(pwd)/mnt"
+mkdir "$mount_point" || fail=1
+mount "${dev}1" "$mount_point" || fail=1
+
+# shrink btrfs
+btrfs filesystem resize 280M "$mount_point" || fail=1
+
+# shrink busy partition (does need --ignore-busy)
+parted --script --ignore-busy "$dev" resizepart 1 95% || fail=1
+
+# grow busy partition (does not need --ignore-busy)
+parted --script "$dev" resizepart 1 100% || fail=1
+
+# unmount btrfs
+umount "${dev}1" || fail=1
+
+Exit $fail
--
Arvin Schnell, <aschnell at suse.com>
Senior Software Engineer, Research & Development
SUSE Software Solutions Germany GmbH
Maxfeldstraße 5
90409 Nürnberg
Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer
More information about the parted-devel
mailing list