Add device geometry to the fdisk API. While it maintains traditional behaviour, the cylinders
are changed to sector_t instead of unsigned int in order to avoid dealing with truncated cylinders.
A new helper is added to compute the amount of cylinders based on the heads and sectors - if a user passed
-H or -S to the program, it must call this function to update the corresponding values.
This patch passes regression tests.
Signed-off-by: Davidlohr Bueso <dave@gnu.org>
partitions = 4; /* maximum partition + 1 */
unsigned int user_cylinders, user_heads, user_sectors;
-unsigned int pt_heads, pt_sectors;
-
-sector_t sector_offset = 1, sectors;
-
-unsigned int heads,
- cylinders,
- units_per_sector = 1,
- display_in_cyl_units = 0;
-
+sector_t sector_offset = 1;
+unsigned int units_per_sector = 1, display_in_cyl_units = 0;
unsigned long grain = DEFAULT_SECTOR_SIZE;
enum labeltype disklabel; /* Current disklabel */
return res;
}
-int warn_geometry(void)
+int warn_geometry(struct fdisk_context *cxt)
{
char *m = NULL;
int prev = 0;
if (disklabel == SGI_LABEL) /* cannot set cylinders etc anyway */
return 0;
- if (!heads)
+ if (!cxt->geom.heads)
prev = test_c(&m, _("heads"));
- if (!sectors)
+ if (!cxt->geom.sectors)
prev = test_c(&m, _("sectors"));
- if (!cylinders)
+ if (!cxt->geom.cylinders)
prev = test_c(&m, _("cylinders"));
if (!m)
return 0;
return 1;
}
-void update_units(void)
+void update_units(struct fdisk_context *cxt)
{
- int cyl_units = heads * sectors;
+ int cyl_units = cxt->geom.heads * cxt->geom.sectors;
if (display_in_cyl_units && cyl_units)
units_per_sector = cyl_units;
}
-static void
-get_partition_table_geometry(struct fdisk_context *cxt) {
+void
+get_partition_table_geometry(struct fdisk_context *cxt, unsigned int *ph, unsigned int *ps) {
unsigned char *bufp = cxt->mbr;
struct partition *p;
int i, h, s, hh, ss;
}
if (!first && !bad) {
- pt_heads = hh;
- pt_sectors = ss;
+ *ph = hh;
+ *ps = ss;
}
}
grain = cxt->io_size;
if (dos_compatible_flag)
- sector_offset = sectors; /* usually 63 sectors */
+ sector_offset = cxt->geom.sectors; /* usually 63 sectors */
else {
/*
* Align the begin of partitions to:
}
}
-void
-get_geometry(struct fdisk_context *cxt, struct geom *g)
-{
- sector_t llcyls;
- unsigned int kern_heads = 0, kern_sectors = 0;
-
- heads = cylinders = sectors = 0;
- pt_heads = pt_sectors = 0;
-
- blkdev_get_geometry(cxt->dev_fd, &kern_heads, &kern_sectors);
- get_partition_table_geometry(cxt);
-
- heads = user_heads ? user_heads :
- pt_heads ? pt_heads :
- kern_heads ? kern_heads : 255;
- sectors = user_sectors ? user_sectors :
- pt_sectors ? pt_sectors :
- kern_sectors ? kern_sectors : 63;
-
- update_sector_offset(cxt);
-
- llcyls = cxt->total_sectors / (heads * sectors);
- cylinders = llcyls;
- if (cylinders != llcyls) /* truncated? */
- cylinders = ~0;
- if (!cylinders)
- cylinders = user_cylinders;
-
- if (g) {
- g->heads = heads;
- g->sectors = sectors;
- g->cylinders = cylinders;
- }
-}
-
/*
* Read MBR. Returns:
* -1: no 0xaa55 flag present (possibly entire disk BSD)
static int get_boot(struct fdisk_context *cxt, int try_only) {
disklabel = ANY_LABEL;
-
- get_geometry(cxt, NULL);
- update_units();
+ update_units(cxt);
if (!check_dos_label(cxt))
if (check_sun_label(cxt) || check_sgi_label(cxt) || check_aix_label(cxt)
* Cylinders
*/
if (!display_in_cyl_units)
- res *= heads * sectors;
+ res *= cxt->geom.heads * cxt->geom.sectors;
} else if (*line_ptr &&
*(line_ptr + 1) == 'B' &&
*(line_ptr + 2) == '\0') {
return P_("sector", "sectors", n);
}
-void change_units(void)
+void change_units(struct fdisk_context *cxt)
{
display_in_cyl_units = !display_in_cyl_units;
- update_units();
+ update_units(cxt);
if (display_in_cyl_units)
printf(_("Changing display/entry units to cylinders (DEPRECATED!)\n"));
if (i < 0)
return;
- if (warn_geometry())
+ if (warn_geometry(cxt))
return; /* C/H/S not set */
ptes[i].changed = 1;
* Lubkin Oct. 1991). */
static void
-long2chs(unsigned long ls, unsigned int *c, unsigned int *h, unsigned int *s) {
- int spc = heads * sectors;
+long2chs(struct fdisk_context *cxt, unsigned long ls,
+ unsigned int *c, unsigned int *h, unsigned int *s) {
+ int spc = cxt->geom.heads * cxt->geom.sectors;
*c = ls / spc;
ls = ls % spc;
- *h = ls / sectors;
- *s = ls % sectors + 1; /* sectors count from 1 */
+ *h = ls / cxt->geom.sectors;
+ *s = ls % cxt->geom.sectors + 1; /* sectors count from 1 */
}
-static void check_consistency(struct partition *p, int partition) {
+static void check_consistency(struct fdisk_context *cxt, struct partition *p, int partition) {
unsigned int pbc, pbh, pbs; /* physical beginning c, h, s */
unsigned int pec, peh, pes; /* physical ending c, h, s */
unsigned int lbc, lbh, lbs; /* logical beginning c, h, s */
if (!dos_compatible_flag)
return;
- if (!heads || !sectors || (partition >= 4))
+ if (!cxt->geom.heads || !cxt->geom.sectors || (partition >= 4))
return; /* do not check extended partitions */
/* physical beginning c, h, s */
pes = p->end_sector & 0x3f;
/* compute logical beginning (c, h, s) */
- long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
+ long2chs(cxt, get_start_sect(p), &lbc, &lbh, &lbs);
/* compute logical ending (c, h, s) */
- long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
+ long2chs(cxt, get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
/* Same physical / logical beginning? */
- if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
+ if (cxt->geom.cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
printf(_("Partition %d has different physical/logical "
"beginnings (non-Linux?):\n"), partition + 1);
printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
}
/* Same physical / logical ending? */
- if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
+ if (cxt->geom.cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
printf(_("Partition %d has different physical/logical "
"endings:\n"), partition + 1);
printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
}
/* Ending on cylinder boundary? */
- if (peh != (heads - 1) || pes != sectors) {
+ if (peh != (cxt->geom.heads - 1) || pes != cxt->geom.sectors) {
printf(_("Partition %i does not end on cylinder boundary.\n"),
partition + 1);
}
printf(_("\nDisk %s: %ld.%ld GB, %llu bytes\n"),
cxt->dev_path, hectomega / 10, hectomega % 10, bytes);
}
- printf(_("%d heads, %llu sectors/track, %d cylinders"),
- heads, sectors, cylinders);
+ printf(_("%d heads, %llu sectors/track, %llu cylinders"),
+ cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders);
if (units_per_sector == 1)
printf(_(", total %llu sectors"), cxt->total_sectors);
printf("\n");
/* type id */ p->sys_ind,
/* type name */ (type = partition_type(p->sys_ind)) ?
type : _("Unknown"));
- check_consistency(p, i);
+ check_consistency(cxt, p, i);
check_alignment(cxt, get_partition_start(pe), i);
}
}
struct partition *p;
int i;
- printf(_("\nDisk %s: %d heads, %llu sectors, %d cylinders\n\n"),
- cxt->dev_path, heads, sectors, cylinders);
+ printf(_("\nDisk %s: %d heads, %llu sectors, %llu cylinders\n\n"),
+ cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders);
printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
for (i = 0 ; i < partitions; i++) {
pe = &ptes[i];
(unsigned long) get_start_sect(p),
(unsigned long) get_nr_sects(p), p->sys_ind);
if (p->sys_ind) {
- check_consistency(p, i);
+ check_consistency(cxt, p, i);
check_alignment(cxt, get_partition_start(pe), i);
}
}
}
static void
-check(int n, unsigned int h, unsigned int s, unsigned int c,
+check(struct fdisk_context *cxt, int n, unsigned int h, unsigned int s, unsigned int c,
unsigned int start) {
unsigned int total, real_s, real_c;
real_s = sector(s) - 1;
real_c = cylinder(s, c);
- total = (real_c * sectors + real_s) * heads + h;
+ total = (real_c * cxt->geom.sectors + real_s) * cxt->geom.heads + h;
if (!total)
fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
- if (h >= heads)
+ if (h >= cxt->geom.heads)
fprintf(stderr,
_("Partition %d: head %d greater than maximum %d\n"),
- n, h + 1, heads);
- if (real_s >= sectors)
+ n, h + 1, cxt->geom.heads);
+ if (real_s >= cxt->geom.sectors)
fprintf(stderr, _("Partition %d: sector %d greater than "
- "maximum %llu\n"), n, s, sectors);
- if (real_c >= cylinders)
+ "maximum %llu\n"), n, s, cxt->geom.sectors);
+ if (real_c >= cxt->geom.cylinders)
fprintf(stderr, _("Partitions %d: cylinder %d greater than "
- "maximum %d\n"), n, real_c + 1, cylinders);
- if (cylinders <= 1024 && start != total)
+ "maximum %llu\n"), n, real_c + 1, cxt->geom.cylinders);
+ if (cxt->geom.cylinders <= 1024 && start != total)
fprintf(stderr,
_("Partition %d: previous sectors %d disagrees with "
"total %d\n"), n, start, total);
unsigned long long first[partitions], last[partitions];
struct partition *p;
- if (warn_geometry())
+ if (warn_geometry(cxt))
return;
if (disklabel == SUN_LABEL) {
p = pe->part_table;
if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
- check_consistency(p, i);
+ check_consistency(cxt, p, i);
check_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);
- check(i + 1, p->end_head, p->end_sector, p->end_cyl,
- last[i]);
+ check(cxt, i + 1, p->end_head, p->end_sector, p->end_cyl,
+ last[i]);
total += last[i] + 1 - first[i];
for (j = 0; j < i; j++)
if ((first[i] >= first[j] && first[i] <= last[j])
static void new_partition(struct fdisk_context *cxt)
{
- if (warn_geometry())
+ if (warn_geometry(cxt))
return;
if (disklabel == SUN_LABEL) {
unsigned int new, free_start, curr_start, last;
int x;
- if (warn_geometry())
+ if (warn_geometry(cxt))
return;
if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
printf(_("Partition %d has no data area\n"), i + 1);
move_begin(cxt, get_partition(cxt, 0, partitions));
break;
case 'c':
- user_cylinders = cylinders =
- read_int(cxt, 1, cylinders, 1048576, 0,
+ user_cylinders = cxt->geom.cylinders =
+ read_int(cxt, 1, cxt->geom.cylinders, 1048576, 0,
_("Number of cylinders"));
if (disklabel == SUN_LABEL)
- sun_set_ncyl(cxt, cylinders);
+ sun_set_ncyl(cxt, cxt->geom.cylinders);
break;
case 'd':
print_raw(cxt);
create_sgilabel(cxt);
break;
case 'h':
- user_heads = heads = read_int(cxt, 1, heads, 256, 0,
+ user_heads = cxt->geom.heads = read_int(cxt, 1, cxt->geom.heads, 256, 0,
_("Number of heads"));
- update_units();
+ update_units(cxt);
break;
case 'i':
if (disklabel == SUN_LABEL)
case 'r':
return;
case 's':
- user_sectors = sectors = read_int(cxt, 1, sectors, 63, 0,
+ user_sectors = cxt->geom.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 "
"compatiblity\n"));
update_sector_offset(cxt);
- update_units();
+ update_units(cxt);
break;
case 'v':
verify(cxt);
err(EXIT_FAILURE, _("unable to open %s"), device);
if (sector_size) /* passed -b option, override autodiscovery */
cxt->phy_sector_size = cxt->sector_size = sector_size;
+ /* passed CHS option(s), override autodiscovery */
+ if (user_cylinders)
+ cxt->geom.cylinders = user_cylinders;
+ if (user_heads) {
+ cxt->geom.heads = user_heads;
+ fdisk_geom_set_cyls(cxt);
+ }
+ if (user_sectors) {
+ cxt->geom.sectors = user_sectors;
+ fdisk_geom_set_cyls(cxt);
+ }
gpt_warning(device);
gb = get_boot(cxt, 1);
change_sysid(cxt);
break;
case 'u':
- change_units();
+ change_units(cxt);
break;
case 'v':
verify(cxt);
printf(_("Warning: the -b (set sector size) option should"
" be used with one specified device\n"));
- /* init_mbr_buffer(); */
-
if (optl) {
nowarn = 1;
if (argc > optind) {
err(EXIT_FAILURE, _("unable to open %s"), argv[optind]);
if (sector_size) /* passed -b option, override autodiscovery */
cxt->phy_sector_size = cxt->sector_size = sector_size;
+ /* passed CHS option(s), override autodiscovery */
+ if (user_cylinders)
+ cxt->geom.cylinders = user_cylinders;
+ if (user_heads) {
+ cxt->geom.heads = user_heads;
+ fdisk_geom_set_cyls(cxt);
+ }
+ if (user_sectors) {
+ cxt->geom.sectors = user_sectors;
+ fdisk_geom_set_cyls(cxt);
+ }
}
else
usage(stderr);
#define FDISK_DEBUG_INIT (1 << 1)
#define FDISK_DEBUG_CONTEXT (1 << 2)
#define FDISK_DEBUG_TOPOLOGY (1 << 3)
+#define FDISK_DEBUG_GEOMETRY (1 << 4)
#define FDISK_DEBUG_ALL 0xFFFF
# define ON_DBG(m, x) do { \
unable_to_write
};
-struct geom {
+typedef unsigned long long sector_t;
+
+/*
+ * Legacy CHS based geometry
+ */
+struct fdisk_geometry {
unsigned int heads;
- unsigned int sectors;
- unsigned int cylinders;
+ sector_t sectors;
+ sector_t cylinders;
};
-typedef unsigned long long sector_t;
-
struct fdisk_context {
int dev_fd; /* device descriptor */
char *dev_path; /* device path */
/* geometry */
sector_t total_sectors; /* in logical sectors */
+ struct fdisk_geometry geom;
};
extern struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly);
extern int fdisk_dev_sectsz_is_default(struct fdisk_context *cxt);
extern void fdisk_free_context(struct fdisk_context *cxt);
extern void fdisk_mbr_zeroize(struct fdisk_context *cxt);
+extern void fdisk_geom_set_cyls(struct fdisk_context *cxt);
/* prototypes for fdisk.c */
extern char *disk_device, *line_ptr;
extern int fd, partitions;
extern unsigned int display_in_cyl_units, units_per_sector;
-extern void change_units(void);
+extern void change_units(struct fdisk_context *cxt);
extern void fatal(struct fdisk_context *cxt, enum failure why);
-extern void get_geometry(struct fdisk_context *, struct geom *);
extern int get_partition(struct fdisk_context *cxt, int warn, int max);
extern void list_types(struct systypes *sys);
extern int read_line (int *asked);
extern unsigned int heads, cylinders;
extern sector_t sectors;
extern char *partition_type(unsigned char type);
-extern void update_units(void);
+extern void update_units(struct fdisk_context *cxt);
extern char read_chars(char *mesg);
extern void set_changed(int);
extern void set_all_unchanged(void);
-extern int warn_geometry(void);
+extern int warn_geometry(struct fdisk_context *cxt);
extern void warn_limits(struct fdisk_context *cxt);
extern void warn_alignment(struct fdisk_context *cxt);
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);
+extern void get_partition_table_geometry(struct fdisk_context *cxt,
+ unsigned int *ph, unsigned int *ps);
#define PLURAL 0
#define SINGULAR 1
return 0;
}
other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
- update_units();
+ update_units(cxt);
disklabel = AIX_LABEL;
partitions= 1016;
volumes = 15;
xbsd_change_fstype ();
break;
case 'u':
- change_units();
+ change_units(cxt);
break;
case 'w':
xbsd_write_disklabel (cxt);
xbsd_initlabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d,
int pindex __attribute__((__unused__))) {
struct xbsd_partition *pp;
- struct geom g;
- get_geometry (cxt, &g);
memset (d, 0, sizeof (struct xbsd_disklabel));
d -> d_magic = BSD_DISKMAGIC;
d -> d_flags = 0;
#endif
d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
- d -> d_nsectors = g.sectors; /* sectors/track */
- d -> d_ntracks = g.heads; /* tracks/cylinder (heads) */
- d -> d_ncylinders = g.cylinders;
- d -> d_secpercyl = g.sectors * g.heads;/* sectors/cylinder */
+ d -> d_nsectors = cxt->geom.sectors; /* sectors/track */
+ d -> d_ntracks = cxt->geom.heads; /* tracks/cylinder (heads) */
+ d -> d_ncylinders = cxt->geom.cylinders;
+ d -> d_secpercyl = cxt->geom.sectors * cxt->geom.heads;/* sectors/cylinder */
if (d -> d_secpercyl == 0)
d -> d_secpercyl = 1; /* avoid segfaults */
d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
#include "fdiskdoslabel.h"
#define set_hsc(h,s,c,sector) { \
- s = sector % sectors + 1; \
- sector /= sectors; \
- h = sector % heads; \
- sector /= heads; \
- c = sector & 0xff; \
- s |= (sector >> 2) & 0xc0; \
+ s = sector % cxt->geom.sectors + 1; \
+ sector /= cxt->geom.sectors; \
+ h = sector % cxt->geom.heads; \
+ sector /= cxt->geom.heads; \
+ c = sector & 0xff; \
+ s |= (sector >> 2) & 0xc0; \
}
#define alignment_required (grain != cxt->sector_size)
pe->changed = 0;
}
- warn_geometry();
+ warn_geometry(cxt);
warn_limits(cxt);
warn_alignment(cxt);
}
if (!doext)
print_partition_size(cxt, i + 1, start, stop, sysid);
- if (dos_compatible_flag && (start/(sectors*heads) > 1023))
- start = heads*sectors*1024 - 1;
+ if (dos_compatible_flag && (start/(cxt->geom.sectors*cxt->geom.heads) > 1023))
+ start = cxt->geom.heads*cxt->geom.sectors*1024 - 1;
set_hsc(p->head, p->sector, p->cyl, start);
- if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
- stop = heads*sectors*1024 - 1;
+ if (dos_compatible_flag && (stop/(cxt->geom.sectors*cxt->geom.heads) > 1023))
+ stop = cxt->geom.heads*cxt->geom.sectors*1024 - 1;
set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
ptes[i].changed = 1;
}
if (n < 4) {
start = sector_offset;
if (display_in_cyl_units || !cxt->total_sectors)
- limit = heads * sectors * cylinders - 1;
+ limit = cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders - 1;
else
limit = cxt->total_sectors - 1;
IS_MAC:
other_endian = (maclabel->magic == MAC_LABEL_MAGIC_SWAPPED); // =?
- update_units();
+ update_units(cxt);
disklabel = MAC_LABEL;
partitions= 1016; // =?
volumes = 15; // =?
fprintf(stderr,
_("Detected sgi disklabel with wrong checksum.\n"));
}
- update_units();
+ update_units(cxt);
disklabel = SGI_LABEL;
partitions= 16;
volumes = 15;
if (xtra) {
printf(_("\nDisk %s (SGI disk label): %d heads, %llu sectors\n"
- "%d cylinders, %d physical cylinders\n"
+ "%llu cylinders, %d physical cylinders\n"
"%d extra sects/cyl, interleave %d:1\n"
"%s\n"
"Units = %s of %d * %ld bytes\n\n"),
- cxt->dev_path, heads, sectors, cylinders,
+ cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders,
SSWAP16(sgiparam.pcylcount),
(int) sgiparam.sparecyl, SSWAP16(sgiparam.ilfact),
(char *)sgilabel,
cxt->sector_size);
} else {
printf(_("\nDisk %s (SGI disk label): "
- "%d heads, %llu sectors, %d cylinders\n"
+ "%d heads, %llu sectors, %llu cylinders\n"
"Units = %s of %d * %ld bytes\n\n"),
- cxt->dev_path, heads, sectors, cylinders,
+ cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders,
str_units(PLURAL), units_per_sector,
cxt->sector_size);
}
}
static unsigned int
-sgi_get_lastblock(void) {
- return heads * sectors * cylinders;
+sgi_get_lastblock(struct fdisk_context *cxt) {
+ return cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders;
}
void
int entire = 0, i = 0;
unsigned int start = 0;
long long gap = 0; /* count unused blocks */
- unsigned int lastblock = sgi_get_lastblock();
+ unsigned int lastblock = sgi_get_lastblock(cxt);
clearfreelist();
for (i=0; i<16; i++) {
for (n=10; n<partitions; n++) {
if (!sgi_get_num_sectors(cxt, n)) {
- sgi_set_partition(cxt, n, 0, sgi_get_lastblock(), SGI_VOLUME);
+ sgi_set_partition(cxt, n, 0, sgi_get_lastblock(cxt), SGI_VOLUME);
break;
}
}
* Choose same default volume header size
* as IRIX fx uses.
*/
- if (4096 < sgi_get_lastblock())
+ if (4096 < sgi_get_lastblock(cxt))
sgi_set_partition(cxt, n, 0, 4096, SGI_VOLHDR);
break;
}
snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
for (;;) {
if (sys == SGI_VOLUME) {
- last = sgi_get_lastblock();
+ last = sgi_get_lastblock(cxt);
first = read_int(cxt, 0, 0, last-1, 0, mesg);
if (first != 0) {
printf(_("It is highly recommended that eleventh partition\n"
last *= units_per_sector;
/*else
last = last; * align to cylinder if You know how ... */
- if ((sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock()))
+ if ((sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock(cxt)))
printf(_("It is highly recommended that eleventh partition\n"
"covers the entire disk and is of type `SGI volume'\n"));
sgi_set_partition(cxt, n, first, last-first, sys);
if (ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry) < 0)
err(EXIT_FAILURE, _("HDIO_GETGEO ioctl failed on %s"), cxt->dev_path);
- heads = geometry.heads;
- sectors = geometry.sectors;
+ cxt->geom.heads = geometry.heads;
+ cxt->geom.sectors = geometry.sectors;
if (res == 0) {
/* the get device size ioctl was successful */
sector_t llcyls;
- llcyls = llsectors / (heads * sectors * sec_fac);
- cylinders = llcyls;
- if (cylinders != llcyls) /* truncated? */
- cylinders = ~0;
+ llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac);
+ cxt->geom.cylinders = llcyls;
+ if (cxt->geom.cylinders != llcyls) /* truncated? */
+ cxt->geom.cylinders = ~0;
} else {
/* otherwise print error and use truncated version */
- cylinders = geometry.cylinders;
+ cxt->geom.cylinders = geometry.cylinders;
fprintf(stderr,
_("Warning: BLKGETSIZE ioctl failed on %s. "
- "Using geometry cylinder value of %d.\n"
+ "Using geometry cylinder value of %llu.\n"
"This value may be truncated for devices"
- " > 33.8 GB.\n"), cxt->dev_path, cylinders);
+ " > 33.8 GB.\n"), cxt->dev_path, cxt->geom.cylinders);
}
#endif
for (i = 0; i < 4; i++) {
sunlabel->part_tags[i].tag = SSWAP16(sysid);
sunlabel->part_tags[i].flag = SSWAP16(0);
sunlabel->partitions[i].start_cylinder =
- SSWAP32(start / (heads * sectors));
+ SSWAP32(start / (cxt->geom.heads * cxt->geom.sectors));
sunlabel->partitions[i].num_sectors =
SSWAP32(stop - start);
set_changed(i);
} else {
int need_fixing = 0;
- heads = SSWAP16(sunlabel->nhead);
- cylinders = SSWAP16(sunlabel->ncyl);
- sectors = SSWAP16(sunlabel->nsect);
+ cxt->geom.heads = SSWAP16(sunlabel->nhead);
+ cxt->geom.cylinders = SSWAP16(sunlabel->ncyl);
+ cxt->geom.sectors = SSWAP16(sunlabel->nsect);
if (sunlabel->version != SSWAP32(SUN_LABEL_VERSION)) {
fprintf(stderr,_("Detected sun disklabel with wrong version [0x%08x].\n"),
set_changed(0);
}
}
- update_units();
+ update_units(cxt);
return 1;
}
#ifdef HDIO_GETGEO
if (!ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry)) {
- heads = geometry.heads;
- sectors = geometry.sectors;
+ cxt->geom.heads = geometry.heads;
+ cxt->geom.sectors = geometry.sectors;
if (res == 0) {
- llcyls = llsectors / (heads * sectors * sec_fac);
- cylinders = llcyls;
- if (cylinders != llcyls)
- cylinders = ~0;
+ llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac);
+ cxt->geom.cylinders = llcyls;
+ if (cxt->geom.cylinders != llcyls)
+ cxt->geom.cylinders = ~0;
} else {
- cylinders = geometry.cylinders;
+ cxt->geom.cylinders = geometry.cylinders;
fprintf(stderr,
_("Warning: BLKGETSIZE ioctl failed on %s. "
- "Using geometry cylinder value of %d.\n"
+ "Using geometry cylinder value of %llu.\n"
"This value may be truncated for devices"
- " > 33.8 GB.\n"), cxt->dev_path, cylinders);
+ " > 33.8 GB.\n"), cxt->dev_path, cxt->geom.cylinders);
}
} else
#endif
{
- heads = read_int(cxt, 1,1,1024,0,_("Heads"));
- sectors = read_int(cxt, 1,1,1024,0,_("Sectors/track"));
- cylinders = read_int(cxt, 1,1,65535,0,_("Cylinders"));
+ cxt->geom.heads = read_int(cxt, 1,1,1024,0,_("Heads"));
+ cxt->geom.sectors = read_int(cxt, 1,1,1024,0,_("Sectors/track"));
+ cxt->geom.cylinders = read_int(cxt, 1,1,65535,0,_("Cylinders"));
}
sunlabel->acyl = SSWAP16(2);
- sunlabel->pcyl = SSWAP16(cylinders);
- sunlabel->ncyl = SSWAP16(cylinders - 2);
+ sunlabel->pcyl = SSWAP16(cxt->geom.cylinders);
+ sunlabel->ncyl = SSWAP16(cxt->geom.cylinders - 2);
sunlabel->rpm = SSWAP16(5400);
sunlabel->intrlv = SSWAP16(1);
sunlabel->apc = SSWAP16(0);
- sunlabel->nhead = SSWAP16(heads);
- sunlabel->nsect = SSWAP16(sectors);
- sunlabel->ncyl = SSWAP16(cylinders);
+ sunlabel->nhead = SSWAP16(cxt->geom.heads);
+ sunlabel->nsect = SSWAP16(cxt->geom.sectors);
+ sunlabel->ncyl = SSWAP16(cxt->geom.cylinders);
snprintf(sunlabel->label_id, sizeof(sunlabel->label_id),
- "Linux cyl %d alt %d hd %d sec %llu",
- cylinders, SSWAP16(sunlabel->acyl), heads, sectors);
+ "Linux cyl %llu alt %d hd %d sec %llu",
+ cxt->geom.cylinders, SSWAP16(sunlabel->acyl), cxt->geom.heads, cxt->geom.sectors);
- if (cylinders * heads * sectors >= 150 * 2048) {
- ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
+ if (cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors >= 150 * 2048) {
+ ndiv = cxt->geom.cylinders - (50 * 2048 / (cxt->geom.heads * cxt->geom.sectors)); /* 50M swap */
} else
- ndiv = cylinders * 2 / 3;
+ ndiv = cxt->geom.cylinders * 2 / 3;
- set_sun_partition(cxt, 0, 0, ndiv * heads * sectors,
+ set_sun_partition(cxt, 0, 0, ndiv * cxt->geom.heads * cxt->geom.sectors,
SUN_TAG_LINUX_NATIVE);
- set_sun_partition(cxt, 1, ndiv * heads * sectors,
- cylinders * heads * sectors,
+ set_sun_partition(cxt, 1, ndiv * cxt->geom.heads * cxt->geom.sectors,
+ cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors,
SUN_TAG_LINUX_SWAP);
sunlabel->part_tags[1].flag |= SSWAP16(SUN_FLAG_UNMNT);
- set_sun_partition(cxt, 2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
+ set_sun_partition(cxt, 2, 0, cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors, SUN_TAG_BACKUP);
{
unsigned short *ush = (unsigned short *)sunlabel;
int i, continuous = 1;
*start = 0;
- *stop = cylinders * heads * sectors;
+ *stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors;
for (i = 0; i < partitions; i++) {
struct sun_partition *part = &sunlabel->partitions[i];
tag->tag != SSWAP16(SUN_TAG_UNASSIGNED) &&
tag->tag != SSWAP16(SUN_TAG_BACKUP)) {
starts[i] = (SSWAP32(part->start_cylinder) *
- heads * sectors);
+ cxt->geom.heads * cxt->geom.sectors);
lens[i] = SSWAP32(part->num_sectors);
if (continuous) {
if (starts[i] == *start)
for (k = 0; k < 7; k++) {
for (i = 0; i < SUN_NUM_PARTITIONS; i++) {
- if (k && (lens[i] % (heads * sectors))) {
+ if (k && (lens[i] % (cxt->geom.heads * cxt->geom.sectors))) {
printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
}
if (lens[i]) {
printf(_("No partitions defined\n"));
return;
}
- stop = cylinders * heads * sectors;
+ stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors;
if (starts[array[0]])
printf(_("Unused gap - sectors 0-%d\n"), starts[array[0]]);
for (i = 0; i < 7 && array[i+1] != -1; i++) {
first *= units_per_sector;
else {
/* Starting sector has to be properly aligned */
- int cs = heads * sectors;
+ int cs = cxt->geom.heads * cxt->geom.sectors;
int x = first % cs;
if (x)
} else
break;
}
- stop = cylinders * heads * sectors; /* ancient */
+ stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors; /* ancient */
stop2 = stop;
for (i = 0; i < partitions; i++) {
if (starts[i] > first && starts[i] < stop)
tag->tag == SSWAP16(SUN_TAG_BACKUP) &&
!part->start_cylinder &&
(nsec = SSWAP32(part->num_sectors))
- == heads * sectors * cylinders)
+ == cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders)
printf(_("If you want to maintain SunOS/Solaris compatibility, "
"consider leaving this\n"
"partition as Whole disk (5), starting at 0, with %u "
if (xtra)
printf(
_("\nDisk %s (Sun disk label): %u heads, %llu sectors, %d rpm\n"
- "%u cylinders, %d alternate cylinders, %d physical cylinders\n"
+ "%llu cylinders, %d alternate cylinders, %d physical cylinders\n"
"%d extra sects/cyl, interleave %d:1\n"
"Label ID: %s\n"
"Volume ID: %s\n"
"Units = %s of %d * 512 bytes\n\n"),
- cxt->dev_path, heads, sectors, SSWAP16(sunlabel->rpm),
- cylinders, SSWAP16(sunlabel->acyl),
+ cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, SSWAP16(sunlabel->rpm),
+ cxt->geom.cylinders, SSWAP16(sunlabel->acyl),
SSWAP16(sunlabel->pcyl),
SSWAP16(sunlabel->apc),
SSWAP16(sunlabel->intrlv),
str_units(PLURAL), units_per_sector);
else
printf(
- _("\nDisk %s (Sun disk label): %u heads, %llu sectors, %u cylinders\n"
+ _("\nDisk %s (Sun disk label): %u heads, %llu sectors, %llu cylinders\n"
"Units = %s of %d * 512 bytes\n\n"),
- cxt->dev_path, heads, sectors, cylinders,
+ cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders,
str_units(PLURAL), units_per_sector);
printf(_("%*s Flag Start End Blocks Id System\n"),
struct sun_tag_flag *tag = &sunlabel->part_tags[i];
if (part->num_sectors) {
- uint32_t start = SSWAP32(part->start_cylinder) * heads * sectors;
+ uint32_t start = SSWAP32(part->start_cylinder) * cxt->geom.heads * cxt->geom.sectors;
uint32_t len = SSWAP32(part->num_sectors);
printf(
"%s %c%c %9lu %9lu %9lu%c %2x %s\n",
void sun_set_xcyl(struct fdisk_context *cxt)
{
sunlabel->apc =
- SSWAP16(read_int(cxt, 0, SSWAP16(sunlabel->apc), sectors, 0,
+ SSWAP16(read_int(cxt, 0, SSWAP16(sunlabel->apc), cxt->geom.sectors, 0,
_("Extra sectors per cylinder")));
}
return DEFAULT_SECTOR_SIZE;
}
+/**
+ * fdisk_geom_set_cyls
+ * @cxt: fdisk context
+ *
+ * Sets the cylinders based on sectors and heads
+ */
+void fdisk_geom_set_cyls(struct fdisk_context *cxt)
+{
+ cxt->geom.cylinders = cxt->total_sectors /
+ (cxt->geom.heads * cxt->geom.sectors);
+}
+
static int __discover_geometry(struct fdisk_context *cxt)
{
sector_t nsects;
+ unsigned int h = 0, s = 0;
/* 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));
+
+ get_partition_table_geometry(cxt, &h, &s);
+ if (h && s)
+ goto hs_ok;
+
+ /* what the kernel/bios thinks the geometry is */
+ blkdev_get_geometry(cxt->dev_fd, &h, &s);
+ if (h && s)
+ goto hs_ok;
+
+ /* unable to discover geometry, use default values */
+ s = 63;
+ h = 255;
+
+hs_ok: /* obtained heads and sectors */
+ cxt->geom.heads = h;
+ cxt->geom.sectors = s;
+ fdisk_geom_set_cyls(cxt);
+ update_sector_offset(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));
+
return 0;
}