diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 68ce56fc61d0..d28a65dd54ad 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -604,6 +604,16 @@ config DM_INTEGRITY
 	  To compile this code as a module, choose M here: the module will
 	  be called dm-integrity.
 
+config DMINT_LAZY_COMMIT
+	tristate "Lazy commit for dm-integrity target"
+	depends on DM_INTEGRITY
+	default n
+	help
+	  Extend the dm-integrity driver to omit writing unused journal data.
+	  Instead use a special lazy commit id that marks the end of the data
+	  in the journal.
+	  To be seen as experimental.
+
 config DM_ZONED
 	tristate "Drive-managed zoned block device target support"
 	depends on BLK_DEV_DM
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index ed45411eb68d..d521b5d4d2d5 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -1083,18 +1083,19 @@ static void rw_journal_sectors(struct dm_integrity_c *ic, blk_opf_t opf,
 }
 
 static void rw_journal(struct dm_integrity_c *ic, blk_opf_t opf,
-		       unsigned int section, unsigned int n_sections,
-		       struct journal_completion *comp)
+		      unsigned int section, unsigned int n_sections,
+		      unsigned int omit_sectors, struct journal_completion *comp)
 {
 	unsigned int sector, n_sectors;
 
 	sector = section * ic->journal_section_sectors;
-	n_sectors = n_sections * ic->journal_section_sectors;
+	n_sectors = n_sections * ic->journal_section_sectors - omit_sectors;
 
 	rw_journal_sectors(ic, opf, sector, n_sectors, comp);
 }
 
-static void write_journal(struct dm_integrity_c *ic, unsigned int commit_start, unsigned int commit_sections)
+static void write_journal(struct dm_integrity_c *ic, unsigned int commit_start,
+			  unsigned int commit_sections, unsigned int omit_sectors)
 {
 	struct journal_completion io_comp;
 	struct journal_completion crypt_comp_1;
@@ -1117,7 +1118,7 @@ static void write_journal(struct dm_integrity_c *ic, unsigned int commit_start,
 				rw_section_mac(ic, commit_start + i, true);
 		}
 		rw_journal(ic, REQ_OP_WRITE | REQ_FUA | REQ_SYNC, commit_start,
-			   commit_sections, &io_comp);
+			   commit_sections, omit_sectors, &io_comp);
 	} else {
 		unsigned int to_end;
 
@@ -1130,7 +1131,7 @@ static void write_journal(struct dm_integrity_c *ic, unsigned int commit_start,
 			encrypt_journal(ic, true, commit_start, to_end, &crypt_comp_1);
 			if (try_wait_for_completion(&crypt_comp_1.comp)) {
 				rw_journal(ic, REQ_OP_WRITE | REQ_FUA,
-					   commit_start, to_end, &io_comp);
+					   commit_start, to_end, 0, &io_comp);
 				reinit_completion(&crypt_comp_1.comp);
 				crypt_comp_1.in_flight = (atomic_t)ATOMIC_INIT(0);
 				encrypt_journal(ic, true, 0, commit_sections - to_end, &crypt_comp_1);
@@ -1141,17 +1142,19 @@ static void write_journal(struct dm_integrity_c *ic, unsigned int commit_start,
 				crypt_comp_2.in_flight = (atomic_t)ATOMIC_INIT(0);
 				encrypt_journal(ic, true, 0, commit_sections - to_end, &crypt_comp_2);
 				wait_for_completion_io(&crypt_comp_1.comp);
-				rw_journal(ic, REQ_OP_WRITE | REQ_FUA, commit_start, to_end, &io_comp);
+				rw_journal(ic, REQ_OP_WRITE | REQ_FUA, commit_start, to_end, 0,
+					   &io_comp);
 				wait_for_completion_io(&crypt_comp_2.comp);
 			}
 		} else {
 			for (i = 0; i < to_end; i++)
 				rw_section_mac(ic, commit_start + i, true);
-			rw_journal(ic, REQ_OP_WRITE | REQ_FUA, commit_start, to_end, &io_comp);
+			rw_journal(ic, REQ_OP_WRITE | REQ_FUA, commit_start, to_end, 0, &io_comp);
 			for (i = 0; i < commit_sections - to_end; i++)
 				rw_section_mac(ic, i, true);
 		}
-		rw_journal(ic, REQ_OP_WRITE | REQ_FUA, 0, commit_sections - to_end, &io_comp);
+		rw_journal(ic, REQ_OP_WRITE | REQ_FUA, 0, commit_sections - to_end,
+			   omit_sectors, &io_comp);
 	}
 
 	wait_for_completion_io(&io_comp.comp);
@@ -1777,7 +1780,6 @@ static void integrity_metadata(struct work_struct *w)
 			if (unlikely(r)) {
 				if (r > 0) {
 					sector_t s;
-
 					s = sector - ((r + ic->tag_size - 1) / ic->tag_size);
 					DMERR_LIMIT("%pg: Checksum failed at sector 0x%llx",
 						    bio->bi_bdev, s);
@@ -2355,6 +2357,9 @@ static void integrity_commit(struct work_struct *w)
 	unsigned int commit_start, commit_sections;
 	unsigned int i, j, n;
 	struct bio *flushes;
+#ifdef CONFIG_DMINT_LAZY_COMMIT
+	unsigned int used_sectors;
+#endif
 
 	del_timer(&ic->autocommit_timer);
 
@@ -2366,6 +2371,15 @@ static void integrity_commit(struct work_struct *w)
 		goto release_flush_bios;
 	}
 
+#ifdef CONFIG_DMINT_LAZY_COMMIT
+	if (ic->free_section_entry)
+		used_sectors = (ic->free_section_entry <<
+				ic->sb->log2_sectors_per_block) +
+			JOURNAL_BLOCK_SECTORS;
+	else
+		used_sectors = ic->journal_section_sectors;
+#endif
+
 	pad_uncommitted(ic);
 	commit_start = ic->uncommitted_section;
 	commit_sections = ic->n_uncommitted_sections;
@@ -2388,6 +2402,16 @@ static void integrity_commit(struct work_struct *w)
 			struct journal_sector *js;
 
 			js = access_journal(ic, i, j);
+#ifdef CONFIG_DMINT_LAZY_COMMIT
+			if (n == commit_sections-1 && j == used_sectors-1) {
+				js->commit_id = dm_integrity_commit_id(ic, ~i,
+								       ~j, ic->commit_seq);
+				DEBUG_print("Lazy commit id=0x%llx: Sections %u.%u. Last section with %u sectors\n",
+					    js->commit_id, commit_start, i,
+					    used_sectors);
+				break;
+			}
+#endif
 			js->commit_id = dm_integrity_commit_id(ic, i, j, ic->commit_seq);
 		}
 		i++;
@@ -2397,7 +2421,12 @@ static void integrity_commit(struct work_struct *w)
 	}
 	smp_rmb();
 
-	write_journal(ic, commit_start, commit_sections);
+#ifdef CONFIG_DMINT_LAZY_COMMIT
+	write_journal(ic, commit_start, commit_sections,
+		      ic->journal_section_sectors-used_sectors);
+#else
+	write_journal(ic, commit_start, commit_sections, 0);
+#endif
 
 	spin_lock_irq(&ic->endio_wait.lock);
 	ic->uncommitted_section += commit_sections;
@@ -2443,12 +2472,13 @@ static void restore_last_bytes(struct dm_integrity_c *ic, struct journal_sector
 	} while (++s < ic->sectors_per_block);
 }
 
