diff options
author | Andriy Gapon <avg@FreeBSD.org> | 2017-03-01 15:30:49 +0200 |
---|---|---|
committer | Prakash Surya <prakash.surya@delphix.com> | 2017-06-13 13:06:13 -0700 |
commit | 403a8da73c64ff9dfb6230ba045c765a242213fb (patch) | |
tree | 4ee87466be14e5bab94e0cc6ef24fe2dcd0d0e1c | |
parent | 4ec4134be29a3b00791f6d70074168a6a3ff4fb3 (diff) | |
download | illumos-joyent-403a8da73c64ff9dfb6230ba045c765a242213fb.tar.gz |
5220 L2ARC does not support devices that do not provide 512B access
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r-- | usr/src/uts/common/fs/zfs/arc.c | 69 |
1 files changed, 57 insertions, 12 deletions
diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c index 1b4542ce01..cabbb5b4e8 100644 --- a/usr/src/uts/common/fs/zfs/arc.c +++ b/usr/src/uts/common/fs/zfs/arc.c @@ -1075,6 +1075,7 @@ typedef struct l2arc_read_callback { blkptr_t l2rcb_bp; /* original blkptr */ zbookmark_phys_t l2rcb_zb; /* original bookmark */ int l2rcb_flags; /* original flags */ + abd_t *l2rcb_abd; /* temporary buffer */ } l2arc_read_callback_t; typedef struct l2arc_write_callback { @@ -5048,6 +5049,8 @@ top: !HDR_L2_WRITING(hdr) && !HDR_L2_EVICTED(hdr) && !(l2arc_noprefetch && HDR_PREFETCH(hdr))) { l2arc_read_callback_t *cb; + abd_t *abd; + uint64_t asize; DTRACE_PROBE1(l2arc__hit, arc_buf_hdr_t *, hdr); ARCSTAT_BUMP(arcstat_l2_hits); @@ -5059,8 +5062,17 @@ top: cb->l2rcb_zb = *zb; cb->l2rcb_flags = zio_flags; + asize = vdev_psize_to_asize(vd, size); + if (asize != size) { + abd = abd_alloc_for_io(asize, + HDR_ISTYPE_METADATA(hdr)); + cb->l2rcb_abd = abd; + } else { + abd = hdr->b_l1hdr.b_pabd; + } + ASSERT(addr >= VDEV_LABEL_START_SIZE && - addr + lsize < vd->vdev_psize - + addr + asize <= vd->vdev_psize - VDEV_LABEL_END_SIZE); /* @@ -5072,7 +5084,7 @@ top: ASSERT3U(HDR_GET_COMPRESS(hdr), !=, ZIO_COMPRESS_EMPTY); rzio = zio_read_phys(pio, vd, addr, - size, hdr->b_l1hdr.b_pabd, + asize, abd, ZIO_CHECKSUM_OFF, l2arc_read_done, cb, priority, zio_flags | ZIO_FLAG_DONT_CACHE | @@ -6566,6 +6578,33 @@ l2arc_read_done(zio_t *zio) mutex_enter(hash_lock); ASSERT3P(hash_lock, ==, HDR_LOCK(hdr)); + /* + * If the data was read into a temporary buffer, + * move it and free the buffer. + */ + if (cb->l2rcb_abd != NULL) { + ASSERT3U(arc_hdr_size(hdr), <, zio->io_size); + if (zio->io_error == 0) { + abd_copy(hdr->b_l1hdr.b_pabd, cb->l2rcb_abd, + arc_hdr_size(hdr)); + } + + /* + * The following must be done regardless of whether + * there was an error: + * - free the temporary buffer + * - point zio to the real ARC buffer + * - set zio size accordingly + * These are required because zio is either re-used for + * an I/O of the block in the case of the error + * or the zio is passed to arc_read_done() and it + * needs real data. + */ + abd_free(cb->l2rcb_abd); + zio->io_size = zio->io_orig_size = arc_hdr_size(hdr); + zio->io_abd = zio->io_orig_abd = hdr->b_l1hdr.b_pabd; + } + ASSERT3P(zio->io_abd, !=, NULL); /* @@ -6903,23 +6942,34 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz) * Normally the L2ARC can use the hdr's data, but if * we're sharing data between the hdr and one of its * bufs, L2ARC needs its own copy of the data so that - * the ZIO below can't race with the buf consumer. To - * ensure that this copy will be available for the + * the ZIO below can't race with the buf consumer. + * Another case where we need to create a copy of the + * data is when the buffer size is not device-aligned + * and we need to pad the block to make it such. + * That also keeps the clock hand suitably aligned. + * + * To ensure that the copy will be available for the * lifetime of the ZIO and be cleaned up afterwards, we * add it to the l2arc_free_on_write queue. */ + uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev, + size); abd_t *to_write; - if (!HDR_SHARED_DATA(hdr)) { + if (!HDR_SHARED_DATA(hdr) && size == asize) { to_write = hdr->b_l1hdr.b_pabd; } else { - to_write = abd_alloc_for_io(size, + to_write = abd_alloc_for_io(asize, HDR_ISTYPE_METADATA(hdr)); abd_copy(to_write, hdr->b_l1hdr.b_pabd, size); + if (asize != size) { + abd_zero_off(to_write, size, + asize - size); + } l2arc_free_abd_on_write(to_write, size, arc_buf_type(hdr)); } wzio = zio_write_phys(pio, dev->l2ad_vdev, - hdr->b_l2hdr.b_daddr, size, to_write, + hdr->b_l2hdr.b_daddr, asize, to_write, ZIO_CHECKSUM_OFF, NULL, hdr, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_CANFAIL, B_FALSE); @@ -6929,11 +6979,6 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz) zio_t *, wzio); write_asize += size; - /* - * Keep the clock hand suitably device-aligned. - */ - uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev, - size); write_psize += asize; dev->l2ad_hand += asize; |