From d09154a9e830f0d400ec0447f6532a6aaeeab001 Mon Sep 17 00:00:00 2001 From: hselasky Date: Thu, 26 May 2016 08:41:55 +0000 Subject: [PATCH] Add support for boolean sysctl's. Because the size of bool can be implementation defined, make a bool sysctl handler which handle bools. Userspace sees the bools like unsigned 8-bit integers. Values are filtered to either 1 or 0 upon read and write, similar to what a compiler would do. Requested by: kmacy @ Sponsored by: Mellanox Technologies --- sys/kern/kern_sysctl.c | 35 +++++++++++++++++++++++++++++++++++ sys/sys/sysctl.h | 19 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 37dfff1419d8..5b8870f3b0f2 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1180,6 +1180,41 @@ static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD|CTLFLAG_MPSAFE|CTLFLAG_CAPRD * Default "handler" functions. */ +/* + * Handle a bool. + * Two cases: + * a variable: point arg1 at it. + * a constant: pass it in arg2. + */ + +int +sysctl_handle_bool(SYSCTL_HANDLER_ARGS) +{ + uint8_t temp; + int error; + + /* + * Attempt to get a coherent snapshot by making a copy of the data. + */ + if (arg1) + temp = *(bool *)arg1 ? 1 : 0; + else + temp = arg2 ? 1 : 0; + + error = SYSCTL_OUT(req, &temp, sizeof(temp)); + if (error || !req->newptr) + return (error); + + if (!arg1) + error = EPERM; + else { + error = SYSCTL_IN(req, &temp, sizeof(temp)); + if (!error) + *(bool *)arg1 = temp ? 1 : 0; + } + return (error); +} + /* * Handle an int8_t, signed or unsigned. * Two cases: diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 4590ef9f86e7..c7d8fdb11c0a 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -194,6 +194,7 @@ struct sysctl_oid { #define SYSCTL_OUT(r, p, l) (r->oldfunc)(r, p, l) #define SYSCTL_OUT_STR(r, p) (r->oldfunc)(r, p, strlen(p) + 1) +int sysctl_handle_bool(SYSCTL_HANDLER_ARGS); int sysctl_handle_8(SYSCTL_HANDLER_ARGS); int sysctl_handle_16(SYSCTL_HANDLER_ARGS); int sysctl_handle_32(SYSCTL_HANDLER_ARGS); @@ -329,6 +330,24 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); __arg, len, sysctl_handle_string, "A", __DESCR(descr)); \ }) +/* Oid for a bool. If ptr is NULL, val is returned. */ +#define SYSCTL_NULL_BOOL_PTR ((bool *)NULL) +#define SYSCTL_BOOL(parent, nbr, name, access, ptr, val, descr) \ + SYSCTL_OID(parent, nbr, name, \ + CTLTYPE_U8 | CTLFLAG_MPSAFE | (access), \ + ptr, val, sysctl_handle_bool, "CU", descr); \ + CTASSERT(((access) & CTLTYPE) == 0 && \ + sizeof(bool) == sizeof(*(ptr))) + +#define SYSCTL_ADD_BOOL(ctx, parent, nbr, name, access, ptr, val, descr) \ +({ \ + bool *__ptr = (ptr); \ + CTASSERT(((access) & CTLTYPE) == 0); \ + sysctl_add_oid(ctx, parent, nbr, name, \ + CTLTYPE_U8 | CTLFLAG_MPSAFE | (access), \ + __ptr, val, sysctl_handle_bool, "CU", __DESCR(descr)); \ +}) + /* Oid for a signed 8-bit int. If ptr is NULL, val is returned. */ #define SYSCTL_NULL_S8_PTR ((int8_t *)NULL) #define SYSCTL_S8(parent, nbr, name, access, ptr, val, descr) \