[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