summaryrefslogtreecommitdiffstats
path: root/libfdisk
diff options
context:
space:
mode:
authorKarel Zak2014-01-29 14:20:11 +0100
committerKarel Zak2014-03-11 11:35:13 +0100
commit1240f549d89febba87130381b38c1d5c2718a098 (patch)
treea7fd9f51e472dd66b0a706b3a2f5ece219856145 /libfdisk
parentlibfdisk: initialize last_lba (diff)
downloadkernel-qcow2-util-linux-1240f549d89febba87130381b38c1d5c2718a098.tar.gz
kernel-qcow2-util-linux-1240f549d89febba87130381b38c1d5c2718a098.tar.xz
kernel-qcow2-util-linux-1240f549d89febba87130381b38c1d5c2718a098.zip
libfdisk: (gpt) initialize last_lba, cleanup pa->{start,size} usage
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk')
-rw-r--r--libfdisk/src/gpt.c89
1 files changed, 69 insertions, 20 deletions
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 8c1c86835..dac9e7107 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -467,6 +467,22 @@ static struct gpt_header *gpt_copy_header(struct fdisk_context *cxt,
return res;
}
+static void count_first_last_lba(struct fdisk_context *cxt,
+ uint64_t *first, uint64_t *last)
+{
+ uint64_t esz = 0;
+
+ assert(cxt);
+
+ esz = sizeof(struct gpt_entry) * GPT_NPARTITIONS / cxt->sector_size;
+ *last = cxt->total_sectors - 2 - esz;
+ *first = esz + 2;
+
+ if (*first < cxt->first_lba && cxt->first_lba < *last)
+ /* Align according to topology */
+ *first = cxt->first_lba;
+}
+
/*
* Builds a clean new GPT header (currently under revision 1.0).
*
@@ -478,13 +494,11 @@ static struct gpt_header *gpt_copy_header(struct fdisk_context *cxt,
static int gpt_mknew_header(struct fdisk_context *cxt,
struct gpt_header *header, uint64_t lba)
{
- uint64_t esz = 0, first, last;
+ uint64_t first, last;
if (!cxt || !header)
return -ENOSYS;
- esz = sizeof(struct gpt_entry) * GPT_NPARTITIONS / cxt->sector_size;
-
header->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
header->revision = cpu_to_le32(GPT_HEADER_REVISION_V1_00);
header->size = cpu_to_le32(sizeof(struct gpt_header));
@@ -496,13 +510,7 @@ static int gpt_mknew_header(struct fdisk_context *cxt,
header->npartition_entries = cpu_to_le32(GPT_NPARTITIONS);
header->sizeof_partition_entry = cpu_to_le32(sizeof(struct gpt_entry));
- last = cxt->total_sectors - 2 - esz;
- first = esz + 2;
-
- if (first < cxt->first_lba && cxt->first_lba < last)
- /* Align according to topology */
- first = cxt->first_lba;
-
+ count_first_last_lba(cxt, &first, &last);
header->first_usable_lba = cpu_to_le64(first);
header->last_usable_lba = cpu_to_le64(last);
@@ -1680,6 +1688,9 @@ static int gpt_create_new_partition(struct fdisk_context *cxt,
assert(cxt->label);
assert(fdisk_is_disklabel(cxt, GPT));
+ DBG(LABEL, dbgprint("GPT new partition: partno=%zu, start=%ju, end=%ju",
+ partnum, fsect, lsect));
+
gpt = self_label(cxt);
if (fsect > lsect || partnum >= cxt->label->nparts_max)
@@ -1735,9 +1746,10 @@ static int gpt_add_partition(
ents = gpt->ents;
rc = fdisk_partition_next_partno(pa, cxt, &partnum);
- if (rc)
+ if (rc) {
+ DBG(LABEL, dbgprint("GPT failed to get next partno"));
return rc;
-
+ }
if (!partition_unused(&ents[partnum])) {
fdisk_warnx(cxt, _("Partition %zu is already defined. "
"Delete it before re-adding it."), partnum +1);
@@ -1804,15 +1816,17 @@ static int gpt_add_partition(
}
}
+
/* Last sector */
dflt_l = find_last_free(pheader, ents, user_f);
if (pa && pa->size) {
- if (pa->size + user_f > dflt_l)
- return -ERANGE;
user_l = user_f + pa->size;
user_l = fdisk_align_lba_in_range(cxt, user_l, user_f, dflt_l) - 1;
+ if (user_l + (cxt->grain / cxt->sector_size) > dflt_l)
+ user_l = dflt_l; /* no space for anything useful, use all space */
+
} else if (pa && pa->end_follow_default) {
user_l = dflt_l;
} else {
@@ -1835,17 +1849,20 @@ static int gpt_add_partition(
goto done;
user_l = fdisk_ask_number_get_result(ask);
- if (fdisk_ask_number_is_relative(ask))
+ if (fdisk_ask_number_is_relative(ask)) {
user_l = fdisk_align_lba_in_range(cxt, user_l, user_f, dflt_l) - 1;
- if (user_l > user_f && user_l <= disk_l)
+ if (user_l + (cxt->grain / cxt->sector_size) > dflt_l)
+ user_l = dflt_l; /* no space for anything useful, use all space */
+ } if (user_l > user_f && user_l <= disk_l)
break;
}
}
- if (gpt_create_new_partition(cxt, partnum,
- user_f, user_l, &typeid, ents) != 0)
+ if ((rc = gpt_create_new_partition(cxt, partnum,
+ user_f, user_l, &typeid, ents) != 0)) {
fdisk_warnx(cxt, _("Could not create partition %ju"), partnum + 1);
- else {
+ goto done;
+ } else {
struct fdisk_parttype *t;
cxt->label->nparts_cur++;
@@ -2220,6 +2237,36 @@ static int gpt_toggle_partition_flag(
return 0;
}
+static int gpt_reset_alignment(struct fdisk_context *cxt)
+{
+ struct fdisk_gpt_label *gpt;
+ struct gpt_header *h;
+
+ assert(cxt);
+ assert(cxt->label);
+ assert(fdisk_is_disklabel(cxt, GPT));
+
+ gpt = self_label(cxt);
+ h = gpt ? gpt->pheader : NULL;
+
+ if (h) {
+ /* always follow existing table */
+ cxt->first_lba = h->first_usable_lba;
+ cxt->last_lba = h->last_usable_lba;
+ } else {
+ /* estimate ranges for GPT */
+ uint64_t first, last;
+
+ count_first_last_lba(cxt, &first, &last);
+
+ if (cxt->first_lba < first)
+ cxt->first_lba = first;
+ if (cxt->last_lba > last)
+ cxt->last_lba = last;
+ }
+
+ return 0;
+}
/*
* Deinitialize fdisk-specific variables
*/
@@ -2259,7 +2306,9 @@ static const struct fdisk_label_operations gpt_operations =
.part_set_type = gpt_set_partition_type,
.part_toggle_flag = gpt_toggle_partition_flag,
- .deinit = gpt_deinit
+ .deinit = gpt_deinit,
+
+ .reset_alignment = gpt_reset_alignment
};
static const struct fdisk_column gpt_columns[] =