Here are two patches I've just pushed. The first exposes new alignment-checking functions for use from the command-line. The second adds a few tests to exercise that code.
Feedback welcome. >From b925eaf8f068994b573fe8b0e7356094a6aaeb52 Mon Sep 17 00:00:00 2001 From: Jim Meyering <[email protected]> Date: Fri, 27 Nov 2009 11:15:53 +0100 Subject: [PATCH 1/2] ui: new command: align-check TYPE N e.g., parted -s /dev/sda align-check min 1 && echo partition 1 is min-aligned parted -s /dev/sda align-check opt 2 && echo partition 2 is opt-aligned * parted/parted.c: * parted/ui.c: * parted/ui.h: * NEWS (New features): Mention it. * doc/parted.texi (align-check): Describe it. --- NEWS | 9 +++++++- doc/parted.texi | 28 +++++++++++++++++++++++++++ parted/parted.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ parted/ui.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ parted/ui.h | 9 +++++++- 5 files changed, 146 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 9c68d7c..5241301 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,14 @@ GNU parted NEWS -*- outline -*- * Noteworthy changes in release ?.? (????-??-??) [?] -** Improvements +** New features + + new command "align-check TYPE N" to determine whether the starting sector + of partition N is TYPE(minimal|optimal)-aligned for the disk. E.g., + parted -s /dev/sda align-check min 1 && echo partition 1 is min-aligned + parted -s /dev/sda align-check opt 2 && echo partition 2 is opt-aligned + This is useful only on kernels for which Parted is able to determine + a disk's alignment characteristics. Add functions to libparted to get minimal and optimal alignment information from devices: diff --git a/doc/parted.texi b/doc/parted.texi index 499d660..a1d794d 100644 --- a/doc/parted.texi +++ b/doc/parted.texi @@ -510,6 +510,7 @@ display the version GNU Parted provides the following commands: @menu +* align-check:: * check:: * cp:: * help:: @@ -529,6 +530,33 @@ GNU Parted provides the following commands: * unit:: @end menu +...@node align-check +...@subsection align-check +...@cindex align-check, command description +...@cindex command description, align-check + +...@deffn Command align-check @var{align-type} @var{n} + +Determine whether the starting sector of partition @var{n} +meets the disk's selected alignment criteria. +...@var{align-type} must be @samp{minimal}, @samp{optimal} +or an abbreviation. +When in script mode, if the partition does not meet the alignment +requirement, exit with status 1; otherwise (including on older +kernels for which alignment data is not available), continue processing +any remaining commands. +Without @option{--script}, print either @sa...@var{n} aligned} +or @sa...@var{n} not aligned}. + +Example: + +...@example +(parted) @kbd{align-check minimal 1} +1 aligned +...@end example + +...@end deffn + @node check @subsection check @cindex check, command description diff --git a/parted/parted.c b/parted/parted.c index d9c4333..099bc94 100644 --- a/parted/parted.c +++ b/parted/parted.c @@ -113,6 +113,7 @@ static const char* number_msg = N_( static const char* label_type_msg_start = N_("LABEL-TYPE is one of: "); static const char* flag_msg_start = N_("FLAG is one of: "); static const char* unit_msg_start = N_("UNIT is one of: "); +static const char* min_or_opt_msg = N_("desired alignment: minimum or optimal"); static const char* part_type_msg = N_("PART-TYPE is one of: primary, logical, " "extended\n"); static const char* fs_type_msg_start = N_("FS-TYPE is one of: "); @@ -1937,6 +1938,49 @@ do_select (PedDevice** dev) return 1; } +/* Return true if partition PART is consistent with DISK's selected + 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. */ +static bool +partition_align_check (PedDisk const *disk, PedPartition const *part, + enum AlignmentType a_type) +{ + PED_ASSERT (part->disk == disk, return false); + PedDevice const *dev = disk->dev; + + PedAlignment *pa = (a_type == PA_MINIMUM + ? ped_device_get_minimum_alignment (dev) + : ped_device_get_optimum_alignment (dev)); + if (pa == NULL) + return true; + + PED_ASSERT (pa->grain_size != 0, return false); + bool ok = (part->geom.start % pa->grain_size == pa->offset); + free (pa); + return ok; +} + +static int +do_align_check (PedDevice **dev) +{ + PedDisk *disk = ped_disk_new (*dev); + if (!disk) + return 0; + + enum AlignmentType align_type; + PedPartition *part = NULL; + bool aligned = + (command_line_get_align_type (_("alignment type(min/opt)"), &align_type) + && command_line_get_partition (_("Partition number?"), disk, &part) + && partition_align_check (disk, part, align_type)); + + ped_disk_destroy (disk); + + return aligned ? 1 : 0; +} + static int do_set (PedDevice** dev) { @@ -2172,6 +2216,18 @@ _done_messages () static void _init_commands () { + command_register (commands, + command_create ( str_list_create_unique ("align-check", + _("align-check"), NULL), + do_align_check, + str_list_create ( + _("align-check TYPE N" + " " + "check partition N for" + " TYPE(min|opt) alignment"), NULL), + + str_list_create (_(number_msg), _(min_or_opt_msg), + NULL), 1)); command_register (commands, command_create ( str_list_create_unique ("check", _("check"), NULL), do_check, diff --git a/parted/ui.c b/parted/ui.c index 58fb80c..bb8222d 100644 --- a/parted/ui.c +++ b/parted/ui.c @@ -193,6 +193,11 @@ static StrList* ex_opt_str [64]; static StrList* on_list; static StrList* off_list; static StrList* on_off_list; + +static StrList* align_opt_list; +static StrList* align_min_list; +static StrList* align_opt_min_list; + static StrList* fs_type_list; static StrList* disk_type_list; @@ -1260,6 +1265,27 @@ command_line_get_ex_opt (const char* prompt, PedExceptionOption options) } int +command_line_get_align_type (const char *prompt, enum AlignmentType *align_type) +{ + char* def_word; + char* input; + + if (*align_type) + def_word = str_list_convert_node (align_opt_list); + else + def_word = str_list_convert_node (align_min_list); + input = command_line_get_word (prompt, def_word, align_opt_min_list, 1); + free (def_word); + if (!input) + return 0; + *align_type = (str_list_match_any (align_opt_list, input) + ? PA_OPTIMUM + : PA_MINIMUM); + free (input); + return 1; +} + +int command_line_get_unit (const char* prompt, PedUnit* unit) { StrList* opts = NULL; @@ -1347,6 +1373,24 @@ done_state_str () } static int +init_alignment_type_str () +{ + align_opt_list = str_list_create_unique (_("optimal"), "optimal", NULL); + align_min_list = str_list_create_unique (_("minimal"), "minimal", NULL); + align_opt_min_list = str_list_join (str_list_duplicate (align_opt_list), + str_list_duplicate (align_min_list)); + return 1; +} + +static void +done_alignment_type_str () +{ + str_list_destroy (align_opt_list); + str_list_destroy (align_min_list); + str_list_destroy (align_opt_min_list); +} + +static int init_fs_type_str () { PedFileSystemType* walk; @@ -1409,6 +1453,7 @@ init_ui () { if (!init_ex_opt_str () || !init_state_str () + || !init_alignment_type_str () || !init_fs_type_str () || !init_disk_type_str ()) return 0; @@ -1453,6 +1498,7 @@ done_ui () ped_exception_set_handler (NULL); done_ex_opt_str (); done_state_str (); + done_alignment_type_str (); str_list_destroy (fs_type_list); str_list_destroy (disk_type_list); } diff --git a/parted/ui.h b/parted/ui.h index e5358e5..d5b3fc0 100644 --- a/parted/ui.h +++ b/parted/ui.h @@ -21,6 +21,12 @@ #include "strlist.h" +enum AlignmentType + { + PA_MINIMUM = 1, + PA_OPTIMUM + }; + extern const char *prog_name; extern int init_ui (); @@ -65,6 +71,8 @@ extern int command_line_get_part_type (const char* prompt, const PedDisk* disk, extern PedExceptionOption command_line_get_ex_opt (const char* prompt, PedExceptionOption options); extern int command_line_get_unit (const char* prompt, PedUnit* unit); +extern int command_line_get_align_type (const char *prompt, + enum AlignmentType *align_type); extern int command_line_is_integer (); extern int command_line_is_sector (); @@ -80,5 +88,4 @@ extern int pretend_input_tty; extern void print_options_help (); extern void print_commands_help (); - #endif /* UI_H_INCLUDED */ -- 1.6.6.rc0.285.g73651 >From 69b68819c3c4a183a0f44046facdb989abd850ed Mon Sep 17 00:00:00 2001 From: Jim Meyering <[email protected]> Date: Fri, 27 Nov 2009 12:30:21 +0100 Subject: [PATCH 2/2] tests: exercise new align-check command * tests/t9030-align-check.sh: New file. * tests/Makefile.am (TESTS): Add it. --- tests/Makefile.am | 3 +- tests/t9030-align-check.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletions(-) create mode 100644 tests/t9030-align-check.sh diff --git a/tests/Makefile.am b/tests/Makefile.am index f47a6e2..b6d8ca2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -30,7 +30,8 @@ TESTS = \ t7000-scripting.sh \ t8000-loop.sh \ t9010-big-sector.sh \ - t9020-alignment.sh + t9020-alignment.sh \ + t9030-align-check.sh EXTRA_DIST = \ $(TESTS) test-lib.sh t-lib.sh lvm-utils.sh t-local.sh t-lvm.sh diff --git a/tests/t9030-align-check.sh b/tests/t9030-align-check.sh new file mode 100644 index 0000000..12c6c77 --- /dev/null +++ b/tests/t9030-align-check.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# exercise the new align-check command + +# Copyright (C) 2009 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 <http://www.gnu.org/licenses/>. + +if test "$VERBOSE" = yes; then + set -x + parted --version +fi + +: ${srcdir=.} +. $srcdir/t-lib.sh + +require_root_ +require_scsi_debug_module_ + +# check for scsi_debug module +modprobe -n scsi_debug || + skip_test_ "you lack the scsi_debug kernel module" + +grep '^#define USE_BLKID 1' "$CONFIG_HEADER" > /dev/null || + skip_test_ 'this system lacks a new-enough libblkid' + +# create memory-backed device +scsi_debug_setup_ dev_size_mb=550 physblk_exp=3 lowest_aligned=7 > dev-name || + skip_test_ 'failed to create scsi_debug device' +scsi_dev=$(cat dev-name) +p1=${scsi_dev}1 + +fail=0 + +parted -s $scsi_dev mklabel gpt || fail=1 + +i=60 +while :; do + parted -s $scsi_dev mkpart p1 ext2 ${i}s 80000s || fail=1 + wait_for_dev_to_appear_ $p1 || fail=1 + parted -s $scsi_dev align-check min 1 > out 2>&1 + result=$? + + test $(expr $i % 8) = 7 && exp_result=0 || exp_result=1 + test $result = $exp_result || fail=1 + compare out /dev/null || fail=1 + + parted -s $scsi_dev rm 1 + i=$(expr $i + 1) + test $i = 70 && break +done + +Exit $fail -- 1.6.6.rc0.285.g73651 _______________________________________________ parted-devel mailing list [email protected] http://lists.alioth.debian.org/mailman/listinfo/parted-devel

