]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: add alignment code
authorKarel Zak <kzak@redhat.com>
Wed, 5 Dec 2012 13:32:20 +0000 (14:32 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 11 Mar 2013 10:20:40 +0000 (11:20 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
fdisks/fdisk.c
fdisks/fdisk.h
fdisks/fdiskdoslabel.c
fdisks/gpt.c
libfdisk/src/Makemodule.am
libfdisk/src/alignment.c [new file with mode: 0644]
libfdisk/src/fdiskP.h

index dd06b9b229fba5bbbafec4dd6c5f179f1de4255c..f34617f08e25719a48744e70b84edefb5c3314ff 100644 (file)
@@ -288,86 +288,6 @@ test_c(char **m, char *mesg) {
        return val;
 }
 
-static int
-lba_is_aligned(struct fdisk_context *cxt, sector_t lba)
-{
-       unsigned int granularity = max(cxt->phy_sector_size, cxt->min_io_size);
-       unsigned long long offset;
-
-       if (cxt->grain > granularity)
-               granularity = cxt->grain;
-       offset = (lba * cxt->sector_size) & (granularity - 1);
-
-       return !((granularity + cxt->alignment_offset - offset) & (granularity - 1));
-}
-
-static int
-lba_is_phy_aligned(struct fdisk_context *cxt, unsigned long long lba)
-{
-       unsigned int granularity = max(cxt->phy_sector_size, cxt->min_io_size);
-       unsigned long long offset = (lba * cxt->sector_size) & (granularity - 1);
-
-       return !((granularity + cxt->alignment_offset - offset) & (granularity - 1));
-}
-
-sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction)
-{
-       sector_t res;
-
-       if (lba_is_aligned(cxt, lba))
-               res = lba;
-       else {
-               sector_t sects_in_phy = cxt->grain / cxt->sector_size;
-
-               if (lba < cxt->first_lba)
-                       res = cxt->first_lba;
-
-               else if (direction == ALIGN_UP)
-                       res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy;
-
-               else if (direction == ALIGN_DOWN)
-                       res = (lba / sects_in_phy) * sects_in_phy;
-
-               else /* ALIGN_NEAREST */
-                       res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy;
-
-               if (cxt->alignment_offset && !lba_is_aligned(cxt, res) &&
-                   res > cxt->alignment_offset / cxt->sector_size) {
-                       /*
-                        * apply alignment_offset
-                        *
-                        * On disk with alignment compensation physical blocks starts
-                        * at LBA < 0 (usually LBA -1). It means we have to move LBA
-                        * according the offset to be on the physical boundary.
-                        */
-                       /* fprintf(stderr, "LBA: %llu apply alignment_offset\n", res); */
-                       res -= (max(cxt->phy_sector_size, cxt->min_io_size) -
-                                       cxt->alignment_offset) / cxt->sector_size;
-
-                       if (direction == ALIGN_UP && res < lba)
-                               res += sects_in_phy;
-               }
-       }
-
-       return res;
-}
-
-
-sector_t align_lba_in_range(struct fdisk_context *cxt,
-                           sector_t lba, sector_t start, sector_t stop)
-{
-       start = align_lba(cxt, start, ALIGN_UP);
-       stop = align_lba(cxt, stop, ALIGN_DOWN);
-
-       lba = align_lba(cxt, lba, ALIGN_NEAREST);
-
-       if (lba < start)
-               return start;
-       else if (lba > stop)
-               return stop;
-       return lba;
-}
-
 int warn_geometry(struct fdisk_context *cxt)
 {
        char *m = NULL;
@@ -862,13 +782,6 @@ void check_consistency(struct fdisk_context *cxt, struct partition *p, int parti
        }
 }
 
-void check_alignment(struct fdisk_context *cxt, sector_t lba, int partition)
-{
-       if (!lba_is_phy_aligned(cxt, lba))
-               printf(_("Partition %i does not start on physical sector boundary.\n"),
-                       partition + 1);
-}
-
 static void
 list_disk_geometry(struct fdisk_context *cxt) {
        unsigned long long bytes = cxt->total_sectors * cxt->sector_size;
@@ -1111,7 +1024,7 @@ static void list_table(struct fdisk_context *cxt, int xtra)
 /* type id */          p->sys_ind,
 /* type name */                type ? type->name : _("Unknown"));
                        check_consistency(cxt, p, i);
-                       check_alignment(cxt, get_partition_start(pe), i);
+                       fdisk_warn_alignment(cxt, get_partition_start(pe), i);
                }
        }
 
@@ -1146,7 +1059,7 @@ x_list_table(struct fdisk_context *cxt, int extend) {
                                (unsigned long) get_nr_sects(p), p->sys_ind);
                        if (p->sys_ind) {
                                check_consistency(cxt, p, i);
-                               check_alignment(cxt, get_partition_start(pe), i);
+                               fdisk_warn_alignment(cxt, get_partition_start(pe), i);
                        }
                }
        }
index 82313c91e83feea231da0e8b27f247d6ddd47219..4ea9b3b9c25643bc8d05a958097dbdfc265986bf 100644 (file)
@@ -26,9 +26,6 @@
 #define LINUX_LVM       0x8e
 #define LINUX_RAID      0xfd
 
