diff --git a/include/linux/blkdev_compat.h b/include/linux/blkdev_compat.h index e263dc836081..01bfad600ce2 100644 --- a/include/linux/blkdev_compat.h +++ b/include/linux/blkdev_compat.h @@ -334,15 +334,30 @@ bio_set_flags_failfast(struct block_device *bdev, int *flags) #endif /* - * 2.6.32 API change - * Use the normal I/O patch for discards. + * 2.6.28 - 2.6.35 API, + * BIO_RW_DISCARD + * + * 2.6.36 - 4.7 API, + * REQ_DISCARD + * + * 4.8 - 4.x API, + * REQ_OP_DISCARD + * + * In all cases the normal I/O path is used for discards. The only + * difference is how the kernel tags individual I/Os as discards. */ #ifdef QUEUE_FLAG_DISCARD -#ifdef HAVE_BIO_RW_DISCARD -#define VDEV_REQ_DISCARD (1 << BIO_RW_DISCARD) +static inline boolean_t +bio_is_discard(struct bio *bio) +{ +#if defined(HAVE_BIO_RW_DISCARD) + return (bio->bi_rw & (1 << BIO_RW_DISCARD)); +#elif defined(REQ_DISCARD) + return (bio->bi_rw & REQ_DISCARD); #else -#define VDEV_REQ_DISCARD REQ_DISCARD + return (bio_op(bio) == REQ_OP_DISCARD); #endif +} #else #error "Allowing the build will cause discard requests to become writes " "potentially triggering the DMU_MAX_ACCESS assertion. Please file a " diff --git a/module/zfs/vdev_disk.c b/module/zfs/vdev_disk.c index 28f145d049fb..ccf1d839d99a 100644 --- a/module/zfs/vdev_disk.c +++ b/module/zfs/vdev_disk.c @@ -484,41 +484,45 @@ bio_map(struct bio *bio, void *bio_ptr, unsigned int bio_size) return (bio_size); } +#ifndef bio_set_op_attrs +#define bio_set_op_attrs(bio, rw, flags) \ + do { (bio)->bi_rw |= (rw)|(flags); } while (0) +#endif + static inline void -vdev_submit_bio_impl(int rw, struct bio *bio) +vdev_submit_bio_impl(struct bio *bio) { #ifdef HAVE_1ARG_SUBMIT_BIO - bio->bi_rw |= rw; submit_bio(bio); #else - submit_bio(rw, bio); + submit_bio(0, bio); #endif } static inline void -vdev_submit_bio(int rw, struct bio *bio) +vdev_submit_bio(struct bio *bio) { #ifdef HAVE_CURRENT_BIO_TAIL struct bio **bio_tail = current->bio_tail; current->bio_tail = NULL; - vdev_submit_bio_impl(rw, bio); + vdev_submit_bio_impl(bio); current->bio_tail = bio_tail; #else struct bio_list *bio_list = current->bio_list; current->bio_list = NULL; - vdev_submit_bio_impl(rw, bio); + vdev_submit_bio_impl(bio); current->bio_list = bio_list; #endif } static int __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr, - size_t kbuf_size, uint64_t kbuf_offset, int flags) + size_t kbuf_size, uint64_t kbuf_offset, int rw, int flags) { dio_request_t *dr; caddr_t bio_ptr; uint64_t bio_offset; - int rw, bio_size, bio_count = 16; + int bio_size, bio_count = 16; int i = 0, error = 0; ASSERT3U(kbuf_offset + kbuf_size, <=, bdev->bd_inode->i_size); @@ -531,7 +535,6 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr, if (zio && !(zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD))) bio_set_flags_failfast(bdev, &flags); - rw = flags; dr->dr_zio = zio; /* @@ -574,9 +577,9 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr, dr->dr_bio[i]->bi_bdev = bdev; BIO_BI_SECTOR(dr->dr_bio[i]) = bio_offset >> 9; - dr->dr_bio[i]->bi_rw = rw; dr->dr_bio[i]->bi_end_io = vdev_disk_physio_completion; dr->dr_bio[i]->bi_private = dr; + bio_set_op_attrs(dr->dr_bio[i], rw, flags); /* Remaining size is returned to become the new size */ bio_size = bio_map(dr->dr_bio[i], bio_ptr, bio_size); @@ -592,7 +595,7 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr, /* Submit all bio's associated with this dio */ for (i = 0; i < dr->dr_bio_count; i++) if (dr->dr_bio[i]) - vdev_submit_bio(rw, dr->dr_bio[i]); + vdev_submit_bio(dr->dr_bio[i]); (void) vdev_disk_dio_put(dr); @@ -602,10 +605,10 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr, #ifndef __linux__ int vdev_disk_physio(struct block_device *bdev, caddr_t kbuf, - size_t size, uint64_t offset, int flags) + size_t size, uint64_t offset, int rw, int flags) { bio_set_flags_failfast(bdev, &flags); - return (__vdev_disk_physio(bdev, NULL, kbuf, size, offset, flags)); + return (__vdev_disk_physio(bdev, NULL, kbuf, size, offset, rw, flags)); } #endif @@ -645,7 +648,8 @@ vdev_disk_io_flush(struct block_device *bdev, zio_t *zio) bio->bi_end_io = vdev_disk_io_flush_completion; bio->bi_private = zio; bio->bi_bdev = bdev; - vdev_submit_bio(VDEV_WRITE_FLUSH_FUA, bio); + bio_set_op_attrs(bio, 0, VDEV_WRITE_FLUSH_FUA); + vdev_submit_bio(bio); invalidate_bdev(bdev); return (0); @@ -656,7 +660,7 @@ vdev_disk_io_start(zio_t *zio) { vdev_t *v = zio->io_vd; vdev_disk_t *vd = v->vdev_tsd; - int flags, error; + int rw, flags, error; switch (zio->io_type) { case ZIO_TYPE_IOCTL: @@ -695,22 +699,24 @@ vdev_disk_io_start(zio_t *zio) zio_execute(zio); return; case ZIO_TYPE_WRITE: + rw = WRITE; #if defined(HAVE_BLK_QUEUE_HAVE_BIO_RW_UNPLUG) - flags = WRITE | (1 << BIO_RW_UNPLUG); + flags = (1 << BIO_RW_UNPLUG); #elif defined(REQ_UNPLUG) - flags = WRITE | REQ_UNPLUG; + flags = REQ_UNPLUG; #else - flags = WRITE; + flags = 0; #endif break; case ZIO_TYPE_READ: + rw = READ; #if defined(HAVE_BLK_QUEUE_HAVE_BIO_RW_UNPLUG) - flags = READ | (1 << BIO_RW_UNPLUG); + flags = (1 << BIO_RW_UNPLUG); #elif defined(REQ_UNPLUG) - flags = READ | REQ_UNPLUG; + flags = REQ_UNPLUG; #else - flags = READ; + flags = 0; #endif break; @@ -722,7 +728,7 @@ vdev_disk_io_start(zio_t *zio) zio->io_target_timestamp = zio_handle_io_delay(zio); error = __vdev_disk_physio(vd->vd_bdev, zio, zio->io_data, - zio->io_size, zio->io_offset, flags); + zio->io_size, zio->io_offset, rw, flags); if (error) { zio->io_error = error; zio_interrupt(zio); @@ -824,7 +830,8 @@ vdev_disk_read_rootlabel(char *devpath, char *devid, nvlist_t **config) /* read vdev label */ offset = vdev_label_offset(size, i, 0); if (vdev_disk_physio(bdev, (caddr_t)label, - VDEV_SKIP_SIZE + VDEV_PHYS_SIZE, offset, READ_SYNC) != 0) + VDEV_SKIP_SIZE + VDEV_PHYS_SIZE, offset, READ, + REQ_SYNC) != 0) continue; if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist, diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 73277901ff16..c25b243db3a8 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -812,7 +812,7 @@ zvol_request(struct request_queue *q, struct bio *bio) goto out2; } - if (bio->bi_rw & VDEV_REQ_DISCARD) { + if (bio_is_discard(bio)) { error = zvol_discard(bio); goto out2; }