Deleted Added
full compact
devd.cc (263758) devd.cc (270004)
1/*-
2 * Copyright (c) 2002-2010 M. Warner Losh.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 49 unchanged lines hidden (view full) ---

58 */
59
60// TODO list:
61// o devd.conf and devd man pages need a lot of help:
62// - devd needs to document the unix domain socket
63// - devd.conf needs more details on the supported statements.
64
65#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2002-2010 M. Warner Losh.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 49 unchanged lines hidden (view full) ---

58 */
59
60// TODO list:
61// o devd.conf and devd man pages need a lot of help:
62// - devd needs to document the unix domain socket
63// - devd.conf needs more details on the supported statements.
64
65#include <sys/cdefs.h>
66__FBSDID("$FreeBSD: head/sbin/devd/devd.cc 263758 2014-03-26 02:25:40Z mjg $");
66__FBSDID("$FreeBSD: head/sbin/devd/devd.cc 270004 2014-08-14 22:33:56Z asomers $");
67
68#include <sys/param.h>
69#include <sys/socket.h>
70#include <sys/stat.h>
71#include <sys/sysctl.h>
72#include <sys/types.h>
73#include <sys/wait.h>
74#include <sys/un.h>

--- 20 unchanged lines hidden (view full) ---

95#include <map>
96#include <string>
97#include <list>
98#include <vector>
99
100#include "devd.h" /* C compatible definitions */
101#include "devd.hh" /* C++ class definitions */
102
67
68#include <sys/param.h>
69#include <sys/socket.h>
70#include <sys/stat.h>
71#include <sys/sysctl.h>
72#include <sys/types.h>
73#include <sys/wait.h>
74#include <sys/un.h>

--- 20 unchanged lines hidden (view full) ---

95#include <map>
96#include <string>
97#include <list>
98#include <vector>
99
100#include "devd.h" /* C compatible definitions */
101#include "devd.hh" /* C++ class definitions */
102
103#define PIPE "/var/run/devd.pipe"
103#define STREAMPIPE "/var/run/devd.pipe"
104#define SEQPACKETPIPE "/var/run/devd.seqpacket.pipe"
104#define CF "/etc/devd.conf"
105#define SYSCTL "hw.bus.devctl_queue"
106
107/*
108 * Since the client socket is nonblocking, we must increase its send buffer to
109 * handle brief event storms. On FreeBSD, AF_UNIX sockets don't have a receive
110 * buffer, so the client can't increate the buffersize by itself.
111 *
112 * For example, when creating a ZFS pool, devd emits one 165 character
113 * resource.fs.zfs.statechange message for each vdev in the pool. A 64k
114 * buffer has enough space for almost 400 drives, which would be very large but
115 * not impossibly large pool. A 128k buffer has enough space for 794 drives,
116 * which is more than can fit in a rack with modern technology.
117 */
118#define CLIENT_BUFSIZE 131072
119
120using namespace std;
121
105#define CF "/etc/devd.conf"
106#define SYSCTL "hw.bus.devctl_queue"
107
108/*
109 * Since the client socket is nonblocking, we must increase its send buffer to
110 * handle brief event storms. On FreeBSD, AF_UNIX sockets don't have a receive
111 * buffer, so the client can't increate the buffersize by itself.
112 *
113 * For example, when creating a ZFS pool, devd emits one 165 character
114 * resource.fs.zfs.statechange message for each vdev in the pool. A 64k
115 * buffer has enough space for almost 400 drives, which would be very large but
116 * not impossibly large pool. A 128k buffer has enough space for 794 drives,
117 * which is more than can fit in a rack with modern technology.
118 */
119#define CLIENT_BUFSIZE 131072
120
121using namespace std;
122
123typedef struct client {
124 int fd;
125 int socktype;
126} client_t;
127
122extern FILE *yyin;
123extern int lineno;
124
125static const char notify = '!';
126static const char nomatch = '?';
127static const char attach = '+';
128static const char detach = '-';
129

--- 687 unchanged lines hidden (view full) ---

817 break;
818 }
819
820 cfg.find_and_execute(type);
821 cfg.pop_var_table();
822}
823
824int
128extern FILE *yyin;
129extern int lineno;
130
131static const char notify = '!';
132static const char nomatch = '?';
133static const char attach = '+';
134static const char detach = '-';
135

