Merge tag 'for-6.1/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/devic...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 18 Nov 2022 20:23:35 +0000 (12:23 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 18 Nov 2022 20:23:35 +0000 (12:23 -0800)
Pull device mapper fixes from Mike Snitzer:

 - Fix misbehavior if list_versions DM ioctl races with module loading

 - Fix missing decrement of no_sleep_enabled if dm_bufio_client_create
   failed

 - Allow DM integrity devices to be activated in read-only mode

* tag 'for-6.1/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm integrity: clear the journal on suspend
  dm integrity: flush the journal on suspend
  dm bufio: Fix missing decrement of no_sleep_enabled if dm_bufio_client_create failed
  dm ioctl: fix misbehavior if list_versions races with module loading

drivers/md/dm-bufio.c
drivers/md/dm-integrity.c
drivers/md/dm-ioctl.c

index 9c5ef81..bb786c3 100644 (file)
@@ -1858,6 +1858,8 @@ bad:
        dm_io_client_destroy(c->dm_io);
 bad_dm_io:
        mutex_destroy(&c->lock);
+       if (c->no_sleep)
+               static_branch_dec(&no_sleep_enabled);
        kfree(c);
 bad_client:
        return ERR_PTR(r);
index aaf2472..648fdfe 100644 (file)
@@ -263,6 +263,7 @@ struct dm_integrity_c {
 
        struct completion crypto_backoff;
 
+       bool wrote_to_journal;
        bool journal_uptodate;
        bool just_formatted;
        bool recalculate_flag;
@@ -2375,6 +2376,8 @@ static void integrity_commit(struct work_struct *w)
        if (!commit_sections)
                goto release_flush_bios;
 
+       ic->wrote_to_journal = true;
+
        i = commit_start;
        for (n = 0; n < commit_sections; n++) {
                for (j = 0; j < ic->journal_section_entries; j++) {
@@ -2591,10 +2594,6 @@ static void integrity_writer(struct work_struct *w)
 
        unsigned prev_free_sectors;
 
-       /* the following test is not needed, but it tests the replay code */
-       if (unlikely(dm_post_suspending(ic->ti)) && !ic->meta_dev)
-               return;
-
        spin_lock_irq(&ic->endio_wait.lock);
        write_start = ic->committed_section;
        write_sections = ic->n_committed_sections;
@@ -3101,10 +3100,17 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
        drain_workqueue(ic->commit_wq);
 
        if (ic->mode == 'J') {
-               if (ic->meta_dev)
-                       queue_work(ic->writer_wq, &ic->writer_work);
+               queue_work(ic->writer_wq, &ic->writer_work);
                drain_workqueue(ic->writer_wq);
                dm_integrity_flush_buffers(ic, true);
+               if (ic->wrote_to_journal) {
+                       init_journal(ic, ic->free_section,
+                                    ic->journal_sections - ic->free_section, ic->commit_seq);
+                       if (ic->free_section) {
+                               init_journal(ic, 0, ic->free_section,
+                                            next_commit_seq(ic->commit_seq));
+                       }
+               }
        }
 
        if (ic->mode == 'B') {
@@ -3132,6 +3138,8 @@ static void dm_integrity_resume(struct dm_target *ti)
 
        DEBUG_print("resume\n");
 
+       ic->wrote_to_journal = false;
+
        if (ic->provided_data_sectors != old_provided_data_sectors) {
                if (ic->provided_data_sectors > old_provided_data_sectors &&
                    ic->mode == 'B' &&
index 6b3f867..3bfc158 100644 (file)
@@ -655,7 +655,7 @@ static void list_version_get_needed(struct target_type *tt, void *needed_param)
     size_t *needed = needed_param;
 
     *needed += sizeof(struct dm_target_versions);
-    *needed += strlen(tt->name);
+    *needed += strlen(tt->name) + 1;
     *needed += ALIGN_MASK;
 }
 
@@ -720,7 +720,7 @@ static int __list_versions(struct dm_ioctl *param, size_t param_size, const char
        iter_info.old_vers = NULL;
        iter_info.vers = vers;
        iter_info.flags = 0;
-       iter_info.end = (char *)vers+len;
+       iter_info.end = (char *)vers + needed;
 
        /*
         * Now loop through filling out the names & versions.