]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: fix partition move/resize code
authorKarel Zak <kzak@redhat.com>
Thu, 17 Sep 2015 10:27:58 +0000 (12:27 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 17 Sep 2015 11:22:11 +0000 (13:22 +0200)
- verify that the new partition fits to the area if the size of the
  has not been modified
- fix remaining space calculation (yes, brown-paper-bag bug..)
- offer also space before first partition as free space

Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/src/partition.c
libfdisk/src/table.c

index 001fa356e6c7fd947548eee7aef3ab25c02d5f08..2031e330812ba02cd566606a3ac6fe47cd0781b3 100644 (file)
@@ -971,13 +971,16 @@ static int resize_get_last_possible(
                    fdisk_partition_is_container(pa))
                        continue;
 
+               DBG(PART, ul_debugobj(pa, "checking start=%ju, size=%ju", pa->start, pa->size));
+
                if (!last) {
                        if (start >= pa->start &&  start < pa->start + pa->size) {
                                if (fdisk_partition_is_freespace(pa) || pa == cur)
                                        last = pa;
                                else
                                        break;
-                               *maxsz = pa->size - (pa->start - start);
+
+                               *maxsz = pa->size - (start - pa->start);
                        }
                } else if (!fdisk_partition_is_freespace(pa) && pa != cur) {
                        break;
@@ -989,8 +992,10 @@ static int resize_get_last_possible(
 
        if (last)
                DBG(PART, ul_debugobj(cur, "resize: max size=%ju", (uintmax_t) *maxsz));
-       return last ? 0 : -1;
+       else
+               DBG(PART, ul_debugobj(cur, "resize: nothing usable after %ju", (uintmax_t) start));
 
+       return last ? 0 : -1;
 }
 
 /*
@@ -1001,7 +1006,7 @@ static int recount_resize(
                        struct fdisk_context *cxt, size_t partno,
                        struct fdisk_partition *res, struct fdisk_partition *tpl)
 {
-       fdisk_sector_t start, size;
+       fdisk_sector_t start, size, xsize;
        struct fdisk_partition *cur = NULL;
        struct fdisk_table *tb = NULL;
        int rc;
@@ -1086,15 +1091,20 @@ static int recount_resize(
        }
 
        /* 4) verify that size is within the current partition or next free space */
-       if (!FDISK_IS_UNDEF(size)) {
+       xsize = !FDISK_IS_UNDEF(size) ? size : fdisk_partition_get_size(cur);
+
+       if (fdisk_partition_has_size(cur)) {
                fdisk_sector_t maxsz;
+
                if (resize_get_last_possible(tb, cur, start, &maxsz))
                        goto erange;
-               DBG(PART, ul_debugobj(tpl, "resize: size wanted=%ju, max=%ju",
-                                       (uintmax_t) size, (uintmax_t) maxsz));
-               if (size > maxsz)
+               DBG(PART, ul_debugobj(tpl, "resize: size=%ju, max=%ju",
+                                       (uintmax_t) xsize, (uintmax_t) maxsz));
+               if (xsize > maxsz)
                        goto erange;
-       } else {
+       }
+
+       if (!FDISK_IS_UNDEF(size)) {
                DBG(PART, ul_debugobj(tpl, "resize: size unchanged (undefined)"));
        }
 
index 9921733d474bf9cdd1fc46b0eee52171fc943df1..1a3d47a7cc83f3d3fea317ebb35e27ff24d1ff7f 100644 (file)
@@ -597,7 +597,12 @@ int fdisk_get_freespaces(struct fdisk_context *cxt, struct fdisk_table **tb)
                                        pa->partno,
                                        (uintmax_t) fdisk_partition_get_start(pa),
                                        (uintmax_t) fdisk_partition_get_end(pa)));
-               if (last + grain <= pa->start) {
+
+               /* We ignore small free spaces (smaller than grain) to keep partitions
+                * aligned, the exception is space before the first partition where
+                * we assume that cxt->first_lba is aligned. */
+               if (last + grain <= pa->start
+                   || (last < pa->start && last == cxt->first_lba)) {
                        rc = table_add_freespace(cxt, *tb,
                                last + (last > cxt->first_lba ? 1 : 0),
                                pa->start - 1, NULL);