aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/xen-blkback
diff options
context:
space:
mode:
authorRoger Pau Monne <roger.pau@citrix.com>2013-04-17 14:18:59 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-04-18 09:29:25 -0400
commitbf0720c48c7cefd127ed2329e6d0e40b39fa4d0e (patch)
treefaece56f2dd1be19c6ae40676210004a599ed792 /drivers/block/xen-blkback
parentbb6acb289fbaac0e99eb552abdefc80a2186ef3f (diff)
xen-blkback: make the queue of free requests per backend
Remove the last dependency from blkbk by moving the list of free requests to blkif. This change reduces the contention on the list of available requests. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: xen-devel@lists.xen.org Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/block/xen-blkback')
-rw-r--r--drivers/block/xen-blkback/blkback.c123
-rw-r--r--drivers/block/xen-blkback/common.h30
-rw-r--r--drivers/block/xen-blkback/xenbus.c26
3 files changed, 74 insertions, 105 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index ae7dc92ad3cf..90a57552f4b7 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -50,20 +50,6 @@
50#include "common.h" 50#include "common.h"
51 51
52/* 52/*
53 * These are rather arbitrary. They are fairly large because adjacent requests
54 * pulled from a communication ring are quite likely to end up being part of
55 * the same scatter/gather request at the disc.
56 *
57 * ** TRY INCREASING 'xen_blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW **
58 *
59 * This will increase the chances of being able to write whole tracks.
60 * 64 should be enough to keep us competitive with Linux.
61 */
62static int xen_blkif_reqs = 64;
63module_param_named(reqs, xen_blkif_reqs, int, 0);
64MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate");
65
66/*
67 * Maximum number of unused free pages to keep in the internal buffer. 53 * Maximum number of unused free pages to keep in the internal buffer.
68 * Setting this to a value too low will reduce memory used in each backend, 54 * Setting this to a value too low will reduce memory used in each backend,
69 * but can have a performance penalty. 55 * but can have a performance penalty.
@@ -112,53 +98,11 @@ MODULE_PARM_DESC(max_persistent_grants,
112static unsigned int log_stats; 98static unsigned int log_stats;
113module_param(log_stats, int, 0644); 99module_param(log_stats, int, 0644);
114 100
115/*
116 * Each outstanding request that we've passed to the lower device layers has a
117 * 'pending_req' allocated to it. Each buffer_head that completes decrements
118 * the pendcnt towards zero. When it hits zero, the specified domain has a
119 * response queued for it, with the saved 'id' passed back.
120 */
121struct pending_req {
122 struct xen_blkif *blkif;
123 u64 id;
124 int nr_pages;
125 atomic_t pendcnt;
126 unsigned short operation;
127 int status;
128 struct list_head free_list;
129 struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
130 struct persistent_gnt *persistent_gnts[BLKIF_MAX_SEGMENTS_PER_REQUEST];
131 grant_handle_t grant_handles[BLKIF_MAX_SEGMENTS_PER_REQUEST];
132};
133
134#define BLKBACK_INVALID_HANDLE (~0) 101#define BLKBACK_INVALID_HANDLE (~0)
135 102
136/* Number of free pages to remove on each call to free_xenballooned_pages */ 103/* Number of free pages to remove on each call to free_xenballooned_pages */
137#define NUM_BATCH_FREE_PAGES 10 104#define NUM_BATCH_FREE_PAGES 10
138 105
139struct xen_blkbk {
140 struct pending_req *pending_reqs;
141 /* List of all 'pending_req' available */
142 struct list_head pending_free;
143 /* And its spinlock. */
144 spinlock_t pending_free_lock;
145 wait_queue_head_t pending_free_wq;
146};
147
148static struct xen_blkbk *blkbk;
149
150/*
151 * Little helpful macro to figure out the index and virtual address of the
152 * pending_pages[..]. For each 'pending_req' we have have up to
153 * BLKIF_MAX_SEGMENTS_PER_REQUEST (11) pages. The seg would be from 0 through
154 * 10 and would index in the pending_pages[..].
155 */
156static inline int vaddr_pagenr(struct pending_req *req, int seg)
157{
158 return (req - blkbk->pending_reqs) *
159 BLKIF_MAX_SEGMENTS_PER_REQUEST + seg;
160}
161
162static inline int get_free_page(struct xen_blkif *blkif, struct page **page) 106static inline int get_free_page(struct xen_blkif *blkif, struct page **page)
163{ 107{
164 unsigned long flags; 108 unsigned long flags;
@@ -485,18 +429,18 @@ finished:
485/* 429/*
486 * Retrieve from the 'pending_reqs' a free pending_req structure to be used. 430 * Retrieve from the 'pending_reqs' a free pending_req structure to be used.
487 */ 431 */
488static struct pending_req *alloc_req(void) 432static struct pending_req *alloc_req(struct xen_blkif *blkif)
489{ 433{
490 struct pending_req *req = NULL; 434 struct pending_req *req = NULL;
491 unsigned long flags; 435 unsigned long flags;
492 436
493 spin_lock_irqsave(&blkbk->pending_free_lock, flags); 437 spin_lock_irqsave(&blkif->pending_free_lock, flags);
494 if (!list_empty(&blkbk->pending_free)) { 438 if (!list_empty(&blkif->pending_free)) {
495 req = list_entry(blkbk->pending_free.next, struct pending_req, 439 req = list_entry(blkif->pending_free.next, struct pending_req,
496 free_list); 440 free_list);
497 list_del(&req->free_list); 441 list_del(&req->free_list);
498 } 442 }
499 spin_unlock_irqrestore(&blkbk->pending_free_lock, flags); 443 spin_unlock_irqrestore(&blkif->pending_free_lock, flags);
500 return req; 444 return req;
501} 445}
502 446
@@ -504,17 +448,17 @@ static struct pending_req *alloc_req(void)
504 * Return the 'pending_req' structure back to the freepool. We also 448 * Return the 'pending_req' structure back to the freepool. We also
505 * wake up the thread if it was waiting for a free page. 449 * wake up the thread if it was waiting for a free page.
506 */ 450 */
507static void free_req(struct pending_req *req) 451static void free_req(struct xen_blkif *blkif, struct pending_req *req)
508{ 452{
509 unsigned long flags; 453 unsigned long flags;
510 int was_empty; 454 int was_empty;
511 455
512 spin_lock_irqsave(&blkbk->pending_free_lock, flags); 456 spin_lock_irqsave(&blkif->pending_free_lock, flags);
513 was_empty = list_empty(&blkbk->pending_free); 457 was_empty = list_empty(&blkif->pending_free);
514 list_add(&req->free_list, &blkbk->pending_free); 458 list_add(&req->free_list, &blkif->pending_free);
515 spin_unlock_irqrestore(&blkbk->pending_free_lock, flags); 459 spin_unlock_irqrestore(&blkif->pending_free_lock, flags);
516 if (was_empty) 460 if (was_empty)
517 wake_up(&blkbk->pending_free_wq); 461 wake_up(&blkif->pending_free_wq);
518} 462}
519 463
520/* 464/*
@@ -649,8 +593,8 @@ int xen_blkif_schedule(void *arg)
649 if (timeout == 0) 593 if (timeout == 0)
650 goto purge_gnt_list; 594 goto purge_gnt_list;
651 timeout = wait_event_interruptible_timeout( 595 timeout = wait_event_interruptible_timeout(
652 blkbk->pending_free_wq, 596 blkif->pending_free_wq,
653 !list_empty(&blkbk->pending_free) || 597 !list_empty(&blkif->pending_free) ||
654 kthread_should_stop(), 598 kthread_should_stop(),
655 timeout); 599 timeout);
656 if (timeout == 0) 600 if (timeout == 0)
@@ -907,7 +851,7 @@ static int dispatch_other_io(struct xen_blkif *blkif,
907 struct blkif_request *req, 851 struct blkif_request *req,
908 struct pending_req *pending_req) 852 struct pending_req *pending_req)
909{ 853{
910 free_req(pending_req); 854 free_req(blkif, pending_req);
911 make_response(blkif, req->u.other.id, req->operation, 855 make_response(blkif, req->u.other.id, req->operation,
912 BLKIF_RSP_EOPNOTSUPP); 856 BLKIF_RSP_EOPNOTSUPP);
913 return -EIO; 857 return -EIO;
@@ -967,7 +911,7 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
967 if (atomic_read(&pending_req->blkif->drain)) 911 if (atomic_read(&pending_req->blkif->drain))
968 complete(&pending_req->blkif->drain_complete); 912 complete(&pending_req->blkif->drain_complete);
969 } 913 }
970 free_req(pending_req); 914 free_req(pending_req->blkif, pending_req);
971 } 915 }
972} 916}
973 917
@@ -1010,7 +954,7 @@ __do_block_io_op(struct xen_blkif *blkif)
1010 break; 954 break;
1011 } 955 }
1012 956
1013 pending_req = alloc_req(); 957 pending_req = alloc_req(blkif);
1014 if (NULL == pending_req) { 958 if (NULL == pending_req) {
1015 blkif->st_oo_req++; 959 blkif->st_oo_req++;
1016 more_to_do = 1; 960 more_to_do = 1;
@@ -1044,7 +988,7 @@ __do_block_io_op(struct xen_blkif *blkif)
1044 goto done; 988 goto done;
1045 break; 989 break;
1046 case BLKIF_OP_DISCARD: 990 case BLKIF_OP_DISCARD:
1047 free_req(pending_req); 991 free_req(blkif, pending_req);
1048 if (dispatch_discard_io(blkif, &req)) 992 if (dispatch_discard_io(blkif, &req))
1049 goto done; 993 goto done;
1050 break; 994 break;
@@ -1246,7 +1190,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
1246 fail_response: 1190 fail_response:
1247 /* Haven't submitted any bio's yet. */ 1191 /* Haven't submitted any bio's yet. */
1248 make_response(blkif, req->u.rw.id, req->operation, BLKIF_RSP_ERROR); 1192 make_response(blkif, req->u.rw.id, req->operation, BLKIF_RSP_ERROR);
1249 free_req(pending_req); 1193 free_req(blkif, pending_req);
1250 msleep(1); /* back off a bit */ 1194 msleep(1); /* back off a bit */
1251 return -EIO; 1195 return -EIO;
1252 1196
@@ -1303,51 +1247,20 @@ static void make_response(struct xen_blkif *blkif, u64 id,
1303 1247
1304static int __init xen_blkif_init(void) 1248static int __init xen_blkif_init(void)
1305{ 1249{
1306 int i;
1307 int rc = 0; 1250 int rc = 0;
1308 1251
1309 if (!xen_domain()) 1252 if (!xen_domain())
1310 return -ENODEV; 1253 return -ENODEV;
1311 1254
1312 blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL);
1313 if (!blkbk) {
1314 pr_alert(DRV_PFX "%s: out of memory!\n", __func__);
1315 return -ENOMEM;
1316 }
1317
1318
1319 blkbk->pending_reqs = kzalloc(sizeof(blkbk->pending_reqs[0]) *
1320 xen_blkif_reqs, GFP_KERNEL);
1321
1322 if (!blkbk->pending_reqs) {
1323 rc = -ENOMEM;
1324 goto out_of_memory;
1325 }
1326
1327 rc = xen_blkif_interface_init(); 1255 rc = xen_blkif_interface_init();
1328 if (rc) 1256 if (rc)
1329 goto failed_init; 1257 goto failed_init;
1330 1258
1331 INIT_LIST_HEAD(&blkbk->pending_free);
1332 spin_lock_init(&blkbk->pending_free_lock);
1333 init_waitqueue_head(&blkbk->pending_free_wq);
1334
1335 for (i = 0; i < xen_blkif_reqs; i++)
1336 list_add_tail(&blkbk->pending_reqs[i].free_list,
1337 &blkbk->pending_free);
1338
1339 rc = xen_blkif_xenbus_init(); 1259 rc = xen_blkif_xenbus_init();
1340 if (rc) 1260 if (rc)
1341 goto failed_init; 1261 goto failed_init;
1342 1262
1343 return 0;
1344
1345 out_of_memory:
1346 pr_alert(DRV_PFX "%s: out of memory\n", __func__);
1347 failed_init: 1263 failed_init:
1348 kfree(blkbk->pending_reqs);
1349 kfree(blkbk);
1350 blkbk = NULL;
1351 return rc; 1264 return rc;
1352} 1265}
1353 1266
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index af9bed48f773..e33fafa0facd 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -192,6 +192,9 @@ struct backend_info;
192 */ 192 */
193#define PERSISTENT_GNT_WAS_ACTIVE 1 193#define PERSISTENT_GNT_WAS_ACTIVE 1
194 194
195/* Number of requests that we can fit in a ring */
196#define XEN_BLKIF_REQS 32
197
195struct persistent_gnt { 198struct persistent_gnt {
196 struct page *page; 199 struct page *page;
197 grant_ref_t gnt; 200 grant_ref_t gnt;
@@ -242,6 +245,14 @@ struct xen_blkif {
242 int free_pages_num; 245 int free_pages_num;
243 struct list_head free_pages; 246 struct list_head free_pages;
244 247
248 /* Allocation of pending_reqs */
249 struct pending_req *pending_reqs;
250 /* List of all 'pending_req' available */
251 struct list_head pending_free;
252 /* And its spinlock. */
253 spinlock_t pending_free_lock;
254 wait_queue_head_t pending_free_wq;
255
245 /* statistics */ 256 /* statistics */
246 unsigned long st_print; 257 unsigned long st_print;
247 unsigned long long st_rd_req; 258 unsigned long long st_rd_req;
@@ -255,6 +266,25 @@ struct xen_blkif {
255 wait_queue_head_t waiting_to_free; 266 wait_queue_head_t waiting_to_free;
256}; 267};
257 268
269/*
270 * Each outstanding request that we've passed to the lower device layers has a
271 * 'pending_req' allocated to it. Each buffer_head that completes decrements
272 * the pendcnt towards zero. When it hits zero, the specified domain has a
273 * response queued for it, with the saved 'id' passed back.
274 */
275struct pending_req {
276 struct xen_blkif *blkif;
277 u64 id;
278 int nr_pages;
279 atomic_t pendcnt;
280 unsigned short operation;
281 int status;
282 struct list_head free_list;
283 struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
284 struct persistent_gnt *persistent_gnts[BLKIF_MAX_SEGMENTS_PER_REQUEST];
285 grant_handle_t grant_handles[BLKIF_MAX_SEGMENTS_PER_REQUEST];
286};
287
258 288
259#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ 289#define vbd_sz(_v) ((_v)->bdev->bd_part ? \
260 (_v)->bdev->bd_part->nr_sects : \ 290 (_v)->bdev->bd_part->nr_sects : \
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index e0fd92a2a4cd..1f1ade6d6e09 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -105,6 +105,7 @@ static void xen_update_blkif_status(struct xen_blkif *blkif)
105static struct xen_blkif *xen_blkif_alloc(domid_t domid) 105static struct xen_blkif *xen_blkif_alloc(domid_t domid)
106{ 106{
107 struct xen_blkif *blkif; 107 struct xen_blkif *blkif;
108 int i;
108 109
109 blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL); 110 blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
110 if (!blkif) 111 if (!blkif)
@@ -124,6 +125,21 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
124 blkif->free_pages_num = 0; 125 blkif->free_pages_num = 0;
125 atomic_set(&blkif->persistent_gnt_in_use, 0); 126 atomic_set(&blkif->persistent_gnt_in_use, 0);
126 127
128 blkif->pending_reqs = kcalloc(XEN_BLKIF_REQS,
129 sizeof(blkif->pending_reqs[0]),
130 GFP_KERNEL);
131 if (!blkif->pending_reqs) {
132 kmem_cache_free(xen_blkif_cachep, blkif);
133 return ERR_PTR(-ENOMEM);
134 }
135 INIT_LIST_HEAD(&blkif->pending_free);
136 spin_lock_init(&blkif->pending_free_lock);
137 init_waitqueue_head(&blkif->pending_free_wq);
138
139 for (i = 0; i < XEN_BLKIF_REQS; i++)
140 list_add_tail(&blkif->pending_reqs[i].free_list,
141 &blkif->pending_free);
142
127 return blkif; 143 return blkif;
128} 144}
129 145
@@ -203,8 +219,18 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
203 219
204static void xen_blkif_free(struct xen_blkif *blkif) 220static void xen_blkif_free(struct xen_blkif *blkif)
205{ 221{
222 struct pending_req *req;
223 int i = 0;
224
206 if (!atomic_dec_and_test(&blkif->refcnt)) 225 if (!atomic_dec_and_test(&blkif->refcnt))
207 BUG(); 226 BUG();
227
228 /* Check that there is no request in use */
229 list_for_each_entry(req, &blkif->pending_free, free_list)
230 i++;
231 BUG_ON(i != XEN_BLKIF_REQS);
232
233 kfree(blkif->pending_reqs);
208 kmem_cache_free(xen_blkif_cachep, blkif); 234 kmem_cache_free(xen_blkif_cachep, blkif);
209} 235}
210 236