]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: (gpt) don't offer first sector before the first partion
authorKarel Zak <kzak@redhat.com>
Mon, 10 Nov 2014 13:01:09 +0000 (14:01 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 10 Nov 2014 13:01:09 +0000 (14:01 +0100)
The GPT first usable LBA is usually aligned to grain (1MiB), but for small
(<=4MiB) devices we strictly follow sector sizes.

In this case there is a small space in front of the aligned begin of
the first partition. This useless space should not be offered for the
next partitions.

Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 32768 bytes
Disklabel type: gpt
Disk identifier: 041E2D54-AD0C-4C7E-A50D-363D23058D47

Device    Start          End Size Type
/dev/sdb1    40         2087   1M Linux filesystem

Command (m for help): n
Partition number (2-128, default 2):
First sector (34-8158, default 2088):
                      ^^

first usable LBA is 34, but first aligned (recommended) LBA is 40, we
use it for the first partition. All this is correct, but the space
before the first partition should be ignored. Fixed version:

        Command (m for help): n
Partition number (2-128, default 2):
First sector (2088-8158, default 2088):
                      ^^^^

Note this problem does not exist for "normal" (large) devices where
first usable LBA is aligned to grain.

Reported-by: Boaz Harrosh <boaz@plexistor.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/src/gpt.c

index 8239c53aa911ee117ed6f1d6830c546d24c005e0..ecf62d2d4f90ed198549a7f66cbc7001873d82a1 100644 (file)
@@ -1945,7 +1945,31 @@ static int gpt_add_partition(
                                pa->type->typestr:
                                GPT_DEFAULT_ENTRY_TYPE, &typeid);
 
-       disk_f = find_first_available(pheader, ents, 0);
+       disk_f = find_first_available(pheader, ents, pheader->first_usable_lba);
+
+       /* if first sector no explicitly defined then ignore small gaps before
+        * the first partition */
+       if ((!pa || !fdisk_partition_has_start(pa))
+           && !partition_unused(&ents[0])
+           && disk_f < gpt_partition_start(&ents[0])) {
+
+               do {
+                       uint64_t x;
+                       DBG(LABEL, ul_debug("testing first sector %ju", disk_f));
+                       disk_f = find_first_available(pheader, ents, disk_f);
+                       if (!disk_f)
+                               break;
+                       x = find_last_free(pheader, ents, disk_f);
+                       if (x - disk_f >= cxt->grain / cxt->sector_size)
+                               break;
+                       DBG(LABEL, ul_debug("first sector %ju addresses to small space, continue...", disk_f));
+                       disk_f = x + 1;
+               } while(1);
+
+               if (disk_f == 0)
+                       disk_f = find_first_available(pheader, ents, pheader->first_usable_lba);
+       }
+
        disk_l = find_last_free_sector(pheader, ents);
 
        /* the default is the largest free space */