summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorEtienne Dechamps <[email protected]>2012-07-11 17:47:10 +0200
committerBrian Behlendorf <[email protected]>2012-07-12 08:59:22 -0700
commitcee43a7477501669920445f29990443679142336 (patch)
tree47bd0a9f4cc014c0214001d463690e399d654530 /lib
parent7608bd0dd01829a130cd8a4d244e197ce8fa590a (diff)
Fix efi_use_whole_disk() when efi_nparts == 128.
Commit e5dc681a changed EFI_NUMPAR from 9 to 128. This means that the on-disk EFI label has efi_nparts = 128 instead of 9. The index of the reserved partition, however, is still 8. This breaks efi_use_whole_disk(), which uses efi_nparts-1 as the index of the reserved partition. This commit fixes efi_use_whole_disk() when the index of the reserved partition is not efi_nparts-1. It rewrites the algorithm and makes it more robust by using the order of the partitions instead of their numbering. It assumes that the last non-empty partition is the reserved partition, and that the non-empty partition before that is the data partition. Signed-off-by: Brian Behlendorf <[email protected]> Issue #808
Diffstat (limited to 'lib')
-rw-r--r--lib/libefi/rdwr_efi.c50
1 files changed, 26 insertions, 24 deletions
diff --git a/lib/libefi/rdwr_efi.c b/lib/libefi/rdwr_efi.c
index 0600a9523..474f78a38 100644
--- a/lib/libefi/rdwr_efi.c
+++ b/lib/libefi/rdwr_efi.c
@@ -1028,24 +1028,15 @@ efi_use_whole_disk(int fd)
struct dk_gpt *efi_label;
int rval;
int i;
- uint_t phy_last_slice = 0;
- diskaddr_t pl_start = 0;
- diskaddr_t pl_size;
+ uint_t resv_index = 0, data_index = 0;
+ diskaddr_t resv_start = 0, data_start = 0;
+ diskaddr_t difference;
rval = efi_alloc_and_read(fd, &efi_label);
if (rval < 0) {
return (rval);
}
- /* find the last physically non-zero partition */
- for (i = 0; i < efi_label->efi_nparts - 2; i ++) {
- if (pl_start < efi_label->efi_parts[i].p_start) {
- pl_start = efi_label->efi_parts[i].p_start;
- phy_last_slice = i;
- }
- }
- pl_size = efi_label->efi_parts[phy_last_slice].p_size;
-
/*
* If alter_lba is 1, we are using the backup label.
* Since we can locate the backup label by disk capacity,
@@ -1061,16 +1052,28 @@ efi_use_whole_disk(int fd)
return (VT_ENOSPC);
}
+ difference = efi_label->efi_last_lba - efi_label->efi_altern_lba;
+
+ /*
+ * Find the last physically non-zero partition.
+ * This is the reserved partition.
+ */
+ for (i = 0; i < efi_label->efi_nparts; i ++) {
+ if (resv_start < efi_label->efi_parts[i].p_start) {
+ resv_start = efi_label->efi_parts[i].p_start;
+ resv_index = i;
+ }
+ }
+
/*
- * If there is space between the last physically non-zero partition
- * and the reserved partition, just add the unallocated space to this
- * area. Otherwise, the unallocated space is added to the last
- * physically non-zero partition.
+ * Find the last physically non-zero partition before that.
+ * This is the data partition.
*/
- if (pl_start + pl_size - 1 == efi_label->efi_last_u_lba -
- EFI_MIN_RESV_SIZE) {
- efi_label->efi_parts[phy_last_slice].p_size +=
- efi_label->efi_last_lba - efi_label->efi_altern_lba;
+ for (i = 0; i < resv_index; i ++) {
+ if (data_start < efi_label->efi_parts[i].p_start) {
+ data_start = efi_label->efi_parts[i].p_start;
+ data_index = i;
+ }
}
/*
@@ -1078,10 +1081,9 @@ efi_use_whole_disk(int fd)
* here except fabricated devids (which get generated via
* efi_write()). So there is no need to copy data.
*/
- efi_label->efi_parts[efi_label->efi_nparts - 1].p_start +=
- efi_label->efi_last_lba - efi_label->efi_altern_lba;
- efi_label->efi_last_u_lba += efi_label->efi_last_lba
- - efi_label->efi_altern_lba;
+ efi_label->efi_parts[data_index].p_size += difference;
+ efi_label->efi_parts[resv_index].p_start += difference;
+ efi_label->efi_last_u_lba += difference;
rval = efi_write(fd, efi_label);
if (rval < 0) {