-#define ALIGN_UP       1
-#define ALIGN_DOWN     2
-#define ALIGN_NEAREST  3
 
 #define LINE_LENGTH    800
 
@@ -95,16 +92,12 @@ extern struct fdisk_parttype *fdisk_get_partition_type(struct fdisk_context *cxt
 extern int fdisk_set_partition_type(struct fdisk_context *cxt, int partnum,
                             struct fdisk_parttype *t);
 
-extern sector_t fdisk_topology_get_first_lba(struct fdisk_context *cxt);
-extern unsigned long fdisk_topology_get_grain(struct fdisk_context *cxt);
-
 /* prototypes for fdisk.c */
 extern char *line_ptr;
 extern int partitions;
 extern unsigned int display_in_cyl_units, units_per_sector;
 
 extern void check_consistency(struct fdisk_context *cxt, struct partition *p, int partition);
-extern void check_alignment(struct fdisk_context *cxt, sector_t lba, int partition);
 extern void check(struct fdisk_context *cxt, int n, unsigned int h, unsigned int s, unsigned int c, unsigned int start);
 
 extern void fatal(struct fdisk_context *cxt, enum failure why);
@@ -132,8 +125,6 @@ extern void warn_limits(struct fdisk_context *cxt);
 extern unsigned int read_int_with_suffix(struct fdisk_context *cxt,
                                         unsigned int low, unsigned int dflt, unsigned int high,
                                  unsigned int base, char *mesg, int *is_suffix_used);
-extern sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction);
-extern sector_t align_lba_in_range(struct fdisk_context *cxt, sector_t lba, sector_t start, sector_t stop);
 extern int get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt);
 
 #define PLURAL 0
index ab940a010bb39c358b4151582566ddd8a1fd7e18..45343c8383fdc9dea70e5c2b4a7a5a0869257869 100644 (file)
@@ -590,7 +590,7 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype
 
                /* the default sector should be aligned and unused */
                do {
-                       aligned = align_lba_in_range(cxt, dflt, dflt, limit);
+                       aligned = fdisk_align_lba_in_range(cxt, dflt, dflt, limit);
                        dflt = get_unused_start(cxt, n, aligned, first, last);
                } while (dflt != aligned && dflt > aligned && dflt < limit);
 
@@ -664,7 +664,7 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype
                         * and align the end of the partition. The next
                         * partition will start at phy.block boundary.
                         */
-                       stop = align_lba_in_range(cxt, stop, start, limit) - 1;
+                       stop = fdisk_align_lba_in_range(cxt, stop, start, limit) - 1;
                        if (stop > limit)
                                stop = limit;
                }
@@ -721,7 +721,7 @@ static int dos_verify_disklabel(struct fdisk_context *cxt)
                p = pe->part_table;
                if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
                        check_consistency(cxt, p, i);
-                       check_alignment(cxt, get_partition_start(pe), i);
+                       fdisk_warn_alignment(cxt, get_partition_start(pe), i);
                        if (get_partition_start(pe) < first[i])
                                printf(_("Warning: bad start-of-data in "
                                         "partition %d\n"), i + 1);
index 87efd2550d6b5f3c44ee912386bf6c324238ceee..0784d639a54c234d456586b8a3028791d6f19752 100644 (file)
@@ -1144,7 +1144,7 @@ void gpt_list_table(struct fdisk_context *cxt,
                       t->name,
                       name);
 
-               check_alignment(cxt, start, i);
+               fdisk_warn_alignment(cxt, start, i);
 
                free(name);
                free(sizestr);
