Skip to content

Commit 24e51e3

Browse files
allanjudetonyhutter
authored andcommitted
Restore FreeBSD sysctl processing for arc.min and arc.max
Before OpenZFS 2.0, trying to set the FreeBSD sysctl vfs.zfs.arc_max to a disallowed value would return an error. Since the switch, it instead only generates WARN_IF_TUNING_IGNORED Keep the ability to set the sysctl's specifically to 0, even though that is less than the minimum, because some tests depend on this. Also lost, was the ability to set vfs.zfs.arc_max to a value less than the default vfs.zfs.arc_min at boot time. Restore this as well. Reviewed-by: Tony Nguyen <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Allan Jude <[email protected]> Closes openzfs#12161
1 parent 744f300 commit 24e51e3

File tree

6 files changed

+98
-6
lines changed

6 files changed

+98
-6
lines changed

include/os/freebsd/spl/sys/mod_os.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@
6262
#define param_set_arc_long_args(var) \
6363
CTLTYPE_ULONG, &var, 0, param_set_arc_long, "LU"
6464

65+
#define param_set_arc_min_args(var) \
66+
CTLTYPE_ULONG, &var, 0, param_set_arc_min, "LU"
67+
68+
#define param_set_arc_max_args(var) \
69+
CTLTYPE_ULONG, &var, 0, param_set_arc_max, "LU"
70+
6571
#define param_set_arc_int_args(var) \
6672
CTLTYPE_INT, &var, 0, param_set_arc_int, "I"
6773

include/sys/arc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ extern "C" {
4646
*/
4747
#define ARC_EVICT_ALL UINT64_MAX
4848

49+
/*
50+
* ZFS gets very unhappy when the maximum ARC size is smaller than the maximum
51+
* block size and a larger block is written. To leave some safety margin, we
52+
* limit the minimum for zfs_arc_max to the maximium transaction size.
53+
*/
54+
#define MIN_ARC_MAX DMU_MAX_ACCESS
55+
4956
#define HDR_SET_LSIZE(hdr, x) do { \
5057
ASSERT(IS_P2ALIGNED(x, 1U << SPA_MINBLOCKSHIFT)); \
5158
(hdr)->b_lsize = ((x) >> SPA_MINBLOCKSHIFT); \

include/sys/arc_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,8 @@ extern void arc_unregister_hotplug(void);
10051005

10061006
extern int param_set_arc_long(ZFS_MODULE_PARAM_ARGS);
10071007
extern int param_set_arc_int(ZFS_MODULE_PARAM_ARGS);
1008+
extern int param_set_arc_min(ZFS_MODULE_PARAM_ARGS);
1009+
extern int param_set_arc_max(ZFS_MODULE_PARAM_ARGS);
10081010

10091011
/* used in zdb.c */
10101012
boolean_t l2arc_log_blkptr_valid(l2arc_dev_t *dev,

module/os/freebsd/zfs/sysctl_os.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,55 @@ extern arc_state_t ARC_l2c_only;
144144

145145
/* arc.c */
146146

147+
int
148+
param_set_arc_max(SYSCTL_HANDLER_ARGS)
149+
{
150+
uint64_t val;
151+
int err;
152+
153+
val = zfs_arc_max;
154+
err = sysctl_handle_long(oidp, &val, 0, req);
155+
if (err != 0 || req->newptr == NULL)
156+
return (SET_ERROR(err));
157+
158+
if (val != 0 && (val < MIN_ARC_MAX || val <= arc_c_min ||
159+
val >= arc_all_memory()))
160+
return (SET_ERROR(EINVAL));
161+
162+
zfs_arc_max = val;
163+
arc_tuning_update(B_TRUE);
164+
165+
/* Update the sysctl to the tuned value */
166+
if (val != 0)
167+
zfs_arc_max = arc_c_max;
168+
169+
return (0);
170+
}
171+
172+
int
173+
param_set_arc_min(SYSCTL_HANDLER_ARGS)
174+
{
175+
uint64_t val;
176+
int err;
177+
178+
val = zfs_arc_min;
179+
err = sysctl_handle_64(oidp, &val, 0, req);
180+
if (err != 0 || req->newptr == NULL)
181+
return (SET_ERROR(err));
182+
183+
if (val != 0 && (val < 2ULL << SPA_MAXBLOCKSHIFT || val > arc_c_max))
184+
return (SET_ERROR(EINVAL));
185+
186+
zfs_arc_min = val;
187+
arc_tuning_update(B_TRUE);
188+
189+
/* Update the sysctl to the tuned value */
190+
if (val != 0)
191+
zfs_arc_min = arc_c_min;
192+
193+
return (0);
194+
}
195+
147196
/* legacy compat */
148197
extern uint64_t l2arc_write_max; /* def max write size */
149198
extern uint64_t l2arc_write_boost; /* extra warmup write */
@@ -278,11 +327,11 @@ param_set_arc_int(SYSCTL_HANDLER_ARGS)
278327

279328
SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_min,
280329
CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
281-
&zfs_arc_min, sizeof (zfs_arc_min), param_set_arc_long, "LU",
330+
&zfs_arc_min, sizeof (zfs_arc_min), param_set_arc_min, "LU",
282331
"min arc size (LEGACY)");
283332
SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_max,
284333
CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
285-
&zfs_arc_max, sizeof (zfs_arc_max), param_set_arc_long, "LU",
334+
&zfs_arc_max, sizeof (zfs_arc_max), param_set_arc_max, "LU",
286335
"max arc size (LEGACY)");
287336