-static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start,
-			     unsigned int write_sections, bool from_replay)
+static int do_journal_write(struct dm_integrity_c *ic, unsigned int write_start,
+			    unsigned int write_sections, bool from_replay)
 {
 	unsigned int i, j, n;
 	struct journal_completion comp;
 	struct blk_plug plug;
+	unsigned int rc = 0;
 
 	blk_start_plug(&plug);
 
@@ -2465,7 +2495,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start
 		for (j = 0; j < ic->journal_section_entries; j++) {
 			struct journal_entry *je = access_journal_entry(ic, i, j);
 			sector_t sec, area, offset;
-			unsigned int k, l, next_loop;
+			unsigned int k, l, next_loop, end;
 			sector_t metadata_block;
 			unsigned int metadata_offset;
 			struct journal_io *io;
@@ -2543,6 +2573,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start
 			spin_unlock_irq(&ic->endio_wait.lock);
 
 			metadata_block = get_metadata_sector_and_offset(ic, area, offset, &metadata_offset);
+			end = k;
 			for (l = j; l < k; l++) {
 				int r;
 				struct journal_entry *je2 = access_journal_entry(ic, i, l);
@@ -2557,8 +2588,24 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start
 					integrity_sector_checksum(ic, sec + ((l - j) << ic->sb->log2_sectors_per_block),
 								  (char *)access_journal_data(ic, i, l), test_tag);
 					if (unlikely(memcmp(test_tag, journal_entry_tag(ic, je2), ic->tag_size))) {
+#ifdef CONFIG_DMINT_LAZY_COMMIT
+						if (!from_replay)
+							dm_integrity_io_error(ic, "tag mismatch when writing journal",
+									      -EILSEQ);
+
+						/*
+						 * during replay, continue processing and discard
+						 * data with a tag mismatch
+						 */
+						rc = -1;
+						if (end > l)
+							end = l;
+
+						DEBUG_print("tag mismatch at section %u entry %u\n", n, l);
+#else
 						dm_integrity_io_error(ic, "tag mismatch when replaying journal", -EILSEQ);
 						dm_audit_log_target(DM_MSG_PREFIX, "integrity-replay-journal", ic->ti, 0);
+#endif
 					}
 				}
 
@@ -2569,11 +2616,15 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start
 					dm_integrity_io_error(ic, "reading tags", r);
 			}
 
-			atomic_inc(&comp.in_flight);
-			copy_from_journal(ic, i, j << ic->sb->log2_sectors_per_block,
-					  (k - j) << ic->sb->log2_sectors_per_block,
-					  get_data_sector(ic, area, offset),
-					  complete_copy_from_journal, io);
+			// copy data that has not been discarded
+			if (end > j) {
+				atomic_inc(&comp.in_flight);
+				copy_from_journal(ic, i, j << ic->sb->log2_sectors_per_block,
+						  (end - j) << ic->sb->log2_sectors_per_block,
+						  get_data_sector(ic, area, offset),
+						  complete_copy_from_journal, io);
+			}
+
 skip_io:
 			j = next_loop;
 		}
@@ -2587,6 +2638,8 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start
 	wait_for_completion_io(&comp.comp);
 
 	dm_integrity_flush_buffers(ic, true);
+
+	return rc;
 }
 
 static void integrity_writer(struct work_struct *w)
@@ -2603,7 +2656,8 @@ static void integrity_writer(struct work_struct *w)
 	if (!write_sections)
 		return;
 
-	do_journal_write(ic, write_start, write_sections, false);
+	if (do_journal_write(ic, write_start, write_sections, false) < 0)
+		write_sections = ~0;
 
 	spin_lock_irq(&ic->endio_wait.lock);
 
@@ -2914,7 +2968,7 @@ static void init_journal(struct dm_integrity_c *ic, unsigned int start_section,
 		}
 	}
 
-	write_journal(ic, start_section, n_sections);
+	write_journal(ic, start_section, n_sections, 0);
 }
 
 static int find_commit_seq(struct dm_integrity_c *ic, unsigned int i, unsigned int j, commit_id_t id)
@@ -2929,6 +2983,50 @@ static int find_commit_seq(struct dm_integrity_c *ic, unsigned int i, unsigned i
 	return -EIO;
 }
 
