From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: Bob Liu <bob.liu@oracle.com>
Cc: jonathan.davies@citrix.com, felipe.franciosi@citrix.com,
rafal.mielniczuk@citrix.com, linux-kernel@vger.kernel.org,
xen-devel@lists.xen.org, axboe@fb.com, david.vrabel@citrix.com,
avanzini.arianna@gmail.com, roger.pau@citrix.com
Subject: Re: [PATCH v4 03/10] xen/blkfront: pseudo support for multi hardware queues/rings
Date: Tue, 3 Nov 2015 14:44:36 -0500 [thread overview]
Message-ID: <20151103194436.GE28527@char.us.oracle.com> (raw)
In-Reply-To: <1446438106-20171-4-git-send-email-bob.liu@oracle.com>
On Mon, Nov 02, 2015 at 12:21:39PM +0800, Bob Liu wrote:
> Preparatory patch for multiple hardware queues (rings). The number of
> rings is unconditionally set to 1, larger number will be enabled in next
> patch so as to make every single patch small and readable.
s/next patch/"xen/blkfront: negotiate number of queues/rings to be used with backend"
>
> Signed-off-by: Bob Liu <bob.liu@oracle.com>
> ---
> drivers/block/xen-blkfront.c | 327 +++++++++++++++++++++++++------------------
> 1 file changed, 188 insertions(+), 139 deletions(-)
>
> diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
> index 2a557e4..eab78e7 100644
> --- a/drivers/block/xen-blkfront.c
> +++ b/drivers/block/xen-blkfront.c
> @@ -145,6 +145,7 @@ struct blkfront_info
> int vdevice;
> blkif_vdev_t handle;
> enum blkif_state connected;
> + /* Number of pages per ring buffer */
Missing full stop, aka '.'.
> unsigned int nr_ring_pages;
> struct request_queue *rq;
> struct list_head grants;
> @@ -158,7 +159,8 @@ struct blkfront_info
> unsigned int max_indirect_segments;
> int is_ready;
> struct blk_mq_tag_set tag_set;
> - struct blkfront_ring_info rinfo;
> + struct blkfront_ring_info *rinfo;
> + unsigned int nr_rings;
> };
>
> static unsigned int nr_minors;
> @@ -190,7 +192,7 @@ static DEFINE_SPINLOCK(minor_lock);
> ((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
>
> static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo);
> -static int blkfront_gather_backend_features(struct blkfront_info *info);
> +static void blkfront_gather_backend_features(struct blkfront_info *info);
>
> static int get_id_from_freelist(struct blkfront_ring_info *rinfo)
> {
> @@ -443,12 +445,13 @@ static int blkif_queue_request(struct request *req, struct blkfront_ring_info *r
> */
> max_grefs += INDIRECT_GREFS(req->nr_phys_segments);
>
> - /* Check if we have enough grants to allocate a requests */
> - if (info->persistent_gnts_c < max_grefs) {
> + /* Check if we have enough grants to allocate a requests, we have to
> + * reserve 'max_grefs' grants because persistent grants are shared by all
> + * rings */
Missing full stop.
> + if (0 < max_grefs) {
<blinks> ? 0!?
max_grefs will at least be BLKIF_MAX_SEGMENTS_PER_REQUEST
so this will always be true.
In which ase why not just ..
> new_persistent_gnts = 1;
> if (gnttab_alloc_grant_references(
> - max_grefs - info->persistent_gnts_c,
> - &gref_head) < 0) {
> + max_grefs, &gref_head) < 0) {
> gnttab_request_free_callback(
> &rinfo->callback,
> blkif_restart_queue_callback,
.. move this whole code down? And get rid of 'new_persistent_gnts'
since it will always be true?
But more importantly, why do we not check for 'info->persistent_gnts_c' anymore?
> @@ -665,7 +668,7 @@ static int blk_mq_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
> {
> struct blkfront_info *info = (struct blkfront_info *)data;
>
> - hctx->driver_data = &info->rinfo;
> + hctx->driver_data = &info->rinfo[index];
Please add an ASSERT here to check to make sure
that info->nr_rings < index.
> return 0;
> }
>
> @@ -924,8 +927,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
>
> static void xlvbd_release_gendisk(struct blkfront_info *info)
> {
> - unsigned int minor, nr_minors;
> - struct blkfront_ring_info *rinfo = &info->rinfo;
> + unsigned int minor, nr_minors, i;
>
> if (info->rq == NULL)
> return;
> @@ -933,11 +935,15 @@ static void xlvbd_release_gendisk(struct blkfront_info *info)
> /* No more blkif_request(). */
> blk_mq_stop_hw_queues(info->rq);
>
> - /* No more gnttab callback work. */
> - gnttab_cancel_free_callback(&rinfo->callback);
> + for (i = 0; i < info->nr_rings; i++) {
> + struct blkfront_ring_info *rinfo = &info->rinfo[i];
>
> - /* Flush gnttab callback work. Must be done with no locks held. */
> - flush_work(&rinfo->work);
> + /* No more gnttab callback work. */
> + gnttab_cancel_free_callback(&rinfo->callback);
> +
> + /* Flush gnttab callback work. Must be done with no locks held. */
> + flush_work(&rinfo->work);
> + }
>
> del_gendisk(info->gd);
>
> @@ -970,37 +976,11 @@ static void blkif_restart_queue(struct work_struct *work)
> spin_unlock_irq(&rinfo->dev_info->io_lock);
> }
>
> -static void blkif_free(struct blkfront_info *info, int suspend)
> +static void blkif_free_ring(struct blkfront_ring_info *rinfo)
> {
> struct grant *persistent_gnt;
> - struct grant *n;
> + struct blkfront_info *info = rinfo->dev_info;
> int i, j, segs;
> - struct blkfront_ring_info *rinfo = &info->rinfo;
> -
> - /* Prevent new requests being issued until we fix things up. */
> - spin_lock_irq(&info->io_lock);
> - info->connected = suspend ?
> - BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
> - /* No more blkif_request(). */
> - if (info->rq)
> - blk_mq_stop_hw_queues(info->rq);
> -
> - /* Remove all persistent grants */
> - if (!list_empty(&info->grants)) {
> - list_for_each_entry_safe(persistent_gnt, n,
> - &info->grants, node) {
> - list_del(&persistent_gnt->node);
> - if (persistent_gnt->gref != GRANT_INVALID_REF) {
> - gnttab_end_foreign_access(persistent_gnt->gref,
> - 0, 0UL);
> - info->persistent_gnts_c--;
> - }
> - if (info->feature_persistent)
> - __free_page(pfn_to_page(persistent_gnt->pfn));
> - kfree(persistent_gnt);
> - }
> - }
> - BUG_ON(info->persistent_gnts_c != 0);
>
> /*
> * Remove indirect pages, this only happens when using indirect
> @@ -1060,7 +1040,6 @@ free_shadow:
>
> /* No more gnttab callback work. */
> gnttab_cancel_free_callback(&rinfo->callback);
> - spin_unlock_irq(&info->io_lock);
>
> /* Flush gnttab callback work. Must be done with no locks held. */
> flush_work(&rinfo->work);
> @@ -1078,7 +1057,41 @@ free_shadow:
> if (rinfo->irq)
> unbind_from_irqhandler(rinfo->irq, rinfo);
> rinfo->evtchn = rinfo->irq = 0;
> +}
>
> +static void blkif_free(struct blkfront_info *info, int suspend)
> +{
> + struct grant *persistent_gnt, *n;
> + int i;
> +
> + /* Prevent new requests being issued until we fix things up. */
> + spin_lock_irq(&info->io_lock);
> + info->connected = suspend ?
> + BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
> + /* No more blkif_request(). */
> + if (info->rq)
> + blk_mq_stop_hw_queues(info->rq);
> +
> + /* Remove all persistent grants */
> + if (!list_empty(&info->grants)) {
> + list_for_each_entry_safe(persistent_gnt, n,
> + &info->grants, node) {
> + list_del(&persistent_gnt->node);
> + if (persistent_gnt->gref != GRANT_INVALID_REF) {
> + gnttab_end_foreign_access(persistent_gnt->gref,
> + 0, 0UL);
> + info->persistent_gnts_c--;
> + }
> + if (info->feature_persistent)
> + __free_page(pfn_to_page(persistent_gnt->pfn));
> + kfree(persistent_gnt);
> + }
> + }
> + BUG_ON(info->persistent_gnts_c != 0);
> +
> + for (i = 0; i < info->nr_rings; i++)
> + blkif_free_ring(&info->rinfo[i]);
Shouldn't you also kfree info->rinfo here and reset nr_rings to zero?
And make info->rinfo[i]= NULL;
Otherwise I can see:
blkback_changed
\- talk_to_blkback (and failing)
| \->blkif_free
| \-> blkif_free_ring
|
\-- > kfree(info)
And memory leak of info->rinfo[0..nr_rings]
> + spin_unlock_irq(&info->io_lock);
> }
>
> static void blkif_completion(struct blk_shadow *s, struct blkfront_ring_info *rinfo,
> @@ -1334,7 +1347,7 @@ static int talk_to_blkback(struct xenbus_device *dev,
> int err, i;
> unsigned int max_page_order = 0;
> unsigned int ring_page_order = 0;
> - struct blkfront_ring_info *rinfo = &info->rinfo;
> + struct blkfront_ring_info *rinfo;
>
> err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
> "max-ring-page-order", "%u", &max_page_order);
> @@ -1345,10 +1358,13 @@ static int talk_to_blkback(struct xenbus_device *dev,
> info->nr_ring_pages = 1 << ring_page_order;
> }
>
> - /* Create shared ring, alloc event channel. */
> - err = setup_blkring(dev, rinfo);
> - if (err)
> - goto out;
> + for (i = 0; i < info->nr_rings; i++) {
> + rinfo = &info->rinfo[i];
> + /* Create shared ring, alloc event channel. */
> + err = setup_blkring(dev, rinfo);
> + if (err)
> + goto destroy_blkring;
> + }
>
> again:
> err = xenbus_transaction_start(&xbt);
> @@ -1357,37 +1373,43 @@ again:
> goto destroy_blkring;
> }
>
> - if (info->nr_ring_pages == 1) {
> - err = xenbus_printf(xbt, dev->nodename,
> - "ring-ref", "%u", rinfo->ring_ref[0]);
> - if (err) {
> - message = "writing ring-ref";
> - goto abort_transaction;
> - }
> - } else {
> - err = xenbus_printf(xbt, dev->nodename,
> - "ring-page-order", "%u", ring_page_order);
> - if (err) {
> - message = "writing ring-page-order";
> - goto abort_transaction;
> - }
> -
> - for (i = 0; i < info->nr_ring_pages; i++) {
> - char ring_ref_name[RINGREF_NAME_LEN];
> -
> - snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
> - err = xenbus_printf(xbt, dev->nodename, ring_ref_name,
> - "%u", rinfo->ring_ref[i]);
> + if (info->nr_rings == 1) {
> + rinfo = &info->rinfo[0];
> + if (info->nr_ring_pages == 1) {
> + err = xenbus_printf(xbt, dev->nodename,
> + "ring-ref", "%u", rinfo->ring_ref[0]);
> if (err) {
> message = "writing ring-ref";
> goto abort_transaction;
> }
> + } else {
> + err = xenbus_printf(xbt, dev->nodename,
> + "ring-page-order", "%u", ring_page_order);
> + if (err) {
> + message = "writing ring-page-order";
> + goto abort_transaction;
> + }
> +
> + for (i = 0; i < info->nr_ring_pages; i++) {
> + char ring_ref_name[RINGREF_NAME_LEN];
> +
> + snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
> + err = xenbus_printf(xbt, dev->nodename, ring_ref_name,
> + "%u", rinfo->ring_ref[i]);
> + if (err) {
> + message = "writing ring-ref";
> + goto abort_transaction;
> + }
> + }
> }
> - }
> - err = xenbus_printf(xbt, dev->nodename,
> - "event-channel", "%u", rinfo->evtchn);
> - if (err) {
> - message = "writing event-channel";
> + err = xenbus_printf(xbt, dev->nodename,
> + "event-channel", "%u", rinfo->evtchn);
> + if (err) {
> + message = "writing event-channel";
> + goto abort_transaction;
> + }
> + } else {
> + /* Not supported at this stage */
Missing full stop.
> goto abort_transaction;
> }
> err = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
> @@ -1410,9 +1432,14 @@ again:
> goto destroy_blkring;
> }
>
> - for (i = 0; i < BLK_RING_SIZE(info); i++)
> - rinfo->shadow[i].req.u.rw.id = i+1;
> - rinfo->shadow[BLK_RING_SIZE(info)-1].req.u.rw.id = 0x0fffffff;
> + for (i = 0; i < info->nr_rings; i++) {
> + int j;
> + rinfo = &info->rinfo[i];
> +
> + for (j = 0; j < BLK_RING_SIZE(info); j++)
> + rinfo->shadow[j].req.u.rw.id = j + 1;
> + rinfo->shadow[BLK_RING_SIZE(info)-1].req.u.rw.id = 0x0fffffff;
> + }
> xenbus_switch_state(dev, XenbusStateInitialised);
>
> return 0;
> @@ -1423,7 +1450,7 @@ again:
> xenbus_dev_fatal(dev, err, "%s", message);
> destroy_blkring:
> blkif_free(info, 0);
> - out:
> +
> return err;
> }
>
> @@ -1436,9 +1463,8 @@ again:
> static int blkfront_probe(struct xenbus_device *dev,
> const struct xenbus_device_id *id)
> {
> - int err, vdevice;
> + int err, vdevice, r_index;
> struct blkfront_info *info;
> - struct blkfront_ring_info *rinfo;
>
> /* FIXME: Use dynamic device id if this is not set. */
> err = xenbus_scanf(XBT_NIL, dev->nodename,
> @@ -1488,10 +1514,22 @@ static int blkfront_probe(struct xenbus_device *dev,
> return -ENOMEM;
> }
>
> - rinfo = &info->rinfo;
> - INIT_LIST_HEAD(&rinfo->indirect_pages);
> - rinfo->dev_info = info;
> - INIT_WORK(&rinfo->work, blkif_restart_queue);
> + info->nr_rings = 1;
> + info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL);
> + if (!info->rinfo) {
> + xenbus_dev_fatal(dev, -ENOMEM, "allocating ring_info structure");
> + kfree(info);
> + return -ENOMEM;
> + }
> +
> + for (r_index = 0; r_index < info->nr_rings; r_index++) {
> + struct blkfront_ring_info *rinfo;
> +
> + rinfo = &info->rinfo[r_index];
> + INIT_LIST_HEAD(&rinfo->indirect_pages);
> + rinfo->dev_info = info;
> + INIT_WORK(&rinfo->work, blkif_restart_queue);
> + }
>
> mutex_init(&info->mutex);
> spin_lock_init(&info->io_lock);
> @@ -1523,7 +1561,7 @@ static void split_bio_end(struct bio *bio)
>
> static int blkif_recover(struct blkfront_info *info)
> {
> - int i;
> + int i, r_index;
> struct request *req, *n;
> struct blk_shadow *copy;
> int rc;
> @@ -1533,57 +1571,62 @@ static int blkif_recover(struct blkfront_info *info)
> int pending, size;
> struct split_bio *split_bio;
> struct list_head requests;
> - struct blkfront_ring_info *rinfo = &info->rinfo;
> -
> - /* Stage 1: Make a safe copy of the shadow state. */
> - copy = kmemdup(rinfo->shadow, sizeof(rinfo->shadow),
> - GFP_NOIO | __GFP_REPEAT | __GFP_HIGH);
> - if (!copy)
> - return -ENOMEM;
> -
> - /* Stage 2: Set up free list. */
> - memset(&rinfo->shadow, 0, sizeof(rinfo->shadow));
> - for (i = 0; i < BLK_RING_SIZE(info); i++)
> - rinfo->shadow[i].req.u.rw.id = i+1;
> - rinfo->shadow_free = rinfo->ring.req_prod_pvt;
> - rinfo->shadow[BLK_RING_SIZE(info)-1].req.u.rw.id = 0x0fffffff;
> -
> - rc = blkfront_gather_backend_features(info);
> - if (rc) {
> - kfree(copy);
> - return rc;
> - }
>
> + blkfront_gather_backend_features(info);
> segs = info->max_indirect_segments ? : BLKIF_MAX_SEGMENTS_PER_REQUEST;
> blk_queue_max_segments(info->rq, segs);
> bio_list_init(&bio_list);
> INIT_LIST_HEAD(&requests);
> - for (i = 0; i < BLK_RING_SIZE(info); i++) {
> - /* Not in use? */
> - if (!copy[i].request)
> - continue;
>
> - /*
> - * Get the bios in the request so we can re-queue them.
> - */
> - if (copy[i].request->cmd_flags &
> - (REQ_FLUSH | REQ_FUA | REQ_DISCARD | REQ_SECURE)) {
> + for (r_index = 0; r_index < info->nr_rings; r_index++) {
This could have been moved to a seperate function. Then you only need
to call the function within the loop.
It is up to you however.
> + struct blkfront_ring_info *rinfo;
> +
> + rinfo = &info->rinfo[r_index];
> + /* Stage 1: Make a safe copy of the shadow state. */
> + copy = kmemdup(rinfo->shadow, sizeof(rinfo->shadow),
> + GFP_NOIO | __GFP_REPEAT | __GFP_HIGH);
> + if (!copy)
> + return -ENOMEM;
> +
> + /* Stage 2: Set up free list. */
> + memset(&rinfo->shadow, 0, sizeof(rinfo->shadow));
> + for (i = 0; i < BLK_RING_SIZE(info); i++)
> + rinfo->shadow[i].req.u.rw.id = i+1;
> + rinfo->shadow_free = rinfo->ring.req_prod_pvt;
> + rinfo->shadow[BLK_RING_SIZE(info)-1].req.u.rw.id = 0x0fffffff;
> +
> + rc = blkfront_setup_indirect(rinfo);
> + if (rc) {
> + kfree(copy);
> + return rc;
> + }
> +
> + for (i = 0; i < BLK_RING_SIZE(info); i++) {
> + /* Not in use? */
> + if (!copy[i].request)
> + continue;
> +
> /*
> - * Flush operations don't contain bios, so
> - * we need to requeue the whole request
> + * Get the bios in the request so we can re-queue them.
> */
> - list_add(©[i].request->queuelist, &requests);
> - continue;
> + if (copy[i].request->cmd_flags &
> + (REQ_FLUSH | REQ_FUA | REQ_DISCARD | REQ_SECURE)) {
> + /*
> + * Flush operations don't contain bios, so
> + * we need to requeue the whole request
> + */
> + list_add(©[i].request->queuelist, &requests);
> + continue;
> + }
> + merge_bio.head = copy[i].request->bio;
> + merge_bio.tail = copy[i].request->biotail;
> + bio_list_merge(&bio_list, &merge_bio);
> + copy[i].request->bio = NULL;
> + blk_end_request_all(copy[i].request, 0);
> }
> - merge_bio.head = copy[i].request->bio;
> - merge_bio.tail = copy[i].request->biotail;
> - bio_list_merge(&bio_list, &merge_bio);
> - copy[i].request->bio = NULL;
> - blk_end_request_all(copy[i].request, 0);
> - }
> -
> - kfree(copy);
>
> + kfree(copy);
> + }
> xenbus_switch_state(info->xbdev, XenbusStateConnected);
>
> spin_lock_irq(&info->io_lock);
> @@ -1591,8 +1634,13 @@ static int blkif_recover(struct blkfront_info *info)
> /* Now safe for us to use the shared ring */
> info->connected = BLKIF_STATE_CONNECTED;
>
> - /* Kick any other new requests queued since we resumed */
> - kick_pending_request_queues(rinfo);
> + for (r_index = 0; r_index < info->nr_rings; r_index++) {
> + struct blkfront_ring_info *rinfo;
> +
> + rinfo = &info->rinfo[r_index];
> + /* Kick any other new requests queued since we resumed */
> + kick_pending_request_queues(rinfo);
> + }
>
> list_for_each_entry_safe(req, n, &requests, queuelist) {
> /* Requeue pending requests (flush or discard) */
> @@ -1801,7 +1849,7 @@ out_of_memory:
> /*
> * Gather all backend feature-*
> */
> -static int blkfront_gather_backend_features(struct blkfront_info *info)
> +static void blkfront_gather_backend_features(struct blkfront_info *info)
> {
> int err;
> int barrier, flush, discard, persistent;
> @@ -1856,8 +1904,6 @@ static int blkfront_gather_backend_features(struct blkfront_info *info)
> else
> info->max_indirect_segments = min(indirect_segments,
> xen_blkif_max_segments);
> -
> - return blkfront_setup_indirect(&info->rinfo);
Aaah nice. That was always bothering me in the code that is suppose
to just gather data.
> }
>
> /*
> @@ -1870,8 +1916,7 @@ static void blkfront_connect(struct blkfront_info *info)
> unsigned long sector_size;
> unsigned int physical_sector_size;
> unsigned int binfo;
> - int err;
> - struct blkfront_ring_info *rinfo = &info->rinfo;
> + int err, i;
>
> switch (info->connected) {
> case BLKIF_STATE_CONNECTED:
> @@ -1928,11 +1973,14 @@ static void blkfront_connect(struct blkfront_info *info)
> if (err != 1)
> physical_sector_size = sector_size;
>
> - err = blkfront_gather_backend_features(info);
> - if (err) {
> - xenbus_dev_fatal(info->xbdev, err, "setup_indirect at %s",
> - info->xbdev->otherend);
> - return;
> + blkfront_gather_backend_features(info);
> + for (i = 0; i < info->nr_rings; i++) {
> + err = blkfront_setup_indirect(&info->rinfo[i]);
> + if (err) {
> + xenbus_dev_fatal(info->xbdev, err, "setup_indirect at %s",
> + info->xbdev->otherend);
> + blkif_free(info, 0);
Missing 'break.'
And you may want to set nr->rings = i temporarily so that the blkif_free_ring
does not needlessly iterate over all the rings (even thouse that
hadn't been initialized)... But it does not matter that much as blkif_free_ring
should be able to handle an unitialized ring.
And naturally you should also kfree the info->rinfo[].. but if you
add that in blkif_free then that will be taken care of.
> + }
> }
>
> err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size,
> @@ -1948,7 +1996,8 @@ static void blkfront_connect(struct blkfront_info *info)
> /* Kick pending requests. */
> spin_lock_irq(&info->io_lock);
> info->connected = BLKIF_STATE_CONNECTED;
> - kick_pending_request_queues(rinfo);
> + for (i = 0; i < info->nr_rings; i++)
> + kick_pending_request_queues(&info->rinfo[i]);
> spin_unlock_irq(&info->io_lock);
>
> add_disk(info->gd);
> @@ -2111,7 +2160,7 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)
> dev_info(disk_to_dev(bdev->bd_disk), "releasing disk\n");
> xlvbd_release_gendisk(info);
> xenbus_frontend_closed(info->xbdev);
> - }
> + }
???
>
> mutex_unlock(&info->mutex);
>
> --
> 1.8.3.1
>
next prev parent reply other threads:[~2015-11-03 19:44 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-02 4:21 [PATCH v4 00/10] xen-block: multi hardware-queues/rings support Bob Liu
2015-11-02 4:21 ` [PATCH v4 01/10] xen/blkif: document blkif multi-queue/ring extension Bob Liu
2015-11-03 18:01 ` Konrad Rzeszutek Wilk
2015-11-02 4:21 ` Bob Liu
2015-11-02 4:21 ` [PATCH v4 02/10] xen/blkfront: separate per ring information out of device info Bob Liu
2015-11-02 4:49 ` kbuild test robot
2015-11-02 4:49 ` kbuild test robot
2015-11-02 5:33 ` Bob Liu
2015-11-02 5:33 ` Bob Liu
2015-11-03 19:09 ` Konrad Rzeszutek Wilk
2015-11-02 4:21 ` Bob Liu
2015-11-02 4:21 ` [PATCH v4 03/10] xen/blkfront: pseudo support for multi hardware queues/rings Bob Liu
2015-11-02 4:21 ` Bob Liu
2015-11-03 19:44 ` Konrad Rzeszutek Wilk [this message]
2015-11-04 1:01 ` Bob Liu
2015-11-04 2:03 ` Konrad Rzeszutek Wilk
2015-11-04 1:01 ` Bob Liu
2015-11-02 4:21 ` [PATCH v4 04/10] xen/blkfront: split per device io_lock Bob Liu
2015-11-02 4:21 ` Bob Liu
2015-11-03 20:09 ` Konrad Rzeszutek Wilk
2015-11-04 1:07 ` Bob Liu
2015-11-04 1:07 ` Bob Liu
2015-11-04 1:51 ` Konrad Rzeszutek Wilk
2015-11-04 1:51 ` Konrad Rzeszutek Wilk
2015-11-02 4:21 ` [PATCH v4 05/10] xen/blkfront: negotiate number of queues/rings to be used with backend Bob Liu
2015-11-02 4:21 ` Bob Liu
2015-11-03 20:40 ` Konrad Rzeszutek Wilk
2015-11-04 1:11 ` Bob Liu
2015-11-04 1:53 ` Konrad Rzeszutek Wilk
2015-11-04 1:53 ` Konrad Rzeszutek Wilk
2015-11-04 1:11 ` Bob Liu
2015-11-02 4:21 ` [PATCH v4 06/10] xen/blkback: separate ring information out of struct xen_blkif Bob Liu
2015-11-02 4:21 ` Bob Liu
2015-11-03 21:37 ` Konrad Rzeszutek Wilk
2015-11-02 4:21 ` [PATCH v4 07/10] xen/blkback: pseudo support for multi hardware queues/rings Bob Liu
2015-11-02 4:21 ` Bob Liu
2015-11-05 2:30 ` Konrad Rzeszutek Wilk
2015-11-05 3:02 ` Bob Liu
2015-11-05 3:02 ` Bob Liu
2015-11-05 3:24 ` Konrad Rzeszutek Wilk
2015-11-05 3:24 ` Konrad Rzeszutek Wilk
2015-11-05 2:30 ` Konrad Rzeszutek Wilk
2015-11-02 4:21 ` [PATCH v4 08/10] xen/blkback: get the number of hardware queues/rings from blkfront Bob Liu
2015-11-02 4:21 ` Bob Liu
2015-11-05 2:37 ` Konrad Rzeszutek Wilk
2015-11-05 2:37 ` Konrad Rzeszutek Wilk
2015-11-02 4:21 ` [PATCH v4 09/10] xen/blkfront: make persistent grants per-queue Bob Liu
2015-11-02 4:21 ` Bob Liu
2015-11-05 2:39 ` Konrad Rzeszutek Wilk
2015-11-05 2:39 ` Konrad Rzeszutek Wilk
2015-11-02 4:21 ` [PATCH v4 10/10] xen/blkback: make pool of persistent grants and free pages per-queue Bob Liu
2015-11-02 4:21 ` Bob Liu
2015-11-05 2:43 ` Konrad Rzeszutek Wilk
2015-11-05 2:43 ` Konrad Rzeszutek Wilk
2015-11-05 2:46 ` Bob Liu
2015-11-05 2:46 ` Bob Liu
2015-11-05 19:50 ` Konrad Rzeszutek Wilk
2015-11-05 19:50 ` Konrad Rzeszutek Wilk
2015-11-02 11:19 ` [PATCH v4 00/10] xen-block: multi hardware-queues/rings support Julien Grall
2015-11-02 11:19 ` [Xen-devel] " Julien Grall
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20151103194436.GE28527@char.us.oracle.com \
--to=konrad.wilk@oracle.com \
--cc=avanzini.arianna@gmail.com \
--cc=axboe@fb.com \
--cc=bob.liu@oracle.com \
--cc=david.vrabel@citrix.com \
--cc=felipe.franciosi@citrix.com \
--cc=jonathan.davies@citrix.com \
--cc=linux-kernel@vger.kernel.org \
--cc=rafal.mielniczuk@citrix.com \
--cc=roger.pau@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.