]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
drivers/xen/blkback: Add the kernel side of the blkback queueing feature.
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 14 Aug 2009 16:28:43 +0000 (17:28 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 14 Aug 2009 16:28:43 +0000 (17:28 +0100)
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 <nenolod@dereferenced.org>
drivers/xen/blkback/blkback.c
drivers/xen/blkback/common.h
drivers/xen/blkback/xenbus.c

index 78311e32ceb9bf8f260a1eef130abd70340cc1f1..eed6a9e2c78829311d4a19c857c7b29a286e4807 100644 (file)
@@ -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;
index 6dff5e7612977d708cd9b6a85d42f0d2d522c335..c6cd00b4ecf2153f72e0d2a50bd4c4b27544a3b9 100644 (file)
@@ -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);
index 7e689c758117f299dc4969924ac8270168577b2e..f43dfe1ca1abb7c7a073ed41d2d1eb20dcd46ec5 100644 (file)
@@ -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) {