288337
/* dbuf.c */

module/os/linux/zfs/arc_os.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,18 @@ param_set_arc_long(const char *buf, zfs_kernel_param_t *kp)
371371
return (0);
372372
}
373373

374+
int
375+
param_set_arc_min(const char *buf, zfs_kernel_param_t *kp)
376+
{
377+
return (param_set_arc_long(buf, kp));
378+
}
379+
380+
int
381+
param_set_arc_max(const char *buf, zfs_kernel_param_t *kp)
382+
{
383+
return (param_set_arc_long(buf, kp));
384+
}
385+
374386
int
375387
param_set_arc_int(const char *buf, zfs_kernel_param_t *kp)
376388
{

module/zfs/arc.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7503,7 +7503,7 @@ arc_tuning_update(boolean_t verbose)
75037503

75047504
/* Valid range: 64M - <all physical memory> */
75057505
if ((zfs_arc_max) && (zfs_arc_max != arc_c_max) &&
7506-
(zfs_arc_max >= 64 << 20) && (zfs_arc_max < allmem) &&
7506+
(zfs_arc_max >= MIN_ARC_MAX) && (zfs_arc_max < allmem) &&
75077507
(zfs_arc_max > arc_c_min)) {
75087508
arc_c_max = zfs_arc_max;
75097509
arc_c = MIN(arc_c, arc_c_max);
@@ -7898,7 +7898,23 @@ arc_init(void)
78987898

78997899
arc_set_limits(allmem);
79007900

7901-
#ifndef _KERNEL
7901+
#ifdef _KERNEL
7902+
/*
7903+
* If zfs_arc_max is non-zero at init, meaning it was set in the kernel
7904+
* environment before the module was loaded, don't block setting the
7905+
* maximum because it is less than arc_c_min, instead, reset arc_c_min
7906+
* to a lower value.
7907+
* zfs_arc_min will be handled by arc_tuning_update().
7908+
*/
7909+
if (zfs_arc_max != 0 && zfs_arc_max >= MIN_ARC_MAX &&
7910+
zfs_arc_max < allmem) {
7911+
arc_c_max = zfs_arc_max;
7912+
if (arc_c_min >= arc_c_max) {
7913+
arc_c_min = MAX(zfs_arc_max / 2,
7914+
2ULL << SPA_MAXBLOCKSHIFT);
7915+
}
7916+
}
7917+
#else
79027918
/*
79037919
* In userland, there's only the memory pressure that we artificially
79047920
* create (see arc_available_memory()). Don't let arc_c get too
@@ -10959,10 +10975,10 @@ EXPORT_SYMBOL(arc_add_prune_callback);
1095910975
EXPORT_SYMBOL(arc_remove_prune_callback);
1096010976

1096110977
/* BEGIN CSTYLED */
10962-
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, min, param_set_arc_long,
10978+
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, min, param_set_arc_min,
1096310979
param_get_long, ZMOD_RW, "Min arc size");
1096410980

10965-
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, max, param_set_arc_long,
10981+
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, max, param_set_arc_max,
1096610982
param_get_long, ZMOD_RW, "Max arc size");
1096710983

1096810984
ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, meta_limit, param_set_arc_long,

0 commit comments

Comments
 (0)