]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fdisk: add device topology to the API
authorDavidlohr Bueso <dave@gnu.org>
Sun, 3 Jun 2012 18:15:17 +0000 (20:15 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 6 Jun 2012 08:30:07 +0000 (10:30 +0200)
This patch adds device topology discovery to the internal API. This
functionality is static only to the API and therefore hidden from general fdisk
code. Functionality itself doesn't really change, min_io_size, io_size, logical
and physical sector sizes and alignment offset are added to the fdisk_context
structure and elements are accessed from there. The logical sector size
(sector_size) is now unsigned long instead of unsigned int, this as no effect
otherwise.

A few things to notice:
 - The patch is larger than I wanted but we need to modify function parameters
   across fdisk and its labels to use the topology data from cxt-> instances.
   Hopefully this will be pretty much it regarding this kind of modifications -
   perhaps geometry will need something of the like too.

 - The -b option must override internal discovery.

 - A new helper function has added to verify if the device provides topology
   information, this replaces the 'has_topology' global variable.

Signed-off-by: Davidlohr Bueso <dave@gnu.org>
fdisk/fdisk.c
fdisk/fdisk.h
fdisk/fdiskbsdlabel.c
fdisk/fdiskdoslabel.c
fdisk/fdiskdoslabel.h
fdisk/fdisksgilabel.c
fdisk/fdisksgilabel.h
fdisk/fdisksunlabel.c
fdisk/fdisksunlabel.h
fdisk/utils.c

index 1143b2f2aaed3c5b05cadcf80c4581860d0d3053..47c5d672088cd705a993230514c8e48d59ee3297 100644 (file)
@@ -47,9 +47,6 @@
 #ifdef HAVE_LINUX_BLKPG_H
 #include <linux/blkpg.h>
 #endif
-#ifdef HAVE_LIBBLKID
-#include <blkid.h>
-#endif
 
 #include "gpt.h"
 
@@ -144,19 +141,12 @@ sector_t sector_offset = 1, sectors;
 
 unsigned int   heads,
        cylinders,
-       sector_size = DEFAULT_SECTOR_SIZE,
        user_set_sector_size = 0,
        units_per_sector = 1,
        display_in_cyl_units = 0;
 
 sector_t total_number_of_sectors; /* in logical 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;
-
+unsigned long grain = DEFAULT_SECTOR_SIZE;
 enum labeltype disklabel;      /* Current disklabel */
 
 static void __attribute__ ((__noreturn__)) usage(FILE *out)
@@ -318,22 +308,22 @@ test_c(char **m, char *mesg) {
 }
 
 static int
-lba_is_aligned(sector_t lba)
+lba_is_aligned(struct fdisk_context *cxt, sector_t lba)
 {
-       unsigned int granularity = max(phy_sector_size, min_io_size);
-       sector_t offset = (lba * sector_size) & (granularity - 1);
+       unsigned int granularity = max(cxt->phy_sector_size, cxt->min_io_size);
+       sector_t offset = (lba * cxt->sector_size) & (granularity - 1);
 
-       return !((granularity + alignment_offset - offset) & (granularity - 1));
+       return !((granularity + cxt->alignment_offset - offset) & (granularity - 1));
 }
 
-sector_t align_lba(sector_t lba, int direction)
+sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction)
 {
        sector_t res;
 
-       if (lba_is_aligned(lba))
+       if (lba_is_aligned(cxt, lba))
                res = lba;
        else {
-               sector_t sects_in_phy = grain / sector_size;
+               sector_t sects_in_phy = grain / cxt->sector_size;
 
                if (lba < sector_offset)
                        res = sector_offset;
@@ -347,8 +337,8 @@ sector_t align_lba(sector_t lba, int direction)
                else /* ALIGN_NEAREST */
                        res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy;
 
-               if (alignment_offset && !lba_is_aligned(res) &&
-                   res > alignment_offset / sector_size) {
+               if (cxt->alignment_offset && !lba_is_aligned(cxt, res) &&
+                   res > cxt->alignment_offset / cxt->sector_size) {
                        /*
                         * apply alignment_offset
                         *
@@ -357,8 +347,8 @@ sector_t align_lba(sector_t lba, int direction)
                         * 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;
+                       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;
@@ -408,31 +398,31 @@ void update_units(void)
                units_per_sector = 1;   /* in sectors */
 }
 
-void warn_limits(void)
+void warn_limits(struct fdisk_context *cxt)
 {
        if (total_number_of_sectors > UINT_MAX && !nowarn) {
-               unsigned long long bytes = total_number_of_sectors * sector_size;
+               unsigned long long bytes = total_number_of_sectors * cxt->sector_size;
                int giga = bytes / 1000000000;
                int hectogiga = (giga + 50) / 100;
 
                fprintf(stderr, _("\n"
 "WARNING: The size of this disk is %d.%d TB (%llu bytes).\n"
 "DOS partition table format can not be used on drives for volumes\n"
-"larger than (%llu bytes) for %d-byte sectors. Use parted(1) and GUID \n"
+"larger than (%llu bytes) for %ld-byte sectors. Use parted(1) and GUID \n"
 "partition table format (GPT).\n\n"),
                        hectogiga / 10, hectogiga % 10,
                        bytes,
-                       (sector_t ) UINT_MAX * sector_size,
-                       sector_size);
+                       (sector_t ) UINT_MAX * cxt->sector_size,
+                       cxt->sector_size);
        }
 }
 
-void warn_alignment(void)
+void warn_alignment(struct fdisk_context *cxt)
 {
        if (nowarn)
                return;
 
-       if (sector_size != phy_sector_size)
+       if (cxt->sector_size != cxt->phy_sector_size)
                fprintf(stderr, _("\n"
 "The device presents a logical sector size that is smaller than\n"
 "the physical sector size. Aligning to a physical sector (or optimal\n"
@@ -450,64 +440,6 @@ void warn_alignment(void)
 
 }
 
-static void
-get_topology(struct fdisk_context *cxt) {
-       int arg;
-#ifdef HAVE_LIBBLKID
-       blkid_probe pr;
-
-       pr = blkid_new_probe();
-       if (pr && blkid_probe_set_device(pr, cxt->dev_fd, 0, 0) == 0) {
-               blkid_topology tp = blkid_probe_get_topology(pr);
-
-               if (tp) {
-                       min_io_size = blkid_topology_get_minimum_io_size(tp);
-                       io_size = blkid_topology_get_optimal_io_size(tp);
-                       phy_sector_size = blkid_topology_get_physical_sector_size(tp);
-                       alignment_offset = blkid_topology_get_alignment_offset(tp);
-
-                       /* We assume that the device provides topology info if
-                        * optimal_io_size is set or alignment_offset is set or
-                        * minimum_io_size is not power of 2.
-                        *
-                        * See also update_sector_offset().
-                        */
-                       if (io_size || alignment_offset ||
-                           (min_io_size & (min_io_size - 1)))
-                               has_topology = 1;
-                       if (!io_size)
-                               /* optimal IO is optional, default to minimum IO */
-                               io_size = min_io_size;
-               }
-       }
-       blkid_free_probe(pr);
-#endif
-
-       if (user_set_sector_size)
-               /* fdisk since 2.17 differentiate between logical and physical
-                * sectors size. For backward compatibility the
-                *    fdisk -b <sectorsize>
-                * changes both, logical and physical sector size.
-                */
-               phy_sector_size = sector_size;
-
-       else if (blkdev_get_sector_size(cxt->dev_fd, &arg) == 0) {
-               sector_size = arg;
-
-               if (!phy_sector_size)
-                       phy_sector_size = sector_size;
-       }
-
-       if (!min_io_size)
-               min_io_size = phy_sector_size;
-       if (!io_size)
-               io_size = min_io_size;
-
-       if (sector_size != DEFAULT_SECTOR_SIZE)
-               printf(_("Note: sector size is %d (not %d)\n"),
-                      sector_size, DEFAULT_SECTOR_SIZE);
-}
-
 static void
 get_partition_table_geometry(void) {
        unsigned char *bufp = MBRbuffer;
@@ -544,9 +476,9 @@ get_partition_table_geometry(void) {
  * Sets LBA of the first partition
  */
 void
-update_sector_offset(void)
+update_sector_offset(struct fdisk_context *cxt)
 {
-       grain = io_size;
+       grain = cxt->io_size;
 
        if (dos_compatible_flag)
                sector_offset = sectors;        /* usually 63 sectors */
@@ -564,29 +496,29 @@ update_sector_offset(void)
                 */
                sector_t x = 0;
 
-               if (has_topology) {
-                       if (alignment_offset)
-                               x = alignment_offset;
-                       else if (io_size > 2048 * 512)
-                               x = io_size;
+               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 / sector_size;
+               sector_offset = x / cxt->sector_size;
 
                /* don't use huge offset on small devices */
                if (total_number_of_sectors <= sector_offset * 4)
-                       sector_offset = phy_sector_size / sector_size;
+                       sector_offset = cxt->phy_sector_size / cxt->sector_size;
 
                /* use 1MiB grain always when possible */
                if (grain < 2048 * 512)
                        grain = 2048 * 512;
 
                /* don't use huge grain on small devices */
-               if (total_number_of_sectors <= (grain * 4 / sector_size))
-                       grain = phy_sector_size;
+               if (total_number_of_sectors <= (grain * 4 / cxt->sector_size))
+                       grain = cxt->phy_sector_size;
        }
 }
 
@@ -595,7 +527,6 @@ get_geometry(struct fdisk_context *cxt, struct geom *g) {
        sector_t llcyls, nsects = 0;
        unsigned int kern_heads = 0, kern_sectors = 0;
 
-       get_topology(cxt);
        heads = cylinders = sectors = 0;
        pt_heads = pt_sectors = 0;
 
@@ -611,9 +542,9 @@ get_geometry(struct fdisk_context *cxt, struct geom *g) {
 
        /* get number of 512-byte sectors, and convert it the real sectors */
        if (blkdev_get_sectors(cxt->dev_fd, &nsects) == 0)
-               total_number_of_sectors = (nsects / (sector_size >> 9));
+               total_number_of_sectors = (nsects / (cxt->sector_size >> 9));
 
-       update_sector_offset();
+       update_sector_offset(cxt);
 
        llcyls = total_number_of_sectors / (heads * sectors);
        cylinders = llcyls;
@@ -676,7 +607,7 @@ static int get_boot(struct fdisk_context *cxt, int try_only) {
 
        if (check_osf_label(cxt)) {
                /* intialize partitions for BSD as well */
-               dos_init();
+               dos_init(cxt);
                if (!valid_part_table_flag(MBRbuffer)) {
                        disklabel = OSF_LABEL;
                        return 0;
@@ -695,7 +626,7 @@ static int get_boot(struct fdisk_context *cxt, int try_only) {
 #ifdef __sparc__
                create_sunlabel(cxt);
 #else
-               create_doslabel();
+               create_doslabel(cxt);
 #endif
        }
        return 0;
@@ -796,7 +727,8 @@ read_hex(struct systypes *sys)
 }
 
 unsigned int
-read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
+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)
 {
        unsigned int res;
@@ -895,7 +827,7 @@ read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
                                unsigned long unit;
 
                                bytes = (unsigned long long) res * absolute;
-                               unit = sector_size * units_per_sector;
+                               unit = cxt->sector_size * units_per_sector;
                                bytes += unit/2;        /* round */
                                bytes /= unit;
                                res = bytes;
@@ -932,18 +864,19 @@ read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
  * There is no default if DFLT is not between LOW and HIGH.
  */
 unsigned int
-read_int(unsigned int low, unsigned int dflt, unsigned int high,
+read_int(struct fdisk_context *cxt,
+        unsigned int low, unsigned int dflt, unsigned int high,
         unsigned int base, char *mesg)
 {
-       return read_int_with_suffix(low, dflt, high, base, mesg, NULL);
+       return read_int_with_suffix(cxt, low, dflt, high, base, mesg, NULL);
 }
 
 int
-get_partition_dflt(int warn, int max, int dflt) {
+get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt) {
        struct pte *pe;
        int i;
 
-       i = read_int(1, dflt, max, 0, _("Partition number")) - 1;
+       i = read_int(cxt, 1, dflt, max, 0, _("Partition number")) - 1;
        pe = &ptes[i];
 
        if (warn) {
@@ -961,14 +894,14 @@ get_partition_dflt(int warn, int max, int dflt) {
 }
 
 int
-get_partition(int warn, int max) {
-       return get_partition_dflt(warn, max, 0);
+get_partition(struct fdisk_context *cxt, int warn, int max) {
+       return get_partition_dflt(cxt, warn, max, 0);
 }
 
 /* User partition selection unless one partition only is available */
 
 static int
-get_existing_partition(int warn, int max) {
+get_existing_partition(struct fdisk_context *cxt, int warn, int max) {
        int pno = -1;
        int i;
 
@@ -995,7 +928,7 @@ get_existing_partition(int warn, int max) {
 
 not_implemented:
 not_unique:
-       return get_partition(warn, max);
+       return get_partition(cxt, warn, max);
 }
 
 const char *
@@ -1031,18 +964,18 @@ toggle_active(int i) {
 }
 
 static void
-toggle_dos_compatibility_flag(void) {
+toggle_dos_compatibility_flag(struct fdisk_context *cxt) {
        dos_compatible_flag = ~dos_compatible_flag;
        if (dos_compatible_flag)
                printf(_("DOS Compatibility flag is set (DEPRECATED!)\n"));
        else
                printf(_("DOS Compatibility flag is not set\n"));
 
-       update_sector_offset();
+       update_sector_offset(cxt);
 }
 
 static void
-delete_partition(int i)
+delete_partition(struct fdisk_context *cxt, int i)
 {
        if (i < 0)
                return;
@@ -1057,18 +990,18 @@ delete_partition(int i)
        else if (disklabel == SUN_LABEL)
                sun_delete_partition(i);
        else if (disklabel == SGI_LABEL)
-               sgi_delete_partition(i);
+               sgi_delete_partition(cxt, i);
 
        printf(_("Partition %d is deleted\n"), i + 1);
 }
 
-static void
-change_sysid(void) {
+static void change_sysid(struct fdisk_context *cxt)
+{
        char *temp;
        int i, sys, origsys;
        struct partition *p;
 
-       i = get_existing_partition(0, partitions);
+       i = get_existing_partition(cxt, 0, partitions);
 
        if (i == -1)
                return;
@@ -1204,16 +1137,16 @@ static void check_consistency(struct partition *p, int partition) {
 }
 
 static void
-check_alignment(sector_t lba, int partition)
+check_alignment(struct fdisk_context *cxt, sector_t lba, int partition)
 {
-       if (!lba_is_aligned(lba))
+       if (!lba_is_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 = total_number_of_sectors * sector_size;
+       unsigned long long bytes = total_number_of_sectors * cxt->sector_size;
        long megabytes = bytes/1000000;
 
        if (megabytes < 10000)
@@ -1229,16 +1162,16 @@ list_disk_geometry(struct fdisk_context *cxt) {
        if (units_per_sector == 1)
                printf(_(", total %llu sectors"), total_number_of_sectors);
        printf("\n");
-       printf(_("Units = %s of %d * %d = %d bytes\n"),
+       printf(_("Units = %s of %d * %ld = %ld bytes\n"),
               str_units(PLURAL),
-              units_per_sector, sector_size, units_per_sector * sector_size);
+              units_per_sector, cxt->sector_size, units_per_sector * cxt->sector_size);
 
-       printf(_("Sector size (logical/physical): %u bytes / %lu bytes\n"),
-                               sector_size, phy_sector_size);
+       printf(_("Sector size (logical/physical): %lu bytes / %lu bytes\n"),
+                               cxt->sector_size, cxt->phy_sector_size);
        printf(_("I/O size (minimum/optimal): %lu bytes / %lu bytes\n"),
-                               min_io_size, io_size);
-       if (alignment_offset)
-               printf(_("Alignment offset: %lu bytes\n"), alignment_offset);
+                               cxt->min_io_size, cxt->io_size);
+       if (cxt->alignment_offset)
+               printf(_("Alignment offset: %lu bytes\n"), cxt->alignment_offset);
        if (disklabel == DOS_LABEL)
                dos_print_mbr_id();
        printf("\n");
@@ -1428,12 +1361,12 @@ list_table(struct fdisk_context *cxt, int xtra) {
                        unsigned int pblocks = psects;
                        unsigned int podd = 0;
 
-                       if (sector_size < 1024) {
-                               pblocks /= (1024 / sector_size);
-                               podd = psects % (1024 / sector_size);
+                       if (cxt->sector_size < 1024) {
+                               pblocks /= (1024 / cxt->sector_size);
+                               podd = psects % (1024 / cxt->sector_size);
                        }
-                       if (sector_size > 1024)
-                               pblocks *= (sector_size / 1024);
+                       if (cxt->sector_size > 1024)
+                               pblocks *= (cxt->sector_size / 1024);
                         printf(
                            "%s  %c %11lu %11lu %11lu%c  %2x  %s\n",
                        partname(cxt->dev_path, i+1, w+2),
@@ -1447,7 +1380,7 @@ list_table(struct fdisk_context *cxt, int xtra) {
 /* type name */                (type = partition_type(p->sys_ind)) ?
                        type : _("Unknown"));
                        check_consistency(p, i);
-                       check_alignment(get_partition_start(pe), i);
+                       check_alignment(cxt, get_partition_start(pe), i);
                }
        }
 
@@ -1482,7 +1415,7 @@ x_list_table(struct fdisk_context *cxt, int extend) {
                                (unsigned long) get_nr_sects(p), p->sys_ind);
                        if (p->sys_ind) {
                                check_consistency(p, i);
-                               check_alignment(get_partition_start(pe), i);
+                               check_alignment(cxt, get_partition_start(pe), i);
                        }
                }
        }
@@ -1533,7 +1466,7 @@ check(int n, unsigned int h, unsigned int s, unsigned int c,
 }
 
 static void
-verify(void) {
+verify(struct fdisk_context *cxt) {
        int i, j;
        sector_t total = 1, n_sectors = total_number_of_sectors;
        unsigned long long first[partitions], last[partitions];
@@ -1559,7 +1492,7 @@ verify(void) {
                p = pe->part_table;
                if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
                        check_consistency(p, i);
-                       check_alignment(get_partition_start(pe), 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);
@@ -1603,30 +1536,31 @@ verify(void) {
                printf(_("Total allocated sectors %llu greater than the maximum"
                        " %llu\n"), total, n_sectors);
        else if (total < n_sectors)
-               printf(_("Remaining %lld unallocated %d-byte sectors\n"),
-                      n_sectors - total, sector_size);
+               printf(_("Remaining %lld unallocated %ld-byte sectors\n"),
+                      n_sectors - total, cxt->sector_size);
 }
 
-void print_partition_size(int num, sector_t start, sector_t stop, int sysid)
+void print_partition_size(struct fdisk_context *cxt,
+                         int num, sector_t start, sector_t stop, int sysid)
 {
        char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE,
-                                    (stop - start + 1) * sector_size);
+                                    (stop - start + 1) * cxt->sector_size);
        printf(_("Partition %d of type %s and of size %s is set\n"), num, partition_type(sysid), str);
        free(str);
 }
 
-static void new_partition(void)
+static void new_partition(struct fdisk_context *cxt)
 {
        if (warn_geometry())
                return;
 
        if (disklabel == SUN_LABEL) {
-               add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
+               add_sun_partition(cxt, get_partition(cxt, 0, partitions), LINUX_NATIVE);
                return;
        }
 
        if (disklabel == SGI_LABEL) {
-               sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
+               sgi_add_partition(cxt, get_partition(cxt, 0, partitions), LINUX_NATIVE);
                return;
        }
 
@@ -1649,7 +1583,7 @@ static void new_partition(void)
        }
 
        /* default to DOS/BSD */
-       dos_new_partition();
+       dos_new_partition(cxt);
 }
 
 static void
@@ -1719,10 +1653,10 @@ reread_partition_table(struct fdisk_context *cxt, int leave) {
 
 #define MAX_PER_LINE   16
 static void
-print_buffer(unsigned char pbuffer[]) {
+print_buffer(struct fdisk_context *cxt, unsigned char pbuffer[]) {
        unsigned int i, l;
 
-       for (i = 0, l = 0; i < sector_size; i++, l++) {
+       for (i = 0, l = 0; i < cxt->sector_size; i++, l++) {
                if (l == 0)
                        printf("0x%03X:", i);
                printf(" %02X", pbuffer[i]);
@@ -1736,19 +1670,19 @@ print_buffer(unsigned char pbuffer[]) {
        printf("\n");
 }
 
-static void
-print_raw(char *dev) {
+static void print_raw(struct fdisk_context *cxt)
+{
        int i;
 
-       printf(_("Device: %s\n"), dev);
+       printf(_("Device: %s\n"), cxt->dev_path);
        if (disklabel == SUN_LABEL || disklabel == SGI_LABEL)
-               print_buffer(MBRbuffer);
+               print_buffer(cxt, MBRbuffer);
        else for (i = 3; i < partitions; i++)
-               print_buffer(ptes[i].sectorbuffer);
+                    print_buffer(cxt, ptes[i].sectorbuffer);
 }
 
 static void
-move_begin(int i) {
+move_begin(struct fdisk_context *cxt, int i) {
        struct pte *pe = &ptes[i];
        struct partition *p = pe->part_table;
        unsigned int new, free_start, curr_start, last;
@@ -1785,7 +1719,7 @@ move_begin(int i) {
 
        last = get_partition_start(pe) + get_nr_sects(p) - 1;
 
-       new = read_int(free_start, curr_start, last, free_start,
+       new = read_int(cxt, free_start, curr_start, last, free_start,
                       _("New beginning of data")) - pe->offset;
 
        if (new != get_nr_sects(p)) {
@@ -1814,27 +1748,27 @@ expert_command_prompt(struct fdisk_context *cxt)
                switch (c) {
                case 'a':
                        if (disklabel == SUN_LABEL)
-                               sun_set_alt_cyl();
+                               sun_set_alt_cyl(cxt);
                        break;
                case 'b':
                        if (disklabel == DOS_LABEL)
-                               move_begin(get_partition(0, partitions));
+                               move_begin(cxt, get_partition(cxt, 0, partitions));
                        break;
                case 'c':
                        user_cylinders = cylinders =
-                               read_int(1, cylinders, 1048576, 0,
+                               read_int(cxt, 1, cylinders, 1048576, 0,
                                         _("Number of cylinders"));
                        if (disklabel == SUN_LABEL)
                                sun_set_ncyl(cylinders);
                        break;
                case 'd':
-                       print_raw(cxt->dev_path);
+                       print_raw(cxt);
                        break;
                case 'e':
                        if (disklabel == SGI_LABEL)
                                sgi_set_xcyl();
                        else if (disklabel == SUN_LABEL)
-                               sun_set_xcyl();
+                               sun_set_xcyl(cxt);
                        else
                        if (disklabel == DOS_LABEL)
                                x_list_table(cxt, 1);
@@ -1847,19 +1781,19 @@ expert_command_prompt(struct fdisk_context *cxt)
                        create_sgilabel(cxt);
                        break;
                case 'h':
-                       user_heads = heads = read_int(1, heads, 256, 0,
+                       user_heads = heads = read_int(cxt, 1, heads, 256, 0,
                                         _("Number of heads"));
                        update_units();
                        break;
                case 'i':
                        if (disklabel == SUN_LABEL)
-                               sun_set_ilfact();
+                               sun_set_ilfact(cxt);
                        else if (disklabel == DOS_LABEL)
                                dos_set_mbr_id();
                        break;
                case 'o':
                        if (disklabel == SUN_LABEL)
-                               sun_set_rspeed();
+                               sun_set_rspeed(cxt);
                        break;
                case 'p':
                        if (disklabel == SUN_LABEL)
@@ -1872,24 +1806,24 @@ expert_command_prompt(struct fdisk_context *cxt)
                case 'r':
                        return;
                case 's':
-                       user_sectors = sectors = read_int(1, sectors, 63, 0,
+                       user_sectors = sectors = read_int(cxt, 1, sectors, 63, 0,
                                           _("Number of sectors"));
                        if (dos_compatible_flag)
                                fprintf(stderr, _("Warning: setting "
                                        "sector offset for DOS "
                                        "compatiblity\n"));
-                       update_sector_offset();
+                       update_sector_offset(cxt);
                        update_units();
                        break;
                case 'v':
-                       verify();
+                       verify(cxt);
                        break;
                case 'w':
                        write_table(cxt);
                        break;
                case 'y':
                        if (disklabel == SUN_LABEL)
-                               sun_set_pcylcount();
+                               sun_set_pcylcount(cxt);
                        break;
                default:
                        print_menu(EXPERT_MENU);
@@ -1918,15 +1852,15 @@ gpt_warning(char *dev)
 }
 
 /* Print disk geometry and partition table of a specified device (-l option) */
-
-static void
-print_partition_table_from_option(char *device)
+static void print_partition_table_from_option(char *device, unsigned long sector_size)
 {
        int gb;
 
        struct fdisk_context *cxt = fdisk_new_context_from_filename(device, 1); /* read-only */
        if (!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;
 
        gpt_warning(device);
        gb = get_boot(cxt, 1);
@@ -1946,7 +1880,7 @@ print_partition_table_from_option(char *device)
  * try all things in /proc/partitions that look like a full disk
  */
 static void
-print_all_partition_table_from_option(void)
+print_all_partition_table_from_option(unsigned long sector_size)
 {
        FILE *procpt;
        char line[128], ptname[128], devname[256];
@@ -1968,7 +1902,7 @@ print_all_partition_table_from_option(void)
                        char *cn = canonicalize_path(devname);
                        if (cn) {
                                if (!is_ide_cdrom_or_tape(cn))
-                                       print_partition_table_from_option(cn);
+                                       print_partition_table_from_option(cn, sector_size);
                                free(cn);
                        }
                }
@@ -2011,13 +1945,13 @@ static void command_prompt(struct fdisk_context *cxt)
                switch (c) {
                case 'a':
                        if (disklabel == DOS_LABEL)
-                               toggle_active(get_partition(1, partitions));
+                               toggle_active(get_partition(cxt, 1, partitions));
                        else if (disklabel == SUN_LABEL)
-                               toggle_sunflags(get_partition(1, partitions),
+                               toggle_sunflags(get_partition(cxt, 1, partitions),
                                                SUN_FLAG_UNMNT);
                        else if (disklabel == SGI_LABEL)
                                sgi_set_bootpartition(
-                                       get_partition(1, partitions));
+                                       get_partition(cxt, 1, partitions));
                        else
                                unknown_command(c);
                        break;
@@ -2033,18 +1967,18 @@ static void command_prompt(struct fdisk_context *cxt)
                        break;
                case 'c':
                        if (disklabel == DOS_LABEL)
-                               toggle_dos_compatibility_flag();
+                               toggle_dos_compatibility_flag(cxt);
                        else if (disklabel == SUN_LABEL)
-                               toggle_sunflags(get_partition(1, partitions),
+                               toggle_sunflags(get_partition(cxt, 1, partitions),
                                                SUN_FLAG_RONLY);
                        else if (disklabel == SGI_LABEL)
                                sgi_set_swappartition(
-                                               get_partition(1, partitions));
+                                       get_partition(cxt, 1, partitions));
                        else
                                unknown_command(c);
                        break;
                case 'd':
-                       delete_partition(get_existing_partition(1, partitions));
+                       delete_partition(cxt, get_existing_partition(cxt, 1, partitions));
                        break;
                case 'i':
                        if (disklabel == SGI_LABEL)
@@ -2059,10 +1993,10 @@ static void command_prompt(struct fdisk_context *cxt)
                        print_menu(MAIN_MENU);
                        break;
                case 'n':
-                       new_partition();
+                       new_partition(cxt);
                        break;
                case 'o':
-                       create_doslabel();
+                       create_doslabel(cxt);
                        break;
                case 'p':
                        list_table(cxt, 0);
@@ -2073,13 +2007,13 @@ static void command_prompt(struct fdisk_context *cxt)
                        create_sunlabel(cxt);
                        break;
                case 't':
-                       change_sysid();
+                       change_sysid(cxt);
                        break;
                case 'u':
                        change_units();
                        break;
                case 'v':
-                       verify();
+                       verify(cxt);
                        break;
                case 'w':
                        write_table(cxt);
@@ -2112,6 +2046,7 @@ static sector_t get_dev_blocks(char *dev)
 int main(int argc, char **argv)
 {
        int c, optl = 0, opts = 0;
+       unsigned long sector_size = 0;
        struct fdisk_context *cxt = NULL;
 
        setlocale(LC_ALL, "");
@@ -2191,9 +2126,9 @@ int main(int argc, char **argv)
                if (argc > optind) {
                        int k;
                        for (k = optind; k < argc; k++)
-                               print_partition_table_from_option(argv[k]);
+                               print_partition_table_from_option(argv[k], sector_size);
                } else
-                       print_all_partition_table_from_option();
+                       print_all_partition_table_from_option(sector_size);
                exit(0);
        }
 
@@ -2216,6 +2151,8 @@ int main(int argc, char **argv)
                cxt = fdisk_new_context_from_filename(argv[optind], 0);
                if (!cxt)
                        err(EXIT_FAILURE, _("unable to open %s"), argv[optind]);
+               if (user_set_sector_size) /* passed -b option, override autodiscovery */
+                       cxt->phy_sector_size = cxt->sector_size = sector_size;
        }
        else
                usage(stderr);
index 31129e86cebea51050d5ac7622ea5fc439ac2b5a..a24fa2056495a7b271ae57dfc9defb4b78d2ba35 100644 (file)
@@ -105,9 +105,17 @@ typedef unsigned long long sector_t;
 struct fdisk_context {
        int dev_fd;     /* device descriptor */
        char *dev_path; /* device path */
+
+       /* topology */
+       unsigned long io_size;
+       unsigned long min_io_size;
+       unsigned long phy_sector_size; /* physical size */
+       unsigned long sector_size; /* logical size */
+       unsigned long alignment_offset;
 };
 
 extern struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly);
+extern int fdisk_dev_has_topology(struct fdisk_context *cxt);
 extern void fdisk_free_context(struct fdisk_context *cxt);
 
 /* prototypes for fdisk.c */
@@ -117,7 +125,7 @@ extern unsigned int display_in_cyl_units, units_per_sector;
 extern void change_units(void);
 extern void fatal(struct fdisk_context *cxt, enum failure why);
 extern void get_geometry(struct fdisk_context *, struct geom *);
-extern int  get_partition(int warn, int max);
+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 char read_char(char *mesg);
@@ -125,14 +133,15 @@ extern int read_hex(struct systypes *sys);
 extern void reread_partition_table(struct fdisk_context *cxt, int leave);
 extern struct partition *get_part_table(int);
 extern int valid_part_table_flag(unsigned char *b);
-extern unsigned int read_int(unsigned int low, unsigned int dflt,
+extern unsigned int read_int(struct fdisk_context *cxt,
+                            unsigned int low, unsigned int dflt,
                             unsigned int high, unsigned int base, char *mesg);
 extern void print_menu(enum menutype);
-extern void print_partition_size(int num, sector_t start, sector_t stop, int sysid);
+extern void print_partition_size(struct fdisk_context *cxt, int num, sector_t start, sector_t stop, int sysid);
 
 extern void zeroize_mbr_buffer(void);
 extern void fill_bounds(sector_t *first, sector_t *last);
-extern unsigned int heads, cylinders, sector_size;
+extern unsigned int heads, cylinders;
 extern sector_t sectors;
 extern char *partition_type(unsigned char type);
 extern void update_units(void);
@@ -140,12 +149,13 @@ extern char read_chars(char *mesg);
 extern void set_changed(int);
 extern void set_all_unchanged(void);
 extern int warn_geometry(void);
-extern void warn_limits(void);
-extern void warn_alignment(void);
-extern unsigned int read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
+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 low, unsigned int dflt, unsigned int high,
                                  unsigned int base, char *mesg, int *is_suffix_used);
-extern sector_t align_lba(sector_t lba, int direction);
-extern int get_partition_dflt(int warn, int max, int dflt);
+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);
 
 #define PLURAL 0
 #define SINGULAR 1
@@ -202,7 +212,7 @@ static inline void set_start_sect(struct partition *p, unsigned int start_sect)
 
 static inline void seek_sector(struct fdisk_context *cxt, sector_t secno)
 {
-       off_t offset = (off_t) secno * sector_size;
+       off_t offset = (off_t) secno * cxt->sector_size;
        if (lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1)
                fatal(cxt, unable_to_seek);
 }
@@ -210,14 +220,14 @@ static inline void seek_sector(struct fdisk_context *cxt, sector_t secno)
 static inline void read_sector(struct fdisk_context *cxt, sector_t secno, unsigned char *buf)
 {
        seek_sector(cxt, secno);
-       if (read(cxt->dev_fd, buf, sector_size) != sector_size)
+       if (read(cxt->dev_fd, buf, cxt->sector_size) != cxt->sector_size)
                fatal(cxt, unable_to_read);
 }
 
 static inline void write_sector(struct fdisk_context *cxt, sector_t secno, unsigned char *buf)
 {
        seek_sector(cxt, secno);
-       if (write(cxt->dev_fd, buf, sector_size) != sector_size)
+       if (write(cxt->dev_fd, buf, cxt->sector_size) != cxt->sector_size)
                fatal(cxt, unable_to_write);
 }
 
index a2a0532cfa30c81f5dbb0f6dd414c743b1ea013b..b92530f5048b21791d0173f4c3617f2a07bc7393 100644 (file)
@@ -62,7 +62,7 @@
 #include "fdiskbsdlabel.h"
 
 static void xbsd_delete_part (void);
-static void xbsd_new_part (void);
+static void xbsd_new_part (struct fdisk_context *cxt);
 static void xbsd_write_disklabel (struct fdisk_context *cxt);
 static int xbsd_create_disklabel (struct fdisk_context *cxt);
 static void xbsd_edit_disklabel (void);
@@ -86,7 +86,7 @@ void alpha_bootblock_checksum (char *boot);
 
 #if !defined (__alpha__)
 static int xbsd_translate_fstype (int linux_type);
-static void xbsd_link_part (void);
+static void xbsd_link_part (struct fdisk_context *cxt);
 static struct partition *xbsd_part;
 static int xbsd_part_index;
 #endif
@@ -196,7 +196,7 @@ bsd_command_prompt (struct fdisk_context *cxt)
        xbsd_list_types ();
        break;
       case 'n':
-       xbsd_new_part ();
+       xbsd_new_part (cxt);
        break;
       case 'p':
              xbsd_print_disklabel (cxt, 0);
@@ -220,7 +220,7 @@ bsd_command_prompt (struct fdisk_context *cxt)
        break;
 #if !defined (__alpha__)
       case 'x':
-       xbsd_link_part ();
+       xbsd_link_part (cxt);
        break;
 #endif
       default:
@@ -245,7 +245,7 @@ xbsd_delete_part (void)
 }
 
 static void
-xbsd_new_part (void)
+xbsd_new_part (struct fdisk_context *cxt)
 {
   unsigned int begin, end;
   char mesg[256];
@@ -263,7 +263,7 @@ xbsd_new_part (void)
 #endif
 
   snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
-  begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
+  begin = read_int (cxt, bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
                    0, mesg);
 
   if (display_in_cyl_units)
@@ -271,7 +271,7 @@ xbsd_new_part (void)
 
   snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
           str_units(SINGULAR));
-  end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
+  end = read_int (cxt, bsd_cround (begin), bsd_cround (end), bsd_cround (end),
                  bsd_cround (begin), mesg);
 
   if (display_in_cyl_units)
@@ -810,12 +810,12 @@ xbsd_translate_fstype (int linux_type)
 }
 
 static void
-xbsd_link_part (void)
+xbsd_link_part (struct fdisk_context *cxt)
 {
   int k, i;
   struct partition *p;
 
-  k = get_partition (1, partitions);
+  k = get_partition (cxt, 1, partitions);
 
   if (!xbsd_check_new_partition (&i))
     return;
index 382909c453ce5c5c1adab60e140a0cca37e5d98f..8ee35666cffd4c39aa1f392e4643792fd55b5231 100644 (file)
                s |= (sector >> 2) & 0xc0;                      \
        }
 
-#define alignment_required     (grain != sector_size)
+#define alignment_required     (grain != cxt->sector_size)
 
 struct pte ptes[MAXIMUM_PARTS];
 sector_t extended_offset;
 int ext_index;
 
-static int get_nonexisting_partition(int warn, int max)
+static int get_nonexisting_partition(struct fdisk_context *cxt, int warn, int max)
 {
        int pno = -1;
        int i;
@@ -54,7 +54,7 @@ static int get_nonexisting_partition(int warn, int max)
        return -1;
 
  not_unique:
-       return get_partition_dflt(warn, max, dflt);
+       return get_partition_dflt(cxt, warn, max, dflt);
 }
 
 
@@ -64,7 +64,7 @@ static void read_pte(struct fdisk_context *cxt, int pno, sector_t offset)
        struct pte *pe = &ptes[pno];
 
        pe->offset = offset;
-       pe->sectorbuffer = xmalloc(sector_size);
+       pe->sectorbuffer = xmalloc(cxt->sector_size);
        read_sector(cxt, offset, pe->sectorbuffer);
        pe->changed = 0;
        pe->part_table = pe->ext_pointer = NULL;
@@ -96,7 +96,7 @@ static void clear_partition(struct partition *p)
        set_nr_sects(p,0);
 }
 
-void dos_init(void)
+void dos_init(struct fdisk_context *cxt)
 {
        int i;
 
@@ -116,8 +116,8 @@ void dos_init(void)
        }
 
        warn_geometry();
-       warn_limits();
-       warn_alignment();
+       warn_limits(cxt);
+       warn_alignment(cxt);
 }
 
 static void read_extended(struct fdisk_context *cxt, int ext)
@@ -219,7 +219,7 @@ void dos_print_mbr_id(void)
        printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(MBRbuffer));
 }
 
-void create_doslabel(void)
+void create_doslabel(struct fdisk_context *cxt)
 {
        unsigned int id;
 
@@ -228,7 +228,7 @@ void create_doslabel(void)
 
        fprintf(stderr, _("Building a new DOS disklabel with disk identifier 0x%08x.\n"), id);
 
-       dos_init();
+       dos_init(cxt);
        zeroize_mbr_buffer();
 
        set_all_unchanged();
@@ -324,7 +324,7 @@ int check_dos_label(struct fdisk_context *cxt)
        if (!valid_part_table_flag(MBRbuffer))
                return 0;
 
-       dos_init();
+       dos_init(cxt);
 
        for (i = 0; i < 4; i++) {
                struct pte *pe = &ptes[i];
@@ -368,7 +368,8 @@ int is_dos_partition(int t)
                t == 0xc1 || t == 0xc4 || t == 0xc6);
 }
 
-static void set_partition(int i, int doext, sector_t start,
+static void set_partition(struct fdisk_context *cxt,
+                         int i, int doext, sector_t start,
                          sector_t stop, int sysid)
 {
        struct partition *p;
@@ -387,7 +388,7 @@ static void set_partition(int i, int doext, sector_t start,
        set_nr_sects(p, stop - start + 1);
 
        if (!doext)
-               print_partition_size(i + 1, start, stop, sysid);
+               print_partition_size(cxt, i + 1, start, stop, sysid);
 
        if (dos_compatible_flag && (start/(sectors*heads) > 1023))
                start = heads*sectors*1024 - 1;
@@ -416,12 +417,13 @@ static sector_t get_unused_start(int part_n, sector_t start,
        return start;
 }
 
-static sector_t align_lba_in_range(sector_t lba, sector_t start, sector_t stop)
+static sector_t align_lba_in_range(struct fdisk_context *cxt,
+                                  sector_t lba, sector_t start, sector_t stop)
 {
-       start = align_lba(start, ALIGN_UP);
-       stop = align_lba(stop, ALIGN_DOWN);
+       start = align_lba(cxt, start, ALIGN_UP);
+       stop = align_lba(cxt, stop, ALIGN_DOWN);
 
-       lba = align_lba(lba, ALIGN_NEAREST);
+       lba = align_lba(cxt, lba, ALIGN_NEAREST);
 
        if (lba < start)
                return start;
@@ -430,7 +432,7 @@ static sector_t align_lba_in_range(sector_t lba, sector_t start, sector_t stop)
        return lba;
 }
 
-void dos_add_partition(int n, int sys)
+void dos_add_partition(struct fdisk_context *cxt, int n, int sys)
 {
        char mesg[256];         /* 48 does not suffice in Japanese */
        int i, read = 0;
@@ -477,7 +479,7 @@ void dos_add_partition(int n, int sys)
 
                /* the default sector should be aligned and unused */
                do {
-                       aligned = align_lba_in_range(dflt, dflt, limit);
+                       aligned = align_lba_in_range(cxt, dflt, dflt, limit);
                        dflt = get_unused_start(n, aligned, first, last);
                } while (dflt != aligned && dflt > aligned && dflt < limit);
 
@@ -493,7 +495,7 @@ void dos_add_partition(int n, int sys)
                if (!read && start == temp) {
                        sector_t i = start;
 
-                       start = read_int(cround(i), cround(dflt), cround(limit),
+                       start = read_int(cxt, cround(i), cround(dflt), cround(limit),
                                         0, mesg);
                        if (display_in_cyl_units) {
                                start = (start - 1) * units_per_sector;
@@ -536,8 +538,9 @@ void dos_add_partition(int n, int sys)
                        _("Last %1$s, +%2$s or +size{K,M,G}"),
                         str_units(SINGULAR), str_units(PLURAL));
 
-               stop = read_int_with_suffix(cround(start), cround(limit), cround(limit),
-                               cround(start), mesg, &is_suffix_used);
+               stop = read_int_with_suffix(cxt,
+                                           cround(start), cround(limit), cround(limit),
+                                           cround(start), mesg, &is_suffix_used);
                if (display_in_cyl_units) {
                        stop = stop * units_per_sector - 1;
                        if (stop >limit)
@@ -550,15 +553,15 @@ void dos_add_partition(int n, int sys)
                         * and align the end of the partition. The next
                         * partition will start at phy.block boundary.
                         */
-                       stop = align_lba_in_range(stop, start, limit) - 1;
+                       stop = align_lba_in_range(cxt, stop, start, limit) - 1;
                        if (stop > limit)
                                stop = limit;
                }
        }
 
-       set_partition(n, 0, start, stop, sys);
+       set_partition(cxt, n, 0, start, stop, sys);
        if (n > 4)
-               set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
+               set_partition(cxt, n - 1, 1, ptes[n].offset, stop, EXTENDED);
 
        if (IS_EXTENDED (sys)) {
                struct pte *pe4 = &ptes[4];
@@ -567,7 +570,7 @@ void dos_add_partition(int n, int sys)
                ext_index = n;
                pen->ext_pointer = p;
                pe4->offset = extended_offset = start;
-               pe4->sectorbuffer = xcalloc(1, sector_size);
+               pe4->sectorbuffer = xcalloc(1, cxt->sector_size);
                pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
                pe4->ext_pointer = pe4->part_table + 1;
                pe4->changed = 1;
@@ -575,12 +578,12 @@ void dos_add_partition(int n, int sys)
        }
 }
 
-static void add_logical(void)
+static void add_logical(struct fdisk_context *cxt)
 {
        if (partitions > 5 || ptes[4].part_table->sys_ind) {
                struct pte *pe = &ptes[partitions];
 
-               pe->sectorbuffer = xcalloc(1, sector_size);
+               pe->sectorbuffer = xcalloc(1, cxt->sector_size);
                pe->part_table = pt_offset(pe->sectorbuffer, 0);
                pe->ext_pointer = pe->part_table + 1;
                pe->offset = 0;
@@ -588,14 +591,14 @@ static void add_logical(void)
                partitions++;
        }
        printf(_("Adding logical partition %d\n"), partitions);
-       dos_add_partition(partitions - 1, LINUX_NATIVE);
+       dos_add_partition(cxt, partitions - 1, LINUX_NATIVE);
 }
 
 /*
  * Ask the user for new partition type information (logical, extended).
  * This function calls the actual partition adding logic - dos_add_partition.
  */
-void dos_new_partition(void)
+void dos_new_partition(struct fdisk_context *cxt)
 {
        int i, free_primary = 0;
 
@@ -610,14 +613,14 @@ void dos_new_partition(void)
        if (!free_primary) {
                if (extended_offset) {
                        printf(_("All primary partitions are in use\n"));
-                       add_logical();
+                       add_logical(cxt);
                } else
                        printf(_("If you want to create more than four partitions, you must replace a\n"
                                 "primary partition with an extended partition first.\n"));
        } else if (partitions >= MAXIMUM_PARTS) {
                printf(_("All logical partitions are in use\n"));
                printf(_("Adding a primary partition\n"));
-               dos_add_partition(get_partition(0, 4), LINUX_NATIVE);
+               dos_add_partition(cxt, get_partition(cxt, 0, 4), LINUX_NATIVE);
        } else {
                char c, dflt, line[LINE_LENGTH];
 
@@ -637,17 +640,17 @@ void dos_new_partition(void)
                        printf(_("Using default response %c\n"), c);
                }
                if (c == 'p') {
-                       int i = get_nonexisting_partition(0, 4);
+                       int i = get_nonexisting_partition(cxt, 0, 4);
                        if (i >= 0)
-                               dos_add_partition(i, LINUX_NATIVE);
+                               dos_add_partition(cxt, i, LINUX_NATIVE);
                        return;
                } else if (c == 'l' && extended_offset) {
-                       add_logical();
+                       add_logical(cxt);
                        return;
                } else if (c == 'e' && !extended_offset) {
-                       int i = get_nonexisting_partition(0, 4);
+                       int i = get_nonexisting_partition(cxt, 0, 4);
                        if (i >= 0)
-                               dos_add_partition(i, EXTENDED);
+                               dos_add_partition(cxt, i, EXTENDED);
                        return;
                } else
                        printf(_("Invalid partition type `%c'\n"), c);
index a436e53b9d0ceb8b6a47b7c82a465bb1529c62b8..8d62d52e8c626a961176a6e68a5b6b6f9901e61e 100644 (file)
@@ -43,15 +43,15 @@ static inline sector_t get_partition_start(struct pte *pe)
        return pe->offset + get_start_sect(pe->part_table);
 }
 
-extern void create_doslabel(void);
+extern void create_doslabel(struct fdisk_context *cxt);
 extern void dos_print_mbr_id(void);
 extern void dos_set_mbr_id(void);
 extern void dos_delete_partition(int i);
 extern int check_dos_label(struct fdisk_context *cxt);
 extern int is_dos_partition(int t);
-extern void dos_init(void);
-extern void dos_add_partition(int n, int sys);
-extern void dos_new_partition(void);
+extern void dos_init(struct fdisk_context *cxt);
+extern void dos_add_partition(struct fdisk_context *cxt, int n, int sys);
+extern void dos_new_partition(struct fdisk_context *cxt);
 extern void dos_write_table(struct fdisk_context *cxt);
 
 #endif
index 14e3443cfb19689311dc45d21af4d7cc99c552a0..9c425b393431e811ff24e5182d1c2a0244d6e625 100644 (file)
@@ -190,20 +190,20 @@ sgi_list_table(struct fdisk_context *cxt, int xtra) {
                         "%d cylinders, %d physical cylinders\n"
                         "%d extra sects/cyl, interleave %d:1\n"
                         "%s\n"
-                        "Units = %s of %d * %d bytes\n\n"),
+                        "Units = %s of %d * %ld bytes\n\n"),
                       cxt->dev_path, heads, sectors, cylinders,
                       SSWAP16(sgiparam.pcylcount),
                       (int) sgiparam.sparecyl, SSWAP16(sgiparam.ilfact),
                       (char *)sgilabel,
                       str_units(PLURAL), units_per_sector,
-                       sector_size);
+                       cxt->sector_size);
        } else {
                printf(_("\nDisk %s (SGI disk label): "
                         "%d heads, %llu sectors, %d cylinders\n"
-                        "Units = %s of %d * %d bytes\n\n"),
+                        "Units = %s of %d * %ld bytes\n\n"),
                       cxt->dev_path, heads, sectors, cylinders,
                       str_units(PLURAL), units_per_sector,
-                       sector_size);
+                       cxt->sector_size);
        }
        printf(_("----- partitions -----\n"
                 "Pt# %*s  Info     Start       End   Sectors  Id  System\n"),
@@ -563,7 +563,8 @@ sgi_entire(void) {
 }
 
 static void
-sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
+sgi_set_partition(struct fdisk_context *cxt,
+                 int i, unsigned int start, unsigned int length, int sys) {
        sgilabel->partitions[i].id = SSWAP32(sys);
        sgilabel->partitions[i].num_sectors = SSWAP32(length);
        sgilabel->partitions[i].start_sector = SSWAP32(start);
@@ -571,16 +572,16 @@ sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
        if (sgi_gaps() < 0)     /* rebuild freelist */
                printf(_("Partition overlap on the disk.\n"));
        if (length)
-               print_partition_size(i + 1, start, start + length, sys);
+               print_partition_size(cxt, i + 1, start, start + length, sys);
 }
 
 static void
-sgi_set_entire(void) {
+sgi_set_entire(struct fdisk_context *cxt) {
        int n;
 
        for (n=10; n<partitions; n++) {
                if (!sgi_get_num_sectors(n)) {
-                       sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
+                       sgi_set_partition(cxt, n, 0, sgi_get_lastblock(), SGI_VOLUME);
                        break;
                }
        }
@@ -588,7 +589,7 @@ sgi_set_entire(void) {
 
 static
 void
-sgi_set_volhdr(void)
+sgi_set_volhdr(struct fdisk_context *cxt)
 {
        int n;
 
@@ -599,20 +600,20 @@ sgi_set_volhdr(void)
                         * as IRIX fx uses.
                         */
                        if (4096 < sgi_get_lastblock())
-                               sgi_set_partition(n, 0, 4096, SGI_VOLHDR);
+                               sgi_set_partition(cxt, n, 0, 4096, SGI_VOLHDR);
                        break;
                }
        }
 }
 
 void
-sgi_delete_partition(int i)
+sgi_delete_partition(struct fdisk_context *cxt, int i)
 {
-       sgi_set_partition(i, 0, 0, 0);
+       sgi_set_partition(cxt, i, 0, 0, 0);
 }
 
 void
-sgi_add_partition(int n, int sys)
+sgi_add_partition(struct fdisk_context *cxt, int n, int sys)
 {
        char mesg[256];
        unsigned int first=0, last=0;
@@ -630,8 +631,8 @@ sgi_add_partition(int n, int sys)
        if ((sgi_entire() == -1)
            &&  (sys != SGI_VOLUME)) {
                printf(_("Attempting to generate entire disk entry automatically.\n"));
-               sgi_set_entire();
-               sgi_set_volhdr();
+               sgi_set_entire(cxt);
+               sgi_set_volhdr(cxt);
        }
        if ((sgi_gaps() == 0) &&  (sys != SGI_VOLUME)) {
                printf(_("The entire disk is already covered with partitions.\n"));
@@ -645,7 +646,7 @@ sgi_add_partition(int n, int sys)
        for (;;) {
                if (sys == SGI_VOLUME) {
                        last = sgi_get_lastblock();
-                       first = read_int(0, 0, last-1, 0, mesg);
+                       first = read_int(cxt, 0, 0, last-1, 0, mesg);
                        if (first != 0) {
                                printf(_("It is highly recommended that eleventh partition\n"
                                         "covers the entire disk and is of type `SGI volume'\n"));
@@ -653,7 +654,7 @@ sgi_add_partition(int n, int sys)
                } else {
                        first = freelist[0].first;
                        last  = freelist[0].last;
-                       first = read_int(scround(first), scround(first), scround(last)-1,
+                       first = read_int(cxt, scround(first), scround(first), scround(last)-1,
                                         0, mesg);
                }
                if (display_in_cyl_units)
@@ -669,7 +670,7 @@ sgi_add_partition(int n, int sys)
                        break;
        }
        snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
-       last = read_int(scround(first), scround(last)-1, scround(last)-1,
+       last = read_int(cxt, scround(first), scround(last)-1, scround(last)-1,
                        scround(first), mesg)+1;
        if (display_in_cyl_units)
                last *= units_per_sector;                                     
@@ -678,7 +679,7 @@ sgi_add_partition(int n, int sys)
        if ((sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock()))
                printf(_("It is highly recommended that eleventh partition\n"
                         "covers the entire disk and is of type `SGI volume'\n"));
-       sgi_set_partition(n, first, last-first, sys);
+       sgi_set_partition(cxt, n, first, last-first, sys);
 }
 
 void
@@ -695,7 +696,7 @@ create_sgilabel(struct fdisk_context *cxt)
        int res;                /* the result from the ioctl */
        int sec_fac;            /* the sector factor */
 
-       sec_fac = sector_size / 512;    /* determine the sector factor */
+       sec_fac = cxt->sector_size / 512;       /* determine the sector factor */
 
        fprintf(stderr,
                _("Building a new SGI disklabel.\n"));
@@ -769,7 +770,7 @@ create_sgilabel(struct fdisk_context *cxt)
        sgilabel->devparam.unused1                      = SSWAP16(0);
        sgilabel->devparam.nsect                        = SSWAP16(geometry.sectors);
        /* sectors/track */
-       sgilabel->devparam.bytes                        = SSWAP16(sector_size);
+       sgilabel->devparam.bytes                        = SSWAP16(cxt->sector_size);
        sgilabel->devparam.ilfact                       = SSWAP16(1);
        sgilabel->devparam.flags                        = SSWAP32(TRACK_FWD|\
                                                                  IGNORE_ERRORS|RESEEK);
@@ -787,11 +788,11 @@ create_sgilabel(struct fdisk_context *cxt)
        disklabel  = SGI_LABEL;
        partitions = 16;
        volumes    = 15;
-       sgi_set_entire();
-       sgi_set_volhdr();
+       sgi_set_entire(cxt);
+       sgi_set_volhdr(cxt);
        for (i = 0; i < 4; i++) {
                if (old[i].sysid) {
-                       sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
+                       sgi_set_partition(cxt, i, old[i].start, old[i].nsect, old[i].sysid);
                }
        }
 }
index 3a11499adfd4a03f775f33a8f104ec27c0f18dd9..7611d327a0c522de33a74a97879d37ffbe9c6619 100644 (file)
@@ -118,8 +118,8 @@ extern int  sgi_change_sysid( int i, int sys );
 extern unsigned int    sgi_get_start_sector( int i );
 extern unsigned int    sgi_get_num_sectors( int i );
 extern int     sgi_get_sysid( int i );
-extern void    sgi_delete_partition( int i );
-extern void    sgi_add_partition( int n, int sys );
+extern void    sgi_delete_partition( struct fdisk_context *cxt, int i );
+extern void    sgi_add_partition( struct fdisk_context *cxt, int n, int sys );
 extern void    create_sgilabel( struct fdisk_context *cxt );
 extern void    create_sgiinfo( void );
 extern int     verify_sgi( int verbose );
index 9d5b3e8d265c9947b60c4aec793a8cf7612dd703..ae24e161175b16bdaa573afdaa060687c8869774 100644 (file)
@@ -59,7 +59,8 @@ static inline uint32_t __swap32(uint32_t x) {
 #define SSWAP32(x) (other_endian ? __swap32(x) \
                                 : (uint32_t)(x))
 
-static void set_sun_partition(int i, uint32_t start, uint32_t stop, uint16_t sysid)
+static void set_sun_partition(struct fdisk_context *cxt,
+                             int i, uint32_t start, uint32_t stop, uint16_t sysid)
 {
        sunlabel->part_tags[i].tag = SSWAP16(sysid);
        sunlabel->part_tags[i].flag = SSWAP16(0);
@@ -68,7 +69,7 @@ static void set_sun_partition(int i, uint32_t start, uint32_t stop, uint16_t sys
        sunlabel->partitions[i].num_sectors =
                SSWAP32(stop - start);
        set_changed(i);
-       print_partition_size(i + 1, start, stop, sysid);
+       print_partition_size(cxt, i + 1, start, stop, sysid);
 }
 
 static void init(void)
@@ -173,7 +174,7 @@ void create_sunlabel(struct fdisk_context *cxt)
        sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
 
        res = blkdev_get_sectors(cxt->dev_fd, &llsectors);
-       sec_fac = sector_size / 512;
+       sec_fac = cxt->sector_size / 512;
 
 #ifdef HDIO_GETGEO
        if (!ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry)) {
@@ -195,9 +196,9 @@ void create_sunlabel(struct fdisk_context *cxt)
        } else
 #endif
        {
-               heads = read_int(1,1,1024,0,_("Heads"));
-               sectors = read_int(1,1,1024,0,_("Sectors/track"));
-               cylinders = read_int(1,1,65535,0,_("Cylinders"));
+               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"));
        }
 
        sunlabel->acyl   = SSWAP16(2);
@@ -220,14 +221,14 @@ void create_sunlabel(struct fdisk_context *cxt)
        } else
                ndiv = cylinders * 2 / 3;
 
-       set_sun_partition(0, 0, ndiv * heads * sectors,
+       set_sun_partition(cxt, 0, 0, ndiv * heads * sectors,
                          SUN_TAG_LINUX_NATIVE);
-       set_sun_partition(1, ndiv * heads * sectors,
+       set_sun_partition(cxt, 1, ndiv * heads * sectors,
                          cylinders * heads * sectors,
                          SUN_TAG_LINUX_SWAP);
        sunlabel->part_tags[1].flag |= SSWAP16(SUN_FLAG_UNMNT);
 
-       set_sun_partition(2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
+       set_sun_partition(cxt, 2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
 
        {
                unsigned short *ush = (unsigned short *)sunlabel;
@@ -363,7 +364,7 @@ void verify_sun(void)
         printf(_("Unused gap - sectors %d-%d\n"), start, stop);
 }
 
-void add_sun_partition(int n, int sys)
+void add_sun_partition(struct fdisk_context *cxt, int n, int sys)
 {
        uint32_t starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS];
        struct sun_partition *part = &sunlabel->partitions[n];
@@ -394,9 +395,9 @@ void add_sun_partition(int n, int sys)
        snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
        for (;;) {
                if (whole_disk)
-                       first = read_int(0, 0, 0, 0, mesg);
+                       first = read_int(cxt, 0, 0, 0, 0, mesg);
                else
-                       first = read_int(scround(start), scround(stop)+1,
+                       first = read_int(cxt, scround(start), scround(stop)+1,
                                         scround(stop), 0, mesg);
                if (display_in_cyl_units)
                        first *= units_per_sector;
@@ -451,13 +452,13 @@ and is of type `Whole disk'\n"));
                 _("Last %s or +size or +sizeM or +sizeK"),
                 str_units(SINGULAR));
        if (whole_disk)
-               last = read_int(scround(stop2), scround(stop2), scround(stop2),
+               last = read_int(cxt, scround(stop2), scround(stop2), scround(stop2),
                                0, mesg);
        else if (n == 2 && !first)
-               last = read_int(scround(first), scround(stop2), scround(stop2),
+               last = read_int(cxt, scround(first), scround(stop2), scround(stop2),
                                scround(first), mesg);
        else
-               last = read_int(scround(first), scround(stop), scround(stop),
+               last = read_int(cxt, scround(first), scround(stop), scround(stop),
                                scround(first), mesg);
        if (display_in_cyl_units)
                last *= units_per_sector;
@@ -480,7 +481,7 @@ and is of type `Whole disk'\n"));
        if (whole_disk)
                sys = SUN_TAG_BACKUP;
 
-       set_sun_partition(n, first, last, sys);
+       set_sun_partition(cxt, n, first, last, sys);
 }
 
 void sun_delete_partition(int i)
@@ -586,10 +587,10 @@ void sun_list_table(struct fdisk_context *cxt, int xtra)
        }
 }
 
-void sun_set_alt_cyl(void)
+void sun_set_alt_cyl(struct fdisk_context *cxt)
 {
        sunlabel->acyl =
-               SSWAP16(read_int(0,SSWAP16(sunlabel->acyl), 65535, 0,
+               SSWAP16(read_int(cxt, 0,SSWAP16(sunlabel->acyl), 65535, 0,
                                 _("Number of alternate cylinders")));
 }
 
@@ -598,31 +599,31 @@ void sun_set_ncyl(int cyl)
        sunlabel->ncyl = SSWAP16(cyl);
 }
 
-void sun_set_xcyl(void)
+void sun_set_xcyl(struct fdisk_context *cxt)
 {
        sunlabel->apc =
-               SSWAP16(read_int(0, SSWAP16(sunlabel->apc), sectors, 0,
+               SSWAP16(read_int(cxt, 0, SSWAP16(sunlabel->apc), sectors, 0,
                                 _("Extra sectors per cylinder")));
 }
 
-void sun_set_ilfact(void)
+void sun_set_ilfact(struct fdisk_context *cxt)
 {
        sunlabel->intrlv =
-               SSWAP16(read_int(1, SSWAP16(sunlabel->intrlv), 32, 0,
+               SSWAP16(read_int(cxt, 1, SSWAP16(sunlabel->intrlv), 32, 0,
                                 _("Interleave factor")));
 }
 
-void sun_set_rspeed(void)
+void sun_set_rspeed(struct fdisk_context *cxt)
 {
        sunlabel->rpm =
-               SSWAP16(read_int(1, SSWAP16(sunlabel->rpm), 100000, 0,
+               SSWAP16(read_int(cxt, 1, SSWAP16(sunlabel->rpm), 100000, 0,
                                 _("Rotation speed (rpm)")));
 }
 
-void sun_set_pcylcount(void)
+void sun_set_pcylcount(struct fdisk_context *cxt)
 {
        sunlabel->pcyl =
-               SSWAP16(read_int(0, SSWAP16(sunlabel->pcyl), 65535, 0,
+               SSWAP16(read_int(cxt, 0, SSWAP16(sunlabel->pcyl), 65535, 0,
                                 _("Number of physical cylinders")));
 }
 
index f33fe1cf57a50fb2ccc7b4d484116ed10bcb7d06..8cb13ec17dfd41dc2597ee5a930144d660aa3057 100644 (file)
@@ -84,14 +84,14 @@ extern void sun_delete_partition(int i);
 extern int sun_change_sysid(int i, uint16_t sys);
 extern void sun_list_table(struct fdisk_context *cxt, int xtra);
 extern void verify_sun(void);
-extern void add_sun_partition(int n, int sys);
+extern void add_sun_partition(struct fdisk_context *cxt, int n, int sys);
 extern void sun_write_table(struct fdisk_context *cxt);
-extern void sun_set_alt_cyl(void);
+extern void sun_set_alt_cyl(struct fdisk_context *cxt);
 extern void sun_set_ncyl(int cyl);
-extern void sun_set_xcyl(void);
-extern void sun_set_ilfact(void);
-extern void sun_set_rspeed(void);
-extern void sun_set_pcylcount(void);
+extern void sun_set_xcyl(struct fdisk_context *cxt);
+extern void sun_set_ilfact(struct fdisk_context *cxt);
+extern void sun_set_rspeed(struct fdisk_context *cxt);
+extern void sun_set_pcylcount(struct fdisk_context *cxt);
 extern void toggle_sunflags(int i, uint16_t mask);
 extern int sun_get_sysid(int i);
 
index 3a12e2e2895ee38aef78750163ccd596f2a5ea53..5de4cab02bd50271d321a33ae19650fa9aee95a5 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#ifdef HAVE_LIBBLKID
+#include <blkid.h>
+#endif
 
+#include "nls.h"
+#include "blkdev.h"
 #include "common.h"
 #include "fdisk.h"
 
 int fdisk_debug_mask;
 
+static unsigned long __get_sector_size(int fd)
+{
+       unsigned int sect_sz;
+
+       if (!blkdev_get_sector_size(fd, &sect_sz))
+               return (unsigned long) sect_sz;
+       return DEFAULT_SECTOR_SIZE;
+}
+
+static int __discover_topology(struct fdisk_context *cxt)
+{
+#ifdef HAVE_LIBBLKID
+       blkid_probe pr;
+
+       pr = blkid_new_probe();
+       if (pr && blkid_probe_set_device(pr, cxt->dev_fd, 0, 0) == 0) {
+               blkid_topology tp = blkid_probe_get_topology(pr);
+
+               if (tp) {
+                       cxt->min_io_size = blkid_topology_get_minimum_io_size(tp);
+                       cxt->io_size = blkid_topology_get_optimal_io_size(tp);
+                       cxt->phy_sector_size = blkid_topology_get_physical_sector_size(tp);
+                       cxt->alignment_offset = blkid_topology_get_alignment_offset(tp);
+
+                       if (!cxt->io_size)
+                               /* optimal IO is optional, default to minimum IO */
+                               cxt->io_size = cxt->min_io_size;
+               }
+       }
+       blkid_free_probe(pr);
+#endif
+
+       /* no blkid or error, use default values */
+       if (!cxt->min_io_size)      cxt->min_io_size = DEFAULT_SECTOR_SIZE;
+       if (!cxt->io_size)          cxt->io_size = DEFAULT_SECTOR_SIZE;
+
+       cxt->sector_size = __get_sector_size(cxt->dev_fd);
+       if (!cxt->phy_sector_size) /* could not discover physical size */
+               cxt->phy_sector_size = cxt->sector_size;
+       if (cxt->sector_size != DEFAULT_SECTOR_SIZE)
+               printf(_("Note: sector size is %ld (not %d)\n"),
+                      cxt->sector_size, DEFAULT_SECTOR_SIZE);
+
+       return 0;
+}
+
+/**
+ * fdisk_dev_has_topology:
+ * @cxt: fdisk context
+ *
+ * Returns 1 if the device provides topology information, otherwise 0.
+ */
+int fdisk_dev_has_topology(struct fdisk_context *cxt)
+{
+       /*
+        * Assume that the device provides topology info if
+        * optimal_io_size is set or alignment_offset is set or
+        * minimum_io_size is not power of 2.
+        */
+       if (cxt->io_size || cxt->alignment_offset ||
+           (cxt->min_io_size & (cxt->min_io_size - 1)))
+               return 1;
+       return 0;
+}
+
 /**
  * fdisk_init_debug:
  * @mask: debug mask (0xffff to enable full debuging)
@@ -81,9 +151,10 @@ struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int rea
        cxt->dev_path = strdup(fname);
        if (!cxt->dev_path)
                goto fail;
+       __discover_topology(cxt);
 
        DBG(CONTEXT, dbgprint("context initialized for %s [%s]",
-                       fname, readonly ? "READ-ONLY" : "READ-WRITE"));
+                             fname, readonly ? "READ-ONLY" : "READ-WRITE"));
        return cxt;
 fail:
        errsv = errno;