From: Keir Fraser Date: Fri, 14 Aug 2009 16:28:43 +0000 (+0100) Subject: drivers/xen/blkback: Add the kernel side of the blkback queueing feature. X-Git-Tag: xen-3.4.2~14 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=65af1b39619444a86e5952dc9b78e2e207fb7c6e;p=legacy%2Flinux-2.6.18-xen.git drivers/xen/blkback: Add the kernel side of the blkback queueing feature. This is similar to the credit scheduler used in netif, except that it allows occasional burstability (for use with e2fsck as an example). Signed-off-by: William Pitcock --- diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c index 78311e32..eed6a9e2 100644 --- a/drivers/xen/blkback/blkback.c +++ b/drivers/xen/blkback/blkback.c @@ -200,6 +200,16 @@ static void print_stats(blkif_t *blkif) blkif->st_oo_req = 0; } +static void refill_credit(blkif_t *blkif) +{ + blkif->credit_time = jiffies + msecs_to_jiffies(blkif->credit_msec); + blkif->available_credit += blkif->credit_req; + + /* this allows for bursting. */ + if (blkif->available_credit > (blkif->credit_req * blkif->credit_msec)) + blkif->available_credit = blkif->credit_req; +} + int blkif_schedule(void *arg) { blkif_t *blkif = arg; @@ -227,6 +237,9 @@ int blkif_schedule(void *arg) blkif->waiting_reqs = 1; unplug_queue(blkif); + if (time_after(jiffies, blkif->credit_time)) + refill_credit(blkif); + if (log_stats && time_after(jiffies, blkif->st_print)) print_stats(blkif); } @@ -313,11 +326,23 @@ static int do_block_io_op(blkif_t *blkif) rp = blk_rings->common.sring->req_prod; rmb(); /* Ensure we see queued requests up to 'rp'. */ + /* if there's no available request credit right now, and limiting + * is requested, then don't bother with going any further. + */ + if (blkif->remaining_credit <= 0 && blkif->credit_req != 0) + return (rc != rp) ? 1 : 0; + while (rc != rp) { if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) break; + /* FIXME: Should we report QoS overages as VBD_OO, or not? */ + if (blkif->credit_req != 0 && --blkif->remaining_credit <= 0) { + more_to_do = 1; + break; + } + if (kthread_should_stop()) { more_to_do = 1; break; diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h index 6dff5e76..c6cd00b4 100644 --- a/drivers/xen/blkback/common.h +++ b/drivers/xen/blkback/common.h @@ -96,6 +96,11 @@ typedef struct blkif_st { grant_handle_t shmem_handle; grant_ref_t shmem_ref; + + int credit_req; + int remaining_credit; + int credit_msec; + unsigned long credit_time; } blkif_t; blkif_t *blkif_alloc(domid_t domid); diff --git a/drivers/xen/blkback/xenbus.c b/drivers/xen/blkback/xenbus.c index 7e689c75..f43dfe1c 100644 --- a/drivers/xen/blkback/xenbus.c +++ b/drivers/xen/blkback/xenbus.c @@ -255,6 +255,42 @@ fail: return err; } +static void blkback_read_credit(struct xenbus_transaction xbt, + struct xenbus_device *dev, + unsigned long *credit, unsigned long *msec) +{ + char *s, *e; + unsigned long b, u; + char *ratestr; + + /* Default to unlimited I/O operations. */ + *credit = ~0UL; + *usec = 0; + + ratestr = xenbus_read(xbt, dev->nodename, "credit", NULL); + if (IS_ERR(ratestr)) + return; + + s = ratestr; + b = simple_strtoul(s, &e, 10); + if ((s == e) || (*e != ',')) + goto fail; + + s = e + 1; + u = simple_strtoul(s, &e, 10); + if ((s == e) || (*e != '\0')) + goto fail; + + *credit = b; + *msec = (u / 1000); + + kfree(ratestr); + return; + + fail: + WPRINTK("Failed to parse I/O credit limit. I/O operations are unlimited.\n"); + kfree(ratestr); +} /** * Callback received when the hotplug scripts have placed the physical-device @@ -401,6 +437,7 @@ static void frontend_changed(struct xenbus_device *dev, /* ** Connection ** */ + /** * Write the physical details regarding the block device to the store, and * switch to Connected state. @@ -425,6 +462,10 @@ again: if (err) goto abort; + blkback_read_credit(xbt, dev, &be->blkif->credit_req, + &be->blkif->credit_msec); + be->blkif->remaining_credit = be->blkif->credit_req; + err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", vbd_size(&be->blkif->vbd)); if (err) {