Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 879466e6 authored by Jens Axboe's avatar Jens Axboe
Browse files

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

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.
parents 0fb662e2 814d04e7
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -314,7 +314,7 @@ struct xen_blkif {
	unsigned long long			st_rd_sect;
	unsigned long long			st_rd_sect;
	unsigned long long			st_wr_sect;
	unsigned long long			st_wr_sect;


	wait_queue_head_t	waiting_to_free;
	struct work_struct	free_work;
	/* Thread shutdown wait queue. */
	/* Thread shutdown wait queue. */
	wait_queue_head_t	shutdown_wq;
	wait_queue_head_t	shutdown_wq;
};
};
@@ -361,7 +361,7 @@ struct pending_req {
#define xen_blkif_put(_b)				\
#define xen_blkif_put(_b)				\
	do {						\
	do {						\
		if (atomic_dec_and_test(&(_b)->refcnt))	\
		if (atomic_dec_and_test(&(_b)->refcnt))	\
			wake_up(&(_b)->waiting_to_free);\
			schedule_work(&(_b)->free_work);\
	} while (0)
	} while (0)


struct phys_req {
struct phys_req {
+40 −13
Original line number Original line Diff line number Diff line
@@ -35,12 +35,26 @@ static void connect(struct backend_info *);
static int connect_ring(struct backend_info *);
static int connect_ring(struct backend_info *);
static void backend_changed(struct xenbus_watch *, const char **,
static void backend_changed(struct xenbus_watch *, const char **,
			    unsigned int);
			    unsigned int);
static void xen_blkif_free(struct xen_blkif *blkif);
static void xen_vbd_free(struct xen_vbd *vbd);


struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be)
struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be)
{
{
	return be->dev;
	return be->dev;
}
}


/*
 * The last request could free the device from softirq context and
 * xen_blkif_free() can sleep.
 */
static void xen_blkif_deferred_free(struct work_struct *work)
{
	struct xen_blkif *blkif;

	blkif = container_of(work, struct xen_blkif, free_work);
	xen_blkif_free(blkif);
}

static int blkback_name(struct xen_blkif *blkif, char *buf)
static int blkback_name(struct xen_blkif *blkif, char *buf)
{
{
	char *devpath, *devname;
	char *devpath, *devname;
@@ -121,7 +135,6 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
	init_completion(&blkif->drain_complete);
	init_completion(&blkif->drain_complete);
	atomic_set(&blkif->drain, 0);
	atomic_set(&blkif->drain, 0);
	blkif->st_print = jiffies;
	blkif->st_print = jiffies;
	init_waitqueue_head(&blkif->waiting_to_free);
	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);
@@ -132,6 +145,7 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
	INIT_WORK(&blkif->persistent_purge_work, xen_blkbk_unmap_purged_grants);
	INIT_WORK(&blkif->persistent_purge_work, xen_blkbk_unmap_purged_grants);


	INIT_LIST_HEAD(&blkif->pending_free);
	INIT_LIST_HEAD(&blkif->pending_free);
	INIT_WORK(&blkif->free_work, xen_blkif_deferred_free);


	for (i = 0; i < XEN_BLKIF_REQS; i++) {
	for (i = 0; i < XEN_BLKIF_REQS; i++) {
		req = kzalloc(sizeof(*req), GFP_KERNEL);
		req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -231,7 +245,7 @@ static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page,
	return 0;
	return 0;
}
}


static void xen_blkif_disconnect(struct xen_blkif *blkif)
static int xen_blkif_disconnect(struct xen_blkif *blkif)
{
{
	if (blkif->xenblkd) {
	if (blkif->xenblkd) {
		kthread_stop(blkif->xenblkd);
		kthread_stop(blkif->xenblkd);
@@ -239,9 +253,12 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
		blkif->xenblkd = NULL;
		blkif->xenblkd = NULL;
	}
	}


	atomic_dec(&blkif->refcnt);
	/* The above kthread_stop() guarantees that at this point we
	wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
	 * don't have any discard_io or other_io requests. So, checking
	atomic_inc(&blkif->refcnt);
	 * for inflight IO is enough.
	 */
	if (atomic_read(&blkif->inflight) > 0)
		return -EBUSY;


	if (blkif->irq) {
	if (blkif->irq) {
		unbind_from_irqhandler(blkif->irq, blkif);
		unbind_from_irqhandler(blkif->irq, blkif);
@@ -252,6 +269,8 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
		xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring);
		xenbus_unmap_ring_vfree(blkif->be->dev, blkif->blk_ring);
		blkif->blk_rings.common.sring = NULL;
		blkif->blk_rings.common.sring = NULL;
	}
	}

	return 0;
}
}


static void xen_blkif_free(struct xen_blkif *blkif)
static void xen_blkif_free(struct xen_blkif *blkif)
@@ -259,8 +278,8 @@ static void xen_blkif_free(struct xen_blkif *blkif)
	struct pending_req *req, *n;
	struct pending_req *req, *n;
	int i = 0, j;
	int i = 0, j;


	if (!atomic_dec_and_test(&blkif->refcnt))
	xen_blkif_disconnect(blkif);
		BUG();
	xen_vbd_free(&blkif->vbd);


	/* Remove all persistent grants and the cache of ballooned pages. */
	/* Remove all persistent grants and the cache of ballooned pages. */
	xen_blkbk_free_caches(blkif);
	xen_blkbk_free_caches(blkif);
@@ -449,16 +468,15 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
		be->backend_watch.node = NULL;
		be->backend_watch.node = NULL;
	}
	}


	dev_set_drvdata(&dev->dev, NULL);

	if (be->blkif) {
	if (be->blkif) {
		xen_blkif_disconnect(be->blkif);
		xen_blkif_disconnect(be->blkif);
		xen_vbd_free(&be->blkif->vbd);
		xen_blkif_put(be->blkif);
		xen_blkif_free(be->blkif);
		be->blkif = NULL;
	}
	}


	kfree(be->mode);
	kfree(be->mode);
	kfree(be);
	kfree(be);
	dev_set_drvdata(&dev->dev, NULL);
	return 0;
	return 0;
}
}


