summaryrefslogtreecommitdiff
path: root/drivers/md/dm-snap.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2014-03-14 18:43:07 -0400
committerMike Snitzer <snitzer@redhat.com>2014-06-03 13:44:07 -0400
commit298eaa89b02e88dc9081f8761a957f7cd5e8b201 (patch)
tree19e9c438300cfee59abc6e499ab6bfaa872a9de5 /drivers/md/dm-snap.c
parent599cdf3bfbe21fe94f4416c9e54363b285c9532a (diff)
dm snapshot: do not split read bios sent to snapshot-origin target
Change the snapshot-origin target so that only write bios are split on chunk boundary. Read bios are passed unchanged to the underlying device, so they don't have to be split. Later, we could change the target so that it accepts a larger write bio if it spans an area that is completely covered by snapshot exceptions. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r--drivers/md/dm-snap.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 220a06bfe91b..e5a84c890e8f 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -2143,6 +2143,7 @@ static int origin_write_extent(struct dm_snapshot *merging_snap,
struct dm_origin {
struct dm_dev *dev;
+ unsigned split_boundary;
};
/*
@@ -2194,13 +2195,24 @@ static void origin_dtr(struct dm_target *ti)
static int origin_map(struct dm_target *ti, struct bio *bio)
{
struct dm_origin *o = ti->private;
+ unsigned available_sectors;
+
bio->bi_bdev = o->dev->bdev;
- if (bio->bi_rw & REQ_FLUSH)
+ if (unlikely(bio->bi_rw & REQ_FLUSH))
+ return DM_MAPIO_REMAPPED;
+
+ if (bio_rw(bio) != WRITE)
return DM_MAPIO_REMAPPED;
+ available_sectors = o->split_boundary -
+ ((unsigned)bio->bi_iter.bi_sector & (o->split_boundary - 1));
+
+ if (bio_sectors(bio) > available_sectors)
+ dm_accept_partial_bio(bio, available_sectors);
+
/* Only tell snapshots if this is a write */
- return (bio_rw(bio) == WRITE) ? do_origin(o->dev, bio) : DM_MAPIO_REMAPPED;
+ return do_origin(o->dev, bio);
}
/*
@@ -2211,7 +2223,7 @@ static void origin_resume(struct dm_target *ti)
{
struct dm_origin *o = ti->private;
- ti->max_io_len = get_origin_minimum_chunksize(o->dev->bdev);
+ o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev);
}
static void origin_status(struct dm_target *ti, status_type_t type,