aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/kernel-blk-queue-unplug.m423
-rw-r--r--config/kernel.m41
-rw-r--r--include/sys/vdev_disk.h2
-rw-r--r--module/zfs/spa.c5
-rw-r--r--module/zfs/vdev_disk.c57
5 files changed, 49 insertions, 39 deletions
diff --git a/config/kernel-blk-queue-unplug.m4 b/config/kernel-blk-queue-unplug.m4
new file mode 100644
index 000000000..45cc2322a
--- /dev/null
+++ b/config/kernel-blk-queue-unplug.m4
@@ -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"
+])
diff --git a/config/kernel.m4 b/config/kernel.m4
index c9b24cbe8..ac6c08ffe 100644
--- a/config/kernel.m4
+++ b/config/kernel.m4
@@ -27,6 +27,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
diff --git a/include/sys/vdev_disk.h b/include/sys/vdev_disk.h
index d5a1889d2..c6d5f92b2 100644
--- a/include/sys/vdev_disk.h
+++ b/include/sys/vdev_disk.h
@@ -37,9 +37,11 @@ typedef struct vdev_disk {
struct block_device *vd_bdev;
} vdev_disk_t;
+#ifndef __linux__
extern int vdev_disk_physio(struct block_device *, caddr_t,
size_t, uint64_t, int);
extern int vdev_disk_read_rootlabel(char *, char *, nvlist_t **);
+#endif
#endif /* _KERNEL */
#endif /* _SYS_VDEV_DISK_H */
diff --git a/module/zfs/spa.c b/module/zfs/spa.c
index 26181af84..15c87866e 100644
--- a/module/zfs/spa.c
+++ b/module/zfs/spa.c
@@ -3971,7 +3971,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
return (0);
}
-#ifdef _KERNEL
+#if defined(_KERNEL) && !defined(__linux__)
/*
* Get the root pool information from the root disk, then import the root pool
* during the system boot up time.
@@ -4174,7 +4174,7 @@ out:
return (error);
}
-#endif
+#endif /* defined(_KERNEL) && !defined(__linux__) */
/*
* Import a non-root pool into the system.
@@ -7038,7 +7038,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);
diff --git a/module/zfs/vdev_disk.c b/module/zfs/vdev_disk.c
index 1ef54d389..205f78d78 100644
--- a/module/zfs/vdev_disk.c
+++ b/module/zfs/vdev_disk.c
@@ -41,10 +41,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 */
@@ -363,7 +361,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;
@@ -425,7 +422,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
@@ -438,13 +434,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
@@ -511,7 +502,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;
caddr_t bio_ptr;
@@ -531,7 +522,6 @@ retry:
rw = flags;
dr->dr_zio = zio;
- dr->dr_wait = wait;
/*
* When the IO size exceeds the maximum bio size for the request
@@ -593,32 +583,20 @@ retry:
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);
- }
-
(void) vdev_disk_dio_put(dr);
return (error);
}
+#ifndef __linux__
int
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));
}
+#endif
BIO_END_IO_PROTO(vdev_disk_io_flush_completion, bio, rc)
{
@@ -667,7 +645,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) {
@@ -707,17 +684,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:
@@ -728,7 +711,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, 0);
+ zio->io_size, zio->io_offset, flags);
if (error) {
zio->io_error = error;
zio_interrupt(zio);
@@ -798,6 +781,7 @@ vdev_ops_t vdev_disk_ops = {
B_TRUE /* leaf vdev */
};
+#ifndef __linux__
/*
* Given the root disk device devid or pathname, read the label from
* the device, and construct a configuration nvlist.
@@ -860,6 +844,7 @@ vdev_disk_read_rootlabel(char *devpath, char *devid, nvlist_t **config)
return (0);
}
+#endif /* __linux__ */
module_param(zfs_vdev_scheduler, charp, 0644);
MODULE_PARM_DESC(zfs_vdev_scheduler, "I/O scheduler");