Enable iterating all sysctls, even ones with CTLFLAG_SKIP
Add an "nextnoskip" sysctl that allows for listing of sysctls intended to be normally skipped for cost reasons. This makes it so the names/descriptions of those sysctls can be discovered with sysctl -aN/sysctl -ad/sysctl -at. It also makes it so children are visited when a node flagged with CTLFLAG_SKIP is explicitly requested. The intended use case is to mark the root "kstat" node with CTLFLAG_SKIP so that the extensive and expensive stats are skipped by default but may still be easily obtained without having to know them all (which may not even be possible) and request each one-by-one. Reviewed by: jhb MFC after: 2 weeks Relnotes: yes Sponsored by: iXsystems, Inc. Differential Revision: https://reviews.freebsd.org/D26560
This commit is contained in:
parent
ce3e137ca1
commit
92e17803cd
@ -81,7 +81,7 @@ static int Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag;
|
||||
static int oidfmt(int *, int, char *, u_int *);
|
||||
static int parsefile(const char *);
|
||||
static int parse(const char *, int);
|
||||
static int show_var(int *, int);
|
||||
static int show_var(int *, int, bool);
|
||||
static int sysctl_all(int *oid, int len);
|
||||
static int name2oid(const char *, int *);
|
||||
|
||||
@ -428,13 +428,13 @@ parse(const char *string, int lineno)
|
||||
if (newvalstr == NULL || dflag) {
|
||||
if ((kind & CTLTYPE) == CTLTYPE_NODE) {
|
||||
if (dflag) {
|
||||
i = show_var(mib, len);
|
||||
i = show_var(mib, len, false);
|
||||
if (!i && !bflag)
|
||||
putchar('\n');
|
||||
}
|
||||
sysctl_all(mib, len);
|
||||
} else {
|
||||
i = show_var(mib, len);
|
||||
i = show_var(mib, len, false);
|
||||
if (!i && !bflag)
|
||||
putchar('\n');
|
||||
}
|
||||
@ -504,7 +504,7 @@ parse(const char *string, int lineno)
|
||||
break;
|
||||
}
|
||||
|
||||
i = show_var(mib, len);
|
||||
i = show_var(mib, len, false);
|
||||
if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
|
||||
free(newbuf);
|
||||
if (!i && !bflag)
|
||||
@ -532,7 +532,7 @@ parse(const char *string, int lineno)
|
||||
printf(" -> ");
|
||||
i = nflag;
|
||||
nflag = 1;
|
||||
j = show_var(mib, len);
|
||||
j = show_var(mib, len, false);
|
||||
if (!j && !bflag)
|
||||
putchar('\n');
|
||||
nflag = i;
|
||||
@ -942,7 +942,7 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
|
||||
* Return minus one if we had errors.
|
||||
*/
|
||||
static int
|
||||
show_var(int *oid, int nlen)
|
||||
show_var(int *oid, int nlen, bool honor_skip)
|
||||
{
|
||||
u_char buf[BUFSIZ], *val, *oval, *p;
|
||||
char name[BUFSIZ], fmt[BUFSIZ];
|
||||
@ -976,11 +976,11 @@ show_var(int *oid, int nlen)
|
||||
oidfmt(oid, nlen, fmt, &kind);
|
||||
/* if Wflag then only list sysctls that are writeable and not stats. */
|
||||
if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0))
|
||||
return 1;
|
||||
return (1);
|
||||
|
||||
/* if Tflag then only list sysctls that are tuneables. */
|
||||
if (Tflag && (kind & CTLFLAG_TUN) == 0)
|
||||
return 1;
|
||||
return (1);
|
||||
|
||||
if (Nflag) {
|
||||
printf("%s", name);
|
||||
@ -1013,6 +1013,10 @@ show_var(int *oid, int nlen)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* bail before fetching the value if we're honoring skip */
|
||||
if (honor_skip && (kind & CTLFLAG_SKIP) != 0)
|
||||
return (1);
|
||||
|
||||
/* don't fetch opaques that we don't know how to print */
|
||||
if (ctltype == CTLTYPE_OPAQUE) {
|
||||
if (strcmp(fmt, "S,clockinfo") == 0)
|
||||
@ -1195,15 +1199,17 @@ sysctl_all(int *oid, int len)
|
||||
int name1[22], name2[22];
|
||||
int i, j;
|
||||
size_t l1, l2;
|
||||
bool honor_skip = false;
|
||||
|
||||
name1[0] = 0;
|
||||
name1[1] = 2;
|
||||
name1[0] = CTL_SYSCTL;
|
||||
name1[1] = (oid != NULL || Nflag || dflag || tflag) ?
|
||||
CTL_SYSCTL_NEXTNOSKIP : CTL_SYSCTL_NEXT;
|
||||
l1 = 2;
|
||||
if (len) {
|
||||
memcpy(name1+2, oid, len * sizeof(int));
|
||||
memcpy(name1 + 2, oid, len * sizeof(int));
|
||||
l1 += len;
|
||||
} else {
|
||||
name1[2] = 1;
|
||||
name1[2] = CTL_KERN;
|
||||
l1++;
|
||||
}
|
||||
for (;;) {
|
||||
@ -1225,11 +1231,12 @@ sysctl_all(int *oid, int len)
|
||||
if (name2[i] != oid[i])
|
||||
return (0);
|
||||
|
||||
i = show_var(name2, l2);
|
||||
i = show_var(name2, l2, honor_skip);
|
||||
if (!i && !bflag)
|
||||
putchar('\n');
|
||||
|
||||
memcpy(name1+2, name2, l2 * sizeof(int));
|
||||
memcpy(name1 + 2, name2, l2 * sizeof(int));
|
||||
l1 = 2 + l2;
|
||||
honor_skip = true;
|
||||
}
|
||||
}
|
||||
|
@ -950,7 +950,8 @@ SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL);
|
||||
* {CTL_SYSCTL, CTL_SYSCTL_DEBUG} printf the entire MIB-tree.
|
||||
* {CTL_SYSCTL, CTL_SYSCTL_NAME, ...} return the name of the "..."
|
||||
* OID.
|
||||
* {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...} return the next OID.
|
||||
* {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...} return the next OID, honoring
|
||||
* CTLFLAG_SKIP.
|
||||
* {CTL_SYSCTL, CTL_SYSCTL_NAME2OID} return the OID of the name in
|
||||
* "new"
|
||||
* {CTL_SYSCTL, CTL_SYSCTL_OIDFMT, ...} return the kind & format info
|
||||
@ -959,6 +960,8 @@ SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL);
|
||||
* "..." OID.
|
||||
* {CTL_SYSCTL, CTL_SYSCTL_OIDLABEL, ...} return the aggregation label of
|
||||
* the "..." OID.
|
||||
* {CTL_SYSCTL, CTL_SYSCTL_NEXTNOSKIP, ...} return the next OID, ignoring
|
||||
* CTLFLAG_SKIP.
|
||||
*/
|
||||
|
||||
#ifdef SYSCTL_DEBUG
|
||||
@ -1099,7 +1102,7 @@ static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NAME, name, CTLFLAG_RD |
|
||||
|
||||
static int
|
||||
sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
|
||||
int *next, int *len, int level, struct sysctl_oid **oidpp)
|
||||
int *next, int *len, int level, struct sysctl_oid **oidpp, bool honor_skip)
|
||||
{
|
||||
struct sysctl_oid *oidp;
|
||||
|
||||
@ -1109,7 +1112,10 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
|
||||
*next = oidp->oid_number;
|
||||
*oidpp = oidp;
|
||||
|
||||
if ((oidp->oid_kind & (CTLFLAG_SKIP | CTLFLAG_DORMANT)) != 0)
|
||||
if ((oidp->oid_kind & CTLFLAG_DORMANT) != 0)
|
||||
continue;
|
||||
|
||||
if (honor_skip && (oidp->oid_kind & CTLFLAG_SKIP) != 0)
|
||||
continue;
|
||||
|
||||
if (!namelen) {
|
||||
@ -1120,7 +1126,7 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
|
||||
return (0);
|
||||
lsp = SYSCTL_CHILDREN(oidp);
|
||||
if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1,
|
||||
len, level+1, oidpp))
|
||||
len, level+1, oidpp, honor_skip))
|
||||
return (0);
|
||||
goto emptynode;
|
||||
}
|
||||
@ -1135,7 +1141,7 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
|
||||
return (0);
|
||||
lsp = SYSCTL_CHILDREN(oidp);
|
||||
if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1,
|
||||
next+1, len, level+1, oidpp))
|
||||
next+1, len, level+1, oidpp, honor_skip))
|
||||
return (0);
|
||||
goto next;
|
||||
}
|
||||
@ -1147,14 +1153,14 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
|
||||
|
||||
lsp = SYSCTL_CHILDREN(oidp);
|
||||
if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1,
|
||||
len, level+1, oidpp))
|
||||
len, level+1, oidpp, honor_skip))
|
||||
return (0);
|
||||
next:
|
||||
namelen = 1;
|
||||
emptynode:
|
||||
*len = level;
|
||||
}
|
||||
return (1);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1162,18 +1168,19 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int *name = (int *) arg1;
|
||||
u_int namelen = arg2;
|
||||
int i, j, error;
|
||||
int len, error;
|
||||
struct sysctl_oid *oid;
|
||||
struct sysctl_oid_list *lsp = &sysctl__children;
|
||||
struct rm_priotracker tracker;
|
||||
int newoid[CTL_MAXNAME];
|
||||
int next[CTL_MAXNAME];
|
||||
|
||||
SYSCTL_RLOCK(&tracker);
|
||||
i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
|
||||
error = sysctl_sysctl_next_ls(lsp, name, namelen, next, &len, 1, &oid,
|
||||
oidp->oid_number == CTL_SYSCTL_NEXT);
|
||||
SYSCTL_RUNLOCK(&tracker);
|
||||
if (i)
|
||||
return (ENOENT);
|
||||
error = SYSCTL_OUT(req, newoid, j * sizeof (int));
|
||||
if (error)
|
||||
return (error);
|
||||
error = SYSCTL_OUT(req, next, len * sizeof (int));
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1184,6 +1191,9 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
|
||||
static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXT, next, CTLFLAG_RD |
|
||||
CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
|
||||
|
||||
static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXTNOSKIP, nextnoskip, CTLFLAG_RD |
|
||||
CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
|
||||
|
||||
static int
|
||||
name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
|
||||
{
|
||||
@ -2726,10 +2736,10 @@ db_show_sysctl_all(int *oid, size_t len, int flags)
|
||||
name1[1] = CTL_SYSCTL_NEXT;
|
||||
l1 = 2;
|
||||
if (len) {
|
||||
memcpy(name1+2, oid, len * sizeof(int));
|
||||
l1 +=len;
|
||||
memcpy(name1 + 2, oid, len * sizeof(int));
|
||||
l1 += len;
|
||||
} else {
|
||||
name1[2] = 1;
|
||||
name1[2] = CTL_KERN;
|
||||
l1++;
|
||||
}
|
||||
for (;;) {
|
||||
@ -2742,7 +2752,7 @@ db_show_sysctl_all(int *oid, size_t len, int flags)
|
||||
if (error == ENOENT)
|
||||
return (0);
|
||||
else
|
||||
db_error("sysctl(getnext)");
|
||||
db_error("sysctl(next)");
|
||||
}
|
||||
|
||||
l2 /= sizeof(int);
|
||||
|
@ -934,11 +934,12 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
|
||||
*/
|
||||
#define CTL_SYSCTL_DEBUG 0 /* printf all nodes */
|
||||
#define CTL_SYSCTL_NAME 1 /* string name of OID */
|
||||
#define CTL_SYSCTL_NEXT 2 /* next OID */
|
||||
#define CTL_SYSCTL_NEXT 2 /* next OID, honoring CTLFLAG_SKIP */
|
||||
#define CTL_SYSCTL_NAME2OID 3 /* int array of name */
|
||||
#define CTL_SYSCTL_OIDFMT 4 /* OID's kind and format */
|
||||
#define CTL_SYSCTL_OIDDESCR 5 /* OID's description */
|
||||
#define CTL_SYSCTL_OIDLABEL 6 /* aggregation label */
|
||||
#define CTL_SYSCTL_NEXTNOSKIP 7 /* next OID, ignoring CTLFLAG_SKIP */
|
||||
|
||||
/*
|
||||
* CTL_KERN identifiers
|
||||
|
@ -2360,6 +2360,9 @@ print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
|
||||
fprintf(fp, "oidlabel ");
|
||||
print_sysctl(fp, oid + 2, len - 2);
|
||||
break;
|
||||
case CTL_SYSCTL_NEXTNOSKIP:
|
||||
fprintf(fp, "nextnoskip");
|
||||
break;
|
||||
default:
|
||||
print_sysctl(fp, oid + 1, len - 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user