diff options
author | Etienne Dechamps <[email protected]> | 2012-07-11 17:47:10 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2012-07-12 08:59:22 -0700 |
commit | cee43a7477501669920445f29990443679142336 (patch) | |
tree | 47bd0a9f4cc014c0214001d463690e399d654530 /lib | |
parent | 7608bd0dd01829a130cd8a4d244e197ce8fa590a (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.c | 50 |
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) { |