]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: add topology and geometry functions
authorKarel Zak <kzak@redhat.com>
Thu, 6 Dec 2012 11:12:41 +0000 (12:12 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 11 Mar 2013 10:20:41 +0000 (11:20 +0100)
 - rename __discovery_* to fdisk_discovery_*
 - rename fdisk_context_force_sector_size() to fdisk_override_sector_size()
 - rename fdisk_context_set_user_geometry() to fdisk_override_geometry()

 - remove non-default sector size warning

Signed-off-by: Karel Zak <kzak@redhat.com>
fdisks/fdisk.c
fdisks/fdisk.h
fdisks/utils.c
libfdisk/src/alignment.c
libfdisk/src/fdiskP.h

index f34617f08e25719a48744e70b84edefb5c3314ff..866d8fe21cbf4dc7a12d7263e251ab8d2b850389 100644 (file)
@@ -1301,7 +1301,7 @@ expert_command_prompt(struct fdisk_context *cxt)
                case 'c':
                        user_cylinders = read_int(cxt, 1, cxt->geom.cylinders, 1048576, 0,
                                         _("Number of cylinders"));
-                       fdisk_context_set_user_geometry(cxt, user_cylinders, user_heads, user_sectors);
+                       fdisk_override_geometry(cxt, user_cylinders, user_heads, user_sectors);
                        if (fdisk_is_disklabel(cxt, SUN))
                                sun_set_ncyl(cxt, cxt->geom.cylinders);
                        break;
@@ -1327,7 +1327,7 @@ expert_command_prompt(struct fdisk_context *cxt)
                case 'h':
                        user_heads = read_int(cxt, 1, cxt->geom.heads, 256, 0,
                                         _("Number of heads"));
-                       fdisk_context_set_user_geometry(cxt, user_cylinders, user_heads, user_sectors);
+                       fdisk_override_geometry(cxt, user_cylinders, user_heads, user_sectors);
                        break;
                case 'i':
                        if (fdisk_is_disklabel(cxt, SUN))
@@ -1356,7 +1356,7 @@ expert_command_prompt(struct fdisk_context *cxt)
                                fprintf(stderr, _("Warning: setting "
                                        "sector offset for DOS "
                                        "compatibility\n"));
-                       fdisk_context_set_user_geometry(cxt, user_cylinders, user_heads, user_sectors);
+                       fdisk_override_geometry(cxt, user_cylinders, user_heads, user_sectors);
                        break;
                case 'v':
                        verify(cxt);
@@ -1396,10 +1396,10 @@ static void print_partition_table_from_option(char *device, unsigned long sector
                err(EXIT_FAILURE, _("cannot open %s"), device);
 
        if (sector_size) /* passed -b option, override autodiscovery */
-               fdisk_context_force_sector_size(cxt, sector_size);
+               fdisk_override_sector_size(cxt, sector_size);
 
        if (user_cylinders || user_heads || user_sectors)
-               fdisk_context_set_user_geometry(cxt, user_cylinders,
+               fdisk_override_geometry(cxt, user_cylinders,
                                        user_heads, user_sectors);
 
        if (!fdisk_dev_has_disklabel(cxt)) {
@@ -1697,18 +1697,14 @@ int main(int argc, char **argv)
                err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
 
        if (sector_size)        /* passed -b option, override autodiscovery */
-               fdisk_context_force_sector_size(cxt, sector_size);
+               fdisk_override_sector_size(cxt, sector_size);
 
        if (user_cylinders || user_heads || user_sectors)
-               fdisk_context_set_user_geometry(cxt, user_cylinders,
+               fdisk_override_geometry(cxt, user_cylinders,
                                                user_heads, user_sectors);
 
        print_welcome();
 
-       if (!fdisk_dev_sectsz_is_default(cxt))
-               printf(_("Note: sector size is %ld (not %d)\n"),
-                      cxt->sector_size, DEFAULT_SECTOR_SIZE);
-
        if (!fdisk_dev_has_disklabel(cxt)) {
                update_units(cxt);      /* to provide compatible 'p'rint output */
                fprintf(stderr,
index 4736bccb9b82d0b0703257d38a028e63afb9bb63..cdbc40886d35ff8864ffd84078c4abd86943f31b 100644 (file)
@@ -72,13 +72,7 @@ extern const struct fdisk_label sgi_label;
 extern const struct fdisk_label gpt_label;
 
 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 int fdisk_dev_sectsz_is_default(struct fdisk_context *cxt);
 extern void fdisk_free_context(struct fdisk_context *cxt);
-extern int fdisk_context_force_sector_size(struct fdisk_context *cxt, sector_t s);
-extern int fdisk_context_set_user_geometry(struct fdisk_context *cxt,
-                           unsigned int cylinders, unsigned int heads,
-                           unsigned int sectors);
 extern int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name);
 extern int fdisk_reset_alignment(struct fdisk_context *cxt);
 extern struct fdisk_parttype *fdisk_get_partition_type(struct fdisk_context *cxt, int partnum);
index 24f169efd03e0db2cb10b4039a0f2b9d5735b49c..15278bf7d2bb903c80dff529a4e48a9c7b43e76b 100644 (file)
@@ -69,262 +69,6 @@ static int __probe_labels(struct fdisk_context *cxt)
        return 1; /* not found */
 }
 
-static unsigned long __get_sector_size(int fd)
-{
-       int sect_sz;
-
-       if (!blkdev_get_sector_size(fd, &sect_sz))
-               return (unsigned long) sect_sz;
-       return DEFAULT_SECTOR_SIZE;
-}
-
-/**
- * fdisk_context_force_sector_size:
- * @cxt: fdisk context
- * @s: required sector size
- *
- * Overwrites logical and physical sector size. Note that the default sector
- * size is discovered by fdisk_new_context_from_device() from device topology.
- *
- * Don't use this function, rely on the default behavioer is more safe.
- *
- * Returns: 0 on success, < 0 on error.
- */
-int fdisk_context_force_sector_size(struct fdisk_context *cxt, sector_t s)
-{
-       if (!cxt)
-               return -EINVAL;
-
-       cxt->phy_sector_size = cxt->sector_size = s;
-       cxt->min_io_size = cxt->io_size = s;
-
-       fdisk_reset_alignment(cxt);
-       return 0;
-}
-
-static void recount_geometry(struct fdisk_context *cxt)
-{
-       cxt->geom.cylinders = cxt->total_sectors /
-               (cxt->geom.heads * cxt->geom.sectors);
-}
-
-/**
- * fdisk_context_set_user_geometry:
- * @cxt: fdisk context
- * @cylinders: user specified cylinders
- * @heads: user specified heads
- * @sectors: user specified sectors
- *
- * Overrides autodiscovery and apply user specified geometry.
- *
- * Returns: 0 on success, < 0 on error.
- */
-int fdisk_context_set_user_geometry(struct fdisk_context *cxt,
-                                   unsigned int cylinders,
-                                   unsigned int heads,
-                                   unsigned int sectors)
-{
-       if (!cxt)
-               return -EINVAL;
-       if (heads)
-               cxt->geom.heads = heads;
-       if (sectors)
-               cxt->geom.sectors = sectors;
-
-       if (cylinders)
-               cxt->geom.cylinders = cylinders;
-       else
-               recount_geometry(cxt);
-
-       fdisk_reset_alignment(cxt);
-       return 0;
-}
-
-/*
- * Generic (label independent) geometry
- */
-static int __discover_system_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));
-
-       /* what the kernel/bios thinks the geometry is */
-       blkdev_get_geometry(cxt->dev_fd, &h, &s);
-       if (!h && !s) {
-               /* unable to discover geometry, use default values */
-               s = 63;
-               h = 255;
-       }
-
-       /* obtained heads and sectors */
-       cxt->geom.heads = h;
-       cxt->geom.sectors = s;
-       recount_geometry(cxt);
-
-       DBG(GEOMETRY, dbgprint("geometry discovered for %s: C/H/S: %lld/%d/%lld",
-                              cxt->dev_path, cxt->geom.cylinders,
-                              cxt->geom.heads, cxt->geom.sectors));
-       return 0;
-}
-
-static int __discover_topology(struct fdisk_context *cxt)
-{
-#ifdef HAVE_LIBBLKID
-       blkid_probe pr;
-
-       DBG(TOPOLOGY, dbgprint("initialize libblkid prober"));
-
-       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->optimal_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);
-
-                       /* I/O size used by fdisk */
-                       cxt->io_size = cxt->optimal_io_size;
-                       if (!cxt->io_size)
-                               /* optimal IO is optional, default to minimum IO */
-                               cxt->io_size = cxt->min_io_size;
-               }
-       }
-       blkid_free_probe(pr);
-#endif
-
-       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;
-
-       /* no blkid or error, use default values */
-       if (!cxt->min_io_size)
-               cxt->min_io_size = cxt->sector_size;
-       if (!cxt->io_size)
-               cxt->io_size = cxt->sector_size;
-
-       DBG(TOPOLOGY, dbgprint("topology discovered for %s:\n"
-                              "\tlogical/physical sector sizes: %ld/%ld\n"
-                              "\tfdisk/minimal/optimal io sizes: %ld/%ld/%ld\n",
-                              cxt->dev_path, cxt->sector_size, cxt->phy_sector_size,
-                              cxt->io_size, cxt->optimal_io_size, cxt->min_io_size));
-       return 0;
-}
-
-/**
- * fdisk_dev_sectsz_is_default:
- * @cxt: fdisk context
- *
- * Returns 1 if the device's sector size is the default value, otherwise 0.
- */
-int fdisk_dev_sectsz_is_default(struct fdisk_context *cxt)
-{
-       if (!cxt)
-               return -EINVAL;
-
-       return cxt->sector_size == DEFAULT_SECTOR_SIZE;
-}
-
-/**
- * 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 &&
-           (cxt->optimal_io_size ||
-            cxt->alignment_offset ||
-            !is_power_of_2(cxt->min_io_size)))
-               return 1;
-       return 0;
-}
-
-/*
- * The LBA of the first partition is based on the device geometry and topology.
- * This offset is generic (and recommended) for all labels.
- *
- * Returns: 0 on error or number of logical sectors.
- */
-sector_t fdisk_topology_get_first_lba(struct fdisk_context *cxt)
-{
-       sector_t x = 0, res;
-
-       if (!cxt)
-               return 0;
-
-       if (!cxt->io_size)
-               __discover_topology(cxt);
-
-       /*
-        * Align the begin of partitions to:
-        *
-        * a) topology
-        *  a2) alignment offset
-        *  a1) or physical sector (minimal_io_size, aka "grain")
-        *
-        * b) or default to 1MiB (2048 sectrors, Windows Vista default)
-        *
-        * c) or for very small devices use 1 phy.sector
-        */
-       if (fdisk_dev_has_topology(cxt)) {
-               if (cxt->alignment_offset)
-                       x = cxt->alignment_offset;
-               else if (cxt->io_size > 2048 * 512)
-                       x = cxt->io_size;
-       }
-       /* default to 1MiB */
-       if (!x)
-               x = 2048 * 512;
-
-       res = x / cxt->sector_size;
-
-       /* don't use huge offset on small devices */
-       if (cxt->total_sectors <= res * 4)
-               res = cxt->phy_sector_size / cxt->sector_size;
-
-       return res;
-}
-
-/*
- * The LBA of the first partition is based on the device geometry and topology.
- * This offset is generic generic (and recommended) for all labels.
- *
- * Returns: 0 on error or number of bytes.
- */
-unsigned long fdisk_topology_get_grain(struct fdisk_context *cxt)
-{
-       unsigned long res;
-
-       if (!cxt)
-               return 0;
-
-       if (!cxt->io_size)
-               __discover_topology(cxt);
-
-       res = cxt->io_size;
-
-       /* use 1MiB grain always when possible */
-       if (res < 2048 * 512)
-               res = 2048 * 512;
-
-       /* don't use huge grain on small devices */
-       if (cxt->total_sectors <= (res * 4 / cxt->sector_size))
-               res = cxt->phy_sector_size;
-
-       return res;
-}
 
 /**
  * fdisk_reset_alignment:
@@ -437,8 +181,8 @@ struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int rea
        if (!cxt->dev_path)
                goto fail;
 
-       __discover_topology(cxt);
-       __discover_system_geometry(cxt);
+       fdisk_discover_topology(cxt);
+       fdisk_discover_geometry(cxt);
 
        if (fdisk_read_firstsector(cxt) < 0)
                goto fail;
index b0d38ae235f34b121676e3ad5a04f835d3dd4bf6..e06e1afb0fc592b6909281ef5ee10e63ae27f310 100644 (file)
@@ -1,6 +1,14 @@
 
+#ifdef HAVE_LIBBLKID
+#include <blkid.h>
+#endif
+#include "blkdev.h"
+
 #include "fdiskP.h"
 
+/* temporary */
+extern int fdisk_reset_alignment(struct fdisk_context *cxt);
+
 /*
  * Alignment according to logical granulity (usually 1MiB)
  */
