Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_hints.c
Show All 27 Lines | |||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mutex.h> | #include <sys/rmlock.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#define FBACK_MDENV 0 /* MD env (e.g. loader.conf) */ | #define FBACK_MDENV 0 /* MD env (e.g. loader.conf) */ | ||||
#define FBACK_STENV 1 /* Static env */ | #define FBACK_STENV 1 /* Static env */ | ||||
#define FBACK_STATIC 2 /* static_hints */ | #define FBACK_STATIC 2 /* static_hints */ | ||||
extern struct rmlock kenv_lock; | |||||
/* | /* | ||||
* We'll use hintenv_merged to indicate that the dynamic environment has been | * We'll use hintenv_merged to indicate that the dynamic environment has been | ||||
* properly prepared for hint usage. This implies that the dynamic environment | * properly prepared for hint usage. This implies that the dynamic environment | ||||
* has already been setup (dynamic_kenv) and that we have added any supplied | * has already been setup (dynamic_kenv) and that we have added any supplied | ||||
* static_hints to the dynamic environment. | * static_hints to the dynamic environment. | ||||
*/ | */ | ||||
static bool hintenv_merged; | static bool hintenv_merged; | ||||
/* Static environment and static hints cannot change, so we'll skip known bad */ | /* Static environment and static hints cannot change, so we'll skip known bad */ | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
* The start point can be remembered for incremental searches. | * The start point can be remembered for incremental searches. | ||||
*/ | */ | ||||
static int | static int | ||||
res_find(char **hintp_cookie, int *line, int *startln, | res_find(char **hintp_cookie, int *line, int *startln, | ||||
const char *name, int *unit, const char *resname, const char *value, | const char *name, int *unit, const char *resname, const char *value, | ||||
const char **ret_name, int *ret_namelen, int *ret_unit, | const char **ret_name, int *ret_namelen, int *ret_unit, | ||||
const char **ret_resname, int *ret_resnamelen, const char **ret_value) | const char **ret_resname, int *ret_resnamelen, const char **ret_value) | ||||
{ | { | ||||
struct rm_priotracker tracker; | |||||
int fbacklvl = FBACK_MDENV, i = 0, n = 0; | int fbacklvl = FBACK_MDENV, i = 0, n = 0; | ||||
char r_name[32]; | char r_name[32]; | ||||
int r_unit; | int r_unit; | ||||
char r_resname[32]; | char r_resname[32]; | ||||
char r_value[128]; | char r_value[128]; | ||||
const char *s, *cp; | const char *s, *cp; | ||||
char *hintp, *p; | char *hintp, *p; | ||||
bool dyn_used = false; | bool dyn_used = false; | ||||
/* | /* | ||||
* We are expecting that the caller will pass us a hintp_cookie that | * We are expecting that the caller will pass us a hintp_cookie that | ||||
* they are tracking. Upon entry, if *hintp_cookie is *not* set, this | * they are tracking. Upon entry, if *hintp_cookie is *not* set, this | ||||
* indicates to us that we should be figuring out based on the current | * indicates to us that we should be figuring out based on the current | ||||
* environment where to search. This keeps us sane throughout the | * environment where to search. This keeps us sane throughout the | ||||
* entirety of a single search. | * entirety of a single search. | ||||
*/ | */ | ||||
if (*hintp_cookie == NULL) { | if (*hintp_cookie == NULL) { | ||||
hintp = NULL; | hintp = NULL; | ||||
if (hintenv_merged) { | if (hintenv_merged) { | ||||
/* | /* | ||||
* static_hints, if it was previously used, has | * static_hints, if it was previously used, has | ||||
* already been folded in to the environment | * already been folded in to the environment | ||||
* by this point. | * by this point. | ||||
*/ | */ | ||||
mtx_lock(&kenv_lock); | rm_rlock(&kenv_lock, &tracker); | ||||
cp = kenvp[0]; | cp = kenvp[0]; | ||||
for (i = 0; cp != NULL; cp = kenvp[++i]) { | for (i = 0; cp != NULL; cp = kenvp[++i]) { | ||||
if (!strncmp(cp, "hint.", 5)) { | if (!strncmp(cp, "hint.", 5)) { | ||||
hintp = kenvp[0]; | hintp = kenvp[0]; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
mtx_unlock(&kenv_lock); | rm_runlock(&kenv_lock, &tracker); | ||||
dyn_used = true; | dyn_used = true; | ||||
} else { | } else { | ||||
/* | /* | ||||
* We'll have a chance to keep coming back here until | * We'll have a chance to keep coming back here until | ||||
* we've actually exhausted all of our possibilities. | * we've actually exhausted all of our possibilities. | ||||
* We might have chosen the MD/Static env because it | * We might have chosen the MD/Static env because it | ||||
* had some kind of hints, but perhaps it didn't have | * had some kind of hints, but perhaps it didn't have | ||||
* the hint we are looking for. We don't provide any | * the hint we are looking for. We don't provide any | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | else | ||||
* to run through the proper fallback procedure again. | * to run through the proper fallback procedure again. | ||||
* This is so that we do continuations right if we're | * This is so that we do continuations right if we're | ||||
* working with *line and *startln. | * working with *line and *startln. | ||||
*/ | */ | ||||
goto fallback; | goto fallback; | ||||
} | } | ||||
if (dyn_used) { | if (dyn_used) { | ||||
mtx_lock(&kenv_lock); | rm_rlock(&kenv_lock, &tracker); | ||||
i = 0; | i = 0; | ||||
} | } | ||||
cp = hintp; | cp = hintp; | ||||
while (cp) { | while (cp) { | ||||
(*line)++; | (*line)++; | ||||
if (strncmp(cp, "hint.", 5) != 0) | if (strncmp(cp, "hint.", 5) != 0) | ||||
goto nexthint; | goto nexthint; | ||||
Show All 28 Lines | if (dyn_used) { | ||||
cp++; | cp++; | ||||
if (*cp == '\0') { | if (*cp == '\0') { | ||||
cp = NULL; | cp = NULL; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (dyn_used) | if (dyn_used) | ||||
mtx_unlock(&kenv_lock); | rm_runlock(&kenv_lock, &tracker); | ||||
if (cp == NULL) | if (cp == NULL) | ||||
goto fallback; | goto fallback; | ||||
s = cp; | s = cp; | ||||
/* This is a bit of a hack, but at least is reentrant */ | /* This is a bit of a hack, but at least is reentrant */ | ||||
/* Note that it returns some !unterminated! strings. */ | /* Note that it returns some !unterminated! strings. */ | ||||
s = strchr(s, '.') + 1; /* start of device */ | s = strchr(s, '.') + 1; /* start of device */ | ||||
if (ret_name) | if (ret_name) | ||||
▲ Show 20 Lines • Show All 236 Lines • Show Last 20 Lines |