Skip to content

Commit e92a532

Browse files
committed
md/md-llbitmap: optimize initial sync with write_zeroes_unmap support
For RAID-456 arrays with llbitmap, if all underlying disks support write_zeroes with unmap, issue write_zeroes to zero all disk data regions and initialize the bitmap to BitCleanUnwritten instead of BitUnwritten. This optimization skips the initial XOR parity building because: 1. write_zeroes with unmap guarantees zeroed reads after the operation 2. For RAID-456, when all data is zero, parity is automatically consistent (0 XOR 0 XOR ... = 0) 3. BitCleanUnwritten indicates parity is valid but no user data has been written The implementation adds two helper functions: - llbitmap_all_disks_support_wzeroes_unmap(): Checks if all active disks support write_zeroes with unmap - llbitmap_zero_all_disks(): Issues blkdev_issue_zeroout() to each rdev's data region to zero all disks The zeroing and bitmap state setting happens in llbitmap_init_state() during bitmap initialization. If any disk fails to zero, we fall back to BitUnwritten and normal lazy recovery. This significantly reduces array initialization time for RAID-456 arrays built on modern NVMe SSDs or other devices that support write_zeroes with unmap. Reviewed-by: Xiao Ni <xni@redhat.com> Link: https://lore.kernel.org/linux-raid/20260323054644.3351791-4-yukuai@fnnas.com/ Signed-off-by: Yu Kuai <yukuai@fnnas.com>
1 parent 4403023 commit e92a532

1 file changed

Lines changed: 61 additions & 1 deletion

File tree

drivers/md/md-llbitmap.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,13 +654,73 @@ static int llbitmap_cache_pages(struct llbitmap *llbitmap)
654654
return 0;
655655
}
656656

657+
/*
658+
* Check if all underlying disks support write_zeroes with unmap.
659+
*/
660+
static bool llbitmap_all_disks_support_wzeroes_unmap(struct llbitmap *llbitmap)
661+
{
662+
struct mddev *mddev = llbitmap->mddev;
663+
struct md_rdev *rdev;
664+
665+
rdev_for_each(rdev, mddev) {
666+
if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags))
667+
continue;
668+
669+
if (bdev_write_zeroes_unmap_sectors(rdev->bdev) == 0)
670+
return false;
671+
}
672+
673+
return true;
674+
}
675+
676+
/*
677+
* Issue write_zeroes to all underlying disks to zero their data regions.
678+
* This ensures parity consistency for RAID-456 (0 XOR 0 = 0).
679+
* Returns true if all disks were successfully zeroed.
680+
*/
681+
static bool llbitmap_zero_all_disks(struct llbitmap *llbitmap)
682+
{
683+
struct mddev *mddev = llbitmap->mddev;
684+
struct md_rdev *rdev;
685+
sector_t dev_sectors = mddev->dev_sectors;
686+
int ret;
687+
688+
rdev_for_each(rdev, mddev) {
689+
if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags))
690+
continue;
691+
692+
ret = blkdev_issue_zeroout(rdev->bdev,
693+
rdev->data_offset,
694+
dev_sectors,
695+
GFP_KERNEL, 0);
696+
if (ret) {
697+
pr_warn("md/llbitmap: failed to zero disk %pg: %d\n",
698+
rdev->bdev, ret);
699+
return false;
700+
}
701+
}
702+
703+
return true;
704+
}
705+
657706
static void llbitmap_init_state(struct llbitmap *llbitmap)
658707
{
708+
struct mddev *mddev = llbitmap->mddev;
659709
enum llbitmap_state state = BitUnwritten;
660710
unsigned long i;
661711

662-
if (test_and_clear_bit(BITMAP_CLEAN, &llbitmap->flags))
712+
if (test_and_clear_bit(BITMAP_CLEAN, &llbitmap->flags)) {
663713
state = BitClean;
714+
} else if (raid_is_456(mddev) &&
715+
llbitmap_all_disks_support_wzeroes_unmap(llbitmap)) {
716+
/*
717+
* All disks support write_zeroes with unmap. Zero all disks
718+
* to ensure parity consistency, then set BitCleanUnwritten
719+
* to skip initial sync.
720+
*/
721+
if (llbitmap_zero_all_disks(llbitmap))
722+
state = BitCleanUnwritten;
723+
}
664724

665725
for (i = 0; i < llbitmap->chunks; i++)
666726
llbitmap_write(llbitmap, state, i);

0 commit comments

Comments
 (0)