Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115269702
D41825.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D41825.diff
View Options
diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c
--- a/sys/kern/kern_environment.c
+++ b/sys/kern/kern_environment.c
@@ -38,6 +38,7 @@
#include <sys/cdefs.h>
#include <sys/param.h>
+#include <sys/eventhandler.h>
#include <sys/systm.h>
#include <sys/kenv.h>
#include <sys/kernel.h>
@@ -666,6 +667,7 @@
kenvp[i + 1] = NULL;
mtx_unlock(&kenv_lock);
}
+ EVENTHANDLER_INVOKE(setenv, name);
return (0);
}
@@ -689,6 +691,7 @@
kenvp[i] = NULL;
mtx_unlock(&kenv_lock);
zfree(oldenv, M_KENV);
+ EVENTHANDLER_INVOKE(unsetenv, name);
return (0);
}
mtx_unlock(&kenv_lock);
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -127,6 +127,7 @@
int recurse);
static int sysctl_old_kernel(struct sysctl_req *, const void *, size_t);
static int sysctl_new_kernel(struct sysctl_req *, void *, size_t);
+static int name2oid(char *, int *, int *, struct sysctl_oid **);
static struct sysctl_oid *
sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
@@ -512,8 +513,14 @@
if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
(oidp->oid_kind & CTLFLAG_TUN) != 0 &&
(oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
- /* only fetch value once */
- oidp->oid_kind |= CTLFLAG_NOFETCH;
+#ifdef VIMAGE
+ /*
+ * Can fetch value multiple times for VNET loader tunables.
+ * Only fetch once for non-VNET loader tunables.
+ */
+ if ((oidp->oid_kind & CTLFLAG_VNET) == 0)
+#endif
+ oidp->oid_kind |= CTLFLAG_NOFETCH;
/* try to fetch value from kernel environment */
sysctl_load_tunable_by_oid_locked(oidp);
}
@@ -969,6 +976,102 @@
}
SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL);
+#ifdef VIMAGE
+static void
+sysctl_setenv_vnet(void *arg __unused, char *name)
+{
+ struct sysctl_oid *oidp;
+ int oid[CTL_MAXNAME];
+ int error, nlen;
+
+ SYSCTL_WLOCK();
+ error = name2oid(name, oid, &nlen, &oidp);
+ if (error)
+ goto out;
+
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
+ (oidp->oid_kind & CTLFLAG_VNET) != 0 &&
+ (oidp->oid_kind & CTLFLAG_TUN) != 0 &&
+ (oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
+ /* Update value from kernel environment */
+ sysctl_load_tunable_by_oid_locked(oidp);
+ }
+out:
+ SYSCTL_WUNLOCK();
+}
+
+static void
+sysctl_unsetenv_vnet(void *arg __unused, char *name)
+{
+ struct sysctl_oid *oidp;
+ int oid[CTL_MAXNAME];
+ int error, nlen;
+
+ SYSCTL_WLOCK();
+ /*
+ * The setenv / unsetenv event handlers are invoked by kern_setenv() /
+ * kern_unsetenv() without exclusive locks. It is rare but still possible
+ * that the invoke order of event handlers is different from that of
+ * kern_setenv() and kern_unsetenv().
+ * Re-check environment variable string to make sure it is unset.
+ */
+ if (testenv(name))
+ goto out;
+ error = name2oid(name, oid, &nlen, &oidp);
+ if (error)
+ goto out;
+
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
+ (oidp->oid_kind & CTLFLAG_VNET) != 0 &&
+ (oidp->oid_kind & CTLFLAG_TUN) != 0 &&
+ (oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
+ size_t size;
+
+ switch (oidp->oid_kind & CTLTYPE) {
+ case CTLTYPE_INT:
+ case CTLTYPE_UINT:
+ size = sizeof(int);
+ break;
+ case CTLTYPE_LONG:
+ case CTLTYPE_ULONG:
+ size = sizeof(long);
+ break;
+ case CTLTYPE_S8:
+ case CTLTYPE_U8:
+ size = sizeof(int8_t);
+ break;
+ case CTLTYPE_S16:
+ case CTLTYPE_U16:
+ size = sizeof(int16_t);
+ break;
+ case CTLTYPE_S32:
+ case CTLTYPE_U32:
+ size = sizeof(int32_t);
+ break;
+ case CTLTYPE_S64:
+ case CTLTYPE_U64:
+ size = sizeof(int64_t);
+ break;
+ case CTLTYPE_STRING:
+ MPASS(oidp->oid_arg2 > 0);
+ size = oidp->oid_arg2;
+ break;
+ default:
+ goto out;
+ }
+ vnet_restore_init(oidp->oid_arg1, size);
+ }
+out:
+ SYSCTL_WUNLOCK();
+}
+
+/*
+ * Register the kernel's setenv / unsetenv events.
+ */
+EVENTHANDLER_DEFINE(setenv, sysctl_setenv_vnet, NULL, EVENTHANDLER_PRI_ANY);
+EVENTHANDLER_DEFINE(unsetenv, sysctl_unsetenv_vnet, NULL, EVENTHANDLER_PRI_ANY);
+#endif
+
/*
* "Staff-functions"
*
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -506,6 +506,7 @@
TAILQ_INIT(&set_pcpu_list);
#ifdef VIMAGE
TAILQ_INIT(&set_vnet_list);
+ vnet_save_init((void *)VNET_START, VNET_STOP - VNET_START);
#endif
}
@@ -767,6 +768,7 @@
return (ENOSPC);
}
memcpy((void *)ef->vnet_base, (void *)ef->vnet_start, size);
+ vnet_save_init((void *)ef->vnet_base, size);
elf_set_add(&set_vnet_list, ef->vnet_start, ef->vnet_stop,
ef->vnet_base);
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -547,6 +547,8 @@
memcpy(vnet_data, ef->progtab[pb].addr,
ef->progtab[pb].size);
ef->progtab[pb].addr = vnet_data;
+ vnet_save_init(ef->progtab[pb].addr,
+ ef->progtab[pb].size);
#endif
} else if ((ef->progtab[pb].name != NULL &&
strcmp(ef->progtab[pb].name, ".ctors") == 0) ||
@@ -1120,6 +1122,12 @@
} else
bzero(ef->progtab[pb].addr, shdr[i].sh_size);
+#ifdef VIMAGE
+ if (ef->progtab[pb].addr != (void *)mapbase &&
+ strcmp(ef->progtab[pb].name, VNET_SETNAME) == 0)
+ vnet_save_init(ef->progtab[pb].addr,
+ ef->progtab[pb].size);
+#endif
/* Update all symbol values with the offset. */
for (j = 0; j < ef->ddbsymcnt; j++) {
es = &ef->ddbsymtab[j];
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -311,6 +311,12 @@
void vnet_data_copy(void *start, int size);
void vnet_data_free(void *start_arg, int size);
+/*
+ * Interfaces to manipulate the initial values of virtualized global variables.
+ */
+void vnet_save_init(void *, size_t);
+void vnet_restore_init(void *, size_t);
+
/*
* Virtual sysinit mechanism, allowing network stack components to declare
* startup and shutdown methods to be run when virtual network stack
diff --git a/sys/net/vnet.c b/sys/net/vnet.c
--- a/sys/net/vnet.c
+++ b/sys/net/vnet.c
@@ -178,6 +178,11 @@
*/
VNET_DEFINE_STATIC(char, modspace[VNET_MODMIN] __aligned(__alignof(void *)));
+/*
+ * A copy of the initial values of all virtualized global variables.
+ */
+static uintptr_t vnet_init_var;
+
/*
* Global lists of subsystem constructor and destructors for vnets. They are
* registered via VNET_SYSINIT() and VNET_SYSUNINIT(). Both lists are
@@ -356,6 +361,7 @@
df->vnd_len = VNET_MODMIN;
TAILQ_INSERT_HEAD(&vnet_data_free_head, df, vnd_link);
sx_init(&vnet_data_free_lock, "vnet_data alloc lock");
+ vnet_init_var = (uintptr_t)malloc(VNET_BYTES, M_VNET_DATA, M_WAITOK);
}
SYSINIT(vnet_data, SI_SUB_KLD, SI_ORDER_FIRST, vnet_data_startup, NULL);
@@ -473,6 +479,33 @@
VNET_LIST_RUNLOCK();
}
+/*
+ * Save a copy of the initial values of virtualized global variables.
+ */
+void
+vnet_save_init(void *start, size_t size)
+{
+ MPASS(vnet_init_var != 0);
+ MPASS(VNET_START <= (uintptr_t)start &&
+ (uintptr_t)start + size <= VNET_STOP);
+ memcpy((void *)(vnet_init_var + ((uintptr_t)start - VNET_START)),
+ start, size);
+}
+
+/*
+ * Restore the 'master' copies of virtualized global variables to theirs
+ * initial values.
+ */
+void
+vnet_restore_init(void *start, size_t size)
+{
+ MPASS(vnet_init_var != 0);
+ MPASS(VNET_START <= (uintptr_t)start &&
+ (uintptr_t)start + size <= VNET_STOP);
+ memcpy(start,
+ (void *)(vnet_init_var + ((uintptr_t)start - VNET_START)), size);
+}
+
/*
* Support for special SYSINIT handlers registered via VNET_SYSINIT()
* and VNET_SYSUNINIT().
diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h
--- a/sys/sys/eventhandler.h
+++ b/sys/sys/eventhandler.h
@@ -326,4 +326,9 @@
typedef void (*rt_addrmsg_fn)(void *, struct ifaddr *, int);
EVENTHANDLER_DECLARE(rt_addrmsg, rt_addrmsg_fn);
+/* Kernel environment variable change event */
+typedef void (*env_change_fn)(void *, const char *);
+EVENTHANDLER_DECLARE(setenv, env_change_fn);
+EVENTHANDLER_DECLARE(unsetenv, env_change_fn);
+
#endif /* _SYS_EVENTHANDLER_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 23, 2:03 AM (9 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17719978
Default Alt Text
D41825.diff (7 KB)
Attached To
Mode
D41825: sysctl: Update 'master' copy of vnet SYSCTLs on kernel environment variables change
Attached
Detach File
Event Timeline
Log In to Comment