The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
To: John Garry <john.g.garry@oracle.com>,
	song@kernel.org, yukuai@fygo.io, magiclinan@didiglobal.com,
	xiao@kernel.org, axboe@kernel.dk, vverma@digitalocean.com,
	martin.petersen@oracle.com, linux-kernel@vger.kernel.org
Cc: linux-raid@vger.kernel.org
Subject: Re: [PATCH v2 2/7] md/raid1: advertise atomic write limits and handle runtime constraints
Date: Mon, 06 Jul 2026 13:35:50 +0200	[thread overview]
Message-ID: <m2pl1073l5.fsf@gmail.com> (raw)
In-Reply-To: <856abedc-d2f3-4248-9583-4d7e1a11abc1@oracle.com>

On Fri, Jul 03, 2026 at 09:28 +0100, John Garry wrote:
> On 30/06/2026 09:39, Abd-Alrhman Masalkhi wrote:
>> 
>> Hi John,
>> 
>> On Mon, Jun 29, 2026 at 15:48 +0100, John Garry wrote:
>>> On 28/06/2026 15:24, Abd-Alrhman Masalkhi wrote:
>>>> Atomic writes in RAID1 must fit within a single barrier unit. Advertise
>>>> this restriction through the queue limits by setting
>>>> atomic_write_hw_unit_max to BARRIER_UNIT_SECTOR_SIZE so that bios which
>>>> would cross a barrier-unit boundary are rejected by the block layer
>>>> before reaching MD.
>>>>
>>>> A bio that passes block-layer validation may still become unserviceable
>>>> within RAID1 due to bad blocks or write-behind constraints. In the former
>>>> case, complete the bio with EIO. In the latter case, disable
>>>> write-behind rather than failing the bio with EIO.
>>>>
>>>> Fixes: f2a38abf5f1c ("md/raid1: Atomic write support")
>>>> Fixes: a4c55c902670 ("md/raid1: simplify raid1_write_request() error handling")
>>>> Signed-off-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
>>>> ---
>>>> Changes in v2:
>>>>    - Drop the early atomic write split check from raid1_write_request().
>>>>    - Advertise the atomic write size limit via queue limits.
>>>>    - Disable write-behind instead of failing atomic writes when the
>>>>      BIO_MAX_VECS limit is encountered.
>>>>    - Link to v1: https://urldefense.com/v3/__https://lore.kernel.org/linux-raid/20260623072456.333437-3-abd.masalkhi@gmail.com/__;!!ACWV5N9M2RV99hQ!LbMSGSClRi0PNBqQti5ZNWGDVjDd34-7saYEAwNyBNjpNTjEA7veqM5RHG8KB1QiscarW4UaIefjm19ywSImtIgh$
>>>> ---
>>>>    drivers/md/raid1.c | 36 +++++++++++++++++++-----------------
>>>>    1 file changed, 19 insertions(+), 17 deletions(-)
>>>>
>>>> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
>>>> index afe2ca96ad8c..f322048ab3c2 100644
>>>> --- a/drivers/md/raid1.c
>>>> +++ b/drivers/md/raid1.c
>>>> @@ -1522,6 +1522,7 @@ static bool raid1_write_request(struct mddev *mddev, struct bio *bio,
>>>>    	int first_clone;
>>>>    	bool write_behind = false;
>>>>    	bool nowait = bio->bi_opf & REQ_NOWAIT;
>>>> +	bool atomic = bio->bi_opf & REQ_ATOMIC;
>>>>    	bool is_discard = op_is_discard(bio->bi_opf);
>>>>    	sector_t sector = bio->bi_iter.bi_sector;
>>>>    
>>>> @@ -1603,20 +1604,6 @@ static bool raid1_write_request(struct mddev *mddev, struct bio *bio,
>>>>    			}
>>>>    			if (is_bad) {
>>>>    				int good_sectors;
>>>> -
>>>> -				/*
>>>> -				 * We cannot atomically write this, so just
>>>> -				 * error in that case. It could be possible to
>>>> -				 * atomically write other mirrors, but the
>>>> -				 * complexity of supporting that is not worth
>>>> -				 * the benefit.
>>>> -				 */
>>>> -				if (bio->bi_opf & REQ_ATOMIC) {
>>>> -					bio->bi_status = BLK_STS_NOTSUPP;
>>>> -					bio_endio(bio);
>>>> -					goto err_dec_pending;
>>>> -				}
>>>> -
>>>>    				good_sectors = first_bad - sector;
>>>>    				if (good_sectors < max_sectors)
>>>>    					max_sectors = good_sectors;
>>>> @@ -1633,10 +1620,24 @@ static bool raid1_write_request(struct mddev *mddev, struct bio *bio,
>>>>    	 * at a time and thus needs a new bio that can fit the whole payload
>>>>    	 * this bio in page sized chunks.
>>>>    	 */
>>>> -	if (write_behind && mddev->bitmap)
>>>> -		max_sectors = min_t(int, max_sectors,
>>>> -				    BIO_MAX_VECS * (PAGE_SIZE >> 9));
>>>> +	if (write_behind && mddev->bitmap) {
>>>> +		if (atomic && max_sectors > BIO_MAX_VECS * (PAGE_SIZE >> 9))
>>>
>>> where does BIO_MAX_VECS * (PAGE_SIZE >> 9) even come from?
>>>
>> 
>> BIO_MAX_VECS * (PAGE_SIZE >> 9) defines the maximum size supported by
>> write-behind. The write-behind copy (alloc_behind_master_bio) uses a
>> single bio, which can hold at most BIO_MAX_VECS pages, making this the
>> largest payload it can carry. With a 4 KiB PAGE_SIZE, that corresponds
>> to 256 pages, or 1 MiB (2048 sectors).
>> This patch changes the behavior for atomic writes that exceed this
>> limit. Instead of failing the write with -EIO when the number of sectors
>> must be reduced, it disables write-behind and proceeds with the atomic
>> write.
>> 
>>>> +			/*
>>>> +			 * Atomic writes cannot be split, so disable
>>>> +			 * write-behind.
>>>> +			 */
>>>> +			write_behind = false;
>
> It's a bit poor to have write_behind initially = false, then allow it to 
> be set = true, and then later be set = false. Can this be improved?
>

Yes, I agree that setting write_behind to true and then resetting it to
false later is not ideal. I will rework this.


>>>> +		else
>>>> +			max_sectors = min_t(int, max_sectors,
>>>> +					    BIO_MAX_VECS * (PAGE_SIZE >> 9));
>>>> +	}
>>>> +
>>>>    	if (max_sectors < bio_sectors(bio)) {
>>>> +		if (atomic) {
>>>> +			bio_io_error(bio);
>>>> +			goto err_dec_pending;
>>>> +		}
>>>> +
>>>>    		bio = bio_submit_split_bioset(bio, max_sectors,
>>>>    					      &conf->bio_split);
>>>>    		if (!bio)
>>>> @@ -3229,6 +3230,7 @@ static int raid1_set_limits(struct mddev *mddev)
>>>>    	lim.max_write_zeroes_sectors = 0;
>>>>    	lim.max_hw_wzeroes_unmap_sectors = 0;
>>>>    	lim.logical_block_size = mddev->logical_block_size;
>>>> +	lim.atomic_write_hw_unit_max = BARRIER_UNIT_SECTOR_SIZE;
>>>
>>> This BARRIER_UNIT_SECTOR_SIZE is a bit like chunk sectors, no? I am just
>>> wondering if we just should set it to chunk sectors =
>>> BARRIER_UNIT_SECTOR_SIZE
>>>
>>> I assume that it affects more than Reads and writes, e.g. discard also.
>>>
>> 
>> BARRIER_UNIT_SECTOR_SIZE is the resync barrier-bucket, not the layout
>> chunk size. Unless I'm missing something, using
>> atomic_write_hw_unit_max seems more appropriate than using the chunk
>> size. That way, the limit only applies to atomic writes instead of
>> affecting other operations such.
>
> well it seems to be that everything in the driver is split over 
> BARRIER_UNIT_SECTOR_SIZE, so is in effect a chunk size.
>
> Note that atomic_write_hw_unit_max is going to be small always compared 
> to BARRIER_UNIT_SECTOR_SIZE.
>
> However, can you check the blk stacking code to make sure that this does 
> as you want? As I remember, for stacking we take the atomic write limits 
> of the first bottom device and then stack the other bottom devices and I 
> don't think that setting atomic_write_hw_unit_max in this way has an 
> impact - see blk_stack_atomic_writes_limits()
>

I checked blk_stack_atomic_writes_limits(), and you are right: setting
atomic_write_hw_unit_max here alone does not have the intended effect on
the final stacked device.

Also, since atomic_write_hw_unit_max is expected to always be smaller
than BARRIER_UNIT_SECTOR_SIZE, it seems that there is no need to set an
additional atomic write limit in raid1, or even to set
atomic_write_hw_unit_max at all. Is that what you mean?

>> 
>>>>    	lim.features |= BLK_FEAT_ATOMIC_WRITES;
>>>>    	lim.features |= BLK_FEAT_PCI_P2PDMA;
>>>>    	err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
>>>
>> 
>

-- 
Best Regards,
Abd-Alrhman

  reply	other threads:[~2026-07-06 11:35 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-28 14:24 [PATCH v2 0/7] md/raid10: fixes, atomic write handling, and error-path cleanup Abd-Alrhman Masalkhi
2026-06-28 14:24 ` [PATCH v2 1/7] md/raid10: fix r10bio leak in raid10_write_request() error paths Abd-Alrhman Masalkhi
2026-06-28 14:24 ` [PATCH v2 2/7] md/raid1: advertise atomic write limits and handle runtime constraints Abd-Alrhman Masalkhi
2026-06-29 14:48   ` John Garry
2026-06-30  8:39     ` Abd-Alrhman Masalkhi
2026-07-03  8:28       ` John Garry
2026-07-06 11:35         ` Abd-Alrhman Masalkhi [this message]
2026-06-28 14:24 ` [PATCH v2 3/7] md/raid10: consistently fail atomic writes that require splitting Abd-Alrhman Masalkhi
2026-06-28 14:24 ` [PATCH v2 4/7] md/raid10: remove unnecessary barrier around bio_submit_split_bioset() Abd-Alrhman Masalkhi
2026-06-28 14:24 ` [PATCH v2 5/7] md/raid10: replace wait loop with wait_event_idle() Abd-Alrhman Masalkhi
2026-06-28 14:24 ` [PATCH v2 6/7] md/raid10: simplify write request error handling Abd-Alrhman Masalkhi
2026-06-28 14:24 ` [PATCH v2 7/7] md/raid10: simplify read " Abd-Alrhman Masalkhi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m2pl1073l5.fsf@gmail.com \
    --to=abd.masalkhi@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=john.g.garry@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-raid@vger.kernel.org \
    --cc=magiclinan@didiglobal.com \
    --cc=martin.petersen@oracle.com \
    --cc=song@kernel.org \
    --cc=vverma@digitalocean.com \
    --cc=xiao@kernel.org \
    --cc=yukuai@fygo.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox