| From a724fc89bee12a174edd74680f811a68f90f99c5 Mon Sep 17 00:00:00 2001 |
| From: Mike Snitzer <snitzer@redhat.com> |
| Date: Wed, 17 Jul 2019 11:12:30 -0400 |
| Subject: [PATCH] dm snapshot: fix oversights in optional discard support |
| |
| commit 3ee25485ba8e8271fe9401eef5003c20ab648ddf upstream. |
| |
| __find_snapshots_sharing_cow() should always be used with _origins_lock |
| held so fix snapshot_io_hints() accordingly. Also, once a snapshot is |
| being merged discards must not be allowed -- otherwise incorrect or |
| duplicate work will be performed. |
| |
| Fixes: 2e6023850e177d ("dm snapshot: add optional discard support features") |
| Reported-by: Nikos Tsironis <ntsironis@arrikto.com> |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c |
| index 63916e1dc569..f150f5c5492b 100644 |
| --- a/drivers/md/dm-snap.c |
| +++ b/drivers/md/dm-snap.c |
| @@ -2072,6 +2072,12 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio) |
| return DM_MAPIO_REMAPPED; |
| } |
| |
| + if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) { |
| + /* Once merging, discards no longer effect change */ |
| + bio_endio(bio); |
| + return DM_MAPIO_SUBMITTED; |
| + } |
| + |
| chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector); |
| |
| down_write(&s->lock); |
| @@ -2331,6 +2337,8 @@ static void snapshot_io_hints(struct dm_target *ti, struct queue_limits *limits) |
| if (snap->discard_zeroes_cow) { |
| struct dm_snapshot *snap_src = NULL, *snap_dest = NULL; |
| |
| + down_read(&_origins_lock); |
| + |
| (void) __find_snapshots_sharing_cow(snap, &snap_src, &snap_dest, NULL); |
| if (snap_src && snap_dest) |
| snap = snap_src; |
| @@ -2338,6 +2346,8 @@ static void snapshot_io_hints(struct dm_target *ti, struct queue_limits *limits) |
| /* All discards are split on chunk_size boundary */ |
| limits->discard_granularity = snap->store->chunk_size; |
| limits->max_discard_sectors = snap->store->chunk_size; |
| + |
| + up_read(&_origins_lock); |
| } |
| } |
| |
| -- |
| 2.7.4 |
| |