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

dm-integrity: introduce the Inline mode

This commit introduces a new 'I' mode for dm-integrity.

The 'I' mode may be selected if the underlying device has non-power-of-2
sector size. In this mode, dm-integrity will store integrity data
directly in device's sectors and it will not use journal.

This mode improves performance and reduces flash wear because there would
be no journal writes.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>

+360 -46
+360 -46
drivers/md/dm-integrity.c
··· 44 44 #define BITMAP_FLUSH_INTERVAL (10 * HZ) 45 45 #define DISCARD_FILLER 0xf6 46 46 #define SALT_SIZE 16 47 + #define RECHECK_POOL_SIZE 256 47 48 48 49 /* 49 50 * Warning - DEBUG_PRINT prints security-sensitive data to the log, ··· 63 62 #define SB_VERSION_3 3 64 63 #define SB_VERSION_4 4 65 64 #define SB_VERSION_5 5 65 + #define SB_VERSION_6 6 66 66 #define SB_SECTORS 8 67 67 #define MAX_SECTORS_PER_BLOCK 8 68 68 ··· 88 86 #define SB_FLAG_DIRTY_BITMAP 0x4 89 87 #define SB_FLAG_FIXED_PADDING 0x8 90 88 #define SB_FLAG_FIXED_HMAC 0x10 89 + #define SB_FLAG_INLINE 0x20 91 90 92 91 #define JOURNAL_ENTRY_ROUNDUP 8 93 92 ··· 169 166 struct dm_dev *meta_dev; 170 167 unsigned int tag_size; 171 168 __s8 log2_tag_size; 169 + unsigned int tuple_size; 172 170 sector_t start; 173 171 mempool_t journal_io_mempool; 174 172 struct dm_io_client *io; ··· 283 279 atomic64_t number_of_mismatches; 284 280 285 281 mempool_t recheck_pool; 282 + struct bio_set recheck_bios; 286 283 287 284 struct notifier_block reboot_notifier; 288 285 }; ··· 319 314 struct completion *completion; 320 315 321 316 struct dm_bio_details bio_details; 317 + 318 + char *integrity_payload; 319 + bool integrity_payload_from_mempool; 322 320 }; 323 321 324 322 struct journal_completion { ··· 359 351 #endif 360 352 361 353 static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map); 354 + static int dm_integrity_map_inline(struct dm_integrity_io *dio); 362 355 static void integrity_bio_wait(struct work_struct *w); 363 356 static void dm_integrity_dtr(struct dm_target *ti); 364 357 ··· 469 460 470 461 static void sb_set_version(struct dm_integrity_c *ic) 471 462 { 472 - if (ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_HMAC)) 463 + if (ic->sb->flags & cpu_to_le32(SB_FLAG_INLINE)) 464 + ic->sb->version = SB_VERSION_6; 465 + else if (ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_HMAC)) 473 466 ic->sb->version = SB_VERSION_5; 474 467 else if (ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_PADDING)) 475 468 ic->sb->version = SB_VERSION_4; ··· 1905 1894 dec_in_flight(dio); 1906 1895 } 1907 1896 1897 + static inline bool dm_integrity_check_limits(struct dm_integrity_c *ic, sector_t logical_sector, struct bio *bio) 1898 + { 1899 + if (unlikely(logical_sector + bio_sectors(bio) > ic->provided_data_sectors)) { 1900 + DMERR("Too big sector number: 0x%llx + 0x%x > 0x%llx", 1901 + logical_sector, bio_sectors(bio), 1902 + ic->provided_data_sectors); 1903 + return false; 1904 + } 1905 + if (unlikely((logical_sector | bio_sectors(bio)) & (unsigned int)(ic->sectors_per_block - 1))) { 1906 + DMERR("Bio not aligned on %u sectors: 0x%llx, 0x%x", 1907 + ic->sectors_per_block, 1908 + logical_sector, bio_sectors(bio)); 1909 + return false; 1910 + } 1911 + if (ic->sectors_per_block > 1 && likely(bio_op(bio) != REQ_OP_DISCARD)) { 1912 + struct bvec_iter iter; 1913 + struct bio_vec bv; 1914 + 1915 + bio_for_each_segment(bv, bio, iter) { 1916 + if (unlikely(bv.bv_len & ((ic->sectors_per_block << SECTOR_SHIFT) - 1))) { 1917 + DMERR("Bio vector (%u,%u) is not aligned on %u-sector boundary", 1918 + bv.bv_offset, bv.bv_len, ic->sectors_per_block); 1919 + return false; 1920 + } 1921 + } 1922 + } 1923 + return true; 1924 + } 1925 + 1908 1926 static int dm_integrity_map(struct dm_target *ti, struct bio *bio) 1909 1927 { 1910 1928 struct dm_integrity_c *ic = ti->private; ··· 1945 1905 dio->ic = ic; 1946 1906 dio->bi_status = 0; 1947 1907 dio->op = bio_op(bio); 1908 + 1909 + if (ic->mode == 'I') 1910 + return dm_integrity_map_inline(dio); 1948 1911 1949 1912 if (unlikely(dio->op == REQ_OP_DISCARD)) { 1950 1913 if (ti->max_io_len) { ··· 1978 1935 */ 1979 1936 bio->bi_opf &= ~REQ_FUA; 1980 1937 } 1981 - if (unlikely(dio->range.logical_sector + bio_sectors(bio) > ic->provided_data_sectors)) { 1982 - DMERR("Too big sector number: 0x%llx + 0x%x > 0x%llx", 1983 - dio->range.logical_sector, bio_sectors(bio), 1984 - ic->provided_data_sectors); 1938 + if (unlikely(!dm_integrity_check_limits(ic, dio->range.logical_sector, bio))) 1985 1939 return DM_MAPIO_KILL; 1986 - } 1987 - if (unlikely((dio->range.logical_sector | bio_sectors(bio)) & (unsigned int)(ic->sectors_per_block - 1))) { 1988 - DMERR("Bio not aligned on %u sectors: 0x%llx, 0x%x", 1989 - ic->sectors_per_block, 1990 - dio->range.logical_sector, bio_sectors(bio)); 1991 - return DM_MAPIO_KILL; 1992 - } 1993 - 1994 - if (ic->sectors_per_block > 1 && likely(dio->op != REQ_OP_DISCARD)) { 1995 - struct bvec_iter iter; 1996 - struct bio_vec bv; 1997 - 1998 - bio_for_each_segment(bv, bio, iter) { 1999 - if (unlikely(bv.bv_len & ((ic->sectors_per_block << SECTOR_SHIFT) - 1))) { 2000 - DMERR("Bio vector (%u,%u) is not aligned on %u-sector boundary", 2001 - bv.bv_offset, bv.bv_len, ic->sectors_per_block); 2002 - return DM_MAPIO_KILL; 2003 - } 2004 - } 2005 - } 2006 1940 2007 1941 bip = bio_integrity(bio); 2008 1942 if (!ic->internal_hash) { ··· 2395 2375 do_endio_flush(ic, dio); 2396 2376 } 2397 2377 2378 + static int dm_integrity_map_inline(struct dm_integrity_io *dio) 2379 + { 2380 + struct dm_integrity_c *ic = dio->ic; 2381 + struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io)); 2382 + struct bio_integrity_payload *bip; 2383 + unsigned payload_len, digest_size, extra_size, ret; 2384 + 2385 + dio->integrity_payload = NULL; 2386 + dio->integrity_payload_from_mempool = false; 2387 + 2388 + if (unlikely(bio_integrity(bio))) { 2389 + bio->bi_status = BLK_STS_NOTSUPP; 2390 + bio_endio(bio); 2391 + return DM_MAPIO_SUBMITTED; 2392 + } 2393 + 2394 + bio_set_dev(bio, ic->dev->bdev); 2395 + if (unlikely((bio->bi_opf & REQ_PREFLUSH) != 0)) 2396 + return DM_MAPIO_REMAPPED; 2397 + 2398 + retry: 2399 + payload_len = ic->tuple_size * (bio_sectors(bio) >> ic->sb->log2_sectors_per_block); 2400 + digest_size = crypto_shash_digestsize(ic->internal_hash); 2401 + extra_size = unlikely(digest_size > ic->tag_size) ? digest_size - ic->tag_size : 0; 2402 + payload_len += extra_size; 2403 + dio->integrity_payload = kmalloc(payload_len, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); 2404 + if (unlikely(!dio->integrity_payload)) { 2405 + const unsigned x_size = PAGE_SIZE << 1; 2406 + if (payload_len > x_size) { 2407 + unsigned sectors = ((x_size - extra_size) / ic->tuple_size) << ic->sb->log2_sectors_per_block; 2408 + if (WARN_ON(!sectors || sectors >= bio_sectors(bio))) { 2409 + bio->bi_status = BLK_STS_NOTSUPP; 2410 + bio_endio(bio); 2411 + return DM_MAPIO_SUBMITTED; 2412 + } 2413 + dm_accept_partial_bio(bio, sectors); 2414 + goto retry; 2415 + } 2416 + dio->integrity_payload = page_to_virt((struct page *)mempool_alloc(&ic->recheck_pool, GFP_NOIO)); 2417 + dio->integrity_payload_from_mempool = true; 2418 + } 2419 + 2420 + bio->bi_iter.bi_sector = dm_target_offset(ic->ti, bio->bi_iter.bi_sector); 2421 + dio->bio_details.bi_iter = bio->bi_iter; 2422 + 2423 + if (unlikely(!dm_integrity_check_limits(ic, bio->bi_iter.bi_sector, bio))) { 2424 + return DM_MAPIO_KILL; 2425 + } 2426 + 2427 + bio->bi_iter.bi_sector += ic->start + SB_SECTORS; 2428 + 2429 + bip = bio_integrity_alloc(bio, GFP_NOIO, 1); 2430 + if (unlikely(IS_ERR(bip))) { 2431 + bio->bi_status = errno_to_blk_status(PTR_ERR(bip)); 2432 + bio_endio(bio); 2433 + return DM_MAPIO_SUBMITTED; 2434 + } 2435 + 2436 + if (dio->op == REQ_OP_WRITE) { 2437 + unsigned pos = 0; 2438 + while (dio->bio_details.bi_iter.bi_size) { 2439 + struct bio_vec bv = bio_iter_iovec(bio, dio->bio_details.bi_iter); 2440 + const char *mem = bvec_kmap_local(&bv); 2441 + if (ic->tag_size < ic->tuple_size) 2442 + memset(dio->integrity_payload + pos + ic->tag_size, 0, ic->tuple_size - ic->tuple_size); 2443 + integrity_sector_checksum(ic, dio->bio_details.bi_iter.bi_sector, mem, dio->integrity_payload + pos); 2444 + kunmap_local(mem); 2445 + pos += ic->tuple_size; 2446 + bio_advance_iter_single(bio, &dio->bio_details.bi_iter, ic->sectors_per_block << SECTOR_SHIFT); 2447 + } 2448 + } 2449 + 2450 + ret = bio_integrity_add_page(bio, virt_to_page(dio->integrity_payload), 2451 + payload_len, offset_in_page(dio->integrity_payload)); 2452 + if (unlikely(ret != payload_len)) { 2453 + bio->bi_status = BLK_STS_RESOURCE; 2454 + bio_endio(bio); 2455 + return DM_MAPIO_SUBMITTED; 2456 + } 2457 + 2458 + return DM_MAPIO_REMAPPED; 2459 + } 2460 + 2461 + static inline void dm_integrity_free_payload(struct dm_integrity_io *dio) 2462 + { 2463 + struct dm_integrity_c *ic = dio->ic; 2464 + if (unlikely(dio->integrity_payload_from_mempool)) 2465 + mempool_free(virt_to_page(dio->integrity_payload), &ic->recheck_pool); 2466 + else 2467 + kfree(dio->integrity_payload); 2468 + dio->integrity_payload = NULL; 2469 + dio->integrity_payload_from_mempool = false; 2470 + } 2471 + 2472 + static void dm_integrity_inline_recheck(struct work_struct *w) 2473 + { 2474 + struct dm_integrity_io *dio = container_of(w, struct dm_integrity_io, work); 2475 + struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io)); 2476 + struct dm_integrity_c *ic = dio->ic; 2477 + struct bio *outgoing_bio; 2478 + void *outgoing_data; 2479 + 2480 + dio->integrity_payload = page_to_virt((struct page *)mempool_alloc(&ic->recheck_pool, GFP_NOIO)); 2481 + dio->integrity_payload_from_mempool = true; 2482 + 2483 + outgoing_data = dio->integrity_payload + PAGE_SIZE; 2484 + 2485 + while (dio->bio_details.bi_iter.bi_size) { 2486 + char digest[HASH_MAX_DIGESTSIZE]; 2487 + int r; 2488 + struct bio_integrity_payload *bip; 2489 + struct bio_vec bv; 2490 + char *mem; 2491 + 2492 + outgoing_bio = bio_alloc_bioset(ic->dev->bdev, 1, REQ_OP_READ, GFP_NOIO, &ic->recheck_bios); 2493 + 2494 + r = bio_add_page(outgoing_bio, virt_to_page(outgoing_data), ic->sectors_per_block << SECTOR_SHIFT, 0); 2495 + if (unlikely(r != (ic->sectors_per_block << SECTOR_SHIFT))) { 2496 + bio_put(outgoing_bio); 2497 + bio->bi_status = BLK_STS_RESOURCE; 2498 + bio_endio(bio); 2499 + return; 2500 + } 2501 + 2502 + bip = bio_integrity_alloc(outgoing_bio, GFP_NOIO, 1); 2503 + if (unlikely(IS_ERR(bip))) { 2504 + bio_put(outgoing_bio); 2505 + bio->bi_status = errno_to_blk_status(PTR_ERR(bip)); 2506 + bio_endio(bio); 2507 + return; 2508 + } 2509 + 2510 + r = bio_integrity_add_page(outgoing_bio, virt_to_page(dio->integrity_payload), ic->tuple_size, 0); 2511 + if (unlikely(r != ic->tuple_size)) { 2512 + bio_put(outgoing_bio); 2513 + bio->bi_status = BLK_STS_RESOURCE; 2514 + bio_endio(bio); 2515 + return; 2516 + } 2517 + 2518 + outgoing_bio->bi_iter.bi_sector = dio->bio_details.bi_iter.bi_sector + ic->start + SB_SECTORS; 2519 + 2520 + r = submit_bio_wait(outgoing_bio); 2521 + if (unlikely(r != 0)) { 2522 + bio_put(outgoing_bio); 2523 + bio->bi_status = errno_to_blk_status(r); 2524 + bio_endio(bio); 2525 + return; 2526 + } 2527 + bio_put(outgoing_bio); 2528 + 2529 + integrity_sector_checksum(ic, dio->bio_details.bi_iter.bi_sector, outgoing_data, digest); 2530 + if (unlikely(memcmp(digest, dio->integrity_payload, min(crypto_shash_digestsize(ic->internal_hash), ic->tag_size)))) { 2531 + DMERR_LIMIT("%pg: Checksum failed at sector 0x%llx", 2532 + ic->dev->bdev, dio->bio_details.bi_iter.bi_sector); 2533 + atomic64_inc(&ic->number_of_mismatches); 2534 + dm_audit_log_bio(DM_MSG_PREFIX, "integrity-checksum", 2535 + bio, dio->bio_details.bi_iter.bi_sector, 0); 2536 + 2537 + bio->bi_status = BLK_STS_PROTECTION; 2538 + bio_endio(bio); 2539 + return; 2540 + } 2541 + 2542 + bv = bio_iter_iovec(bio, dio->bio_details.bi_iter); 2543 + mem = bvec_kmap_local(&bv); 2544 + memcpy(mem, outgoing_data, ic->sectors_per_block << SECTOR_SHIFT); 2545 + kunmap_local(mem); 2546 + 2547 + bio_advance_iter_single(bio, &dio->bio_details.bi_iter, ic->sectors_per_block << SECTOR_SHIFT); 2548 + } 2549 + 2550 + bio_endio(bio); 2551 + } 2552 + 2553 + static int dm_integrity_end_io(struct dm_target *ti, struct bio *bio, blk_status_t *status) 2554 + { 2555 + struct dm_integrity_c *ic = ti->private; 2556 + if (ic->mode == 'I') { 2557 + struct dm_integrity_io *dio = dm_per_bio_data(bio, sizeof(struct dm_integrity_io)); 2558 + if (dio->op == REQ_OP_READ && likely(*status == BLK_STS_OK)) { 2559 + unsigned pos = 0; 2560 + while (dio->bio_details.bi_iter.bi_size) { 2561 + char digest[HASH_MAX_DIGESTSIZE]; 2562 + struct bio_vec bv = bio_iter_iovec(bio, dio->bio_details.bi_iter); 2563 + char *mem = bvec_kmap_local(&bv); 2564 + //memset(mem, 0xff, ic->sectors_per_block << SECTOR_SHIFT); 2565 + integrity_sector_checksum(ic, dio->bio_details.bi_iter.bi_sector, mem, digest); 2566 + if (unlikely(memcmp(digest, dio->integrity_payload + pos, 2567 + min(crypto_shash_digestsize(ic->internal_hash), ic->tag_size)))) { 2568 + kunmap_local(mem); 2569 + dm_integrity_free_payload(dio); 2570 + INIT_WORK(&dio->work, dm_integrity_inline_recheck); 2571 + queue_work(ic->offload_wq, &dio->work); 2572 + return DM_ENDIO_INCOMPLETE; 2573 + } 2574 + kunmap_local(mem); 2575 + pos += ic->tuple_size; 2576 + bio_advance_iter_single(bio, &dio->bio_details.bi_iter, ic->sectors_per_block << SECTOR_SHIFT); 2577 + } 2578 + } 2579 + if (likely(dio->op == REQ_OP_READ) || likely(dio->op == REQ_OP_WRITE)) { 2580 + dm_integrity_free_payload(dio); 2581 + } 2582 + } 2583 + return DM_ENDIO_DONE; 2584 + } 2398 2585 2399 2586 static void integrity_bio_wait(struct work_struct *w) 2400 2587 { ··· 2639 2412 struct bio *flushes; 2640 2413 2641 2414 del_timer(&ic->autocommit_timer); 2415 + 2416 + if (ic->mode == 'I') 2417 + return; 2642 2418 2643 2419 spin_lock_irq(&ic->endio_wait.lock); 2644 2420 flushes = bio_list_get(&ic->flush_bio_list); ··· 3745 3515 return -EINVAL; 3746 3516 ic->initial_sectors = initial_sectors; 3747 3517 3748 - if (!ic->meta_dev) { 3518 + if (ic->mode == 'I') { 3519 + if (ic->initial_sectors + ic->provided_data_sectors > ic->meta_device_sectors) 3520 + return -EINVAL; 3521 + } else if (!ic->meta_dev) { 3749 3522 sector_t last_sector, last_area, last_offset; 3750 3523 3751 3524 /* we have to maintain excessive padding for compatibility with existing volumes */ ··· 3811 3578 3812 3579 memset(ic->sb, 0, SB_SECTORS << SECTOR_SHIFT); 3813 3580 memcpy(ic->sb->magic, SB_MAGIC, 8); 3581 + if (ic->mode == 'I') 3582 + ic->sb->flags |= cpu_to_le32(SB_FLAG_INLINE); 3814 3583 ic->sb->integrity_tag_size = cpu_to_le16(ic->tag_size); 3815 3584 ic->sb->log2_sectors_per_block = __ffs(ic->sectors_per_block); 3816 3585 if (ic->journal_mac_alg.alg_string) ··· 3822 3587 journal_sections = journal_sectors / ic->journal_section_sectors; 3823 3588 if (!journal_sections) 3824 3589 journal_sections = 1; 3590 + if (ic->mode == 'I') 3591 + journal_sections = 0; 3825 3592 3826 3593 if (ic->fix_hmac && (ic->internal_hash_alg.alg_string || ic->journal_mac_alg.alg_string)) { 3827 3594 ic->sb->flags |= cpu_to_le32(SB_FLAG_FIXED_HMAC); ··· 4372 4135 } 4373 4136 4374 4137 if (!strcmp(argv[3], "J") || !strcmp(argv[3], "B") || 4375 - !strcmp(argv[3], "D") || !strcmp(argv[3], "R")) { 4138 + !strcmp(argv[3], "D") || !strcmp(argv[3], "R") || 4139 + !strcmp(argv[3], "I")) { 4376 4140 ic->mode = argv[3][0]; 4377 4141 } else { 4378 - ti->error = "Invalid mode (expecting J, B, D, R)"; 4142 + ti->error = "Invalid mode (expecting J, B, D, R, I)"; 4379 4143 r = -EINVAL; 4380 4144 goto bad; 4381 4145 } ··· 4522 4284 else 4523 4285 ic->log2_tag_size = -1; 4524 4286 4287 + if (ic->mode == 'I') { 4288 + struct blk_integrity *bi; 4289 + if (ic->meta_dev) { 4290 + r = -EINVAL; 4291 + ti->error = "Metadata device not supported in inline mode"; 4292 + goto bad; 4293 + } 4294 + if (!ic->internal_hash_alg.alg_string) { 4295 + r = -EINVAL; 4296 + ti->error = "Internal hash not set in inline mode"; 4297 + goto bad; 4298 + } 4299 + if (ic->journal_crypt_alg.alg_string || ic->journal_mac_alg.alg_string) { 4300 + r = -EINVAL; 4301 + ti->error = "Journal crypt not supported in inline mode"; 4302 + goto bad; 4303 + } 4304 + if (ic->discard) { 4305 + r = -EINVAL; 4306 + ti->error = "Discards not supported in inline mode"; 4307 + goto bad; 4308 + } 4309 + bi = blk_get_integrity(ic->dev->bdev->bd_disk); 4310 + if (!bi || bi->csum_type != BLK_INTEGRITY_CSUM_NONE) { 4311 + r = -EINVAL; 4312 + ti->error = "Integrity profile not supported"; 4313 + goto bad; 4314 + } 4315 + /*printk("tag_size: %u, tuple_size: %u\n", bi->tag_size, bi->tuple_size);*/ 4316 + if (bi->tuple_size < ic->tag_size) { 4317 + r = -EINVAL; 4318 + ti->error = "The integrity profile is smaller than tag size"; 4319 + goto bad; 4320 + } 4321 + if ((unsigned long)bi->tuple_size > PAGE_SIZE / 2) { 4322 + r = -EINVAL; 4323 + ti->error = "Too big tuple size"; 4324 + goto bad; 4325 + } 4326 + ic->tuple_size = bi->tuple_size; 4327 + if (1 << bi->interval_exp != ic->sectors_per_block << SECTOR_SHIFT) { 4328 + r = -EINVAL; 4329 + ti->error = "Integrity profile sector size mismatch"; 4330 + goto bad; 4331 + } 4332 + } 4333 + 4525 4334 if (ic->mode == 'B' && !ic->internal_hash) { 4526 4335 r = -EINVAL; 4527 4336 ti->error = "Bitmap mode can be only used with internal hash"; ··· 4599 4314 goto bad; 4600 4315 } 4601 4316 4602 - r = mempool_init_page_pool(&ic->recheck_pool, 1, 0); 4317 + r = mempool_init_page_pool(&ic->recheck_pool, 1, ic->mode == 'I' ? 1 : 0); 4603 4318 if (r) { 4604 4319 ti->error = "Cannot allocate mempool"; 4605 4320 goto bad; 4321 + } 4322 + 4323 + if (ic->mode == 'I') { 4324 + r = bioset_init(&ic->recheck_bios, RECHECK_POOL_SIZE, 0, BIOSET_NEED_BVECS); 4325 + if (r) { 4326 + ti->error = "Cannot allocate bio set"; 4327 + goto bad; 4328 + } 4329 + r = bioset_integrity_create(&ic->recheck_bios, RECHECK_POOL_SIZE); 4330 + if (r) { 4331 + ti->error = "Cannot allocate bio integrity set"; 4332 + r = -ENOMEM; 4333 + goto bad; 4334 + } 4606 4335 } 4607 4336 4608 4337 ic->metadata_wq = alloc_workqueue("dm-integrity-metadata", ··· 4695 4396 should_write_sb = true; 4696 4397 } 4697 4398 4698 - if (!ic->sb->version || ic->sb->version > SB_VERSION_5) { 4399 + if (!ic->sb->version || ic->sb->version > SB_VERSION_6) { 4699 4400 r = -EINVAL; 4700 4401 ti->error = "Unknown version"; 4402 + goto bad; 4403 + } 4404 + if (!!(ic->sb->flags & cpu_to_le32(SB_FLAG_INLINE)) != (ic->mode == 'I')) { 4405 + r = -EINVAL; 4406 + ti->error = "Inline flag mismatch"; 4701 4407 goto bad; 4702 4408 } 4703 4409 if (le16_to_cpu(ic->sb->integrity_tag_size) != ic->tag_size) { ··· 4715 4411 ti->error = "Block size doesn't match the information in superblock"; 4716 4412 goto bad; 4717 4413 } 4718 - if (!le32_to_cpu(ic->sb->journal_sections)) { 4414 + if (!le32_to_cpu(ic->sb->journal_sections) != (ic->mode == 'I')) { 4719 4415 r = -EINVAL; 4720 - ti->error = "Corrupted superblock, journal_sections is 0"; 4416 + if (ic->mode != 'I') 4417 + ti->error = "Corrupted superblock, journal_sections is 0"; 4418 + else 4419 + ti->error = "Corrupted superblock, journal_sections is not 0"; 4721 4420 goto bad; 4722 4421 } 4723 4422 /* make sure that ti->max_io_len doesn't overflow */ ··· 4772 4465 bits_in_journal = ((__u64)ic->journal_section_sectors * ic->journal_sections) << (SECTOR_SHIFT + 3); 4773 4466 if (bits_in_journal > UINT_MAX) 4774 4467 bits_in_journal = UINT_MAX; 4775 - while (bits_in_journal < (ic->provided_data_sectors + ((sector_t)1 << log2_sectors_per_bitmap_bit) - 1) >> log2_sectors_per_bitmap_bit) 4776 - log2_sectors_per_bitmap_bit++; 4468 + if (bits_in_journal) 4469 + while (bits_in_journal < (ic->provided_data_sectors + ((sector_t)1 << log2_sectors_per_bitmap_bit) - 1) >> log2_sectors_per_bitmap_bit) 4470 + log2_sectors_per_bitmap_bit++; 4777 4471 4778 4472 log2_blocks_per_bitmap_bit = log2_sectors_per_bitmap_bit - ic->sb->log2_sectors_per_block; 4779 4473 ic->log2_blocks_per_bitmap_bit = log2_blocks_per_bitmap_bit; ··· 4793 4485 ti->error = "Not enough provided sectors for requested mapping size"; 4794 4486 goto bad; 4795 4487 } 4796 - 4797 4488 4798 4489 threshold = (__u64)ic->journal_entries * (100 - journal_watermark); 4799 4490 threshold += 50; ··· 4845 4538 goto bad; 4846 4539 } 4847 4540 4848 - ic->bufio = dm_bufio_client_create(ic->meta_dev ? ic->meta_dev->bdev : ic->dev->bdev, 4849 - 1U << (SECTOR_SHIFT + ic->log2_buffer_sectors), 1, 0, NULL, NULL, 0); 4850 - if (IS_ERR(ic->bufio)) { 4851 - r = PTR_ERR(ic->bufio); 4852 - ti->error = "Cannot initialize dm-bufio"; 4853 - ic->bufio = NULL; 4854 - goto bad; 4541 + if (ic->mode != 'I') { 4542 + ic->bufio = dm_bufio_client_create(ic->meta_dev ? ic->meta_dev->bdev : ic->dev->bdev, 4543 + 1U << (SECTOR_SHIFT + ic->log2_buffer_sectors), 1, 0, NULL, NULL, 0); 4544 + if (IS_ERR(ic->bufio)) { 4545 + r = PTR_ERR(ic->bufio); 4546 + ti->error = "Cannot initialize dm-bufio"; 4547 + ic->bufio = NULL; 4548 + goto bad; 4549 + } 4550 + dm_bufio_set_sector_offset(ic->bufio, ic->start + ic->initial_sectors); 4855 4551 } 4856 - dm_bufio_set_sector_offset(ic->bufio, ic->start + ic->initial_sectors); 4857 4552 4858 - if (ic->mode != 'R') { 4553 + if (ic->mode != 'R' && ic->mode != 'I') { 4859 4554 r = create_journal(ic, &ti->error); 4860 4555 if (r) 4861 4556 goto bad; ··· 4917 4608 ic->just_formatted = true; 4918 4609 } 4919 4610 4920 - if (!ic->meta_dev) { 4611 + if (!ic->meta_dev && ic->mode != 'I') { 4921 4612 r = dm_set_target_max_io_len(ti, 1U << ic->sb->log2_interleave_sectors); 4922 4613 if (r) 4923 4614 goto bad; ··· 4940 4631 ti->flush_supported = true; 4941 4632 if (ic->discard) 4942 4633 ti->num_discard_bios = 1; 4634 + 4635 + if (ic->mode == 'I') 4636 + ti->mempool_needs_integrity = true; 4943 4637 4944 4638 dm_audit_log_ctr(DM_MSG_PREFIX, ti, 1); 4945 4639 return 0; ··· 4977 4665 kvfree(ic->bbs); 4978 4666 if (ic->bufio) 4979 4667 dm_bufio_client_destroy(ic->bufio); 4668 + bioset_exit(&ic->recheck_bios); 4980 4669 mempool_exit(&ic->recheck_pool); 4981 4670 mempool_exit(&ic->journal_io_mempool); 4982 4671 if (ic->io) ··· 5031 4718 5032 4719 static struct target_type integrity_target = { 5033 4720 .name = "integrity", 5034 - .version = {1, 11, 0}, 4721 + .version = {1, 12, 0}, 5035 4722 .module = THIS_MODULE, 5036 4723 .features = DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY, 5037 4724 .ctr = dm_integrity_ctr, 5038 4725 .dtr = dm_integrity_dtr, 5039 4726 .map = dm_integrity_map, 4727 + .end_io = dm_integrity_end_io, 5040 4728 .postsuspend = dm_integrity_postsuspend, 5041 4729 .resume = dm_integrity_resume, 5042 4730 .status = dm_integrity_status,