Commit 9d4cb8e3 authored by Jens Axboe's avatar Jens Axboe

Merge branch 'stable/for-jens-3.14' of...

Merge branch 'stable/for-jens-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip into for-linus

Konrad writes:

Please git pull the following branch:

 git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git stable/for-jens-3.14

which is based off v3.13-rc6. If you would like me to rebase it on
a different branch/tag I would be more than happy to do so.

The patches are all bug-fixes and hopefully can go in 3.14.

They deal with xen-blkback shutdown and cause memory leaks
as well as shutdown races. They should go to stable tree and if you
are OK with I will ask them to backport those fixes.

There is also a fix to xen-blkfront to deal with unexpected state
transition. And lastly a fix to the header where it was using the
__aligned__ unnecessarily.
parents 11c94444 36613717
...@@ -375,7 +375,7 @@ static void purge_persistent_gnt(struct xen_blkif *blkif) ...@@ -375,7 +375,7 @@ static void purge_persistent_gnt(struct xen_blkif *blkif)
pr_debug(DRV_PFX "Going to purge %u persistent grants\n", num_clean); pr_debug(DRV_PFX "Going to purge %u persistent grants\n", num_clean);
INIT_LIST_HEAD(&blkif->persistent_purge_list); BUG_ON(!list_empty(&blkif->persistent_purge_list));
root = &blkif->persistent_gnts; root = &blkif->persistent_gnts;
purge_list: purge_list:
foreach_grant_safe(persistent_gnt, n, root, node) { foreach_grant_safe(persistent_gnt, n, root, node) {
...@@ -625,9 +625,23 @@ int xen_blkif_schedule(void *arg) ...@@ -625,9 +625,23 @@ int xen_blkif_schedule(void *arg)
print_stats(blkif); print_stats(blkif);
} }
/* Since we are shutting down remove all pages from the buffer */ /* Drain pending purge work */
shrink_free_pagepool(blkif, 0 /* All */); flush_work(&blkif->persistent_purge_work);
if (log_stats)
print_stats(blkif);
blkif->xenblkd = NULL;
xen_blkif_put(blkif);
return 0;
}
/*
* Remove persistent grants and empty the pool of free pages
*/
void xen_blkbk_free_caches(struct xen_blkif *blkif)
{
/* Free all persistent grant pages */ /* Free all persistent grant pages */
if (!RB_EMPTY_ROOT(&blkif->persistent_gnts)) if (!RB_EMPTY_ROOT(&blkif->persistent_gnts))
free_persistent_gnts(blkif, &blkif->persistent_gnts, free_persistent_gnts(blkif, &blkif->persistent_gnts,
...@@ -636,13 +650,8 @@ int xen_blkif_schedule(void *arg) ...@@ -636,13 +650,8 @@ int xen_blkif_schedule(void *arg)
BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts)); BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts));
blkif->persistent_gnt_c = 0; blkif->persistent_gnt_c = 0;
if (log_stats) /* Since we are shutting down remove all pages from the buffer */
print_stats(blkif); shrink_free_pagepool(blkif, 0 /* All */);
blkif->xenblkd = NULL;
xen_blkif_put(blkif);
return 0;
} }
/* /*
...@@ -838,7 +847,7 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req, ...@@ -838,7 +847,7 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req,
struct grant_page **pages = pending_req->indirect_pages; struct grant_page **pages = pending_req->indirect_pages;
struct xen_blkif *blkif = pending_req->blkif; struct xen_blkif *blkif = pending_req->blkif;
int indirect_grefs, rc, n, nseg, i; int indirect_grefs, rc, n, nseg, i;
struct blkif_request_segment_aligned *segments = NULL; struct blkif_request_segment *segments = NULL;
nseg = pending_req->nr_pages; nseg = pending_req->nr_pages;
indirect_grefs = INDIRECT_PAGES(nseg); indirect_grefs = INDIRECT_PAGES(nseg);
...@@ -934,9 +943,7 @@ static void xen_blk_drain_io(struct xen_blkif *blkif) ...@@ -934,9 +943,7 @@ static void xen_blk_drain_io(struct xen_blkif *blkif)
{ {
atomic_set(&blkif->drain, 1); atomic_set(&blkif->drain, 1);
do { do {
/* The initial value is one, and one refcnt taken at the if (atomic_read(&blkif->inflight) == 0)
* start of the xen_blkif_schedule thread. */
if (atomic_read(&blkif->refcnt) <= 2)
break; break;
wait_for_completion_interruptible_timeout( wait_for_completion_interruptible_timeout(
&blkif->drain_complete, HZ); &blkif->drain_complete, HZ);
...@@ -976,17 +983,30 @@ static void __end_block_io_op(struct pending_req *pending_req, int error) ...@@ -976,17 +983,30 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
* the proper response on the ring. * the proper response on the ring.
*/ */
if (atomic_dec_and_test(&pending_req->pendcnt)) { if (atomic_dec_and_test(&pending_req->pendcnt)) {
xen_blkbk_unmap(pending_req->blkif, struct xen_blkif *blkif = pending_req->blkif;
xen_blkbk_unmap(blkif,
pending_req->segments, pending_req->segments,
pending_req->nr_pages); pending_req->nr_pages);
make_response(pending_req->blkif, pending_req->id, make_response(blkif, pending_req->id,
pending_req->operation, pending_req->status); pending_req->operation, pending_req->status);
xen_blkif_put(pending_req->blkif); free_req(blkif, pending_req);
if (atomic_read(&pending_req->blkif->refcnt) <= 2) { /*
if (atomic_read(&pending_req->blkif->drain)) * Make sure the request is freed before releasing blkif,
complete(&pending_req->blkif->drain_complete); * or there could be a race between free_req and the
* cleanup done in xen_blkif_free during shutdown.
*
* NB: The fact that we might try to wake up pending_free_wq
* before drain_complete (in case there's a drain going on)
* it's not a problem with our current implementation
* because we can assure there's no thread waiting on
* pending_free_wq if there's a drain going on, but it has
* to be taken into account if the current model is changed.
*/
if (atomic_dec_and_test(&blkif->inflight) && atomic_read(&blkif->drain)) {
complete(&blkif->drain_complete);
} }
free_req(pending_req->blkif, pending_req); xen_blkif_put(blkif);
} }
} }
...@@ -1240,6 +1260,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, ...@@ -1240,6 +1260,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
* below (in "!bio") if we are handling a BLKIF_OP_DISCARD. * below (in "!bio") if we are handling a BLKIF_OP_DISCARD.
*/ */
xen_blkif_get(blkif); xen_blkif_get(blkif);
atomic_inc(&blkif->inflight);
for (i = 0; i < nseg; i++) { for (i = 0; i < nseg; i++) {
while ((bio == NULL) || while ((bio == NULL) ||
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
#define MAX_INDIRECT_SEGMENTS 256 #define MAX_INDIRECT_SEGMENTS 256
#define SEGS_PER_INDIRECT_FRAME \ #define SEGS_PER_INDIRECT_FRAME \
(PAGE_SIZE/sizeof(struct blkif_request_segment_aligned)) (PAGE_SIZE/sizeof(struct blkif_request_segment))
#define MAX_INDIRECT_PAGES \ #define MAX_INDIRECT_PAGES \
((MAX_INDIRECT_SEGMENTS + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME) ((MAX_INDIRECT_SEGMENTS + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
#define INDIRECT_PAGES(_segs) \ #define INDIRECT_PAGES(_segs) \
...@@ -278,6 +278,7 @@ struct xen_blkif { ...@@ -278,6 +278,7 @@ struct xen_blkif {
/* for barrier (drain) requests */ /* for barrier (drain) requests */
struct completion drain_complete; struct completion drain_complete;
atomic_t drain; atomic_t drain;
atomic_t inflight;
/* One thread per one blkif. */ /* One thread per one blkif. */
struct task_struct *xenblkd; struct task_struct *xenblkd;
unsigned int waiting_reqs; unsigned int waiting_reqs;
...@@ -376,6 +377,7 @@ int xen_blkif_xenbus_init(void); ...@@ -376,6 +377,7 @@ int xen_blkif_xenbus_init(void);
irqreturn_t xen_blkif_be_int(int irq, void *dev_id); irqreturn_t xen_blkif_be_int(int irq, void *dev_id);
int xen_blkif_schedule(void *arg); int xen_blkif_schedule(void *arg);
int xen_blkif_purge_persistent(void *arg); int xen_blkif_purge_persistent(void *arg);
void xen_blkbk_free_caches(struct xen_blkif *blkif);
int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
struct backend_info *be, int state); struct backend_info *be, int state);
......
...@@ -125,8 +125,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) ...@@ -125,8 +125,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
blkif->persistent_gnts.rb_node = NULL; blkif->persistent_gnts.rb_node = NULL;
spin_lock_init(&blkif->free_pages_lock); spin_lock_init(&blkif->free_pages_lock);
INIT_LIST_HEAD(&blkif->free_pages); INIT_LIST_HEAD(&blkif->free_pages);
INIT_LIST_HEAD(&blkif->persistent_purge_list);
blkif->free_pages_num = 0; blkif->free_pages_num = 0;
atomic_set(&blkif->persistent_gnt_in_use, 0); atomic_set(&blkif->persistent_gnt_in_use, 0);
atomic_set(&blkif->inflight, 0);
INIT_LIST_HEAD(&blkif->pending_free); INIT_LIST_HEAD(&blkif->pending_free);
...@@ -259,6 +261,17 @@ static void xen_blkif_free(struct xen_blkif *blkif) ...@@ -259,6 +261,17 @@ static void xen_blkif_free(struct xen_blkif *blkif)
if (!atomic_dec_and_test(&blkif->refcnt)) if (!atomic_dec_and_test(&blkif->refcnt))
BUG(); BUG();
/* Remove all persistent grants and the cache of ballooned pages. */
xen_blkbk_free_caches(blkif);
/* Make sure everything is drained before shutting down */
BUG_ON(blkif->persistent_gnt_c != 0);
BUG_ON(atomic_read(&blkif->persistent_gnt_in_use) != 0);
BUG_ON(blkif->free_pages_num != 0);
BUG_ON(!list_empty(&blkif->persistent_purge_list));
BUG_ON(!list_empty(&blkif->free_pages));
BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts));
/* Check that there is no request in use */ /* Check that there is no request in use */
list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) { list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) {
list_del(&req->free_list); list_del(&req->free_list);
......
...@@ -162,7 +162,7 @@ static DEFINE_SPINLOCK(minor_lock); ...@@ -162,7 +162,7 @@ static DEFINE_SPINLOCK(minor_lock);
#define DEV_NAME "xvd" /* name in /dev */ #define DEV_NAME "xvd" /* name in /dev */
#define SEGS_PER_INDIRECT_FRAME \ #define SEGS_PER_INDIRECT_FRAME \
(PAGE_SIZE/sizeof(struct blkif_request_segment_aligned)) (PAGE_SIZE/sizeof(struct blkif_request_segment))
#define INDIRECT_GREFS(_segs) \ #define INDIRECT_GREFS(_segs) \
((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME) ((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
...@@ -393,7 +393,7 @@ static int blkif_queue_request(struct request *req) ...@@ -393,7 +393,7 @@ static int blkif_queue_request(struct request *req)
unsigned long id; unsigned long id;
unsigned int fsect, lsect; unsigned int fsect, lsect;
int i, ref, n; int i, ref, n;
struct blkif_request_segment_aligned *segments = NULL; struct blkif_request_segment *segments = NULL;
/* /*
* Used to store if we are able to queue the request by just using * Used to store if we are able to queue the request by just using
...@@ -550,7 +550,7 @@ static int blkif_queue_request(struct request *req) ...@@ -550,7 +550,7 @@ static int blkif_queue_request(struct request *req)
} else { } else {
n = i % SEGS_PER_INDIRECT_FRAME; n = i % SEGS_PER_INDIRECT_FRAME;
segments[n] = segments[n] =
(struct blkif_request_segment_aligned) { (struct blkif_request_segment) {
.gref = ref, .gref = ref,
.first_sect = fsect, .first_sect = fsect,
.last_sect = lsect }; .last_sect = lsect };
...@@ -1904,13 +1904,16 @@ static void blkback_changed(struct xenbus_device *dev, ...@@ -1904,13 +1904,16 @@ static void blkback_changed(struct xenbus_device *dev,
case XenbusStateReconfiguring: case XenbusStateReconfiguring:
case XenbusStateReconfigured: case XenbusStateReconfigured:
case XenbusStateUnknown: case XenbusStateUnknown:
case XenbusStateClosed:
break; break;
case XenbusStateConnected: case XenbusStateConnected:
blkfront_connect(info); blkfront_connect(info);
break; break;
case XenbusStateClosed:
if (dev->state == XenbusStateClosed)
break;
/* Missed the backend's Closing state -- fallthrough */
case XenbusStateClosing: case XenbusStateClosing:
blkfront_closing(info); blkfront_closing(info);
break; break;
......
...@@ -113,13 +113,13 @@ typedef uint64_t blkif_sector_t; ...@@ -113,13 +113,13 @@ typedef uint64_t blkif_sector_t;
* it's less than the number provided by the backend. The indirect_grefs field * it's less than the number provided by the backend. The indirect_grefs field
* in blkif_request_indirect should be filled by the frontend with the * in blkif_request_indirect should be filled by the frontend with the
* grant references of the pages that are holding the indirect segments. * grant references of the pages that are holding the indirect segments.
* This pages are filled with an array of blkif_request_segment_aligned * These pages are filled with an array of blkif_request_segment that hold the
* that hold the information about the segments. The number of indirect * information about the segments. The number of indirect pages to use is
* pages to use is determined by the maximum number of segments * determined by the number of segments an indirect request contains. Every
* a indirect request contains. Every indirect page can contain a maximum * indirect page can contain a maximum of
* of 512 segments (PAGE_SIZE/sizeof(blkif_request_segment_aligned)), * (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
* so to calculate the number of indirect pages to use we have to do * calculate the number of indirect pages to use we have to do
* ceil(indirect_segments/512). * ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
* *
* If a backend does not recognize BLKIF_OP_INDIRECT, it should *not* * If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
* create the "feature-max-indirect-segments" node! * create the "feature-max-indirect-segments" node!
...@@ -135,13 +135,12 @@ typedef uint64_t blkif_sector_t; ...@@ -135,13 +135,12 @@ typedef uint64_t blkif_sector_t;
#define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8 #define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
struct blkif_request_segment_aligned { struct blkif_request_segment {
grant_ref_t gref; /* reference to I/O buffer frame */ grant_ref_t gref; /* reference to I/O buffer frame */
/* @first_sect: first sector in frame to transfer (inclusive). */ /* @first_sect: first sector in frame to transfer (inclusive). */
/* @last_sect: last sector in frame to transfer (inclusive). */ /* @last_sect: last sector in frame to transfer (inclusive). */
uint8_t first_sect, last_sect; uint8_t first_sect, last_sect;
uint16_t _pad; /* padding to make it 8 bytes, so it's cache-aligned */ };
} __attribute__((__packed__));
struct blkif_request_rw { struct blkif_request_rw {
uint8_t nr_segments; /* number of segments */ uint8_t nr_segments; /* number of segments */
...@@ -151,12 +150,7 @@ struct blkif_request_rw { ...@@ -151,12 +150,7 @@ struct blkif_request_rw {
#endif #endif
uint64_t id; /* private guest value, echoed in resp */ uint64_t id; /* private guest value, echoed in resp */
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
struct blkif_request_segment { struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
grant_ref_t gref; /* reference to I/O buffer frame */
/* @first_sect: first sector in frame to transfer (inclusive). */
/* @last_sect: last sector in frame to transfer (inclusive). */
uint8_t first_sect, last_sect;
} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
} __attribute__((__packed__)); } __attribute__((__packed__));
struct blkif_request_discard { struct blkif_request_discard {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment