summaryrefslogtreecommitdiffstats
path: root/module/zfs/zio.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zio.c')
-rw-r--r--module/zfs/zio.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index 0ba167c62..9d70b3e59 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -889,8 +889,8 @@ zio_read_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
ASSERT3U(offset + size, <=, vd->vdev_psize);
zio = zio_create(pio, vd->vdev_spa, 0, NULL, data, size, done, private,
- ZIO_TYPE_READ, priority, flags, vd, offset, NULL,
- ZIO_STAGE_OPEN, ZIO_READ_PHYS_PIPELINE);
+ ZIO_TYPE_READ, priority, flags | ZIO_FLAG_PHYSICAL, vd, offset,
+ NULL, ZIO_STAGE_OPEN, ZIO_READ_PHYS_PIPELINE);
zio->io_prop.zp_checksum = checksum;
@@ -910,8 +910,8 @@ zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, uint64_t size,
ASSERT3U(offset + size, <=, vd->vdev_psize);
zio = zio_create(pio, vd->vdev_spa, 0, NULL, data, size, done, private,
- ZIO_TYPE_WRITE, priority, flags, vd, offset, NULL,
- ZIO_STAGE_OPEN, ZIO_WRITE_PHYS_PIPELINE);
+ ZIO_TYPE_WRITE, priority, flags | ZIO_FLAG_PHYSICAL, vd, offset,
+ NULL, ZIO_STAGE_OPEN, ZIO_WRITE_PHYS_PIPELINE);
zio->io_prop.zp_checksum = checksum;
@@ -2642,7 +2642,9 @@ zio_vdev_io_start(zio_t *zio)
align = 1ULL << vd->vdev_top->vdev_ashift;
- if (P2PHASE(zio->io_size, align) != 0) {
+ if (!(zio->io_flags & ZIO_FLAG_PHYSICAL) &&
+ P2PHASE(zio->io_size, align) != 0) {
+ /* Transform logical writes to be a full physical block size. */
uint64_t asize = P2ROUNDUP(zio->io_size, align);
char *abuf = zio_buf_alloc(asize);
ASSERT(vd == vd->vdev_top);
@@ -2653,8 +2655,22 @@ zio_vdev_io_start(zio_t *zio)
zio_push_transform(zio, abuf, asize, asize, zio_subblock);
}
- ASSERT(P2PHASE(zio->io_offset, align) == 0);
- ASSERT(P2PHASE(zio->io_size, align) == 0);
+ /*
+ * If this is not a physical io, make sure that it is properly aligned
+ * before proceeding.
+ */
+ if (!(zio->io_flags & ZIO_FLAG_PHYSICAL)) {
+ ASSERT0(P2PHASE(zio->io_offset, align));
+ ASSERT0(P2PHASE(zio->io_size, align));
+ } else {
+ /*
+ * For physical writes, we allow 512b aligned writes and assume
+ * the device will perform a read-modify-write as necessary.
+ */
+ ASSERT0(P2PHASE(zio->io_offset, SPA_MINBLOCKSIZE));
+ ASSERT0(P2PHASE(zio->io_size, SPA_MINBLOCKSIZE));
+ }
+
VERIFY(zio->io_type != ZIO_TYPE_WRITE || spa_writeable(spa));
/*