diff options
Diffstat (limited to 'drivers/md/dm-ebs-target.c')
| -rw-r--r-- | drivers/md/dm-ebs-target.c | 76 |
1 files changed, 36 insertions, 40 deletions
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c index 44451276f128..6abb31ca9662 100644 --- a/drivers/md/dm-ebs-target.c +++ b/drivers/md/dm-ebs-target.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2020 Red Hat GmbH * @@ -28,7 +29,7 @@ struct ebs_c { spinlock_t lock; /* Guard bios input list above. */ sector_t start; /* <start> table line argument, see ebs_ctr below. */ unsigned int e_bs; /* Emulated block size in sectors exposed to upper layer. */ - unsigned int u_bs; /* Underlying block size in sectors retrievd from/set on lower layer device. */ + unsigned int u_bs; /* Underlying block size in sectors retrieved from/set on lower layer device. */ unsigned char block_shift; /* bitshift sectors -> blocks used in dm-bufio API. */ bool u_bs_set:1; /* Flag to indicate underlying block size is set on table line. */ }; @@ -43,7 +44,7 @@ static inline sector_t __block_mod(sector_t sector, unsigned int bs) return sector & (bs - 1); } -/* Return number of blocks for a bio, accounting for misalignement of start and end sectors. */ +/* Return number of blocks for a bio, accounting for misalignment of start and end sectors. */ static inline unsigned int __nr_blocks(struct ebs_c *ec, struct bio *bio) { sector_t end_sector = __block_mod(bio->bi_iter.bi_sector, ec->u_bs) + bio_sectors(bio); @@ -61,7 +62,8 @@ static inline bool __ebs_check_bs(unsigned int bs) * * copy blocks between bufio blocks and bio vector's (partial/overlapping) pages. */ -static int __ebs_rw_bvec(struct ebs_c *ec, int rw, struct bio_vec *bv, struct bvec_iter *iter) +static int __ebs_rw_bvec(struct ebs_c *ec, enum req_op op, struct bio_vec *bv, + struct bvec_iter *iter) { int r = 0; unsigned char *ba, *pa; @@ -74,19 +76,19 @@ static int __ebs_rw_bvec(struct ebs_c *ec, int rw, struct bio_vec *bv, struct bv if (unlikely(!bv->bv_page || !bv_len)) return -EIO; - pa = page_address(bv->bv_page) + bv->bv_offset; + pa = bvec_virt(bv); /* Handle overlapping page <-> blocks */ while (bv_len) { cur_len = min(dm_bufio_get_block_size(ec->bufio) - buf_off, bv_len); /* Avoid reading for writes in case bio vector's page overwrites block completely. */ - if (rw == READ || buf_off || bv_len < dm_bufio_get_block_size(ec->bufio)) + if (op == REQ_OP_READ || buf_off || bv_len < dm_bufio_get_block_size(ec->bufio)) ba = dm_bufio_read(ec->bufio, block, &b); else ba = dm_bufio_new(ec->bufio, block, &b); - if (unlikely(IS_ERR(ba))) { + if (IS_ERR(ba)) { /* * Carry on with next buffer, if any, to issue all possible * data but return error. @@ -95,7 +97,7 @@ static int __ebs_rw_bvec(struct ebs_c *ec, int rw, struct bio_vec *bv, struct bv } else { /* Copy data to/from bio to buffer if read/new was successful above. */ ba += buf_off; - if (rw == READ) { + if (op == REQ_OP_READ) { memcpy(pa, ba, cur_len); flush_dcache_page(bv->bv_page); } else { @@ -117,14 +119,14 @@ static int __ebs_rw_bvec(struct ebs_c *ec, int rw, struct bio_vec *bv, struct bv } /* READ/WRITE: iterate bio vector's copying between (partial) pages and bufio blocks. */ -static int __ebs_rw_bio(struct ebs_c *ec, int rw, struct bio *bio) +static int __ebs_rw_bio(struct ebs_c *ec, enum req_op op, struct bio *bio) { int r = 0, rr; struct bio_vec bv; struct bvec_iter iter; bio_for_each_bvec(bv, bio, iter) { - rr = __ebs_rw_bvec(ec, rw, &bv, &iter); + rr = __ebs_rw_bvec(ec, op, &bv, &iter); if (rr) r = rr; } @@ -171,7 +173,7 @@ static void __ebs_forget_bio(struct ebs_c *ec, struct bio *bio) dm_bufio_forget_buffers(ec->bufio, __sector_to_block(ec, sector), blocks); } -/* Worker funtion to process incoming bios. */ +/* Worker function to process incoming bios. */ static void __ebs_process_bios(struct work_struct *ws) { int r; @@ -205,10 +207,10 @@ static void __ebs_process_bios(struct work_struct *ws) bio_list_for_each(bio, &bios) { r = -EIO; if (bio_op(bio) == REQ_OP_READ) - r = __ebs_rw_bio(ec, READ, bio); + r = __ebs_rw_bio(ec, REQ_OP_READ, bio); else if (bio_op(bio) == REQ_OP_WRITE) { write = true; - r = __ebs_rw_bio(ec, WRITE, bio); + r = __ebs_rw_bio(ec, REQ_OP_WRITE, bio); } else if (bio_op(bio) == REQ_OP_DISCARD) { __ebs_forget_bio(ec, bio); r = __ebs_discard_bio(ec, bio); @@ -240,7 +242,7 @@ static void __ebs_process_bios(struct work_struct *ws) * <offset>: offset in 512 bytes sectors into <dev_path> * <ebs>: emulated block size in units of 512 bytes exposed to the upper layer * [<ubs>]: underlying block size in units of 512 bytes imposed on the lower layer; - * optional, if not supplied, retrieve logical block size from underlying device + * optional, if not supplied, retrieve logical block size from underlying device */ static int ebs_ctr(struct dm_target *ti, unsigned int argc, char **argv) { @@ -312,7 +314,8 @@ static int ebs_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad; } - ec->bufio = dm_bufio_client_create(ec->dev->bdev, to_bytes(ec->u_bs), 1, 0, NULL, NULL); + ec->bufio = dm_bufio_client_create(ec->dev->bdev, to_bytes(ec->u_bs), 1, + 0, NULL, NULL, 0); if (IS_ERR(ec->bufio)) { ti->error = "Cannot create dm bufio client"; r = PTR_ERR(ec->bufio); @@ -335,7 +338,6 @@ static int ebs_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->num_flush_bios = 1; ti->num_discard_bios = 1; ti->num_secure_erase_bios = 0; - ti->num_write_same_bios = 0; ti->num_write_zeroes_bios = 0; return 0; bad: @@ -363,7 +365,7 @@ static int ebs_map(struct dm_target *ti, struct bio *bio) bio_set_dev(bio, ec->dev->bdev); bio->bi_iter.bi_sector = ec->start + dm_target_offset(ti, bio->bi_iter.bi_sector); - if (unlikely(bio->bi_opf & REQ_OP_FLUSH)) + if (unlikely(bio_op(bio) == REQ_OP_FLUSH)) return DM_MAPIO_REMAPPED; /* * Only queue for bufio processing in case of partial or overlapping buffers @@ -388,8 +390,14 @@ static int ebs_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_REMAPPED; } +static void ebs_postsuspend(struct dm_target *ti) +{ + struct ebs_c *ec = ti->private; + dm_bufio_client_reset(ec->bufio); +} + static void ebs_status(struct dm_target *ti, status_type_t type, - unsigned status_flags, char *result, unsigned maxlen) + unsigned int status_flags, char *result, unsigned int maxlen) { struct ebs_c *ec = ti->private; @@ -401,10 +409,14 @@ static void ebs_status(struct dm_target *ti, status_type_t type, snprintf(result, maxlen, ec->u_bs_set ? "%s %llu %u %u" : "%s %llu %u", ec->dev->name, (unsigned long long) ec->start, ec->e_bs, ec->u_bs); break; + case STATUSTYPE_IMA: + *result = '\0'; + break; } } -static int ebs_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) +static int ebs_prepare_ioctl(struct dm_target *ti, struct block_device **bdev, + unsigned int cmd, unsigned long arg, bool *forward) { struct ebs_c *ec = ti->private; struct dm_dev *dev = ec->dev; @@ -413,7 +425,7 @@ static int ebs_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) * Only pass ioctls through if the device sizes match exactly. */ *bdev = dev->bdev; - return !!(ec->start || ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT); + return !!(ec->start || ti->len != bdev_nr_sectors(dev->bdev)); } static void ebs_io_hints(struct dm_target *ti, struct queue_limits *limits) @@ -423,7 +435,7 @@ static void ebs_io_hints(struct dm_target *ti, struct queue_limits *limits) limits->logical_block_size = to_bytes(ec->e_bs); limits->physical_block_size = to_bytes(ec->u_bs); limits->alignment_offset = limits->physical_block_size; - blk_limits_io_min(limits, limits->logical_block_size); + limits->io_min = limits->logical_block_size; } static int ebs_iterate_devices(struct dm_target *ti, @@ -437,35 +449,19 @@ static int ebs_iterate_devices(struct dm_target *ti, static struct target_type ebs_target = { .name = "ebs", .version = {1, 0, 1}, - .features = DM_TARGET_PASSES_INTEGRITY, + .features = 0, .module = THIS_MODULE, .ctr = ebs_ctr, .dtr = ebs_dtr, .map = ebs_map, + .postsuspend = ebs_postsuspend, .status = ebs_status, .io_hints = ebs_io_hints, .prepare_ioctl = ebs_prepare_ioctl, .iterate_devices = ebs_iterate_devices, }; +module_dm(ebs); -static int __init dm_ebs_init(void) -{ - int r = dm_register_target(&ebs_target); - - if (r < 0) - DMERR("register failed %d", r); - - return r; -} - -static void dm_ebs_exit(void) -{ - dm_unregister_target(&ebs_target); -} - -module_init(dm_ebs_init); -module_exit(dm_ebs_exit); - -MODULE_AUTHOR("Heinz Mauelshagen <dm-devel@redhat.com>"); +MODULE_AUTHOR("Heinz Mauelshagen <dm-devel@lists.linux.dev>"); MODULE_DESCRIPTION(DM_NAME " emulated block size target"); MODULE_LICENSE("GPL"); |