--- 687 unchanged lines hidden (view full) ---

823 break;
824 }
825
826 cfg.find_and_execute(type);
827 cfg.pop_var_table();
828}
829
830int
825create_socket(const char *name)
831create_socket(const char *name, int socktype)
826{
827 int fd, slen;
828 struct sockaddr_un sun;
829
832{
833 int fd, slen;
834 struct sockaddr_un sun;
835
830 if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
836 if ((fd = socket(PF_LOCAL, socktype, 0)) < 0)
831 err(1, "socket");
832 bzero(&sun, sizeof(sun));
833 sun.sun_family = AF_UNIX;
834 strlcpy(sun.sun_path, name, sizeof(sun.sun_path));
835 slen = SUN_LEN(&sun);
836 unlink(name);
837 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
838 err(1, "fcntl");
839 if (::bind(fd, (struct sockaddr *) & sun, slen) < 0)
840 err(1, "bind");
841 listen(fd, 4);
842 chown(name, 0, 0); /* XXX - root.wheel */
843 chmod(name, 0666);
844 return (fd);
845}
846
847unsigned int max_clients = 10; /* Default, can be overriden on cmdline. */
848unsigned int num_clients;
837 err(1, "socket");
838 bzero(&sun, sizeof(sun));
839 sun.sun_family = AF_UNIX;
840 strlcpy(sun.sun_path, name, sizeof(sun.sun_path));
841 slen = SUN_LEN(&sun);
842 unlink(name);
843 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
844 err(1, "fcntl");
845 if (::bind(fd, (struct sockaddr *) & sun, slen) < 0)
846 err(1, "bind");
847 listen(fd, 4);
848 chown(name, 0, 0); /* XXX - root.wheel */
849 chmod(name, 0666);
850 return (fd);
851}
852
853unsigned int max_clients = 10; /* Default, can be overriden on cmdline. */
854unsigned int num_clients;
849list<int> clients;
850
855
856list<client_t> clients;
857
851void
852notify_clients(const char *data, int len)
853{
858void
859notify_clients(const char *data, int len)
860{
854 list<int>::iterator i;
861 list<client_t>::iterator i;
855
856 /*
857 * Deliver the data to all clients. Throw clients overboard at the
858 * first sign of trouble. This reaps clients who've died or closed
859 * their sockets, and also clients who are alive but failing to keep up
860 * (or who are maliciously not reading, to consume buffer space in
861 * kernel memory or tie up the limited number of available connections).
862 */
863 for (i = clients.begin(); i != clients.end(); ) {
862
863 /*
864 * Deliver the data to all clients. Throw clients overboard at the
865 * first sign of trouble. This reaps clients who've died or closed
866 * their sockets, and also clients who are alive but failing to keep up
867 * (or who are maliciously not reading, to consume buffer space in
868 * kernel memory or tie up the limited number of available connections).
869 */
870 for (i = clients.begin(); i != clients.end(); ) {
864 if (write(*i, data, len) != len) {
871 int flags;
872 if (i->socktype == SOCK_SEQPACKET)
873 flags = MSG_EOR;
874 else
875 flags = 0;
876
877 if (send(i->fd, data, len, flags) != len) {
865 --num_clients;
878 --num_clients;
866 close(*i);
879 close(i->fd);
867 i = clients.erase(i);
880 i = clients.erase(i);
868 devdlog(LOG_WARNING, "notify_clients: write() failed; "
881 devdlog(LOG_WARNING, "notify_clients: send() failed; "
869 "dropping unresponsive client\n");
870 } else
871 ++i;
872 }
873}
874
875void
876check_clients(void)
877{
878 int s;
879 struct pollfd pfd;
882 "dropping unresponsive client\n");
883 } else
884 ++i;
885 }
886}
887
888void
889check_clients(void)
890{
891 int s;
892 struct pollfd pfd;
880 list<int>::iterator i;
893 list<client_t>::iterator i;
881
882 /*
883 * Check all existing clients to see if any of them have disappeared.
884 * Normally we reap clients when we get an error trying to send them an
885 * event. This check eliminates the problem of an ever-growing list of
886 * zombie clients because we're never writing to them on a system
887 * without frequent device-change activity.
888 */
889 pfd.events = 0;
890 for (i = clients.begin(); i != clients.end(); ) {
894
895 /*
896 * Check all existing clients to see if any of them have disappeared.
897 * Normally we reap clients when we get an error trying to send them an
898 * event. This check eliminates the problem of an ever-growing list of
899 * zombie clients because we're never writing to them on a system
900 * without frequent device-change activity.
901 */
902 pfd.events = 0;
903 for (i = clients.begin(); i != clients.end(); ) {
891 pfd.fd = *i;
904 pfd.fd = i->fd;
892 s = poll(&pfd, 1, 0);
893 if ((s < 0 && s != EINTR ) ||
894 (s > 0 && (pfd.revents & POLLHUP))) {
895 --num_clients;
905 s = poll(&pfd, 1, 0);
906 if ((s < 0 && s != EINTR ) ||
907 (s > 0 && (pfd.revents & POLLHUP))) {
908 --num_clients;
896 close(*i);
909 close(i->fd);
897 i = clients.erase(i);
898 devdlog(LOG_NOTICE, "check_clients: "
899 "dropping disconnected client\n");
900 } else
901 ++i;
902 }
903}
904
905void
910 i = clients.erase(i);
911 devdlog(LOG_NOTICE, "check_clients: "
912 "dropping disconnected client\n");
913 } else
914 ++i;
915 }
916}
917
918void
906new_client(int fd)
919new_client(int fd, int socktype)
907{
920{
908 int s;
921 client_t s;
909 int sndbuf_size;
910
911 /*
912 * First go reap any zombie clients, then accept the connection, and
913 * shut down the read side to stop clients from consuming kernel memory
914 * by sending large buffers full of data we'll never read.
915 */
916 check_clients();
922 int sndbuf_size;
923
924 /*
925 * First go reap any zombie clients, then accept the connection, and
926 * shut down the read side to stop clients from consuming kernel memory
927 * by sending large buffers full of data we'll never read.
928 */
929 check_clients();
917 s = accept(fd, NULL, NULL);
918 if (s != -1) {
930 s.socktype = socktype;
931 s.fd = accept(fd, NULL, NULL);
932 if (s.fd != -1) {
919 sndbuf_size = CLIENT_BUFSIZE;
933 sndbuf_size = CLIENT_BUFSIZE;
920 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_size,
934 if (setsockopt(s.fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size,
921 sizeof(sndbuf_size)))
922 err(1, "setsockopt");
935 sizeof(sndbuf_size)))
936 err(1, "setsockopt");
923 shutdown(s, SHUT_RD);
937 shutdown(s.fd, SHUT_RD);
924 clients.push_back(s);
925 ++num_clients;
926 } else
927 err(1, "accept");
928}
929
930static void
931event_loop(void)
932{
933 int rv;
934 int fd;
935 char buffer[DEVCTL_MAXBUF];
936 int once = 0;
938 clients.push_back(s);
939 ++num_clients;
940 } else
941 err(1, "accept");
942}
943
944static void
945event_loop(void)
946{
947 int rv;
948 int fd;
949 char buffer[DEVCTL_MAXBUF];
950 int once = 0;
937 int server_fd, max_fd;
951 int stream_fd, seqpacket_fd, max_fd;
938 int accepting;
939 timeval tv;
940 fd_set fds;
941
942 fd = open(PATH_DEVCTL, O_RDONLY | O_CLOEXEC);
943 if (fd == -1)
944 err(1, "Can't open devctl device %s", PATH_DEVCTL);
952 int accepting;
953 timeval tv;
954 fd_set fds;
955
956 fd = open(PATH_DEVCTL, O_RDONLY | O_CLOEXEC);
957 if (fd == -1)
958 err(1, "Can't open devctl device %s", PATH_DEVCTL);
945 server_fd = create_socket(PIPE);
959 stream_fd = create_socket(STREAMPIPE, SOCK_STREAM);
960 seqpacket_fd = create_socket(SEQPACKETPIPE, SOCK_SEQPACKET);
946 accepting = 1;
961 accepting = 1;
947 max_fd = max(fd, server_fd) + 1;
962 max_fd = max(fd, max(stream_fd, seqpacket_fd)) + 1;
948 while (!romeo_must_die) {
949 if (!once && !no_daemon && !daemonize_quick) {
950 // Check to see if we have any events pending.
951 tv.tv_sec = 0;
952 tv.tv_usec = 0;
953 FD_ZERO(&fds);
954 FD_SET(fd, &fds);
955 rv = select(fd + 1, &fds, &fds, &fds, &tv);

--- 4 unchanged lines hidden (view full) ---

960 cfg.open_pidfile();
961 daemon(0, 0);
962 cfg.write_pidfile();
963 once++;
964 }
965 }
966 /*
967 * When we've already got the max number of clients, stop
963 while (!romeo_must_die) {
964 if (!once && !no_daemon && !daemonize_quick) {
965 // Check to see if we have any events pending.
966 tv.tv_sec = 0;
967 tv.tv_usec = 0;
968 FD_ZERO(&fds);
969 FD_SET(fd, &fds);
970 rv = select(fd + 1, &fds, &fds, &fds, &tv);

--- 4 unchanged lines hidden (view full) ---

975 cfg.open_pidfile();
976 daemon(0, 0);
977 cfg.write_pidfile();
978 once++;
979 }
980 }
981 /*
982 * When we've already got the max number of clients, stop
968 * accepting new connections (don't put server_fd in the set),
969 * shrink the accept() queue to reject connections quickly, and
970 * poll the existing clients more often, so that we notice more
971 * quickly when any of them disappear to free up client slots.
983 * accepting new connections (don't put the listening sockets in
984 * the set), shrink the accept() queue to reject connections
985 * quickly, and poll the existing clients more often, so that we
986 * notice more quickly when any of them disappear to free up
987 * client slots.
972 */
973 FD_ZERO(&fds);
974 FD_SET(fd, &fds);
975 if (num_clients < max_clients) {
976 if (!accepting) {
988 */
989 FD_ZERO(&fds);
990 FD_SET(fd, &fds);
991 if (num_clients < max_clients) {
992 if (!accepting) {
977 listen(server_fd, max_clients);
993 listen(stream_fd, max_clients);
994 listen(seqpacket_fd, max_clients);
978 accepting = 1;
979 }
995 accepting = 1;
996 }
980 FD_SET(server_fd, &fds);
997 FD_SET(stream_fd, &fds);
998 FD_SET(seqpacket_fd, &fds);
981 tv.tv_sec = 60;
982 tv.tv_usec = 0;
983 } else {
984 if (accepting) {
999 tv.tv_sec = 60;
1000 tv.tv_usec = 0;
1001 } else {
1002 if (accepting) {
985 listen(server_fd, 0);
1003 listen(stream_fd, 0);
1004 listen(seqpacket_fd, 0);
986 accepting = 0;
987 }
988 tv.tv_sec = 2;
989 tv.tv_usec = 0;
990 }
991 rv = select(max_fd, &fds, NULL, NULL, &tv);
992 if (got_siginfo) {
993 devdlog(LOG_NOTICE, "Events received so far=%u\n",

--- 23 unchanged lines hidden (view full) ---

1017 } else if (rv < 0) {
1018 if (errno != EINTR)
1019 break;
1020 } else {
1021 /* EOF */
1022 break;
1023 }
1024 }
1005 accepting = 0;
1006 }
1007 tv.tv_sec = 2;
1008 tv.tv_usec = 0;
1009 }
1010 rv = select(max_fd, &fds, NULL, NULL, &tv);
1011 if (got_siginfo) {
1012 devdlog(LOG_NOTICE, "Events received so far=%u\n",

--- 23 unchanged lines hidden (view full) ---

1036 } else if (rv < 0) {
1037 if (errno != EINTR)
1038 break;
1039 } else {
1040 /* EOF */
1041 break;
1042 }
1043 }
1025 if (FD_ISSET(server_fd, &fds))
1026 new_client(server_fd);
1044 if (FD_ISSET(stream_fd, &fds))
1045 new_client(stream_fd, SOCK_STREAM);
1046 /*
1047 * Aside from the socket type, both sockets use the same
1048 * protocol, so we can process clients the same way.
1049 */
1050 if (FD_ISSET(seqpacket_fd, &fds))
1051 new_client(seqpacket_fd, SOCK_SEQPACKET);
1027 }
1028 close(fd);
1029}
1030
1031/*
1032 * functions that the parser uses.
1033 */
1034void

--- 184 unchanged lines hidden ---
1052 }
1053 close(fd);
1054}
1055
1056/*
1057 * functions that the parser uses.
1058 */
1059void

--- 184 unchanged lines hidden ---