]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: (dos) fix last possible sector calculation
authorKarel Zak <kzak@redhat.com>
Thu, 11 Feb 2021 10:49:56 +0000 (11:49 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 11 Feb 2021 11:18:34 +0000 (12:18 +0100)
* rename 'last' to 'first' as we use this value as the first available free
  sector rather than last used

* use '-1' when calculate last partition sector to compare with last
  disk sector

* improve debug messages

Fixes: https://github.com/karelzak/util-linux/issues/1249
Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/src/dos.c
libfdisk/src/table.c

index 82ccb6940308424b96fd578b1aa0e5e41267d089..463886e172f09297474aa1f7952c2c458bd86070 100644 (file)
@@ -1729,7 +1729,7 @@ static int dos_add_partition(struct fdisk_context *cxt,
 {
        size_t i;
        uint8_t free_primary = 0, free_sectors = 0;
-       fdisk_sector_t last = 0, grain;
+       fdisk_sector_t first = 0, grain;
        int rc = 0;
        struct fdisk_dos_label *l;
        struct pte *ext_pe;
@@ -1827,32 +1827,41 @@ static int dos_add_partition(struct fdisk_context *cxt,
 
        /* check if there is space for primary partition */
        grain = cxt->grain > cxt->sector_size ? cxt->grain / cxt->sector_size : 1;
-       last = cxt->first_lba;
+       first = cxt->first_lba;
 
        if (cxt->parent && fdisk_is_label(cxt->parent, GPT)) {
                /* modifying a hybrid MBR, which throws out the rules */
                grain = 1;
-               last = 1;
+               first = 1;
        }
 
+       /* set @first after the last used partition, set @free_sectors if there
+        * is gap in front if the first partition or between used parrtitions. */
        for (i = 0; i < 4; i++) {
                struct dos_partition *p = self_partition(cxt, i);
 
                assert(p);
                if (is_used_partition(p)) {
                        fdisk_sector_t start = dos_partition_get_start(p);
-                       if (last + grain <= start)
+                       if (first + grain <= start)
                                free_sectors = 1;
-                       last = start + dos_partition_get_size(p);
+                       first = start + dos_partition_get_size(p);
                } else
                        free_primary++;
        }
-       if (last + grain < cxt->total_sectors - 1)
+
+       /* set @free_sectors if there is a space after the first usable sector */
+       if (first + grain - 1 <= cxt->total_sectors - 1)
                free_sectors = 1;
 
+       DBG(LABEL, ul_debug("DOS: primary: first free: %ju, last on disk: %ju, "
+                           "free_sectors=%d, free_primary=%d",
+                               (uintmax_t) first,
+                               (uintmax_t) cxt->total_sectors - 1,
+                               free_sectors, free_primary));
 
        if (!free_primary || !free_sectors) {
-               DBG(LABEL, ul_debug("DOS: primary impossible, add logical"));
+               DBG(LABEL, ul_debug("DOS: primary impossible"));
                if (l->ext_offset) {
                        if (!pa || fdisk_partition_has_start(pa)) {
                                /* See above case A); here we have start, but
@@ -1869,6 +1878,7 @@ static int dos_add_partition(struct fdisk_context *cxt,
                                }
                                fdisk_info(cxt, msg);
                        }
+                       DBG(LABEL, ul_debug("DOS: tring logical"));
                        rc = add_logical(cxt, pa, &res);
                } else {
                        if (free_primary)
index b814a1f4cb3b4d4c6f9074158c87752790109ce7..84c60d448e447c295c46579786fde684df3de1a2 100644 (file)
@@ -235,8 +235,8 @@ int fdisk_table_add_partition(struct fdisk_table *tb, struct fdisk_partition *pa
        DBG(TAB, ul_debugobj(tb, "add entry %p [start=%ju, end=%ju, size=%ju, %s %s %s]",
                        pa,
                        (uintmax_t) fdisk_partition_get_start(pa),
-                       (uintmax_t) fdisk_partition_get_end(pa),
-                       (uintmax_t) fdisk_partition_get_size(pa),
+                       fdisk_partition_has_end(pa) ? (uintmax_t) fdisk_partition_get_end(pa) : 0,
+                       fdisk_partition_has_size(pa) ? (uintmax_t) fdisk_partition_get_size(pa) : 0,
                        fdisk_partition_is_freespace(pa) ? "freespace" : "",
                        fdisk_partition_is_nested(pa)    ? "nested"    : "",
                        fdisk_partition_is_container(pa) ? "container" : "primary"));