svn commit: r270242 - in stable/10: etc/mtree sbin/devd sbin/devd/tests
Alan Somers
asomers at FreeBSD.org
Wed Aug 20 19:31:00 UTC 2014
Author: asomers
Date: Wed Aug 20 19:30:58 2014
New Revision: 270242
URL: http://svnweb.freebsd.org/changeset/base/270242
Log:
MFC devd-related changes
r270004
Convert devd's client socket to type SOCK_SEQPACKET.
This change consists of two merges from projects/zfsd/head along with the
addition of an ATF test case for the new functionality.
sbin/devd/tests/Makefile
sbin/devd/tests/client_test.c
Add ATF test cases for reading events from both devd socket types.
r266519:
sbin/devd/devd.8
sbin/devd/devd.cc
Create a new socket, of type SOCK_SEQPACKET, for communicating with
clients. SOCK_SEQPACKET sockets preserve record boundaries,
simplying code in the client. The old SOCK_STREAM socket is retained
for backwards-compatibility with existing clients.
r269993:
sbin/devd/devd.8
Fix grammar bug.
r270019 (from bz)
Remove bogus ; at the end of the if condition in order to unbreak gcc builds
after r270004.
MFC after: 4 days
X-MFX with: r270004
Added:
stable/10/sbin/devd/tests/
- copied from r270004, head/sbin/devd/tests/
Modified:
stable/10/etc/mtree/BSD.tests.dist
stable/10/sbin/devd/Makefile
stable/10/sbin/devd/devd.8
stable/10/sbin/devd/devd.cc
stable/10/sbin/devd/tests/client_test.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/etc/mtree/BSD.tests.dist
==============================================================================
--- stable/10/etc/mtree/BSD.tests.dist Wed Aug 20 19:12:19 2014 (r270241)
+++ stable/10/etc/mtree/BSD.tests.dist Wed Aug 20 19:30:58 2014 (r270242)
@@ -95,6 +95,8 @@
sbin
dhclient
..
+ devd
+ ..
growfs
..
mdconfig
Modified: stable/10/sbin/devd/Makefile
==============================================================================
--- stable/10/sbin/devd/Makefile Wed Aug 20 19:12:19 2014 (r270241)
+++ stable/10/sbin/devd/Makefile Wed Aug 20 19:30:58 2014 (r270242)
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
PROG_CXX=devd
SRCS= devd.cc token.l parse.y y.tab.h
MAN= devd.8 devd.conf.5
@@ -16,4 +18,8 @@ CFLAGS+=-I. -I${.CURDIR}
CLEANFILES= y.output
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
Modified: stable/10/sbin/devd/devd.8
==============================================================================
--- stable/10/sbin/devd/devd.8 Wed Aug 20 19:12:19 2014 (r270241)
+++ stable/10/sbin/devd/devd.8 Wed Aug 20 19:30:58 2014 (r270242)
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 30, 2013
+.Dd August 14, 2014
.Dt DEVD 8
.Os
.Sh NAME
@@ -55,9 +55,7 @@ If option
.Fl f
is specified more than once, the last file specified is used.
.It Fl l Ar num
-Limit concurrent
-.Pa /var/run/devd.pipe
-connections to
+Limit concurrent socket connections to
.Ar num .
The default connection limit is 10.
.It Fl n
@@ -130,22 +128,27 @@ wish to hook into the
system without modifying the user's other
config files.
.Pp
-All messages that
+Since
+.Xr devctl 4
+allows only one active reader,
.Nm
-receives are forwarded to the
+multiplexes it, forwarding all events to any number of connected clients.
+Clients connect by opening the SOCK_SEQPACKET
.Ux
domain socket at
-.Pa /var/run/devd.pipe .
+.Pa /var/run/devd.seqpacket.pipe .
.Sh FILES
-.Bl -tag -width ".Pa /var/run/devd.pipe" -compact
+.Bl -tag -width ".Pa /var/run/devd.seqpacket.pipe" -compact
.It Pa /etc/devd.conf
The default
.Nm
configuration file.
-.It Pa /var/run/devd.pipe
+.It Pa /var/run/devd.seqpacket.pipe
The socket used by
.Nm
to communicate with its clients.
+.It Pa /var/run/devd.pipe
+A deprecated socket retained for use with old clients.
.El
.Sh SEE ALSO
.Xr devctl 4 ,
Modified: stable/10/sbin/devd/devd.cc
==============================================================================
--- stable/10/sbin/devd/devd.cc Wed Aug 20 19:12:19 2014 (r270241)
+++ stable/10/sbin/devd/devd.cc Wed Aug 20 19:30:58 2014 (r270242)
@@ -100,7 +100,8 @@ __FBSDID("$FreeBSD$");
#include "devd.h" /* C compatible definitions */
#include "devd.hh" /* C++ class definitions */
-#define PIPE "/var/run/devd.pipe"
+#define STREAMPIPE "/var/run/devd.pipe"
+#define SEQPACKETPIPE "/var/run/devd.seqpacket.pipe"
#define CF "/etc/devd.conf"
#define SYSCTL "hw.bus.devctl_queue"
@@ -119,6 +120,11 @@ __FBSDID("$FreeBSD$");
using namespace std;
+typedef struct client {
+ int fd;
+ int socktype;
+} client_t;
+
extern FILE *yyin;
extern int lineno;
@@ -822,12 +828,12 @@ process_event(char *buffer)
}
int
-create_socket(const char *name)
+create_socket(const char *name, int socktype)
{
int fd, slen;
struct sockaddr_un sun;
- if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
+ if ((fd = socket(PF_LOCAL, socktype, 0)) < 0)
err(1, "socket");
bzero(&sun, sizeof(sun));
sun.sun_family = AF_UNIX;
@@ -846,12 +852,13 @@ create_socket(const char *name)
unsigned int max_clients = 10; /* Default, can be overriden on cmdline. */
unsigned int num_clients;
-list<int> clients;
+
+list<client_t> clients;
void
notify_clients(const char *data, int len)
{
- list<int>::iterator i;
+ list<client_t>::iterator i;
/*
* Deliver the data to all clients. Throw clients overboard at the
@@ -861,11 +868,17 @@ notify_clients(const char *data, int len
* kernel memory or tie up the limited number of available connections).
*/
for (i = clients.begin(); i != clients.end(); ) {
- if (write(*i, data, len) != len) {
+ int flags;
+ if (i->socktype == SOCK_SEQPACKET)
+ flags = MSG_EOR;
+ else
+ flags = 0;
+
+ if (send(i->fd, data, len, flags) != len) {
--num_clients;
- close(*i);
+ close(i->fd);
i = clients.erase(i);
- devdlog(LOG_WARNING, "notify_clients: write() failed; "
+ devdlog(LOG_WARNING, "notify_clients: send() failed; "
"dropping unresponsive client\n");
} else
++i;
@@ -877,7 +890,7 @@ check_clients(void)
{
int s;
struct pollfd pfd;
- list<int>::iterator i;
+ list<client_t>::iterator i;
/*
* Check all existing clients to see if any of them have disappeared.
@@ -888,12 +901,12 @@ check_clients(void)
*/
pfd.events = 0;
for (i = clients.begin(); i != clients.end(); ) {
- pfd.fd = *i;
+ pfd.fd = i->fd;
s = poll(&pfd, 1, 0);
if ((s < 0 && s != EINTR ) ||
(s > 0 && (pfd.revents & POLLHUP))) {
--num_clients;
- close(*i);
+ close(i->fd);
i = clients.erase(i);
devdlog(LOG_NOTICE, "check_clients: "
"dropping disconnected client\n");
@@ -903,9 +916,9 @@ check_clients(void)
}
void
-new_client(int fd)
+new_client(int fd, int socktype)
{
- int s;
+ client_t s;
int sndbuf_size;
/*
@@ -914,13 +927,14 @@ new_client(int fd)
* by sending large buffers full of data we'll never read.
*/
check_clients();
- s = accept(fd, NULL, NULL);
- if (s != -1) {
+ s.socktype = socktype;
+ s.fd = accept(fd, NULL, NULL);
+ if (s.fd != -1) {
sndbuf_size = CLIENT_BUFSIZE;
- if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_size,
+ if (setsockopt(s.fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size,
sizeof(sndbuf_size)))
err(1, "setsockopt");
- shutdown(s, SHUT_RD);
+ shutdown(s.fd, SHUT_RD);
clients.push_back(s);
++num_clients;
} else
@@ -934,7 +948,7 @@ event_loop(void)
int fd;
char buffer[DEVCTL_MAXBUF];
int once = 0;
- int server_fd, max_fd;
+ int stream_fd, seqpacket_fd, max_fd;
int accepting;
timeval tv;
fd_set fds;
@@ -942,9 +956,10 @@ event_loop(void)
fd = open(PATH_DEVCTL, O_RDONLY | O_CLOEXEC);
if (fd == -1)
err(1, "Can't open devctl device %s", PATH_DEVCTL);
- server_fd = create_socket(PIPE);
+ stream_fd = create_socket(STREAMPIPE, SOCK_STREAM);
+ seqpacket_fd = create_socket(SEQPACKETPIPE, SOCK_SEQPACKET);
accepting = 1;
- max_fd = max(fd, server_fd) + 1;
+ max_fd = max(fd, max(stream_fd, seqpacket_fd)) + 1;
while (!romeo_must_die) {
if (!once && !no_daemon && !daemonize_quick) {
// Check to see if we have any events pending.
@@ -965,24 +980,28 @@ event_loop(void)
}
/*
* When we've already got the max number of clients, stop
- * accepting new connections (don't put server_fd in the set),
- * shrink the accept() queue to reject connections quickly, and
- * poll the existing clients more often, so that we notice more
- * quickly when any of them disappear to free up client slots.
+ * accepting new connections (don't put the listening sockets in
+ * the set), shrink the accept() queue to reject connections
+ * quickly, and poll the existing clients more often, so that we
+ * notice more quickly when any of them disappear to free up
+ * client slots.
*/
FD_ZERO(&fds);
FD_SET(fd, &fds);
if (num_clients < max_clients) {
if (!accepting) {
- listen(server_fd, max_clients);
+ listen(stream_fd, max_clients);
+ listen(seqpacket_fd, max_clients);
accepting = 1;
}
- FD_SET(server_fd, &fds);
+ FD_SET(stream_fd, &fds);
+ FD_SET(seqpacket_fd, &fds);
tv.tv_sec = 60;
tv.tv_usec = 0;
} else {
if (accepting) {
- listen(server_fd, 0);
+ listen(stream_fd, 0);
+ listen(seqpacket_fd, 0);
accepting = 0;
}
tv.tv_sec = 2;
@@ -1022,8 +1041,14 @@ event_loop(void)
break;
}
}
- if (FD_ISSET(server_fd, &fds))
- new_client(server_fd);
+ if (FD_ISSET(stream_fd, &fds))
+ new_client(stream_fd, SOCK_STREAM);
+ /*
+ * Aside from the socket type, both sockets use the same
+ * protocol, so we can process clients the same way.
+ */
+ if (FD_ISSET(seqpacket_fd, &fds))
+ new_client(seqpacket_fd, SOCK_SEQPACKET);
}
close(fd);
}
Modified: stable/10/sbin/devd/tests/client_test.c
==============================================================================
--- head/sbin/devd/tests/client_test.c Thu Aug 14 22:33:56 2014 (r270004)
+++ stable/10/sbin/devd/tests/client_test.c Wed Aug 20 19:30:58 2014 (r270242)
@@ -49,7 +49,7 @@ create_two_events(void)
char destroy_cmd[80];
char *error;
- create_stdout = popen("mdconfig -a -s 64 -t null", "r");
+ create_stdout = popen("mdconfig -a -s 64 -t swap", "r");
ATF_REQUIRE(create_stdout != NULL);
error = fgets(mdname, sizeof(mdname), create_stdout);
ATF_REQUIRE(error != NULL);
@@ -168,11 +168,11 @@ ATF_TC_BODY(stream, tc)
printf("%s", event);
create_pos = strstr(event, create_pat);
- if (create_pos != NULL);
+ if (create_pos != NULL)
got_create_event = true;
destroy_pos = strstr(event, destroy_pat);
- if (destroy_pos != NULL);
+ if (destroy_pos != NULL)
got_destroy_event = true;
}
More information about the svn-src-all
mailing list