]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drbd: always set BLK_FEAT_STABLE_WRITES
authorChristoph Böhmwalder <christoph.boehmwalder@linbit.com>
Thu, 5 Feb 2026 17:39:29 +0000 (18:39 +0100)
committerJens Axboe <axboe@kernel.dk>
Wed, 11 Feb 2026 17:35:56 +0000 (10:35 -0700)
DRBD requires stable pages because it may read the same bio data
multiple times for local disk I/O and network transmission, and in
some cases for calculating checksums.

The BLK_FEAT_STABLE_WRITES flag is set when the device is first
created, but blk_set_stacking_limits() clears it whenever a
backing device is attached. In some cases the flag may be
inherited from the backing device, but we want it to be enabled
at all times.

Unconditionally re-enable BLK_FEAT_STABLE_WRITES in
drbd_reconsider_queue_parameters() after the queue parameter
negotiations.

Also, document why we want this flag enabled in the first place.

Fixes: 1a02f3a73f8c ("block: move the stable_writes flag to queue_limits")
Signed-off-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_nl.c

index c73376886e7a5143ff71cf2057b8b32b21c9439a..1f6ac9202b66a14e9973d9d087081e0799aa0005 100644 (file)
@@ -2659,9 +2659,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
                 * connect.
                 */
                .max_hw_sectors         = DRBD_MAX_BIO_SIZE_SAFE >> 8,
-               .features               = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA |
-                                         BLK_FEAT_ROTATIONAL |
-                                         BLK_FEAT_STABLE_WRITES,
        };
 
        device = minor_to_device(minor);
index 91f3b8afb63ce620c4123a5d4e3fd99416a71d7f..b502038be0a923156856278a3cd34c903809b54c 100644 (file)
@@ -1296,6 +1296,8 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device,
                lim.max_segments = drbd_backing_dev_max_segments(device);
        } else {
                lim.max_segments = BLK_MAX_SEGMENTS;
+               lim.features = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA |
+                              BLK_FEAT_ROTATIONAL | BLK_FEAT_STABLE_WRITES;
        }
 
        lim.max_hw_sectors = new >> SECTOR_SHIFT;
@@ -1318,8 +1320,24 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device,
                lim.max_hw_discard_sectors = 0;
        }
 
-       if (bdev)
+       if (bdev) {
                blk_stack_limits(&lim, &b->limits, 0);
+               /*
+                * blk_set_stacking_limits() cleared the features, and
+                * blk_stack_limits() may or may not have inherited
+                * BLK_FEAT_STABLE_WRITES from the backing device.
+                *
+                * DRBD always requires stable writes because:
+                * 1. The same bio data is read for both local disk I/O and
+                *    network transmission. If the page changes mid-flight,
+                *    the local and remote copies could diverge.
+                * 2. When data integrity is enabled, DRBD calculates a
+                *    checksum before sending the data. If the page changes
+                *    between checksum calculation and transmission, the
+                *    receiver will detect a checksum mismatch.
+                */
+               lim.features |= BLK_FEAT_STABLE_WRITES;
+       }
 
        /*
         * If we can handle "zeroes" efficiently on the protocol, we want to do