md: sync blockdev before stopping raid or setting readonly
authorLi Nan <linan122@huawei.com>
Mon, 26 Feb 2024 03:14:42 +0000 (11:14 +0800)
committerSong Liu <song@kernel.org>
Mon, 26 Feb 2024 18:22:22 +0000 (10:22 -0800)
Commit a05b7ea03d72 ("md: avoid crash when stopping md array races
with closing other open fds.") added sync_block before stopping raid and
setting readonly. Later in commit 260fa034ef7a ("md: avoid deadlock when
dirty buffers during md_stop.") it is moved to ioctl. array_state_store()
was ignored. Add sync blockdev to array_state_store() now.

Signed-off-by: Li Nan <linan122@huawei.com>
Signed-off-by: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240226031444.3606764-8-linan666@huaweicloud.com
drivers/md/md.c

index 4d58e3496d164f01f438a6ddef4bbe16e1771422..3b653e68db0c2998824439d644f386d84eb63463 100644 (file)
@@ -4500,6 +4500,17 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
        case broken:            /* cannot be set */
        case bad_word:
                return -EINVAL;
+       case clear:
+       case readonly:
+       case inactive:
+       case read_auto:
+               if (!mddev->pers || !md_is_rdwr(mddev))
+                       break;
+               /* write sysfs will not open mddev and opener should be 0 */
+               err = mddev_set_closing_and_sync_blockdev(mddev, 0);
+               if (err)
+                       return err;
+               break;
        default:
                break;
        }
@@ -4599,6 +4610,11 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
                sysfs_notify_dirent_safe(mddev->sysfs_state);
        }
        mddev_unlock(mddev);
+
+       if (st == readonly || st == read_auto || st == inactive ||
+           (err && st == clear))
+               clear_bit(MD_CLOSING, &mddev->flags);
+
        return err ?: len;
 }
 static struct md_sysfs_entry md_array_state =