Re: [PATCH 00/23] md/llbitmap: md/md-llbitmap: introduce a new lockless bitmap
From: Xiao Ni
Date: Mon Jun 30 2025 - 01:39:20 EST
On Mon, Jun 30, 2025 at 11:46 AM Yu Kuai <yukuai1@xxxxxxxxxxxxxxx> wrote:
>
> Hi,
>
> 在 2025/06/30 11:25, Xiao Ni 写道:
> > On Mon, Jun 30, 2025 at 10:34 AM Yu Kuai <yukuai1@xxxxxxxxxxxxxxx> wrote:
> >>
> >> Hi,
> >>
> >> 在 2025/06/30 9:59, Xiao Ni 写道:
> >>>
> >>> After reading other patches, I want to check if I understand right.
> >>>
> >>> The first write sets the bitmap bit. The second write which hits the
> >>> same block (one sector, 512 bits) will call llbitmap_infect_dirty_bits
> >>> to set all other bits. Then the third write doesn't need to set bitmap
> >>> bits. If I'm right, the comments above should say only the first two
> >>> writes have additional overhead?
> >>
> >> Yes, for the same bit, it's twice; For different bit in the same block,
> >> it's third, by infect all bits in the block in the second.
> >
> > For different bits in the same block, test_and_set_bit(bit,
> > pctl->dirty) should be true too, right? So it infects other bits when
> > second write hits the same block too.
>
> The dirty will be cleared after bitmap_unplug.
I understand you now. The for loop in llbitmap_set_page_dirty is used
for new writes after unplug.
> >
> > [946761.035079] llbitmap_set_page_dirty:390 page[0] offset 2024, block 3
> > [946761.035430] llbitmap_state_machine:646 delay raid456 initial recovery
> > [946761.035802] llbitmap_state_machine:652 bit 1001 state from 0 to 3
> > [946761.036498] llbitmap_set_page_dirty:390 page[0] offset 2025, block 3
> > [946761.036856] llbitmap_set_page_dirty:403 call llbitmap_infect_dirty_bits
> >
> > As the debug logs show, different bits in the same block, the second
> > write (offset 2025) infects other bits.
> >
> >>
> >> For Reload action, if the bitmap bit is
> >>> NeedSync, the changed status will be x. It can't trigger resync/recovery.
> >>
> >> This is not expected, see llbitmap_state_machine(), if old or new state
> >> is need_sync, it will trigger a resync.
> >>
> >> c = llbitmap_read(llbitmap, start);
> >> if (c == BitNeedSync)
> >> need_resync = true;
> >> -> for RELOAD case, need_resync is still set.
> >>
> >> state = state_machine[c][action];
> >> if (state == BitNone)
> >> continue
> >
> > If bitmap bit is BitNeedSync,
> > state_machine[BitNeedSync][BitmapActionReload] returns BitNone, so if
> > (state == BitNone) is true, it can't set MD_RECOVERY_NEEDED and it
> > can't start sync after assembling the array.
>
> You missed what I said above that llbitmap_read() will trigger resync as
> well.
> >
> >> if (state == BitNeedSync)
> >> need_resync = true;
> >>
> >>>
> >>> For example:
> >>>
> >>> cat /sys/block/md127/md/llbitmap/bits
> >>> unwritten 3480
> >>> clean 2
> >>> dirty 0
> >>> need sync 510
> >>>
> >>> It doesn't do resync after aseembling the array. Does it need to modify
> >>> the changed status from x to NeedSync?
> >>
> >> Can you explain in detail how to reporduce this? Aseembling in my VM is
> >> fine.
> >
> > I added many debug logs, so the sync request runs slowly. The test I do:
> > mdadm -CR /dev/md0 -l5 -n3 /dev/loop[0-2] --bitmap=lockless -x 1 /dev/loop3
> > dd if=/dev/zero of=/dev/md0 bs=1M count=1 seek=500 oflag=direct
> > mdadm --stop /dev/md0 (the sync thread finishes the region that two
> > bitmap bits represent, so you can see llbitmap/bits has 510 bits (need
> > sync))
> > mdadm -As
>
> I don't quite understand, in my case, mdadm -As works fine.
Sorry for this, I forgot I removed the codes in function llbitmap_state_machine
//if (c == BitNeedSync)
// need_resync = true;
The reason I do this: I find if the status table changes like this, it
doesn't need to check the original status anymore
- [BitmapActionReload] = BitNone,
+ [BitmapActionReload] = BitNeedSync,//?
Regards
Xiao
Xiao
> >
> > Regards
> > Xiao
> >>
> >> Thanks,
> >> Kuai
> >>
> >>
> >
> >
> > .
> >
>