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;
}
}
-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;
/* 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);
}
}
(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);
}
}
}
#define LINUX_LVM 0x8e
#define LINUX_RAID 0xfd
-#define ALIGN_UP 1
-#define ALIGN_DOWN 2
-#define ALIGN_NEAREST 3
#define LINE_LENGTH 800
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);
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
/* 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);
* 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;
}
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);
t->name,
name);
- check_alignment(cxt, start, i);
+ fdisk_warn_alignment(cxt, start, i);
free(name);
free(sizestr);
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);
&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;
libfdisk/src/libfdisk.h \
\
libfdisk/src/init.c \
+ libfdisk/src/alignment.c \
libfdisk/src/parttype.c
--- /dev/null
+
+#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);
+}
#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
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 */