Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Konrad writes:

Please git pull the following branch:

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

which has a bunch of fixes to the Xen block frontend and backend driver
and a new parameter for Xen backend driver - an override (set by the toolstack)
whether to expose the discard support (if disk of course supports it) or not.

+57 -42
+2 -2
drivers/block/xen-blkback/common.h
··· 314 314 unsigned long long st_rd_sect; 315 315 unsigned long long st_wr_sect; 316 316 317 - wait_queue_head_t waiting_to_free; 317 + struct work_struct free_work; 318 318 /* Thread shutdown wait queue. */ 319 319 wait_queue_head_t shutdown_wq; 320 320 }; ··· 361 361 #define xen_blkif_put(_b) \ 362 362 do { \ 363 363 if (atomic_dec_and_test(&(_b)->refcnt)) \ 364 - wake_up(&(_b)->waiting_to_free);\ 364 + schedule_work(&(_b)->free_work);\ 365 365 } while (0) 366 366 367 367 struct phys_req {
+40 -13
drivers/block/xen-blkback/xenbus.c
··· 35 35 static int connect_ring(struct backend_info *); 36 36 static void backend_changed(struct xenbus_watch *, const char **, 37 37 unsigned int); 38 + static void xen_blkif_free(struct xen_blkif *blkif); 39 + static void xen_vbd_free(struct xen_vbd *vbd); 38 40 39 41 struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be) 40 42 { 41 43 return be->dev; 44 + } 45 + 46 + /* 47 + * The last request could free the device from softirq context and 48 + * xen_blkif_free() can sleep. 49 + */ 50 + static void xen_blkif_deferred_free(struct work_struct *work) 51 + { 52 + struct xen_blkif *blkif; 53 + 54 + blkif = container_of(work, struct xen_blkif, free_work); 55 + xen_blkif_free(blkif); 42 56 } 43 57 44 58 static int blkback_name(struct xen_blkif *blkif, char *buf) ··· 135 121 init_completion(&blkif->drain_complete); 136 122 atomic_set(&blkif->drain, 0); 137 123 blkif->st_print = jiffies; 138 - init_waitqueue_head(&blkif->waiting_to_free); 139 124 blkif->persistent_gnts.rb_node = NULL; 140 125 spin_lock_init(&blkif->free_pages_lock); 141 126 INIT_LIST_HEAD(&blkif->free_pages); ··· 145 132 INIT_WORK(&blkif->persistent_purge_work, xen_blkbk_unmap_purged_grants); 146 133 147 134 INIT_LIST_HEAD(&blkif->pending_free); 135 + INIT_WORK(&blkif->free_work, xen_blkif_deferred_free); 148 136 149 137 for (i = 0; i < XEN_BLKIF_REQS; i++) { 150 138 req = kzalloc(sizeof(*req), GFP_KERNEL); ··· 245 231 return 0; 246 232 } 247 233 248 - static void xen_blkif_disconnect(struct xen_blkif *blkif) 234 + static int xen_blkif_disconnect(struct xen_blkif *blkif) 249 235 { 250 236 if (blkif->xenblkd) { 251 237 kthread_stop(blkif->xenblkd); ··· 253 239 blkif->xenblkd = NULL; 254 240 } 255 241 256 - atomic_dec(&blkif->refcnt); 257 - wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); 258 - atomic_inc(&blkif->refcnt); 242 + /* The above kthread_stop() guarantees that at this point we 243 + * don't have any discard_io or other_io requests. So, checking 244 + * for inflight IO is enough. 245 + */ 246 + if (atomic_read(&blkif->inflight) > 0) 247 + return -EBUSY; 259 248 260 249 if (blkif->irq) { 261 250 unbind_from_irqhandler(blkif->irq, blkif); ··· 269 252 xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring); 270 253 blkif->blk_rings.common.sring = NULL; 271 254 } 255 + 256 + return 0; 272 257 } 273 258 274 259 static void xen_blkif_free(struct xen_blkif *blkif) ··· 278 259 struct pending_req *req, *n; 279 260 int i = 0, j; 280 261 281 - if (!atomic_dec_and_test(&blkif->refcnt)) 282 - BUG(); 262 + xen_blkif_disconnect(blkif); 263 + xen_vbd_free(&blkif->vbd); 283 264 284 265 /* Remove all persistent grants and the cache of ballooned pages. */ 285 266 xen_blkbk_free_caches(blkif); ··· 468 449 be->backend_watch.node = NULL; 469 450 } 470 451 452 + dev_set_drvdata(&dev->dev, NULL); 453 + 471 454 if (be->blkif) { 472 455 xen_blkif_disconnect(be->blkif); 473 - xen_vbd_free(&be->blkif->vbd); 474 - xen_blkif_free(be->blkif); 475 - be->blkif = NULL; 456 + xen_blkif_put(be->blkif); 476 457 } 477 458 478 459 kfree(be->mode); 479 460 kfree(be); 480 - dev_set_drvdata(&dev->dev, NULL); 481 461 return 0; 482 462 } 483 463 ··· 499 481 struct xenbus_device *dev = be->dev; 500 482 struct xen_blkif *blkif = be->blkif; 501 483 int err; 502 - int state = 0; 484 + int state = 0, discard_enable; 503 485 struct block_device *bdev = be->blkif->vbd.bdev; 504 486 struct request_queue *q = bdev_get_queue(bdev); 487 + 488 + err = xenbus_scanf(XBT_NIL, dev->nodename, "discard-enable", "%d", 489 + &discard_enable); 490 + if (err == 1 && !discard_enable) 491 + return; 505 492 506 493 if (blk_queue_discard(q)) { 507 494 err = xenbus_printf(xbt, dev->nodename, ··· 723 700 * Enforce precondition before potential leak point. 724 701 * xen_blkif_disconnect() is idempotent. 725 702 */ 726 - xen_blkif_disconnect(be->blkif); 703 + err = xen_blkif_disconnect(be->blkif); 704 + if (err) { 705 + xenbus_dev_fatal(dev, err, "pending I/O"); 706 + break; 707 + } 727 708 728 709 err = connect_ring(be); 729 710 if (err)
+14 -26
drivers/block/xen-blkfront.c
··· 1635 1635 static void blkfront_setup_discard(struct blkfront_info *info) 1636 1636 { 1637 1637 int err; 1638 - char *type; 1639 1638 unsigned int discard_granularity; 1640 1639 unsigned int discard_alignment; 1641 1640 unsigned int discard_secure; 1642 1641 1643 - type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL); 1644 - if (IS_ERR(type)) 1645 - return; 1646 - 1647 - info->feature_secdiscard = 0; 1648 - if (strncmp(type, "phy", 3) == 0) { 1649 - err = xenbus_gather(XBT_NIL, info->xbdev->otherend, 1650 - "discard-granularity", "%u", &discard_granularity, 1651 - "discard-alignment", "%u", &discard_alignment, 1652 - NULL); 1653 - if (!err) { 1654 - info->feature_discard = 1; 1655 - info->discard_granularity = discard_granularity; 1656 - info->discard_alignment = discard_alignment; 1657 - } 1658 - err = xenbus_gather(XBT_NIL, info->xbdev->otherend, 1659 - "discard-secure", "%d", &discard_secure, 1660 - NULL); 1661 - if (!err) 1662 - info->feature_secdiscard = discard_secure; 1663 - 1664 - } else if (strncmp(type, "file", 4) == 0) 1665 - info->feature_discard = 1; 1666 - 1667 - kfree(type); 1642 + info->feature_discard = 1; 1643 + err = xenbus_gather(XBT_NIL, info->xbdev->otherend, 1644 + "discard-granularity", "%u", &discard_granularity, 1645 + "discard-alignment", "%u", &discard_alignment, 1646 + NULL); 1647 + if (!err) { 1648 + info->discard_granularity = discard_granularity; 1649 + info->discard_alignment = discard_alignment; 1650 + } 1651 + err = xenbus_gather(XBT_NIL, info->xbdev->otherend, 1652 + "discard-secure", "%d", &discard_secure, 1653 + NULL); 1654 + if (!err) 1655 + info->feature_secdiscard = !!discard_secure; 1668 1656 } 1669 1657 1670 1658 static int blkfront_setup_indirect(struct blkfront_info *info)
+1 -1
include/xen/interface/io/blkif.h
··· 86 86 * Interface%20manuals/100293068c.pdf 87 87 * The backend can optionally provide three extra XenBus attributes to 88 88 * further optimize the discard functionality: 89 - * 'discard-aligment' - Devices that support discard functionality may 89 + * 'discard-alignment' - Devices that support discard functionality may 90 90 * internally allocate space in units that are bigger than the exported 91 91 * logical block size. The discard-alignment parameter indicates how many bytes 92 92 * the beginning of the partition is offset from the internal allocation unit's