2 * TUX - Integrated Application Protocols Layer and Object Cache
4 * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
6 * proc.c: /proc/sys/tux handling
11 /****************************************************************
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 ****************************************************************/
28 char tux_common_docroot[200] = "/var/www/tux/";
29 char tux_http_subdocroot[200] = "";
30 char tux_ftp_subdocroot[200] = "";
31 char tux_logfile[200] = "/var/log/tux";
32 char tux_cgiroot[200] = "/var/www/tux/cgiroot/";
33 char tux_404_page[200] = "404.html";
34 char tux_default_vhost[200] = "default";
35 char tux_extra_html_header[600];
36 unsigned int tux_extra_html_header_size = 0;
40 unsigned int tux_clientport = 8080;
41 unsigned int tux_logging = 0;
42 unsigned int tux_threads = 2;
43 unsigned int tux_max_connect = 10000;
44 unsigned int tux_max_keepalives = 10000;
45 unsigned int tux_max_backlog = 2048;
46 unsigned int tux_keepalive_timeout = 0;
47 unsigned int tux_max_output_bandwidth = 0;
48 unsigned int tux_defer_accept = 1;
49 unsigned int tux_mode_forbidden = 0 /*S_IXUGO*/; /* do not allow executable (CGI) files */
50 unsigned int tux_mode_allowed = S_IROTH; /* allow access if read-other is set */
51 unsigned int tux_virtual_server = 0;
52 unsigned int tux_ftp_virtual_server = 0;
53 unsigned int mass_hosting_hash = 0;
54 unsigned int strip_host_tail = 0;
55 unsigned int tux_max_object_size = 0;
56 unsigned int log_cpu_mask = ~0;
57 unsigned int tux_compression = 0;
58 unsigned int tux_noid = 0;
59 unsigned int tux_cgi_inherit_cpu = 0;
60 unsigned int tux_cgi_cpu_mask = ~0;
61 unsigned int tux_zerocopy_header = 1;
62 unsigned int tux_max_free_requests = 1000;
63 unsigned int tux_ignore_query = 0;
64 unsigned int tux_all_userspace = 0;
65 unsigned int tux_redirect_logging = 1;
66 unsigned int tux_max_header_len = 3000;
67 unsigned int tux_referer_logging = 0;
68 unsigned int tux_generate_etags = 1;
69 unsigned int tux_generate_last_mod = 1;
70 unsigned int tux_generate_cache_control = 1;
71 unsigned int tux_ip_logging = 1;
72 unsigned int tux_ftp_wait_close = 1;
73 unsigned int tux_ftp_log_retr_only = 0;
74 unsigned int tux_hide_unreadable = 1;
75 unsigned int tux_http_dir_indexing = 0;
76 unsigned int tux_log_incomplete = 0;
77 unsigned int tux_cpu_offset = 0;
78 unsigned int tux_ftp_login_message = 0;
80 static struct ctl_table_header *tux_table_header;
82 static ctl_table tux_table[] = {
86 sizeof(tux_common_docroot),
98 sizeof(tux_http_subdocroot),
110 sizeof(tux_ftp_subdocroot),
143 { NET_TUX_KEEPALIVE_TIMEOUT,
145 &tux_keepalive_timeout,
155 { NET_TUX_MAX_KEEPALIVE_BW,
156 "max_output_bandwidth",
157 &tux_max_output_bandwidth,
167 { NET_TUX_DEFER_ACCEPT,
179 { NET_TUX_MAX_BACKLOG,
191 { NET_TUX_MAX_CONNECT,
203 { NET_TUX_MAX_KEEPALIVES,
215 { NET_TUX_MODE_FORBIDDEN,
227 { NET_TUX_MODE_ALLOWED,
278 sizeof(tux_404_page),
290 sizeof(tux_default_vhost),
301 &tux_extra_html_header,
302 sizeof(tux_extra_html_header),
311 { NET_TUX_CLIENTPORT,
312 "extra_html_header_size",
313 &tux_extra_html_header_size,
323 { NET_TUX_CLIENTPORT,
335 { NET_TUX_CLIENTPORT,
347 { NET_TUX_CLIENTPORT,
349 &tux_generate_last_mod,
359 { NET_TUX_CLIENTPORT,
360 "generate_cache_control",
361 &tux_generate_cache_control,
371 { NET_TUX_CLIENTPORT,
383 { NET_TUX_CLIENTPORT,
395 { NET_TUX_CLIENTPORT,
397 &tux_ftp_log_retr_only,
407 { NET_TUX_CLIENTPORT,
409 &tux_http_dir_indexing,
419 { NET_TUX_CLIENTPORT,
421 &tux_hide_unreadable,
431 { NET_TUX_CLIENTPORT,
481 { NET_TUX_LOGENTRY_ALIGN_ORDER,
482 "logentry_align_order",
483 &tux_logentry_align_order,
493 { NET_TUX_ACK_PINGPONG,
517 { NET_TUX_ZEROCOPY_PARSE,
529 { NET_TUX_VIRTUAL_SERVER,
541 { NET_TUX_VIRTUAL_SERVER,
553 { NET_TUX_VIRTUAL_SERVER,
565 { NET_TUX_VIRTUAL_SERVER,
566 "ftp_virtual_server",
567 &tux_ftp_virtual_server,
577 { NET_TUX_MAX_OBJECT_SIZE,
579 &tux_max_object_size,
589 { NET_TUX_COMPRESSION,
613 { NET_TUX_CGI_INHERIT_CPU,
615 &tux_cgi_inherit_cpu,
625 { NET_TUX_CGI_CPU_MASK,
637 { NET_TUX_ZEROCOPY_HEADER,
639 &tux_zerocopy_header,
649 { NET_TUX_ZEROCOPY_SENDFILE,
651 &tux_zerocopy_sendfile,
661 { NET_TUX_MAX_FREE_REQUESTS,
663 &tux_max_free_requests,
673 { NET_TUX_ALL_USERSPACE,
685 { NET_TUX_REDIRECT_LOGGING,
687 &tux_redirect_logging,
697 { NET_TUX_IGNORE_QUERY,
709 { NET_TUX_REFERER_LOGGING,
711 &tux_referer_logging,
721 { NET_TUX_REFERER_LOGGING,
733 { NET_TUX_REFERER_LOGGING,
735 &tux_ftp_login_message,
745 { NET_TUX_MAX_HEADER_LEN,
757 {0,0,0,0,0,0,0,0,0,0,0} };
760 static ctl_table tux_dir_table[] = {
761 {NET_TUX, "tux", NULL, 0, 0555, tux_table,0,0,0,0,0},
762 {0,0,0,0,0,0,0,0,0,0,0}
765 static ctl_table tux_root_table[] = {
766 {CTL_NET, "net", NULL, 0, 0555, tux_dir_table,0,0,0,0,0},
767 {0,0,0,0,0,0,0,0,0,0,0}
771 static struct proc_dir_entry * root_tux_dir;
772 static struct proc_dir_entry * log_cpu_mask_entry;
773 static struct proc_dir_entry * stat_entry;
774 static struct proc_dir_entry * tux_dir [CONFIG_TUX_NUMTHREADS];
775 static struct proc_dir_entry * listen_dir [CONFIG_TUX_NUMTHREADS];
777 tux_socket_t tux_listen [CONFIG_TUX_NUMTHREADS][CONFIG_TUX_NUMSOCKETS] =
778 { [0 ... CONFIG_TUX_NUMTHREADS-1] = { {&tux_proto_http, 0, 80, NULL}, } };
782 static int hex_read_proc (char *page, char **start, off_t off,
783 int count, int *eof, void *data)
785 if (count < HEX_DIGITS+1)
787 return sprintf (page, "%08x\n", *(unsigned int *)data);
790 static int hex_write_proc (struct file *file, const char *buffer,
791 unsigned long count, void *data)
793 char hexnum [HEX_DIGITS];
794 unsigned int new_value;
795 unsigned int i, full_count = count;
799 if (count > HEX_DIGITS)
801 if (copy_from_user(hexnum, buffer, count))
805 * Parse the first 8 characters as a hex string, any non-hex char
806 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are the same.
810 for (i = 0; i < count; i++) {
811 unsigned int c = hexnum[i];
814 case '0' ... '9': c -= '0'; break;
815 case 'a' ... 'f': c -= 'a'-10; break;
816 case 'A' ... 'F': c -= 'A'-10; break;
820 new_value = (new_value << 4) | c;
823 *(int *)data = new_value;
828 #define LINE_SIZE 1024
829 #define LINE_MASK (LINE_SIZE-1)
831 static int print_request_stats (threadinfo_t *ti, char *page, unsigned int skip_count, unsigned int max_count)
833 struct list_head *head, *curr;
835 unsigned int count = 0, size, line_off, len;
836 char stat_line [LINE_SIZE];
841 head = &ti->all_requests;
844 while (curr != head) {
845 req = list_entry(curr, tux_req_t, all);
848 if (count <= skip_count)
852 line_off += sprintf(stat_line + line_off, x)
854 if (req->proto == &tux_proto_http)
860 SP("%d ", req->atom_idx);
861 if (req->atom_idx >= 1)
862 SP("%p ", req->atoms[0]);
865 if (req->atom_idx >= 2)
866 SP("%p ", req->atoms[1]);
869 if (!list_empty(&req->work)) SP("W"); else SP(".");
870 if (!list_empty(&req->free)) SP("F"); else SP(".");
871 if (!list_empty(&req->lru)) SP("L"); else SP(".");
872 if (req->keep_alive) SP("K"); else SP(".");
873 if (req->idle_input) SP("I"); else SP(".");
874 if (timer_pending(&req->keepalive_timer))
875 SP("T(%lu/%lu)",jiffies,req->keepalive_timer.expires); else SP(".");
876 if (req->wait_output_space) SP("O"); else SP(".");
877 if (timer_pending(&req->output_timer))
878 SP("T"); else SP(".");
879 SP(" %d ", req->error);
880 SP(" %d ", req->status);
882 #define SP_HOST(ip,port) \
883 SP("%d.%d.%d.%d:%d ",NIPQUAD(ip),port)
887 SP("%d:", req->sock->sk->sk_state);
892 SP_HOST(req->client_addr, req->client_port);
894 SP("%Ld ", req->total_file_len);
895 SP("%Ld ", req->in_file.f_pos);
896 if (req->proto == &tux_proto_http) {
897 SP("%d ", req->method);
898 SP("%d ", req->version);
900 if (req->proto == &tux_proto_ftp) {
901 SP("%d ", req->ftp_command);
902 if (req->data_sock) {
903 if (req->data_sock->sk)
904 SP("%d:",req->data_sock->sk->sk_state);
907 if (req->data_sock->sk)
908 SP_HOST(inet_sk(req->data_sock->sk)->daddr,
909 inet_sk(req->data_sock->sk)->dport);
915 SP("%p/%p %p/%p ", req->sock, req->sock ? req->sock->sk : (void *)-1, req->data_sock, req->data_sock ? req->data_sock->sk : (void *)-1);
917 SP("%d\n", req->parsed_len);
918 len = req->headers_len;
922 memcpy(stat_line + line_off, req->headers, len);
924 len = req->objectname_len;
928 memcpy(stat_line + line_off, req->objectname, len);
931 if (line_off >= LINE_SIZE)
933 Dprintk("printing req %p, count %d, page %p: {%s}.\n", req, count, page, stat_line);
934 size = sprintf(page, "%-*s\n", LINE_SIZE-1, stat_line);
935 if (size != LINE_SIZE)
938 if (count-skip_count >= max_count)
942 Dprintk("count: %d.\n", count-skip_count);
943 return count - skip_count;
946 static int stat_read_proc (char *page, char **start, off_t off,
947 int max_size, int *eof, void *data)
949 unsigned int i, nr_total = 0, nr, nr_off, nr_skip, size = 0, nr_wanted;
951 Dprintk("START, page: %p, max_size: %d, off: %ld.\n", page, max_size, off);
953 if (max_size & LINE_MASK)
960 nr_off = off/LINE_SIZE;
962 for (i = 0; i < nr_tux_threads; i++) {
963 threadinfo_t *ti = threadinfo + i;
964 spin_lock_irq(&ti->work_lock);
965 nr = ti->nr_requests;
966 Dprintk("ti: %p, nr: %d, nr_total: %d, nr_off: %d.\n", ti, nr, nr_total, nr_off);
968 if (nr_off >= nr_total) {
969 spin_unlock_irq(&ti->work_lock);
972 nr_skip = nr_off - (nr_total - nr);
973 nr_wanted = (max_size-size) / LINE_SIZE;
974 Dprintk("nr_skip: %d, nr_wanted: %d.\n", nr_skip, nr_wanted);
975 nr = print_request_stats(ti, page + size, nr_skip, nr_wanted);
976 spin_unlock_irq(&ti->work_lock);
978 size += nr * LINE_SIZE;
979 Dprintk("ret: %d requests, size: %d.\n", nr, size);
982 if (size == max_size)
985 Dprintk("DONE: size: %d.\n", size);
994 static int stat_write_proc (struct file *file, const char *buffer,
995 unsigned long count, void *data)
1000 #define MAX_STRING "http://255.255.255.255:65535"
1001 #define MAX_STRINGLEN (sizeof(MAX_STRING))
1003 #define INACTIVE_1 "[inactive]\n"
1004 #define INACTIVE_2 "0\n"
1006 static int listen_read_proc (char *page, char **start, off_t off,
1007 int count, int *eof, void *data)
1009 tux_socket_t *listen = data;
1011 if (count < MAX_STRINGLEN)
1015 return sprintf(page, INACTIVE_1);
1017 return sprintf (page, "%s://%u.%u.%u.%u:%hu\n", listen->proto->name,
1018 HIPQUAD(listen->ip), listen->port);
1021 static int listen_write_proc (struct file *file, const char *buffer,
1022 unsigned long count, void *data)
1024 char string [MAX_STRINGLEN];
1025 unsigned int d1, d2, d3, d4;
1026 unsigned short port;
1027 tux_socket_t *listen = data;
1031 if (count > MAX_STRINGLEN)
1032 count = MAX_STRINGLEN;
1033 if (copy_from_user(string, buffer, count))
1037 if (!strcmp(string, INACTIVE_1) || !strcmp(string, INACTIVE_2)) {
1038 listen->proto = NULL;
1044 #define MK_IP(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | d)
1046 if (sscanf(string, "http://%u.%u.%u.%u:%hu\n",
1047 &d1, &d2, &d3, &d4, &port) == 5) {
1048 listen->ip = MK_IP(d1,d2,d3,d4);
1049 listen->port = port;
1050 listen->proto = &tux_proto_http;
1054 if (sscanf(string, "ftp://%u.%u.%u.%u:%hu\n",
1055 &d1, &d2, &d3, &d4, &port) == 5) {
1056 listen->ip = MK_IP(d1,d2,d3,d4);
1057 listen->port = port;
1058 listen->proto = &tux_proto_ftp;
1061 printk(KERN_ERR "tux: invalid listen-socket parameters: %s\n", string);
1065 #define MAX_NAMELEN 10
1067 static void register_tux_proc (unsigned int nr)
1069 struct proc_dir_entry *entry;
1070 char name [MAX_NAMELEN];
1076 sprintf(name, "%d", nr);
1078 /* create /proc/net/tux/1234/ */
1079 tux_dir[nr] = proc_mkdir(name, root_tux_dir);
1081 /* create /proc/net/tux/1234/listen/ */
1082 listen_dir[nr] = proc_mkdir("listen", tux_dir[nr]);
1084 /* create /proc/net/tux/1234/listen/ */
1085 for (i = 0; i < CONFIG_TUX_NUMSOCKETS; i++) {
1086 sprintf(name, "%d", i);
1087 entry = create_proc_entry(name, 0700, listen_dir[nr]);
1090 entry->data = (void *)(tux_listen[nr] + i);
1091 entry->read_proc = listen_read_proc;
1092 entry->write_proc = listen_write_proc;
1093 tux_listen[nr][i].entry = entry;
1097 static void unregister_tux_proc (unsigned int nr)
1101 for (i = 0; i < CONFIG_TUX_NUMSOCKETS; i++) {
1102 remove_proc_entry(tux_listen[nr][i].entry->name,listen_dir[nr]);
1103 tux_listen[nr][i].entry = NULL;
1106 remove_proc_entry(listen_dir[nr]->name, tux_dir[nr]);
1108 remove_proc_entry(tux_dir[nr]->name, root_tux_dir);
1111 static void cleanup_tux_proc (void)
1115 Dprintk("cleaning up /proc/net/tux/\n");
1117 for (i = 0; i < CONFIG_TUX_NUMTHREADS; i++)
1118 unregister_tux_proc(i);
1119 remove_proc_entry(stat_entry->name, root_tux_dir);
1120 remove_proc_entry(log_cpu_mask_entry->name, root_tux_dir);
1121 remove_proc_entry(root_tux_dir->name, proc_net);
1124 static void init_tux_proc (void)
1126 struct proc_dir_entry *entry;
1132 /* create /proc/net/tux */
1133 root_tux_dir = proc_mkdir("tux", proc_net);
1135 entry = create_proc_entry("log_cpu_mask", 0700, root_tux_dir);
1138 entry->data = (void *)&log_cpu_mask;
1139 entry->read_proc = hex_read_proc;
1140 entry->write_proc = hex_write_proc;
1142 log_cpu_mask_entry = entry;
1144 entry = create_proc_entry("stat", 0700, root_tux_dir);
1148 entry->read_proc = stat_read_proc;
1149 entry->write_proc = stat_write_proc;
1154 * Create entries for all existing threads.
1156 for (i = 0; i < CONFIG_TUX_NUMTHREADS; i++)
1157 register_tux_proc(i);
1160 void start_sysctl(void)
1163 tux_table_header = register_sysctl_table(tux_root_table,1);
1166 void end_sysctl(void)
1169 unregister_sysctl_table(tux_table_header);
1173 void mask_to_cpumask(unsigned int mask, cpumask_t *cpu_mask)
1176 unsigned int bit_mask, i;
1180 for (i=NR_CPUS-1; i--; i >= 0) {
1182 cpu_set(i, *cpu_mask);
1184 cpu_clear(i, *cpu_mask);