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 cpumask_t tux_log_cpu_mask = CPU_MASK_ALL;
57 unsigned int tux_compression = 0;
58 unsigned int tux_noid = 0;
59 unsigned int tux_cgi_inherit_cpu = 0;
60 cpumask_t tux_cgi_cpu_mask = CPU_MASK_ALL;
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_ZEROCOPY_HEADER,
627 &tux_zerocopy_header,
637 { NET_TUX_ZEROCOPY_SENDFILE,
639 &tux_zerocopy_sendfile,
649 { NET_TUX_MAX_FREE_REQUESTS,
651 &tux_max_free_requests,
661 { NET_TUX_ALL_USERSPACE,
673 { NET_TUX_REDIRECT_LOGGING,
675 &tux_redirect_logging,
685 { NET_TUX_IGNORE_QUERY,
697 { NET_TUX_REFERER_LOGGING,
699 &tux_referer_logging,
709 { NET_TUX_REFERER_LOGGING,
721 { NET_TUX_REFERER_LOGGING,
723 &tux_ftp_login_message,
733 { NET_TUX_MAX_HEADER_LEN,
745 {0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL} };
748 static ctl_table tux_dir_table[] = {
749 {NET_TUX, "tux", NULL, 0, 0555, tux_table, NULL, NULL, NULL, NULL, NULL},
750 {0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL}
753 static ctl_table tux_root_table[] = {
754 {CTL_NET, "net", NULL, 0, 0555, tux_dir_table, NULL, NULL, NULL, NULL, NULL},
755 {0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL}
759 static struct proc_dir_entry * root_tux_dir;
760 static struct proc_dir_entry * log_cpu_mask_entry;
761 static struct proc_dir_entry * cgi_cpu_mask_entry;
762 static struct proc_dir_entry * stat_entry;
763 static struct proc_dir_entry * tux_dir [CONFIG_TUX_NUMTHREADS];
764 static struct proc_dir_entry * listen_dir [CONFIG_TUX_NUMTHREADS];
766 tux_socket_t tux_listen [CONFIG_TUX_NUMTHREADS][CONFIG_TUX_NUMSOCKETS] =
767 { [0 ... CONFIG_TUX_NUMTHREADS-1] = { {&tux_proto_http, 0, 80, NULL}, } };
769 static int cpu_mask_read_proc (char *page, char **start, off_t off,
770 int count, int *eof, void *data)
772 int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
775 len += sprintf(page + len, "\n");
779 static int cpu_mask_write_proc (struct file *file,
780 const char __user *buffer,
781 unsigned long count, void *data)
783 cpumask_t *mask = (cpumask_t *)data;
784 unsigned long full_count = count, err;
787 err = cpumask_parse(buffer, count, new_value);
795 #define LINE_SIZE 1024
796 #define LINE_MASK (LINE_SIZE-1)
798 static int print_request_stats (threadinfo_t *ti, char *page, unsigned int skip_count, unsigned int max_count)
800 struct list_head *head, *curr;
802 unsigned int count = 0, size, line_off, len;
803 char stat_line [LINE_SIZE];
808 head = &ti->all_requests;
811 while (curr != head) {
812 req = list_entry(curr, tux_req_t, all);
815 if (count <= skip_count)
819 line_off += sprintf(stat_line + line_off, x)
821 if (req->proto == &tux_proto_http)
827 SP("%d ", req->atom_idx);
828 if (req->atom_idx >= 1)
829 SP("%p ", req->atoms[0]);
832 if (req->atom_idx >= 2)
833 SP("%p ", req->atoms[1]);
836 if (!list_empty(&req->work)) SP("W"); else SP(".");
837 if (!list_empty(&req->free)) SP("F"); else SP(".");
838 if (!list_empty(&req->lru)) SP("L"); else SP(".");
839 if (req->keep_alive) SP("K"); else SP(".");
840 if (req->idle_input) SP("I"); else SP(".");
841 if (timer_pending(&req->keepalive_timer))
842 SP("T(%lu/%lu)",jiffies,req->keepalive_timer.expires); else SP(".");
843 if (req->wait_output_space) SP("O"); else SP(".");
844 if (timer_pending(&req->output_timer))
845 SP("T"); else SP(".");
846 SP(" %d ", req->error);
847 SP(" %d ", req->status);
849 #define SP_HOST(ip,port) \
850 SP("%d.%d.%d.%d:%d ",NIPQUAD(ip),port)
854 SP("%d:", req->sock->sk->sk_state);
859 SP_HOST(req->client_addr, req->client_port);
861 SP("%Ld ", req->total_file_len);
862 SP("%Ld ", req->in_file ? req->in_file->f_pos : -1);
863 if (req->proto == &tux_proto_http) {
864 SP("%d ", req->method);
865 SP("%d ", req->version);
867 if (req->proto == &tux_proto_ftp) {
868 SP("%d ", req->ftp_command);
869 if (req->data_sock) {
870 if (req->data_sock->sk)
871 SP("%d:",req->data_sock->sk->sk_state);
874 if (req->data_sock->sk)
875 SP_HOST(inet_sk(req->data_sock->sk)->daddr,
876 inet_sk(req->data_sock->sk)->dport);
882 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);
884 SP("%d\n", req->parsed_len);
885 len = req->headers_len;
889 memcpy(stat_line + line_off, req->headers, len);
891 len = req->objectname_len;
895 memcpy(stat_line + line_off, req->objectname, len);
898 if (line_off >= LINE_SIZE)
900 Dprintk("printing req %p, count %d, page %p: {%s}.\n", req, count, page, stat_line);
901 size = sprintf(page, "%-*s\n", LINE_SIZE-1, stat_line);
902 if (size != LINE_SIZE)
905 if (count-skip_count >= max_count)
909 Dprintk("count: %d.\n", count-skip_count);
910 return count - skip_count;
913 static int stat_read_proc (char *page, char **start, off_t off,
914 int max_size, int *eof, void *data)
916 unsigned int i, nr_total = 0, nr, nr_off, nr_skip, size = 0, nr_wanted;
918 Dprintk("START, page: %p, max_size: %d, off: %ld.\n", page, max_size, off);
920 if (max_size & LINE_MASK)
927 nr_off = off/LINE_SIZE;
929 for (i = 0; i < nr_tux_threads; i++) {
930 threadinfo_t *ti = threadinfo + i;
931 spin_lock_irq(&ti->work_lock);
932 nr = ti->nr_requests;
933 Dprintk("ti: %p, nr: %d, nr_total: %d, nr_off: %d.\n", ti, nr, nr_total, nr_off);
935 if (nr_off >= nr_total) {
936 spin_unlock_irq(&ti->work_lock);
939 nr_skip = nr_off - (nr_total - nr);
940 nr_wanted = (max_size-size) / LINE_SIZE;
941 Dprintk("nr_skip: %d, nr_wanted: %d.\n", nr_skip, nr_wanted);
942 nr = print_request_stats(ti, page + size, nr_skip, nr_wanted);
943 spin_unlock_irq(&ti->work_lock);
945 size += nr * LINE_SIZE;
946 Dprintk("ret: %d requests, size: %d.\n", nr, size);
949 if (size == max_size)
952 Dprintk("DONE: size: %d.\n", size);
961 static int stat_write_proc (struct file *file, const char *buffer,
962 unsigned long count, void *data)
967 #define MAX_STRING "http://255.255.255.255:65535"
968 #define MAX_STRINGLEN (sizeof(MAX_STRING))
970 #define INACTIVE_1 "[inactive]\n"
971 #define INACTIVE_2 "0\n"
973 static int listen_read_proc (char *page, char **start, off_t off,
974 int count, int *eof, void *data)
976 tux_socket_t *listen = data;
978 if (count < MAX_STRINGLEN)
982 return sprintf(page, INACTIVE_1);
984 return sprintf (page, "%s://%u.%u.%u.%u:%hu\n", listen->proto->name,
985 HIPQUAD(listen->ip), listen->port);
988 static int listen_write_proc (struct file *file, const char *buffer,
989 unsigned long count, void *data)
991 char string [MAX_STRINGLEN];
992 unsigned int d1, d2, d3, d4;
994 tux_socket_t *listen = data;
998 if (count > MAX_STRINGLEN)
999 count = MAX_STRINGLEN;
1000 if (copy_from_user(string, buffer, count))
1004 if (!strcmp(string, INACTIVE_1) || !strcmp(string, INACTIVE_2)) {
1005 listen->proto = NULL;
1011 #define MK_IP(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | d)
1013 if (sscanf(string, "http://%u.%u.%u.%u:%hu\n",
1014 &d1, &d2, &d3, &d4, &port) == 5) {
1015 listen->ip = MK_IP(d1,d2,d3,d4);
1016 listen->port = port;
1017 listen->proto = &tux_proto_http;
1021 if (sscanf(string, "ftp://%u.%u.%u.%u:%hu\n",
1022 &d1, &d2, &d3, &d4, &port) == 5) {
1023 listen->ip = MK_IP(d1,d2,d3,d4);
1024 listen->port = port;
1025 listen->proto = &tux_proto_ftp;
1028 printk(KERN_ERR "tux: invalid listen-socket parameters: %s\n", string);
1032 #define MAX_NAMELEN 10
1034 static void register_tux_proc (unsigned int nr)
1036 struct proc_dir_entry *entry;
1037 char name [MAX_NAMELEN];
1043 sprintf(name, "%d", nr);
1045 /* create /proc/net/tux/1234/ */
1046 tux_dir[nr] = proc_mkdir(name, root_tux_dir);
1048 /* create /proc/net/tux/1234/listen/ */
1049 listen_dir[nr] = proc_mkdir("listen", tux_dir[nr]);
1051 /* create /proc/net/tux/1234/listen/ */
1052 for (i = 0; i < CONFIG_TUX_NUMSOCKETS; i++) {
1053 sprintf(name, "%d", i);
1054 entry = create_proc_entry(name, 0700, listen_dir[nr]);
1057 entry->data = (void *)(tux_listen[nr] + i);
1058 entry->read_proc = listen_read_proc;
1059 entry->write_proc = listen_write_proc;
1060 tux_listen[nr][i].entry = entry;
1064 static void unregister_tux_proc (unsigned int nr)
1068 for (i = 0; i < CONFIG_TUX_NUMSOCKETS; i++) {
1069 remove_proc_entry(tux_listen[nr][i].entry->name,listen_dir[nr]);
1070 tux_listen[nr][i].entry = NULL;
1073 remove_proc_entry(listen_dir[nr]->name, tux_dir[nr]);
1075 remove_proc_entry(tux_dir[nr]->name, root_tux_dir);
1078 static void cleanup_tux_proc (void)
1082 Dprintk("cleaning up /proc/net/tux/\n");
1084 for (i = 0; i < CONFIG_TUX_NUMTHREADS; i++)
1085 unregister_tux_proc(i);
1086 remove_proc_entry(stat_entry->name, root_tux_dir);
1087 remove_proc_entry(log_cpu_mask_entry->name, root_tux_dir);
1088 remove_proc_entry(cgi_cpu_mask_entry->name, root_tux_dir);
1089 remove_proc_entry(root_tux_dir->name, proc_net);
1092 static void init_tux_proc (void)
1094 struct proc_dir_entry *entry;
1100 /* create /proc/net/tux */
1101 root_tux_dir = proc_mkdir("tux", proc_net);
1103 entry = create_proc_entry("log_cpu_mask", 0700, root_tux_dir);
1106 entry->data = (void *)&tux_log_cpu_mask;
1107 entry->read_proc = cpu_mask_read_proc;
1108 entry->write_proc = cpu_mask_write_proc;
1110 log_cpu_mask_entry = entry;
1112 entry = create_proc_entry("cgi_cpu_mask", 0700, root_tux_dir);
1115 entry->data = (void *)&tux_cgi_cpu_mask;
1116 entry->read_proc = cpu_mask_read_proc;
1117 entry->write_proc = cpu_mask_write_proc;
1119 cgi_cpu_mask_entry = entry;
1121 entry = create_proc_entry("stat", 0700, root_tux_dir);
1125 entry->read_proc = stat_read_proc;
1126 entry->write_proc = stat_write_proc;
1131 * Create entries for all existing threads.
1133 for (i = 0; i < CONFIG_TUX_NUMTHREADS; i++)
1134 register_tux_proc(i);
1137 void start_sysctl(void)
1140 tux_table_header = register_sysctl_table(tux_root_table,1);
1143 void end_sysctl(void)
1146 unregister_sysctl_table(tux_table_header);