From a7d850a3b39b160dcc23e12491cb2cc7c056cd01 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Wed, 28 Oct 2015 11:57:22 -0700 Subject: [PATCH 35/36] parted: Display details of partition alignment failure (#726856) When alignment for a new partition fails it isn't always obvious why it failed. This adds printing the reason for the failure, in the form of: start % grain != offset This modifies align-check in interactive mode to print the alignment the error details if it isn't aligned. Script mode behavior is unchanged. Also cleanup pointer usage and handle asprintf failure by using a constant string in the error report - "unknown (malloc failure)". (cherry picked from commit 1726dbb4cd2dc4b19fe8d3c4b94e172fc0bd2c7c) --- parted/parted.c | 64 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/parted/parted.c b/parted/parted.c index 18b778c..06f9971 100644 --- a/parted/parted.c +++ b/parted/parted.c @@ -183,7 +183,8 @@ static TimerContext timer_context; static int _print_list (); static void _done (PedDevice* dev, PedDisk *diskp); static bool partition_align_check (PedDisk const *disk, - PedPartition const *part, enum AlignmentType a_type); + PedPartition const *part, enum AlignmentType a_type, + char **align_err); static void _timer_handler (PedTimer* timer, void* context) @@ -783,21 +784,27 @@ do_mkpart (PedDevice** dev, PedDisk** diskp) } } + char *align_err = NULL; if ((alignment == ALIGNMENT_OPTIMAL && - !partition_align_check(disk, part, PA_OPTIMUM)) || + !partition_align_check(disk, part, PA_OPTIMUM, &align_err)) || (alignment == ALIGNMENT_MINIMAL && - !partition_align_check(disk, part, PA_MINIMUM))) { + !partition_align_check(disk, part, PA_MINIMUM, &align_err))) { if (ped_exception_throw( PED_EXCEPTION_WARNING, (opt_script_mode ? PED_EXCEPTION_OK : PED_EXCEPTION_IGNORE_CANCEL), _("The resulting partition is not properly " - "aligned for best performance.")) == + "aligned for best performance: %s"), + align_err ? align_err : _("unknown (malloc failed)")) == PED_EXCEPTION_CANCEL) { + if (align_err) + free(align_err); /* undo partition addition */ goto error_remove_part; } + if (align_err) + free(align_err); } } else { ped_exception_leave_all(); @@ -1629,10 +1636,18 @@ do_select (PedDevice** dev, PedDisk** diskp) offset and alignment requirements. Also return true if there is insufficient kernel support to determine DISK's alignment requirements. Otherwise, return false. A_TYPE selects whether to check for minimal - or optimal alignment requirements. */ + or optimal alignment requirements. + + If align_err is not NULL a string describing why the check failed + will be allocated and returned. It is up to the caller to free this. + Pass NULL if no error description is needed. + + If allocating the error string fails *align_err will be set to NULL, the + caller should always check for this. +*/ static bool partition_align_check (PedDisk const *disk, PedPartition const *part, - enum AlignmentType a_type) + enum AlignmentType a_type, char **align_err) { PED_ASSERT (part->disk == disk); PedDevice const *dev = disk->dev; @@ -1641,10 +1656,20 @@ partition_align_check (PedDisk const *disk, PedPartition const *part, ? ped_device_get_minimum_alignment (dev) : ped_device_get_optimum_alignment (dev)); if (pa == NULL) - return true; + return true; PED_ASSERT (pa->grain_size != 0); bool ok = (part->geom.start % pa->grain_size == pa->offset); + + /* If it isn't aligned and the caller wants an explanation, + show them the math. */ + if (!ok && align_err) { + if (asprintf(align_err, + "%llds %% %llds != %llds", + part->geom.start, pa->grain_size, pa->offset) < 0) { + *align_err = NULL; + } + } free (pa); return ok; } @@ -1665,12 +1690,25 @@ do_align_check (PedDevice **dev, PedDisk** diskp) if (!command_line_get_partition (_("Partition number?"), *diskp, &part)) goto error; - bool aligned = partition_align_check (*diskp, part, align_type); - if (!opt_script_mode) - printf(aligned ? _("%d aligned\n") : _("%d not aligned\n"), part->num); - - if (opt_script_mode) - return aligned ? 1 : 0; + char *align_err = NULL; + bool aligned = partition_align_check (*diskp, part, align_type, &align_err); + + /* Don't print the error in script mode */ + if (opt_script_mode) { + if (align_err) + free(align_err); + return aligned ? 1 : 0; + } + + if (aligned) + printf(_("%d aligned\n"), part->num); + else + printf(_("%d not aligned: %s\n"), + part->num, + align_err ? align_err : _("unknown (malloc failed)")); + + if (align_err) + free(align_err); /* Always return 1 in interactive mode, to be consistent with the other modes. */ -- 2.5.5