From 86dd0fd9222b6103c6533036c47b908ece944460 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Sun, 19 Aug 2012 17:17:02 -0700 Subject: Pre-allocate vdev I/O buffers The vdev queue layer may require a small number of buffers when attempting to create aggregate I/O requests. Rather than attempting to allocate them from the global zio buffers, which is slow under memory pressure, it makes sense to pre-allocate them because... 1) These buffers are short lived. They are only required for the life of a single I/O at which point they can be used by the next I/O. 2) The maximum number of concurrent buffers needed by a vdev is small. It's roughly limited by the zfs_vdev_max_pending tunable which defaults to 10. By keeping a small list of these buffer per-vdev we can ensure one is always available when we need it. This significantly reduces contention on the vq->vq_lock, because we no longer need to perform a slow allocation under this lock. This is particularly important when memory is already low on the system. It would probably be wise to extend the use of these buffers beyond aggregate I/O and in to the raidz implementation. The inability to quickly allocate buffer for the parity stripes could result in similiar problems. Signed-off-by: Brian Behlendorf --- include/sys/vdev_impl.h | 7 +++++++ include/sys/zio.h | 2 ++ 2 files changed, 9 insertions(+) (limited to 'include') diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h index 1df61a587..8862d9bc9 100644 --- a/include/sys/vdev_impl.h +++ b/include/sys/vdev_impl.h @@ -49,6 +49,7 @@ extern "C" { * Forward declarations that lots of things need. */ typedef struct vdev_queue vdev_queue_t; +typedef struct vdev_io vdev_io_t; typedef struct vdev_cache vdev_cache_t; typedef struct vdev_cache_entry vdev_cache_entry_t; @@ -102,9 +103,15 @@ struct vdev_queue { avl_tree_t vq_read_tree; avl_tree_t vq_write_tree; avl_tree_t vq_pending_tree; + list_t vq_io_list; kmutex_t vq_lock; }; +struct vdev_io { + char vi_buffer[SPA_MAXBLOCKSIZE]; /* Must be first */ + list_node_t vi_node; +}; + /* * Virtual device descriptor */ diff --git a/include/sys/zio.h b/include/sys/zio.h index c0da4e2d7..4f20cab65 100644 --- a/include/sys/zio.h +++ b/include/sys/zio.h @@ -494,6 +494,8 @@ extern void *zio_buf_alloc(size_t size); extern void zio_buf_free(void *buf, size_t size); extern void *zio_data_buf_alloc(size_t size); extern void zio_data_buf_free(void *buf, size_t size); +extern void *zio_vdev_alloc(void); +extern void zio_vdev_free(void *buf); extern void zio_resubmit_stage_async(void *); -- cgit v1.2.3