This action moves second(backup) GPT header to the end of the disk. It is usable in in-place image expanding, since free space after second GPT header is unusable. To use additional space, we have to move second header. This is what sgdisk -e does. However, sgdisk -e may perform additional actions if the partition table has unexpected params (e.g. if we call sgdisk -e /dev/sda1, it may fix partition table thus destroying the filesystem). To prevent such cases, we do a dry-run at first and fail if additional actions are scheduled. --- daemon/parted.c | 33 +++++++++++++++++++++++++++++++++ generator/actions.ml | 14 ++++++++++++++ src/MAX_PROC_NR | 2 +- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/daemon/parted.c b/daemon/parted.c index df6b7e7..033c136 100644 --- a/daemon/parted.c +++ b/daemon/parted.c @@ -928,3 +928,36 @@ do_part_get_mbr_part_type (const char *device, int partnum) reply_with_error ("strdup failed"); return NULL; } + +int +do_part_expand_gpt(const char *device) +{ + CLEANUP_FREE char *err = NULL; + + /* If something is broken, sgdisk may try to correct it. + * (e.g. recreate partition table and so on). + * We do not want such behavior, so dry-run at first.*/ + int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, + str_sgdisk, "--pretend", "-e", device, NULL); + + if (r == -1) { + reply_with_error ("%s --pretend -e %s: %s", str_sgdisk, device, err); + return -1; + } + if (err && strlen(err) != 0) { + /* Unexpected actions. */ + reply_with_error ("%s --pretend -e %s: %s", str_sgdisk, device, err); + return -1; + } + + /* Now we can do a real run. */ + r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, + str_sgdisk, "-e", device, NULL); + + if (r == -1) { + reply_with_error ("%s -e %s: %s", str_sgdisk, device, err); + return -1; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index 7ab8ee4..3a14683 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12787,6 +12787,20 @@ See also L<ntfsresize(8)>, L<resize2fs(8)>, L<btrfs(8)>, L<xfs_info(8)>." }; longdesc = "\ This is the internal call which implements C<guestfs_feature_available>." }; + { defaults with + name = "part_expand_gpt"; added = (1, 31, 29); + style = RErr, [Device "device"], []; + proc_nr = Some 459; + optional = Some "gdisk"; + shortdesc = "move backup GPT header to the end of the disk"; + longdesc = "\ +Move backup GPT data structures to the end of the disk. +This is useful in case of in-place image expand +since disk space after backup GPT header is not usable. +This is equivalent to C<sgdisk -e>. + +See also L<sgdisk(8)>." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index c92ddb6..658bd78 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -458 +459 -- 1.8.3.1
Maxim Perevedentsev
2015-Nov-25 11:43 UTC
Re: [Libguestfs] [PATCH] New API: part_expand_gpt.
On 11/25/2015 02:32 PM, Maxim Perevedentsev wrote:> + { defaults with > + name = "part_expand_gpt"; added = (1, 31, 29); > + style = RErr, [Device "device"], []; > + proc_nr = Some 459; > + optional = Some "gdisk"; > + shortdesc = "move backup GPT header to the end of the disk"; > + longdesc = "\ > +Move backup GPT data structures to the end of the disk. > +This is useful in case of in-place image expand > +since disk space after backup GPT header is not usable. > +This is equivalent to C<sgdisk -e>. > + > +See also L<sgdisk(8)>." }; > + >Unfortunately, I failed to write a test, since the main usage is something like > qemu-img create disk 200M > guestfish -a disk run : part-disk /dev/sda gpt > qemu-img resize disk 300M > guestfish -a disk run : part-expand-gpt /dev/sda -> success > guestfish -a disk run : part-expand-gpt /dev/sda1 -> fail Should I add it as shell script to /tests/daemon ? -- Your sincerely, Maxim Perevedentsev