Align parition end on 1 MiB boundary

Some devices have exhibited sensitivity to the ending alignment of
partitions.  In particular, even if the first partition begins at 1
MiB, we have seen many sd driver task abort errors with certain SSDs
if the first partition doesn't end on a 1 MiB boundary.  This occurs
when the vdev label is read during pool creation or importation and
causes a delay of about 30 seconds per device.  It can also be
simulated with dd when the pool isn't imported:

  dd if=/dev/sda1 of=/dev/null bs=262144 count=1

For the record, this problem was observed with SMARTMOD
SG9XCA2E200GE01 200GB SSDs.  Unfortunately I don't have a good
explanation for this behavior. It seems to have something to do with
highly fragmented single-sector requests being issued to the device,
which it may not support.  With end-aligned partitions at least
page-sized requests were queued and issued to the driver according
to blktrace. In any case, aligning the partition end is a fairly
innocuous work-around, wasting at most 1 MiB of space.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #574
This commit is contained in:
Ned Bass 2012-02-29 10:08:20 -08:00 committed by Brian Behlendorf
parent ec2626ad3f
commit 613d88eda8
1 changed files with 6 additions and 3 deletions

View File

@ -672,10 +672,12 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
* Don't start the slice at the default block of 34; many storage * Don't start the slice at the default block of 34; many storage
* devices will use a stripe width of 128k, other vendors prefer a 1m * devices will use a stripe width of 128k, other vendors prefer a 1m
* alignment. It is best to play it safe and ensure a 1m alignment * alignment. It is best to play it safe and ensure a 1m alignment
* give 512b blocks. When the block size is larger by a power of 2 * given 512B blocks. When the block size is larger by a power of 2
* we will still be 1m aligned. * we will still be 1m aligned. Some devices are sensitive to the
* partition ending alignment as well.
*/ */
#define NEW_START_BLOCK 2048 #define NEW_START_BLOCK 2048
#define PARTITION_END_ALIGNMENT 2048
/* /*
* Validate the given pool name, optionally putting an extended error message in * Validate the given pool name, optionally putting an extended error message in
@ -3786,6 +3788,7 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
if (start_block == MAXOFFSET_T) if (start_block == MAXOFFSET_T)
start_block = NEW_START_BLOCK; start_block = NEW_START_BLOCK;
slice_size -= start_block; slice_size -= start_block;
slice_size = P2ALIGN(slice_size, PARTITION_END_ALIGNMENT);
vtoc->efi_parts[0].p_start = start_block; vtoc->efi_parts[0].p_start = start_block;
vtoc->efi_parts[0].p_size = slice_size; vtoc->efi_parts[0].p_size = slice_size;