dm-buffered: fix an off-by-one bug in _discard_blocks Suppose that bi_sector == 0, bio_end_sector == 8 and block size is 4k. start = 0 end = 1 n_blocks = end - start + 1 = 2 n_blocks is incorrect, it should be 1 in this case, the code would discard one-more sector. Fix this logic - we round bi_sector up to a block boundary (we round it down with _to_block and if it is not divisibe by block size, we add 1). - we round bio_end_sector down - we just call _to_block and nothing else. If start < end, there is something to discard. Signed-off-by: Mikulas Patocka --- drivers/md/dm-buffered-target.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) Index: linux-2.6/drivers/md/dm-buffered-target.c =================================================================== --- linux-2.6.orig/drivers/md/dm-buffered-target.c +++ linux-2.6/drivers/md/dm-buffered-target.c @@ -288,17 +288,11 @@ static void _discard_blocks(struct buffe if (_sector_mod(bc, bio->bi_iter.bi_sector)) start++; - if (_sector_mod(bc, bio_end_sector(bio))) { - if (!end) - /* Partial first block. */ - return; - end--; - } - - n_blocks = end - start + 1; - if (unlikely(!n_blocks)) + if (unlikely(start >= end)) return; + n_blocks = end - start; + /* ADDRESSME: dirty buffers won't be forgotten! */ dm_bufio_forget_buffers(bc->bufio, start, n_blocks); atomic_inc(&bc->stats[S_DISCARDS]);