All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Add support for altering GPT size
@ 2016-05-12 11:54 Sassan Panahinejad
  2016-05-12 11:54 ` [PATCH v2 1/3] libfdisk: " Sassan Panahinejad
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Sassan Panahinejad @ 2016-05-12 11:54 UTC (permalink / raw)
  To: util-linux; +Cc: Sassan Panahinejad

As requested by Karel, this version adds a GPT specific function.

The following additional error checking is performed:
* Check that memory for the new entries array could be allocated
* Check that the new table will fit on the disk
* Check that no existing partition will be overlapped by the new table

fdisk and sfdisk have been modified to use the new function and the
pre-existing fdisk_get_npartitions instead of the two new generic
functions added by the previous patch version.

Sassan Panahinejad (3):
  libfdisk: Add support for altering GPT size
  fdisk: Add support for altering GPT size
  sfdisk: Add support for altering GPT size

 disk-utils/fdisk-menu.c    |   8 ++++
 libfdisk/src/gpt.c         | 100 +++++++++++++++++++++++++++++++++++++++++++++
 libfdisk/src/libfdisk.h.in |   1 +
 libfdisk/src/libfdisk.sym  |   1 +
 libfdisk/src/script.c      |  15 ++++++-
 5 files changed, 123 insertions(+), 2 deletions(-)

-- 
2.1.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/3] libfdisk: Add support for altering GPT size
  2016-05-12 11:54 [PATCH v2 0/3] Add support for altering GPT size Sassan Panahinejad
@ 2016-05-12 11:54 ` Sassan Panahinejad
  2016-05-13 13:52   ` Mike Frysinger
  2016-05-12 11:54 ` [PATCH v2 2/3] fdisk: " Sassan Panahinejad
  2016-05-12 11:54 ` [PATCH v2 3/3] sfdisk: " Sassan Panahinejad
  2 siblings, 1 reply; 8+ messages in thread
From: Sassan Panahinejad @ 2016-05-12 11:54 UTC (permalink / raw)
  To: util-linux; +Cc: Sassan Panahinejad

This is useful in two situations:

1. More than 128 partitions are required. Or

2. The partition table must be restricted in size, such as when a system
expects to find a bootloader at a location that would otherwise overlap the
partition table.

The gdisk partitioner supports this feature.

libfdisk is already capable of reading and writing partition tables of any
size, but previously could only create ones of 128 entries and could not
resize.

This change should be fairly safe, as it has no effect unless explicitly
activated.
---
 libfdisk/src/gpt.c         | 100 +++++++++++++++++++++++++++++++++++++++++++++
 libfdisk/src/libfdisk.h.in |   1 +
 libfdisk/src/libfdisk.sym  |   1 +
 3 files changed, 102 insertions(+)

diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 39c93bb..b9f4e43 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -2453,6 +2453,106 @@ static int gpt_set_disklabel_id(struct fdisk_context *cxt)
 	return 0;
 }
 
+static int gpt_check_table_overlap(struct fdisk_context *cxt,
+				   uint64_t first_usable,
+				   uint64_t last_usable)
+{
+	struct fdisk_gpt_label *gpt = self_label(cxt);
+	unsigned int i;
+	int rc = 0;
+
+	/* First check if there's enough room for the table. last_lba may have wrapped */
+	if (first_usable > cxt->total_sectors || /* far too little space */
+	    last_usable > cxt->total_sectors || /* wrapped */
+	    first_usable > last_usable) { /* too little space */
+		fdisk_warnx(cxt, _("Not enough space for new partition table!"));
+		return -ENOSPC;
+	}
+
+	/* check that all partitions fit in the remaining space */
+	for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
+		if (partition_unused(&gpt->ents[i]))
+		        continue;
+		if (gpt_partition_start(&gpt->ents[i]) < first_usable) {
+			fdisk_warnx(cxt, _("Partition #%u out of range (minimal start is %ju sectors)"),
+		                    i + 1, first_usable);
+			rc = -EINVAL;
+		}
+		if (gpt_partition_end(&gpt->ents[i]) > last_usable) {
+			fdisk_warnx(cxt, _("Partition #%u out of range (maximal end is %ju sectors)"),
+		                    i + 1, last_usable - 1);
+			rc = -EINVAL;
+		}
+	}
+	return rc;
+}
+
+int fdisk_gpt_set_npartitions(struct fdisk_context *cxt, unsigned long new)
+{
+	struct fdisk_gpt_label *gpt;
+	size_t old_size, new_size;
+	unsigned long old;
+	struct gpt_entry *ents;
+	uint64_t first_usable, last_usable;
+	int rc;
+
+	assert(cxt);
+	assert(cxt->label);
+	assert(fdisk_is_label(cxt, GPT));
+
+	gpt = self_label(cxt);
+
+	old = le32_to_cpu(gpt->pheader->npartition_entries);
+
+	/* calculate the size (bytes) of the entries array */
+	new_size = new * le32_to_cpu(gpt->pheader->sizeof_partition_entry);
+	old_size = old * le32_to_cpu(gpt->pheader->sizeof_partition_entry);
+
+	/* calculate new range of usable LBAs */
+	first_usable = (new_size / cxt->sector_size) + 2;
+	last_usable = cxt->total_sectors - 2 - (new_size / cxt->sector_size);
+
+	/* if expanding the table, first check that everything fits,
+	 * then allocate more memory and zero. */
+	if (new > old) {
+		rc = gpt_check_table_overlap(cxt, first_usable, last_usable);
+		if (rc)
+			return rc;
+		ents = realloc(gpt->ents, new_size);
+		if (!ents) {
+			fdisk_warnx(cxt, _("Cannot allocate memory!"));
+			return -ENOMEM;
+		}
+		memset(ents + old, 0, new_size - old_size);
+		gpt->ents = ents;
+	}
+
+	/* everything's ok, apply the new size */
+	gpt->pheader->npartition_entries = cpu_to_le32(new);
+	gpt->bheader->npartition_entries = cpu_to_le32(new);
+
+	/* usable LBA addresses will have changed */
+	fdisk_set_first_lba(cxt, first_usable);
+	fdisk_set_last_lba(cxt, last_usable);
+	gpt->pheader->first_usable_lba = cpu_to_le64(first_usable);
+	gpt->bheader->first_usable_lba = cpu_to_le64(first_usable);
+	gpt->pheader->last_usable_lba = cpu_to_le64(last_usable);
+	gpt->bheader->last_usable_lba = cpu_to_le64(last_usable);
+
+
+	/* The backup header must be recalculated */
+	gpt_mknew_header_common(cxt, gpt->bheader, le64_to_cpu(gpt->pheader->alternative_lba));
+
+	/* CRCs will have changed */
+	gpt_recompute_crc(gpt->pheader, gpt->ents);
+	gpt_recompute_crc(gpt->bheader, gpt->ents);
+
+	fdisk_info(cxt, _("Partition table length changed from %lu to %lu."), old, new);
+
+	fdisk_label_set_changed(cxt->label, 1);
+	return 0;
+}
+
 static int gpt_part_is_used(struct fdisk_context *cxt, size_t i)
 {
 	struct fdisk_gpt_label *gpt;
diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in
index 6bd3a1e..f081711 100644
--- a/libfdisk/src/libfdisk.h.in
+++ b/libfdisk/src/libfdisk.h.in
@@ -602,6 +602,7 @@ enum fdisk_labelitem_sgi {
 #define GPT_FLAG_GUIDSPECIFIC	4
 
 extern int fdisk_gpt_is_hybrid(struct fdisk_context *cxt);
+extern int fdisk_gpt_set_npartitions(struct fdisk_context *cxt, unsigned long entries);
 extern int fdisk_gpt_get_partition_attrs(struct fdisk_context *cxt, size_t partnum, uint64_t *attrs);
 extern int fdisk_gpt_set_partition_attrs(struct fdisk_context *cxt, size_t partnum, uint64_t attrs);
 
diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym
index c5aeac6..af0b401 100644
--- a/libfdisk/src/libfdisk.sym
+++ b/libfdisk/src/libfdisk.sym
@@ -262,4 +262,5 @@ FDISK_2.28 {
 
 FDISK_2.29 {
 	fdisk_wipe_partition;
+	fdisk_gpt_set_npartitions;
 } FDISK_2.28;
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/3] fdisk: Add support for altering GPT size
  2016-05-12 11:54 [PATCH v2 0/3] Add support for altering GPT size Sassan Panahinejad
  2016-05-12 11:54 ` [PATCH v2 1/3] libfdisk: " Sassan Panahinejad