@@ -99,3 +107,246 @@ void fdisk_warn_alignment(struct fdisk_context *cxt, sector_t lba, int partition
                printf(_("Partition %i does not start on physical sector boundary.\n"),
                        partition + 1);
 }
+
+static unsigned long get_sector_size(int fd)
+{
+       int sect_sz;
+
+       if (!blkdev_get_sector_size(fd, &sect_sz))
+               return (unsigned long) sect_sz;
+       return DEFAULT_SECTOR_SIZE;
+}
+
+/**
+ * fdisk_override_sector_size:
+ * @cxt: fdisk context
+ * @s: required sector size
+ *
+ * Overwrites logical and physical sector size. Note that the default sector
+ * size is discovered by fdisk_new_context_from_device() from device topology.
+ *
+ * Don't use this function, rely on the default behavioer is more safe.
+ *
+ * Returns: 0 on success, < 0 on error.
+ */
+int fdisk_override_sector_size(struct fdisk_context *cxt, sector_t s)
+{
+       if (!cxt)
+               return -EINVAL;
+
+       cxt->phy_sector_size = cxt->sector_size = s;
+       cxt->min_io_size = cxt->io_size = s;
+
+       fdisk_reset_alignment(cxt);
+       return 0;
+}
+
+static void recount_geometry(struct fdisk_context *cxt)
+{
+       cxt->geom.cylinders = cxt->total_sectors /
+               (cxt->geom.heads * cxt->geom.sectors);
+}
+
+/**
+ * fdisk_override_geometry:
+ * @cxt: fdisk context
+ * @cylinders: user specified cylinders
+ * @heads: user specified heads
+ * @sectors: user specified sectors
+ *
+ * Overrides autodiscovery and apply user specified geometry.
+ *
+ * Returns: 0 on success, < 0 on error.
+ */
+int fdisk_override_geometry(struct fdisk_context *cxt,
+                           unsigned int cylinders,
+                           unsigned int heads,
+                           unsigned int sectors)
+{
+       if (!cxt)
+               return -EINVAL;
+       if (heads)
+               cxt->geom.heads = heads;
+       if (sectors)
+               cxt->geom.sectors = sectors;
+
+       if (cylinders)
+               cxt->geom.cylinders = cylinders;
+       else
+               recount_geometry(cxt);
+
+       fdisk_reset_alignment(cxt);
+       return 0;
+}
+
+/*
+ * Generic (label independent) geometry
+ */
+int fdisk_discover_geometry(struct fdisk_context *cxt)
+{
+       sector_t nsects;
+       unsigned int h = 0, s = 0;
+
+       assert(cxt);
+       assert(!cxt->geom.heads);
+
+       /* 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));
+
+       /* what the kernel/bios thinks the geometry is */
+       blkdev_get_geometry(cxt->dev_fd, &h, &s);
+       if (!h && !s) {
+               /* unable to discover geometry, use default values */
+               s = 63;
+               h = 255;
+       }
+
+       /* obtained heads and sectors */
+       cxt->geom.heads = h;
+       cxt->geom.sectors = s;
+       recount_geometry(cxt);
+
+       DBG(GEOMETRY, dbgprint("geometry discovered for %s: C/H/S: %lld/%d/%lld",
+                              cxt->dev_path, cxt->geom.cylinders,
+                              cxt->geom.heads, cxt->geom.sectors));
+       return 0;
+}
+
+int fdisk_discover_topology(struct fdisk_context *cxt)
+{
+       assert(cxt);
+       assert(cxt->sector_size == 0);
+
+#ifdef HAVE_LIBBLKID
+       blkid_probe pr;
+
+       DBG(TOPOLOGY, dbgprint("initialize libblkid prober"));
+
+       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->optimal_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);
+
+                       /* I/O size used by fdisk */
+                       cxt->io_size = cxt->optimal_io_size;
+                       if (!cxt->io_size)
+                               /* optimal IO is optional, default to minimum IO */
+                               cxt->io_size = cxt->min_io_size;
+               }
+       }
+       blkid_free_probe(pr);
+#endif
+
+       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;
+
+       /* no blkid or error, use default values */
+       if (!cxt->min_io_size)
+               cxt->min_io_size = cxt->sector_size;
+       if (!cxt->io_size)
+               cxt->io_size = cxt->sector_size;
+
+       DBG(TOPOLOGY, dbgprint("topology discovered for %s:\n"
+                              "\tlogical/physical sector sizes: %ld/%ld\n"
+                              "\tfdisk/minimal/optimal io sizes: %ld/%ld/%ld\n",
+                              cxt->dev_path, cxt->sector_size, cxt->phy_sector_size,
+                              cxt->io_size, cxt->optimal_io_size, cxt->min_io_size));
+       return 0;
+}
+
+static int 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 &&
+           (cxt->optimal_io_size ||
+            cxt->alignment_offset ||
+            !is_power_of_2(cxt->min_io_size)))
+               return 1;
+       return 0;
+}
+
+/*
+ * The LBA of the first partition is based on the device geometry and topology.
+ * This offset is generic (and recommended) for all labels.
+ *
+ * Returns: 0 on error or number of logical sectors.
+ */
+sector_t fdisk_topology_get_first_lba(struct fdisk_context *cxt)
+{
+       sector_t x = 0, res;
+
+       if (!cxt)
+               return 0;
+
+       if (!cxt->io_size)
+               fdisk_discover_topology(cxt);
+
+       /*
+        * Align the begin of partitions to:
+        *
+        * a) topology
+        *  a2) alignment offset
+        *  a1) or physical sector (minimal_io_size, aka "grain")
+        *
+        * b) or default to 1MiB (2048 sectrors, Windows Vista default)
+        *
+        * c) or for very small devices use 1 phy.sector
+        */
+       if (has_topology(cxt)) {
+               if (cxt->alignment_offset)
+                       x = cxt->alignment_offset;
+               else if (cxt->io_size > 2048 * 512)
+                       x = cxt->io_size;
+       }
+       /* default to 1MiB */
+       if (!x)
+               x = 2048 * 512;
+
+       res = x / cxt->sector_size;
+
+       /* don't use huge offset on small devices */
+       if (cxt->total_sectors <= res * 4)
+               res = cxt->phy_sector_size / cxt->sector_size;
+
+       return res;
+}
+
+/*
+ * The LBA of the first partition is based on the device geometry and topology.
+ * This offset is generic generic (and recommended) for all labels.
+ *
+ * Returns: 0 on error or number of bytes.
+ */
+unsigned long fdisk_topology_get_grain(struct fdisk_context *cxt)
+{
+       unsigned long res;
+
+       if (!cxt)
+               return 0;
+
+       if (!cxt->io_size)
+               fdisk_discover_topology(cxt);
+
+       res = cxt->io_size;
+
+       /* use 1MiB grain always when possible */
+       if (res < 2048 * 512)
+               res = 2048 * 512;
+
+       /* don't use huge grain on small devices */
+       if (cxt->total_sectors <= (res * 4 / cxt->sector_size))
+               res = cxt->phy_sector_size;
+
+       return res;
+}
index 4f5585733abb2f90b9cf542109a70b2967239882..e9c21ca898cbd8c12fea96a09655e18fab12a199 100644 (file)
@@ -192,6 +192,14 @@ extern sector_t fdisk_align_lba_in_range(struct fdisk_context *cxt, sector_t lba
                                         sector_t start, sector_t stop);
 
 
+extern int fdisk_override_sector_size(struct fdisk_context *cxt, sector_t s);
+extern int fdisk_override_geometry(struct fdisk_context *cxt,
+                           unsigned int cylinders, unsigned int heads,
+                            unsigned int sectors);
+
+extern int fdisk_discover_geometry(struct fdisk_context *cxt);
+extern int fdisk_discover_topology(struct fdisk_context *cxt);
+
 /* utils.c */
 extern void fdisk_zeroize_firstsector(struct fdisk_context *cxt);
 extern int fdisk_read_firstsector(struct fdisk_context *cxt);