aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2008-09-13 14:26:01 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:09 -0400
commitc7c22e4d5c1fdebfac4dba76de7d0338c2b0d832 (patch)
treeecc3d2517b3471ccc35d4cb4e3b48d4b57205061 /include
parent18887ad910e56066233a07fd3cfb2fa11338b782 (diff)
block: add support for IO CPU affinity
This patch adds support for controlling the IO completion CPU of either all requests on a queue, or on a per-request basis. We export a sysfs variable (rq_affinity) which, if set, migrates completions of requests to the CPU that originally submitted it. A bio helper (bio_set_completion_cpu()) is also added, so that queuers can ask for completion on that specific CPU. In testing, this has been show to cut the system time by as much as 20-40% on synthetic workloads where CPU affinity is desired. This requires a little help from the architecture, so it'll only work as designed for archs that are using the new generic smp helper infrastructure. Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'include')
-rw-r--r--include/linux/bio.h11
-rw-r--r--include/linux/blkdev.h5
-rw-r--r--include/linux/elevator.h8
3 files changed, 19 insertions, 5 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 2c0c09034fd2..13aba20edb2d 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -81,6 +81,8 @@ struct bio {
81 81
82 unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ 82 unsigned int bi_max_vecs; /* max bvl_vecs we can hold */
83 83
84 unsigned int bi_comp_cpu; /* completion CPU */
85
84 struct bio_vec *bi_io_vec; /* the actual vec list */ 86 struct bio_vec *bi_io_vec; /* the actual vec list */
85 87
86 bio_end_io_t *bi_end_io; 88 bio_end_io_t *bi_end_io;
@@ -105,6 +107,7 @@ struct bio {
105#define BIO_BOUNCED 5 /* bio is a bounce bio */ 107#define BIO_BOUNCED 5 /* bio is a bounce bio */
106#define BIO_USER_MAPPED 6 /* contains user pages */ 108#define BIO_USER_MAPPED 6 /* contains user pages */
107#define BIO_EOPNOTSUPP 7 /* not supported */ 109#define BIO_EOPNOTSUPP 7 /* not supported */
110#define BIO_CPU_AFFINE 8 /* complete bio on same CPU as submitted */
108#define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) 111#define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag)))
109 112
110/* 113/*
@@ -343,6 +346,14 @@ extern struct bio_vec *bvec_alloc_bs(gfp_t, int, unsigned long *, struct bio_set
343extern unsigned int bvec_nr_vecs(unsigned short idx); 346extern unsigned int bvec_nr_vecs(unsigned short idx);
344 347
345/* 348/*
349 * Allow queuer to specify a completion CPU for this bio
350 */
351static inline void bio_set_completion_cpu(struct bio *bio, unsigned int cpu)
352{
353 bio->bi_comp_cpu = cpu;
354}
355
356/*
346 * bio_set is used to allow other portions of the IO system to 357 * bio_set is used to allow other portions of the IO system to
347 * allocate their own private memory pools for bio and iovec structures. 358 * allocate their own private memory pools for bio and iovec structures.
348 * These memory pools in turn all allocate from the bio_slab 359 * These memory pools in turn all allocate from the bio_slab
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 10aa46c8f170..93204bf7b297 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -17,6 +17,7 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/stringify.h> 18#include <linux/stringify.h>
19#include <linux/bsg.h> 19#include <linux/bsg.h>
20#include <linux/smp.h>
20 21
21#include <asm/scatterlist.h> 22#include <asm/scatterlist.h>
22 23
@@ -139,7 +140,8 @@ enum rq_flag_bits {
139 */ 140 */
140struct request { 141struct request {
141 struct list_head queuelist; 142 struct list_head queuelist;
142 struct list_head donelist; 143 struct call_single_data csd;
144 int cpu;
143 145
144 struct request_queue *q; 146 struct request_queue *q;
145 147
@@ -420,6 +422,7 @@ struct request_queue
420#define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */ 422#define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */
421#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */ 423#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */
422#define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */ 424#define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */
425#define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */
423 426
424static inline int queue_is_locked(struct request_queue *q) 427static inline int queue_is_locked(struct request_queue *q)
425{ 428{
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 639624b55fbe..bb791c311a56 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -173,15 +173,15 @@ enum {
173#define rb_entry_rq(node) rb_entry((node), struct request, rb_node) 173#define rb_entry_rq(node) rb_entry((node), struct request, rb_node)
174 174
175/* 175/*
176 * Hack to reuse the donelist list_head as the fifo time holder while 176 * Hack to reuse the csd.list list_head as the fifo time holder while
177 * the request is in the io scheduler. Saves an unsigned long in rq. 177 * the request is in the io scheduler. Saves an unsigned long in rq.
178 */ 178 */
179#define rq_fifo_time(rq) ((unsigned long) (rq)->donelist.next) 179#define rq_fifo_time(rq) ((unsigned long) (rq)->csd.list.next)
180#define rq_set_fifo_time(rq,exp) ((rq)->donelist.next = (void *) (exp)) 180#define rq_set_fifo_time(rq,exp) ((rq)->csd.list.next = (void *) (exp))
181#define rq_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) 181#define rq_entry_fifo(ptr) list_entry((ptr), struct request, queuelist)
182#define rq_fifo_clear(rq) do { \ 182#define rq_fifo_clear(rq) do { \
183 list_del_init(&(rq)->queuelist); \ 183 list_del_init(&(rq)->queuelist); \
184 INIT_LIST_HEAD(&(rq)->donelist); \ 184 INIT_LIST_HEAD(&(rq)->csd.list); \
185 } while (0) 185 } while (0)
186 186
187/* 187/*