Skip to content

Commit

Permalink
Pull request openzfs#4858
Browse files Browse the repository at this point in the history
  • Loading branch information
snajpa committed Jul 18, 2016
1 parent c197a04 commit c802b49
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 37 deletions.
23 changes: 23 additions & 0 deletions config/kernel-blk-queue-unplug.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
dnl #
dnl # 2.6.32-2.6.35 API - The BIO_RW_UNPLUG enum can be used as a hint
dnl # to unplug the queue.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BIO_RW_UNPLUG], [
AC_MSG_CHECKING([whether the BIO_RW_UNPLUG enum is available])
tmp_flags="$EXTRA_KCFLAGS"
EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
ZFS_LINUX_TRY_COMPILE([
#include <linux/blkdev.h>
],[
extern enum bio_rw_flags rw;
rw = BIO_RW_UNPLUG;
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_BLK_QUEUE_HAVE_BIO_RW_UNPLUG, 1,
[BIO_RW_UNPLUG is available])
],[
AC_MSG_RESULT(no)
])
EXTRA_KCFLAGS="$tmp_flags"
])
1 change: 1 addition & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_BLK_QUEUE_FLUSH
ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS
ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS
ZFS_AC_KERNEL_BLK_QUEUE_HAVE_BIO_RW_UNPLUG
ZFS_AC_KERNEL_GET_DISK_RO
ZFS_AC_KERNEL_GET_GENDISK
ZFS_AC_KERNEL_DISCARD_GRANULARITY
Expand Down
1 change: 0 additions & 1 deletion module/zfs/spa.c
Original file line number Diff line number Diff line change
Expand Up @@ -6767,7 +6767,6 @@ EXPORT_SYMBOL(spa_open);
EXPORT_SYMBOL(spa_open_rewind);
EXPORT_SYMBOL(spa_get_stats);
EXPORT_SYMBOL(spa_create);
EXPORT_SYMBOL(spa_import_rootpool);
EXPORT_SYMBOL(spa_import);
EXPORT_SYMBOL(spa_tryimport);
EXPORT_SYMBOL(spa_destroy);
Expand Down
53 changes: 17 additions & 36 deletions module/zfs/vdev_disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,8 @@ static void *zfs_vdev_holder = VDEV_HOLDER;
* Virtual device vector for disks.
*/
typedef struct dio_request {
struct completion dr_comp; /* Completion for sync IO */
zio_t *dr_zio; /* Parent ZIO */
atomic_t dr_ref; /* References */
int dr_wait; /* Wait for IO */
int dr_error; /* Bio error */
int dr_bio_count; /* Count of bio's */
struct bio *dr_bio[0]; /* Attached bio's */
Expand Down Expand Up @@ -365,7 +363,6 @@ vdev_disk_dio_alloc(int bio_count)
dr = kmem_zalloc(sizeof (dio_request_t) +
sizeof (struct bio *) * bio_count, KM_SLEEP);
if (dr) {
init_completion(&dr->dr_comp);
atomic_set(&dr->dr_ref, 0);
dr->dr_bio_count = bio_count;
dr->dr_error = 0;
Expand Down Expand Up @@ -428,7 +425,6 @@ BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, error)
{
dio_request_t *dr = bio->bi_private;
int rc;
int wait;

if (dr->dr_error == 0) {
#ifdef HAVE_1ARG_BIO_END_IO_T
Expand All @@ -441,13 +437,8 @@ BIO_END_IO_PROTO(vdev_disk_physio_completion, bio, error)
#endif
}

wait = dr->dr_wait;
/* Drop reference aquired by __vdev_disk_physio */
rc = vdev_disk_dio_put(dr);

/* Wake up synchronous waiter this is the last outstanding bio */
if (wait && rc == 1)
complete(&dr->dr_comp);
}

static inline unsigned long
Expand Down Expand Up @@ -514,7 +505,7 @@ vdev_submit_bio(int rw, struct bio *bio)

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, int wait)
size_t kbuf_size, uint64_t kbuf_offset, int flags)
{
dio_request_t *dr;
uint64_t zio_offset;
Expand All @@ -537,7 +528,6 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr,

rw = flags;
dr->dr_zio = zio;
dr->dr_wait = wait;

/*
* When the IO size exceeds the maximum bio size for the request
Expand Down Expand Up @@ -612,20 +602,6 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr,
if (dr->dr_bio[i])
vdev_submit_bio(rw, dr->dr_bio[i]);

/*
* On synchronous blocking requests we wait for all bio the completion
* callbacks to run. We will be woken when the last callback runs
* for this dio. We are responsible for putting the last dio_request
* reference will in turn put back the last bio references. The
* only synchronous consumer is vdev_disk_read_rootlabel() all other
* IO originating from vdev_disk_io_start() is asynchronous.
*/
if (wait) {
wait_for_completion(&dr->dr_comp);
error = dr->dr_error;
ASSERT3S(atomic_read(&dr->dr_ref), ==, 1);
}

if (kbuf_ptr)
abd_put(zio_data);

Expand All @@ -639,7 +615,7 @@ vdev_disk_physio(struct block_device *bdev, caddr_t kbuf,
size_t size, uint64_t offset, int flags)
{
bio_set_flags_failfast(bdev, &flags);
return (__vdev_disk_physio(bdev, NULL, kbuf, size, offset, flags, 1));
return (__vdev_disk_physio(bdev, NULL, kbuf, size, offset, flags));
}

BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, rc)
Expand Down Expand Up @@ -691,7 +667,6 @@ vdev_disk_io_start(zio_t *zio)
{
vdev_t *v = zio->io_vd;
vdev_disk_t *vd = v->vdev_tsd;
zio_priority_t pri = zio->io_priority;
int flags, error;

switch (zio->io_type) {
Expand Down Expand Up @@ -731,17 +706,23 @@ vdev_disk_io_start(zio_t *zio)
zio_execute(zio);
return;
case ZIO_TYPE_WRITE:
if ((pri == ZIO_PRIORITY_SYNC_WRITE) && (v->vdev_nonrot))
flags = WRITE_SYNC;
else
flags = WRITE;
#if defined(HAVE_BLK_QUEUE_HAVE_BIO_RW_UNPLUG)
flags = WRITE | (1 << BIO_RW_UNPLUG);
#elif defined(REQ_UNPLUG)
flags = WRITE | REQ_UNPLUG;
#else
flags = WRITE;
#endif
break;

case ZIO_TYPE_READ:
if ((pri == ZIO_PRIORITY_SYNC_READ) && (v->vdev_nonrot))
flags = READ_SYNC;
else
flags = READ;
#if defined(HAVE_BLK_QUEUE_HAVE_BIO_RW_UNPLUG)
flags = READ | (1 << BIO_RW_UNPLUG);
#elif defined(REQ_UNPLUG)
flags = READ | REQ_UNPLUG;
#else
flags = READ;
#endif
break;

default:
Expand All @@ -751,7 +732,7 @@ vdev_disk_io_start(zio_t *zio)
}

error = __vdev_disk_physio(vd->vd_bdev, zio, NULL,
zio->io_size, zio->io_offset, flags, 0);
zio->io_size, zio->io_offset, flags);
if (error) {
zio->io_error = error;
zio_interrupt(zio);
Expand Down

0 comments on commit c802b49

Please sign in to comment.