@@ -278,6 +278,8 @@ struct dm_integrity_c {
278278
279279 atomic64_t number_of_mismatches ;
280280
281+ mempool_t recheck_pool ;
282+
281283 struct notifier_block reboot_notifier ;
282284};
283285
@@ -1689,6 +1691,79 @@ static void integrity_sector_checksum(struct dm_integrity_c *ic, sector_t sector
16891691 get_random_bytes (result , ic -> tag_size );
16901692}
16911693
1694+ static void integrity_recheck (struct dm_integrity_io * dio )
1695+ {
1696+ struct bio * bio = dm_bio_from_per_bio_data (dio , sizeof (struct dm_integrity_io ));
1697+ struct dm_integrity_c * ic = dio -> ic ;
1698+ struct bvec_iter iter ;
1699+ struct bio_vec bv ;
1700+ sector_t sector , logical_sector , area , offset ;
1701+ char checksum_onstack [max_t (size_t , HASH_MAX_DIGESTSIZE , MAX_TAG_SIZE )];
1702+ struct page * page ;
1703+ void * buffer ;
1704+
1705+ get_area_and_offset (ic , dio -> range .logical_sector , & area , & offset );
1706+ dio -> metadata_block = get_metadata_sector_and_offset (ic , area , offset ,
1707+ & dio -> metadata_offset );
1708+ sector = get_data_sector (ic , area , offset );
1709+ logical_sector = dio -> range .logical_sector ;
1710+
1711+ page = mempool_alloc (& ic -> recheck_pool , GFP_NOIO );
1712+ buffer = page_to_virt (page );
1713+
1714+ __bio_for_each_segment (bv , bio , iter , dio -> bio_details .bi_iter ) {
1715+ unsigned pos = 0 ;
1716+
1717+ do {
1718+ char * mem ;
1719+ int r ;
1720+ struct dm_io_request io_req ;
1721+ struct dm_io_region io_loc ;
1722+ io_req .bi_opf = REQ_OP_READ ;
1723+ io_req .mem .type = DM_IO_KMEM ;
1724+ io_req .mem .ptr .addr = buffer ;
1725+ io_req .notify .fn = NULL ;
1726+ io_req .client = ic -> io ;
1727+ io_loc .bdev = ic -> dev -> bdev ;
1728+ io_loc .sector = sector ;
1729+ io_loc .count = ic -> sectors_per_block ;
1730+
1731+ r = dm_io (& io_req , 1 , & io_loc , NULL );
1732+ if (unlikely (r )) {
1733+ dio -> bi_status = errno_to_blk_status (r );
1734+ goto free_ret ;
1735+ }
1736+
1737+ integrity_sector_checksum (ic , logical_sector , buffer ,
1738+ checksum_onstack );
1739+ r = dm_integrity_rw_tag (ic , checksum_onstack , & dio -> metadata_block ,
1740+ & dio -> metadata_offset , ic -> tag_size , TAG_CMP );
1741+ if (r ) {
1742+ if (r > 0 ) {
1743+ DMERR_LIMIT ("%pg: Checksum failed at sector 0x%llx" ,
1744+ bio -> bi_bdev , logical_sector );
1745+ atomic64_inc (& ic -> number_of_mismatches );
1746+ dm_audit_log_bio (DM_MSG_PREFIX , "integrity-checksum" ,
1747+ bio , logical_sector , 0 );
1748+ r = - EILSEQ ;
1749+ }
1750+ dio -> bi_status = errno_to_blk_status (r );
1751+ goto free_ret ;
1752+ }
1753+
1754+ mem = bvec_kmap_local (& bv );
1755+ memcpy (mem + pos , buffer , ic -> sectors_per_block << SECTOR_SHIFT );
1756+ kunmap_local (mem );
1757+
1758+ pos += ic -> sectors_per_block << SECTOR_SHIFT ;
1759+ sector += ic -> sectors_per_block ;
1760+ logical_sector += ic -> sectors_per_block ;
1761+ } while (pos < bv .bv_len );
1762+ }
1763+ free_ret :
1764+ mempool_free (page , & ic -> recheck_pool );
1765+ }
1766+
16921767static void integrity_metadata (struct work_struct * w )
16931768{
16941769 struct dm_integrity_io * dio = container_of (w , struct dm_integrity_io , work );
@@ -1776,15 +1851,8 @@ static void integrity_metadata(struct work_struct *w)
17761851 checksums_ptr - checksums , dio -> op == REQ_OP_READ ? TAG_CMP : TAG_WRITE );
17771852 if (unlikely (r )) {
17781853 if (r > 0 ) {
1779- sector_t s ;
1780-
1781- s = sector - ((r + ic -> tag_size - 1 ) / ic -> tag_size );
1782- DMERR_LIMIT ("%pg: Checksum failed at sector 0x%llx" ,
1783- bio -> bi_bdev , s );
1784- r = - EILSEQ ;
1785- atomic64_inc (& ic -> number_of_mismatches );
1786- dm_audit_log_bio (DM_MSG_PREFIX , "integrity-checksum" ,
1787- bio , s , 0 );
1854+ integrity_recheck (dio );
1855+ goto skip_io ;
17881856 }
17891857 if (likely (checksums != checksums_onstack ))
17901858 kfree (checksums );
@@ -4261,6 +4329,12 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv
42614329 goto bad ;
42624330 }
42634331
4332+ r = mempool_init_page_pool (& ic -> recheck_pool , 1 , 0 );
4333+ if (r ) {
4334+ ti -> error = "Cannot allocate mempool" ;
4335+ goto bad ;
4336+ }
4337+
42644338 ic -> metadata_wq = alloc_workqueue ("dm-integrity-metadata" ,
42654339 WQ_MEM_RECLAIM , METADATA_WORKQUEUE_MAX_ACTIVE );
42664340 if (!ic -> metadata_wq ) {
@@ -4609,6 +4683,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
46094683 kvfree (ic -> bbs );
46104684 if (ic -> bufio )
46114685 dm_bufio_client_destroy (ic -> bufio );
4686+ mempool_exit (& ic -> recheck_pool );
46124687 mempool_exit (& ic -> journal_io_mempool );
46134688 if (ic -> io )
46144689 dm_io_client_destroy (ic -> io );
0 commit comments