+#ifdef CONFIG_DMINT_LAZY_COMMIT
+static int find_commit_seq_lazy(struct dm_integrity_c *ic, unsigned int i,
+	unsigned int j, commit_id_t id, bool *lazy)
+{
+	unsigned char k;
+	*lazy = false;
+	for (k = 0; k < N_COMMIT_IDS; k++) {
+		if (dm_integrity_commit_id(ic, i, j, k) == id)
+			return k;
+	}
+	for (k = 0; k < N_COMMIT_IDS; k++) {
+		if (dm_integrity_commit_id(ic, ~i, ~j, k) == id) {
+			DEBUG_print("Found a lazy commit id at %d:%d\n", i, j);
+			*lazy = true;
+			return k;
+		}
+	}
+	dm_integrity_io_error(ic, "journal commit id", -EIO);
+	return -EIO;
+}
+
+static bool journal_check_lazy_commit(struct dm_integrity_c *ic,
+	unsigned int i, unsigned int sector)
+{
+	unsigned int j;
+
+	if (sector%ic->sectors_per_block) {
+		DEBUG_print("The lazy commit id is not aligned to the block size. Not replaying section\n");
+		return false;
+	}
+
+	for (j = sector>>ic->sb->log2_sectors_per_block;
+		j < ic->journal_section_entries; j++) {
+		struct journal_entry *je = access_journal_entry(ic, i, j);
+
+		if (!journal_entry_is_unused(je)) {
+			DEBUG_print("Found used journal entry after lazy commit. Not replaying section\n");
+			return false;
+		}
+	}
+	return true;
+}
+#endif
+
 static void replay_journal(struct dm_integrity_c *ic)
 {
 	unsigned int i, j;
@@ -2938,6 +3036,7 @@ static void replay_journal(struct dm_integrity_c *ic)
 	unsigned int continue_section;
 	bool journal_empty;
 	unsigned char unused, last_used, want_commit_seq;
+	unsigned int first_bad, last_bad, dead;
 
 	if (ic->mode == 'R')
 		return;
@@ -2947,10 +3046,13 @@ static void replay_journal(struct dm_integrity_c *ic)
 
 	last_used = 0;
 	write_start = 0;
+	first_bad = 0;
+	last_bad = 0;
+	dead = 0;
 
 	if (!ic->just_formatted) {
 		DEBUG_print("reading journal\n");
-		rw_journal(ic, REQ_OP_READ, 0, ic->journal_sections, NULL);
+		rw_journal(ic, REQ_OP_READ, 0, ic->journal_sections, 0, NULL);
 		if (ic->journal_io)
 			DEBUG_bytes(lowmem_page_address(ic->journal_io[0].page), 64, "read journal");
 		if (ic->journal_io) {
@@ -2972,17 +3074,32 @@ static void replay_journal(struct dm_integrity_c *ic)
 	memset(used_commit_ids, 0, sizeof(used_commit_ids));
 	memset(max_commit_id_sections, 0, sizeof(max_commit_id_sections));
 	for (i = 0; i < ic->journal_sections; i++) {
+		bool bad = false;
 		for (j = 0; j < ic->journal_section_sectors; j++) {
 			int k;
 			struct journal_sector *js = access_journal(ic, i, j);
-
+#ifndef CONFIG_DMINT_LAZY_COMMIT
 			k = find_commit_seq(ic, i, j, js->commit_id);
-			if (k < 0)
-				goto clear_journal;
+#else
+			bool lazy;
+
+			k = find_commit_seq_lazy(ic, i, j, js->commit_id,
+						 &lazy);
+			if (lazy)
+				j = ic->journal_section_sectors;
+#endif
+			if (k < 0) {
+				/* remember the first and last bad section */
+				bad = true;
+				if (!first_bad)
+					first_bad = i + 1;
+				last_bad = i + 1;
+				break;
+			}
 			used_commit_ids[k] = true;
 			max_commit_id_sections[k] = i;
 		}
-		if (journal_empty) {
+		if (!bad && journal_empty) {
 			for (j = 0; j < ic->journal_section_entries; j++) {
 				struct journal_entry *je = access_journal_entry(ic, i, j);
 
@@ -3022,21 +3139,75 @@ static void replay_journal(struct dm_integrity_c *ic)
 		want_commit_seq = next_commit_seq(want_commit_seq);
 	wraparound_section(ic, &write_start);
 
+	if (unlikely(first_bad)) {
+		DEBUG_print("dm-integrity: write_start=%u first_bad=%u last_bad=%u\n",
+			    write_start, first_bad, last_bad);
+
+		if (last_bad <= write_start)
+			/*
+			 * section     0   1   2   3  | 4   5   6   7
+			 * id          2   2   2   2  | 2   1   1   1
+			 * first_bad=3         ^
+			 * last_bad=4              ^
+			 * start=4                      ^
+			 * dead=2              X   X
+			 */
+			dead = write_start - first_bad + 1;
+		else if (first_bad > write_start)
+			/*
+			 * section     0   1   2   3  | 4   5   6   7
+			 * id          2   2   2   2  | 2   1   1   1
+			 * first_bad=7                          ^
+			 * last_bad=8                               ^
+			 * start=4                      ^
+			 * dead=6      X   X   X   X            X   X
+			 */
+			dead = ic->journal_sections + write_start - first_bad + 1;
+		else
+			/*
+			 * section     0   1   2   3  | 4   5   6   7
+			 * id          2   2   2   2  | 2   1   1   1
+			 * first_bad=4             ^
+			 * last_bad=7                           ^
+			 * start=4                      ^
+			 * dead=0      X   X   X   X    X   X   X   X
+			 */
+			dead = 0;
+
+		DEBUG_print("dm-integrity: sections=%u, empty=%s, dead=%u\n",
+			    ic->journal_sections, journal_empty ? "true" : "false", dead);
+
+		if (journal_empty || dead == 0)
+			goto clear_journal;
+	}
+
 	i = write_start;
-	for (write_sections = 0; write_sections < ic->journal_sections; write_sections++) {
+	for (write_sections = 0; write_sections < ic->journal_sections - dead;
+	     write_sections++) {
 		for (j = 0; j < ic->journal_section_sectors; j++) {
 			struct journal_sector *js = access_journal(ic, i, j);
-
-			if (js->commit_id != dm_integrity_commit_id(ic, i, j, want_commit_seq)) {
-				/*
-				 * This could be caused by crash during writing.
-				 * We won't replay the inconsistent part of the
-				 * journal.
-				 */
-				DEBUG_print("commit id mismatch at position (%u, %u): %d != %d\n",
-					    i, j, find_commit_seq(ic, i, j, js->commit_id), want_commit_seq);
-				goto brk;
+			if (js->commit_id == dm_integrity_commit_id(ic, i, j,
+				want_commit_seq))
+				continue; /* regular commit */
+#ifdef CONFIG_DMINT_LAZY_COMMIT
+			if (js->commit_id == dm_integrity_commit_id(ic, ~i, ~j,
+				want_commit_seq)) {
+				/* Lazy commit */
+				DEBUG_print("Found lazy commit in replay: %u, %u\n",
+					i, j);
+				if (journal_check_lazy_commit(ic, i, j + 1))
+					break;
 			}
+#endif
+			/*
+			 * This could be caused by crash during writing.
+			 * We won't replay the inconsistent part of the
+			 * journal.
+			 */
+			DEBUG_print("commit id mismatch at position (%u, %u): %d != %d\n",
+				i, j, find_commit_seq(ic, i, j,
+				js->commit_id), want_commit_seq);
+			goto brk;
 		}
 		i++;
 		if (unlikely(i >= ic->journal_sections))
@@ -3785,7 +3956,10 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
 	if (ic->journal_crypt_alg.alg_string) {
 		unsigned int ivsize, blocksize;
 		struct journal_completion comp;
-
+#ifdef CONFIG_DMINT_LAZY_COMMIT
+		*error = "Lazy commit with journal encryption is currently not supported";
+		goto bad;
+#endif
 		comp.ic = ic;
 		ic->journal_crypt = crypto_alloc_skcipher(ic->journal_crypt_alg.alg_string, 0, CRYPTO_ALG_ALLOCATES_MEMORY);
 		if (IS_ERR(ic->journal_crypt)) {
