diff options
-rw-r--r-- | fdisks/fdisk.c | 50 | ||||
-rw-r--r-- | libfdisk/src/alignment.c | 164 | ||||
-rw-r--r-- | libfdisk/src/context.c | 19 | ||||
-rw-r--r-- | libfdisk/src/fdiskP.h | 11 | ||||
-rw-r--r-- | libfdisk/src/label.c | 9 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.h | 10 |
6 files changed, 182 insertions, 81 deletions
diff --git a/fdisks/fdisk.c b/fdisks/fdisk.c index 96cd71958..12700ee6e 100644 --- a/fdisks/fdisk.c +++ b/fdisks/fdisk.c @@ -58,9 +58,6 @@ char *line_ptr, /* interactive input */ int nowarn = 0; /* no warnings for fdisk -l/-s */ -/* when C/H/S specified on command line */ -static unsigned int user_cylinders, user_heads, user_sectors; - void toggle_units(struct fdisk_context *cxt) { fdisk_context_set_unit(cxt, @@ -796,19 +793,13 @@ static int is_ide_cdrom_or_tape(char *device) } /* Print disk geometry and partition table of a specified device (-l option) */ -static void print_partition_table_from_option(struct fdisk_context *cxt, - char *device, unsigned long sector_size) +static void print_partition_table_from_option( + struct fdisk_context *cxt, + char *device) { if (fdisk_context_assign_device(cxt, device, 1) != 0) /* read-only */ err(EXIT_FAILURE, _("cannot open %s"), device); - if (sector_size) /* passed -b option, override autodiscovery */ - fdisk_override_sector_size(cxt, sector_size); - - if (user_cylinders || user_heads || user_sectors) - fdisk_override_geometry(cxt, user_cylinders, - user_heads, user_sectors); - if (fdisk_dev_has_disklabel(cxt)) list_table(cxt, 0); else @@ -820,8 +811,7 @@ static void print_partition_table_from_option(struct fdisk_context *cxt, * try all things in /proc/partitions that look like a full disk */ static void -print_all_partition_table_from_option(struct fdisk_context *cxt, - unsigned long sector_size) +print_all_partition_table_from_option(struct fdisk_context *cxt) { FILE *procpt; char line[128 + 1], ptname[128 + 1], devname[256]; @@ -843,7 +833,7 @@ print_all_partition_table_from_option(struct fdisk_context *cxt, char *cn = canonicalize_path(devname); if (cn) { if (!is_ide_cdrom_or_tape(cn)) - print_partition_table_from_option(cxt, cn, sector_size); + print_partition_table_from_option(cxt, cn); free(cn); } } @@ -1029,9 +1019,13 @@ int main(int argc, char **argv) if (sector_size != 512 && sector_size != 1024 && sector_size != 2048 && sector_size != 4096) usage(stderr); + fdisk_save_user_sector_size(cxt, sector_size, sector_size); break; case 'C': - user_cylinders = strtou32_or_err(optarg, _("invalid cylinders argument")); + fdisk_save_user_geometry(cxt, + strtou32_or_err(optarg, + _("invalid cylinders argument")), + 0, 0); break; case 'c': if (optarg) { @@ -1050,14 +1044,15 @@ int main(int argc, char **argv) /* use default if no optarg specified */ break; case 'H': - user_heads = strtou32_or_err(optarg, _("invalid heads argument")); - if (user_heads > 256) - user_heads = 0; + fdisk_save_user_geometry(cxt, 0, + strtou32_or_err(optarg, + _("invalid heads argument")), + 0); break; case 'S': - user_sectors = strtou32_or_err(optarg, _("invalid sectors argument")); - if (user_sectors >= 64) - user_sectors = 0; + fdisk_save_user_geometry(cxt, 0, 0, + strtou32_or_err(optarg, + _("invalid sectors argument"))); break; case 'l': optl = 1; @@ -1092,9 +1087,9 @@ int main(int argc, char **argv) if (argc > optind) { int k; for (k = optind; k < argc; k++) - print_partition_table_from_option(cxt, argv[k], sector_size); + print_partition_table_from_option(cxt, argv[k]); } else - print_all_partition_table_from_option(cxt, sector_size); + print_all_partition_table_from_option(cxt); exit(EXIT_SUCCESS); } @@ -1119,13 +1114,6 @@ int main(int argc, char **argv) if (fdisk_context_assign_device(cxt, argv[optind], 0) != 0) err(EXIT_FAILURE, _("cannot open %s"), argv[optind]); - if (sector_size) /* passed -b option, override autodiscovery */ - fdisk_override_sector_size(cxt, sector_size); - - if (user_cylinders || user_heads || user_sectors) - fdisk_override_geometry(cxt, user_cylinders, - user_heads, user_sectors); - print_welcome(); if (!fdisk_dev_has_disklabel(cxt)) { diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c index b4d3ee01d..9e7d33b67 100644 --- a/libfdisk/src/alignment.c +++ b/libfdisk/src/alignment.c @@ -74,6 +74,10 @@ sector_t fdisk_align_lba(struct fdisk_context *cxt, sector_t lba, int direction) } } + if (lba != res) + DBG(TOPOLOGY, dbgprint("LBA %ju -aligned-to-> %ju", + (uintmax_t) lba, + (uintmax_t) res)); return res; } @@ -114,30 +118,6 @@ static unsigned long get_sector_size(int fd) return DEFAULT_SECTOR_SIZE; } -/** - * fdisk_override_sector_size: - * @cxt: fdisk context - * @s: required sector size - * - * Overwrites logical and physical sector size. Note that the default sector - * size is discovered by fdisk_new_context_from_device() from device topology. - * - * Don't use this function, rely on the default behavioer is more safe. - * - * Returns: 0 on success, < 0 on error. - */ -int fdisk_override_sector_size(struct fdisk_context *cxt, sector_t s) -{ - if (!cxt) - return -EINVAL; - - cxt->phy_sector_size = cxt->sector_size = s; - cxt->min_io_size = cxt->io_size = s; - - fdisk_reset_alignment(cxt); - return 0; -} - static void recount_geometry(struct fdisk_context *cxt) { cxt->geom.cylinders = cxt->total_sectors / @@ -151,7 +131,8 @@ static void recount_geometry(struct fdisk_context *cxt) * @heads: user specified heads * @sectors: user specified sectors * - * Overrides autodiscovery and apply user specified geometry. + * Overrides autodiscovery and apply user specified geometry. The function + * fdisk_reset_device_properties() restores the original setting. * * Returns: 0 on success, < 0 on error. */ @@ -173,6 +154,118 @@ int fdisk_override_geometry(struct fdisk_context *cxt, recount_geometry(cxt); fdisk_reset_alignment(cxt); + + DBG(GEOMETRY, dbgprint("override C/H/S: %u/%u/%u", + (unsigned) cxt->geom.cylinders, + (unsigned) cxt->geom.heads, + (unsigned) cxt->geom.sectors)); + + return 0; +} + +int fdisk_save_user_geometry(struct fdisk_context *cxt, + unsigned int cylinders, + unsigned int heads, + unsigned int sectors) +{ + if (!cxt) + return -EINVAL; + + cxt->user_geom.heads = heads > 256 ? 0 : heads; + cxt->user_geom.sectors = sectors >= 64 ? 0 : sectors; + cxt->user_geom.cylinders = cylinders; + + DBG(GEOMETRY, dbgprint("user C/H/S: %u/%u/%u", + cylinders, heads, sectors)); + + return 0; +} + +int fdisk_save_user_sector_size(struct fdisk_context *cxt, + unsigned int phy, + unsigned int log) +{ + if (!cxt) + return -EINVAL; + + DBG(TOPOLOGY, dbgprint("user phy/log sector size: %u/%u", phy, log)); + + cxt->user_pyh_sector = phy; + cxt->user_log_sector = log; + + return 0; +} + +int fdisk_apply_user_device_properties(struct fdisk_context *cxt) +{ + if (!cxt) + return -EINVAL; + + DBG(TOPOLOGY, dbgprint("appling user device properties")); + + if (cxt->user_pyh_sector) + cxt->phy_sector_size = cxt->user_pyh_sector; + if (cxt->user_log_sector) + cxt->sector_size = cxt->min_io_size = + cxt->io_size = cxt->user_log_sector; + + if (cxt->user_geom.heads) + cxt->geom.heads = cxt->user_geom.heads; + if (cxt->user_geom.sectors) + cxt->geom.sectors = cxt->user_geom.sectors; + if (cxt->user_geom.cylinders) + cxt->geom.cylinders = cxt->user_geom.cylinders; + else if (cxt->user_geom.heads || cxt->user_geom.sectors) + recount_geometry(cxt); + + fdisk_reset_alignment(cxt); + + DBG(GEOMETRY, dbgprint("new C/H/S: %u/%u/%u", + (unsigned) cxt->geom.cylinders, + (unsigned) cxt->geom.heads, + (unsigned) cxt->geom.sectors)); + DBG(TOPOLOGY, dbgprint("new log/phy sector size: %u/%u", + (unsigned) cxt->sector_size, + (unsigned) cxt->phy_sector_size)); + + return 0; +} + +void fdisk_zeroize_device_properties(struct fdisk_context *cxt) +{ + assert(cxt); + + cxt->io_size = 0; + cxt->optimal_io_size = 0; + cxt->min_io_size = 0; + cxt->phy_sector_size = 0; + cxt->sector_size = 0; + cxt->alignment_offset = 0; + cxt->grain = 0; + cxt->first_lba = 0; + cxt->total_sectors = 0; + + memset(&cxt->geom, 0, sizeof(struct fdisk_geometry)); +} + +int fdisk_reset_device_properties(struct fdisk_context *cxt) +{ + int rc; + + if (!cxt) + return -EINVAL; + + DBG(TOPOLOGY, dbgprint("*** reseting device properties")); + + fdisk_zeroize_device_properties(cxt); + fdisk_discover_topology(cxt); + fdisk_discover_geometry(cxt); + + rc = fdisk_read_firstsector(cxt); + if (rc) + return rc; + + fdisk_apply_user_device_properties(cxt); return 0; } @@ -187,6 +280,8 @@ int fdisk_discover_geometry(struct fdisk_context *cxt) assert(cxt); assert(cxt->geom.heads == 0); + DBG(GEOMETRY, dbgprint("%s: discovering geometry...", cxt->dev_path)); + /* get number of 512-byte sectors, and convert it the real sectors */ if (!blkdev_get_sectors(cxt->dev_fd, &nsects)) cxt->total_sectors = (nsects / (cxt->sector_size >> 9)); @@ -204,9 +299,10 @@ int fdisk_discover_geometry(struct fdisk_context *cxt) cxt->geom.sectors = s; recount_geometry(cxt); - DBG(GEOMETRY, dbgprint("geometry discovered for %s: C/H/S: %lld/%d/%lld", - cxt->dev_path, cxt->geom.cylinders, - cxt->geom.heads, cxt->geom.sectors)); + DBG(GEOMETRY, dbgprint("result: C/H/S: %u/%u/%u", + (unsigned) cxt->geom.cylinders, + (unsigned) cxt->geom.heads, + (unsigned) cxt->geom.sectors)); return 0; } @@ -218,6 +314,7 @@ int fdisk_discover_topology(struct fdisk_context *cxt) assert(cxt); assert(cxt->sector_size == 0); + DBG(TOPOLOGY, dbgprint("%s: discovering topology...", cxt->dev_path)); #ifdef HAVE_LIBBLKID DBG(TOPOLOGY, dbgprint("initialize libblkid prober")); @@ -251,11 +348,10 @@ int fdisk_discover_topology(struct fdisk_context *cxt) if (!cxt->io_size) cxt->io_size = cxt->sector_size; - DBG(TOPOLOGY, dbgprint("topology discovered for %s:\n" - "\tlogical/physical sector sizes: %ld/%ld\n" - "\tfdisk/minimal/optimal io sizes: %ld/%ld/%ld\n", - cxt->dev_path, cxt->sector_size, cxt->phy_sector_size, - cxt->io_size, cxt->optimal_io_size, cxt->min_io_size)); + DBG(TOPOLOGY, dbgprint("result: log/phy sector size: %ld/%ld", + cxt->sector_size, cxt->phy_sector_size)); + DBG(TOPOLOGY, dbgprint("result: fdisk/min/optimal io: %ld/%ld/%ld", + cxt->io_size, cxt->optimal_io_size, cxt->min_io_size)); return 0; } @@ -364,6 +460,8 @@ int fdisk_reset_alignment(struct fdisk_context *cxt) if (!cxt) return -EINVAL; + DBG(TOPOLOGY, dbgprint("reseting alignment...")); + /* default */ cxt->grain = fdisk_topology_get_grain(cxt); cxt->first_lba = fdisk_topology_get_first_lba(cxt); diff --git a/libfdisk/src/context.c b/libfdisk/src/context.c index 6ede3e468..f2b0f7871 100644 --- a/libfdisk/src/context.c +++ b/libfdisk/src/context.c @@ -106,7 +106,7 @@ static void reset_context(struct fdisk_context *cxt) { size_t i; - DBG(CONTEXT, dbgprint("\n-----\nresetting context %p", cxt)); + DBG(CONTEXT, dbgprint("*** resetting context %p", cxt)); /* reset drives' private data */ for (i = 0; i < cxt->nlabels; i++) @@ -123,17 +123,7 @@ static void reset_context(struct fdisk_context *cxt) cxt->dev_path = NULL; cxt->firstsector = NULL; - cxt->io_size = 0; - cxt->optimal_io_size = 0; - cxt->min_io_size = 0; - cxt->phy_sector_size = 0; - cxt->sector_size = 0; - cxt->alignment_offset = 0; - cxt->grain = 0; - cxt->first_lba = 0; - cxt->total_sectors = 0; - - memset(&cxt->geom, 0, sizeof(struct fdisk_geometry)); + fdisk_zeroize_device_properties(cxt); cxt->label = NULL; } @@ -179,7 +169,10 @@ int fdisk_context_assign_device(struct fdisk_context *cxt, /* detect labels and apply labes specific stuff (e.g geomery) * to the context */ fdisk_probe_labels(cxt); - fdisk_reset_alignment(cxt); + + /* let's apply user geometry *after* label prober + * to make it possible to override in-label setting */ + fdisk_apply_user_device_properties(cxt); DBG(CONTEXT, dbgprint("context %p initialized for %s [%s]", cxt, fname, diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index 167670fcb..9434f3213 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -272,9 +272,14 @@ struct fdisk_context { sector_t first_lba; /* recommended begin of the first partition */ /* geometry */ - sector_t total_sectors; /* in logical sectors */ + sector_t total_sectors; /* in logical sectors */ struct fdisk_geometry geom; + /* user setting to overwrite device default */ + struct fdisk_geometry user_geom; + unsigned long user_pyh_sector; + unsigned long user_log_sector; + struct fdisk_label *label; /* current label, pointer to labels[] */ size_t nlabels; /* number of initialized label drivers */ @@ -314,7 +319,6 @@ extern sector_t fdisk_align_lba_in_range(struct fdisk_context *cxt, sector_t lba sector_t start, sector_t stop); -extern int fdisk_override_sector_size(struct fdisk_context *cxt, sector_t s); extern int fdisk_override_geometry(struct fdisk_context *cxt, unsigned int cylinders, unsigned int heads, unsigned int sectors); @@ -322,6 +326,9 @@ extern int fdisk_override_geometry(struct fdisk_context *cxt, extern int fdisk_discover_geometry(struct fdisk_context *cxt); extern int fdisk_discover_topology(struct fdisk_context *cxt); +extern int fdisk_apply_user_device_properties(struct fdisk_context *cxt); +extern void fdisk_zeroize_device_properties(struct fdisk_context *cxt); + /* utils.c */ extern void fdisk_zeroize_firstsector(struct fdisk_context *cxt); extern int fdisk_read_firstsector(struct fdisk_context *cxt); diff --git a/libfdisk/src/label.c b/libfdisk/src/label.c index d518d876d..cabf3d751 100644 --- a/libfdisk/src/label.c +++ b/libfdisk/src/label.c @@ -182,6 +182,8 @@ int fdisk_delete_partition(struct fdisk_context *cxt, size_t partnum) */ int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name) { + int haslabel = 0; + if (!cxt) return -EINVAL; @@ -193,8 +195,10 @@ int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name) #endif } - if (cxt->label) + if (cxt->label) { fdisk_deinit_label(cxt->label); + haslabel = 1; + } cxt->label = fdisk_context_get_label(cxt, name); if (!cxt->label) @@ -204,7 +208,8 @@ int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name) if (!cxt->label->op->create) return -ENOSYS; - fdisk_reset_alignment(cxt); + if (haslabel) + fdisk_reset_device_properties(cxt); return cxt->label->op->create(cxt); } diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h index fc38ef770..3832af070 100644 --- a/libfdisk/src/libfdisk.h +++ b/libfdisk/src/libfdisk.h @@ -136,6 +136,16 @@ extern int fdisk_partition_toggle_flag(struct fdisk_context *cxt, size_t partnum /* alignment.c */ extern int fdisk_reset_alignment(struct fdisk_context *cxt); +extern int fdisk_reset_device_properties(struct fdisk_context *cxt); + +extern int fdisk_save_user_geometry(struct fdisk_context *cxt, + unsigned int cylinders, + unsigned int heads, + unsigned int sectors); + +extern int fdisk_save_user_sector_size(struct fdisk_context *cxt, + unsigned int phy, + unsigned int log); /* dos.c */ |