Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mikulas Patocka and committed by
Mike Snitzer
298eaa89 599cdf3b

+15 -3
+15 -3
drivers/md/dm-snap.c
··· 2143 2143 2144 2144 struct dm_origin { 2145 2145 struct dm_dev *dev; 2146 + unsigned split_boundary; 2146 2147 }; 2147 2148 2148 2149 /* ··· 2195 2194 static int origin_map(struct dm_target *ti, struct bio *bio) 2196 2195 { 2197 2196 struct dm_origin *o = ti->private; 2197 + unsigned available_sectors; 2198 + 2198 2199 bio->bi_bdev = o->dev->bdev; 2199 2200 2200 - if (bio->bi_rw & REQ_FLUSH) 2201 + if (unlikely(bio->bi_rw & REQ_FLUSH)) 2201 2202 return DM_MAPIO_REMAPPED; 2202 2203 2204 + if (bio_rw(bio) != WRITE) 2205 + return DM_MAPIO_REMAPPED; 2206 + 2207 + available_sectors = o->split_boundary - 2208 + ((unsigned)bio->bi_iter.bi_sector & (o->split_boundary - 1)); 2209 + 2210 + if (bio_sectors(bio) > available_sectors) 2211 + dm_accept_partial_bio(bio, available_sectors); 2212 + 2203 2213 /* Only tell snapshots if this is a write */ 2204 - return (bio_rw(bio) == WRITE) ? do_origin(o->dev, bio) : DM_MAPIO_REMAPPED; 2214 + return do_origin(o->dev, bio); 2205 2215 } 2206 2216 2207 2217 /* ··· 2223 2211 { 2224 2212 struct dm_origin *o = ti->private; 2225 2213 2226 - ti->max_io_len = get_origin_minimum_chunksize(o->dev->bdev); 2214 + o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev); 2227 2215 } 2228 2216 2229 2217 static void origin_status(struct dm_target *ti, status_type_t type,