[PATCH] md: support to align bio to limits

Yu Kuai posted 1 patch 1 week, 3 days ago
drivers/md/md.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/md/md.h |  1 +
2 files changed, 47 insertions(+)
[PATCH] md: support to align bio to limits
Posted by Yu Kuai 1 week, 3 days ago
For personalities that report optimal IO size, it's indicate that users
can get the best IO bandwidth if they issue IO with this size. However
there is also an implicit condition that IO should also be aligned to the
optimal IO size.

Currently, bio will only be split by limits, if bio offset is not aligned
to limits, then all split bio will not be aligned. This patch add a new
feature to align bio to limits first, and following patches will support
this for each personality if necessary.

Signed-off-by: Yu Kuai <yukuai@fnnas.com>
---
 drivers/md/md.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/md/md.h |  1 +
 2 files changed, 47 insertions(+)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 7b5c5967568f..b09f87b27807 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -427,6 +427,48 @@ bool md_handle_request(struct mddev *mddev, struct bio *bio)
 }
 EXPORT_SYMBOL(md_handle_request);
 
+static struct bio *__md_bio_align_to_limits(struct mddev *mddev,
+					    struct bio *bio)
+{
+	unsigned int max_sectors = mddev->gendisk->queue->limits.max_sectors;
+	sector_t start = bio->bi_iter.bi_sector;
+	sector_t align_start = roundup(start, max_sectors);
+	sector_t end;
+	sector_t align_end;
+
+	/* already aligned */
+	if (align_start == start)
+		return bio;
+
+	end = start + bio_sectors(bio);
+	align_end = rounddown(end, max_sectors);
+
+	/* bio is too small to split */
+	if (align_end <= align_start)
+		return bio;
+
+	return bio_submit_split_bioset(bio, align_start - start,
+				       &mddev->gendisk->bio_split);
+}
+
+static struct bio *md_bio_align_to_limits(struct mddev *mddev, struct bio *bio)
+{
+	if (!mddev->bio_align_to_limits)
+		return bio;
+
+	/* atomic write can't split */
+	if (bio->bi_opf & REQ_ATOMIC)
+		return bio;
+
+	switch (bio_op(bio)) {
+	case REQ_OP_READ:
+	case REQ_OP_WRITE:
+		return __md_bio_align_to_limits(mddev, bio);
+	default:
+		return bio;
+	}
+}
+
 static void md_submit_bio(struct bio *bio)
 {
 	const int rw = bio_data_dir(bio);
@@ -442,6 +484,10 @@ static void md_submit_bio(struct bio *bio)
 		return;
 	}
 
+	bio = md_bio_align_to_limits(mddev, bio);
+	if (!bio)
+		return;
+
 	bio = bio_split_to_limits(bio);
 	if (!bio)
 		return;
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 75fd8c873b6f..1ed90fd85ac4 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -630,6 +630,7 @@ struct mddev {
 	bool	has_superblocks:1;
 	bool	fail_last_dev:1;
 	bool	serialize_policy:1;
+	bool	bio_align_to_limits:1;
 };
 
 enum recovery_flags {
-- 
2.51.0
Re: [PATCH] md: support to align bio to limits
Posted by kernel test robot 6 days, 16 hours ago
Hi Yu,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.18-rc7 next-20251124]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yu-Kuai/md-support-to-align-bio-to-limits/20251121-131703
base:   linus/master
patch link:    https://lore.kernel.org/r/20251121051406.1316884-3-yukuai%40fnnas.com
patch subject: [PATCH] md: support to align bio to limits
config: arm-randconfig-002-20251125 (https://download.01.org/0day-ci/archive/20251125/202511251523.ariD3O9E-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 10.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251125/202511251523.ariD3O9E-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511251523.ariD3O9E-lkp@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "__aeabi_uldivmod" [drivers/md/md-mod.ko] undefined!

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] md: support to align bio to limits
Posted by kernel test robot 6 days, 23 hours ago
Hi Yu,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.18-rc7 next-20251124]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yu-Kuai/md-support-to-align-bio-to-limits/20251121-131703
base:   linus/master
patch link:    https://lore.kernel.org/r/20251121051406.1316884-3-yukuai%40fnnas.com
patch subject: [PATCH] md: support to align bio to limits
config: i386-randconfig-002-20251125 (https://download.01.org/0day-ci/archive/20251125/202511250848.gq6d7JeR-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251125/202511250848.gq6d7JeR-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511250848.gq6d7JeR-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/md/md.o: in function `__md_bio_align_to_limits':
>> drivers/md/md.c:434:(.text+0x68e4): undefined reference to `__umoddi3'
>> ld: drivers/md/md.c:443:(.text+0x693a): undefined reference to `__umoddi3'


vim +434 drivers/md/md.c

   428	
   429	static struct bio *__md_bio_align_to_limits(struct mddev *mddev,
   430						    struct bio *bio)
   431	{
   432		unsigned int max_sectors = mddev->gendisk->queue->limits.max_sectors;
   433		sector_t start = bio->bi_iter.bi_sector;
 > 434		sector_t align_start = roundup(start, max_sectors);
   435		sector_t end;
   436		sector_t align_end;
   437	
   438		/* already aligned */
   439		if (align_start == start)
   440			return bio;
   441	
   442		end = start + bio_sectors(bio);
 > 443		align_end = rounddown(end, max_sectors);
   444	
   445		/* bio is too small to split */
   446		if (align_end <= align_start)
   447			return bio;
   448	
   449		return bio_submit_split_bioset(bio, align_start - start,
   450					       &mddev->gendisk->bio_split);
   451	}
   452	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH] md: support to align bio to limits
