Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_bus.c
Show First 20 Lines • Show All 5,701 Lines • ▼ Show 20 Lines | device_do_deferred_actions(void) | ||||||||||
/* | /* | ||||||||||
* We also defer no-match events during a freeze. Walk the tree and | * We also defer no-match events during a freeze. Walk the tree and | ||||||||||
* generate all the pent-up events that are still relevant. | * generate all the pent-up events that are still relevant. | ||||||||||
*/ | */ | ||||||||||
device_gen_nomatch(root_bus); | device_gen_nomatch(root_bus); | ||||||||||
bus_data_generation_update(); | bus_data_generation_update(); | ||||||||||
} | } | ||||||||||
static const char * | |||||||||||
jhb: I would maybe just make this return a `char *`. It's a static function and the caller has to… | |||||||||||
Done Inline ActionsOK. imp: OK. | |||||||||||
device_get_path(device_t dev, const char *locator) | |||||||||||
{ | |||||||||||
struct sbuf *sb; | |||||||||||
ssize_t len; | |||||||||||
const char *rv = NULL; | |||||||||||
char *r; | |||||||||||
int error; | |||||||||||
sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND | SBUF_INCLUDENUL); | |||||||||||
error = BUS_GET_DEVICE_PATH(device_get_parent(dev), dev, locator, sb); | |||||||||||
sbuf_finish(sb); | |||||||||||
Done Inline ActionsHmm, I guess sbuf_finish() can't fail in practice due to SBUF_AUTOEXTEND? jhb: Hmm, I guess sbuf_finish() can't fail in practice due to SBUF_AUTOEXTEND? | |||||||||||
Done Inline ActionsDoesn't matter if it fails or not. If it does fail, len will be -1, which is checked below. imp: Doesn't matter if it fails or not. If it does fail, len will be -1, which is checked below. | |||||||||||
if (error != 0) | |||||||||||
goto out; | |||||||||||
len = sbuf_len(sb); | |||||||||||
if (len <= 1) | |||||||||||
goto out; | |||||||||||
rv = r = malloc(len, M_BUS, M_NOWAIT); | |||||||||||
memcpy(r, sbuf_data(sb), len); | |||||||||||
out: | |||||||||||
sbuf_delete(sb); | |||||||||||
return rv; | |||||||||||
Done Inline Actions
jhb: | |||||||||||
} | |||||||||||
static int | static int | ||||||||||
devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, | devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, | ||||||||||
struct thread *td) | struct thread *td) | ||||||||||
{ | { | ||||||||||
struct devreq *req; | struct devreq *req; | ||||||||||
device_t dev; | device_t dev; | ||||||||||
int error, old; | int error, old; | ||||||||||
/* Locate the device to control. */ | /* Locate the device to control. */ | ||||||||||
mtx_lock(&Giant); | mtx_lock(&Giant); | ||||||||||
req = (struct devreq *)data; | req = (struct devreq *)data; | ||||||||||
switch (cmd) { | switch (cmd) { | ||||||||||
case DEV_ATTACH: | case DEV_ATTACH: | ||||||||||
case DEV_DETACH: | case DEV_DETACH: | ||||||||||
case DEV_ENABLE: | case DEV_ENABLE: | ||||||||||
case DEV_DISABLE: | case DEV_DISABLE: | ||||||||||
case DEV_SUSPEND: | case DEV_SUSPEND: | ||||||||||
case DEV_RESUME: | case DEV_RESUME: | ||||||||||
case DEV_SET_DRIVER: | case DEV_SET_DRIVER: | ||||||||||
case DEV_CLEAR_DRIVER: | case DEV_CLEAR_DRIVER: | ||||||||||
case DEV_RESCAN: | case DEV_RESCAN: | ||||||||||
case DEV_DELETE: | case DEV_DELETE: | ||||||||||
case DEV_RESET: | case DEV_RESET: | ||||||||||
case DEV_GET_PATH: | |||||||||||
Done Inline ActionsI would be fine with not requiring PRIV_DRIVER for this request. jhb: I would be fine with not requiring `PRIV_DRIVER` for this request. | |||||||||||
Done Inline ActionsOK. /dev/devctl2's permissions would need to be updated for that to be completely useful though. imp: OK. /dev/devctl2's permissions would need to be updated for that to be completely useful though. | |||||||||||
error = priv_check(td, PRIV_DRIVER); | error = priv_check(td, PRIV_DRIVER); | ||||||||||
if (error == 0) | if (error == 0) | ||||||||||
error = find_device(req, &dev); | error = find_device(req, &dev); | ||||||||||
break; | break; | ||||||||||
case DEV_FREEZE: | case DEV_FREEZE: | ||||||||||
case DEV_THAW: | case DEV_THAW: | ||||||||||
error = priv_check(td, PRIV_DRIVER); | error = priv_check(td, PRIV_DRIVER); | ||||||||||
break; | break; | ||||||||||
▲ Show 20 Lines • Show All 217 Lines • ▼ Show 20 Lines | devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, | ||||||||||
case DEV_RESET: | case DEV_RESET: | ||||||||||
if ((req->dr_flags & ~(DEVF_RESET_DETACH)) != 0) { | if ((req->dr_flags & ~(DEVF_RESET_DETACH)) != 0) { | ||||||||||
error = EINVAL; | error = EINVAL; | ||||||||||
break; | break; | ||||||||||
} | } | ||||||||||
error = BUS_RESET_CHILD(device_get_parent(dev), dev, | error = BUS_RESET_CHILD(device_get_parent(dev), dev, | ||||||||||
req->dr_flags); | req->dr_flags); | ||||||||||
break; | break; | ||||||||||
case DEV_GET_PATH: { | |||||||||||
char locator[64]; | |||||||||||
const char *path; | |||||||||||
ssize_t len; | |||||||||||
error = copyinstr(req->dr_buffer.buffer, locator, sizeof(locator), NULL); | |||||||||||
if (error) | |||||||||||
break; | |||||||||||
path = device_get_path(dev, locator); | |||||||||||
if (path == NULL) { | |||||||||||
error = ENOMEM; | |||||||||||
break; | |||||||||||
} | |||||||||||
len = strlen(path) + 1; | |||||||||||
if (req->dr_buffer.length < len) { | |||||||||||
error = ENAMETOOLONG; | |||||||||||
} else { | |||||||||||
error = copyout(path, req->dr_buffer.buffer, len); | |||||||||||
} | |||||||||||
req->dr_buffer.length = len; | |||||||||||
free(__DECONST(void *, path), M_BUS); | |||||||||||
break; | |||||||||||
} | |||||||||||
} | } | ||||||||||
mtx_unlock(&Giant); | mtx_unlock(&Giant); | ||||||||||
return (error); | return (error); | ||||||||||
} | } | ||||||||||
static struct cdevsw devctl2_cdevsw = { | static struct cdevsw devctl2_cdevsw = { | ||||||||||
.d_version = D_VERSION, | .d_version = D_VERSION, | ||||||||||
.d_ioctl = devctl2_ioctl, | .d_ioctl = devctl2_ioctl, | ||||||||||
▲ Show 20 Lines • Show All 86 Lines • Show Last 20 Lines |
I would maybe just make this return a char *. It's a static function and the caller has to pass the result to free anyway, so it's always going to require an ugly __DECONST in the caller to deal with free. Doing this removes the __DECONST below in the ioctl handler and also removes the need for both rv and r in this function.