From 1e0831b6aa5d5518d160a0732b58c225a16d6b31 Mon Sep 17 00:00:00 2001 From: Ziyu Zhang Date: Mon, 4 May 2026 11:25:50 +0800 Subject: [PATCH] drbd: serialize UUID snapshot in drbd_md_write() drbd_md_write() copies device->ldev->md.uuid[] into the on-disk metadata block without holding uuid_lock. The write-side helpers drbd_uuid_new_current() and drbd_uuid_set_bm() update md.uuid[] under uuid_lock, and some updates span multiple UUID slots as one logical state transition. An unlocked drbd_md_write() can therefore observe and persist a mixed UUID tuple assembled from two different states. This is problematic because the serialized UUID tuple is written to stable storage and later consumed by reconnect and resync decision logic, meaning an inconsistent on-disk snapshot can represent a state that never existed atomically in memory. Protect the UUID copy with uuid_lock so drbd_md_write() serializes one coherent snapshot. Fixes: b411b3637fa7 ("The DRBD driver") Signed-off-by: Ziyu Zhang --- drivers/block/drbd/drbd_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index b1a721dd04969..87296e4a69e00 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2962,13 +2962,17 @@ void drbd_md_write(struct drbd_device *device, void *b) { struct meta_data_on_disk *buffer = b; sector_t sector; + unsigned long flags; int i; memset(buffer, 0, sizeof(*buffer)); buffer->la_size_sect = cpu_to_be64(get_capacity(device->vdisk)); + /* Serialize the UUID tuple as one coherent snapshot. */ + spin_lock_irqsave(&device->ldev->md.uuid_lock, flags); for (i = UI_CURRENT; i < UI_SIZE; i++) buffer->uuid[i] = cpu_to_be64(device->ldev->md.uuid[i]); + spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags); buffer->flags = cpu_to_be32(device->ldev->md.flags); buffer->magic = cpu_to_be32(DRBD_MD_MAGIC_84_UNCLEAN);