@ 2016-05-12 11:54 ` Sassan Panahinejad
  2016-05-12 11:54 ` [PATCH v2 3/3] sfdisk: " Sassan Panahinejad
  2 siblings, 0 replies; 8+ messages in thread
From: Sassan Panahinejad @ 2016-05-12 11:54 UTC (permalink / raw)
  To: util-linux; +Cc: Sassan Panahinejad

Adds an options (l) to the GPT menu to resize the GPT.
---
 disk-utils/fdisk-menu.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/disk-utils/fdisk-menu.c b/disk-utils/fdisk-menu.c
index b099cc3..0d7e4de 100644
--- a/disk-utils/fdisk-menu.c
+++ b/disk-utils/fdisk-menu.c
@@ -165,6 +165,7 @@ struct menu menu_gpt = {
 		MENU_XENT('i', N_("change disk GUID")),
 		MENU_XENT('n', N_("change partition name")),
 		MENU_XENT('u', N_("change partition UUID")),
+		MENU_XENT('l', N_("change table length")),
 		MENU_XENT('M', N_("enter protective/hybrid MBR")),
 
 		MENU_XSEP(""),
@@ -691,6 +692,7 @@ static int gpt_menu_cb(struct fdisk_context **cxt0,
 	struct fdisk_partition *pa = NULL;
 	size_t n;
 	int rc = 0;
+	unsigned long length;
 
 	assert(cxt);
 	assert(ent);
@@ -702,6 +704,12 @@ static int gpt_menu_cb(struct fdisk_context **cxt0,
 		switch (ent->key) {
 		case 'i':
 			return fdisk_set_disklabel_id(cxt);
+		case 'l':
+	                rc =  fdisk_ask_number(cxt, 1, fdisk_get_npartitions(cxt),
+	                                ~0UL, _("New maximum entries"), &length);
+			if (rc)
+				return rc;
+			return fdisk_gpt_set_npartitions(cxt, length);
 		case 'M':
 			mbr = fdisk_new_nested_context(cxt, "dos");
 			if (!mbr)
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/3] sfdisk: Add support for altering GPT size
  2016-05-12 11:54 [PATCH v2 0/3] Add support for altering GPT size Sassan Panahinejad
  2016-05-12 11:54 ` [PATCH v2 1/3] libfdisk: " Sassan Panahinejad
  2016-05-12 11:54 ` [PATCH v2 2/3] fdisk: " Sassan Panahinejad
@ 2016-05-12 11:54 ` Sassan Panahinejad
  2016-05-18 12:31   ` Karel Zak
  2 siblings, 1 reply; 8+ messages in thread
From: Sassan Panahinejad @ 2016-05-12 11:54 UTC (permalink / raw)
  To: util-linux; +Cc: Sassan Panahinejad

Adds a header option to alter the GPT table length
---
 libfdisk/src/script.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c
index 096f37c..fd05bf7 100644
--- a/libfdisk/src/script.c
+++ b/libfdisk/src/script.c
@@ -705,7 +705,8 @@ static int parse_line_header(struct fdisk_script *dp, char *s)
 	} else if (strcmp(name, "label-id") == 0
 		   || strcmp(name, "device") == 0
 		   || strcmp(name, "first-lba") == 0
-		   || strcmp(name, "last-lba") == 0) {
+		   || strcmp(name, "last-lba") == 0
+		   || strcmp(name, "table-length") == 0) {
 		;					/* whatever is posssible */
 	} else
 		goto done;				/* unknown header */
@@ -1326,6 +1327,8 @@ struct fdisk_script *fdisk_get_script(struct fdisk_context *cxt)
 int fdisk_apply_script_headers(struct fdisk_context *cxt, struct fdisk_script *dp)
 {
 	const char *name;
+	const char *str;
+	int rc;
 
 	assert(cxt);
 	assert(dp);
@@ -1338,7 +1341,15 @@ int fdisk_apply_script_headers(struct fdisk_context *cxt, struct fdisk_script *d
 	if (!name)
 		return -EINVAL;
 
-	return fdisk_create_disklabel(cxt, name);
+	rc = fdisk_create_disklabel(cxt, name);
+	if (rc)
+		return rc;
+
+	str = fdisk_script_get_header(dp, "table-length");
+	if (str)
+		return fdisk_gpt_set_npartitions(cxt, strtoul(str, NULL, 0));
+
+	return 0;
 }
 
 /**
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/3] libfdisk: Add support for altering GPT size
  2016-05-12 11:54 ` [PATCH v2 1/3] libfdisk: " Sassan Panahinejad
@ 2016-05-13 13:52   ` Mike Frysinger
  2016-05-13 13:54     ` Sassan Panahinejad
  0 siblings, 1 reply; 8+ messages in thread
From: Mike Frysinger @ 2016-05-13 13:52 UTC (permalink / raw)
  To: Sassan Panahinejad; +Cc: util-linux

[-- Attachment #1: Type: text/plain, Size: 679 bytes --]

On 12 May 2016 12:54, Sassan Panahinejad wrote:
> +static int gpt_check_table_overlap(struct fdisk_context *cxt,
> +				   uint64_t first_usable,
> +				   uint64_t last_usable)
> +{
> ...
> +		if (gpt_partition_start(&gpt->ents[i]) < first_usable) {
> +			fdisk_warnx(cxt, _("Partition #%u out of range (minimal start is %ju sectors)"),
> +		                    i + 1, first_usable);

%j is for uintmax_t but this is uint64_t, so you'll want to use ..." PRIu64 "...

> +		if (gpt_partition_end(&gpt->ents[i]) > last_usable) {
> +			fdisk_warnx(cxt, _("Partition #%u out of range (maximal end is %ju sectors)"),
> +		                    i + 1, last_usable - 1);

same here
-mike

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/3] libfdisk: Add support for altering GPT size
  2016-05-13 13:52   ` Mike Frysinger
@ 2016-05-13 13:54     ` Sassan Panahinejad
  0 siblings, 0 replies; 8+ messages in thread
From: Sassan Panahinejad @ 2016-05-13 13:54 UTC (permalink / raw)
  To: Sassan Panahinejad, util-linux

Thanks, I'll fix that and resubmit.

On 13 May 2016 at 14:52, Mike Frysinger <vapier@gentoo.org> wrote:
> On 12 May 2016 12:54, Sassan Panahinejad wrote:
>> +static int gpt_check_table_overlap(struct fdisk_context *cxt,
>> +                                uint64_t first_usable,
>> +                                uint64_t last_usable)
>> +{
>> ...
>> +             if (gpt_partition_start(&gpt->ents[i]) < first_usable) {
>> +                     fdisk_warnx(cxt, _("Partition #%u out of range (minimal start is %ju sectors)"),
>> +                                 i + 1, first_usable);
>
> %j is for uintmax_t but this is uint64_t, so you'll want to use ..." PRIu64 "...
>
>> +             if (gpt_partition_end(&gpt->ents[i]) > last_usable) {
>> +                     fdisk_warnx(cxt, _("Partition #%u out of range (maximal end is %ju sectors)"),
>> +                                 i + 1, last_usable - 1);
>
> same here
> -mike

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 3/3] sfdisk: Add support for altering GPT size
  2016-05-12 11:54 ` [PATCH v2 3/3] sfdisk: " Sassan Panahinejad
@ 2016-05-18 12:31   ` Karel Zak
  2016-05-18 13:51     ` Sassan Panahinejad
  0 siblings, 1 reply; 8+ messages in thread
From: Karel Zak @ 2016-05-18 12:31 UTC (permalink / raw)
  To: Sassan Panahinejad; +Cc: util-linux

On Thu, May 12, 2016 at 12:54:43PM +0100, Sassan Panahinejad wrote:
>  libfdisk/src/script.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)

Applied, thanks.

I have also added "table-length" to the --dump output if table length
is different than the default.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 3/3] sfdisk: Add support for altering GPT size
  2016-05-18 12:31   ` Karel Zak
@ 2016-05-18 13:51     ` Sassan Panahinejad
  0 siblings, 0 replies; 8+ messages in thread
From: Sassan Panahinejad @ 2016-05-18 13:51 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux

Good idea!

Thanks!

On 18 May 2016 at 13:31, Karel Zak <kzak@redhat.com> wrote:
> On Thu, May 12, 2016 at 12:54:43PM +0100, Sassan Panahinejad wrote:
>>  libfdisk/src/script.c | 15 +++++++++++++--
>>  1 file changed, 13 insertions(+), 2 deletions(-)
>
> Applied, thanks.
>
> I have also added "table-length" to the --dump output if table length
> is different than the default.
>
>     Karel
>
> --
>  Karel Zak  <kzak@redhat.com>
>  http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2016-05-18 13:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-12 11:54 [PATCH v2 0/3] Add support for altering GPT size Sassan Panahinejad
2016-05-12 11:54 ` [PATCH v2 1/3] libfdisk: " Sassan Panahinejad
2016-05-13 13:52   ` Mike Frysinger
2016-05-13 13:54     ` Sassan Panahinejad
2016-05-12 11:54 ` [PATCH v2 2/3] fdisk: " Sassan Panahinejad
2016-05-12 11:54 ` [PATCH v2 3/3] sfdisk: " Sassan Panahinejad
2016-05-18 12:31   ` Karel Zak
2016-05-18 13:51     ` Sassan Panahinejad

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.