Posted by Yu Kuai 1 week, 3 days ago
Hi,

I forgot to remove this patch, that is patch 3 in this set, before sending
to mail list, please ignore this one.

在 2025/11/21 13:14, Yu Kuai 写道:
> For personalities that report optimal IO size, it's indicate that users
> can get the best IO bandwidth if they issue IO with this size. However
> there is also an implicit condition that IO should also be aligned to the
> optimal IO size.
>
> Currently, bio will only be split by limits, if bio offset is not aligned
> to limits, then all split bio will not be aligned. This patch add a new
> feature to align bio to limits first, and following patches will support
> this for each personality if necessary.
>
> Signed-off-by: Yu Kuai <yukuai@fnnas.com>
> ---
>   drivers/md/md.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>   drivers/md/md.h |  1 +
>   2 files changed, 47 insertions(+)
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index 7b5c5967568f..b09f87b27807 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -427,6 +427,48 @@ bool md_handle_request(struct mddev *mddev, struct bio *bio)
>   }
>   EXPORT_SYMBOL(md_handle_request);
>   
> +static struct bio *__md_bio_align_to_limits(struct mddev *mddev,
> +					    struct bio *bio)
> +{
> +	unsigned int max_sectors = mddev->gendisk->queue->limits.max_sectors;
> +	sector_t start = bio->bi_iter.bi_sector;
> +	sector_t align_start = roundup(start, max_sectors);
> +	sector_t end;
> +	sector_t align_end;
> +
> +	/* already aligned */
> +	if (align_start == start)
> +		return bio;
> +
> +	end = start + bio_sectors(bio);
> +	align_end = rounddown(end, max_sectors);
> +
> +	/* bio is too small to split */
> +	if (align_end <= align_start)
> +		return bio;
> +
> +	return bio_submit_split_bioset(bio, align_start - start,
> +				       &mddev->gendisk->bio_split);
> +}
> +
> +static struct bio *md_bio_align_to_limits(struct mddev *mddev, struct bio *bio)
> +{
> +	if (!mddev->bio_align_to_limits)
> +		return bio;
> +
> +	/* atomic write can't split */
> +	if (bio->bi_opf & REQ_ATOMIC)
> +		return bio;
> +
> +	switch (bio_op(bio)) {
> +	case REQ_OP_READ:
> +	case REQ_OP_WRITE:
> +		return __md_bio_align_to_limits(mddev, bio);
> +	default:
> +		return bio;
> +	}
> +}
> +
>   static void md_submit_bio(struct bio *bio)
>   {
>   	const int rw = bio_data_dir(bio);
> @@ -442,6 +484,10 @@ static void md_submit_bio(struct bio *bio)
>   		return;
>   	}
>   
> +	bio = md_bio_align_to_limits(mddev, bio);
> +	if (!bio)
> +		return;
> +
>   	bio = bio_split_to_limits(bio);
>   	if (!bio)
>   		return;
> diff --git a/drivers/md/md.h b/drivers/md/md.h
> index 75fd8c873b6f..1ed90fd85ac4 100644
> --- a/drivers/md/md.h
> +++ b/drivers/md/md.h
> @@ -630,6 +630,7 @@ struct mddev {
>   	bool	has_superblocks:1;
>   	bool	fail_last_dev:1;
>   	bool	serialize_policy:1;
> +	bool	bio_align_to_limits:1;
>   };
>   
>   enum recovery_flags {

-- 
Thanks,
Kuai