xref: /OK3568_Linux_fs/kernel/drivers/md/dm-ebs-target.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2020 Red Hat GmbH
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * This file is released under the GPL.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Device-mapper target to emulate smaller logical block
7*4882a593Smuzhiyun  * size on backing devices exposing (natively) larger ones.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * E.g. 512 byte sector emulation on 4K native disks.
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include "dm.h"
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/workqueue.h>
15*4882a593Smuzhiyun #include <linux/dm-bufio.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define DM_MSG_PREFIX "ebs"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun static void ebs_dtr(struct dm_target *ti);
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /* Emulated block size context. */
22*4882a593Smuzhiyun struct ebs_c {
23*4882a593Smuzhiyun 	struct dm_dev *dev;		/* Underlying device to emulate block size on. */
24*4882a593Smuzhiyun 	struct dm_bufio_client *bufio;	/* Use dm-bufio for read and read-modify-write processing. */
25*4882a593Smuzhiyun 	struct workqueue_struct *wq;	/* Workqueue for ^ processing of bios. */
26*4882a593Smuzhiyun 	struct work_struct ws;		/* Work item used for ^. */
27*4882a593Smuzhiyun 	struct bio_list bios_in;	/* Worker bios input list. */
28*4882a593Smuzhiyun 	spinlock_t lock;		/* Guard bios input list above. */
29*4882a593Smuzhiyun 	sector_t start;			/* <start> table line argument, see ebs_ctr below. */
30*4882a593Smuzhiyun 	unsigned int e_bs;		/* Emulated block size in sectors exposed to upper layer. */
31*4882a593Smuzhiyun 	unsigned int u_bs;		/* Underlying block size in sectors retrievd from/set on lower layer device. */
32*4882a593Smuzhiyun 	unsigned char block_shift;	/* bitshift sectors -> blocks used in dm-bufio API. */
33*4882a593Smuzhiyun 	bool u_bs_set:1;		/* Flag to indicate underlying block size is set on table line. */
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun 
__sector_to_block(struct ebs_c * ec,sector_t sector)36*4882a593Smuzhiyun static inline sector_t __sector_to_block(struct ebs_c *ec, sector_t sector)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	return sector >> ec->block_shift;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
__block_mod(sector_t sector,unsigned int bs)41*4882a593Smuzhiyun static inline sector_t __block_mod(sector_t sector, unsigned int bs)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	return sector & (bs - 1);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /* Return number of blocks for a bio, accounting for misalignement of start and end sectors. */
__nr_blocks(struct ebs_c * ec,struct bio * bio)47*4882a593Smuzhiyun static inline unsigned int __nr_blocks(struct ebs_c *ec, struct bio *bio)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	sector_t end_sector = __block_mod(bio->bi_iter.bi_sector, ec->u_bs) + bio_sectors(bio);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	return __sector_to_block(ec, end_sector) + (__block_mod(end_sector, ec->u_bs) ? 1 : 0);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
__ebs_check_bs(unsigned int bs)54*4882a593Smuzhiyun static inline bool __ebs_check_bs(unsigned int bs)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	return bs && is_power_of_2(bs);
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun /*
60*4882a593Smuzhiyun  * READ/WRITE:
61*4882a593Smuzhiyun  *
62*4882a593Smuzhiyun  * copy blocks between bufio blocks and bio vector's (partial/overlapping) pages.
63*4882a593Smuzhiyun  */
__ebs_rw_bvec(struct ebs_c * ec,int rw,struct bio_vec * bv,struct bvec_iter * iter)64*4882a593Smuzhiyun static int __ebs_rw_bvec(struct ebs_c *ec, int rw, struct bio_vec *bv, struct bvec_iter *iter)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	int r = 0;
67*4882a593Smuzhiyun 	unsigned char *ba, *pa;
68*4882a593Smuzhiyun 	unsigned int cur_len;
69*4882a593Smuzhiyun 	unsigned int bv_len = bv->bv_len;
70*4882a593Smuzhiyun 	unsigned int buf_off = to_bytes(__block_mod(iter->bi_sector, ec->u_bs));
71*4882a593Smuzhiyun 	sector_t block = __sector_to_block(ec, iter->bi_sector);
72*4882a593Smuzhiyun 	struct dm_buffer *b;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	if (unlikely(!bv->bv_page || !bv_len))
75*4882a593Smuzhiyun 		return -EIO;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	pa = page_address(bv->bv_page) + bv->bv_offset;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	/* Handle overlapping page <-> blocks */
80*4882a593Smuzhiyun 	while (bv_len) {
81*4882a593Smuzhiyun 		cur_len = min(dm_bufio_get_block_size(ec->bufio) - buf_off, bv_len);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 		/* Avoid reading for writes in case bio vector's page overwrites block completely. */
84*4882a593Smuzhiyun 		if (rw == READ || buf_off || bv_len < dm_bufio_get_block_size(ec->bufio))
85*4882a593Smuzhiyun 			ba = dm_bufio_read(ec->bufio, block, &b);
86*4882a593Smuzhiyun 		else
87*4882a593Smuzhiyun 			ba = dm_bufio_new(ec->bufio, block, &b);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 		if (unlikely(IS_ERR(ba))) {
90*4882a593Smuzhiyun 			/*
91*4882a593Smuzhiyun 			 * Carry on with next buffer, if any, to issue all possible
92*4882a593Smuzhiyun 			 * data but return error.
93*4882a593Smuzhiyun 			 */
94*4882a593Smuzhiyun 			r = PTR_ERR(ba);
95*4882a593Smuzhiyun 		} else {
96*4882a593Smuzhiyun 			/* Copy data to/from bio to buffer if read/new was successful above. */
97*4882a593Smuzhiyun 			ba += buf_off;
98*4882a593Smuzhiyun 			if (rw == READ) {
99*4882a593Smuzhiyun 				memcpy(pa, ba, cur_len);
100*4882a593Smuzhiyun 				flush_dcache_page(bv->bv_page);
101*4882a593Smuzhiyun 			} else {
102*4882a593Smuzhiyun 				flush_dcache_page(bv->bv_page);
103*4882a593Smuzhiyun 				memcpy(ba, pa, cur_len);
104*4882a593Smuzhiyun 				dm_bufio_mark_partial_buffer_dirty(b, buf_off, buf_off + cur_len);
105*4882a593Smuzhiyun 			}
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 			dm_bufio_release(b);
108*4882a593Smuzhiyun 		}
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 		pa += cur_len;
111*4882a593Smuzhiyun 		bv_len -= cur_len;
112*4882a593Smuzhiyun 		buf_off = 0;
113*4882a593Smuzhiyun 		block++;
114*4882a593Smuzhiyun 	}
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return r;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun /* READ/WRITE: iterate bio vector's copying between (partial) pages and bufio blocks. */
__ebs_rw_bio(struct ebs_c * ec,int rw,struct bio * bio)120*4882a593Smuzhiyun static int __ebs_rw_bio(struct ebs_c *ec, int rw, struct bio *bio)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	int r = 0, rr;
123*4882a593Smuzhiyun 	struct bio_vec bv;
124*4882a593Smuzhiyun 	struct bvec_iter iter;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	bio_for_each_bvec(bv, bio, iter) {
127*4882a593Smuzhiyun 		rr = __ebs_rw_bvec(ec, rw, &bv, &iter);
128*4882a593Smuzhiyun 		if (rr)
129*4882a593Smuzhiyun 			r = rr;
130*4882a593Smuzhiyun 	}
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	return r;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun /*
136*4882a593Smuzhiyun  * Discard bio's blocks, i.e. pass discards down.
137*4882a593Smuzhiyun  *
138*4882a593Smuzhiyun  * Avoid discarding partial blocks at beginning and end;
139*4882a593Smuzhiyun  * return 0 in case no blocks can be discarded as a result.
140*4882a593Smuzhiyun  */
__ebs_discard_bio(struct ebs_c * ec,struct bio * bio)141*4882a593Smuzhiyun static int __ebs_discard_bio(struct ebs_c *ec, struct bio *bio)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	sector_t block, blocks, sector = bio->bi_iter.bi_sector;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	block = __sector_to_block(ec, sector);
146*4882a593Smuzhiyun 	blocks = __nr_blocks(ec, bio);
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	/*
149*4882a593Smuzhiyun 	 * Partial first underlying block (__nr_blocks() may have
150*4882a593Smuzhiyun 	 * resulted in one block).
151*4882a593Smuzhiyun 	 */
152*4882a593Smuzhiyun 	if (__block_mod(sector, ec->u_bs)) {
153*4882a593Smuzhiyun 		block++;
154*4882a593Smuzhiyun 		blocks--;
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	/* Partial last underlying block if any. */
158*4882a593Smuzhiyun 	if (blocks && __block_mod(bio_end_sector(bio), ec->u_bs))
159*4882a593Smuzhiyun 		blocks--;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	return blocks ? dm_bufio_issue_discard(ec->bufio, block, blocks) : 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun /* Release blocks them from the bufio cache. */
__ebs_forget_bio(struct ebs_c * ec,struct bio * bio)165*4882a593Smuzhiyun static void __ebs_forget_bio(struct ebs_c *ec, struct bio *bio)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 	sector_t blocks, sector = bio->bi_iter.bi_sector;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	blocks = __nr_blocks(ec, bio);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	dm_bufio_forget_buffers(ec->bufio, __sector_to_block(ec, sector), blocks);
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun /* Worker funtion to process incoming bios. */
__ebs_process_bios(struct work_struct * ws)175*4882a593Smuzhiyun static void __ebs_process_bios(struct work_struct *ws)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	int r;
178*4882a593Smuzhiyun 	bool write = false;
179*4882a593Smuzhiyun 	sector_t block1, block2;
180*4882a593Smuzhiyun 	struct ebs_c *ec = container_of(ws, struct ebs_c, ws);
181*4882a593Smuzhiyun 	struct bio *bio;
182*4882a593Smuzhiyun 	struct bio_list bios;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	bio_list_init(&bios);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	spin_lock_irq(&ec->lock);
187*4882a593Smuzhiyun 	bios = ec->bios_in;
188*4882a593Smuzhiyun 	bio_list_init(&ec->bios_in);
189*4882a593Smuzhiyun 	spin_unlock_irq(&ec->lock);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	/* Prefetch all read and any mis-aligned write buffers */
192*4882a593Smuzhiyun 	bio_list_for_each(bio, &bios) {
193*4882a593Smuzhiyun 		block1 = __sector_to_block(ec, bio->bi_iter.bi_sector);
194*4882a593Smuzhiyun 		if (bio_op(bio) == REQ_OP_READ)
195*4882a593Smuzhiyun 			dm_bufio_prefetch(ec->bufio, block1, __nr_blocks(ec, bio));
196*4882a593Smuzhiyun 		else if (bio_op(bio) == REQ_OP_WRITE && !(bio->bi_opf & REQ_PREFLUSH)) {
197*4882a593Smuzhiyun 			block2 = __sector_to_block(ec, bio_end_sector(bio));
198*4882a593Smuzhiyun 			if (__block_mod(bio->bi_iter.bi_sector, ec->u_bs))
199*4882a593Smuzhiyun 				dm_bufio_prefetch(ec->bufio, block1, 1);
200*4882a593Smuzhiyun 			if (__block_mod(bio_end_sector(bio), ec->u_bs) && block2 != block1)
201*4882a593Smuzhiyun 				dm_bufio_prefetch(ec->bufio, block2, 1);
202*4882a593Smuzhiyun 		}
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	bio_list_for_each(bio, &bios) {
206*4882a593Smuzhiyun 		r = -EIO;
207*4882a593Smuzhiyun 		if (bio_op(bio) == REQ_OP_READ)
208*4882a593Smuzhiyun 			r = __ebs_rw_bio(ec, READ, bio);
209*4882a593Smuzhiyun 		else if (bio_op(bio) == REQ_OP_WRITE) {
210*4882a593Smuzhiyun 			write = true;
211*4882a593Smuzhiyun 			r = __ebs_rw_bio(ec, WRITE, bio);
212*4882a593Smuzhiyun 		} else if (bio_op(bio) == REQ_OP_DISCARD) {
213*4882a593Smuzhiyun 			__ebs_forget_bio(ec, bio);
214*4882a593Smuzhiyun 			r = __ebs_discard_bio(ec, bio);
215*4882a593Smuzhiyun 		}
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 		if (r < 0)
218*4882a593Smuzhiyun 			bio->bi_status = errno_to_blk_status(r);
219*4882a593Smuzhiyun 	}
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	/*
222*4882a593Smuzhiyun 	 * We write dirty buffers after processing I/O on them
223*4882a593Smuzhiyun 	 * but before we endio thus addressing REQ_FUA/REQ_SYNC.
224*4882a593Smuzhiyun 	 */
225*4882a593Smuzhiyun 	r = write ? dm_bufio_write_dirty_buffers(ec->bufio) : 0;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	while ((bio = bio_list_pop(&bios))) {
228*4882a593Smuzhiyun 		/* Any other request is endioed. */
229*4882a593Smuzhiyun 		if (unlikely(r && bio_op(bio) == REQ_OP_WRITE))
230*4882a593Smuzhiyun 			bio_io_error(bio);
231*4882a593Smuzhiyun 		else
232*4882a593Smuzhiyun 			bio_endio(bio);
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun /*
237*4882a593Smuzhiyun  * Construct an emulated block size mapping: <dev_path> <offset> <ebs> [<ubs>]
238*4882a593Smuzhiyun  *
239*4882a593Smuzhiyun  * <dev_path>: path of the underlying device
240*4882a593Smuzhiyun  * <offset>: offset in 512 bytes sectors into <dev_path>
241*4882a593Smuzhiyun  * <ebs>: emulated block size in units of 512 bytes exposed to the upper layer
242*4882a593Smuzhiyun  * [<ubs>]: underlying block size in units of 512 bytes imposed on the lower layer;
243*4882a593Smuzhiyun  * 	    optional, if not supplied, retrieve logical block size from underlying device
244*4882a593Smuzhiyun  */
ebs_ctr(struct dm_target * ti,unsigned int argc,char ** argv)245*4882a593Smuzhiyun static int ebs_ctr(struct dm_target *ti, unsigned int argc, char **argv)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	int r;
248*4882a593Smuzhiyun 	unsigned short tmp1;
249*4882a593Smuzhiyun 	unsigned long long tmp;
250*4882a593Smuzhiyun 	char dummy;
251*4882a593Smuzhiyun 	struct ebs_c *ec;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	if (argc < 3 || argc > 4) {
254*4882a593Smuzhiyun 		ti->error = "Invalid argument count";
255*4882a593Smuzhiyun 		return -EINVAL;
256*4882a593Smuzhiyun 	}
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	ec = ti->private = kzalloc(sizeof(*ec), GFP_KERNEL);
259*4882a593Smuzhiyun 	if (!ec) {
260*4882a593Smuzhiyun 		ti->error = "Cannot allocate ebs context";
261*4882a593Smuzhiyun 		return -ENOMEM;
262*4882a593Smuzhiyun 	}
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	r = -EINVAL;
265*4882a593Smuzhiyun 	if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1 ||
266*4882a593Smuzhiyun 	    tmp != (sector_t)tmp ||
267*4882a593Smuzhiyun 	    (sector_t)tmp >= ti->len) {
268*4882a593Smuzhiyun 		ti->error = "Invalid device offset sector";
269*4882a593Smuzhiyun 		goto bad;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 	ec->start = tmp;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	if (sscanf(argv[2], "%hu%c", &tmp1, &dummy) != 1 ||
274*4882a593Smuzhiyun 	    !__ebs_check_bs(tmp1) ||
275*4882a593Smuzhiyun 	    to_bytes(tmp1) > PAGE_SIZE) {
276*4882a593Smuzhiyun 		ti->error = "Invalid emulated block size";
277*4882a593Smuzhiyun 		goto bad;
278*4882a593Smuzhiyun 	}
279*4882a593Smuzhiyun 	ec->e_bs = tmp1;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	if (argc > 3) {
282*4882a593Smuzhiyun 		if (sscanf(argv[3], "%hu%c", &tmp1, &dummy) != 1 || !__ebs_check_bs(tmp1)) {
283*4882a593Smuzhiyun 			ti->error = "Invalid underlying block size";
284*4882a593Smuzhiyun 			goto bad;
285*4882a593Smuzhiyun 		}
286*4882a593Smuzhiyun 		ec->u_bs = tmp1;
287*4882a593Smuzhiyun 		ec->u_bs_set = true;
288*4882a593Smuzhiyun 	} else
289*4882a593Smuzhiyun 		ec->u_bs_set = false;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &ec->dev);
292*4882a593Smuzhiyun 	if (r) {
293*4882a593Smuzhiyun 		ti->error = "Device lookup failed";
294*4882a593Smuzhiyun 		ec->dev = NULL;
295*4882a593Smuzhiyun 		goto bad;
296*4882a593Smuzhiyun 	}
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	r = -EINVAL;
299*4882a593Smuzhiyun 	if (!ec->u_bs_set) {
300*4882a593Smuzhiyun 		ec->u_bs = to_sector(bdev_logical_block_size(ec->dev->bdev));
301*4882a593Smuzhiyun 		if (!__ebs_check_bs(ec->u_bs)) {
302*4882a593Smuzhiyun 			ti->error = "Invalid retrieved underlying block size";
303*4882a593Smuzhiyun 			goto bad;
304*4882a593Smuzhiyun 		}
305*4882a593Smuzhiyun 	}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	if (!ec->u_bs_set && ec->e_bs == ec->u_bs)
308*4882a593Smuzhiyun 		DMINFO("Emulation superfluous: emulated equal to underlying block size");
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	if (__block_mod(ec->start, ec->u_bs)) {
311*4882a593Smuzhiyun 		ti->error = "Device offset must be multiple of underlying block size";
312*4882a593Smuzhiyun 		goto bad;
313*4882a593Smuzhiyun 	}
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	ec->bufio = dm_bufio_client_create(ec->dev->bdev, to_bytes(ec->u_bs), 1, 0, NULL, NULL);
316*4882a593Smuzhiyun 	if (IS_ERR(ec->bufio)) {
317*4882a593Smuzhiyun 		ti->error = "Cannot create dm bufio client";
318*4882a593Smuzhiyun 		r = PTR_ERR(ec->bufio);
319*4882a593Smuzhiyun 		ec->bufio = NULL;
320*4882a593Smuzhiyun 		goto bad;
321*4882a593Smuzhiyun 	}
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	ec->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM);
324*4882a593Smuzhiyun 	if (!ec->wq) {
325*4882a593Smuzhiyun 		ti->error = "Cannot create dm-" DM_MSG_PREFIX " workqueue";
326*4882a593Smuzhiyun 		r = -ENOMEM;
327*4882a593Smuzhiyun 		goto bad;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	ec->block_shift = __ffs(ec->u_bs);
331*4882a593Smuzhiyun 	INIT_WORK(&ec->ws, &__ebs_process_bios);
332*4882a593Smuzhiyun 	bio_list_init(&ec->bios_in);
333*4882a593Smuzhiyun 	spin_lock_init(&ec->lock);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	ti->num_flush_bios = 1;
336*4882a593Smuzhiyun 	ti->num_discard_bios = 1;
337*4882a593Smuzhiyun 	ti->num_secure_erase_bios = 0;
338*4882a593Smuzhiyun 	ti->num_write_same_bios = 0;
339*4882a593Smuzhiyun 	ti->num_write_zeroes_bios = 0;
340*4882a593Smuzhiyun 	return 0;
341*4882a593Smuzhiyun bad:
342*4882a593Smuzhiyun 	ebs_dtr(ti);
343*4882a593Smuzhiyun 	return r;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
ebs_dtr(struct dm_target * ti)346*4882a593Smuzhiyun static void ebs_dtr(struct dm_target *ti)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun 	struct ebs_c *ec = ti->private;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	if (ec->wq)
351*4882a593Smuzhiyun 		destroy_workqueue(ec->wq);
352*4882a593Smuzhiyun 	if (ec->bufio)
353*4882a593Smuzhiyun 		dm_bufio_client_destroy(ec->bufio);
354*4882a593Smuzhiyun 	if (ec->dev)
355*4882a593Smuzhiyun 		dm_put_device(ti, ec->dev);
356*4882a593Smuzhiyun 	kfree(ec);
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun 
ebs_map(struct dm_target * ti,struct bio * bio)359*4882a593Smuzhiyun static int ebs_map(struct dm_target *ti, struct bio *bio)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun 	struct ebs_c *ec = ti->private;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	bio_set_dev(bio, ec->dev->bdev);
364*4882a593Smuzhiyun 	bio->bi_iter.bi_sector = ec->start + dm_target_offset(ti, bio->bi_iter.bi_sector);
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	if (unlikely(bio_op(bio) == REQ_OP_FLUSH))
367*4882a593Smuzhiyun 		return DM_MAPIO_REMAPPED;
368*4882a593Smuzhiyun 	/*
369*4882a593Smuzhiyun 	 * Only queue for bufio processing in case of partial or overlapping buffers
370*4882a593Smuzhiyun 	 * -or-
371*4882a593Smuzhiyun 	 * emulation with ebs == ubs aiming for tests of dm-bufio overhead.
372*4882a593Smuzhiyun 	 */
373*4882a593Smuzhiyun 	if (likely(__block_mod(bio->bi_iter.bi_sector, ec->u_bs) ||
374*4882a593Smuzhiyun 		   __block_mod(bio_end_sector(bio), ec->u_bs) ||
375*4882a593Smuzhiyun 		   ec->e_bs == ec->u_bs)) {
376*4882a593Smuzhiyun 		spin_lock_irq(&ec->lock);
377*4882a593Smuzhiyun 		bio_list_add(&ec->bios_in, bio);
378*4882a593Smuzhiyun 		spin_unlock_irq(&ec->lock);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 		queue_work(ec->wq, &ec->ws);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 		return DM_MAPIO_SUBMITTED;
383*4882a593Smuzhiyun 	}
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	/* Forget any buffer content relative to this direct backing device I/O. */
386*4882a593Smuzhiyun 	__ebs_forget_bio(ec, bio);
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	return DM_MAPIO_REMAPPED;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun 
ebs_status(struct dm_target * ti,status_type_t type,unsigned status_flags,char * result,unsigned maxlen)391*4882a593Smuzhiyun static void ebs_status(struct dm_target *ti, status_type_t type,
392*4882a593Smuzhiyun 		       unsigned status_flags, char *result, unsigned maxlen)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	struct ebs_c *ec = ti->private;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	switch (type) {
397*4882a593Smuzhiyun 	case STATUSTYPE_INFO:
398*4882a593Smuzhiyun 		*result = '\0';
399*4882a593Smuzhiyun 		break;
400*4882a593Smuzhiyun 	case STATUSTYPE_TABLE:
401*4882a593Smuzhiyun 		snprintf(result, maxlen, ec->u_bs_set ? "%s %llu %u %u" : "%s %llu %u",
402*4882a593Smuzhiyun 			 ec->dev->name, (unsigned long long) ec->start, ec->e_bs, ec->u_bs);
403*4882a593Smuzhiyun 		break;
404*4882a593Smuzhiyun 	}
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun 
ebs_prepare_ioctl(struct dm_target * ti,struct block_device ** bdev)407*4882a593Smuzhiyun static int ebs_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	struct ebs_c *ec = ti->private;
410*4882a593Smuzhiyun 	struct dm_dev *dev = ec->dev;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	/*
413*4882a593Smuzhiyun 	 * Only pass ioctls through if the device sizes match exactly.
414*4882a593Smuzhiyun 	 */
415*4882a593Smuzhiyun 	*bdev = dev->bdev;
416*4882a593Smuzhiyun 	return !!(ec->start || ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun 
ebs_io_hints(struct dm_target * ti,struct queue_limits * limits)419*4882a593Smuzhiyun static void ebs_io_hints(struct dm_target *ti, struct queue_limits *limits)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun 	struct ebs_c *ec = ti->private;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	limits->logical_block_size = to_bytes(ec->e_bs);
424*4882a593Smuzhiyun 	limits->physical_block_size = to_bytes(ec->u_bs);
425*4882a593Smuzhiyun 	limits->alignment_offset = limits->physical_block_size;
426*4882a593Smuzhiyun 	blk_limits_io_min(limits, limits->logical_block_size);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
ebs_iterate_devices(struct dm_target * ti,iterate_devices_callout_fn fn,void * data)429*4882a593Smuzhiyun static int ebs_iterate_devices(struct dm_target *ti,
430*4882a593Smuzhiyun 				  iterate_devices_callout_fn fn, void *data)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun 	struct ebs_c *ec = ti->private;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	return fn(ti, ec->dev, ec->start, ti->len, data);
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun static struct target_type ebs_target = {
438*4882a593Smuzhiyun 	.name		 = "ebs",
439*4882a593Smuzhiyun 	.version	 = {1, 0, 1},
440*4882a593Smuzhiyun 	.features	 = DM_TARGET_PASSES_INTEGRITY,
441*4882a593Smuzhiyun 	.module		 = THIS_MODULE,
442*4882a593Smuzhiyun 	.ctr		 = ebs_ctr,
443*4882a593Smuzhiyun 	.dtr		 = ebs_dtr,
444*4882a593Smuzhiyun 	.map		 = ebs_map,
445*4882a593Smuzhiyun 	.status		 = ebs_status,
446*4882a593Smuzhiyun 	.io_hints	 = ebs_io_hints,
447*4882a593Smuzhiyun 	.prepare_ioctl	 = ebs_prepare_ioctl,
448*4882a593Smuzhiyun 	.iterate_devices = ebs_iterate_devices,
449*4882a593Smuzhiyun };
450*4882a593Smuzhiyun 
dm_ebs_init(void)451*4882a593Smuzhiyun static int __init dm_ebs_init(void)
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun 	int r = dm_register_target(&ebs_target);
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	if (r < 0)
456*4882a593Smuzhiyun 		DMERR("register failed %d", r);
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	return r;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
dm_ebs_exit(void)461*4882a593Smuzhiyun static void dm_ebs_exit(void)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun 	dm_unregister_target(&ebs_target);
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun module_init(dm_ebs_init);
467*4882a593Smuzhiyun module_exit(dm_ebs_exit);
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun MODULE_AUTHOR("Heinz Mauelshagen <dm-devel@redhat.com>");
470*4882a593Smuzhiyun MODULE_DESCRIPTION(DM_NAME " emulated block size target");
471*4882a593Smuzhiyun MODULE_LICENSE("GPL");
472