Skip to content

Commit e1952e4

Browse files
committed
Sleep periodically when rebuilding L2ARC.
L2ARC devices of several terabytes filled with 4KB blocks may take 15 minutes to rebuild. Due to the way L2ARC log reading is implemented it is quite likely that for all that time rebuild thread will never sleep. At least on FreeBSD kernel threads have absolute priority and can not be preempted by threads with lower priorities. If some thread is also bound to that specific CPU it may not get any CPU time for all the 15 minutes. This patch adds small throttling to the rebuild process, putting it into sleep for 1 tick every 10 log block. On my system this means approximately 1ms every 10ms, reaching the single CPU usage of ~90%. Signed-off-by: Alexander Motin <[email protected]>
1 parent 5c810ac commit e1952e4

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

man/man5/zfs-module-parameters.5

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,19 @@ has become somehow fragmented/unusable).
325325
Use \fB1\fR for yes (default) and \fB0\fR for no.
326326
.RE
327327

328+
.sp
329+
.ne 2
330+
.na
331+
\fBl2arc_rebuild_batch\fR (int)
332+
.ad
333+
.RS 12n
334+
Number of L2ARC log blocks to process before sleeping for a tick to relieve
335+
some CPU and let scheduler switch the context.
336+
Setting this value to 0 will disable the throttle.
337+
.sp
338+
Default value: \fB10\fR.
339+
.RE
340+
328341
.sp
329342
.ne 2
330343
.na

module/zfs/arc.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,8 @@ unsigned long l2arc_trim_ahead = 0;
942942
* l2arc_rebuild_enabled : A ZFS module parameter that controls whether adding
943943
* an L2ARC device (either at pool import or later) will attempt
944944
* to rebuild L2ARC buffer contents.
945+
* l2arc_rebuild_batch: Number of blocks to process before sleeping for 1/hz
946+
* to relieve some CPU and let scheduler switch the context.
945947
* l2arc_rebuild_blocks_min_l2size : A ZFS module parameter that controls
946948
* whether log blocks are written to the L2ARC device. If the L2ARC
947949
* device is less than 1GB, the amount of data l2arc_evict()
@@ -950,6 +952,7 @@ unsigned long l2arc_trim_ahead = 0;
950952
* not to waste space.
951953
*/
952954
int l2arc_rebuild_enabled = B_TRUE;
955+
int l2arc_rebuild_batch = 10;
953956
unsigned long l2arc_rebuild_blocks_min_l2size = 1024 * 1024 * 1024;
954957

955958
/* L2ARC persistence rebuild control routines. */
@@ -9767,7 +9770,7 @@ l2arc_rebuild(l2arc_dev_t *dev)
97679770
{
97689771
vdev_t *vd = dev->l2ad_vdev;
97699772
spa_t *spa = vd->vdev_spa;
9770-
int err = 0;
9773+
int err = 0, batch = 0;
97719774
l2arc_dev_hdr_phys_t *l2dhdr = dev->l2ad_dev_hdr;
97729775
l2arc_log_blk_phys_t *this_lb, *next_lb;
97739776
zio_t *this_io = NULL, *next_io = NULL;
@@ -9893,6 +9896,14 @@ l2arc_rebuild(l2arc_dev_t *dev)
98939896
!dev->l2ad_first)
98949897
goto out;
98959898

9899+
/*
9900+
* Release the CPU periodically to not monopolize it.
9901+
*/
9902+
if (l2arc_rebuild_batch && ++batch >= l2arc_rebuild_batch) {
9903+
batch = 0;
9904+
delay(1);
9905+
}
9906+
98969907
for (;;) {
98979908
mutex_enter(&l2arc_rebuild_thr_lock);
98989909
if (dev->l2ad_rebuild_cancel) {
@@ -10719,6 +10730,9 @@ ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, meta_percent, INT, ZMOD_RW,
1071910730
ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, rebuild_enabled, INT, ZMOD_RW,
1072010731
"Rebuild the L2ARC when importing a pool");
1072110732

10733+
ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, rebuild_batch, INT, ZMOD_RW,
10734+
"Number of blocks to process before sleeping for 1/hz");
10735+
1072210736
ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, rebuild_blocks_min_l2size, ULONG, ZMOD_RW,
1072310737
"Min size in bytes to write rebuild log blocks in L2ARC");
1072410738

0 commit comments

Comments
 (0)