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 --- |