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

Commit ec2f0fad authored by Jens Axboe's avatar Jens Axboe
Browse files

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

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

Pull xen-blkback fixes from Konrad:

"Security and memory leak fixes in xen block driver."
parents dc9edc44 089bc014
Loading
Loading
Loading
Loading
+12 −14
Original line number Diff line number Diff line
@@ -609,8 +609,6 @@ int xen_blkif_schedule(void *arg)
	unsigned long timeout;
	int ret;

	xen_blkif_get(blkif);

	set_freezable();
	while (!kthread_should_stop()) {
		if (try_to_freeze())
@@ -665,7 +663,6 @@ int xen_blkif_schedule(void *arg)
		print_stats(ring);

	ring->xenblkd = NULL;
	xen_blkif_put(blkif);

	return 0;
}
@@ -1436,34 +1433,35 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
static void make_response(struct xen_blkif_ring *ring, u64 id,
			  unsigned short op, int st)
{
	struct blkif_response  resp;
	struct blkif_response *resp;
	unsigned long     flags;
	union blkif_back_rings *blk_rings;
	int notify;

	resp.id        = id;
	resp.operation = op;
	resp.status    = st;

	spin_lock_irqsave(&ring->blk_ring_lock, flags);
	blk_rings = &ring->blk_rings;
	/* Place on the response ring for the relevant domain. */
	switch (ring->blkif->blk_protocol) {
	case BLKIF_PROTOCOL_NATIVE:
		memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt),
		       &resp, sizeof(resp));
		resp = RING_GET_RESPONSE(&blk_rings->native,
					 blk_rings->native.rsp_prod_pvt);
		break;
	case BLKIF_PROTOCOL_X86_32:
		memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt),
		       &resp, sizeof(resp));
		resp = RING_GET_RESPONSE(&blk_rings->x86_32,
					 blk_rings->x86_32.rsp_prod_pvt);
		break;
	case BLKIF_PROTOCOL_X86_64:
		memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt),
		       &resp, sizeof(resp));
		resp = RING_GET_RESPONSE(&blk_rings->x86_64,
					 blk_rings->x86_64.rsp_prod_pvt);
		break;
	default:
		BUG();
	}

	resp->id        = id;
	resp->operation = op;
	resp->status    = st;

	blk_rings->common.rsp_prod_pvt++;
	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
	spin_unlock_irqrestore(&ring->blk_ring_lock, flags);
+6 −20
Original line number Diff line number Diff line
@@ -75,9 +75,8 @@ extern unsigned int xenblk_max_queues;
struct blkif_common_request {
	char dummy;
};
struct blkif_common_response {
	char dummy;
};

/* i386 protocol version */

struct blkif_x86_32_request_rw {
	uint8_t        nr_segments;  /* number of segments                   */
@@ -129,14 +128,6 @@ struct blkif_x86_32_request {
	} u;
} __attribute__((__packed__));

/* i386 protocol version */
#pragma pack(push, 4)
struct blkif_x86_32_response {
	uint64_t        id;              /* copied from request */
	uint8_t         operation;       /* copied from request */
	int16_t         status;          /* BLKIF_RSP_???       */
};
#pragma pack(pop)
/* x86_64 protocol version */

struct blkif_x86_64_request_rw {
@@ -193,18 +184,12 @@ struct blkif_x86_64_request {
	} u;
} __attribute__((__packed__));

struct blkif_x86_64_response {
	uint64_t       __attribute__((__aligned__(8))) id;
	uint8_t         operation;       /* copied from request */
	int16_t         status;          /* BLKIF_RSP_???       */
};

DEFINE_RING_TYPES(blkif_common, struct blkif_common_request,
		  struct blkif_common_response);
		  struct blkif_response);
DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request,
		  struct blkif_x86_32_response);
		  struct blkif_response __packed);
DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request,
		  struct blkif_x86_64_response);
		  struct blkif_response);

union blkif_back_rings {
	struct blkif_back_ring        native;
@@ -281,6 +266,7 @@ struct xen_blkif_ring {

	wait_queue_head_t	wq;
	atomic_t		inflight;
	bool			active;
	/* One thread per blkif ring. */
	struct task_struct	*xenblkd;
	unsigned int		waiting_reqs;
+8 −7
Original line number Diff line number Diff line
@@ -159,7 +159,7 @@ static int xen_blkif_alloc_rings(struct xen_blkif *blkif)
		init_waitqueue_head(&ring->shutdown_wq);
		ring->blkif = blkif;
		ring->st_print = jiffies;
		xen_blkif_get(blkif);
		ring->active = true;
	}

	return 0;
@@ -249,10 +249,12 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
		struct xen_blkif_ring *ring = &blkif->rings[r];
		unsigned int i = 0;

		if (!ring->active)
			continue;

		if (ring->xenblkd) {
			kthread_stop(ring->xenblkd);
			wake_up(&ring->shutdown_wq);
			ring->xenblkd = NULL;
		}

		/* The above kthread_stop() guarantees that at this point we
@@ -296,7 +298,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
		BUG_ON(ring->free_pages_num != 0);
		BUG_ON(ring->persistent_gnt_c != 0);
		WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
		xen_blkif_put(blkif);
		ring->active = false;
	}
	blkif->nr_ring_pages = 0;
	/*
@@ -312,9 +314,10 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)

static void xen_blkif_free(struct xen_blkif *blkif)
{

	xen_blkif_disconnect(blkif);
	WARN_ON(xen_blkif_disconnect(blkif));
	xen_vbd_free(&blkif->vbd);
	kfree(blkif->be->mode);
	kfree(blkif->be);

	/* Make sure everything is drained before shutting down */
	kmem_cache_free(xen_blkif_cachep, blkif);
@@ -511,8 +514,6 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
		xen_blkif_put(be->blkif);
	}

	kfree(be->mode);
	kfree(be);
	return 0;
}