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. +@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, <[email protected]> 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
