From: Karel Zak Date: Mon, 3 Dec 2012 14:32:16 +0000 (+0100) Subject: fdisk: remove global variable sector_offset X-Git-Tag: v2.23-rc1~463 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf3808e468dd0a16506941cde318c8e813a2996e;p=thirdparty%2Futil-linux.git fdisk: remove global variable sector_offset - add cxt->first_lba as replacement to sector_offset - add label->reset_alignment() to overwrite the default alignment setting - add fdisk_reset_alignment() to setup grain, first LBA offset, etc. Signed-off-by: Karel Zak --- diff --git a/fdisks/fdisk.c b/fdisks/fdisk.c index d9e4f62d06..6ceb7620d4 100644 --- a/fdisks/fdisk.c +++ b/fdisks/fdisk.c @@ -62,7 +62,6 @@ int MBRbuffer_changed; #define sector(s) ((s) & 0x3f) #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2)) -#define fdisk_is_disklabel(c, x) fdisk_dev_is_disklabel(c, FDISK_DISKLABEL_ ## x) /* menu list description */ @@ -133,7 +132,6 @@ int nowarn = 0, /* no warnings for fdisk -l/-s */ partitions = 4; /* maximum partition + 1 */ unsigned int user_cylinders, user_heads, user_sectors; -sector_t sector_offset = 1; unsigned int units_per_sector = 1, display_in_cyl_units = 0; static void __attribute__ ((__noreturn__)) usage(FILE *out) @@ -322,8 +320,8 @@ sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction) else { sector_t sects_in_phy = cxt->grain / cxt->sector_size; - if (lba < sector_offset) - res = sector_offset; + 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; @@ -428,56 +426,6 @@ void warn_alignment(struct fdisk_context *cxt) } -/* - * Sets LBA of the first partition - */ -void -update_sector_offset(struct fdisk_context *cxt) -{ - cxt->grain = cxt->io_size; - - if (dos_compatible_flag) - sector_offset = cxt->geom.sectors; /* usually 63 sectors */ - else { - /* - * Align the begin of partitions to: - * - * a) topology - * a2) alignment offset - * a1) or physical sector (minimal_io_size, aka "grain") - * - * b) or default to 1MiB (2048 sectrors, Windows Vista default) - * - * c) or for very small devices use 1 phy.sector - */ - sector_t x = 0; - - if (fdisk_dev_has_topology(cxt)) { - if (cxt->alignment_offset) - x = cxt->alignment_offset; - else if (cxt->io_size > 2048 * 512) - x = cxt->io_size; - } - /* default to 1MiB */ - if (!x) - x = 2048 * 512; - - sector_offset = x / cxt->sector_size; - - /* don't use huge offset on small devices */ - if (cxt->total_sectors <= sector_offset * 4) - sector_offset = cxt->phy_sector_size / cxt->sector_size; - - /* use 1MiB grain always when possible */ - if (cxt->grain < 2048 * 512) - cxt->grain = 2048 * 512; - - /* don't use huge grain on small devices */ - if (cxt->total_sectors <= (cxt->grain * 4 / cxt->sector_size)) - cxt->grain = cxt->phy_sector_size; - } -} - static int is_partition_table_changed(void) { int i; @@ -825,7 +773,7 @@ toggle_dos_compatibility_flag(struct fdisk_context *cxt) { else printf(_("DOS Compatibility flag is not set\n")); - update_sector_offset(cxt); + fdisk_reset_alignment(cxt); } static void delete_partition(struct fdisk_context *cxt, int partnum) @@ -1465,9 +1413,9 @@ expert_command_prompt(struct fdisk_context *cxt) move_begin(cxt, get_partition(cxt, 0, partitions)); break; case 'c': - user_cylinders = cxt->geom.cylinders = - read_int(cxt, 1, cxt->geom.cylinders, 1048576, 0, + user_cylinders = read_int(cxt, 1, cxt->geom.cylinders, 1048576, 0, _("Number of cylinders")); + fdisk_context_set_user_geometry(cxt, user_cylinders, user_heads, user_sectors); if (fdisk_is_disklabel(cxt, SUN)) sun_set_ncyl(cxt, cxt->geom.cylinders); break; @@ -1491,8 +1439,9 @@ expert_command_prompt(struct fdisk_context *cxt) fdisk_create_disklabel(cxt, "sgi"); break; case 'h': - user_heads = cxt->geom.heads = read_int(cxt, 1, cxt->geom.heads, 256, 0, + user_heads = read_int(cxt, 1, cxt->geom.heads, 256, 0, _("Number of heads")); + fdisk_context_set_user_geometry(cxt, user_cylinders, user_heads, user_sectors); update_units(cxt); break; case 'i': @@ -1516,13 +1465,13 @@ expert_command_prompt(struct fdisk_context *cxt) case 'r': return; case 's': - user_sectors = cxt->geom.sectors = read_int(cxt, 1, cxt->geom.sectors, 63, 0, + user_sectors = read_int(cxt, 1, cxt->geom.sectors, 63, 0, _("Number of sectors")); if (dos_compatible_flag) fprintf(stderr, _("Warning: setting " "sector offset for DOS " "compatibility\n")); - update_sector_offset(cxt); + fdisk_context_set_user_geometry(cxt, user_cylinders, user_heads, user_sectors); update_units(cxt); break; case 'v': @@ -1777,7 +1726,6 @@ int main(int argc, char **argv) if (sector_size != 512 && sector_size != 1024 && sector_size != 2048 && sector_size != 4096) usage(stderr); - sector_offset = 2; break; case 'C': user_cylinders = strtou32_or_err(optarg, _("invalid cylinders argument")); diff --git a/fdisks/fdisk.h b/fdisks/fdisk.h index 39aafe63c0..4433eaef96 100644 --- a/fdisks/fdisk.h +++ b/fdisks/fdisk.h @@ -158,7 +158,9 @@ struct fdisk_context { enum fdisk_labeltype disklabel; /* current disklabel */ + /* alignment */ unsigned long grain; /* alignment unit */ + sector_t first_lba; /* recommended begin of the first partition */ /* geometry */ sector_t total_sectors; /* in logical sectors */ @@ -168,6 +170,8 @@ struct fdisk_context { const struct fdisk_label *label; }; +#define fdisk_is_disklabel(c, x) fdisk_dev_is_disklabel(c, FDISK_DISKLABEL_ ## x) + /* * Label specific operations */ @@ -194,6 +198,8 @@ struct fdisk_label { struct fdisk_parttype *(*part_get_type)(struct fdisk_context *cxt, int partnum); /* set partition type */ int (*part_set_type)(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t); + /* refresh alignment setting */ + int (*reset_alignment)(struct fdisk_context *cxt); }; /* @@ -223,6 +229,7 @@ extern int fdisk_add_partition(struct fdisk_context *cxt, int partnum, struct fd extern int fdisk_write_disklabel(struct fdisk_context *cxt); extern int fdisk_verify_disklabel(struct fdisk_context *cxt); extern int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name); +extern int fdisk_reset_alignment(struct fdisk_context *cxt); extern struct fdisk_parttype *fdisk_get_partition_type(struct fdisk_context *cxt, int partnum); extern int fdisk_set_partition_type(struct fdisk_context *cxt, int partnum, struct fdisk_parttype *t); @@ -237,6 +244,9 @@ extern struct fdisk_parttype *fdisk_parse_parttype(struct fdisk_context *cxt, co extern struct fdisk_parttype *fdisk_new_unknown_parttype(unsigned int type, const char *typestr); extern void fdisk_free_parttype(struct fdisk_parttype *type); +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; @@ -276,7 +286,6 @@ extern unsigned int read_int_with_suffix(struct fdisk_context *cxt, unsigned int base, char *mesg, int *is_suffix_used); extern sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction); extern int get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt); -extern void update_sector_offset(struct fdisk_context *cxt); #define PLURAL 0 #define SINGULAR 1 diff --git a/fdisks/fdiskdoslabel.c b/fdisks/fdiskdoslabel.c index bc8e550221..b310acf895 100644 --- a/fdisks/fdiskdoslabel.c +++ b/fdisks/fdiskdoslabel.c @@ -26,7 +26,7 @@ static struct fdisk_parttype dos_parttypes[] = { s |= (sector >> 2) & 0xc0; \ } -#define alignment_required (cxt->grain != cxt->sector_size) +#define alignment_required(_x) ((_x)->grain != (_x)->sector_size) struct pte ptes[MAXIMUM_PARTS]; sector_t extended_offset; @@ -367,8 +367,24 @@ static void get_partition_table_geometry(struct fdisk_context *cxt, *ph = hh; *ps = ss; } + + DBG(CONTEXT, dbgprint("DOS PT geometry: heads=%u, sectors=%u", *ph, *ps)); } +static int dos_reset_alignment(struct fdisk_context *cxt) +{ + /* overwrite necessary stuff by DOS deprecated stuff */ + if (dos_compatible_flag) { + if (cxt->geom.sectors) + cxt->first_lba = cxt->geom.sectors; /* usually 63 */ + + cxt->grain = cxt->sector_size; /* usually 512 */ + } + /* units_per_sector has impact to deprecated DOS stuff */ + update_units(cxt); + + return 0; +} static int dos_probe_label(struct fdisk_context *cxt) { @@ -459,7 +475,8 @@ static void set_partition(struct fdisk_context *cxt, ptes[i].changed = 1; } -static sector_t get_unused_start(int part_n, sector_t start, +static sector_t get_unused_start(struct fdisk_context *cxt, + int part_n, sector_t start, sector_t first[], sector_t last[]) { int i; @@ -468,8 +485,8 @@ static sector_t get_unused_start(int part_n, sector_t start, sector_t lastplusoff; if (start == ptes[i].offset) - start += sector_offset; - lastplusoff = last[i] + ((part_n < 4) ? 0 : sector_offset); + start += cxt->first_lba; + lastplusoff = last[i] + ((part_n < 4) ? 0 : cxt->first_lba); if (start >= first[i] && start <= lastplusoff) start = lastplusoff + 1; } @@ -510,7 +527,7 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype } fill_bounds(first, last); if (n < 4) { - start = sector_offset; + start = cxt->first_lba; if (display_in_cyl_units || !cxt->total_sectors) limit = cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders - 1; else @@ -525,7 +542,7 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype get_nr_sects(q) - 1; } } else { - start = extended_offset + sector_offset; + start = extended_offset + cxt->first_lba; limit = get_start_sect(q) + get_nr_sects(q) - 1; } if (display_in_cyl_units) @@ -537,12 +554,12 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype sector_t dflt, aligned; temp = start; - dflt = start = get_unused_start(n, start, first, last); + dflt = start = get_unused_start(cxt, n, start, first, last); /* the default sector should be aligned and unused */ do { aligned = align_lba_in_range(cxt, dflt, dflt, limit); - dflt = get_unused_start(n, aligned, first, last); + dflt = get_unused_start(cxt, n, aligned, first, last); } while (dflt != aligned && dflt > aligned && dflt < limit); if (dflt >= limit) @@ -569,10 +586,10 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype if (n > 4) { /* NOT for fifth partition */ struct pte *pe = &ptes[n]; - pe->offset = start - sector_offset; + pe->offset = start - cxt->first_lba; if (pe->offset == extended_offset) { /* must be corrected */ pe->offset++; - if (sector_offset == 1) + if (cxt->first_lba == 1) start++; } } @@ -609,7 +626,7 @@ static int add_partition(struct fdisk_context *cxt, int n, struct fdisk_parttype stop = limit; } - if (is_suffix_used && alignment_required) { + if (is_suffix_used && alignment_required(cxt)) { /* the last sector has not been exactly requested (but * defined by +size{K,M,G} convention), so be smart * and align the end of the partition. The next @@ -899,4 +916,5 @@ const struct fdisk_label dos_label = .part_delete = dos_delete_partition, .part_get_type = dos_get_parttype, .part_set_type = dos_set_parttype, + .reset_alignment = dos_reset_alignment, }; diff --git a/fdisks/fdiskdoslabel.h b/fdisks/fdiskdoslabel.h index 3b6d64478d..60190ed5b5 100644 --- a/fdisks/fdiskdoslabel.h +++ b/fdisks/fdiskdoslabel.h @@ -24,7 +24,7 @@ extern int dos_compatible_flag; (n) * sizeof(struct partition))) extern int ext_index; /* the prime extended partition */ -extern sector_t extended_offset, sector_offset; +extern sector_t extended_offset; /* A valid partition table sector ends in 0x55 0xaa */ static inline unsigned int part_table_flag(unsigned char *b) diff --git a/fdisks/utils.c b/fdisks/utils.c index da48392ed7..311304351d 100644 --- a/fdisks/utils.c +++ b/fdisks/utils.c @@ -198,7 +198,7 @@ int fdisk_context_force_sector_size(struct fdisk_context *cxt, sector_t s) cxt->phy_sector_size = cxt->sector_size = s; cxt->min_io_size = cxt->io_size = s; - update_sector_offset(cxt); + fdisk_reset_alignment(cxt); return 0; } @@ -236,7 +236,7 @@ int fdisk_context_set_user_geometry(struct fdisk_context *cxt, else recount_geometry(cxt); - update_sector_offset(cxt); + fdisk_reset_alignment(cxt); return 0; } @@ -316,6 +316,7 @@ static int __discover_topology(struct fdisk_context *cxt) return 0; } + /** * fdisk_zeroize_firstsector: * @cxt: fdisk context @@ -368,6 +369,112 @@ int fdisk_dev_has_topology(struct fdisk_context *cxt) return 0; } +/* + * The LBA of the first partition is based on the device geometry and topology. + * This offset is generic (and recommended) for all labels. + * + * Returns: 0 on error or number of logical sectors. + */ +sector_t fdisk_topology_get_first_lba(struct fdisk_context *cxt) +{ + sector_t x = 0, res; + + if (!cxt) + return 0; + + if (!cxt->io_size) + __discover_topology(cxt); + + /* + * Align the begin of partitions to: + * + * a) topology + * a2) alignment offset + * a1) or physical sector (minimal_io_size, aka "grain") + * + * b) or default to 1MiB (2048 sectrors, Windows Vista default) + * + * c) or for very small devices use 1 phy.sector + */ + if (fdisk_dev_has_topology(cxt)) { + if (cxt->alignment_offset) + x = cxt->alignment_offset; + else if (cxt->io_size > 2048 * 512) + x = cxt->io_size; + } + /* default to 1MiB */ + if (!x) + x = 2048 * 512; + + res = x / cxt->sector_size; + + /* don't use huge offset on small devices */ + if (cxt->total_sectors <= res * 4) + res = cxt->phy_sector_size / cxt->sector_size; + + return res; +} + +/* + * The LBA of the first partition is based on the device geometry and topology. + * This offset is generic generic (and recommended) for all labels. + * + * Returns: 0 on error or number of bytes. + */ +unsigned long fdisk_topology_get_grain(struct fdisk_context *cxt) +{ + unsigned long res; + + if (!cxt) + return 0; + + if (!cxt->io_size) + __discover_topology(cxt); + + res = cxt->io_size; + + /* use 1MiB grain always when possible */ + if (res < 2048 * 512) + res = 2048 * 512; + + /* don't use huge grain on small devices */ + if (cxt->total_sectors <= (res * 4 / cxt->sector_size)) + res = cxt->phy_sector_size; + + return res; +} + +/** + * fdisk_reset_alignment: + * @cxt: fdisk context + * + * Resets alignment setting to the default or label specific values. + * + * Returns: 0 on success, < 0 in case of error. + */ +int fdisk_reset_alignment(struct fdisk_context *cxt) +{ + int rc = 0; + + if (!cxt) + return -EINVAL; + + /* default */ + cxt->grain = fdisk_topology_get_grain(cxt); + cxt->first_lba = fdisk_topology_get_first_lba(cxt); + + /* overwrite default by label stuff */ + if (cxt->label && cxt->label->reset_alignment) + rc = cxt->label->reset_alignment(cxt); + + DBG(LABEL, dbgprint("%s alignment reseted to: " + "first LBA=%ju, grain=%lu [rc=%d]", + cxt->label ? cxt->label->name : NULL, + (uintmax_t) cxt->first_lba, + cxt->grain, rc)); + return rc; +} + /** * fdisk_dev_has_disklabel: * @cxt: fdisk context @@ -432,6 +539,8 @@ int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name) if (!cxt->label->create) return -ENOSYS; + fdisk_reset_alignment(cxt); + return cxt->label->create(cxt); } @@ -505,7 +614,7 @@ struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int rea * to the context */ __probe_labels(cxt); - update_sector_offset(cxt); + fdisk_reset_alignment(cxt); DBG(CONTEXT, dbgprint("context %p initialized for %s [%s]", cxt, fname,