@@ -1516,7 +1516,7 @@ static int gpt_add_partition(struct fdisk_context *cxt, int partnum,
        dflt_l = find_last_free(pheader, ents, dflt_f);
 
        /* align the default in range <dflt_f,dflt_l>*/
-       dflt_f = align_lba_in_range(cxt, dflt_f, dflt_f, dflt_l);
+       dflt_f = fdisk_align_lba_in_range(cxt, dflt_f, dflt_f, dflt_l);
 
        if (t && t->typestr)
                string_to_uuid(t->typestr, &uuid);
@@ -1550,7 +1550,7 @@ static int gpt_add_partition(struct fdisk_context *cxt, int partnum,
                                        &is_suffix_used);
 
                if (is_suffix_used)
-                       user_l = align_lba_in_range(cxt, user_l, user_f, dflt_l) - 1;
+                       user_l = fdisk_align_lba_in_range(cxt, user_l, user_f, dflt_l) - 1;
 
                if (user_l > user_f && user_l <= disk_l)
                        break;
index 66cbe872c9eb7d82179cca07f1125be6a0060161..3159432f5182042005cfa05ef9641357bef972ce 100644 (file)
@@ -9,6 +9,7 @@ libfdisk_la_SOURCES = \
        libfdisk/src/libfdisk.h \
        \
        libfdisk/src/init.c \
+       libfdisk/src/alignment.c \
        libfdisk/src/parttype.c
 
 
diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c
new file mode 100644 (file)
index 0000000..b0d38ae
--- /dev/null
@@ -0,0 +1,101 @@
+
+#include "fdiskP.h"
+
+/*
+ * Alignment according to logical granulity (usually 1MiB)
+ */
+static int lba_is_aligned(struct fdisk_context *cxt, sector_t lba)
+{
+       unsigned long granularity = max(cxt->phy_sector_size, cxt->min_io_size);
+       uintmax_t offset;
+
+       if (cxt->grain > granularity)
+               granularity = cxt->grain;
+       offset = (lba * cxt->sector_size) & (granularity - 1);
+
+       return !((granularity + cxt->alignment_offset - offset) & (granularity - 1));
+}
+
+/*
+ * Alignment according to physical device topology (usually minimal i/o size)
+ */
+static int lba_is_phy_aligned(struct fdisk_context *cxt, sector_t lba)
+{
+       unsigned long granularity = max(cxt->phy_sector_size, cxt->min_io_size);
+       uintmax_t offset = (lba * cxt->sector_size) & (granularity - 1);
+
+       return !((granularity + cxt->alignment_offset - offset) & (granularity - 1));
+}
+
+/*
+ * Align @lba in @direction FDISK_ALIGN_{UP,DOWN,NEAREST}
+ */
+sector_t fdisk_align_lba(struct fdisk_context *cxt, sector_t lba, int direction)
+{
+       sector_t res;
+
+       if (lba_is_aligned(cxt, lba))
+               res = lba;
+       else {
+               sector_t sects_in_phy = cxt->grain / cxt->sector_size;
+
+               if (lba < cxt->first_lba)
+                       res = cxt->first_lba;
+
+               else if (direction == FDISK_ALIGN_UP)
+                       res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy;
+
+               else if (direction == FDISK_ALIGN_DOWN)
+                       res = (lba / sects_in_phy) * sects_in_phy;
+
+               else /* FDISK_ALIGN_NEAREST */
+                       res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy;
+
+               if (cxt->alignment_offset && !lba_is_aligned(cxt, res) &&
+                   res > cxt->alignment_offset / cxt->sector_size) {
+                       /*
+                        * apply alignment_offset
+                        *
+                        * On disk with alignment compensation physical blocks starts
+                        * at LBA < 0 (usually LBA -1). It means we have to move LBA
+                        * according the offset to be on the physical boundary.
+                        */
+                       /* fprintf(stderr, "LBA: %llu apply alignment_offset\n", res); */
+                       res -= (max(cxt->phy_sector_size, cxt->min_io_size) -
+                                       cxt->alignment_offset) / cxt->sector_size;
+
+                       if (direction == FDISK_ALIGN_UP && res < lba)
+                               res += sects_in_phy;
+               }
+       }
+
+       return res;
+}
+
+/*
+ * Align @lba, the result has to be between @start and @stop
+ */
+sector_t fdisk_align_lba_in_range(struct fdisk_context *cxt,
+                                 sector_t lba, sector_t start, sector_t stop)
+{
+       start = fdisk_align_lba(cxt, start, FDISK_ALIGN_UP);
+       stop = fdisk_align_lba(cxt, stop, FDISK_ALIGN_DOWN);
+       lba = fdisk_align_lba(cxt, lba, FDISK_ALIGN_NEAREST);
+
+       if (lba < start)
+               return start;
+       else if (lba > stop)
+               return stop;
+       return lba;
+}
+
+/*
+ * Print warning if the partition @lba (start of the @partition) is not
+ * aligned to physical sector boundary.
+ */
+void fdisk_warn_alignment(struct fdisk_context *cxt, sector_t lba, int partition)
+{
+       if (!lba_is_phy_aligned(cxt, lba))
+               printf(_("Partition %i does not start on physical sector boundary.\n"),
+                       partition + 1);
+}
index 82443453aa999f9eb61bb9a0a02d87243934a8b4..9ae258e13df51d88c2eceddf201650d306941144 100644 (file)
@@ -20,6 +20,8 @@
 #include "c.h"
 #include "libfdisk.h"
 
+#include "nls.h"               /* temporary before dialog API will be implamented */
+
 /* features */
 #define CONFIG_LIBFDISK_ASSERT
 #define CONFIG_LIBFDISK_DEBUG
@@ -189,4 +191,20 @@ struct fdisk_label {
        int (*reset_alignment)(struct fdisk_context *cxt);
 };
 
+/* alignment.c */
+extern sector_t fdisk_topology_get_first_lba(struct fdisk_context *cxt);
+extern unsigned long fdisk_topology_get_grain(struct fdisk_context *cxt);
+
+extern void fdisk_warn_alignment(struct fdisk_context *cxt,
+                                sector_t lba, int partition);
+
+
+#define FDISK_ALIGN_UP         1
+#define FDISK_ALIGN_DOWN       2
+#define FDISK_ALIGN_NEAREST    3
+
+extern sector_t fdisk_align_lba(struct fdisk_context *cxt, sector_t lba, int direction);
+extern sector_t fdisk_align_lba_in_range(struct fdisk_context *cxt, sector_t lba,
+                                        sector_t start, sector_t stop);
+
 #endif /* _LIBFDISK_PRIVATE_H */