Lines 44-50
Link Here
|
44 |
#include <sys/queue.h> |
44 |
#include <sys/queue.h> |
45 |
#include <sys/lock.h> |
45 |
#include <sys/lock.h> |
46 |
#include <sys/malloc.h> |
46 |
#include <sys/malloc.h> |
47 |
#include <sys/mutex.h> |
47 |
#include <sys/rmlock.h> |
48 |
#include <sys/priv.h> |
48 |
#include <sys/priv.h> |
49 |
#include <sys/kernel.h> |
49 |
#include <sys/kernel.h> |
50 |
#include <sys/systm.h> |
50 |
#include <sys/systm.h> |
Lines 78-84
Link Here
|
78 |
|
78 |
|
79 |
/* dynamic environment variables */ |
79 |
/* dynamic environment variables */ |
80 |
char **kenvp; |
80 |
char **kenvp; |
81 |
struct mtx kenv_lock; |
81 |
struct rmlock kenv_lock; |
82 |
|
82 |
|
83 |
/* |
83 |
/* |
84 |
* No need to protect this with a mutex since SYSINITS are single threaded. |
84 |
* No need to protect this with a mutex since SYSINITS are single threaded. |
Lines 100-105
Link Here
|
100 |
int len; |
100 |
int len; |
101 |
} */ *uap; |
101 |
} */ *uap; |
102 |
{ |
102 |
{ |
|
|
103 |
struct rm_priotracker tracker; |
103 |
char *name, *value, *buffer = NULL; |
104 |
char *name, *value, *buffer = NULL; |
104 |
size_t len, done, needed, buflen; |
105 |
size_t len, done, needed, buflen; |
105 |
int error, i; |
106 |
int error, i; |
Lines 120-126
Link Here
|
120 |
kenv_mvallen + 2); |
121 |
kenv_mvallen + 2); |
121 |
if (uap->len > 0 && uap->value != NULL) |
122 |
if (uap->len > 0 && uap->value != NULL) |
122 |
buffer = malloc(buflen, M_TEMP, M_WAITOK|M_ZERO); |
123 |
buffer = malloc(buflen, M_TEMP, M_WAITOK|M_ZERO); |
123 |
mtx_lock(&kenv_lock); |
124 |
rm_rlock(&kenv_lock, &tracker); |
124 |
for (i = 0; kenvp[i] != NULL; i++) { |
125 |
for (i = 0; kenvp[i] != NULL; i++) { |
125 |
len = strlen(kenvp[i]) + 1; |
126 |
len = strlen(kenvp[i]) + 1; |
126 |
needed += len; |
127 |
needed += len; |
Lines 134-140
Link Here
|
134 |
done += len; |
135 |
done += len; |
135 |
} |
136 |
} |
136 |
} |
137 |
} |
137 |
mtx_unlock(&kenv_lock); |
138 |
rm_runlock(&kenv_lock, &tracker); |
138 |
if (buffer != NULL) { |
139 |
if (buffer != NULL) { |
139 |
error = copyout(buffer, uap->value, done); |
140 |
error = copyout(buffer, uap->value, done); |
140 |
free(buffer, M_TEMP); |
141 |
free(buffer, M_TEMP); |
Lines 396-402
Link Here
|
396 |
init_dynamic_kenv_from(kern_envp, &dynamic_envpos); |
397 |
init_dynamic_kenv_from(kern_envp, &dynamic_envpos); |
397 |
kenvp[dynamic_envpos] = NULL; |
398 |
kenvp[dynamic_envpos] = NULL; |
398 |
|
399 |
|
399 |
mtx_init(&kenv_lock, "kernel environment", NULL, MTX_DEF); |
400 |
rm_init(&kenv_lock, "kernel environment"); |
400 |
dynamic_kenv = true; |
401 |
dynamic_kenv = true; |
401 |
} |
402 |
} |
402 |
SYSINIT(kenv, SI_SUB_KMEM + 1, SI_ORDER_FIRST, init_dynamic_kenv, NULL); |
403 |
SYSINIT(kenv, SI_SUB_KMEM + 1, SI_ORDER_FIRST, init_dynamic_kenv, NULL); |
Lines 436-442
Link Here
|
436 |
_getenv_dynamic(const char *name, int *idx) |
437 |
_getenv_dynamic(const char *name, int *idx) |
437 |
{ |
438 |
{ |
438 |
|
439 |
|
439 |
mtx_assert(&kenv_lock, MA_OWNED); |
440 |
rm_assert(&kenv_lock, RA_LOCKED); |
440 |
return (_getenv_dynamic_locked(name, idx)); |
441 |
return (_getenv_dynamic_locked(name, idx)); |
441 |
} |
442 |
} |
442 |
|
443 |
|
Lines 501-512
Link Here
|
501 |
int |
502 |
int |
502 |
testenv(const char *name) |
503 |
testenv(const char *name) |
503 |
{ |
504 |
{ |
|
|
505 |
struct rm_priotracker tracker; |
504 |
char *cp; |
506 |
char *cp; |
505 |
|
507 |
|
506 |
if (dynamic_kenv) { |
508 |
if (dynamic_kenv) { |
507 |
mtx_lock(&kenv_lock); |
509 |
rm_rlock(&kenv_lock, &tracker); |
508 |
cp = _getenv_dynamic(name, NULL); |
510 |
cp = _getenv_dynamic(name, NULL); |
509 |
mtx_unlock(&kenv_lock); |
511 |
rm_runlock(&kenv_lock, &tracker); |
510 |
} else |
512 |
} else |
511 |
cp = _getenv_static(name); |
513 |
cp = _getenv_static(name); |
512 |
if (cp != NULL) |
514 |
if (cp != NULL) |
Lines 562-573
Link Here
|
562 |
buf = malloc(namelen + vallen, M_KENV, M_WAITOK); |
564 |
buf = malloc(namelen + vallen, M_KENV, M_WAITOK); |
563 |
sprintf(buf, "%s=%s", name, value); |
565 |
sprintf(buf, "%s=%s", name, value); |
564 |
|
566 |
|
565 |
mtx_lock(&kenv_lock); |
567 |
rm_wlock(&kenv_lock); |
566 |
cp = _getenv_dynamic(name, &i); |
568 |
cp = _getenv_dynamic(name, &i); |
567 |
if (cp != NULL) { |
569 |
if (cp != NULL) { |
568 |
oldenv = kenvp[i]; |
570 |
oldenv = kenvp[i]; |
569 |
kenvp[i] = buf; |
571 |
kenvp[i] = buf; |
570 |
mtx_unlock(&kenv_lock); |
572 |
rm_wunlock(&kenv_lock); |
571 |
free(oldenv, M_KENV); |
573 |
free(oldenv, M_KENV); |
572 |
} else { |
574 |
} else { |
573 |
/* We add the option if it wasn't found */ |
575 |
/* We add the option if it wasn't found */ |
Lines 577-589
Link Here
|
577 |
/* Bounds checking */ |
579 |
/* Bounds checking */ |
578 |
if (i < 0 || i >= KENV_SIZE) { |
580 |
if (i < 0 || i >= KENV_SIZE) { |
579 |
free(buf, M_KENV); |
581 |
free(buf, M_KENV); |
580 |
mtx_unlock(&kenv_lock); |
582 |
rm_wunlock(&kenv_lock); |
581 |
return (-1); |
583 |
return (-1); |
582 |
} |
584 |
} |
583 |
|
585 |
|
584 |
kenvp[i] = buf; |
586 |
kenvp[i] = buf; |
585 |
kenvp[i + 1] = NULL; |
587 |
kenvp[i + 1] = NULL; |
586 |
mtx_unlock(&kenv_lock); |
588 |
rm_wunlock(&kenv_lock); |
587 |
} |
589 |
} |
588 |
return (0); |
590 |
return (0); |
589 |
} |
591 |
} |
Lines 599-605
Link Here
|
599 |
|
601 |
|
600 |
KENV_CHECK; |
602 |
KENV_CHECK; |
601 |
|
603 |
|
602 |
mtx_lock(&kenv_lock); |
604 |
rm_wlock(&kenv_lock); |
603 |
cp = _getenv_dynamic(name, &i); |
605 |
cp = _getenv_dynamic(name, &i); |
604 |
if (cp != NULL) { |
606 |
if (cp != NULL) { |
605 |
oldenv = kenvp[i]; |
607 |
oldenv = kenvp[i]; |
Lines 606-616
Link Here
|
606 |
for (j = i + 1; kenvp[j] != NULL; j++) |
608 |
for (j = i + 1; kenvp[j] != NULL; j++) |
607 |
kenvp[i++] = kenvp[j]; |
609 |
kenvp[i++] = kenvp[j]; |
608 |
kenvp[i] = NULL; |
610 |
kenvp[i] = NULL; |
609 |
mtx_unlock(&kenv_lock); |
611 |
rm_wunlock(&kenv_lock); |
610 |
zfree(oldenv, M_KENV); |
612 |
zfree(oldenv, M_KENV); |
611 |
return (0); |
613 |
return (0); |
612 |
} |
614 |
} |
613 |
mtx_unlock(&kenv_lock); |
615 |
rm_wunlock(&kenv_lock); |
614 |
return (-1); |
616 |
return (-1); |
615 |
} |
617 |
} |
616 |
|
618 |
|
Lines 620-625
Link Here
|
620 |
static char * |
622 |
static char * |
621 |
getenv_string_buffer(const char *name) |
623 |
getenv_string_buffer(const char *name) |
622 |
{ |
624 |
{ |
|
|
625 |
struct rm_priotracker tracker; |
623 |
char *cp, *ret; |
626 |
char *cp, *ret; |
624 |
int len; |
627 |
int len; |
625 |
|
628 |
|
Lines 626-636
Link Here
|
626 |
if (dynamic_kenv) { |
629 |
if (dynamic_kenv) { |
627 |
len = KENV_MNAMELEN + 1 + kenv_mvallen + 1; |
630 |
len = KENV_MNAMELEN + 1 + kenv_mvallen + 1; |
628 |
ret = uma_zalloc(kenv_zone, M_WAITOK | M_ZERO); |
631 |
ret = uma_zalloc(kenv_zone, M_WAITOK | M_ZERO); |
629 |
mtx_lock(&kenv_lock); |
632 |
rm_rlock(&kenv_lock, &tracker); |
630 |
cp = _getenv_dynamic(name, NULL); |
633 |
cp = _getenv_dynamic(name, NULL); |
631 |
if (cp != NULL) |
634 |
if (cp != NULL) |
632 |
strlcpy(ret, cp, len); |
635 |
strlcpy(ret, cp, len); |
633 |
mtx_unlock(&kenv_lock); |
636 |
rm_runlock(&kenv_lock, &tracker); |
634 |
if (cp == NULL) { |
637 |
if (cp == NULL) { |
635 |
uma_zfree(kenv_zone, ret); |
638 |
uma_zfree(kenv_zone, ret); |
636 |
ret = NULL; |
639 |
ret = NULL; |
Lines 647-660
Link Here
|
647 |
int |
650 |
int |
648 |
getenv_string(const char *name, char *data, int size) |
651 |
getenv_string(const char *name, char *data, int size) |
649 |
{ |
652 |
{ |
|
|
653 |
struct rm_priotracker tracker; |
650 |
char *cp; |
654 |
char *cp; |
651 |
|
655 |
|
652 |
if (dynamic_kenv) { |
656 |
if (dynamic_kenv) { |
653 |
mtx_lock(&kenv_lock); |
657 |
rm_rlock(&kenv_lock, &tracker); |
654 |
cp = _getenv_dynamic(name, NULL); |
658 |
cp = _getenv_dynamic(name, NULL); |
655 |
if (cp != NULL) |
659 |
if (cp != NULL) |
656 |
strlcpy(data, cp, size); |
660 |
strlcpy(data, cp, size); |
657 |
mtx_unlock(&kenv_lock); |
661 |
rm_runlock(&kenv_lock, &tracker); |
658 |
} else { |
662 |
} else { |
659 |
cp = _getenv_static(name); |
663 |
cp = _getenv_static(name); |
660 |
if (cp != NULL) |
664 |
if (cp != NULL) |
Lines 670-688
Link Here
|
670 |
getenv_array(const char *name, void *pdata, int size, int *psize, |
674 |
getenv_array(const char *name, void *pdata, int size, int *psize, |
671 |
int type_size, bool allow_signed) |
675 |
int type_size, bool allow_signed) |
672 |
{ |
676 |
{ |
|
|
677 |
struct rm_priotracker tracker; |
673 |
uint8_t shift; |
678 |
uint8_t shift; |
674 |
int64_t value; |
679 |
int64_t value; |
675 |
int64_t old; |
680 |
int64_t old; |
676 |
char *buf; |
681 |
const char *buf; |
677 |
char *end; |
682 |
char *end; |
678 |
char *ptr; |
683 |
const char *ptr; |
679 |
int n; |
684 |
int n; |
680 |
int rc; |
685 |
int rc; |
681 |
|
686 |
|
682 |
if ((buf = getenv_string_buffer(name)) == NULL) |
687 |
if (dynamic_kenv) { |
683 |
return (0); |
688 |
rm_rlock(&kenv_lock, &tracker); |
|
|
689 |
buf = _getenv_dynamic(name, NULL); |
690 |
} else |
691 |
buf = _getenv_static(name); |
684 |
|
692 |
|
685 |
rc = 0; /* assume failure */ |
693 |
rc = 0; /* assume failure */ |
|
|
694 |
|
695 |
if (buf == NULL) |
696 |
goto error; |
697 |
|
686 |
/* get maximum number of elements */ |
698 |
/* get maximum number of elements */ |
687 |
size /= type_size; |
699 |
size /= type_size; |
688 |
|
700 |
|
Lines 798-804
Link Here
|
798 |
rc = 1; /* success */ |
810 |
rc = 1; /* success */ |
799 |
error: |
811 |
error: |
800 |
if (dynamic_kenv) |
812 |
if (dynamic_kenv) |
801 |
uma_zfree(kenv_zone, buf); |
813 |
rm_runlock(&kenv_lock, &tracker); |
802 |
return (rc); |
814 |
return (rc); |
803 |
} |
815 |
} |
804 |
|
816 |
|
Lines 898-915
Link Here
|
898 |
int |
910 |
int |
899 |
getenv_quad(const char *name, quad_t *data) |
911 |
getenv_quad(const char *name, quad_t *data) |
900 |
{ |
912 |
{ |
901 |
char *value, *vtp; |
913 |
struct rm_priotracker tracker; |
902 |
quad_t iv; |
914 |
const char *value; |
|
|
915 |
char suffix, *vtp; |
916 |
quad_t iv; |
903 |
|
917 |
|
904 |
value = getenv_string_buffer(name); |
918 |
if (dynamic_kenv) { |
905 |
if (value == NULL) |
919 |
rm_rlock(&kenv_lock, &tracker); |
906 |
return (0); |
920 |
value = _getenv_dynamic(name, NULL); |
|
|
921 |
} else |
922 |
value = _getenv_static(name); |
923 |
if (value == NULL) { |
924 |
goto error; |
925 |
} |
907 |
iv = strtoq(value, &vtp, 0); |
926 |
iv = strtoq(value, &vtp, 0); |
908 |
if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) { |
927 |
if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) { |
909 |
freeenv(value); |
928 |
goto error; |
910 |
return (0); |
|
|
911 |
} |
929 |
} |
912 |
switch (vtp[0]) { |
930 |
suffix = vtp[0]; |
|
|
931 |
if (dynamic_kenv) |
932 |
rm_runlock(&kenv_lock, &tracker); |
933 |
switch (suffix) { |
913 |
case 't': case 'T': |
934 |
case 't': case 'T': |
914 |
iv *= 1024; |
935 |
iv *= 1024; |
915 |
/* FALLTHROUGH */ |
936 |
/* FALLTHROUGH */ |
Lines 924-935
Link Here
|
924 |
case '\0': |
945 |
case '\0': |
925 |
break; |
946 |
break; |
926 |
default: |
947 |
default: |
927 |
freeenv(value); |
|
|
928 |
return (0); |
948 |
return (0); |
929 |
} |
949 |
} |
930 |
freeenv(value); |
|
|
931 |
*data = iv; |
950 |
*data = iv; |
932 |
return (1); |
951 |
return (1); |
|
|
952 |
error: |
953 |
if (dynamic_kenv) |
954 |
rm_runlock(&kenv_lock, &tracker); |
955 |
return (0); |
933 |
} |
956 |
} |
934 |
|
957 |
|
935 |
/* |
958 |
/* |