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