This is a note to let you know that I've just added the patch titled

    xen-blkfront: restore the non-persistent data path

to the 3.10-stable tree which can be found at:
    
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     xen-blkfront-restore-the-non-persistent-data-path.patch
and it can be found in the queue-3.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <[email protected]> know about it.


>From bfe11d6de1c416cea4f3f0f35f864162063ce3fa Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <[email protected]>
Date: Tue, 29 Oct 2013 18:31:14 +0100
Subject: xen-blkfront: restore the non-persistent data path
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

From: Roger Pau Monne <[email protected]>

commit bfe11d6de1c416cea4f3f0f35f864162063ce3fa upstream.

When persistent grants were added they were always used, even if the
backend doesn't have this feature (there's no harm in always using the
same set of pages). This restores the old data path when the backend
doesn't have persistent grants, removing the burden of doing a memcpy
when it is not actually needed.

Signed-off-by: Roger Pau MonnĂ© <[email protected]>
Reported-by: Felipe Franciosi <[email protected]>
Cc: Felipe Franciosi <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: David Vrabel <[email protected]>
Signed-off-by: Konrad Rzeszutek Wilk <[email protected]>
[v2: Fix up whitespace issues]
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 drivers/block/xen-blkfront.c |  105 ++++++++++++++++++++++++++++++-------------
 1 file changed, 74 insertions(+), 31 deletions(-)

--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -104,7 +104,7 @@ struct blkfront_info
        struct work_struct work;
        struct gnttab_free_callback callback;
        struct blk_shadow shadow[BLK_RING_SIZE];
-       struct list_head persistent_gnts;
+       struct list_head grants;
        unsigned int persistent_gnts_c;
        unsigned long shadow_free;
        unsigned int feature_flush;