@@ -481,10 +499,15 @@ static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info
	struct xenbus_device *dev = be->dev;
	struct xenbus_device *dev = be->dev;
	struct xen_blkif *blkif = be->blkif;
	struct xen_blkif *blkif = be->blkif;
	int err;
	int err;
	int state = 0;
	int state = 0, discard_enable;
	struct block_device *bdev = be->blkif->vbd.bdev;
	struct block_device *bdev = be->blkif->vbd.bdev;
	struct request_queue *q = bdev_get_queue(bdev);
	struct request_queue *q = bdev_get_queue(bdev);


	err = xenbus_scanf(XBT_NIL, dev->nodename, "discard-enable", "%d",
			   &discard_enable);
	if (err == 1 && !discard_enable)
		return;

	if (blk_queue_discard(q)) {
	if (blk_queue_discard(q)) {
		err = xenbus_printf(xbt, dev->nodename,
		err = xenbus_printf(xbt, dev->nodename,
			"discard-granularity", "%u",
			"discard-granularity", "%u",
@@ -700,7 +723,11 @@ static void frontend_changed(struct xenbus_device *dev,
		 * Enforce precondition before potential leak point.
		 * Enforce precondition before potential leak point.
		 * xen_blkif_disconnect() is idempotent.
		 * xen_blkif_disconnect() is idempotent.
		 */
		 */
		xen_blkif_disconnect(be->blkif);
		err = xen_blkif_disconnect(be->blkif);
		if (err) {
			xenbus_dev_fatal(dev, err, "pending I/O");
			break;
		}


		err = connect_ring(be);
		err = connect_ring(be);
		if (err)
		if (err)
+14 −26
Original line number Original line Diff line number Diff line
@@ -1635,23 +1635,16 @@ blkfront_closing(struct blkfront_info *info)
static void blkfront_setup_discard(struct blkfront_info *info)
static void blkfront_setup_discard(struct blkfront_info *info)
{
{
	int err;
	int err;
	char *type;
	unsigned int discard_granularity;
	unsigned int discard_granularity;
	unsigned int discard_alignment;
	unsigned int discard_alignment;
	unsigned int discard_secure;
	unsigned int discard_secure;


	type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL);
	info->feature_discard = 1;
	if (IS_ERR(type))
		return;

	info->feature_secdiscard = 0;
	if (strncmp(type, "phy", 3) == 0) {
	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
		"discard-granularity", "%u", &discard_granularity,
		"discard-granularity", "%u", &discard_granularity,
		"discard-alignment", "%u", &discard_alignment,
		"discard-alignment", "%u", &discard_alignment,
		NULL);
		NULL);
	if (!err) {
	if (!err) {
			info->feature_discard = 1;
		info->discard_granularity = discard_granularity;
		info->discard_granularity = discard_granularity;
		info->discard_alignment = discard_alignment;
		info->discard_alignment = discard_alignment;
	}
	}
@@ -1659,12 +1652,7 @@ static void blkfront_setup_discard(struct blkfront_info *info)
		    "discard-secure", "%d", &discard_secure,
		    "discard-secure", "%d", &discard_secure,
		    NULL);
		    NULL);
	if (!err)
	if (!err)
			info->feature_secdiscard = discard_secure;
		info->feature_secdiscard = !!discard_secure;

	} else if (strncmp(type, "file", 4) == 0)
		info->feature_discard = 1;

	kfree(type);
}
}


static int blkfront_setup_indirect(struct blkfront_info *info)
static int blkfront_setup_indirect(struct blkfront_info *info)
+1 −1
Original line number Original line Diff line number Diff line
@@ -86,7 +86,7 @@ typedef uint64_t blkif_sector_t;
 *     Interface%20manuals/100293068c.pdf
 *     Interface%20manuals/100293068c.pdf
 * The backend can optionally provide three extra XenBus attributes to
 * The backend can optionally provide three extra XenBus attributes to
 * further optimize the discard functionality:
 * further optimize the discard functionality:
 * 'discard-aligment' - Devices that support discard functionality may
 * 'discard-alignment' - Devices that support discard functionality may
 * internally allocate space in units that are bigger than the exported
 * internally allocate space in units that are bigger than the exported
 * logical block size. The discard-alignment parameter indicates how many bytes
 * logical block size. The discard-alignment parameter indicates how many bytes
 * the beginning of the partition is offset from the internal allocation unit's
 * the beginning of the partition is offset from the internal allocation unit's