Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177551933
D61346.1794697938.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
5 KB
Referenced Files
None
Subscribers
None
D61346.1794697938.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D61346: devd: expose maximum record size via sysconf(3)
Attached
Detach File
Event Timeline