libdevctl: Add devctl_getpath

Helper routine to call the kernel to get a path to the named device.
Different path enumeration methods (called locators) can be used
for different path types depending on what the kernel implements.

Sponsored by:		Netflix
Reviewed by:		jhb
Differential Revision:	https://reviews.freebsd.org/D32746
This commit is contained in:
Warner Losh 2022-02-28 14:27:28 -07:00
parent 38e942a345
commit b01f409ffe
3 changed files with 57 additions and 0 deletions

View File

@ -36,6 +36,7 @@
.Nm devctl_disable ,
.Nm devctl_enable ,
.Nm devctl_freeze ,
.Nm devctl_getpath ,
.Nm devctl_rescan ,
.Nm devctl_reset ,
.Nm devctl_resume ,
@ -62,6 +63,8 @@
.Ft int
.Fn devctl_freeze "void"
.Ft int
.Fn devctl_getpath "const char *device" "const char *locator" "char **buffer"
.Ft int
.Fn devctl_rescan "const char *device"
.Ft int
.Fn devctl_reset "const char *device" "bool detach"
@ -199,6 +202,18 @@ function rescans a bus device checking for devices that have been added or
removed.
.Pp
The
.Fn devctl_getpath
retrieves the path to the
.Fa device
from the kernel using the
.Fa locator
method to construct the path.
The
.Fa buffer
pointer is updated with an allocated buffer that must be freed with
.Xr free .
.Pp
The
.Fn devctl_freeze
function freezes probe and attach processing initiated in response to
drivers being loaded.

View File

@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "devctl.h"
@ -166,3 +167,43 @@ devctl_reset(const char *device, bool detach)
return (devctl_simple_request(DEV_RESET, device, detach ?
DEVF_RESET_DETACH : 0));
}
#define BUFLEN 1024
int
devctl_getpath(const char *device, const char *locator, char **buffer)
{
struct devreq req;
int serrno;
memset(&req, 0, sizeof(req));
if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >=
sizeof(req.dr_name)) {
errno = EINVAL;
*buffer = NULL;
return (-1);
}
/*
* Maybe do the request twice. Once to get the length, and then again to
* get the string if BUFLEN bytes is insufficient.
*/
req.dr_flags = 0;
req.dr_buffer.length = BUFLEN;
again:
req.dr_buffer.buffer = malloc(req.dr_buffer.length);
strlcpy(req.dr_buffer.buffer, locator, req.dr_buffer.length);
if (devctl_request(DEV_GET_PATH, &req) == 0) {
*buffer = req.dr_buffer.buffer;
return (0);
}
if (errno == ENAMETOOLONG && req.dr_buffer.length != BUFLEN) {
free(req.dr_buffer.buffer);
goto again;
}
serrno = errno;
free(req.dr_buffer.buffer);
errno = serrno;
*buffer = NULL;
return (-1);
}

View File

@ -44,6 +44,7 @@ int devctl_delete(const char *device, bool force);
int devctl_freeze(void);
int devctl_thaw(void);
int devctl_reset(const char *device, bool detach);
int devctl_getpath(const char *device, const char *locator, char **buffer);
__END_DECLS
#endif /* !__DEVCTL_H__ */