mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
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.
This commit is contained in:
commit
879466e6a5
@ -314,7 +314,7 @@ struct xen_blkif {
|
||||
unsigned long long st_rd_sect;
|
||||
unsigned long long st_wr_sect;
|
||||
|
||||
wait_queue_head_t waiting_to_free;
|
||||
struct work_struct free_work;
|
||||
/* Thread shutdown wait queue. */
|
||||
wait_queue_head_t shutdown_wq;
|
||||
};
|
||||
@ -361,7 +361,7 @@ struct pending_req {
|
||||
#define xen_blkif_put(_b) \
|
||||
do { \
|
||||
if (atomic_dec_and_test(&(_b)->refcnt)) \
|
||||
wake_up(&(_b)->waiting_to_free);\
|
||||
schedule_work(&(_b)->free_work);\
|
||||
} while (0)
|
||||
|
||||
struct phys_req {
|
||||
|
@ -35,12 +35,26 @@ static void connect(struct backend_info *);
|
||||
static int connect_ring(struct backend_info *);
|
||||
static void backend_changed(struct xenbus_watch *, const char **,
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
char *devpath, *devname;
|
||||
@ -121,7 +135,6 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
|
||||
init_completion(&blkif->drain_complete);
|
||||
atomic_set(&blkif->drain, 0);
|
||||
blkif->st_print = jiffies;
|
||||
init_waitqueue_head(&blkif->waiting_to_free);
|
||||
blkif->persistent_gnts.rb_node = NULL;
|
||||
spin_lock_init(&blkif->free_pages_lock);
|
||||
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_LIST_HEAD(&blkif->pending_free);
|
||||
INIT_WORK(&blkif->free_work, xen_blkif_deferred_free);
|
||||
|
||||
for (i = 0; i < XEN_BLKIF_REQS; i++) {
|
||||
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;
|
||||
}
|
||||
|
||||
static void xen_blkif_disconnect(struct xen_blkif *blkif)
|
||||
static int xen_blkif_disconnect(struct xen_blkif *blkif)
|
||||
{
|
||||
if (blkif->xenblkd) {
|
||||
kthread_stop(blkif->xenblkd);
|
||||
@ -239,9 +253,12 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
|
||||
blkif->xenblkd = NULL;
|
||||
}
|
||||
|
||||
atomic_dec(&blkif->refcnt);
|
||||
wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
|
||||
atomic_inc(&blkif->refcnt);
|
||||
/* The above kthread_stop() guarantees that at this point we
|
||||
* don't have any discard_io or other_io requests. So, checking
|
||||
* for inflight IO is enough.
|
||||
*/
|
||||
if (atomic_read(&blkif->inflight) > 0)
|
||||
return -EBUSY;
|
||||
|
||||
if (blkif->irq) {
|
||||
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);
|
||||
blkif->blk_rings.common.sring = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
int i = 0, j;
|
||||
|
||||
if (!atomic_dec_and_test(&blkif->refcnt))
|
||||
BUG();
|
||||
xen_blkif_disconnect(blkif);
|
||||
xen_vbd_free(&blkif->vbd);
|
||||
|
||||
/* Remove all persistent grants and the cache of ballooned pages. */
|
||||
xen_blkbk_free_caches(blkif);
|
||||
@ -449,16 +468,15 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
|
||||
be->backend_watch.node = NULL;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&dev->dev, NULL);
|
||||
|
||||
if (be->blkif) {
|
||||
xen_blkif_disconnect(be->blkif);
|
||||
xen_vbd_free(&be->blkif->vbd);
|
||||
xen_blkif_free(be->blkif);
|
||||
be->blkif = NULL;
|
||||
xen_blkif_put(be->blkif);
|
||||
}
|
||||
|
||||
kfree(be->mode);
|
||||
kfree(be);
|
||||
dev_set_drvdata(&dev->dev, NULL);
|
||||
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 xen_blkif *blkif = be->blkif;
|
||||
int err;
|
||||
int state = 0;
|
||||
int state = 0, discard_enable;
|
||||
struct block_device *bdev = be->blkif->vbd.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)) {
|
||||
err = xenbus_printf(xbt, dev->nodename,
|
||||
"discard-granularity", "%u",
|
||||
@ -700,7 +723,11 @@ static void frontend_changed(struct xenbus_device *dev,
|
||||
* Enforce precondition before potential leak point.
|
||||
* 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);
|
||||
if (err)
|
||||
|
@ -1635,36 +1635,24 @@ blkfront_closing(struct blkfront_info *info)
|
||||
static void blkfront_setup_discard(struct blkfront_info *info)
|
||||
{
|
||||
int err;
|
||||
char *type;
|
||||
unsigned int discard_granularity;
|
||||
unsigned int discard_alignment;
|
||||
unsigned int discard_secure;
|
||||
|
||||
type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL);
|
||||
if (IS_ERR(type))
|
||||
return;
|
||||
|
||||
info->feature_secdiscard = 0;
|
||||
if (strncmp(type, "phy", 3) == 0) {
|
||||
err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
|
||||
"discard-granularity", "%u", &discard_granularity,
|
||||
"discard-alignment", "%u", &discard_alignment,
|
||||
NULL);
|
||||
if (!err) {
|
||||
info->feature_discard = 1;
|
||||
info->discard_granularity = discard_granularity;
|
||||
info->discard_alignment = discard_alignment;
|
||||
}
|
||||
err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
|
||||
"discard-secure", "%d", &discard_secure,
|
||||
NULL);
|
||||
if (!err)
|
||||
info->feature_secdiscard = discard_secure;
|
||||
|
||||
} else if (strncmp(type, "file", 4) == 0)
|
||||
info->feature_discard = 1;
|
||||
|
||||
kfree(type);
|
||||
info->feature_discard = 1;
|
||||
err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
|
||||
"discard-granularity", "%u", &discard_granularity,
|
||||
"discard-alignment", "%u", &discard_alignment,
|
||||
NULL);
|
||||
if (!err) {
|
||||
info->discard_granularity = discard_granularity;
|
||||
info->discard_alignment = discard_alignment;
|
||||
}
|
||||
err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
|
||||
"discard-secure", "%d", &discard_secure,
|
||||
NULL);
|
||||
if (!err)
|
||||
info->feature_secdiscard = !!discard_secure;
|
||||
}
|
||||
|
||||
static int blkfront_setup_indirect(struct blkfront_info *info)
|
||||
|
@ -86,7 +86,7 @@ typedef uint64_t blkif_sector_t;
|
||||
* Interface%20manuals/100293068c.pdf
|
||||
* The backend can optionally provide three extra XenBus attributes to
|
||||
* 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
|
||||
* logical block size. The discard-alignment parameter indicates how many bytes
|
||||
* the beginning of the partition is offset from the internal allocation unit's
|
||||
|
Loading…
Reference in New Issue
Block a user