Merge tag 'pinctrl-v5.3-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[sfrench/cifs-2.6.git] / drivers / md / dm-integrity.c
index 44e76cda087aa658fbb13195fa5d91f4117902b8..9118ab85cb3ad96414805059f7ec2b96df1a29b3 100644 (file)
@@ -476,6 +476,9 @@ static int sync_rw_sb(struct dm_integrity_c *ic, int op, int op_flags)
        io_loc.sector = ic->start;
        io_loc.count = SB_SECTORS;
 
+       if (op == REQ_OP_WRITE)
+               sb_set_version(ic);
+
        return dm_io(&io_req, 1, &io_loc, NULL);
 }
 
@@ -1940,7 +1943,22 @@ offload_to_thread:
                        queue_work(ic->wait_wq, &dio->work);
                        return;
                }
+               if (journal_read_pos != NOT_FOUND)
+                       dio->range.n_sectors = ic->sectors_per_block;
                wait_and_add_new_range(ic, &dio->range);
+               /*
+                * wait_and_add_new_range drops the spinlock, so the journal
+                * may have been changed arbitrarily. We need to recheck.
+                * To simplify the code, we restrict I/O size to just one block.
+                */
+               if (journal_read_pos != NOT_FOUND) {
+                       sector_t next_sector;
+                       unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
+                       if (unlikely(new_pos != journal_read_pos)) {
+                               remove_range_unlocked(ic, &dio->range);
+                               goto retry;
+                       }
+               }
        }
        spin_unlock_irq(&ic->endio_wait.lock);
 
@@ -2317,7 +2335,6 @@ static void recalc_write_super(struct dm_integrity_c *ic)
        if (dm_integrity_failed(ic))
                return;
 
-       sb_set_version(ic);
        r = sync_rw_sb(ic, REQ_OP_WRITE, 0);
        if (unlikely(r))
                dm_integrity_io_error(ic, "writing superblock", r);
@@ -3358,7 +3375,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                                goto bad;
                        }
 
-                       crypt_iv = kmalloc(ivsize, GFP_KERNEL);
+                       crypt_iv = kzalloc(ivsize, GFP_KERNEL);
                        if (!crypt_iv) {
                                *error = "Could not allocate iv";
                                r = -ENOMEM;
@@ -3387,7 +3404,6 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                                sg_set_buf(&sg[i], va, PAGE_SIZE);
                        }
                        sg_set_buf(&sg[i], &ic->commit_ids, sizeof ic->commit_ids);
-                       memset(crypt_iv, 0x00, ivsize);
 
                        skcipher_request_set_crypt(req, sg, sg,
                                                   PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, crypt_iv);