Page MenuHomeFreeBSD

D61346.1794697938.diff
No OneTemporary

Authored By
Unknown
Size
5 KB
Referenced Files
None
Subscribers
None

D61346.1794697938.diff

diff --git a/include/unistd.h b/include/unistd.h
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -312,6 +312,10 @@
#define _SC_NSIG 124
#endif
+#if __BSD_VISIBLE
+#define _SC_DEVCTL_MAXRECORD 125
+#endif
+
/* Keys for the confstr(3) function. */
#if __POSIX_VISIBLE >= 199209
#define _CS_PATH 1 /* default value of PATH */
diff --git a/lib/libc/gen/sysconf.3 b/lib/libc/gen/sysconf.3
--- a/lib/libc/gen/sysconf.3
+++ b/lib/libc/gen/sysconf.3
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd August 30, 2025
+.Dd November 7, 2026
.Dt SYSCONF 3
.Os
.Sh NAME
@@ -227,6 +227,14 @@
will overflow a
.Vt long
in some configurations on a 32bit machine.
+.It Li _SC_DEVCTL_MAXRECORD
+Maximum record size from
+.Xr devctl 4 .
+See
+.Xr devd 8
+and
+.Xr devctl 4
+for details.
.El
.Sh RETURN VALUES
If the call to
diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c
--- a/lib/libc/gen/sysconf.c
+++ b/lib/libc/gen/sysconf.c
@@ -622,6 +622,13 @@
case _SC_UEXTERR_MAXLEN:
return (UEXTERROR_MAXLEN);
+ case _SC_DEVCTL_MAXRECORD:
+ len = sizeof(value);
+ if (sysctlbyname("vm.uma.DEVCTL.size", &value, &len, NULL,
+ 0) == -1)
+ return (-1);
+ return ((long)value);
+
default:
errno = EINVAL;
return (-1);
diff --git a/sbin/devd/devd.8 b/sbin/devd/devd.8
--- a/sbin/devd/devd.8
+++ b/sbin/devd/devd.8
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 7, 2025
+.Dd November 7, 2026
.Dt DEVD 8
.Os
.Sh NAME
@@ -131,16 +131,33 @@
.Nm
system without modifying the user's other
config files.
-.Pp
+.Sh CLIENT SOCKET
Since
.Xr devctl 4
allows only one active reader,
.Nm
multiplexes it, forwarding all events to any number of connected clients.
-Clients connect by opening the SOCK_SEQPACKET
-.Ux
+Clients connect by opening the
+.Dv SOCK_SEQPACKET
+.Xr unix 4
domain socket at
-.Pa /var/run/devd.seqpacket.pipe .
+.Pa /var/run/devd.seqpacket.pipe ,
+also defined as
+.Va _PATH_DEVD_SOCKET
+in
+.In paths.h .
+.Pp
+The messages from
+.Xr devctl 4
+are copied verbatim to clients.
+This implies the newline termination and lack of NUL termination.
+The kernel and
+.Nm
+guarantee that a message shall be of a size less than
+.Fn sysconf _SC_DEVCTL_MAXRECORD .
+The above features allow a robust client implementation without
+a need to take care of a reassembly, see
+.Sx EXAMPLES .
.Sh FILES
.Bl -tag -width ".Pa /var/run/devd.seqpacket.pipe" -compact
.It Pa /etc/devd.conf
@@ -155,6 +172,36 @@
A deprecated socket retained for use with old clients.
.El
.Sh EXAMPLES
+A trivial client in C:
+.Bd -literal -offset indent
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <paths.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+ struct sockaddr_un sun = {
+ .sun_family = AF_LOCAL,
+ .sun_path = _PATH_DEVD_SOCKET,
+ };
+ ssize_t len, maxrec = sysconf(_SC_DEVCTL_MAXRECORD);
+ char event[maxrec];
+ int s;
+
+ s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+ connect(s, (struct sockaddr *)&sun, sizeof(sun));
+ while ((len = recv(s, event, maxrec, MSG_WAITALL)) > 0) {
+ event[len] = '\\0';
+ printf("%s", event);
+ }
+
+ return (0);
+}
+.Ed
+.Pp
Use
.Xr cat 1
to monitor kernel events:
@@ -162,7 +209,8 @@
.Dl cat /var/run/devd.seqpacket.pipe
.Sh SEE ALSO
.Xr devctl 4 ,
-.Xr devd.conf 5
+.Xr devd.conf 5 ,
+.Xr sysconf 3
.Sh HISTORY
The
.Nm
diff --git a/sbin/devd/tests/client_test.c b/sbin/devd/tests/client_test.c
--- a/sbin/devd/tests/client_test.c
+++ b/sbin/devd/tests/client_test.c
@@ -105,22 +105,17 @@
* If we never get both events, then the test will timeout.
*/
while (!(got_create_event && got_destroy_event)) {
- int cmp;
- ssize_t len;
- char event[1024];
+ ssize_t len, maxrec = sysconf(_SC_DEVCTL_MAXRECORD);
+ char event[maxrec];
- /* Read 1 less than sizeof(event) to allow space for NULL */
- len = recv(s, event, sizeof(event) - 1, MSG_WAITALL);
+ len = recv(s, event, maxrec, MSG_WAITALL);
ATF_REQUIRE(len != -1);
- /* NULL terminate the result */
event[len] = '\0';
printf("%s", event);
- cmp = strncmp(event, create_pat, sizeof(create_pat) - 1);
- if (cmp == 0)
+ if (strncmp(event, create_pat, sizeof(create_pat) - 1) == 0)
got_create_event = true;
- cmp = strncmp(event, destroy_pat, sizeof(destroy_pat) - 1);
- if (cmp == 0)
+ if (strncmp(event, destroy_pat, sizeof(destroy_pat) - 1) == 0)
got_destroy_event = true;
}
diff --git a/sys/kern/kern_devctl.c b/sys/kern/kern_devctl.c
--- a/sys/kern/kern_devctl.c
+++ b/sys/kern/kern_devctl.c
@@ -105,6 +105,14 @@
static d_poll_t devpoll;
static d_kqfilter_t devkqfilter;
+/*
+ * The size of struct dev_event_info is exposed to the userland via
+ * sysconf(_SC_DEVCTL_MAXRECORD). We suggest applications to use a slightly
+ * bigger buffer than DEVCTL_BUFFER, off just by size of a pointer. This is
+ * documented and allows applications to utilize this extra space for an
+ * optional NUL termination. If this structure substantially changes, care
+ * should be taken to export proper size.
+ */
#define DEVCTL_BUFFER (1024 - sizeof(void *))
struct dev_event_info {
STAILQ_ENTRY(dev_event_info) dei_link;
@@ -159,6 +167,7 @@
* usage. The reserve usually allows coverage of surges of
* events during memory shortages. Normally we won't have to
* re-use events from the queue, but will in extreme shortages.
+ * NB: the zone name is used by sysconf(_SC_DEVCTL_MAXRECORD).
*/
z = devsoftc.zone = uma_zcreate("DEVCTL",
sizeof(struct dev_event_info), NULL, NULL, NULL, NULL,

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 14, 11:12 PM (7 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41681780
Default Alt Text
D61346.1794697938.diff (5 KB)

Event Timeline