diff options
author | Karel Zak | 2014-02-03 14:40:27 +0100 |
---|---|---|
committer | Karel Zak | 2014-03-11 11:35:14 +0100 |
commit | 036439315f4c29748fddd10c33d6cc4868dd9352 (patch) | |
tree | b835ad35c81cab7e2434f04edbecdaa48a007703 /libfdisk | |
parent | libfdisk: don't ask for pri/log if wanted start within extended partition (diff) | |
download | kernel-qcow2-util-linux-036439315f4c29748fddd10c33d6cc4868dd9352.tar.gz kernel-qcow2-util-linux-036439315f4c29748fddd10c33d6cc4868dd9352.tar.xz kernel-qcow2-util-linux-036439315f4c29748fddd10c33d6cc4868dd9352.zip |
libfdisk: improve freesapce detection
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk')
-rw-r--r-- | libfdisk/src/dos.c | 5 | ||||
-rw-r--r-- | libfdisk/src/fdiskP.h | 11 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.h | 3 | ||||
-rw-r--r-- | libfdisk/src/partition.c | 12 | ||||
-rw-r--r-- | libfdisk/src/table.c | 76 |
5 files changed, 83 insertions, 24 deletions
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c index cb34be8ab..327a747cf 100644 --- a/libfdisk/src/dos.c +++ b/libfdisk/src/dos.c @@ -1612,6 +1612,11 @@ static int dos_get_partition(struct fdisk_context *cxt, size_t n, pa->end = get_abs_partition_start(pe) + psects - (psects ? 1 : 0); pa->size = psects; + if (n >= 4) { + pa->parent_partno = self_label(cxt)->ext_index; + pa->nested = 1; + } + if (asprintf(&pa->attrs, "%02x", p->boot_ind) < 0) return -ENOMEM; diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index 46e6c430e..899a043b0 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -158,6 +158,7 @@ enum { struct fdisk_partition { int refcount; /* reference counter */ size_t partno; /* partition number */ + size_t parent_partno; /* for logical partitions */ uint64_t start; /* first sectors */ uint64_t end; /* last sector */ @@ -188,8 +189,7 @@ struct fdisk_partition { end_follow_default : 1, /* use default end */ freespace : 1, /* dthis is not partition, this is free space */ nested : 1, /* logical partition */ - used : 1, /* partition already used */ - endrel : 1; /* end is specified as relative number */ + used : 1; /* partition already used */ }; #define FDISK_EMPTY_PARTNO ((size_t) -1) @@ -201,13 +201,6 @@ struct fdisk_table { size_t nents; /* number of partitions */ }; -extern int fdisk_table_add_freespace( - struct fdisk_context *cxt, - struct fdisk_table *tb, - uint64_t start, - uint64_t end, - int dosort); - /* * Legacy CHS based geometry */ diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h index af31b6b8c..726296c32 100644 --- a/libfdisk/src/libfdisk.h +++ b/libfdisk/src/libfdisk.h @@ -188,7 +188,7 @@ extern uint64_t fdisk_partition_get_start(struct fdisk_partition *pa); extern int fdisk_partition_cmp_start(struct fdisk_partition *a, struct fdisk_partition *b); -extern int fdisk_partition_set_end(struct fdisk_partition *pa, uint64_t off, int isrel); +extern int fdisk_partition_set_end(struct fdisk_partition *pa, uint64_t off); extern uint64_t fdisk_partition_get_end(struct fdisk_partition *pa); extern int fdisk_partition_set_size(struct fdisk_partition *pa, uint64_t size); extern uint64_t fdisk_partition_get_size(struct fdisk_partition *pa); @@ -207,6 +207,7 @@ extern const char *fdisk_partition_get_uuid(struct fdisk_partition *pa); extern const char *fdisk_partition_get_attrs(struct fdisk_partition *pa); extern int fdisk_partition_set_nested(struct fdisk_partition *pa, int nested); extern int fdisk_partition_is_nested(struct fdisk_partition *pa); +extern int fdisk_partition_get_parent(struct fdisk_partition *pa, size_t *parent); extern int fdisk_partition_is_used(struct fdisk_partition *pa); extern int fdisk_partition_to_string(struct fdisk_partition *pa, struct fdisk_context *cxt, diff --git a/libfdisk/src/partition.c b/libfdisk/src/partition.c index da5e75c25..20993ba3a 100644 --- a/libfdisk/src/partition.c +++ b/libfdisk/src/partition.c @@ -72,13 +72,12 @@ int fdisk_partition_cmp_start(struct fdisk_partition *a, return a->start - b->start; } -int fdisk_partition_set_end(struct fdisk_partition *pa, uint64_t off, int isrel) +int fdisk_partition_set_end(struct fdisk_partition *pa, uint64_t off) { if (!pa) return -EINVAL; pa->end = off; pa->size = 0; - pa->endrel = isrel ? 1 : 0; return 0; } @@ -220,6 +219,15 @@ int fdisk_partition_is_nested(struct fdisk_partition *pa) return pa && pa->nested; } +int fdisk_partition_get_parent(struct fdisk_partition *pa, size_t *parent) +{ + if (pa && parent) + *parent = pa->parent_partno; + else + return -EINVAL; + return 0; +} + int fdisk_partition_is_used(struct fdisk_partition *pa) { return pa && pa->used; diff --git a/libfdisk/src/table.c b/libfdisk/src/table.c index 84ce357dd..a78be477f 100644 --- a/libfdisk/src/table.c +++ b/libfdisk/src/table.c @@ -310,12 +310,13 @@ int fdisk_table_sort_partitions(struct fdisk_table *tb, return 0; } -int fdisk_table_add_freespace( +static int table_add_freespace( struct fdisk_context *cxt, struct fdisk_table *tb, uint64_t start, uint64_t end, - int dosort) + int dosort, + struct fdisk_partition **res) { struct fdisk_partition *pa; int rc = 0; @@ -346,6 +347,8 @@ int fdisk_table_add_freespace( } rc = table_insert_partition(tb, best, pa); } + if (res) + *res = pa; fdisk_unref_partition(pa); return rc; } @@ -368,6 +371,7 @@ int fdisk_get_freespaces(struct fdisk_context *cxt, struct fdisk_table **tb) struct fdisk_table *parts = NULL; struct fdisk_partition *pa; struct fdisk_iter itr; + size_t cont = FDISK_EMPTY_PARTNO; DBG(LABEL, dbgprint("get freespace")); @@ -390,31 +394,79 @@ int fdisk_get_freespaces(struct fdisk_context *cxt, struct fdisk_table **tb) dosort = !fdisk_table_is_empty(*tb); last = cxt->first_lba; - grain = cxt->grain / cxt->sector_size; + grain = cxt->grain > cxt->sector_size ? cxt->grain / cxt->sector_size : 1; /* analyze gaps between partitions */ while (fdisk_table_next_partition(parts, &itr, &pa) == 0) { - + if (pa->nested) + cont = (int) pa->parent_partno; + if (!pa->used || pa->nested) + continue; DBG(LABEL, dbgprint("freespace analyze: partno=%zu, start=%ju, end=%ju", pa->partno, pa->start, pa->end)); - - if (!fdisk_partition_is_used(pa)) - continue; if (last + grain < pa->start) { - rc = fdisk_table_add_freespace(cxt, *tb, + rc = table_add_freespace(cxt, *tb, last + (last > cxt->first_lba ? 1 : 0), pa->start - 1, - dosort); + dosort, NULL); } last = pa->end; } - /* add free-space (behind last partition) to the list */ + /* add free-space behind last partition to the list */ if (rc == 0 && last + grain < cxt->total_sectors - 1) - rc = fdisk_table_add_freespace(cxt, *tb, + rc = table_add_freespace(cxt, *tb, last + (last > cxt->first_lba ? 1 : 0), cxt->last_lba, - dosort); + dosort, NULL); + + /* add gaps between logical partitions */ + if (cont != FDISK_EMPTY_PARTNO) { + uint64_t x; + struct fdisk_partition *fr; + struct fdisk_partition *parent = + fdisk_table_get_partition(parts, cont); + if (!parent) + goto done; + last = fdisk_partition_get_start(parent) + cxt->first_lba; + + DBG(LABEL, dbgprint("check container freespace last=%ju, " + "grain=%ju, partno=%zu, start=%ju, end=%ju", + last, grain, parent->partno, parent->start, + parent->end)); + + fdisk_reset_iter(&itr, FDISK_ITER_FORWARD); + + while (fdisk_table_next_partition(parts, &itr, &pa) == 0) { + uint64_t lastfree = pa->start - 1 - cxt->first_lba; + + if (!pa->used || !pa->nested) + continue; + if (last + grain < lastfree) { + rc = table_add_freespace(cxt, *tb, + last + grain, lastfree, + dosort, &fr); + if (rc == 0 && fr) { + fr->parent_partno = parent->partno; + fr->nested = 1; + } + } + last = pa->end; + } + + /* free-space remaining in extended partition */ + x = fdisk_partition_get_start(parent) + + fdisk_partition_get_size(parent) - 1; + if (last + grain < x) + rc = table_add_freespace(cxt, *tb, + last + grain, x - 1, + dosort, &fr); + if (rc == 0 && fr) { + fr->parent_partno = parent->partno; + fr->nested = 1; + } + } + done: fdisk_unref_table(parts); return rc; |