1dfc07b13SKonrad Rzeszutek Wilk /******************************************************************************
2dfc07b13SKonrad Rzeszutek Wilk  *
3dfc07b13SKonrad Rzeszutek Wilk  * Back-end of the driver for virtual block devices. This portion of the
4dfc07b13SKonrad Rzeszutek Wilk  * driver exports a 'unified' block-device interface that can be accessed
5dfc07b13SKonrad Rzeszutek Wilk  * by any operating system that implements a compatible front end. A
6dfc07b13SKonrad Rzeszutek Wilk  * reference front-end implementation can be found in:
7dfc07b13SKonrad Rzeszutek Wilk  *  drivers/block/xen-blkfront.c
8dfc07b13SKonrad Rzeszutek Wilk  *
9dfc07b13SKonrad Rzeszutek Wilk  * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
10dfc07b13SKonrad Rzeszutek Wilk  * Copyright (c) 2005, Christopher Clark
11dfc07b13SKonrad Rzeszutek Wilk  *
12dfc07b13SKonrad Rzeszutek Wilk  * This program is free software; you can redistribute it and/or
13dfc07b13SKonrad Rzeszutek Wilk  * modify it under the terms of the GNU General Public License version 2
14dfc07b13SKonrad Rzeszutek Wilk  * as published by the Free Software Foundation; or, when distributed
15dfc07b13SKonrad Rzeszutek Wilk  * separately from the Linux kernel or incorporated into other
16dfc07b13SKonrad Rzeszutek Wilk  * software packages, subject to the following license:
17dfc07b13SKonrad Rzeszutek Wilk  *
18dfc07b13SKonrad Rzeszutek Wilk  * Permission is hereby granted, free of charge, to any person obtaining a copy
19dfc07b13SKonrad Rzeszutek Wilk  * of this source file (the "Software"), to deal in the Software without
20dfc07b13SKonrad Rzeszutek Wilk  * restriction, including without limitation the rights to use, copy, modify,
21dfc07b13SKonrad Rzeszutek Wilk  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
22dfc07b13SKonrad Rzeszutek Wilk  * and to permit persons to whom the Software is furnished to do so, subject to
23dfc07b13SKonrad Rzeszutek Wilk  * the following conditions:
24dfc07b13SKonrad Rzeszutek Wilk  *
25dfc07b13SKonrad Rzeszutek Wilk  * The above copyright notice and this permission notice shall be included in
26dfc07b13SKonrad Rzeszutek Wilk  * all copies or substantial portions of the Software.
27dfc07b13SKonrad Rzeszutek Wilk  *
28dfc07b13SKonrad Rzeszutek Wilk  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29dfc07b13SKonrad Rzeszutek Wilk  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30dfc07b13SKonrad Rzeszutek Wilk  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31dfc07b13SKonrad Rzeszutek Wilk  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32dfc07b13SKonrad Rzeszutek Wilk  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33dfc07b13SKonrad Rzeszutek Wilk  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34dfc07b13SKonrad Rzeszutek Wilk  * IN THE SOFTWARE.
35dfc07b13SKonrad Rzeszutek Wilk  */
36dfc07b13SKonrad Rzeszutek Wilk 
3777387b82STao Chen #define pr_fmt(fmt) "xen-blkback: " fmt
3877387b82STao Chen 
39dfc07b13SKonrad Rzeszutek Wilk #include <linux/spinlock.h>
40dfc07b13SKonrad Rzeszutek Wilk #include <linux/kthread.h>
41dfc07b13SKonrad Rzeszutek Wilk #include <linux/list.h>
42dfc07b13SKonrad Rzeszutek Wilk #include <linux/delay.h>
43dfc07b13SKonrad Rzeszutek Wilk #include <linux/freezer.h>
440a8704a5SRoger Pau Monne #include <linux/bitmap.h>
45dfc07b13SKonrad Rzeszutek Wilk 
46dfc07b13SKonrad Rzeszutek Wilk #include <xen/events.h>
47dfc07b13SKonrad Rzeszutek Wilk #include <xen/page.h>
48e79affc3SStefano Stabellini #include <xen/xen.h>
49dfc07b13SKonrad Rzeszutek Wilk #include <asm/xen/hypervisor.h>
50dfc07b13SKonrad Rzeszutek Wilk #include <asm/xen/hypercall.h>
51087ffecdSRoger Pau Monne #include <xen/balloon.h>
52c43cf3eaSJennifer Herbert #include <xen/grant_table.h>
53dfc07b13SKonrad Rzeszutek Wilk #include "common.h"
54dfc07b13SKonrad Rzeszutek Wilk 
55dfc07b13SKonrad Rzeszutek Wilk /*
56c6cc142dSRoger Pau Monne  * Maximum number of unused free pages to keep in the internal buffer.
57c6cc142dSRoger Pau Monne  * Setting this to a value too low will reduce memory used in each backend,
58c6cc142dSRoger Pau Monne  * but can have a performance penalty.
59c6cc142dSRoger Pau Monne  *
60c6cc142dSRoger Pau Monne  * A sane value is xen_blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST, but can
61c6cc142dSRoger Pau Monne  * be set to a lower value that might degrade performance on some intensive
62c6cc142dSRoger Pau Monne  * IO workloads.
63c6cc142dSRoger Pau Monne  */
64c6cc142dSRoger Pau Monne 
65823f2091SSeongJae Park static int max_buffer_pages = 1024;
66823f2091SSeongJae Park module_param_named(max_buffer_pages, max_buffer_pages, int, 0644);
67c6cc142dSRoger Pau Monne MODULE_PARM_DESC(max_buffer_pages,
68c6cc142dSRoger Pau Monne "Maximum number of free pages to keep in each block backend buffer");
69c6cc142dSRoger Pau Monne 
703f3aad5eSRoger Pau Monne /*
713f3aad5eSRoger Pau Monne  * Maximum number of grants to map persistently in blkback. For maximum
723f3aad5eSRoger Pau Monne  * performance this should be the total numbers of grants that can be used
733f3aad5eSRoger Pau Monne  * to fill the ring, but since this might become too high, specially with
743f3aad5eSRoger Pau Monne  * the use of indirect descriptors, we set it to a value that provides good
753f3aad5eSRoger Pau Monne  * performance without using too much memory.
763f3aad5eSRoger Pau Monne  *
773f3aad5eSRoger Pau Monne  * When the list of persistent grants is full we clean it up using a LRU
783f3aad5eSRoger Pau Monne  * algorithm.
793f3aad5eSRoger Pau Monne  */
803f3aad5eSRoger Pau Monne 
81823f2091SSeongJae Park static int max_pgrants = 1056;
82823f2091SSeongJae Park module_param_named(max_persistent_grants, max_pgrants, int, 0644);
833f3aad5eSRoger Pau Monne MODULE_PARM_DESC(max_persistent_grants,
843f3aad5eSRoger Pau Monne                  "Maximum number of grants to map persistently");
853f3aad5eSRoger Pau Monne 
863f3aad5eSRoger Pau Monne /*
87973e5405SJuergen Gross  * How long a persistent grant is allowed to remain allocated without being in
88973e5405SJuergen Gross  * use. The time is in seconds, 0 means indefinitely long.
89973e5405SJuergen Gross  */
90973e5405SJuergen Gross 
91823f2091SSeongJae Park static unsigned int pgrant_timeout = 60;
92823f2091SSeongJae Park module_param_named(persistent_grant_unused_seconds, pgrant_timeout,
93973e5405SJuergen Gross 		   uint, 0644);
94973e5405SJuergen Gross MODULE_PARM_DESC(persistent_grant_unused_seconds,
95973e5405SJuergen Gross 		 "Time in seconds an unused persistent grant is allowed to "
96973e5405SJuergen Gross 		 "remain allocated. Default is 60, 0 means unlimited.");
97973e5405SJuergen Gross 
98973e5405SJuergen Gross /*
99d62d8600SBob Liu  * Maximum number of rings/queues blkback supports, allow as many queues as there
100d62d8600SBob Liu  * are CPUs if user has not specified a value.
101d62d8600SBob Liu  */
102d62d8600SBob Liu unsigned int xenblk_max_queues;
103d62d8600SBob Liu module_param_named(max_queues, xenblk_max_queues, uint, 0644);
104d62d8600SBob Liu MODULE_PARM_DESC(max_queues,
105d62d8600SBob Liu 		 "Maximum number of hardware queues per virtual disk." \
106d62d8600SBob Liu 		 "By default it is the number of online CPUs.");
107d62d8600SBob Liu 
108d62d8600SBob Liu /*
10986839c56SBob Liu  * Maximum order of pages to be used for the shared ring between front and
11086839c56SBob Liu  * backend, 4KB page granularity is used.
11186839c56SBob Liu  */
1129cce2914SJulien Grall unsigned int xen_blkif_max_ring_order = XENBUS_MAX_RING_GRANT_ORDER;
1135657a819SJoe Perches module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, 0444);
11486839c56SBob Liu MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring");
11586839c56SBob Liu /*
1163f3aad5eSRoger Pau Monne  * The LRU mechanism to clean the lists of persistent grants needs to
1173f3aad5eSRoger Pau Monne  * be executed periodically. The time interval between consecutive executions
1183f3aad5eSRoger Pau Monne  * of the purge mechanism is set in ms.
1193f3aad5eSRoger Pau Monne  */
1203f3aad5eSRoger Pau Monne #define LRU_INTERVAL 100
1213f3aad5eSRoger Pau Monne 
1223f3aad5eSRoger Pau Monne /*
1233f3aad5eSRoger Pau Monne  * When the persistent grants list is full we will remove unused grants
1243f3aad5eSRoger Pau Monne  * from the list. The percent number of grants to be removed at each LRU
1253f3aad5eSRoger Pau Monne  * execution.
1263f3aad5eSRoger Pau Monne  */
1273f3aad5eSRoger Pau Monne #define LRU_PERCENT_CLEAN 5
1283f3aad5eSRoger Pau Monne 
129dfc07b13SKonrad Rzeszutek Wilk /* Run-time switchable: /sys/module/blkback/parameters/ */
130dfc07b13SKonrad Rzeszutek Wilk static unsigned int log_stats;
131dfc07b13SKonrad Rzeszutek Wilk module_param(log_stats, int, 0644);
132dfc07b13SKonrad Rzeszutek Wilk 
133dfc07b13SKonrad Rzeszutek Wilk #define BLKBACK_INVALID_HANDLE (~0)
134dfc07b13SKonrad Rzeszutek Wilk 
persistent_gnt_timeout(struct persistent_gnt * persistent_gnt)135973e5405SJuergen Gross static inline bool persistent_gnt_timeout(struct persistent_gnt *persistent_gnt)
136973e5405SJuergen Gross {
137823f2091SSeongJae Park 	return pgrant_timeout && (jiffies - persistent_gnt->last_used >=
138823f2091SSeongJae Park 			HZ * pgrant_timeout);
139973e5405SJuergen Gross }
140973e5405SJuergen Gross 
141c6cc142dSRoger Pau Monne #define vaddr(page) ((unsigned long)pfn_to_kaddr(page_to_pfn(page)))
142dfc07b13SKonrad Rzeszutek Wilk 
14301263a1fSJuergen Gross static int do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags);
14459795700SBob Liu static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
145dfc07b13SKonrad Rzeszutek Wilk 				struct blkif_request *req,
146dfc07b13SKonrad Rzeszutek Wilk 				struct pending_req *pending_req);
14759795700SBob Liu static void make_response(struct xen_blkif_ring *ring, u64 id,
148dfc07b13SKonrad Rzeszutek Wilk 			  unsigned short op, int st);
149dfc07b13SKonrad Rzeszutek Wilk 
1507dc34117SRoger Pau Monne #define foreach_grant_safe(pos, n, rbtree, node) \
1517dc34117SRoger Pau Monne 	for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \
152217fd5e7SRoger Pau Monne 	     (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL; \
1530a8704a5SRoger Pau Monne 	     &(pos)->node != NULL; \
1547dc34117SRoger Pau Monne 	     (pos) = container_of(n, typeof(*(pos)), node), \
1557dc34117SRoger Pau Monne 	     (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)
1560a8704a5SRoger Pau Monne 
1570a8704a5SRoger Pau Monne 
1583f3aad5eSRoger Pau Monne /*
1593f3aad5eSRoger Pau Monne  * We don't need locking around the persistent grant helpers
160d4bf0065SBob Liu  * because blkback uses a single-thread for each backend, so we
1613f3aad5eSRoger Pau Monne  * can be sure that this functions will never be called recursively.
1623f3aad5eSRoger Pau Monne  *
1633f3aad5eSRoger Pau Monne  * The only exception to that is put_persistent_grant, that can be called
1643f3aad5eSRoger Pau Monne  * from interrupt context (by xen_blkbk_unmap), so we have to use atomic
1653f3aad5eSRoger Pau Monne  * bit operations to modify the flags of a persistent grant and to count
1663f3aad5eSRoger Pau Monne  * the number of used grants.
1673f3aad5eSRoger Pau Monne  */
add_persistent_gnt(struct xen_blkif_ring * ring,struct persistent_gnt * persistent_gnt)168d4bf0065SBob Liu static int add_persistent_gnt(struct xen_blkif_ring *ring,
1690a8704a5SRoger Pau Monne 			       struct persistent_gnt *persistent_gnt)
1700a8704a5SRoger Pau Monne {
1713f3aad5eSRoger Pau Monne 	struct rb_node **new = NULL, *parent = NULL;
1720a8704a5SRoger Pau Monne 	struct persistent_gnt *this;
173d4bf0065SBob Liu 	struct xen_blkif *blkif = ring->blkif;
1740a8704a5SRoger Pau Monne 
175823f2091SSeongJae Park 	if (ring->persistent_gnt_c >= max_pgrants) {
1763f3aad5eSRoger Pau Monne 		if (!blkif->vbd.overflow_max_grants)
1773f3aad5eSRoger Pau Monne 			blkif->vbd.overflow_max_grants = 1;
1783f3aad5eSRoger Pau Monne 		return -EBUSY;
1793f3aad5eSRoger Pau Monne 	}
1800a8704a5SRoger Pau Monne 	/* Figure out where to put new node */
181d4bf0065SBob Liu 	new = &ring->persistent_gnts.rb_node;
1820a8704a5SRoger Pau Monne 	while (*new) {
1830a8704a5SRoger Pau Monne 		this = container_of(*new, struct persistent_gnt, node);
1840a8704a5SRoger Pau Monne 
1850a8704a5SRoger Pau Monne 		parent = *new;
1860a8704a5SRoger Pau Monne 		if (persistent_gnt->gnt < this->gnt)
1870a8704a5SRoger Pau Monne 			new = &((*new)->rb_left);
1880a8704a5SRoger Pau Monne 		else if (persistent_gnt->gnt > this->gnt)
1890a8704a5SRoger Pau Monne 			new = &((*new)->rb_right);
1900a8704a5SRoger Pau Monne 		else {
19177387b82STao Chen 			pr_alert_ratelimited("trying to add a gref that's already in the tree\n");
192c6cc142dSRoger Pau Monne 			return -EINVAL;
1930a8704a5SRoger Pau Monne 		}
1940a8704a5SRoger Pau Monne 	}
1950a8704a5SRoger Pau Monne 
196d77ff24eSJuergen Gross 	persistent_gnt->active = true;
1970a8704a5SRoger Pau Monne 	/* Add new node and rebalance tree. */
1980a8704a5SRoger Pau Monne 	rb_link_node(&(persistent_gnt->node), parent, new);
199d4bf0065SBob Liu 	rb_insert_color(&(persistent_gnt->node), &ring->persistent_gnts);
200d4bf0065SBob Liu 	ring->persistent_gnt_c++;
201d4bf0065SBob Liu 	atomic_inc(&ring->persistent_gnt_in_use);
202c6cc142dSRoger Pau Monne 	return 0;
2030a8704a5SRoger Pau Monne }
2040a8704a5SRoger Pau Monne 
get_persistent_gnt(struct xen_blkif_ring * ring,grant_ref_t gref)205d4bf0065SBob Liu static struct persistent_gnt *get_persistent_gnt(struct xen_blkif_ring *ring,
2060a8704a5SRoger Pau Monne 						 grant_ref_t gref)
2070a8704a5SRoger Pau Monne {
2080a8704a5SRoger Pau Monne 	struct persistent_gnt *data;
2093f3aad5eSRoger Pau Monne 	struct rb_node *node = NULL;
2100a8704a5SRoger Pau Monne 
211d4bf0065SBob Liu 	node = ring->persistent_gnts.rb_node;
2120a8704a5SRoger Pau Monne 	while (node) {
2130a8704a5SRoger Pau Monne 		data = container_of(node, struct persistent_gnt, node);
2140a8704a5SRoger Pau Monne 
2150a8704a5SRoger Pau Monne 		if (gref < data->gnt)
2160a8704a5SRoger Pau Monne 			node = node->rb_left;
2170a8704a5SRoger Pau Monne 		else if (gref > data->gnt)
2180a8704a5SRoger Pau Monne 			node = node->rb_right;
2193f3aad5eSRoger Pau Monne 		else {
220d77ff24eSJuergen Gross 			if (data->active) {
22177387b82STao Chen 				pr_alert_ratelimited("requesting a grant already in use\n");
2223f3aad5eSRoger Pau Monne 				return NULL;
2233f3aad5eSRoger Pau Monne 			}
224d77ff24eSJuergen Gross 			data->active = true;
225d4bf0065SBob Liu 			atomic_inc(&ring->persistent_gnt_in_use);
2260a8704a5SRoger Pau Monne 			return data;
2270a8704a5SRoger Pau Monne 		}
2283f3aad5eSRoger Pau Monne 	}
2290a8704a5SRoger Pau Monne 	return NULL;
2300a8704a5SRoger Pau Monne }
2310a8704a5SRoger Pau Monne 
put_persistent_gnt(struct xen_blkif_ring * ring,struct persistent_gnt * persistent_gnt)232d4bf0065SBob Liu static void put_persistent_gnt(struct xen_blkif_ring *ring,
2333f3aad5eSRoger Pau Monne                                struct persistent_gnt *persistent_gnt)
2343f3aad5eSRoger Pau Monne {
235d77ff24eSJuergen Gross 	if (!persistent_gnt->active)
23677387b82STao Chen 		pr_alert_ratelimited("freeing a grant already unused\n");
237973e5405SJuergen Gross 	persistent_gnt->last_used = jiffies;
238d77ff24eSJuergen Gross 	persistent_gnt->active = false;
239d4bf0065SBob Liu 	atomic_dec(&ring->persistent_gnt_in_use);
2403f3aad5eSRoger Pau Monne }
2413f3aad5eSRoger Pau Monne 
free_persistent_gnts(struct xen_blkif_ring * ring)242e7b4c07dSJuergen Gross static void free_persistent_gnts(struct xen_blkif_ring *ring)
2434d4f270fSRoger Pau Monne {
244e7b4c07dSJuergen Gross 	struct rb_root *root = &ring->persistent_gnts;
2454d4f270fSRoger Pau Monne 	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
2464d4f270fSRoger Pau Monne 	struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
2474d4f270fSRoger Pau Monne 	struct persistent_gnt *persistent_gnt;
2487dc34117SRoger Pau Monne 	struct rb_node *n;
2494d4f270fSRoger Pau Monne 	int segs_to_unmap = 0;
250c43cf3eaSJennifer Herbert 	struct gntab_unmap_queue_data unmap_data;
251c43cf3eaSJennifer Herbert 
252e7b4c07dSJuergen Gross 	if (RB_EMPTY_ROOT(root))
253e7b4c07dSJuergen Gross 		return;
254e7b4c07dSJuergen Gross 
255c43cf3eaSJennifer Herbert 	unmap_data.pages = pages;
256c43cf3eaSJennifer Herbert 	unmap_data.unmap_ops = unmap;
257c43cf3eaSJennifer Herbert 	unmap_data.kunmap_ops = NULL;
2584d4f270fSRoger Pau Monne 
2597dc34117SRoger Pau Monne 	foreach_grant_safe(persistent_gnt, n, root, node) {
2604d4f270fSRoger Pau Monne 		BUG_ON(persistent_gnt->handle ==
2614d4f270fSRoger Pau Monne 			BLKBACK_INVALID_HANDLE);
2624d4f270fSRoger Pau Monne 		gnttab_set_unmap_op(&unmap[segs_to_unmap],
2634d4f270fSRoger Pau Monne 			(unsigned long) pfn_to_kaddr(page_to_pfn(
2644d4f270fSRoger Pau Monne 				persistent_gnt->page)),
2654d4f270fSRoger Pau Monne 			GNTMAP_host_map,
2664d4f270fSRoger Pau Monne 			persistent_gnt->handle);
2674d4f270fSRoger Pau Monne 
2684d4f270fSRoger Pau Monne 		pages[segs_to_unmap] = persistent_gnt->page;
2694d4f270fSRoger Pau Monne 
2704d4f270fSRoger Pau Monne 		if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
2714d4f270fSRoger Pau Monne 			!rb_next(&persistent_gnt->node)) {
272c43cf3eaSJennifer Herbert 
273c43cf3eaSJennifer Herbert 			unmap_data.count = segs_to_unmap;
274b44166cdSBob Liu 			BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
275c43cf3eaSJennifer Herbert 
276ca33479cSJuergen Gross 			gnttab_page_cache_put(&ring->free_pages, pages,
277ca33479cSJuergen Gross 					      segs_to_unmap);
2784d4f270fSRoger Pau Monne 			segs_to_unmap = 0;
2794d4f270fSRoger Pau Monne 		}
2807dc34117SRoger Pau Monne 
2817dc34117SRoger Pau Monne 		rb_erase(&persistent_gnt->node, root);
2827dc34117SRoger Pau Monne 		kfree(persistent_gnt);
283e7b4c07dSJuergen Gross 		ring->persistent_gnt_c--;
2844d4f270fSRoger Pau Monne 	}
285e7b4c07dSJuergen Gross 
286e7b4c07dSJuergen Gross 	BUG_ON(!RB_EMPTY_ROOT(&ring->persistent_gnts));
287e7b4c07dSJuergen Gross 	BUG_ON(ring->persistent_gnt_c != 0);
2884d4f270fSRoger Pau Monne }
2894d4f270fSRoger Pau Monne 
xen_blkbk_unmap_purged_grants(struct work_struct * work)290abb97b8cSRoger Pau Monne void xen_blkbk_unmap_purged_grants(struct work_struct *work)
2913f3aad5eSRoger Pau Monne {
2923f3aad5eSRoger Pau Monne 	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
2933f3aad5eSRoger Pau Monne 	struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
2943f3aad5eSRoger Pau Monne 	struct persistent_gnt *persistent_gnt;
295325d73bfSBob Liu 	int segs_to_unmap = 0;
296d4bf0065SBob Liu 	struct xen_blkif_ring *ring = container_of(work, typeof(*ring), persistent_purge_work);
297325d73bfSBob Liu 	struct gntab_unmap_queue_data unmap_data;
298325d73bfSBob Liu 
299325d73bfSBob Liu 	unmap_data.pages = pages;
300325d73bfSBob Liu 	unmap_data.unmap_ops = unmap;
301325d73bfSBob Liu 	unmap_data.kunmap_ops = NULL;
3023f3aad5eSRoger Pau Monne 
303d4bf0065SBob Liu 	while(!list_empty(&ring->persistent_purge_list)) {
304d4bf0065SBob Liu 		persistent_gnt = list_first_entry(&ring->persistent_purge_list,
3053f3aad5eSRoger Pau Monne 		                                  struct persistent_gnt,
3063f3aad5eSRoger Pau Monne 		                                  remove_node);
3073f3aad5eSRoger Pau Monne 		list_del(&persistent_gnt->remove_node);
3083f3aad5eSRoger Pau Monne 
3093f3aad5eSRoger Pau Monne 		gnttab_set_unmap_op(&unmap[segs_to_unmap],
3103f3aad5eSRoger Pau Monne 			vaddr(persistent_gnt->page),
3113f3aad5eSRoger Pau Monne 			GNTMAP_host_map,
3123f3aad5eSRoger Pau Monne 			persistent_gnt->handle);
3133f3aad5eSRoger Pau Monne 
3143f3aad5eSRoger Pau Monne 		pages[segs_to_unmap] = persistent_gnt->page;
3153f3aad5eSRoger Pau Monne 
3163f3aad5eSRoger Pau Monne 		if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
317325d73bfSBob Liu 			unmap_data.count = segs_to_unmap;
318b44166cdSBob Liu 			BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
319ca33479cSJuergen Gross 			gnttab_page_cache_put(&ring->free_pages, pages,
320ca33479cSJuergen Gross 					      segs_to_unmap);
3213f3aad5eSRoger Pau Monne 			segs_to_unmap = 0;
3223f3aad5eSRoger Pau Monne 		}
3233f3aad5eSRoger Pau Monne 		kfree(persistent_gnt);
3243f3aad5eSRoger Pau Monne 	}
3253f3aad5eSRoger Pau Monne 	if (segs_to_unmap > 0) {
326325d73bfSBob Liu 		unmap_data.count = segs_to_unmap;
327b44166cdSBob Liu 		BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
328ca33479cSJuergen Gross 		gnttab_page_cache_put(&ring->free_pages, pages, segs_to_unmap);
3293f3aad5eSRoger Pau Monne 	}
3303f3aad5eSRoger Pau Monne }
3313f3aad5eSRoger Pau Monne 
purge_persistent_gnt(struct xen_blkif_ring * ring)332d4bf0065SBob Liu static void purge_persistent_gnt(struct xen_blkif_ring *ring)
3333f3aad5eSRoger Pau Monne {
3343f3aad5eSRoger Pau Monne 	struct persistent_gnt *persistent_gnt;
3353f3aad5eSRoger Pau Monne 	struct rb_node *n;
3363f3aad5eSRoger Pau Monne 	unsigned int num_clean, total;
337973e5405SJuergen Gross 	bool scan_used = false;
3383f3aad5eSRoger Pau Monne 	struct rb_root *root;
3393f3aad5eSRoger Pau Monne 
340d4bf0065SBob Liu 	if (work_busy(&ring->persistent_purge_work)) {
34153bc7dc0SBob Liu 		pr_alert_ratelimited("Scheduled work from previous purge is still busy, cannot purge list\n");
34259795700SBob Liu 		goto out;
3433f3aad5eSRoger Pau Monne 	}
3443f3aad5eSRoger Pau Monne 
345823f2091SSeongJae Park 	if (ring->persistent_gnt_c < max_pgrants ||
346823f2091SSeongJae Park 	    (ring->persistent_gnt_c == max_pgrants &&
347973e5405SJuergen Gross 	    !ring->blkif->vbd.overflow_max_grants)) {
348973e5405SJuergen Gross 		num_clean = 0;
349973e5405SJuergen Gross 	} else {
350823f2091SSeongJae Park 		num_clean = (max_pgrants / 100) * LRU_PERCENT_CLEAN;
351823f2091SSeongJae Park 		num_clean = ring->persistent_gnt_c - max_pgrants + num_clean;
352d4bf0065SBob Liu 		num_clean = min(ring->persistent_gnt_c, num_clean);
353973e5405SJuergen Gross 		pr_debug("Going to purge at least %u persistent grants\n",
354973e5405SJuergen Gross 			 num_clean);
355973e5405SJuergen Gross 	}
3563f3aad5eSRoger Pau Monne 
3573f3aad5eSRoger Pau Monne 	/*
3583f3aad5eSRoger Pau Monne 	 * At this point, we can assure that there will be no calls
3593f3aad5eSRoger Pau Monne          * to get_persistent_grant (because we are executing this code from
3603f3aad5eSRoger Pau Monne          * xen_blkif_schedule), there can only be calls to put_persistent_gnt,
3613f3aad5eSRoger Pau Monne          * which means that the number of currently used grants will go down,
3623f3aad5eSRoger Pau Monne          * but never up, so we will always be able to remove the requested
3633f3aad5eSRoger Pau Monne          * number of grants.
3643f3aad5eSRoger Pau Monne 	 */
3653f3aad5eSRoger Pau Monne 
366973e5405SJuergen Gross 	total = 0;
3673f3aad5eSRoger Pau Monne 
368d4bf0065SBob Liu 	BUG_ON(!list_empty(&ring->persistent_purge_list));
369d4bf0065SBob Liu 	root = &ring->persistent_gnts;
3703f3aad5eSRoger Pau Monne purge_list:
3713f3aad5eSRoger Pau Monne 	foreach_grant_safe(persistent_gnt, n, root, node) {
3723f3aad5eSRoger Pau Monne 		BUG_ON(persistent_gnt->handle ==
3733f3aad5eSRoger Pau Monne 			BLKBACK_INVALID_HANDLE);
3743f3aad5eSRoger Pau Monne 
375d77ff24eSJuergen Gross 		if (persistent_gnt->active)
3763f3aad5eSRoger Pau Monne 			continue;
377973e5405SJuergen Gross 		if (!scan_used && !persistent_gnt_timeout(persistent_gnt))
378973e5405SJuergen Gross 			continue;
379973e5405SJuergen Gross 		if (scan_used && total >= num_clean)
3803f3aad5eSRoger Pau Monne 			continue;
3813f3aad5eSRoger Pau Monne 
3823f3aad5eSRoger Pau Monne 		rb_erase(&persistent_gnt->node, root);
3833f3aad5eSRoger Pau Monne 		list_add(&persistent_gnt->remove_node,
384d4bf0065SBob Liu 			 &ring->persistent_purge_list);
385973e5405SJuergen Gross 		total++;
3863f3aad5eSRoger Pau Monne 	}
3873f3aad5eSRoger Pau Monne 	/*
388973e5405SJuergen Gross 	 * Check whether we also need to start cleaning
3893f3aad5eSRoger Pau Monne 	 * grants that were used since last purge in order to cope
3903f3aad5eSRoger Pau Monne 	 * with the requested num
3913f3aad5eSRoger Pau Monne 	 */
392973e5405SJuergen Gross 	if (!scan_used && total < num_clean) {
393973e5405SJuergen Gross 		pr_debug("Still missing %u purged frames\n", num_clean - total);
3943f3aad5eSRoger Pau Monne 		scan_used = true;
3953f3aad5eSRoger Pau Monne 		goto purge_list;
3963f3aad5eSRoger Pau Monne 	}
3972d910543SRoger Pau Monne 
398973e5405SJuergen Gross 	if (total) {
399973e5405SJuergen Gross 		ring->persistent_gnt_c -= total;
400d4bf0065SBob Liu 		ring->blkif->vbd.overflow_max_grants = 0;
4013f3aad5eSRoger Pau Monne 
4023f3aad5eSRoger Pau Monne 		/* We can defer this work */
403d4bf0065SBob Liu 		schedule_work(&ring->persistent_purge_work);
404973e5405SJuergen Gross 		pr_debug("Purged %u/%u\n", num_clean, total);
405973e5405SJuergen Gross 	}
40659795700SBob Liu 
40759795700SBob Liu out:
4083f3aad5eSRoger Pau Monne 	return;
4093f3aad5eSRoger Pau Monne }
4103f3aad5eSRoger Pau Monne 
411dfc07b13SKonrad Rzeszutek Wilk /*
412dfc07b13SKonrad Rzeszutek Wilk  * Retrieve from the 'pending_reqs' a free pending_req structure to be used.
413dfc07b13SKonrad Rzeszutek Wilk  */
alloc_req(struct xen_blkif_ring * ring)41459795700SBob Liu static struct pending_req *alloc_req(struct xen_blkif_ring *ring)
415dfc07b13SKonrad Rzeszutek Wilk {
416dfc07b13SKonrad Rzeszutek Wilk 	struct pending_req *req = NULL;
417dfc07b13SKonrad Rzeszutek Wilk 	unsigned long flags;
418dfc07b13SKonrad Rzeszutek Wilk 
41959795700SBob Liu 	spin_lock_irqsave(&ring->pending_free_lock, flags);
42059795700SBob Liu 	if (!list_empty(&ring->pending_free)) {
42159795700SBob Liu 		req = list_entry(ring->pending_free.next, struct pending_req,
422dfc07b13SKonrad Rzeszutek Wilk 				 free_list);
423dfc07b13SKonrad Rzeszutek Wilk 		list_del(&req->free_list);
424dfc07b13SKonrad Rzeszutek Wilk 	}
42559795700SBob Liu 	spin_unlock_irqrestore(&ring->pending_free_lock, flags);
426dfc07b13SKonrad Rzeszutek Wilk 	return req;
427dfc07b13SKonrad Rzeszutek Wilk }
428dfc07b13SKonrad Rzeszutek Wilk 
429dfc07b13SKonrad Rzeszutek Wilk /*
430dfc07b13SKonrad Rzeszutek Wilk  * Return the 'pending_req' structure back to the freepool. We also
431dfc07b13SKonrad Rzeszutek Wilk  * wake up the thread if it was waiting for a free page.
432dfc07b13SKonrad Rzeszutek Wilk  */
free_req(struct xen_blkif_ring * ring,struct pending_req * req)43359795700SBob Liu static void free_req(struct xen_blkif_ring *ring, struct pending_req *req)
434dfc07b13SKonrad Rzeszutek Wilk {
435dfc07b13SKonrad Rzeszutek Wilk 	unsigned long flags;
436dfc07b13SKonrad Rzeszutek Wilk 	int was_empty;
437dfc07b13SKonrad Rzeszutek Wilk 
43859795700SBob Liu 	spin_lock_irqsave(&ring->pending_free_lock, flags);
43959795700SBob Liu 	was_empty = list_empty(&ring->pending_free);
44059795700SBob Liu 	list_add(&req->free_list, &ring->pending_free);
44159795700SBob Liu 	spin_unlock_irqrestore(&ring->pending_free_lock, flags);
442dfc07b13SKonrad Rzeszutek Wilk 	if (was_empty)
44359795700SBob Liu 		wake_up(&ring->pending_free_wq);
444dfc07b13SKonrad Rzeszutek Wilk }
445dfc07b13SKonrad Rzeszutek Wilk 
446dfc07b13SKonrad Rzeszutek Wilk /*
447ee9ff853SKonrad Rzeszutek Wilk  * Routines for managing virtual block devices (vbds).
448ee9ff853SKonrad Rzeszutek Wilk  */
xen_vbd_translate(struct phys_req * req,struct xen_blkif * blkif,enum req_op operation)4493d814731SKonrad Rzeszutek Wilk static int xen_vbd_translate(struct phys_req *req, struct xen_blkif *blkif,
4506c5412e2SBart Van Assche 			     enum req_op operation)
451ee9ff853SKonrad Rzeszutek Wilk {
4523d814731SKonrad Rzeszutek Wilk 	struct xen_vbd *vbd = &blkif->vbd;
453ee9ff853SKonrad Rzeszutek Wilk 	int rc = -EACCES;
454ee9ff853SKonrad Rzeszutek Wilk 
455a022606eSMike Christie 	if ((operation != REQ_OP_READ) && vbd->readonly)
456ee9ff853SKonrad Rzeszutek Wilk 		goto out;
457ee9ff853SKonrad Rzeszutek Wilk 
4588ab52150SJan Beulich 	if (likely(req->nr_sects)) {
4598ab52150SJan Beulich 		blkif_sector_t end = req->sector_number + req->nr_sects;
4608ab52150SJan Beulich 
4618ab52150SJan Beulich 		if (unlikely(end < req->sector_number))
462ee9ff853SKonrad Rzeszutek Wilk 			goto out;
4638ab52150SJan Beulich 		if (unlikely(end > vbd_sz(vbd)))
4648ab52150SJan Beulich 			goto out;
4658ab52150SJan Beulich 	}
466ee9ff853SKonrad Rzeszutek Wilk 
467ee9ff853SKonrad Rzeszutek Wilk 	req->dev  = vbd->pdevice;
468ee9ff853SKonrad Rzeszutek Wilk 	req->bdev = vbd->bdev;
469ee9ff853SKonrad Rzeszutek Wilk 	rc = 0;
470ee9ff853SKonrad Rzeszutek Wilk 
471ee9ff853SKonrad Rzeszutek Wilk  out:
472ee9ff853SKonrad Rzeszutek Wilk 	return rc;
473ee9ff853SKonrad Rzeszutek Wilk }
474ee9ff853SKonrad Rzeszutek Wilk 
xen_vbd_resize(struct xen_blkif * blkif)4753d814731SKonrad Rzeszutek Wilk static void xen_vbd_resize(struct xen_blkif *blkif)
476ee9ff853SKonrad Rzeszutek Wilk {
4773d814731SKonrad Rzeszutek Wilk 	struct xen_vbd *vbd = &blkif->vbd;
478ee9ff853SKonrad Rzeszutek Wilk 	struct xenbus_transaction xbt;
479ee9ff853SKonrad Rzeszutek Wilk 	int err;
4808b6bf747SKonrad Rzeszutek Wilk 	struct xenbus_device *dev = xen_blkbk_xenbus(blkif->be);
48142c7841dSKonrad Rzeszutek Wilk 	unsigned long long new_size = vbd_sz(vbd);
482ee9ff853SKonrad Rzeszutek Wilk 
48377387b82STao Chen 	pr_info("VBD Resize: Domid: %d, Device: (%d, %d)\n",
484ee9ff853SKonrad Rzeszutek Wilk 		blkif->domid, MAJOR(vbd->pdevice), MINOR(vbd->pdevice));
48577387b82STao Chen 	pr_info("VBD Resize: new size %llu\n", new_size);
486ee9ff853SKonrad Rzeszutek Wilk 	vbd->size = new_size;
487ee9ff853SKonrad Rzeszutek Wilk again:
488ee9ff853SKonrad Rzeszutek Wilk 	err = xenbus_transaction_start(&xbt);
489ee9ff853SKonrad Rzeszutek Wilk 	if (err) {
49077387b82STao Chen 		pr_warn("Error starting transaction\n");
491ee9ff853SKonrad Rzeszutek Wilk 		return;
492ee9ff853SKonrad Rzeszutek Wilk 	}
493ee9ff853SKonrad Rzeszutek Wilk 	err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
49442c7841dSKonrad Rzeszutek Wilk 			    (unsigned long long)vbd_sz(vbd));
495ee9ff853SKonrad Rzeszutek Wilk 	if (err) {
49677387b82STao Chen 		pr_warn("Error writing new size\n");
497ee9ff853SKonrad Rzeszutek Wilk 		goto abort;
498ee9ff853SKonrad Rzeszutek Wilk 	}
499ee9ff853SKonrad Rzeszutek Wilk 	/*
500ee9ff853SKonrad Rzeszutek Wilk 	 * Write the current state; we will use this to synchronize
501ee9ff853SKonrad Rzeszutek Wilk 	 * the front-end. If the current state is "connected" the
502ee9ff853SKonrad Rzeszutek Wilk 	 * front-end will get the new size information online.
503ee9ff853SKonrad Rzeszutek Wilk 	 */
504ee9ff853SKonrad Rzeszutek Wilk 	err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state);
505ee9ff853SKonrad Rzeszutek Wilk 	if (err) {
50677387b82STao Chen 		pr_warn("Error writing the state\n");
507ee9ff853SKonrad Rzeszutek Wilk 		goto abort;
508ee9ff853SKonrad Rzeszutek Wilk 	}
509ee9ff853SKonrad Rzeszutek Wilk 
510ee9ff853SKonrad Rzeszutek Wilk 	err = xenbus_transaction_end(xbt, 0);
511ee9ff853SKonrad Rzeszutek Wilk 	if (err == -EAGAIN)
512ee9ff853SKonrad Rzeszutek Wilk 		goto again;
513ee9ff853SKonrad Rzeszutek Wilk 	if (err)
51477387b82STao Chen 		pr_warn("Error ending transaction\n");
515496b318eSLaszlo Ersek 	return;
516ee9ff853SKonrad Rzeszutek Wilk abort:
517ee9ff853SKonrad Rzeszutek Wilk 	xenbus_transaction_end(xbt, 1);
518ee9ff853SKonrad Rzeszutek Wilk }
519ee9ff853SKonrad Rzeszutek Wilk 
520ee9ff853SKonrad Rzeszutek Wilk /*
521dfc07b13SKonrad Rzeszutek Wilk  * Notification from the guest OS.
522dfc07b13SKonrad Rzeszutek Wilk  */
blkif_notify_work(struct xen_blkif_ring * ring)52359795700SBob Liu static void blkif_notify_work(struct xen_blkif_ring *ring)
524dfc07b13SKonrad Rzeszutek Wilk {
52559795700SBob Liu 	ring->waiting_reqs = 1;
52659795700SBob Liu 	wake_up(&ring->wq);
527dfc07b13SKonrad Rzeszutek Wilk }
528dfc07b13SKonrad Rzeszutek Wilk 
xen_blkif_be_int(int irq,void * dev_id)5298b6bf747SKonrad Rzeszutek Wilk irqreturn_t xen_blkif_be_int(int irq, void *dev_id)
530dfc07b13SKonrad Rzeszutek Wilk {
531dfc07b13SKonrad Rzeszutek Wilk 	blkif_notify_work(dev_id);
532dfc07b13SKonrad Rzeszutek Wilk 	return IRQ_HANDLED;
533dfc07b13SKonrad Rzeszutek Wilk }
534dfc07b13SKonrad Rzeszutek Wilk 
535dfc07b13SKonrad Rzeszutek Wilk /*
536dfc07b13SKonrad Rzeszutek Wilk  * SCHEDULER FUNCTIONS
537dfc07b13SKonrad Rzeszutek Wilk  */
538dfc07b13SKonrad Rzeszutek Wilk 
print_stats(struct xen_blkif_ring * ring)539d4bf0065SBob Liu static void print_stats(struct xen_blkif_ring *ring)
540dfc07b13SKonrad Rzeszutek Wilk {
54177387b82STao Chen 	pr_info("(%s): oo %3llu  |  rd %4llu  |  wr %4llu  |  f %4llu"
5423f3aad5eSRoger Pau Monne 		 "  |  ds %4llu | pg: %4u/%4d\n",
543db6fbc10SBob Liu 		 current->comm, ring->st_oo_req,
544db6fbc10SBob Liu 		 ring->st_rd_req, ring->st_wr_req,
545db6fbc10SBob Liu 		 ring->st_f_req, ring->st_ds_req,
546823f2091SSeongJae Park 		 ring->persistent_gnt_c, max_pgrants);
547db6fbc10SBob Liu 	ring->st_print = jiffies + msecs_to_jiffies(10 * 1000);
548db6fbc10SBob Liu 	ring->st_rd_req = 0;
549db6fbc10SBob Liu 	ring->st_wr_req = 0;
550db6fbc10SBob Liu 	ring->st_oo_req = 0;
551db6fbc10SBob Liu 	ring->st_ds_req = 0;
552dfc07b13SKonrad Rzeszutek Wilk }
553dfc07b13SKonrad Rzeszutek Wilk 
xen_blkif_schedule(void * arg)5548b6bf747SKonrad Rzeszutek Wilk int xen_blkif_schedule(void *arg)
555dfc07b13SKonrad Rzeszutek Wilk {
55659795700SBob Liu 	struct xen_blkif_ring *ring = arg;
55759795700SBob Liu 	struct xen_blkif *blkif = ring->blkif;
5583d814731SKonrad Rzeszutek Wilk 	struct xen_vbd *vbd = &blkif->vbd;
5593f3aad5eSRoger Pau Monne 	unsigned long timeout;
5608e3f8755SKonrad Rzeszutek Wilk 	int ret;
56101263a1fSJuergen Gross 	bool do_eoi;
56201263a1fSJuergen Gross 	unsigned int eoi_flags = XEN_EOI_FLAG_SPURIOUS;
563dfc07b13SKonrad Rzeszutek Wilk 
564a6e7af12SJiri Kosina 	set_freezable();
565dfc07b13SKonrad Rzeszutek Wilk 	while (!kthread_should_stop()) {
566dfc07b13SKonrad Rzeszutek Wilk 		if (try_to_freeze())
567dfc07b13SKonrad Rzeszutek Wilk 			continue;
56842c7841dSKonrad Rzeszutek Wilk 		if (unlikely(vbd->size != vbd_sz(vbd)))
5693d814731SKonrad Rzeszutek Wilk 			xen_vbd_resize(blkif);
570dfc07b13SKonrad Rzeszutek Wilk 
5713f3aad5eSRoger Pau Monne 		timeout = msecs_to_jiffies(LRU_INTERVAL);
5723f3aad5eSRoger Pau Monne 
5733f3aad5eSRoger Pau Monne 		timeout = wait_event_interruptible_timeout(
57459795700SBob Liu 			ring->wq,
57559795700SBob Liu 			ring->waiting_reqs || kthread_should_stop(),
5763f3aad5eSRoger Pau Monne 			timeout);
5773f3aad5eSRoger Pau Monne 		if (timeout == 0)
5783f3aad5eSRoger Pau Monne 			goto purge_gnt_list;
5793f3aad5eSRoger Pau Monne 		timeout = wait_event_interruptible_timeout(
58059795700SBob Liu 			ring->pending_free_wq,
58159795700SBob Liu 			!list_empty(&ring->pending_free) ||
5823f3aad5eSRoger Pau Monne 			kthread_should_stop(),
5833f3aad5eSRoger Pau Monne 			timeout);
5843f3aad5eSRoger Pau Monne 		if (timeout == 0)
5853f3aad5eSRoger Pau Monne 			goto purge_gnt_list;
586dfc07b13SKonrad Rzeszutek Wilk 
58701263a1fSJuergen Gross 		do_eoi = ring->waiting_reqs;
58801263a1fSJuergen Gross 
58959795700SBob Liu 		ring->waiting_reqs = 0;
590dfc07b13SKonrad Rzeszutek Wilk 		smp_mb(); /* clear flag *before* checking for work */
591dfc07b13SKonrad Rzeszutek Wilk 
59201263a1fSJuergen Gross 		ret = do_block_io_op(ring, &eoi_flags);
5938e3f8755SKonrad Rzeszutek Wilk 		if (ret > 0)
59459795700SBob Liu 			ring->waiting_reqs = 1;
5958e3f8755SKonrad Rzeszutek Wilk 		if (ret == -EACCES)
59659795700SBob Liu 			wait_event_interruptible(ring->shutdown_wq,
5978e3f8755SKonrad Rzeszutek Wilk 						 kthread_should_stop());
598dfc07b13SKonrad Rzeszutek Wilk 
59901263a1fSJuergen Gross 		if (do_eoi && !ring->waiting_reqs) {
60001263a1fSJuergen Gross 			xen_irq_lateeoi(ring->irq, eoi_flags);
60101263a1fSJuergen Gross 			eoi_flags |= XEN_EOI_FLAG_SPURIOUS;
60201263a1fSJuergen Gross 		}
60301263a1fSJuergen Gross 
6043f3aad5eSRoger Pau Monne purge_gnt_list:
6053f3aad5eSRoger Pau Monne 		if (blkif->vbd.feature_gnt_persistent &&
606d4bf0065SBob Liu 		    time_after(jiffies, ring->next_lru)) {
607d4bf0065SBob Liu 			purge_persistent_gnt(ring);
608d4bf0065SBob Liu 			ring->next_lru = jiffies + msecs_to_jiffies(LRU_INTERVAL);
6093f3aad5eSRoger Pau Monne 		}
6103f3aad5eSRoger Pau Monne 
611cb9369bdSSeongJae Park 		/* Shrink the free pages pool if it is too large. */
612cb9369bdSSeongJae Park 		if (time_before(jiffies, blkif->buffer_squeeze_end))
613ca33479cSJuergen Gross 			gnttab_page_cache_shrink(&ring->free_pages, 0);
614cb9369bdSSeongJae Park 		else
615ca33479cSJuergen Gross 			gnttab_page_cache_shrink(&ring->free_pages,
616ca33479cSJuergen Gross 						 max_buffer_pages);
617c6cc142dSRoger Pau Monne 
618db6fbc10SBob Liu 		if (log_stats && time_after(jiffies, ring->st_print))
619d4bf0065SBob Liu 			print_stats(ring);
620dfc07b13SKonrad Rzeszutek Wilk 	}
621dfc07b13SKonrad Rzeszutek Wilk 
622ef753411SRoger Pau Monne 	/* Drain pending purge work */
623d4bf0065SBob Liu 	flush_work(&ring->persistent_purge_work);
6240a8704a5SRoger Pau Monne 
625dfc07b13SKonrad Rzeszutek Wilk 	if (log_stats)
626d4bf0065SBob Liu 		print_stats(ring);
627dfc07b13SKonrad Rzeszutek Wilk 
62859795700SBob Liu 	ring->xenblkd = NULL;
629dfc07b13SKonrad Rzeszutek Wilk 
630dfc07b13SKonrad Rzeszutek Wilk 	return 0;
631dfc07b13SKonrad Rzeszutek Wilk }
632dfc07b13SKonrad Rzeszutek Wilk 
633dfc07b13SKonrad Rzeszutek Wilk /*
634ef753411SRoger Pau Monne  * Remove persistent grants and empty the pool of free pages
635ef753411SRoger Pau Monne  */
xen_blkbk_free_caches(struct xen_blkif_ring * ring)63659795700SBob Liu void xen_blkbk_free_caches(struct xen_blkif_ring *ring)
637ef753411SRoger Pau Monne {
638dfc07b13SKonrad Rzeszutek Wilk 	/* Free all persistent grant pages */
639e7b4c07dSJuergen Gross 	free_persistent_gnts(ring);
640dfc07b13SKonrad Rzeszutek Wilk 
6412ed22e3cSMatt Rushton 	/* Since we are shutting down remove all pages from the buffer */
642ca33479cSJuergen Gross 	gnttab_page_cache_shrink(&ring->free_pages, 0 /* All */);
643dfc07b13SKonrad Rzeszutek Wilk }
644dfc07b13SKonrad Rzeszutek Wilk 
xen_blkbk_unmap_prepare(struct xen_blkif_ring * ring,struct grant_page ** pages,unsigned int num,struct gnttab_unmap_grant_ref * unmap_ops,struct page ** unmap_pages)645c43cf3eaSJennifer Herbert static unsigned int xen_blkbk_unmap_prepare(
64659795700SBob Liu 	struct xen_blkif_ring *ring,
647c43cf3eaSJennifer Herbert 	struct grant_page **pages,
648c43cf3eaSJennifer Herbert 	unsigned int num,
649c43cf3eaSJennifer Herbert 	struct gnttab_unmap_grant_ref *unmap_ops,
650c43cf3eaSJennifer Herbert 	struct page **unmap_pages)
651dfc07b13SKonrad Rzeszutek Wilk {
652dfc07b13SKonrad Rzeszutek Wilk 	unsigned int i, invcount = 0;
653dfc07b13SKonrad Rzeszutek Wilk 
65431552ee3SRoger Pau Monne 	for (i = 0; i < num; i++) {
655bb642e83SRoger Pau Monne 		if (pages[i]->persistent_gnt != NULL) {
656d4bf0065SBob Liu 			put_persistent_gnt(ring, pages[i]->persistent_gnt);
6570a8704a5SRoger Pau Monne 			continue;
6583f3aad5eSRoger Pau Monne 		}
659bb642e83SRoger Pau Monne 		if (pages[i]->handle == BLKBACK_INVALID_HANDLE)
660dfc07b13SKonrad Rzeszutek Wilk 			continue;
661bb642e83SRoger Pau Monne 		unmap_pages[invcount] = pages[i]->page;
662c43cf3eaSJennifer Herbert 		gnttab_set_unmap_op(&unmap_ops[invcount], vaddr(pages[i]->page),
663bb642e83SRoger Pau Monne 				    GNTMAP_host_map, pages[i]->handle);
664bb642e83SRoger Pau Monne 		pages[i]->handle = BLKBACK_INVALID_HANDLE;
665c43cf3eaSJennifer Herbert 		invcount++;
66631552ee3SRoger Pau Monne 	}
667c43cf3eaSJennifer Herbert 
668c43cf3eaSJennifer Herbert 	return invcount;
66931552ee3SRoger Pau Monne }
670c43cf3eaSJennifer Herbert 
xen_blkbk_unmap_and_respond_callback(int result,struct gntab_unmap_queue_data * data)671c43cf3eaSJennifer Herbert static void xen_blkbk_unmap_and_respond_callback(int result, struct gntab_unmap_queue_data *data)
672c43cf3eaSJennifer Herbert {
673c43cf3eaSJennifer Herbert 	struct pending_req *pending_req = (struct pending_req *)(data->data);
67459795700SBob Liu 	struct xen_blkif_ring *ring = pending_req->ring;
67559795700SBob Liu 	struct xen_blkif *blkif = ring->blkif;
676c43cf3eaSJennifer Herbert 
677c43cf3eaSJennifer Herbert 	/* BUG_ON used to reproduce existing behaviour,
678c43cf3eaSJennifer Herbert 	   but is this the best way to deal with this? */
679c43cf3eaSJennifer Herbert 	BUG_ON(result);
680c43cf3eaSJennifer Herbert 
681ca33479cSJuergen Gross 	gnttab_page_cache_put(&ring->free_pages, data->pages, data->count);
68259795700SBob Liu 	make_response(ring, pending_req->id,
683c43cf3eaSJennifer Herbert 		      pending_req->operation, pending_req->status);
68459795700SBob Liu 	free_req(ring, pending_req);
685c43cf3eaSJennifer Herbert 	/*
686c43cf3eaSJennifer Herbert 	 * Make sure the request is freed before releasing blkif,
687c43cf3eaSJennifer Herbert 	 * or there could be a race between free_req and the
688c43cf3eaSJennifer Herbert 	 * cleanup done in xen_blkif_free during shutdown.
689c43cf3eaSJennifer Herbert 	 *
690c43cf3eaSJennifer Herbert 	 * NB: The fact that we might try to wake up pending_free_wq
691c43cf3eaSJennifer Herbert 	 * before drain_complete (in case there's a drain going on)
692c43cf3eaSJennifer Herbert 	 * it's not a problem with our current implementation
693c43cf3eaSJennifer Herbert 	 * because we can assure there's no thread waiting on
694c43cf3eaSJennifer Herbert 	 * pending_free_wq if there's a drain going on, but it has
695c43cf3eaSJennifer Herbert 	 * to be taken into account if the current model is changed.
696c43cf3eaSJennifer Herbert 	 */
69759795700SBob Liu 	if (atomic_dec_and_test(&ring->inflight) && atomic_read(&blkif->drain)) {
698c43cf3eaSJennifer Herbert 		complete(&blkif->drain_complete);
699c43cf3eaSJennifer Herbert 	}
700c43cf3eaSJennifer Herbert 	xen_blkif_put(blkif);
701c43cf3eaSJennifer Herbert }
702c43cf3eaSJennifer Herbert 
xen_blkbk_unmap_and_respond(struct pending_req * req)703c43cf3eaSJennifer Herbert static void xen_blkbk_unmap_and_respond(struct pending_req *req)
704c43cf3eaSJennifer Herbert {
705c43cf3eaSJennifer Herbert 	struct gntab_unmap_queue_data* work = &req->gnttab_unmap_data;
70659795700SBob Liu 	struct xen_blkif_ring *ring = req->ring;
707c43cf3eaSJennifer Herbert 	struct grant_page **pages = req->segments;
708c43cf3eaSJennifer Herbert 	unsigned int invcount;
709c43cf3eaSJennifer Herbert 
71059795700SBob Liu 	invcount = xen_blkbk_unmap_prepare(ring, pages, req->nr_segs,
711c43cf3eaSJennifer Herbert 					   req->unmap, req->unmap_pages);
712c43cf3eaSJennifer Herbert 
713c43cf3eaSJennifer Herbert 	work->data = req;
714c43cf3eaSJennifer Herbert 	work->done = xen_blkbk_unmap_and_respond_callback;
715c43cf3eaSJennifer Herbert 	work->unmap_ops = req->unmap;
716c43cf3eaSJennifer Herbert 	work->kunmap_ops = NULL;
717c43cf3eaSJennifer Herbert 	work->pages = req->unmap_pages;
718c43cf3eaSJennifer Herbert 	work->count = invcount;
719c43cf3eaSJennifer Herbert 
720c43cf3eaSJennifer Herbert 	gnttab_unmap_refs_async(&req->gnttab_unmap_data);
721c43cf3eaSJennifer Herbert }
722c43cf3eaSJennifer Herbert 
723c43cf3eaSJennifer Herbert 
724c43cf3eaSJennifer Herbert /*
725c43cf3eaSJennifer Herbert  * Unmap the grant references.
726c43cf3eaSJennifer Herbert  *
727c43cf3eaSJennifer Herbert  * This could accumulate ops up to the batch size to reduce the number
728c43cf3eaSJennifer Herbert  * of hypercalls, but since this is only used in error paths there's
729c43cf3eaSJennifer Herbert  * no real need.
730c43cf3eaSJennifer Herbert  */
xen_blkbk_unmap(struct xen_blkif_ring * ring,struct grant_page * pages[],int num)73159795700SBob Liu static void xen_blkbk_unmap(struct xen_blkif_ring *ring,
732c43cf3eaSJennifer Herbert                             struct grant_page *pages[],
733c43cf3eaSJennifer Herbert                             int num)
734c43cf3eaSJennifer Herbert {
735c43cf3eaSJennifer Herbert 	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
736c43cf3eaSJennifer Herbert 	struct page *unmap_pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
737c43cf3eaSJennifer Herbert 	unsigned int invcount = 0;
738c43cf3eaSJennifer Herbert 	int ret;
739c43cf3eaSJennifer Herbert 
740c43cf3eaSJennifer Herbert 	while (num) {
741c43cf3eaSJennifer Herbert 		unsigned int batch = min(num, BLKIF_MAX_SEGMENTS_PER_REQUEST);
742c43cf3eaSJennifer Herbert 
74359795700SBob Liu 		invcount = xen_blkbk_unmap_prepare(ring, pages, batch,
744c43cf3eaSJennifer Herbert 						   unmap, unmap_pages);
74531552ee3SRoger Pau Monne 		if (invcount) {
74631552ee3SRoger Pau Monne 			ret = gnttab_unmap_refs(unmap, NULL, unmap_pages, invcount);
74731552ee3SRoger Pau Monne 			BUG_ON(ret);
748ca33479cSJuergen Gross 			gnttab_page_cache_put(&ring->free_pages, unmap_pages,
749ca33479cSJuergen Gross 					      invcount);
75031552ee3SRoger Pau Monne 		}
751c43cf3eaSJennifer Herbert 		pages += batch;
752c43cf3eaSJennifer Herbert 		num -= batch;
753c43cf3eaSJennifer Herbert 	}
754dfc07b13SKonrad Rzeszutek Wilk }
75501f37f2dSKonrad Rzeszutek Wilk 
xen_blkbk_map(struct xen_blkif_ring * ring,struct grant_page * pages[],int num,bool ro)75659795700SBob Liu static int xen_blkbk_map(struct xen_blkif_ring *ring,
757bb642e83SRoger Pau Monne 			 struct grant_page *pages[],
75831552ee3SRoger Pau Monne 			 int num, bool ro)
759dfc07b13SKonrad Rzeszutek Wilk {
760dfc07b13SKonrad Rzeszutek Wilk 	struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
7610a8704a5SRoger Pau Monne 	struct page *pages_to_gnt[BLKIF_MAX_SEGMENTS_PER_REQUEST];
7620a8704a5SRoger Pau Monne 	struct persistent_gnt *persistent_gnt = NULL;
7630a8704a5SRoger Pau Monne 	phys_addr_t addr = 0;
764c6cc142dSRoger Pau Monne 	int i, seg_idx, new_map_idx;
7650a8704a5SRoger Pau Monne 	int segs_to_map = 0;
766dfc07b13SKonrad Rzeszutek Wilk 	int ret = 0;
76731552ee3SRoger Pau Monne 	int last_map = 0, map_until = 0;
7680a8704a5SRoger Pau Monne 	int use_persistent_gnts;
76959795700SBob Liu 	struct xen_blkif *blkif = ring->blkif;
7700a8704a5SRoger Pau Monne 
7710a8704a5SRoger Pau Monne 	use_persistent_gnts = (blkif->vbd.feature_gnt_persistent);
7720a8704a5SRoger Pau Monne 
77301f37f2dSKonrad Rzeszutek Wilk 	/*
77401f37f2dSKonrad Rzeszutek Wilk 	 * Fill out preq.nr_sects with proper amount of sectors, and setup
775dfc07b13SKonrad Rzeszutek Wilk 	 * assign map[..] with the PFN of the page in our domain with the
776dfc07b13SKonrad Rzeszutek Wilk 	 * corresponding grant reference for each page.
777dfc07b13SKonrad Rzeszutek Wilk 	 */
77831552ee3SRoger Pau Monne again:
77931552ee3SRoger Pau Monne 	for (i = map_until; i < num; i++) {
780dfc07b13SKonrad Rzeszutek Wilk 		uint32_t flags;
781dfc07b13SKonrad Rzeszutek Wilk 
78259795700SBob Liu 		if (use_persistent_gnts) {
7830a8704a5SRoger Pau Monne 			persistent_gnt = get_persistent_gnt(
784d4bf0065SBob Liu 				ring,
785bb642e83SRoger Pau Monne 				pages[i]->gref);
78659795700SBob Liu 		}
7870a8704a5SRoger Pau Monne 
7880a8704a5SRoger Pau Monne 		if (persistent_gnt) {
7890a8704a5SRoger Pau Monne 			/*
7900a8704a5SRoger Pau Monne 			 * We are using persistent grants and
7910a8704a5SRoger Pau Monne 			 * the grant is already mapped
7920a8704a5SRoger Pau Monne 			 */
793bb642e83SRoger Pau Monne 			pages[i]->page = persistent_gnt->page;
794bb642e83SRoger Pau Monne 			pages[i]->persistent_gnt = persistent_gnt;
7950a8704a5SRoger Pau Monne 		} else {
796ca33479cSJuergen Gross 			if (gnttab_page_cache_get(&ring->free_pages,
797871997bcSJan Beulich 						  &pages[i]->page)) {
798871997bcSJan Beulich 				gnttab_page_cache_put(&ring->free_pages,
799871997bcSJan Beulich 						      pages_to_gnt,
800871997bcSJan Beulich 						      segs_to_map);
801871997bcSJan Beulich 				ret = -ENOMEM;
802871997bcSJan Beulich 				goto out;
803871997bcSJan Beulich 			}
804bb642e83SRoger Pau Monne 			addr = vaddr(pages[i]->page);
805bb642e83SRoger Pau Monne 			pages_to_gnt[segs_to_map] = pages[i]->page;
806bb642e83SRoger Pau Monne 			pages[i]->persistent_gnt = NULL;
8070a8704a5SRoger Pau Monne 			flags = GNTMAP_host_map;
80831552ee3SRoger Pau Monne 			if (!use_persistent_gnts && ro)
8090a8704a5SRoger Pau Monne 				flags |= GNTMAP_readonly;
8100a8704a5SRoger Pau Monne 			gnttab_set_map_op(&map[segs_to_map++], addr,
811bb642e83SRoger Pau Monne 					  flags, pages[i]->gref,
8120a8704a5SRoger Pau Monne 					  blkif->domid);
8130a8704a5SRoger Pau Monne 		}
81431552ee3SRoger Pau Monne 		map_until = i + 1;
81531552ee3SRoger Pau Monne 		if (segs_to_map == BLKIF_MAX_SEGMENTS_PER_REQUEST)
81631552ee3SRoger Pau Monne 			break;
8170a8704a5SRoger Pau Monne 	}
8180a8704a5SRoger Pau Monne 
8195a264285SJan Beulich 	if (segs_to_map)
8200a8704a5SRoger Pau Monne 		ret = gnttab_map_refs(map, NULL, pages_to_gnt, segs_to_map);
821dfc07b13SKonrad Rzeszutek Wilk 
82201f37f2dSKonrad Rzeszutek Wilk 	/*
82301f37f2dSKonrad Rzeszutek Wilk 	 * Now swizzle the MFN in our domain with the MFN from the other domain
824dfc07b13SKonrad Rzeszutek Wilk 	 * so that when we access vaddr(pending_req,i) it has the contents of
825dfc07b13SKonrad Rzeszutek Wilk 	 * the page from the other domain.
826dfc07b13SKonrad Rzeszutek Wilk 	 */
82731552ee3SRoger Pau Monne 	for (seg_idx = last_map, new_map_idx = 0; seg_idx < map_until; seg_idx++) {
828bb642e83SRoger Pau Monne 		if (!pages[seg_idx]->persistent_gnt) {
8290a8704a5SRoger Pau Monne 			/* This is a newly mapped grant */
830c6cc142dSRoger Pau Monne 			BUG_ON(new_map_idx >= segs_to_map);
831c6cc142dSRoger Pau Monne 			if (unlikely(map[new_map_idx].status != 0)) {
83277387b82STao Chen 				pr_debug("invalid buffer -- could not remap it\n");
833ca33479cSJuergen Gross 				gnttab_page_cache_put(&ring->free_pages,
834ca33479cSJuergen Gross 						      &pages[seg_idx]->page, 1);
835bb642e83SRoger Pau Monne 				pages[seg_idx]->handle = BLKBACK_INVALID_HANDLE;
8365a264285SJan Beulich 				ret |= !ret;
837c6cc142dSRoger Pau Monne 				goto next;
8380a8704a5SRoger Pau Monne 			}
839bb642e83SRoger Pau Monne 			pages[seg_idx]->handle = map[new_map_idx].handle;
84031552ee3SRoger Pau Monne 		} else {
84131552ee3SRoger Pau Monne 			continue;
84231552ee3SRoger Pau Monne 		}
843c6cc142dSRoger Pau Monne 		if (use_persistent_gnts &&
844823f2091SSeongJae Park 		    ring->persistent_gnt_c < max_pgrants) {
845c6cc142dSRoger Pau Monne 			/*
846c6cc142dSRoger Pau Monne 			 * We are using persistent grants, the grant is
8473f3aad5eSRoger Pau Monne 			 * not mapped but we might have room for it.
848c6cc142dSRoger Pau Monne 			 */
849c6cc142dSRoger Pau Monne 			persistent_gnt = kmalloc(sizeof(struct persistent_gnt),
850c6cc142dSRoger Pau Monne 				                 GFP_KERNEL);
851c6cc142dSRoger Pau Monne 			if (!persistent_gnt) {
852c6cc142dSRoger Pau Monne 				/*
853c6cc142dSRoger Pau Monne 				 * If we don't have enough memory to
854c6cc142dSRoger Pau Monne 				 * allocate the persistent_gnt struct
855c6cc142dSRoger Pau Monne 				 * map this grant non-persistenly
856c6cc142dSRoger Pau Monne 				 */
85731552ee3SRoger Pau Monne 				goto next;
858c6cc142dSRoger Pau Monne 			}
859c6cc142dSRoger Pau Monne 			persistent_gnt->gnt = map[new_map_idx].ref;
860c6cc142dSRoger Pau Monne 			persistent_gnt->handle = map[new_map_idx].handle;
861bb642e83SRoger Pau Monne 			persistent_gnt->page = pages[seg_idx]->page;
862d4bf0065SBob Liu 			if (add_persistent_gnt(ring,
863c6cc142dSRoger Pau Monne 			                       persistent_gnt)) {
864c6cc142dSRoger Pau Monne 				kfree(persistent_gnt);
865c6cc142dSRoger Pau Monne 				persistent_gnt = NULL;
86631552ee3SRoger Pau Monne 				goto next;
867c6cc142dSRoger Pau Monne 			}
868bb642e83SRoger Pau Monne 			pages[seg_idx]->persistent_gnt = persistent_gnt;
86977387b82STao Chen 			pr_debug("grant %u added to the tree of persistent grants, using %u/%u\n",
870d4bf0065SBob Liu 				 persistent_gnt->gnt, ring->persistent_gnt_c,
871823f2091SSeongJae Park 				 max_pgrants);
872c6cc142dSRoger Pau Monne 			goto next;
873c6cc142dSRoger Pau Monne 		}
874c6cc142dSRoger Pau Monne 		if (use_persistent_gnts && !blkif->vbd.overflow_max_grants) {
875c6cc142dSRoger Pau Monne 			blkif->vbd.overflow_max_grants = 1;
87677387b82STao Chen 			pr_debug("domain %u, device %#x is using maximum number of persistent grants\n",
877c6cc142dSRoger Pau Monne 			         blkif->domid, blkif->vbd.handle);
878c6cc142dSRoger Pau Monne 		}
879c6cc142dSRoger Pau Monne 		/*
880c6cc142dSRoger Pau Monne 		 * We could not map this grant persistently, so use it as
881c6cc142dSRoger Pau Monne 		 * a non-persistent grant.
882c6cc142dSRoger Pau Monne 		 */
883c6cc142dSRoger Pau Monne next:
88431552ee3SRoger Pau Monne 		new_map_idx++;
885dfc07b13SKonrad Rzeszutek Wilk 	}
88631552ee3SRoger Pau Monne 	segs_to_map = 0;
88731552ee3SRoger Pau Monne 	last_map = map_until;
888871997bcSJan Beulich 	if (!ret && map_until != num)
88931552ee3SRoger Pau Monne 		goto again;
89031552ee3SRoger Pau Monne 
891871997bcSJan Beulich out:
892871997bcSJan Beulich 	for (i = last_map; i < num; i++) {
893871997bcSJan Beulich 		/* Don't zap current batch's valid persistent grants. */
894a846738fSJan Beulich 		if (i >= map_until)
895871997bcSJan Beulich 			pages[i]->persistent_gnt = NULL;
896f9bd84a8SSeongJae Park 		pages[i]->handle = BLKBACK_INVALID_HANDLE;
897871997bcSJan Beulich 	}
898871997bcSJan Beulich 
899871997bcSJan Beulich 	return ret;
900dfc07b13SKonrad Rzeszutek Wilk }
901dfc07b13SKonrad Rzeszutek Wilk 
xen_blkbk_map_seg(struct pending_req * pending_req)902bb642e83SRoger Pau Monne static int xen_blkbk_map_seg(struct pending_req *pending_req)
90331552ee3SRoger Pau Monne {
904402b27f9SRoger Pau Monne 	int rc;
90531552ee3SRoger Pau Monne 
90659795700SBob Liu 	rc = xen_blkbk_map(pending_req->ring, pending_req->segments,
9076684fa1cSJulien Grall 			   pending_req->nr_segs,
90831552ee3SRoger Pau Monne 	                   (pending_req->operation != BLKIF_OP_READ));
909402b27f9SRoger Pau Monne 
91031552ee3SRoger Pau Monne 	return rc;
911402b27f9SRoger Pau Monne }
91231552ee3SRoger Pau Monne 
xen_blkbk_parse_indirect(struct blkif_request * req,struct pending_req * pending_req,struct seg_buf seg[],struct phys_req * preq)913402b27f9SRoger Pau Monne static int xen_blkbk_parse_indirect(struct blkif_request *req,
914402b27f9SRoger Pau Monne 				    struct pending_req *pending_req,
915402b27f9SRoger Pau Monne 				    struct seg_buf seg[],
916402b27f9SRoger Pau Monne 				    struct phys_req *preq)
917402b27f9SRoger Pau Monne {
918bb642e83SRoger Pau Monne 	struct grant_page **pages = pending_req->indirect_pages;
91959795700SBob Liu 	struct xen_blkif_ring *ring = pending_req->ring;
920402b27f9SRoger Pau Monne 	int indirect_grefs, rc, n, nseg, i;
92180bfa2f6SRoger Pau Monne 	struct blkif_request_segment *segments = NULL;
92231552ee3SRoger Pau Monne 
9236684fa1cSJulien Grall 	nseg = pending_req->nr_segs;
924402b27f9SRoger Pau Monne 	indirect_grefs = INDIRECT_PAGES(nseg);
925402b27f9SRoger Pau Monne 	BUG_ON(indirect_grefs > BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST);
926402b27f9SRoger Pau Monne 
927bb642e83SRoger Pau Monne 	for (i = 0; i < indirect_grefs; i++)
928bb642e83SRoger Pau Monne 		pages[i]->gref = req->u.indirect.indirect_grefs[i];
929bb642e83SRoger Pau Monne 
93059795700SBob Liu 	rc = xen_blkbk_map(ring, pages, indirect_grefs, true);
931402b27f9SRoger Pau Monne 	if (rc)
932402b27f9SRoger Pau Monne 		goto unmap;
933402b27f9SRoger Pau Monne 
93493b4e747SColin Ian King 	for (n = 0; n < nseg; n++) {
93518779149SRoger Pau Monné 		uint8_t first_sect, last_sect;
93618779149SRoger Pau Monné 
937402b27f9SRoger Pau Monne 		if ((n % SEGS_PER_INDIRECT_FRAME) == 0) {
938402b27f9SRoger Pau Monne 			/* Map indirect segments */
939402b27f9SRoger Pau Monne 			if (segments)
940402b27f9SRoger Pau Monne 				kunmap_atomic(segments);
941bb642e83SRoger Pau Monne 			segments = kmap_atomic(pages[n/SEGS_PER_INDIRECT_FRAME]->page);
942402b27f9SRoger Pau Monne 		}
943402b27f9SRoger Pau Monne 		i = n % SEGS_PER_INDIRECT_FRAME;
94418779149SRoger Pau Monné 
945bb642e83SRoger Pau Monne 		pending_req->segments[n]->gref = segments[i].gref;
94618779149SRoger Pau Monné 
94718779149SRoger Pau Monné 		first_sect = READ_ONCE(segments[i].first_sect);
94818779149SRoger Pau Monné 		last_sect = READ_ONCE(segments[i].last_sect);
94918779149SRoger Pau Monné 		if (last_sect >= (XEN_PAGE_SIZE >> 9) || last_sect < first_sect) {
950402b27f9SRoger Pau Monne 			rc = -EINVAL;
951402b27f9SRoger Pau Monne 			goto unmap;
952402b27f9SRoger Pau Monne 		}
95318779149SRoger Pau Monné 
95418779149SRoger Pau Monné 		seg[n].nsec = last_sect - first_sect + 1;
95518779149SRoger Pau Monné 		seg[n].offset = first_sect << 9;
956402b27f9SRoger Pau Monne 		preq->nr_sects += seg[n].nsec;
957402b27f9SRoger Pau Monne 	}
958402b27f9SRoger Pau Monne 
959402b27f9SRoger Pau Monne unmap:
960402b27f9SRoger Pau Monne 	if (segments)
961402b27f9SRoger Pau Monne 		kunmap_atomic(segments);
96259795700SBob Liu 	xen_blkbk_unmap(ring, pages, indirect_grefs);
963402b27f9SRoger Pau Monne 	return rc;
96431552ee3SRoger Pau Monne }
96531552ee3SRoger Pau Monne 
dispatch_discard_io(struct xen_blkif_ring * ring,struct blkif_request * req)96659795700SBob Liu static int dispatch_discard_io(struct xen_blkif_ring *ring,
96742146352SKonrad Rzeszutek Wilk 				struct blkif_request *req)
968b3cb0d6aSLi Dongyang {
969b3cb0d6aSLi Dongyang 	int err = 0;
970b3cb0d6aSLi Dongyang 	int status = BLKIF_RSP_OKAY;
97159795700SBob Liu 	struct xen_blkif *blkif = ring->blkif;
972b3cb0d6aSLi Dongyang 	struct block_device *bdev = blkif->vbd.bdev;
973604c499cSKonrad Rzeszutek Wilk 	struct phys_req preq;
974b3cb0d6aSLi Dongyang 
975ea5ec76dSVegard Nossum 	xen_blkif_get(blkif);
976ea5ec76dSVegard Nossum 
977604c499cSKonrad Rzeszutek Wilk 	preq.sector_number = req->u.discard.sector_number;
978604c499cSKonrad Rzeszutek Wilk 	preq.nr_sects      = req->u.discard.nr_sectors;
979604c499cSKonrad Rzeszutek Wilk 
980a022606eSMike Christie 	err = xen_vbd_translate(&preq, blkif, REQ_OP_WRITE);
981604c499cSKonrad Rzeszutek Wilk 	if (err) {
98277387b82STao Chen 		pr_warn("access denied: DISCARD [%llu->%llu] on dev=%04x\n",
983604c499cSKonrad Rzeszutek Wilk 			preq.sector_number,
984604c499cSKonrad Rzeszutek Wilk 			preq.sector_number + preq.nr_sects, blkif->vbd.pdevice);
985604c499cSKonrad Rzeszutek Wilk 		goto fail_response;
986604c499cSKonrad Rzeszutek Wilk 	}
987db6fbc10SBob Liu 	ring->st_ds_req++;
98842146352SKonrad Rzeszutek Wilk 
98944abff2cSChristoph Hellwig 	if (blkif->vbd.discard_secure &&
99044abff2cSChristoph Hellwig 	    (req->u.discard.flag & BLKIF_DISCARD_SECURE))
99144abff2cSChristoph Hellwig 		err = blkdev_issue_secure_erase(bdev,
99244abff2cSChristoph Hellwig 				req->u.discard.sector_number,
99344abff2cSChristoph Hellwig 				req->u.discard.nr_sectors, GFP_KERNEL);
99444abff2cSChristoph Hellwig 	else
9954dae7670SKonrad Rzeszutek Wilk 		err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
99644abff2cSChristoph Hellwig 				req->u.discard.nr_sectors, GFP_KERNEL);
99744abff2cSChristoph Hellwig 
998604c499cSKonrad Rzeszutek Wilk fail_response:
999b3cb0d6aSLi Dongyang 	if (err == -EOPNOTSUPP) {
100077387b82STao Chen 		pr_debug("discard op failed, not supported\n");
1001b3cb0d6aSLi Dongyang 		status = BLKIF_RSP_EOPNOTSUPP;
1002b3cb0d6aSLi Dongyang 	} else if (err)
1003b3cb0d6aSLi Dongyang 		status = BLKIF_RSP_ERROR;
1004b3cb0d6aSLi Dongyang 
100559795700SBob Liu 	make_response(ring, req->u.discard.id, req->operation, status);
100642146352SKonrad Rzeszutek Wilk 	xen_blkif_put(blkif);
100742146352SKonrad Rzeszutek Wilk 	return err;
1008b3cb0d6aSLi Dongyang }
1009b3cb0d6aSLi Dongyang 
dispatch_other_io(struct xen_blkif_ring * ring,struct blkif_request * req,struct pending_req * pending_req)101059795700SBob Liu static int dispatch_other_io(struct xen_blkif_ring *ring,
10110e367ae4SDavid Vrabel 			     struct blkif_request *req,
10120e367ae4SDavid Vrabel 			     struct pending_req *pending_req)
10130e367ae4SDavid Vrabel {
101459795700SBob Liu 	free_req(ring, pending_req);
101559795700SBob Liu 	make_response(ring, req->u.other.id, req->operation,
10160e367ae4SDavid Vrabel 		      BLKIF_RSP_EOPNOTSUPP);
10170e367ae4SDavid Vrabel 	return -EIO;
10180e367ae4SDavid Vrabel }
10190e367ae4SDavid Vrabel 
xen_blk_drain_io(struct xen_blkif_ring * ring)102059795700SBob Liu static void xen_blk_drain_io(struct xen_blkif_ring *ring)
102129bde093SKonrad Rzeszutek Wilk {
102259795700SBob Liu 	struct xen_blkif *blkif = ring->blkif;
102359795700SBob Liu 
102429bde093SKonrad Rzeszutek Wilk 	atomic_set(&blkif->drain, 1);
102529bde093SKonrad Rzeszutek Wilk 	do {
102659795700SBob Liu 		if (atomic_read(&ring->inflight) == 0)
10276927d920SKonrad Rzeszutek Wilk 			break;
102829bde093SKonrad Rzeszutek Wilk 		wait_for_completion_interruptible_timeout(
102929bde093SKonrad Rzeszutek Wilk 				&blkif->drain_complete, HZ);
103029bde093SKonrad Rzeszutek Wilk 
103129bde093SKonrad Rzeszutek Wilk 		if (!atomic_read(&blkif->drain))
103229bde093SKonrad Rzeszutek Wilk 			break;
103329bde093SKonrad Rzeszutek Wilk 	} while (!kthread_should_stop());
103429bde093SKonrad Rzeszutek Wilk 	atomic_set(&blkif->drain, 0);
103529bde093SKonrad Rzeszutek Wilk }
103629bde093SKonrad Rzeszutek Wilk 
__end_block_io_op(struct pending_req * pending_req,blk_status_t error)10374e4cbee9SChristoph Hellwig static void __end_block_io_op(struct pending_req *pending_req,
10384e4cbee9SChristoph Hellwig 		blk_status_t error)
1039dfc07b13SKonrad Rzeszutek Wilk {
1040dfc07b13SKonrad Rzeszutek Wilk 	/* An error fails the entire request. */
10414e4cbee9SChristoph Hellwig 	if (pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE &&
10424e4cbee9SChristoph Hellwig 	    error == BLK_STS_NOTSUPP) {
104377387b82STao Chen 		pr_debug("flush diskcache op failed, not supported\n");
104459795700SBob Liu 		xen_blkbk_flush_diskcache(XBT_NIL, pending_req->ring->blkif->be, 0);
1045dfc07b13SKonrad Rzeszutek Wilk 		pending_req->status = BLKIF_RSP_EOPNOTSUPP;
10464e4cbee9SChristoph Hellwig 	} else if (pending_req->operation == BLKIF_OP_WRITE_BARRIER &&
10474e4cbee9SChristoph Hellwig 		   error == BLK_STS_NOTSUPP) {
104877387b82STao Chen 		pr_debug("write barrier op failed, not supported\n");
104959795700SBob Liu 		xen_blkbk_barrier(XBT_NIL, pending_req->ring->blkif->be, 0);
105029bde093SKonrad Rzeszutek Wilk 		pending_req->status = BLKIF_RSP_EOPNOTSUPP;
1051dfc07b13SKonrad Rzeszutek Wilk 	} else if (error) {
105277387b82STao Chen 		pr_debug("Buffer not up-to-date at end of operation,"
1053dfc07b13SKonrad Rzeszutek Wilk 			 " error=%d\n", error);
1054dfc07b13SKonrad Rzeszutek Wilk 		pending_req->status = BLKIF_RSP_ERROR;
1055dfc07b13SKonrad Rzeszutek Wilk 	}
1056dfc07b13SKonrad Rzeszutek Wilk 
105701f37f2dSKonrad Rzeszutek Wilk 	/*
105801f37f2dSKonrad Rzeszutek Wilk 	 * If all of the bio's have completed it is time to unmap
1059dfc07b13SKonrad Rzeszutek Wilk 	 * the grant references associated with 'request' and provide
1060dfc07b13SKonrad Rzeszutek Wilk 	 * the proper response on the ring.
1061dfc07b13SKonrad Rzeszutek Wilk 	 */
1062c43cf3eaSJennifer Herbert 	if (atomic_dec_and_test(&pending_req->pendcnt))
1063c43cf3eaSJennifer Herbert 		xen_blkbk_unmap_and_respond(pending_req);
1064dfc07b13SKonrad Rzeszutek Wilk }
1065dfc07b13SKonrad Rzeszutek Wilk 
1066dfc07b13SKonrad Rzeszutek Wilk /*
1067dfc07b13SKonrad Rzeszutek Wilk  * bio callback.
1068dfc07b13SKonrad Rzeszutek Wilk  */
end_block_io_op(struct bio * bio)10694246a0b6SChristoph Hellwig static void end_block_io_op(struct bio *bio)
1070dfc07b13SKonrad Rzeszutek Wilk {
10714e4cbee9SChristoph Hellwig 	__end_block_io_op(bio->bi_private, bio->bi_status);
1072dfc07b13SKonrad Rzeszutek Wilk 	bio_put(bio);
1073dfc07b13SKonrad Rzeszutek Wilk }
1074dfc07b13SKonrad Rzeszutek Wilk 
blkif_get_x86_32_req(struct blkif_request * dst,const struct blkif_x86_32_request * src)1075*cbfac770SJuergen Gross static void blkif_get_x86_32_req(struct blkif_request *dst,
1076*cbfac770SJuergen Gross 				 const struct blkif_x86_32_request *src)
1077*cbfac770SJuergen Gross {
1078*cbfac770SJuergen Gross 	unsigned int i, n;
1079dfc07b13SKonrad Rzeszutek Wilk 
1080*cbfac770SJuergen Gross 	dst->operation = READ_ONCE(src->operation);
1081*cbfac770SJuergen Gross 
1082*cbfac770SJuergen Gross 	switch (dst->operation) {
1083*cbfac770SJuergen Gross 	case BLKIF_OP_READ:
1084*cbfac770SJuergen Gross 	case BLKIF_OP_WRITE:
1085*cbfac770SJuergen Gross 	case BLKIF_OP_WRITE_BARRIER:
1086*cbfac770SJuergen Gross 	case BLKIF_OP_FLUSH_DISKCACHE:
1087*cbfac770SJuergen Gross 		dst->u.rw.nr_segments = READ_ONCE(src->u.rw.nr_segments);
1088*cbfac770SJuergen Gross 		dst->u.rw.handle = src->u.rw.handle;
1089*cbfac770SJuergen Gross 		dst->u.rw.id = src->u.rw.id;
1090*cbfac770SJuergen Gross 		dst->u.rw.sector_number = src->u.rw.sector_number;
1091*cbfac770SJuergen Gross 		n = min_t(unsigned int, BLKIF_MAX_SEGMENTS_PER_REQUEST,
1092*cbfac770SJuergen Gross 			  dst->u.rw.nr_segments);
1093*cbfac770SJuergen Gross 		for (i = 0; i < n; i++)
1094*cbfac770SJuergen Gross 			dst->u.rw.seg[i] = src->u.rw.seg[i];
1095*cbfac770SJuergen Gross 		break;
1096*cbfac770SJuergen Gross 
1097*cbfac770SJuergen Gross 	case BLKIF_OP_DISCARD:
1098*cbfac770SJuergen Gross 		dst->u.discard.flag = src->u.discard.flag;
1099*cbfac770SJuergen Gross 		dst->u.discard.id = src->u.discard.id;
1100*cbfac770SJuergen Gross 		dst->u.discard.sector_number = src->u.discard.sector_number;
1101*cbfac770SJuergen Gross 		dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
1102*cbfac770SJuergen Gross 		break;
1103*cbfac770SJuergen Gross 
1104*cbfac770SJuergen Gross 	case BLKIF_OP_INDIRECT:
1105*cbfac770SJuergen Gross 		dst->u.indirect.indirect_op = src->u.indirect.indirect_op;
1106*cbfac770SJuergen Gross 		dst->u.indirect.nr_segments =
1107*cbfac770SJuergen Gross 			READ_ONCE(src->u.indirect.nr_segments);
1108*cbfac770SJuergen Gross 		dst->u.indirect.handle = src->u.indirect.handle;
1109*cbfac770SJuergen Gross 		dst->u.indirect.id = src->u.indirect.id;
1110*cbfac770SJuergen Gross 		dst->u.indirect.sector_number = src->u.indirect.sector_number;
1111*cbfac770SJuergen Gross 		n = min(MAX_INDIRECT_PAGES,
1112*cbfac770SJuergen Gross 			INDIRECT_PAGES(dst->u.indirect.nr_segments));
1113*cbfac770SJuergen Gross 		for (i = 0; i < n; i++)
1114*cbfac770SJuergen Gross 			dst->u.indirect.indirect_grefs[i] =
1115*cbfac770SJuergen Gross 				src->u.indirect.indirect_grefs[i];
1116*cbfac770SJuergen Gross 		break;
1117*cbfac770SJuergen Gross 
1118*cbfac770SJuergen Gross 	default:
1119*cbfac770SJuergen Gross 		/*
1120*cbfac770SJuergen Gross 		 * Don't know how to translate this op. Only get the
1121*cbfac770SJuergen Gross 		 * ID so failure can be reported to the frontend.
1122*cbfac770SJuergen Gross 		 */
1123*cbfac770SJuergen Gross 		dst->u.other.id = src->u.other.id;
1124*cbfac770SJuergen Gross 		break;
1125*cbfac770SJuergen Gross 	}
1126*cbfac770SJuergen Gross }
1127*cbfac770SJuergen Gross 
blkif_get_x86_64_req(struct blkif_request * dst,const struct blkif_x86_64_request * src)1128*cbfac770SJuergen Gross static void blkif_get_x86_64_req(struct blkif_request *dst,
1129*cbfac770SJuergen Gross 				 const struct blkif_x86_64_request *src)
1130*cbfac770SJuergen Gross {
1131*cbfac770SJuergen Gross 	unsigned int i, n;
1132*cbfac770SJuergen Gross 
1133*cbfac770SJuergen Gross 	dst->operation = READ_ONCE(src->operation);
1134*cbfac770SJuergen Gross 
1135*cbfac770SJuergen Gross 	switch (dst->operation) {
1136*cbfac770SJuergen Gross 	case BLKIF_OP_READ:
1137*cbfac770SJuergen Gross 	case BLKIF_OP_WRITE:
1138*cbfac770SJuergen Gross 	case BLKIF_OP_WRITE_BARRIER:
1139*cbfac770SJuergen Gross 	case BLKIF_OP_FLUSH_DISKCACHE:
1140*cbfac770SJuergen Gross 		dst->u.rw.nr_segments = READ_ONCE(src->u.rw.nr_segments);
1141*cbfac770SJuergen Gross 		dst->u.rw.handle = src->u.rw.handle;
1142*cbfac770SJuergen Gross 		dst->u.rw.id = src->u.rw.id;
1143*cbfac770SJuergen Gross 		dst->u.rw.sector_number = src->u.rw.sector_number;
1144*cbfac770SJuergen Gross 		n = min_t(unsigned int, BLKIF_MAX_SEGMENTS_PER_REQUEST,
1145*cbfac770SJuergen Gross 			  dst->u.rw.nr_segments);
1146*cbfac770SJuergen Gross 		for (i = 0; i < n; i++)
1147*cbfac770SJuergen Gross 			dst->u.rw.seg[i] = src->u.rw.seg[i];
1148*cbfac770SJuergen Gross 		break;
1149*cbfac770SJuergen Gross 
1150*cbfac770SJuergen Gross 	case BLKIF_OP_DISCARD:
1151*cbfac770SJuergen Gross 		dst->u.discard.flag = src->u.discard.flag;
1152*cbfac770SJuergen Gross 		dst->u.discard.id = src->u.discard.id;
1153*cbfac770SJuergen Gross 		dst->u.discard.sector_number = src->u.discard.sector_number;
1154*cbfac770SJuergen Gross 		dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
1155*cbfac770SJuergen Gross 		break;
1156*cbfac770SJuergen Gross 
1157*cbfac770SJuergen Gross 	case BLKIF_OP_INDIRECT:
1158*cbfac770SJuergen Gross 		dst->u.indirect.indirect_op = src->u.indirect.indirect_op;
1159*cbfac770SJuergen Gross 		dst->u.indirect.nr_segments =
1160*cbfac770SJuergen Gross 			READ_ONCE(src->u.indirect.nr_segments);
1161*cbfac770SJuergen Gross 		dst->u.indirect.handle = src->u.indirect.handle;
1162*cbfac770SJuergen Gross 		dst->u.indirect.id = src->u.indirect.id;
1163*cbfac770SJuergen Gross 		dst->u.indirect.sector_number = src->u.indirect.sector_number;
1164*cbfac770SJuergen Gross 		n = min(MAX_INDIRECT_PAGES,
1165*cbfac770SJuergen Gross 			INDIRECT_PAGES(dst->u.indirect.nr_segments));
1166*cbfac770SJuergen Gross 		for (i = 0; i < n; i++)
1167*cbfac770SJuergen Gross 			dst->u.indirect.indirect_grefs[i] =
1168*cbfac770SJuergen Gross 				src->u.indirect.indirect_grefs[i];
1169*cbfac770SJuergen Gross 		break;
1170*cbfac770SJuergen Gross 
1171*cbfac770SJuergen Gross 	default:
1172*cbfac770SJuergen Gross 		/*
1173*cbfac770SJuergen Gross 		 * Don't know how to translate this op. Only get the
1174*cbfac770SJuergen Gross 		 * ID so failure can be reported to the frontend.
1175*cbfac770SJuergen Gross 		 */
1176*cbfac770SJuergen Gross 		dst->u.other.id = src->u.other.id;
1177*cbfac770SJuergen Gross 		break;
1178*cbfac770SJuergen Gross 	}
1179*cbfac770SJuergen Gross }
1180dfc07b13SKonrad Rzeszutek Wilk 
1181dfc07b13SKonrad Rzeszutek Wilk /*
1182dfc07b13SKonrad Rzeszutek Wilk  * Function to copy the from the ring buffer the 'struct blkif_request'
1183dfc07b13SKonrad Rzeszutek Wilk  * (which has the sectors we want, number of them, grant references, etc),
1184dfc07b13SKonrad Rzeszutek Wilk  * and transmute  it to the block API to hand it over to the proper block disk.
1185dfc07b13SKonrad Rzeszutek Wilk  */
1186b4726a9dSDaniel Stodden static int
__do_block_io_op(struct xen_blkif_ring * ring,unsigned int * eoi_flags)118701263a1fSJuergen Gross __do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags)
1188dfc07b13SKonrad Rzeszutek Wilk {
118959795700SBob Liu 	union blkif_back_rings *blk_rings = &ring->blk_rings;
1190dfc07b13SKonrad Rzeszutek Wilk 	struct blkif_request req;
1191dfc07b13SKonrad Rzeszutek Wilk 	struct pending_req *pending_req;
1192dfc07b13SKonrad Rzeszutek Wilk 	RING_IDX rc, rp;
1193dfc07b13SKonrad Rzeszutek Wilk 	int more_to_do = 0;
1194dfc07b13SKonrad Rzeszutek Wilk 
1195dfc07b13SKonrad Rzeszutek Wilk 	rc = blk_rings->common.req_cons;
1196dfc07b13SKonrad Rzeszutek Wilk 	rp = blk_rings->common.sring->req_prod;
1197dfc07b13SKonrad Rzeszutek Wilk 	rmb(); /* Ensure we see queued requests up to 'rp'. */
1198dfc07b13SKonrad Rzeszutek Wilk 
11998e3f8755SKonrad Rzeszutek Wilk 	if (RING_REQUEST_PROD_OVERFLOW(&blk_rings->common, rp)) {
12008e3f8755SKonrad Rzeszutek Wilk 		rc = blk_rings->common.rsp_prod_pvt;
120177387b82STao Chen 		pr_warn("Frontend provided bogus ring requests (%d - %d = %d). Halting ring processing on dev=%04x\n",
120259795700SBob Liu 			rp, rc, rp - rc, ring->blkif->vbd.pdevice);
12038e3f8755SKonrad Rzeszutek Wilk 		return -EACCES;
12048e3f8755SKonrad Rzeszutek Wilk 	}
1205dfc07b13SKonrad Rzeszutek Wilk 	while (rc != rp) {
1206dfc07b13SKonrad Rzeszutek Wilk 
1207dfc07b13SKonrad Rzeszutek Wilk 		if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
1208dfc07b13SKonrad Rzeszutek Wilk 			break;
1209dfc07b13SKonrad Rzeszutek Wilk 
121001263a1fSJuergen Gross 		/* We've seen a request, so clear spurious eoi flag. */
121101263a1fSJuergen Gross 		*eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS;
121201263a1fSJuergen Gross 
1213dfc07b13SKonrad Rzeszutek Wilk 		if (kthread_should_stop()) {
1214dfc07b13SKonrad Rzeszutek Wilk 			more_to_do = 1;
1215dfc07b13SKonrad Rzeszutek Wilk 			break;
1216dfc07b13SKonrad Rzeszutek Wilk 		}
1217dfc07b13SKonrad Rzeszutek Wilk 
121859795700SBob Liu 		pending_req = alloc_req(ring);
1219dfc07b13SKonrad Rzeszutek Wilk 		if (NULL == pending_req) {
1220db6fbc10SBob Liu 			ring->st_oo_req++;
1221dfc07b13SKonrad Rzeszutek Wilk 			more_to_do = 1;
1222dfc07b13SKonrad Rzeszutek Wilk 			break;
1223dfc07b13SKonrad Rzeszutek Wilk 		}
1224dfc07b13SKonrad Rzeszutek Wilk 
122559795700SBob Liu 		switch (ring->blkif->blk_protocol) {
1226dfc07b13SKonrad Rzeszutek Wilk 		case BLKIF_PROTOCOL_NATIVE:
1227dfc07b13SKonrad Rzeszutek Wilk 			memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req));
1228dfc07b13SKonrad Rzeszutek Wilk 			break;
1229dfc07b13SKonrad Rzeszutek Wilk 		case BLKIF_PROTOCOL_X86_32:
1230dfc07b13SKonrad Rzeszutek Wilk 			blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc));
1231dfc07b13SKonrad Rzeszutek Wilk 			break;
1232dfc07b13SKonrad Rzeszutek Wilk 		case BLKIF_PROTOCOL_X86_64:
1233dfc07b13SKonrad Rzeszutek Wilk 			blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc));
1234dfc07b13SKonrad Rzeszutek Wilk 			break;
1235dfc07b13SKonrad Rzeszutek Wilk 		default:
1236dfc07b13SKonrad Rzeszutek Wilk 			BUG();
1237dfc07b13SKonrad Rzeszutek Wilk 		}
1238dfc07b13SKonrad Rzeszutek Wilk 		blk_rings->common.req_cons = ++rc; /* before make_response() */
1239dfc07b13SKonrad Rzeszutek Wilk 
1240dfc07b13SKonrad Rzeszutek Wilk 		/* Apply all sanity checks to /private copy/ of request. */
1241dfc07b13SKonrad Rzeszutek Wilk 		barrier();
12420e367ae4SDavid Vrabel 
12430e367ae4SDavid Vrabel 		switch (req.operation) {
12440e367ae4SDavid Vrabel 		case BLKIF_OP_READ:
12450e367ae4SDavid Vrabel 		case BLKIF_OP_WRITE:
12460e367ae4SDavid Vrabel 		case BLKIF_OP_WRITE_BARRIER:
12470e367ae4SDavid Vrabel 		case BLKIF_OP_FLUSH_DISKCACHE:
1248402b27f9SRoger Pau Monne 		case BLKIF_OP_INDIRECT:
124959795700SBob Liu 			if (dispatch_rw_block_io(ring, &req, pending_req))
12500e367ae4SDavid Vrabel 				goto done;
12510e367ae4SDavid Vrabel 			break;
12520e367ae4SDavid Vrabel 		case BLKIF_OP_DISCARD:
125359795700SBob Liu 			free_req(ring, pending_req);
125459795700SBob Liu 			if (dispatch_discard_io(ring, &req))
12550e367ae4SDavid Vrabel 				goto done;
125642146352SKonrad Rzeszutek Wilk 			break;
12570e367ae4SDavid Vrabel 		default:
125859795700SBob Liu 			if (dispatch_other_io(ring, &req, pending_req))
12590e367ae4SDavid Vrabel 				goto done;
1260dfc07b13SKonrad Rzeszutek Wilk 			break;
12610e367ae4SDavid Vrabel 		}
1262dfc07b13SKonrad Rzeszutek Wilk 
1263dfc07b13SKonrad Rzeszutek Wilk 		/* Yield point for this unbounded loop. */
1264dfc07b13SKonrad Rzeszutek Wilk 		cond_resched();
1265dfc07b13SKonrad Rzeszutek Wilk 	}
12660e367ae4SDavid Vrabel done:
1267dfc07b13SKonrad Rzeszutek Wilk 	return more_to_do;
1268dfc07b13SKonrad Rzeszutek Wilk }
1269dfc07b13SKonrad Rzeszutek Wilk 
1270b4726a9dSDaniel Stodden static int
do_block_io_op(struct xen_blkif_ring * ring,unsigned int * eoi_flags)127101263a1fSJuergen Gross do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags)
1272b4726a9dSDaniel Stodden {
127359795700SBob Liu 	union blkif_back_rings *blk_rings = &ring->blk_rings;
1274b4726a9dSDaniel Stodden 	int more_to_do;
1275b4726a9dSDaniel Stodden 
1276b4726a9dSDaniel Stodden 	do {
127701263a1fSJuergen Gross 		more_to_do = __do_block_io_op(ring, eoi_flags);
1278b4726a9dSDaniel Stodden 		if (more_to_do)
1279b4726a9dSDaniel Stodden 			break;
1280b4726a9dSDaniel Stodden 
1281b4726a9dSDaniel Stodden 		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
1282b4726a9dSDaniel Stodden 	} while (more_to_do);
1283b4726a9dSDaniel Stodden 
1284b4726a9dSDaniel Stodden 	return more_to_do;
1285b4726a9dSDaniel Stodden }
1286dfc07b13SKonrad Rzeszutek Wilk /*
128701f37f2dSKonrad Rzeszutek Wilk  * Transmutation of the 'struct blkif_request' to a proper 'struct bio'
128801f37f2dSKonrad Rzeszutek Wilk  * and call the 'submit_bio' to pass it to the underlying storage.
1289dfc07b13SKonrad Rzeszutek Wilk  */
dispatch_rw_block_io(struct xen_blkif_ring * ring,struct blkif_request * req,struct pending_req * pending_req)129059795700SBob Liu static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
1291dfc07b13SKonrad Rzeszutek Wilk 				struct blkif_request *req,
1292dfc07b13SKonrad Rzeszutek Wilk 				struct pending_req *pending_req)
1293dfc07b13SKonrad Rzeszutek Wilk {
1294dfc07b13SKonrad Rzeszutek Wilk 	struct phys_req preq;
1295402b27f9SRoger Pau Monne 	struct seg_buf *seg = pending_req->seg;
1296dfc07b13SKonrad Rzeszutek Wilk 	unsigned int nseg;
1297dfc07b13SKonrad Rzeszutek Wilk 	struct bio *bio = NULL;
1298402b27f9SRoger Pau Monne 	struct bio **biolist = pending_req->biolist;
1299dfc07b13SKonrad Rzeszutek Wilk 	int i, nbio = 0;
13006c5412e2SBart Van Assche 	enum req_op operation;
13016c5412e2SBart Van Assche 	blk_opf_t operation_flags = 0;
1302a19be5f0SKonrad Rzeszutek Wilk 	struct blk_plug plug;
130329bde093SKonrad Rzeszutek Wilk 	bool drain = false;
1304bb642e83SRoger Pau Monne 	struct grant_page **pages = pending_req->segments;
1305402b27f9SRoger Pau Monne 	unsigned short req_operation;
1306dfc07b13SKonrad Rzeszutek Wilk 
1307402b27f9SRoger Pau Monne 	req_operation = req->operation == BLKIF_OP_INDIRECT ?
1308402b27f9SRoger Pau Monne 			req->u.indirect.indirect_op : req->operation;
130967de5dfbSJulien Grall 
1310402b27f9SRoger Pau Monne 	if ((req->operation == BLKIF_OP_INDIRECT) &&
1311402b27f9SRoger Pau Monne 	    (req_operation != BLKIF_OP_READ) &&
1312402b27f9SRoger Pau Monne 	    (req_operation != BLKIF_OP_WRITE)) {
131377387b82STao Chen 		pr_debug("Invalid indirect operation (%u)\n", req_operation);
1314402b27f9SRoger Pau Monne 		goto fail_response;
1315402b27f9SRoger Pau Monne 	}
1316402b27f9SRoger Pau Monne 
1317402b27f9SRoger Pau Monne 	switch (req_operation) {
1318dfc07b13SKonrad Rzeszutek Wilk 	case BLKIF_OP_READ:
1319db6fbc10SBob Liu 		ring->st_rd_req++;
1320a022606eSMike Christie 		operation = REQ_OP_READ;
1321dfc07b13SKonrad Rzeszutek Wilk 		break;
1322dfc07b13SKonrad Rzeszutek Wilk 	case BLKIF_OP_WRITE:
1323db6fbc10SBob Liu 		ring->st_wr_req++;
1324a022606eSMike Christie 		operation = REQ_OP_WRITE;
132570fd7614SChristoph Hellwig 		operation_flags = REQ_SYNC | REQ_IDLE;
1326dfc07b13SKonrad Rzeszutek Wilk 		break;
132729bde093SKonrad Rzeszutek Wilk 	case BLKIF_OP_WRITE_BARRIER:
132829bde093SKonrad Rzeszutek Wilk 		drain = true;
1329df561f66SGustavo A. R. Silva 		fallthrough;
133024f567f9SKonrad Rzeszutek Wilk 	case BLKIF_OP_FLUSH_DISKCACHE:
1331db6fbc10SBob Liu 		ring->st_f_req++;
1332a022606eSMike Christie 		operation = REQ_OP_WRITE;
133370fd7614SChristoph Hellwig 		operation_flags = REQ_PREFLUSH;
1334dfc07b13SKonrad Rzeszutek Wilk 		break;
1335dfc07b13SKonrad Rzeszutek Wilk 	default:
1336dfc07b13SKonrad Rzeszutek Wilk 		operation = 0; /* make gcc happy */
1337fc53bf75SKonrad Rzeszutek Wilk 		goto fail_response;
1338fc53bf75SKonrad Rzeszutek Wilk 		break;
1339dfc07b13SKonrad Rzeszutek Wilk 	}
1340dfc07b13SKonrad Rzeszutek Wilk 
1341dfc07b13SKonrad Rzeszutek Wilk 	/* Check that the number of segments is sane. */
1342402b27f9SRoger Pau Monne 	nseg = req->operation == BLKIF_OP_INDIRECT ?
1343402b27f9SRoger Pau Monne 	       req->u.indirect.nr_segments : req->u.rw.nr_segments;
134497e36834SKonrad Rzeszutek Wilk 
134570fd7614SChristoph Hellwig 	if (unlikely(nseg == 0 && operation_flags != REQ_PREFLUSH) ||
1346402b27f9SRoger Pau Monne 	    unlikely((req->operation != BLKIF_OP_INDIRECT) &&
1347402b27f9SRoger Pau Monne 		     (nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) ||
1348402b27f9SRoger Pau Monne 	    unlikely((req->operation == BLKIF_OP_INDIRECT) &&
1349402b27f9SRoger Pau Monne 		     (nseg > MAX_INDIRECT_SEGMENTS))) {
135077387b82STao Chen 		pr_debug("Bad number of segments in request (%d)\n", nseg);
1351dfc07b13SKonrad Rzeszutek Wilk 		/* Haven't submitted any bio's yet. */
1352dfc07b13SKonrad Rzeszutek Wilk 		goto fail_response;
1353dfc07b13SKonrad Rzeszutek Wilk 	}
1354dfc07b13SKonrad Rzeszutek Wilk 
1355dfc07b13SKonrad Rzeszutek Wilk 	preq.nr_sects      = 0;
1356dfc07b13SKonrad Rzeszutek Wilk 
135759795700SBob Liu 	pending_req->ring      = ring;
135897e36834SKonrad Rzeszutek Wilk 	pending_req->id        = req->u.rw.id;
1359402b27f9SRoger Pau Monne 	pending_req->operation = req_operation;
1360dfc07b13SKonrad Rzeszutek Wilk 	pending_req->status    = BLKIF_RSP_OKAY;
13616684fa1cSJulien Grall 	pending_req->nr_segs   = nseg;
1362dfc07b13SKonrad Rzeszutek Wilk 
1363402b27f9SRoger Pau Monne 	if (req->operation != BLKIF_OP_INDIRECT) {
1364402b27f9SRoger Pau Monne 		preq.dev               = req->u.rw.handle;
1365402b27f9SRoger Pau Monne 		preq.sector_number     = req->u.rw.sector_number;
1366dfc07b13SKonrad Rzeszutek Wilk 		for (i = 0; i < nseg; i++) {
1367bb642e83SRoger Pau Monne 			pages[i]->gref = req->u.rw.seg[i].gref;
1368dfc07b13SKonrad Rzeszutek Wilk 			seg[i].nsec = req->u.rw.seg[i].last_sect -
1369dfc07b13SKonrad Rzeszutek Wilk 				req->u.rw.seg[i].first_sect + 1;
1370402b27f9SRoger Pau Monne 			seg[i].offset = (req->u.rw.seg[i].first_sect << 9);
137167de5dfbSJulien Grall 			if ((req->u.rw.seg[i].last_sect >= (XEN_PAGE_SIZE >> 9)) ||
1372402b27f9SRoger Pau Monne 			    (req->u.rw.seg[i].last_sect <
1373402b27f9SRoger Pau Monne 			     req->u.rw.seg[i].first_sect))
1374dfc07b13SKonrad Rzeszutek Wilk 				goto fail_response;
1375dfc07b13SKonrad Rzeszutek Wilk 			preq.nr_sects += seg[i].nsec;
1376402b27f9SRoger Pau Monne 		}
1377402b27f9SRoger Pau Monne 	} else {
1378402b27f9SRoger Pau Monne 		preq.dev               = req->u.indirect.handle;
1379402b27f9SRoger Pau Monne 		preq.sector_number     = req->u.indirect.sector_number;
1380402b27f9SRoger Pau Monne 		if (xen_blkbk_parse_indirect(req, pending_req, seg, &preq))
1381402b27f9SRoger Pau Monne 			goto fail_response;
1382dfc07b13SKonrad Rzeszutek Wilk 	}
1383dfc07b13SKonrad Rzeszutek Wilk 
138459795700SBob Liu 	if (xen_vbd_translate(&preq, ring->blkif, operation) != 0) {
138577387b82STao Chen 		pr_debug("access denied: %s of [%llu,%llu] on dev=%04x\n",
1386a022606eSMike Christie 			 operation == REQ_OP_READ ? "read" : "write",
1387dfc07b13SKonrad Rzeszutek Wilk 			 preq.sector_number,
1388a72d9002SChen Gang 			 preq.sector_number + preq.nr_sects,
138959795700SBob Liu 			 ring->blkif->vbd.pdevice);
1390dfc07b13SKonrad Rzeszutek Wilk 		goto fail_response;
1391dfc07b13SKonrad Rzeszutek Wilk 	}
139201f37f2dSKonrad Rzeszutek Wilk 
139301f37f2dSKonrad Rzeszutek Wilk 	/*
13943d814731SKonrad Rzeszutek Wilk 	 * This check _MUST_ be done after xen_vbd_translate as the preq.bdev
139501f37f2dSKonrad Rzeszutek Wilk 	 * is set there.
139601f37f2dSKonrad Rzeszutek Wilk 	 */
1397dfc07b13SKonrad Rzeszutek Wilk 	for (i = 0; i < nseg; i++) {
1398dfc07b13SKonrad Rzeszutek Wilk 		if (((int)preq.sector_number|(int)seg[i].nsec) &
1399dfc07b13SKonrad Rzeszutek Wilk 		    ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) {
140077387b82STao Chen 			pr_debug("Misaligned I/O request from domain %d\n",
140159795700SBob Liu 				 ring->blkif->domid);
1402dfc07b13SKonrad Rzeszutek Wilk 			goto fail_response;
1403dfc07b13SKonrad Rzeszutek Wilk 		}
1404dfc07b13SKonrad Rzeszutek Wilk 	}
140501f37f2dSKonrad Rzeszutek Wilk 
140629bde093SKonrad Rzeszutek Wilk 	/* Wait on all outstanding I/O's and once that has been completed
140770fd7614SChristoph Hellwig 	 * issue the flush.
140829bde093SKonrad Rzeszutek Wilk 	 */
140929bde093SKonrad Rzeszutek Wilk 	if (drain)
141059795700SBob Liu 		xen_blk_drain_io(pending_req->ring);
141129bde093SKonrad Rzeszutek Wilk 
141201f37f2dSKonrad Rzeszutek Wilk 	/*
141301f37f2dSKonrad Rzeszutek Wilk 	 * If we have failed at this point, we need to undo the M2P override,
1414dfc07b13SKonrad Rzeszutek Wilk 	 * set gnttab_set_unmap_op on all of the grant references and perform
1415dfc07b13SKonrad Rzeszutek Wilk 	 * the hypercall to unmap the grants - that is all done in
1416dfc07b13SKonrad Rzeszutek Wilk 	 * xen_blkbk_unmap.
1417dfc07b13SKonrad Rzeszutek Wilk 	 */
1418bb642e83SRoger Pau Monne 	if (xen_blkbk_map_seg(pending_req))
1419dfc07b13SKonrad Rzeszutek Wilk 		goto fail_flush;
1420dfc07b13SKonrad Rzeszutek Wilk 
1421b3cb0d6aSLi Dongyang 	/*
1422b3cb0d6aSLi Dongyang 	 * This corresponding xen_blkif_put is done in __end_block_io_op, or
1423b3cb0d6aSLi Dongyang 	 * below (in "!bio") if we are handling a BLKIF_OP_DISCARD.
1424b3cb0d6aSLi Dongyang 	 */
142559795700SBob Liu 	xen_blkif_get(ring->blkif);
142659795700SBob Liu 	atomic_inc(&ring->inflight);
1427dfc07b13SKonrad Rzeszutek Wilk 
1428dfc07b13SKonrad Rzeszutek Wilk 	for (i = 0; i < nseg; i++) {
1429dfc07b13SKonrad Rzeszutek Wilk 		while ((bio == NULL) ||
1430dfc07b13SKonrad Rzeszutek Wilk 		       (bio_add_page(bio,
1431bb642e83SRoger Pau Monne 				     pages[i]->page,
1432dfc07b13SKonrad Rzeszutek Wilk 				     seg[i].nsec << 9,
1433ffb1dabdSRoger Pau Monne 				     seg[i].offset) == 0)) {
143407888c66SChristoph Hellwig 			bio = bio_alloc(preq.bdev, bio_max_segs(nseg - i),
143507888c66SChristoph Hellwig 					operation | operation_flags,
143607888c66SChristoph Hellwig 					GFP_KERNEL);
143703e0edf9SKonrad Rzeszutek Wilk 			biolist[nbio++] = bio;
1438dfc07b13SKonrad Rzeszutek Wilk 			bio->bi_private = pending_req;
1439dfc07b13SKonrad Rzeszutek Wilk 			bio->bi_end_io  = end_block_io_op;
14404f024f37SKent Overstreet 			bio->bi_iter.bi_sector  = preq.sector_number;
1441dfc07b13SKonrad Rzeszutek Wilk 		}
1442dfc07b13SKonrad Rzeszutek Wilk 
1443dfc07b13SKonrad Rzeszutek Wilk 		preq.sector_number += seg[i].nsec;
1444dfc07b13SKonrad Rzeszutek Wilk 	}
1445dfc07b13SKonrad Rzeszutek Wilk 
1446b3cb0d6aSLi Dongyang 	/* This will be hit if the operation was a flush or discard. */
1447dfc07b13SKonrad Rzeszutek Wilk 	if (!bio) {
144870fd7614SChristoph Hellwig 		BUG_ON(operation_flags != REQ_PREFLUSH);
144903e0edf9SKonrad Rzeszutek Wilk 
145007888c66SChristoph Hellwig 		bio = bio_alloc(preq.bdev, 0, operation | operation_flags,
145107888c66SChristoph Hellwig 				GFP_KERNEL);
145203e0edf9SKonrad Rzeszutek Wilk 		biolist[nbio++] = bio;
1453dfc07b13SKonrad Rzeszutek Wilk 		bio->bi_private = pending_req;
1454dfc07b13SKonrad Rzeszutek Wilk 		bio->bi_end_io  = end_block_io_op;
1455dfc07b13SKonrad Rzeszutek Wilk 	}
1456dfc07b13SKonrad Rzeszutek Wilk 
1457dfc07b13SKonrad Rzeszutek Wilk 	atomic_set(&pending_req->pendcnt, nbio);
1458a19be5f0SKonrad Rzeszutek Wilk 	blk_start_plug(&plug);
1459a19be5f0SKonrad Rzeszutek Wilk 
1460dfc07b13SKonrad Rzeszutek Wilk 	for (i = 0; i < nbio; i++)
14614e49ea4aSMike Christie 		submit_bio(biolist[i]);
1462dfc07b13SKonrad Rzeszutek Wilk 
1463a19be5f0SKonrad Rzeszutek Wilk 	/* Let the I/Os go.. */
14643d68b399SKonrad Rzeszutek Wilk 	blk_finish_plug(&plug);
1465a19be5f0SKonrad Rzeszutek Wilk 
1466a022606eSMike Christie 	if (operation == REQ_OP_READ)
1467db6fbc10SBob Liu 		ring->st_rd_sect += preq.nr_sects;
1468a022606eSMike Christie 	else if (operation == REQ_OP_WRITE)
1469db6fbc10SBob Liu 		ring->st_wr_sect += preq.nr_sects;
1470dfc07b13SKonrad Rzeszutek Wilk 
1471fc53bf75SKonrad Rzeszutek Wilk 	return 0;
1472dfc07b13SKonrad Rzeszutek Wilk 
1473dfc07b13SKonrad Rzeszutek Wilk  fail_flush:
147459795700SBob Liu 	xen_blkbk_unmap(ring, pending_req->segments,
14756684fa1cSJulien Grall 	                pending_req->nr_segs);
1476dfc07b13SKonrad Rzeszutek Wilk  fail_response:
1477dfc07b13SKonrad Rzeszutek Wilk 	/* Haven't submitted any bio's yet. */
147859795700SBob Liu 	make_response(ring, req->u.rw.id, req_operation, BLKIF_RSP_ERROR);
147959795700SBob Liu 	free_req(ring, pending_req);
1480dfc07b13SKonrad Rzeszutek Wilk 	msleep(1); /* back off a bit */
1481fc53bf75SKonrad Rzeszutek Wilk 	return -EIO;
1482dfc07b13SKonrad Rzeszutek Wilk }
1483dfc07b13SKonrad Rzeszutek Wilk 
1484dfc07b13SKonrad Rzeszutek Wilk 
1485dfc07b13SKonrad Rzeszutek Wilk 
1486dfc07b13SKonrad Rzeszutek Wilk /*
1487dfc07b13SKonrad Rzeszutek Wilk  * Put a response on the ring on how the operation fared.
1488dfc07b13SKonrad Rzeszutek Wilk  */
make_response(struct xen_blkif_ring * ring,u64 id,unsigned short op,int st)148959795700SBob Liu static void make_response(struct xen_blkif_ring *ring, u64 id,
1490dfc07b13SKonrad Rzeszutek Wilk 			  unsigned short op, int st)
1491dfc07b13SKonrad Rzeszutek Wilk {
1492089bc014SJan Beulich 	struct blkif_response *resp;
1493dfc07b13SKonrad Rzeszutek Wilk 	unsigned long     flags;
149459795700SBob Liu 	union blkif_back_rings *blk_rings;
1495dfc07b13SKonrad Rzeszutek Wilk 	int notify;
1496dfc07b13SKonrad Rzeszutek Wilk 
149759795700SBob Liu 	spin_lock_irqsave(&ring->blk_ring_lock, flags);
149859795700SBob Liu 	blk_rings = &ring->blk_rings;
1499dfc07b13SKonrad Rzeszutek Wilk 	/* Place on the response ring for the relevant domain. */
150059795700SBob Liu 	switch (ring->blkif->blk_protocol) {
1501dfc07b13SKonrad Rzeszutek Wilk 	case BLKIF_PROTOCOL_NATIVE:
1502089bc014SJan Beulich 		resp = RING_GET_RESPONSE(&blk_rings->native,
1503089bc014SJan Beulich 					 blk_rings->native.rsp_prod_pvt);
1504dfc07b13SKonrad Rzeszutek Wilk 		break;
1505dfc07b13SKonrad Rzeszutek Wilk 	case BLKIF_PROTOCOL_X86_32:
1506089bc014SJan Beulich 		resp = RING_GET_RESPONSE(&blk_rings->x86_32,
1507089bc014SJan Beulich 					 blk_rings->x86_32.rsp_prod_pvt);
1508dfc07b13SKonrad Rzeszutek Wilk 		break;
1509dfc07b13SKonrad Rzeszutek Wilk 	case BLKIF_PROTOCOL_X86_64:
1510089bc014SJan Beulich 		resp = RING_GET_RESPONSE(&blk_rings->x86_64,
1511089bc014SJan Beulich 					 blk_rings->x86_64.rsp_prod_pvt);
1512dfc07b13SKonrad Rzeszutek Wilk 		break;
1513dfc07b13SKonrad Rzeszutek Wilk 	default:
1514dfc07b13SKonrad Rzeszutek Wilk 		BUG();
1515dfc07b13SKonrad Rzeszutek Wilk 	}
1516089bc014SJan Beulich 
1517089bc014SJan Beulich 	resp->id        = id;
1518089bc014SJan Beulich 	resp->operation = op;
1519089bc014SJan Beulich 	resp->status    = st;
1520089bc014SJan Beulich 
1521dfc07b13SKonrad Rzeszutek Wilk 	blk_rings->common.rsp_prod_pvt++;
1522dfc07b13SKonrad Rzeszutek Wilk 	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
152359795700SBob Liu 	spin_unlock_irqrestore(&ring->blk_ring_lock, flags);
1524dfc07b13SKonrad Rzeszutek Wilk 	if (notify)
152559795700SBob Liu 		notify_remote_via_irq(ring->irq);
1526dfc07b13SKonrad Rzeszutek Wilk }
1527dfc07b13SKonrad Rzeszutek Wilk 
xen_blkif_init(void)15288b6bf747SKonrad Rzeszutek Wilk static int __init xen_blkif_init(void)
1529dfc07b13SKonrad Rzeszutek Wilk {
1530dfc07b13SKonrad Rzeszutek Wilk 	int rc = 0;
1531dfc07b13SKonrad Rzeszutek Wilk 
1532b2167ba6SDaniel De Graaf 	if (!xen_domain())
1533dfc07b13SKonrad Rzeszutek Wilk 		return -ENODEV;
1534dfc07b13SKonrad Rzeszutek Wilk 
15359cce2914SJulien Grall 	if (xen_blkif_max_ring_order > XENBUS_MAX_RING_GRANT_ORDER) {
153686839c56SBob Liu 		pr_info("Invalid max_ring_order (%d), will use default max: %d.\n",
15379cce2914SJulien Grall 			xen_blkif_max_ring_order, XENBUS_MAX_RING_GRANT_ORDER);
15389cce2914SJulien Grall 		xen_blkif_max_ring_order = XENBUS_MAX_RING_GRANT_ORDER;
153986839c56SBob Liu 	}
154086839c56SBob Liu 
1541d62d8600SBob Liu 	if (xenblk_max_queues == 0)
1542d62d8600SBob Liu 		xenblk_max_queues = num_online_cpus();
1543d62d8600SBob Liu 
15448b6bf747SKonrad Rzeszutek Wilk 	rc = xen_blkif_interface_init();
1545dfc07b13SKonrad Rzeszutek Wilk 	if (rc)
1546dfc07b13SKonrad Rzeszutek Wilk 		goto failed_init;
1547dfc07b13SKonrad Rzeszutek Wilk 
15488b6bf747SKonrad Rzeszutek Wilk 	rc = xen_blkif_xenbus_init();
1549dfc07b13SKonrad Rzeszutek Wilk 	if (rc)
1550dfc07b13SKonrad Rzeszutek Wilk 		goto failed_init;
1551dfc07b13SKonrad Rzeszutek Wilk 
1552dfc07b13SKonrad Rzeszutek Wilk  failed_init:
1553dfc07b13SKonrad Rzeszutek Wilk 	return rc;
1554dfc07b13SKonrad Rzeszutek Wilk }
1555dfc07b13SKonrad Rzeszutek Wilk 
15568b6bf747SKonrad Rzeszutek Wilk module_init(xen_blkif_init);
1557dfc07b13SKonrad Rzeszutek Wilk 
xen_blkif_fini(void)155814855954SPaul Durrant static void __exit xen_blkif_fini(void)
155914855954SPaul Durrant {
156014855954SPaul Durrant 	xen_blkif_xenbus_fini();
156114855954SPaul Durrant 	xen_blkif_interface_fini();
156214855954SPaul Durrant }
156314855954SPaul Durrant 
156414855954SPaul Durrant module_exit(xen_blkif_fini);
156514855954SPaul Durrant 
1566dfc07b13SKonrad Rzeszutek Wilk MODULE_LICENSE("Dual BSD/GPL");
1567a7e9357fSBastian Blank MODULE_ALIAS("xen-backend:vbd");
1568