]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fdisk: remove global variable sector_offset
authorKarel Zak <kzak@redhat.com>
Mon, 3 Dec 2012 14:32:16 +0000 (15:32 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Dec 2012 14:48:31 +0000 (15:48 +0100)
 - add cxt->first_lba as replacement to sector_offset
 - add label->reset_alignment() to overwrite the default alignment setting
 - add fdisk_reset_alignment() to setup grain, first LBA offset, etc.

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

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