@@ -208,6 +208,20 @@ enum llbitmap_state {
208208 BitNeedSync ,
209209 /* data is synchronizing */
210210 BitSyncing ,
211+ /*
212+ * Proactive sync requested for unwritten region (raid456 only).
213+ * Triggered via sysfs when user wants to pre-build XOR parity
214+ * for regions that have never been written.
215+ */
216+ BitNeedSyncUnwritten ,
217+ /* Proactive sync in progress for unwritten region */
218+ BitSyncingUnwritten ,
219+ /*
220+ * XOR parity has been pre-built for a region that has never had
221+ * user data written. When user writes to this region, it transitions
222+ * to BitDirty.
223+ */
224+ BitCleanUnwritten ,
211225 BitStateCount ,
212226 BitNone = 0xff ,
213227};
@@ -232,6 +246,12 @@ enum llbitmap_action {
232246 * BitNeedSync.
233247 */
234248 BitmapActionStale ,
249+ /*
250+ * Proactive sync trigger for raid456 - builds XOR parity for
251+ * Unwritten regions without requiring user data write first.
252+ */
253+ BitmapActionProactiveSync ,
254+ BitmapActionClearUnwritten ,
235255 BitmapActionCount ,
236256 /* Init state is BitUnwritten */
237257 BitmapActionInit ,
@@ -304,6 +324,8 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
304324 [BitmapActionDaemon ] = BitNone ,
305325 [BitmapActionDiscard ] = BitNone ,
306326 [BitmapActionStale ] = BitNone ,
327+ [BitmapActionProactiveSync ] = BitNeedSyncUnwritten ,
328+ [BitmapActionClearUnwritten ] = BitNone ,
307329 },
308330 [BitClean ] = {
309331 [BitmapActionStartwrite ] = BitDirty ,
@@ -314,6 +336,8 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
314336 [BitmapActionDaemon ] = BitNone ,
315337 [BitmapActionDiscard ] = BitUnwritten ,
316338 [BitmapActionStale ] = BitNeedSync ,
339+ [BitmapActionProactiveSync ] = BitNone ,
340+ [BitmapActionClearUnwritten ] = BitNone ,
317341 },
318342 [BitDirty ] = {
319343 [BitmapActionStartwrite ] = BitNone ,
@@ -324,6 +348,8 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
324348 [BitmapActionDaemon ] = BitClean ,
325349 [BitmapActionDiscard ] = BitUnwritten ,
326350 [BitmapActionStale ] = BitNeedSync ,
351+ [BitmapActionProactiveSync ] = BitNone ,
352+ [BitmapActionClearUnwritten ] = BitNone ,
327353 },
328354 [BitNeedSync ] = {
329355 [BitmapActionStartwrite ] = BitNone ,
@@ -334,6 +360,8 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
334360 [BitmapActionDaemon ] = BitNone ,
335361 [BitmapActionDiscard ] = BitUnwritten ,
336362 [BitmapActionStale ] = BitNone ,
363+ [BitmapActionProactiveSync ] = BitNone ,
364+ [BitmapActionClearUnwritten ] = BitNone ,
337365 },
338366 [BitSyncing ] = {
339367 [BitmapActionStartwrite ] = BitNone ,
@@ -344,6 +372,44 @@ static char state_machine[BitStateCount][BitmapActionCount] = {
344372 [BitmapActionDaemon ] = BitNone ,
345373 [BitmapActionDiscard ] = BitUnwritten ,
346374 [BitmapActionStale ] = BitNeedSync ,
375+ [BitmapActionProactiveSync ] = BitNone ,
376+ [BitmapActionClearUnwritten ] = BitNone ,
377+ },
378+ [BitNeedSyncUnwritten ] = {
379+ [BitmapActionStartwrite ] = BitNeedSync ,
380+ [BitmapActionStartsync ] = BitSyncingUnwritten ,
381+ [BitmapActionEndsync ] = BitNone ,
382+ [BitmapActionAbortsync ] = BitUnwritten ,
383+ [BitmapActionReload ] = BitUnwritten ,
384+ [BitmapActionDaemon ] = BitNone ,
385+ [BitmapActionDiscard ] = BitUnwritten ,
386+ [BitmapActionStale ] = BitUnwritten ,
387+ [BitmapActionProactiveSync ] = BitNone ,
388+ [BitmapActionClearUnwritten ] = BitUnwritten ,
389+ },
390+ [BitSyncingUnwritten ] = {
391+ [BitmapActionStartwrite ] = BitSyncing ,
392+ [BitmapActionStartsync ] = BitSyncingUnwritten ,
393+ [BitmapActionEndsync ] = BitCleanUnwritten ,
394+ [BitmapActionAbortsync ] = BitUnwritten ,
395+ [BitmapActionReload ] = BitUnwritten ,
396+ [BitmapActionDaemon ] = BitNone ,
397+ [BitmapActionDiscard ] = BitUnwritten ,
398+ [BitmapActionStale ] = BitUnwritten ,
399+ [BitmapActionProactiveSync ] = BitNone ,
400+ [BitmapActionClearUnwritten ] = BitUnwritten ,
401+ },
402+ [BitCleanUnwritten ] = {
403+ [BitmapActionStartwrite ] = BitDirty ,
404+ [BitmapActionStartsync ] = BitNone ,
405+ [BitmapActionEndsync ] = BitNone ,
406+ [BitmapActionAbortsync ] = BitNone ,
407+ [BitmapActionReload ] = BitNone ,
408+ [BitmapActionDaemon ] = BitNone ,
409+ [BitmapActionDiscard ] = BitUnwritten ,
410+ [BitmapActionStale ] = BitUnwritten ,
411+ [BitmapActionProactiveSync ] = BitNone ,
412+ [BitmapActionClearUnwritten ] = BitUnwritten ,
347413 },
348414};
349415
@@ -376,14 +442,15 @@ static void llbitmap_infect_dirty_bits(struct llbitmap *llbitmap,
376442 pctl -> state [pos ] = level_456 ? BitNeedSync : BitDirty ;
377443 break ;
378444 case BitClean :
445+ case BitCleanUnwritten :
379446 pctl -> state [pos ] = BitDirty ;
380447 break ;
381448 }
382449 }
383450}
384451
385452static void llbitmap_set_page_dirty (struct llbitmap * llbitmap , int idx ,
386- int offset )
453+ int offset , bool infect )
387454{
388455 struct llbitmap_page_ctl * pctl = llbitmap -> pctl [idx ];
389456 unsigned int io_size = llbitmap -> io_size ;
@@ -398,7 +465,7 @@ static void llbitmap_set_page_dirty(struct llbitmap *llbitmap, int idx,
398465 * resync all the dirty bits, hence skip infect new dirty bits to
399466 * prevent resync unnecessary data.
400467 */
401- if (llbitmap -> mddev -> degraded ) {
468+ if (llbitmap -> mddev -> degraded || ! infect ) {
402469 set_bit (block , pctl -> dirty );
403470 return ;
404471 }
@@ -438,7 +505,9 @@ static void llbitmap_write(struct llbitmap *llbitmap, enum llbitmap_state state,
438505
439506 llbitmap -> pctl [idx ]-> state [bit ] = state ;
440507 if (state == BitDirty || state == BitNeedSync )
441- llbitmap_set_page_dirty (llbitmap , idx , bit );
508+ llbitmap_set_page_dirty (llbitmap , idx , bit , true);
509+ else if (state == BitNeedSyncUnwritten )
510+ llbitmap_set_page_dirty (llbitmap , idx , bit , false);
442511}
443512
444513static struct page * llbitmap_read_page (struct llbitmap * llbitmap , int idx )
@@ -627,11 +696,10 @@ static enum llbitmap_state llbitmap_state_machine(struct llbitmap *llbitmap,
627696 goto write_bitmap ;
628697 }
629698
630- if (c == BitNeedSync )
699+ if (c == BitNeedSync || c == BitNeedSyncUnwritten )
631700 need_resync = !mddev -> degraded ;
632701
633702 state = state_machine [c ][action ];
634-
635703write_bitmap :
636704 if (unlikely (mddev -> degraded )) {
637705 /* For degraded array, mark new data as need sync. */
@@ -658,8 +726,7 @@ static enum llbitmap_state llbitmap_state_machine(struct llbitmap *llbitmap,
658726 }
659727
660728 llbitmap_write (llbitmap , state , start );
661-
662- if (state == BitNeedSync )
729+ if (state == BitNeedSync || state == BitNeedSyncUnwritten )
663730 need_resync = !mddev -> degraded ;
664731 else if (state == BitDirty &&
665732 !timer_pending (& llbitmap -> pending_timer ))
@@ -1229,7 +1296,7 @@ static bool llbitmap_blocks_synced(struct mddev *mddev, sector_t offset)
12291296 unsigned long p = offset >> llbitmap -> chunkshift ;
12301297 enum llbitmap_state c = llbitmap_read (llbitmap , p );
12311298
1232- return c == BitClean || c == BitDirty ;
1299+ return c == BitClean || c == BitDirty || c == BitCleanUnwritten ;
12331300}
12341301
12351302static sector_t llbitmap_skip_sync_blocks (struct mddev * mddev , sector_t offset )
@@ -1243,6 +1310,10 @@ static sector_t llbitmap_skip_sync_blocks(struct mddev *mddev, sector_t offset)
12431310 if (c == BitUnwritten )
12441311 return blocks ;
12451312
1313+ /* Skip CleanUnwritten - no user data, will be reset after recovery */
1314+ if (c == BitCleanUnwritten )
1315+ return blocks ;
1316+
12461317 /* For degraded array, don't skip */
12471318 if (mddev -> degraded )
12481319 return 0 ;
@@ -1261,14 +1332,25 @@ static bool llbitmap_start_sync(struct mddev *mddev, sector_t offset,
12611332{
12621333 struct llbitmap * llbitmap = mddev -> bitmap ;
12631334 unsigned long p = offset >> llbitmap -> chunkshift ;
1335+ enum llbitmap_state state ;
1336+
1337+ /*
1338+ * Before recovery starts, convert CleanUnwritten to Unwritten.
1339+ * This ensures the new disk won't have stale parity data.
1340+ */
1341+ if (offset == 0 && test_bit (MD_RECOVERY_RECOVER , & mddev -> recovery ) &&
1342+ !test_bit (MD_RECOVERY_LAZY_RECOVER , & mddev -> recovery ))
1343+ llbitmap_state_machine (llbitmap , 0 , llbitmap -> chunks - 1 ,
1344+ BitmapActionClearUnwritten );
1345+
12641346
12651347 /*
12661348 * Handle one bit at a time, this is much simpler. And it doesn't matter
12671349 * if md_do_sync() loop more times.
12681350 */
12691351 * blocks = llbitmap -> chunksize - (offset & (llbitmap -> chunksize - 1 ));
1270- return llbitmap_state_machine (llbitmap , p , p ,
1271- BitmapActionStartsync ) == BitSyncing ;
1352+ state = llbitmap_state_machine (llbitmap , p , p , BitmapActionStartsync );
1353+ return state == BitSyncing || state == BitSyncingUnwritten ;
12721354}
12731355
12741356/* Something is wrong, sync_thread stop at @offset */
@@ -1474,9 +1556,15 @@ static ssize_t bits_show(struct mddev *mddev, char *page)
14741556 }
14751557
14761558 mutex_unlock (& mddev -> bitmap_info .mutex );
1477- return sprintf (page , "unwritten %d\nclean %d\ndirty %d\nneed sync %d\nsyncing %d\n" ,
1559+ return sprintf (page ,
1560+ "unwritten %d\nclean %d\ndirty %d\n"
1561+ "need sync %d\nsyncing %d\n"
1562+ "need sync unwritten %d\nsyncing unwritten %d\n"
1563+ "clean unwritten %d\n" ,
14781564 bits [BitUnwritten ], bits [BitClean ], bits [BitDirty ],
1479- bits [BitNeedSync ], bits [BitSyncing ]);
1565+ bits [BitNeedSync ], bits [BitSyncing ],
1566+ bits [BitNeedSyncUnwritten ], bits [BitSyncingUnwritten ],
1567+ bits [BitCleanUnwritten ]);
14801568}
14811569
14821570static struct md_sysfs_entry llbitmap_bits = __ATTR_RO (bits );
@@ -1549,11 +1637,39 @@ barrier_idle_store(struct mddev *mddev, const char *buf, size_t len)
15491637
15501638static struct md_sysfs_entry llbitmap_barrier_idle = __ATTR_RW (barrier_idle );
15511639
1640+ static ssize_t
1641+ proactive_sync_store (struct mddev * mddev , const char * buf , size_t len )
1642+ {
1643+ struct llbitmap * llbitmap ;
1644+
1645+ /* Only for RAID-456 */
1646+ if (!raid_is_456 (mddev ))
1647+ return - EINVAL ;
1648+
1649+ mutex_lock (& mddev -> bitmap_info .mutex );
1650+ llbitmap = mddev -> bitmap ;
1651+ if (!llbitmap || !llbitmap -> pctl ) {
1652+ mutex_unlock (& mddev -> bitmap_info .mutex );
1653+ return - ENODEV ;
1654+ }
1655+
1656+ /* Trigger proactive sync on all Unwritten regions */
1657+ llbitmap_state_machine (llbitmap , 0 , llbitmap -> chunks - 1 ,
1658+ BitmapActionProactiveSync );
1659+
1660+ mutex_unlock (& mddev -> bitmap_info .mutex );
1661+ return len ;
1662+ }
1663+
1664+ static struct md_sysfs_entry llbitmap_proactive_sync =
1665+ __ATTR (proactive_sync , 0200 , NULL , proactive_sync_store );
1666+
15521667static struct attribute * md_llbitmap_attrs [] = {
15531668 & llbitmap_bits .attr ,
15541669 & llbitmap_metadata .attr ,
15551670 & llbitmap_daemon_sleep .attr ,
15561671 & llbitmap_barrier_idle .attr ,
1672+ & llbitmap_proactive_sync .attr ,
15571673 NULL
15581674};
15591675
0 commit comments