@@ -175,15 +175,17 @@ static int fill_grant_buffer(struct blkf
                if (!gnt_list_entry)
                        goto out_of_memory;
 
-               granted_page = alloc_page(GFP_NOIO);
-               if (!granted_page) {
-                       kfree(gnt_list_entry);
-                       goto out_of_memory;
+               if (info->feature_persistent) {
+                       granted_page = alloc_page(GFP_NOIO);
+                       if (!granted_page) {
+                               kfree(gnt_list_entry);
+                               goto out_of_memory;
+                       }
+                       gnt_list_entry->pfn = page_to_pfn(granted_page);
                }
 
-               gnt_list_entry->pfn = page_to_pfn(granted_page);
                gnt_list_entry->gref = GRANT_INVALID_REF;
-               list_add(&gnt_list_entry->node, &info->persistent_gnts);
+               list_add(&gnt_list_entry->node, &info->grants);
                i++;
        }
 
@@ -191,9 +193,10 @@ static int fill_grant_buffer(struct blkf
 
 out_of_memory:
        list_for_each_entry_safe(gnt_list_entry, n,
-                                &info->persistent_gnts, node) {
+                                &info->grants, node) {
                list_del(&gnt_list_entry->node);
-               __free_page(pfn_to_page(gnt_list_entry->pfn));
+               if (info->feature_persistent)
+                       __free_page(pfn_to_page(gnt_list_entry->pfn));
                kfree(gnt_list_entry);
                i--;
        }
@@ -202,14 +205,14 @@ out_of_memory:
 }
 
 static struct grant *get_grant(grant_ref_t *gref_head,
+                               unsigned long pfn,
                                struct blkfront_info *info)
 {
        struct grant *gnt_list_entry;
        unsigned long buffer_mfn;
 
-       BUG_ON(list_empty(&info->persistent_gnts));
-       gnt_list_entry = list_first_entry(&info->persistent_gnts, struct grant,
-                                         node);
+       BUG_ON(list_empty(&info->grants));
+       gnt_list_entry = list_first_entry(&info->grants, struct grant, node);
        list_del(&gnt_list_entry->node);
 
        if (gnt_list_entry->gref != GRANT_INVALID_REF) {
@@ -220,6 +223,10 @@ static struct grant *get_grant(grant_ref
        /* Assign a gref to this page */
        gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
        BUG_ON(gnt_list_entry->gref == -ENOSPC);
+       if (!info->feature_persistent) {
+               BUG_ON(!pfn);
+               gnt_list_entry->pfn = pfn;
+       }
        buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn);
        gnttab_grant_foreign_access_ref(gnt_list_entry->gref,
                                        info->xbdev->otherend_id,
@@ -430,12 +437,12 @@ static int blkif_queue_request(struct re
                        fsect = sg->offset >> 9;
                        lsect = fsect + (sg->length >> 9) - 1;
 
-                       gnt_list_entry = get_grant(&gref_head, info);
+                       gnt_list_entry = get_grant(&gref_head, 
page_to_pfn(sg_page(sg)), info);
                        ref = gnt_list_entry->gref;
 
                        info->shadow[id].grants_used[i] = gnt_list_entry;
 
-                       if (rq_data_dir(req)) {
+                       if (rq_data_dir(req) && info->feature_persistent) {
                                char *bvec_data;
                                void *shared_data;
 
@@ -828,16 +835,17 @@ static void blkif_free(struct blkfront_i
                blk_stop_queue(info->rq);
 
        /* Remove all persistent grants */
-       if (!list_empty(&info->persistent_gnts)) {
+       if (!list_empty(&info->grants)) {
                list_for_each_entry_safe(persistent_gnt, n,
-                                        &info->persistent_gnts, node) {
+                                        &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--;
                        }
-                       __free_page(pfn_to_page(persistent_gnt->pfn));
+                       if (info->feature_persistent)
+                               __free_page(pfn_to_page(persistent_gnt->pfn));
                        kfree(persistent_gnt);
                }
        }
@@ -874,7 +882,7 @@ static void blkif_completion(struct blk_
 
        nseg = s->req.u.rw.nr_segments;
 
-       if (bret->operation == BLKIF_OP_READ) {
+       if (bret->operation == BLKIF_OP_READ && info->feature_persistent) {
                /*
                 * Copy the data received from the backend into the bvec.
                 * Since bv_offset can be different than 0, and bv_len different
@@ -902,7 +910,10 @@ static void blkif_completion(struct blk_
                         * we add it at the head of the list, so it will be
                         * reused first.
                         */
-                       list_add(&s->grants_used[i]->node, 
&info->persistent_gnts);
+                       if (!info->feature_persistent)
+                               pr_alert_ratelimited("backed has not unmapped 
grant: %u\n",
+                                                    s->grants_used[i]->gref);
+                       list_add(&s->grants_used[i]->node, &info->grants);
                        info->persistent_gnts_c++;
                } else {
                        /*
@@ -913,7 +924,7 @@ static void blkif_completion(struct blk_
                         */
                        gnttab_end_foreign_access(s->grants_used[i]->gref, 0, 
0UL);
                        s->grants_used[i]->gref = GRANT_INVALID_REF;
-                       list_add_tail(&s->grants_used[i]->node, 
&info->persistent_gnts);
+                       list_add_tail(&s->grants_used[i]->node, &info->grants);
                }
        }
 }
@@ -1052,12 +1063,6 @@ static int setup_blkring(struct xenbus_d
        for (i = 0; i < BLK_RING_SIZE; i++)
                sg_init_table(info->shadow[i].sg, 
BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
-       /* Allocate memory for grants */
-       err = fill_grant_buffer(info, BLK_RING_SIZE *
-                                     BLKIF_MAX_SEGMENTS_PER_REQUEST);
-       if (err)
-               goto fail;
-
        err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
        if (err < 0) {
                free_page((unsigned long)sring);
@@ -1216,7 +1221,7 @@ static int blkfront_probe(struct xenbus_
        spin_lock_init(&info->io_lock);
        info->xbdev = dev;
        info->vdevice = vdevice;
-       INIT_LIST_HEAD(&info->persistent_gnts);
+       INIT_LIST_HEAD(&info->grants);
        info->persistent_gnts_c = 0;
        info->connected = BLKIF_STATE_DISCONNECTED;
        INIT_WORK(&info->work, blkif_restart_queue);
@@ -1245,7 +1250,8 @@ static int blkif_recover(struct blkfront
        int i;
        struct blkif_request *req;
        struct blk_shadow *copy;
-       int j;
+       unsigned int persistent;
+       int j, rc;
 
        /* Stage 1: Make a safe copy of the shadow state. */
        copy = kmemdup(info->shadow, sizeof(info->shadow),
@@ -1260,6 +1266,24 @@ static int blkif_recover(struct blkfront
        info->shadow_free = info->ring.req_prod_pvt;
        info->shadow[BLK_RING_SIZE-1].req.u.rw.id = 0x0fffffff;
 
+       /* Check if the backend supports persistent grants */
+       rc = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                          "feature-persistent", "%u", &persistent,
+                          NULL);
+       if (rc)
+               info->feature_persistent = 0;
+       else
+               info->feature_persistent = persistent;
+
+       /* Allocate memory for grants */
+       rc = fill_grant_buffer(info, BLK_RING_SIZE *
+                                    BLKIF_MAX_SEGMENTS_PER_REQUEST);
+       if (rc) {
+               xenbus_dev_fatal(info->xbdev, rc, "setting grant buffer 
failed");
+               kfree(copy);
+               return rc;
+       }
+
        /* Stage 3: Find pending requests and requeue them. */
        for (i = 0; i < BLK_RING_SIZE; i++) {
                /* Not in use? */
@@ -1324,8 +1348,12 @@ static int blkfront_resume(struct xenbus
        blkif_free(info, info->connected == BLKIF_STATE_CONNECTED);
 
        err = talk_to_blkback(dev, info);
-       if (info->connected == BLKIF_STATE_SUSPENDED && !err)
-               err = blkif_recover(info);
+
+       /*
+        * We have to wait for the backend to switch to
+        * connected state, since we want to read which
+        * features it supports.
+        */
 
        return err;
 }
@@ -1429,9 +1457,16 @@ static void blkfront_connect(struct blkf
                       sectors);
                set_capacity(info->gd, sectors);
                revalidate_disk(info->gd);
+               return;
 
-               /* fall through */
        case BLKIF_STATE_SUSPENDED:
+               /*
+                * If we are recovering from suspension, we need to wait
+                * for the backend to announce it's features before
+                * reconnecting, we need to know if the backend supports
+                * persistent grants.
+                */
+               blkif_recover(info);
                return;
 
        default:
@@ -1499,6 +1534,14 @@ static void blkfront_connect(struct blkf
        else
                info->feature_persistent = persistent;
 
+       /* Allocate memory for grants */
+       err = fill_grant_buffer(info, BLK_RING_SIZE *
+                                     BLKIF_MAX_SEGMENTS_PER_REQUEST);
+       if (err) {
+               xenbus_dev_fatal(info->xbdev, err, "setting grant buffer 
failed");
+               return;
+       }
+
        err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
        if (err) {
                xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",


Patches currently in stable-queue which might be from [email protected] are

queue-3.10/xen-blkfront-revoke-foreign-access-for-grants-not-mapped-by-the-backend.patch
queue-3.10/xen-blkfront-restore-the-non-persistent-data-path.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to