Index: sys/kern/kern_environment.c =================================================================== --- sys/kern/kern_environment.c +++ sys/kern/kern_environment.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include #include @@ -78,7 +78,7 @@ /* dynamic environment variables */ char **kenvp; -struct mtx kenv_lock; +struct rmlock kenv_lock; /* * No need to protect this with a mutex since SYSINITS are single threaded. @@ -100,6 +100,7 @@ int len; } */ *uap; { + struct rm_priotracker tracker; char *name, *value, *buffer = NULL; size_t len, done, needed, buflen; int error, i; @@ -120,7 +121,7 @@ kenv_mvallen + 2); if (uap->len > 0 && uap->value != NULL) buffer = malloc(buflen, M_TEMP, M_WAITOK|M_ZERO); - mtx_lock(&kenv_lock); + rm_rlock(&kenv_lock, &tracker); for (i = 0; kenvp[i] != NULL; i++) { len = strlen(kenvp[i]) + 1; needed += len; @@ -134,7 +135,7 @@ done += len; } } - mtx_unlock(&kenv_lock); + rm_runlock(&kenv_lock, &tracker); if (buffer != NULL) { error = copyout(buffer, uap->value, done); free(buffer, M_TEMP); @@ -396,7 +397,7 @@ init_dynamic_kenv_from(kern_envp, &dynamic_envpos); kenvp[dynamic_envpos] = NULL; - mtx_init(&kenv_lock, "kernel environment", NULL, MTX_DEF); + rm_init(&kenv_lock, "kernel environment"); dynamic_kenv = true; } SYSINIT(kenv, SI_SUB_KMEM + 1, SI_ORDER_FIRST, init_dynamic_kenv, NULL); @@ -436,7 +437,7 @@ _getenv_dynamic(const char *name, int *idx) { - mtx_assert(&kenv_lock, MA_OWNED); + rm_assert(&kenv_lock, RA_LOCKED); return (_getenv_dynamic_locked(name, idx)); } @@ -501,12 +502,13 @@ int testenv(const char *name) { + struct rm_priotracker tracker; char *cp; if (dynamic_kenv) { - mtx_lock(&kenv_lock); + rm_rlock(&kenv_lock, &tracker); cp = _getenv_dynamic(name, NULL); - mtx_unlock(&kenv_lock); + rm_runlock(&kenv_lock, &tracker); } else cp = _getenv_static(name); if (cp != NULL) @@ -562,12 +564,12 @@ buf = malloc(namelen + vallen, M_KENV, M_WAITOK); sprintf(buf, "%s=%s", name, value); - mtx_lock(&kenv_lock); + rm_wlock(&kenv_lock); cp = _getenv_dynamic(name, &i); if (cp != NULL) { oldenv = kenvp[i]; kenvp[i] = buf; - mtx_unlock(&kenv_lock); + rm_wunlock(&kenv_lock); free(oldenv, M_KENV); } else { /* We add the option if it wasn't found */ @@ -577,13 +579,13 @@ /* Bounds checking */ if (i < 0 || i >= KENV_SIZE) { free(buf, M_KENV); - mtx_unlock(&kenv_lock); + rm_wunlock(&kenv_lock); return (-1); } kenvp[i] = buf; kenvp[i + 1] = NULL; - mtx_unlock(&kenv_lock); + rm_wunlock(&kenv_lock); } return (0); } @@ -599,18 +601,18 @@ KENV_CHECK; - mtx_lock(&kenv_lock); + rm_wlock(&kenv_lock); cp = _getenv_dynamic(name, &i); if (cp != NULL) { oldenv = kenvp[i]; for (j = i + 1; kenvp[j] != NULL; j++) kenvp[i++] = kenvp[j]; kenvp[i] = NULL; - mtx_unlock(&kenv_lock); + rm_wunlock(&kenv_lock); zfree(oldenv, M_KENV); return (0); } - mtx_unlock(&kenv_lock); + rm_wunlock(&kenv_lock); return (-1); } @@ -620,17 +622,18 @@ static char * getenv_string_buffer(const char *name) { + struct rm_priotracker tracker; char *cp, *ret; int len; if (dynamic_kenv) { len = KENV_MNAMELEN + 1 + kenv_mvallen + 1; ret = uma_zalloc(kenv_zone, M_WAITOK | M_ZERO); - mtx_lock(&kenv_lock); + rm_rlock(&kenv_lock, &tracker); cp = _getenv_dynamic(name, NULL); if (cp != NULL) strlcpy(ret, cp, len); - mtx_unlock(&kenv_lock); + rm_runlock(&kenv_lock, &tracker); if (cp == NULL) { uma_zfree(kenv_zone, ret); ret = NULL; @@ -647,14 +650,15 @@ int getenv_string(const char *name, char *data, int size) { + struct rm_priotracker tracker; char *cp; if (dynamic_kenv) { - mtx_lock(&kenv_lock); + rm_rlock(&kenv_lock, &tracker); cp = _getenv_dynamic(name, NULL); if (cp != NULL) strlcpy(data, cp, size); - mtx_unlock(&kenv_lock); + rm_runlock(&kenv_lock, &tracker); } else { cp = _getenv_static(name); if (cp != NULL) @@ -670,19 +674,27 @@ getenv_array(const char *name, void *pdata, int size, int *psize, int type_size, bool allow_signed) { + struct rm_priotracker tracker; uint8_t shift; int64_t value; int64_t old; - char *buf; + const char *buf; char *end; - char *ptr; + const char *ptr; int n; int rc; - if ((buf = getenv_string_buffer(name)) == NULL) - return (0); + if (dynamic_kenv) { + rm_rlock(&kenv_lock, &tracker); + buf = _getenv_dynamic(name, NULL); + } else + buf = _getenv_static(name); rc = 0; /* assume failure */ + + if (buf == NULL) + goto error; + /* get maximum number of elements */ size /= type_size; @@ -798,7 +810,7 @@ rc = 1; /* success */ error: if (dynamic_kenv) - uma_zfree(kenv_zone, buf); + rm_runlock(&kenv_lock, &tracker); return (rc); } @@ -898,18 +910,27 @@ int getenv_quad(const char *name, quad_t *data) { - char *value, *vtp; - quad_t iv; + struct rm_priotracker tracker; + const char *value; + char suffix, *vtp; + quad_t iv; - value = getenv_string_buffer(name); - if (value == NULL) - return (0); + if (dynamic_kenv) { + rm_rlock(&kenv_lock, &tracker); + value = _getenv_dynamic(name, NULL); + } else + value = _getenv_static(name); + if (value == NULL) { + goto error; + } iv = strtoq(value, &vtp, 0); if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) { - freeenv(value); - return (0); + goto error; } - switch (vtp[0]) { + suffix = vtp[0]; + if (dynamic_kenv) + rm_runlock(&kenv_lock, &tracker); + switch (suffix) { case 't': case 'T': iv *= 1024; /* FALLTHROUGH */ @@ -924,12 +945,14 @@ case '\0': break; default: - freeenv(value); return (0); } - freeenv(value); *data = iv; return (1); +error: + if (dynamic_kenv) + rm_runlock(&kenv_lock, &tracker); + return (0); } /* Index: sys/kern/subr_hints.c =================================================================== --- sys/kern/subr_hints.c +++ sys/kern/subr_hints.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,6 +42,8 @@ #define FBACK_STENV 1 /* Static env */ #define FBACK_STATIC 2 /* static_hints */ +extern struct rmlock kenv_lock; + /* * We'll use hintenv_merged to indicate that the dynamic environment has been * properly prepared for hint usage. This implies that the dynamic environment @@ -126,6 +128,7 @@ const char **ret_name, int *ret_namelen, int *ret_unit, const char **ret_resname, int *ret_resnamelen, const char **ret_value) { + struct rm_priotracker tracker; int fbacklvl = FBACK_MDENV, i = 0, n = 0; char r_name[32]; int r_unit; @@ -150,7 +153,7 @@ * already been folded in to the environment * by this point. */ - mtx_lock(&kenv_lock); + rm_rlock(&kenv_lock, &tracker); cp = kenvp[0]; for (i = 0; cp != NULL; cp = kenvp[++i]) { if (!strncmp(cp, "hint.", 5)) { @@ -158,7 +161,7 @@ break; } } - mtx_unlock(&kenv_lock); + rm_runlock(&kenv_lock, &tracker); dyn_used = true; } else { /* @@ -224,7 +227,7 @@ } if (dyn_used) { - mtx_lock(&kenv_lock); + rm_rlock(&kenv_lock, &tracker); i = 0; } @@ -269,7 +272,7 @@ } } if (dyn_used) - mtx_unlock(&kenv_lock); + rm_runlock(&kenv_lock, &tracker); if (cp == NULL) goto fallback; Index: sys/sys/systm.h =================================================================== --- sys/sys/systm.h +++ sys/sys/systm.h @@ -195,7 +195,6 @@ */ extern int osreldate; extern bool dynamic_kenv; -extern struct mtx kenv_lock; extern char *kern_envp; extern char *md_envp; extern char static_env[];