mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 19:19:32 +03:00
Don't ashift-align vdev read requests.
Currently, the size of read and write requests on vdevs is aligned according to the vdev's ashift, allocating a new ZIO buffer and padding if need be. This makes sense for write requests to prevent read/modify/write if the write happens to be smaller than the device's internal block size. For reads however, the rationale is less clear. It seems that the original code aligns reads because, on Solaris, device drivers will outright refuse unaligned requests. We don't have that issue on Linux. Indeed, Linux block devices are able to accept requests of any size, and take care of alignment issues themselves. As a result, there's no point in enforcing alignment for read requests on Linux. This is a nice optimization opportunity for two reasons: - We remove a memory allocation in a heavily-used code path; - The request gets aligned in the lowest layer possible, which shrinks the path that the additional, useless padding data has to travel. For example, when using 4k-sector drives that lie about their sector size, using 512b read requests instead of 4k means that there will be less data traveling down the ATA/SCSI interface, even though the drive actually reads 4k from the platter. The only exception is raidz, because raidz needs to read the whole allocated block for parity. This patch removes alignment enforcement for read requests, except on raidz. Note that we also remove an assertion that checks that we're aligning a top-level vdev I/O, because that's not the case anymore for repair writes that results from failed reads. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #1022
This commit is contained in:
parent
b68503fb30
commit
a5c20e2a0a
@ -2432,19 +2432,25 @@ zio_vdev_io_start(zio_t *zio)
|
|||||||
|
|
||||||
align = 1ULL << vd->vdev_top->vdev_ashift;
|
align = 1ULL << vd->vdev_top->vdev_ashift;
|
||||||
|
|
||||||
if (P2PHASE(zio->io_size, align) != 0) {
|
/*
|
||||||
|
* On Linux, we don't care about read alignment. The backing block
|
||||||
|
* device driver will take care of that for us.
|
||||||
|
* The only exception is raidz, which needs a full block for parity.
|
||||||
|
*/
|
||||||
|
if (P2PHASE(zio->io_size, align) != 0 &&
|
||||||
|
(zio->io_type != ZIO_TYPE_READ ||
|
||||||
|
vd->vdev_ops == &vdev_raidz_ops)) {
|
||||||
uint64_t asize = P2ROUNDUP(zio->io_size, align);
|
uint64_t asize = P2ROUNDUP(zio->io_size, align);
|
||||||
char *abuf = zio_buf_alloc(asize);
|
char *abuf = zio_buf_alloc(asize);
|
||||||
ASSERT(vd == vd->vdev_top);
|
|
||||||
if (zio->io_type == ZIO_TYPE_WRITE) {
|
if (zio->io_type == ZIO_TYPE_WRITE) {
|
||||||
bcopy(zio->io_data, abuf, zio->io_size);
|
bcopy(zio->io_data, abuf, zio->io_size);
|
||||||
bzero(abuf + zio->io_size, asize - zio->io_size);
|
bzero(abuf + zio->io_size, asize - zio->io_size);
|
||||||
}
|
}
|
||||||
zio_push_transform(zio, abuf, asize, asize, zio_subblock);
|
zio_push_transform(zio, abuf, asize, asize, zio_subblock);
|
||||||
|
ASSERT(P2PHASE(zio->io_size, align) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(P2PHASE(zio->io_offset, align) == 0);
|
ASSERT(P2PHASE(zio->io_offset, align) == 0);
|
||||||
ASSERT(P2PHASE(zio->io_size, align) == 0);
|
|
||||||
VERIFY(zio->io_type != ZIO_TYPE_WRITE || spa_writeable(spa));
|
VERIFY(zio->io_type != ZIO_TYPE_WRITE || spa_writeable(spa));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user