dm integrity: fix inefficient allocation of journal space
authorMikulas Patocka <mpatocka@redhat.com>
Wed, 19 Jul 2017 15:23:40 +0000 (11:23 -0400)
committerMike Snitzer <snitzer@redhat.com>
Wed, 19 Jul 2017 22:44:18 +0000 (18:44 -0400)
When using a block size greater than 512 bytes, the dm-integrity target
allocates journal space inefficiently.  It allocates one journal entry
for each 512-byte chunk of data, fills an entry for each block of data
and leaves the remaining entries unused.

This issue doesn't cause data corruption, but all the unused journal
entries degrade performance severely.

For example, with 4k blocks and an 8k bio, it would allocate 16 journal
entries but only use 2 entries.  The remaining 14 entries were left
unused.

Fix this by adding the missing 'log2_sectors_per_block' shifts that are
required to have each journal entry map to a full block.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org
Fixes: 7eada909bfd7 ("dm: add integrity target")
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm-integrity.c

index 1b224aa9cf15213ac22bafe6f27d2206d37ff1b5..4b2fd524e38d9d6a6bb276afca2487dbf5f882e6 100644 (file)
@@ -1587,16 +1587,18 @@ retry:
        if (likely(ic->mode == 'J')) {
                if (dio->write) {
                        unsigned next_entry, i, pos;
-                       unsigned ws, we;
+                       unsigned ws, we, range_sectors;
 
-                       dio->range.n_sectors = min(dio->range.n_sectors, ic->free_sectors);
+                       dio->range.n_sectors = min(dio->range.n_sectors,
+                                                  ic->free_sectors << ic->sb->log2_sectors_per_block);
                        if (unlikely(!dio->range.n_sectors))
                                goto sleep;
-                       ic->free_sectors -= dio->range.n_sectors;
+                       range_sectors = dio->range.n_sectors >> ic->sb->log2_sectors_per_block;
+                       ic->free_sectors -= range_sectors;
                        journal_section = ic->free_section;
                        journal_entry = ic->free_section_entry;
 
-                       next_entry = ic->free_section_entry + dio->range.n_sectors;
+                       next_entry = ic->free_section_entry + range_sectors;
                        ic->free_section_entry = next_entry % ic->journal_section_entries;
                        ic->free_section += next_entry / ic->journal_section_entries;
                        ic->n_uncommitted_sections += next_entry / ic->journal_section_entries;