dm.c (5eac3eb30c9ab9ee7fe2bd9aa9db6373cabb77f8) dm.c (d41003513e61dd9d4974cb441d30b63650b85654)
1/*
2 * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
3 * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
4 *
5 * This file is released under the GPL.
6 */
7
8#include "dm-core.h"

--- 426 unchanged lines hidden (view full) ---

435
436static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
437{
438 struct mapped_device *md = bdev->bd_disk->private_data;
439
440 return dm_get_geometry(md, geo);
441}
442
1/*
2 * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
3 * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
4 *
5 * This file is released under the GPL.
6 */
7
8#include "dm-core.h"

--- 426 unchanged lines hidden (view full) ---

435
436static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
437{
438 struct mapped_device *md = bdev->bd_disk->private_data;
439
440 return dm_get_geometry(md, geo);
441}
442
443#ifdef CONFIG_BLK_DEV_ZONED
444int dm_report_zones_cb(struct blk_zone *zone, unsigned int idx, void *data)
445{
446 struct dm_report_zones_args *args = data;
447 sector_t sector_diff = args->tgt->begin - args->start;
448
449 /*
450 * Ignore zones beyond the target range.
451 */
452 if (zone->start >= args->start + args->tgt->len)
453 return 0;
454
455 /*
456 * Remap the start sector and write pointer position of the zone
457 * to match its position in the target range.
458 */
459 zone->start += sector_diff;
460 if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) {
461 if (zone->cond == BLK_ZONE_COND_FULL)
462 zone->wp = zone->start + zone->len;
463 else if (zone->cond == BLK_ZONE_COND_EMPTY)
464 zone->wp = zone->start;
465 else
466 zone->wp += sector_diff;
467 }
468
469 args->next_sector = zone->start + zone->len;
470 return args->orig_cb(zone, args->zone_idx++, args->orig_data);
471}
472EXPORT_SYMBOL_GPL(dm_report_zones_cb);
473
443static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
474static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
444 struct blk_zone *zones, unsigned int *nr_zones)
475 unsigned int nr_zones, report_zones_cb cb, void *data)
445{
476{
446#ifdef CONFIG_BLK_DEV_ZONED
447 struct mapped_device *md = disk->private_data;
477 struct mapped_device *md = disk->private_data;
448 struct dm_target *tgt;
449 struct dm_table *map;
450 int srcu_idx, ret;
478 struct dm_table *map;
479 int srcu_idx, ret;
480 struct dm_report_zones_args args = {
481 .next_sector = sector,
482 .orig_data = data,
483 .orig_cb = cb,
484 };
451
452 if (dm_suspended_md(md))
453 return -EAGAIN;
454
455 map = dm_get_live_table(md, &srcu_idx);
456 if (!map)
457 return -EIO;
458
485
486 if (dm_suspended_md(md))
487 return -EAGAIN;
488
489 map = dm_get_live_table(md, &srcu_idx);
490 if (!map)
491 return -EIO;
492
459 tgt = dm_table_find_target(map, sector);
460 if (!tgt) {
461 ret = -EIO;
462 goto out;
463 }
493 do {
494 struct dm_target *tgt;
464
495
465 /*
466 * If we are executing this, we already know that the block device
467 * is a zoned device and so each target should have support for that
468 * type of drive. A missing report_zones method means that the target
469 * driver has a problem.
470 */
471 if (WARN_ON(!tgt->type->report_zones)) {
472 ret = -EIO;
473 goto out;
474 }
496 tgt = dm_table_find_target(map, args.next_sector);
497 if (WARN_ON_ONCE(!tgt->type->report_zones)) {
498 ret = -EIO;
499 goto out;
500 }
475
501
476 ret = tgt->type->report_zones(tgt, sector, zones, nr_zones);
502 args.tgt = tgt;
503 ret = tgt->type->report_zones(tgt, &args, nr_zones);
504 if (ret < 0)
505 goto out;
506 } while (args.zone_idx < nr_zones &&
507 args.next_sector < get_capacity(disk));
477
508
509 ret = args.zone_idx;
478out:
479 dm_put_live_table(md, srcu_idx);
480 return ret;
510out:
511 dm_put_live_table(md, srcu_idx);
512 return ret;
481#else
482 return -ENOTSUPP;
483#endif
484}
513}
514#else
515#define dm_blk_report_zones NULL
516#endif /* CONFIG_BLK_DEV_ZONED */
485
486static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
487 struct block_device **bdev)
488 __acquires(md->io_barrier)
489{
490 struct dm_target *tgt;
491 struct dm_table *map;
492 int r;

--- 709 unchanged lines hidden (view full) ---

1202 BUG_ON(bio->bi_opf & REQ_PREFLUSH);
1203 BUG_ON(bi_size > *tio->len_ptr);
1204 BUG_ON(n_sectors > bi_size);
1205 *tio->len_ptr -= bi_size - n_sectors;
1206 bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT;
1207}
1208EXPORT_SYMBOL_GPL(dm_accept_partial_bio);
1209
517
518static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
519 struct block_device **bdev)
520 __acquires(md->io_barrier)
521{
522 struct dm_target *tgt;
523 struct dm_table *map;
524 int r;

--- 709 unchanged lines hidden (view full) ---

1234 BUG_ON(bio->bi_opf & REQ_PREFLUSH);
1235 BUG_ON(bi_size > *tio->len_ptr);
1236 BUG_ON(n_sectors > bi_size);
1237 *tio->len_ptr -= bi_size - n_sectors;
1238 bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT;
1239}
1240EXPORT_SYMBOL_GPL(dm_accept_partial_bio);
1241
1210/*
1211 * The zone descriptors obtained with a zone report indicate
1212 * zone positions within the underlying device of the target. The zone
1213 * descriptors must be remapped to match their position within the dm device.
1214 */
1215void dm_remap_zone_report(struct dm_target *ti, sector_t start,
1216 struct blk_zone *zones, unsigned int *nr_zones)
1217{
1218#ifdef CONFIG_BLK_DEV_ZONED
1219 struct blk_zone *zone;
1220 unsigned int nrz = *nr_zones;
1221 int i;
1222
1223 /*
1224 * Remap the start sector and write pointer position of the zones in
1225 * the array. Since we may have obtained from the target underlying
1226 * device more zones that the target size, also adjust the number
1227 * of zones.
1228 */
1229 for (i = 0; i < nrz; i++) {
1230 zone = zones + i;
1231 if (zone->start >= start + ti->len) {
1232 memset(zone, 0, sizeof(struct blk_zone) * (nrz - i));
1233 break;
1234 }
1235
1236 zone->start = zone->start + ti->begin - start;
1237 if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
1238 continue;
1239
1240 if (zone->cond == BLK_ZONE_COND_FULL)
1241 zone->wp = zone->start + zone->len;
1242 else if (zone->cond == BLK_ZONE_COND_EMPTY)
1243 zone->wp = zone->start;
1244 else
1245 zone->wp = zone->wp + ti->begin - start;
1246 }
1247
1248 *nr_zones = i;
1249#else /* !CONFIG_BLK_DEV_ZONED */
1250 *nr_zones = 0;
1251#endif
1252}
1253EXPORT_SYMBOL_GPL(dm_remap_zone_report);
1254
1255static blk_qc_t __map_bio(struct dm_target_io *tio)
1256{
1257 int r;
1258 sector_t sector;
1259 struct bio *clone = &tio->clone;
1260 struct dm_io *io = tio->io;
1261 struct mapped_device *md = io->md;
1262 struct dm_target *ti = tio->ti;

--- 1967 unchanged lines hidden ---
1242static blk_qc_t __map_bio(struct dm_target_io *tio)
1243{
1244 int r;
1245 sector_t sector;
1246 struct bio *clone = &tio->clone;
1247 struct dm_io *io = tio->io;
1248 struct mapped_device *md = io->md;
1249 struct dm_target *ti = tio->ti;

--- 1967 unchanged lines hidden ---