Patch "xen-blkfront: save uncompleted reqs in blkfront_resume()" has been added to the 4.6-stable tree
Subsystems (4)
This is a note to let you know that I've just added the patch titled
xen-blkfront: save uncompleted reqs in blkfront_resume()
to the 4.6-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-save-uncompleted-reqs-in-blkfront_resume.patch
and it can be found in the queue-4.6 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
7b427a59538a98161321aa46c13f4ea81b43f4ebMon Sep 17 00:00:00 2001
From: Bob Liu <[email protected]>
Date: Mon, 27 Jun 2016 16:33:24 +0800
Subject: xen-blkfront: save uncompleted reqs in blkfront_resume()
From: Bob Liu <[email protected]>
commit 7b427a59538a98161321aa46c13f4ea81b43f4eb upstream.
Uncompleted reqs used to be 'saved and resubmitted' in blkfront_recover() during migration, but that's too late after multi-queue was introduced.
After a migrate to another host (which may not have multiqueue support), the number of rings (block hardware queues) may be changed and the ring and shadow structure will also be reallocated.
The blkfront_recover() then can't 'save and resubmit' the real uncompleted reqs because shadow structure have been reallocated.
This patch fixes this issue by moving the 'save' logic out of blkfront_recover() to earlier place in blkfront_resume().
The 'resubmit' is not changed and still in blkfront_recover().
--- drivers/block/xen-blkfront.c | 91 ++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 51 deletions(-)
drivers/block/xen-blkfront.c +40 -51
@@ -207,6 +207,9 @@ struct blkfront_infostruct blk_mq_tag_set tag_set;struct blkfront_ring_info *rinfo;unsigned int nr_rings; +/* Save uncomplete reqs and bios for migration. */ +struct list_head requests; +struct bio_list bio_list; };static unsigned int nr_minors;
@@ -2007,69 +2010,22 @@ static int blkif_recover(struct blkfront {unsigned int i, r_index;struct request *req, *n; -struct blk_shadow *copy;int rc;struct bio *bio, *cloned_bio; -struct bio_list bio_list, merge_bio;unsigned int segs, offset;int pending, size;struct split_bio *split_bio; -struct list_head requests;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 (r_index =0 ; r_index < info->nr_rings; r_index++) { -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 ; +struct blkfront_ring_info *rinfo = &info->rinfo[r_index]; rc =blkfront_setup_indirect (rinfo); -if (rc) { -kfree (copy); +if (rc)return rc; - } - -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 )) { -/* -* 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 ); - } - -kfree (copy); }xenbus_switch_state (info->xbdev, XenbusStateConnected);
@@ -2084,7 +2040,7 @@ static int blkif_recover(struct blkfrontkick_pending_request_queues (rinfo); } -list_for_each_entry_safe (req, n, &requests, queuelist) { +list_for_each_entry_safe (req, n, &info->requests, queuelist) {/* Requeue pending requests (flush or discard) */ list_del_init (&req->queuelist);BUG_ON (req->nr_phys_segments > segs);
@@ -2092,7 +2048,7 @@ static int blkif_recover(struct blkfront }blk_mq_kick_requeue_list (info->rq); -while ((bio =bio_list_pop (&bio_list)) !=NULL ) { +while ((bio =bio_list_pop (&info->bio_list)) !=NULL ) {/* Traverse the list of pending bios and re-queue them */ if (bio_segments (bio) > segs) {/*
@@ -2138,9 +2094,42 @@ static int blkfront_resume(struct xenbus {struct blkfront_info *info =dev_get_drvdata (&dev->dev);int err =0 ; +unsigned int i, j;dev_dbg (&dev->dev,"blkfront_resume: %s\n" , dev->nodename); +bio_list_init (&info->bio_list); +INIT_LIST_HEAD (&info->requests); +for (i =0 ; i < info->nr_rings; i++) { +struct blkfront_ring_info *rinfo = &info->rinfo[i]; +struct bio_list merge_bio; +struct blk_shadow *shadow = rinfo->shadow; + +for (j =0 ; j <BLK_RING_SIZE (info); j++) { +/* Not in use? */ +if (!shadow[j].request) +continue ; + +/* +* Get the bios in the request so we can re-queue them. +*/ +if (shadow[j].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 (&shadow[j].request->queuelist, &info->requests); +continue ; + } + merge_bio.head = shadow[j].request->bio; + merge_bio.tail = shadow[j].request->biotail; +bio_list_merge (&info->bio_list, &merge_bio); + shadow[j].request->bio =NULL ; +blk_mq_end_request (shadow[j].request,0 ); + } + } +blkif_free (info, info->connected ==BLKIF_STATE_CONNECTED ); err =negotiate_mq (info);
Patches currently in stable-queue which might be from [email protected] are
queue-4.6/xen-blkfront-don-t-call-talk_to_blkback-when-already-connected-to-blkback.patch queue-4.6/xen-blkfront-save-uncompleted-reqs-in-blkfront_resume.patch queue-4.6/xen-blkfront-fix-resume-issues-after-a-migration.patch