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

dm bufio: implement discard

Add functions dm_bufio_issue_discard and dm_bufio_discard_buffers.
dm_bufio_issue_discard sends discard request to the underlying device.
dm_bufio_discard_buffers frees buffers in the range and then calls
dm_bufio_issue_discard.

Also, factor out block_to_sector for reuse in dm_bufio_issue_discard.

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
6fbeb004 d3c7b35c

+76 -5
+64 -5
drivers/md/dm-bufio.c
··· 631 631 submit_bio(bio); 632 632 } 633 633 634 + static inline sector_t block_to_sector(struct dm_bufio_client *c, sector_t block) 635 + { 636 + sector_t sector; 637 + 638 + if (likely(c->sectors_per_block_bits >= 0)) 639 + sector = block << c->sectors_per_block_bits; 640 + else 641 + sector = block * (c->block_size >> SECTOR_SHIFT); 642 + sector += c->start; 643 + 644 + return sector; 645 + } 646 + 634 647 static void submit_io(struct dm_buffer *b, int rw, void (*end_io)(struct dm_buffer *, blk_status_t)) 635 648 { 636 649 unsigned n_sectors; ··· 652 639 653 640 b->end_io = end_io; 654 641 655 - if (likely(b->c->sectors_per_block_bits >= 0)) 656 - sector = b->block << b->c->sectors_per_block_bits; 657 - else 658 - sector = b->block * (b->c->block_size >> SECTOR_SHIFT); 659 - sector += b->c->start; 642 + sector = block_to_sector(b->c, b->block); 660 643 661 644 if (rw != REQ_OP_WRITE) { 662 645 n_sectors = b->c->block_size >> SECTOR_SHIFT; ··· 1333 1324 return dm_io(&io_req, 1, &io_reg, NULL); 1334 1325 } 1335 1326 EXPORT_SYMBOL_GPL(dm_bufio_issue_flush); 1327 + 1328 + /* 1329 + * Use dm-io to send a discard request to flush the device. 1330 + */ 1331 + int dm_bufio_issue_discard(struct dm_bufio_client *c, sector_t block, sector_t count) 1332 + { 1333 + struct dm_io_request io_req = { 1334 + .bi_op = REQ_OP_DISCARD, 1335 + .bi_op_flags = REQ_SYNC, 1336 + .mem.type = DM_IO_KMEM, 1337 + .mem.ptr.addr = NULL, 1338 + .client = c->dm_io, 1339 + }; 1340 + struct dm_io_region io_reg = { 1341 + .bdev = c->bdev, 1342 + .sector = block_to_sector(c, block), 1343 + .count = block_to_sector(c, count), 1344 + }; 1345 + 1346 + BUG_ON(dm_bufio_in_request()); 1347 + 1348 + return dm_io(&io_req, 1, &io_reg, NULL); 1349 + } 1350 + EXPORT_SYMBOL_GPL(dm_bufio_issue_discard); 1351 + 1352 + /* 1353 + * Free the specified range of buffers. If a buffer is held by other process, it 1354 + * is not freed. If a buffer is dirty, it is discarded without writeback. 1355 + * Finally, send the discard request to the device. 1356 + */ 1357 + int dm_bufio_discard_buffers(struct dm_bufio_client *c, sector_t block, sector_t count) 1358 + { 1359 + sector_t i; 1360 + 1361 + for (i = block; i < block + count; i++) { 1362 + struct dm_buffer *b; 1363 + dm_bufio_lock(c); 1364 + b = __find(c, i); 1365 + if (b && likely(!b->hold_count)) { 1366 + wait_on_bit_io(&b->state, B_READING, TASK_UNINTERRUPTIBLE); 1367 + wait_on_bit_io(&b->state, B_WRITING, TASK_UNINTERRUPTIBLE); 1368 + __unlink_buffer(b); 1369 + __free_buffer_wake(b); 1370 + } 1371 + dm_bufio_unlock(c); 1372 + } 1373 + 1374 + return dm_bufio_issue_discard(c, block, count); 1375 + } 1376 + EXPORT_SYMBOL_GPL(dm_bufio_discard_buffers); 1336 1377 1337 1378 /* 1338 1379 * We first delete any other buffer that may be at that new location.
+12
include/linux/dm-bufio.h
··· 119 119 int dm_bufio_issue_flush(struct dm_bufio_client *c); 120 120 121 121 /* 122 + * Send a discard request to the underlying device. 123 + */ 124 + int dm_bufio_issue_discard(struct dm_bufio_client *c, sector_t block, sector_t count); 125 + 126 + /* 127 + * Free the specified range of buffers. If a buffer is held by other process, it 128 + * is not freed. If a buffer is dirty, it is discarded without writeback. 129 + * Finally, send the discard request to the device. 130 + */ 131 + int dm_bufio_discard_buffers(struct dm_bufio_client *c, sector_t block, sector_t count); 132 + 133 + /* 122 134 * Like dm_bufio_release but also move the buffer to the new 123 135 * block. dm_bufio_write_dirty_buffers is needed to commit the new block. 124 136 */