From: Karel Zak Date: Fri, 12 Feb 2010 20:43:03 +0000 (+0100) Subject: fdisk: use more elegant way to count and check alignment X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45ccee537ab3fc96b6e6125752efce29f13c9cae;p=util-linux fdisk: use more elegant way to count and check alignment Signed-off-by: Karel Zak --- diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index c1868c01..affea090 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -215,7 +215,6 @@ unsigned long long sector_offset = 1, extended_offset = 0, sectors; unsigned int heads, cylinders, - phy_sector_size = DEFAULT_SECTOR_SIZE, sector_size = DEFAULT_SECTOR_SIZE, sector_factor = 1, user_set_sector_size = 0, @@ -226,6 +225,7 @@ unsigned long long total_number_of_sectors; /* (!) 512-byte sectors */ unsigned long grain = DEFAULT_SECTOR_SIZE, io_size = DEFAULT_SECTOR_SIZE, min_io_size = DEFAULT_SECTOR_SIZE, + phy_sector_size = DEFAULT_SECTOR_SIZE, alignment_offset; int has_topology; @@ -647,12 +647,10 @@ test_c(char **m, char *mesg) { static int lba_is_aligned(unsigned long long lba) { - unsigned long long bytes, phy_sectors; + unsigned int granularity = max(phy_sector_size, min_io_size); + unsigned long long offset = (lba << 9) & (granularity - 1); - bytes = lba * sector_size; - phy_sectors = bytes / phy_sector_size; - - return (alignment_offset + (phy_sectors * phy_sector_size) == bytes); + return !((granularity + alignment_offset - offset) & (granularity - 1)); } #define ALIGN_UP 1 @@ -662,41 +660,44 @@ lba_is_aligned(unsigned long long lba) static unsigned long long align_lba(unsigned long long lba, int direction) { - unsigned long long sects_in_phy, res; - - sects_in_phy = grain / sector_size; - - if (lba == sector_offset) - res = lba; /* the offset should be aligned */ + unsigned long long res; - else if (lba < sects_in_phy) - res = sects_in_phy; /* align to the first physical sector */ + if (lba_is_aligned(lba)) + res = lba; + else { + unsigned long long sects_in_phy = grain / sector_size; - else if (lba % sects_in_phy == 0) - res = lba; /* already aligned to the grain */ + if (lba < sector_offset) + res = sector_offset; - else if (direction == ALIGN_UP) - res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy; + 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 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; + else /* ALIGN_NEAREST */ + res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy; - if (alignment_offset && res > alignment_offset / sector_size) - /* - * apply alignment_offset - * - * On disk with alignment compensation physical blocks start - * at LBA < 0 (usually LBA -1). It means we have to move LBA - * according the offset to be on the physical boundary. - */ - res -= (phy_sector_size - alignment_offset) / sector_size; + if (alignment_offset && !lba_is_aligned(res) && + res > alignment_offset / 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(phy_sector_size, min_io_size) - + alignment_offset) / sector_size; + } + } /*** - fprintf(stderr, "LBA %llu --align-(%s)--> %llu (%s)\n", + fprintf(stderr, "LBA %llu (%s) --align-(%s)--> %llu (%s)\n", lba, + lba_is_aligned(lba) ? "OK" : "FALSE", direction == ALIGN_UP ? "UP " : direction == ALIGN_DOWN ? "DOWN " : "NEAREST", res, @@ -1861,7 +1862,7 @@ list_disk_geometry(void) { str_units(PLURAL), units_per_sector, sector_size, units_per_sector * sector_size); - printf(_("Sector size (logical/physical): %u bytes / %u bytes\n"), + printf(_("Sector size (logical/physical): %u bytes / %lu bytes\n"), sector_size, phy_sector_size); printf(_("I/O size (minimum/optimal): %lu bytes / %lu bytes\n"), min_io_size, io_size);