5 * TUX - Integrated Application Protocols Layer and Object Cache
7 * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
9 * tux.h: main structure definitions and function prototypes
12 #define __KERNEL_SYSCALLS__
15 #include <linux/net.h>
16 #include <linux/wait.h>
17 #include <linux/namei.h>
18 #include <linux/file.h>
19 #include <linux/mman.h>
20 #include <linux/swap.h>
21 #include <linux/ctype.h>
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/unistd.h>
25 #include <linux/sysctl.h>
26 #include <linux/proc_fs.h>
27 #include <linux/pagemap.h>
28 #include <linux/vmalloc.h>
29 #include <linux/utsname.h>
30 #include <linux/smp_lock.h>
31 #include <linux/kernel_stat.h>
32 #include <linux/kernel_stat.h>
33 #include <linux/time.h>
34 #include <asm/div64.h>
35 #include <asm/unaligned.h>
36 #include <linux/compiler.h>
37 #include <linux/mount.h>
38 #include <linux/zlib.h>
39 #include <linux/syscalls.h>
40 #include <linux/cpumask.h>
43 #include <net/tux_u.h>
45 /* Maximum number of threads: */
46 #define CONFIG_TUX_NUMTHREADS 16
48 /* Number of cachemiss/IO threads: */
49 #define NR_IO_THREADS 64
51 /* Maximum number of listen sockets per thread: */
52 #define CONFIG_TUX_NUMSOCKETS 16
54 extern spinlock_t tux_module_lock;
55 extern struct module *tux_module;
56 extern asmlinkage long (*sys_tux_ptr) (unsigned int action, user_req_t *u_info);
60 extern int tux_TDprintk;
61 extern int tux_Dprintk;
63 #ifdef CONFIG_TUX_DEBUG
64 # define TUX_BUG() BUG()
66 # define TUX_DPRINTK 1
67 # define TDprintk(x...) do { if (tux_TDprintk) { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } } while (0)
68 # define Dprintk(x...) do { if (tux_Dprintk == 1) TDprintk(x); } while (0)
70 # define TUX_DPRINTK 0
71 # define Dprintk(x...) do { } while (0)
72 # define TDprintk(x...) do { } while (0)
73 //# define TUX_BUG() BUG()
74 # define TUX_BUG() do { } while (0)
78 # define INC_STAT(x) do { } while (0)
79 # define DEC_STAT(x) do { } while (0)
80 # define ADD_STAT(x,y) do { } while (0)
81 # define SUB_STAT(x,y) do { } while (0)
83 # define INC_STAT(x) atomic_inc((atomic_t *)&kstat.x)
84 # define DEC_STAT(x) atomic_dec((atomic_t *)&kstat.x)
85 # define ADD_STAT(y,x) atomic_add(y,(atomic_t *)&kstat.x)
86 # define SUB_STAT(y,x) atomic_sub(y,(atomic_t *)&kstat.x)
91 # define DEBUG_DEL_LIST(x...) do { INIT_LIST_HEAD((x)); } while (0)
94 #define LOG_LEN (8*1024*1024UL)
96 struct tux_req_struct;
97 typedef struct tux_req_struct tux_req_t;
98 typedef struct tux_threadinfo threadinfo_t;
100 extern struct address_space_operations url_aops;
102 typedef struct tcapi_template_s {
104 struct list_head modules;
105 int (*query) (tux_req_t *req);
107 unsigned int userspace_id;
110 typedef struct mimetype_s {
111 struct list_head list;
114 unsigned int ext_len;
116 unsigned int type_len;
118 unsigned int expire_str_len;
120 unsigned int special;
123 typedef struct tux_attribute_s {
125 tcapi_template_t *tcapi;
128 #define MAX_TUX_ATOMS 8
130 typedef void (atom_func_t)(tux_req_t *req, int cachemiss);
132 typedef struct tux_proto_s
134 unsigned int defer_accept;
135 unsigned int can_redirect;
136 void (*got_request) (tux_req_t *req);
137 int (*parse_message) (tux_req_t *req, const int total_len);
138 atom_func_t *illegal_request;
139 atom_func_t *request_timeout;
140 void (*pre_log) (tux_req_t *req);
141 int (*check_req_err) (tux_req_t *req, int cachemiss);
142 char * (*print_dir_line) (tux_req_t *req, char *tmp, char *d_name, int d_len, int d_type, struct dentry *dentry, struct inode *inode);
144 struct nameidata main_docroot;
147 typedef struct tux_socket_s {
151 struct proc_dir_entry *entry;
154 extern tux_socket_t tux_listen [CONFIG_TUX_NUMTHREADS][CONFIG_TUX_NUMSOCKETS];
157 typedef struct abuf_s {
161 unsigned int max_len;
167 struct linux_dirent64 {
170 unsigned short d_reclen;
171 unsigned char d_type;
175 struct getdents_callback64 {
176 struct linux_dirent64 * current_dir;
177 struct linux_dirent64 * previous;
182 #define TUX_MAGIC 0x12457801
184 #define MAX_TUX_ATOMS 8
186 struct tux_req_struct
191 atom_func_t *atoms [MAX_TUX_ATOMS];
192 struct list_head work;
194 struct list_head all;
195 struct list_head free;
196 struct list_head lru;
198 unsigned long idle_input;
199 unsigned long wait_output_space;
202 struct dentry *dentry;
203 struct vfsmount *mnt;
204 struct dentry *docroot_dentry;
205 struct vfsmount *docroot_mnt;
206 struct dentry *cwd_dentry;
207 struct vfsmount *cwd_mnt;
209 struct file *in_file;
211 read_descriptor_t desc;
214 unsigned int virtual;
216 loff_t total_file_len;
217 unsigned int lendigits;
222 loff_t ftp_offset_start;
225 unsigned int etaglen;
229 unsigned int usermodule_idx;
230 struct dentry *module_dentry;
231 struct vfsmount *module_mnt;
233 unsigned int userlen;
235 tux_attribute_t *attr;
239 wait_queue_t ftp_sleep;
243 * Parsed request fields. In-line strings are zero-delimited.
246 unsigned int headers_len;
248 unsigned int parsed_len;
251 ftp_command_t ftp_command;
255 struct socket *data_sock;
256 unsigned int prev_pos;
259 struct linux_dirent64 *dirp0;
260 unsigned int curroff, total;
262 #define MAX_USERNAME_LEN 16
263 char username[MAX_USERNAME_LEN];
264 unsigned int username_len;
267 http_method_t method;
268 const char *method_str;
269 unsigned int method_len;
271 http_version_t version;
272 const char *version_str;
273 unsigned int version_len;
278 unsigned int uri_len;
280 /* Objectname (filename/scriptname) this URI refers to: */
282 #define MAX_OBJECTNAME_LEN 256
283 char objectname[MAX_OBJECTNAME_LEN + 4]; // space for .gz as well
284 unsigned int objectname_len;
286 /* Query string within the URI: */
288 const char *query_str;
289 unsigned int query_len;
293 const char *cookies_str;
294 unsigned int cookies_len;
295 unsigned int parse_cookies;
298 const char *content_type_str;
299 unsigned int content_type_len;
301 /* Content-Length: */
303 const char *contentlen_str;
304 unsigned int contentlen_len;
305 unsigned int content_len;
309 const char *user_agent_str;
310 unsigned int user_agent_len;
314 const char *accept_str;
315 unsigned int accept_len;
317 /* Accept-Charset: */
319 const char *accept_charset_str;
320 unsigned int accept_charset_len;
322 /* Accept-Language: */
324 const char *accept_language_str;
325 unsigned int accept_language_len;
329 const char *cache_control_str;
330 unsigned int cache_control_len;
332 /* If-Modified-Since: */
334 const char *if_modified_since_str;
335 unsigned int if_modified_since_len;
338 const char *if_none_match_str;
339 unsigned int if_none_match_len;
343 const char *if_range_str;
344 unsigned int if_range_len;
348 const char *negotiate_str;
349 unsigned int negotiate_len;
353 const char *pragma_str;
354 unsigned int pragma_len;
358 const char *referer_str;
359 unsigned int referer_len;
361 /* Accept-Encoding: */
363 const char *accept_encoding_str;
364 unsigned int accept_encoding_len;
365 unsigned int may_send_gzip;
366 unsigned int content_gzipped;
370 #define MAX_HOST_LEN 128
371 char host[MAX_HOST_LEN];
372 unsigned int host_len;
376 const char *post_data_str;
377 unsigned int post_data_len;
381 /* the file being sent */
383 unsigned int bytes_sent;
384 #ifdef CONFIG_TUX_DEBUG
385 unsigned int bytes_expected;
387 unsigned long first_timestamp;
388 unsigned int body_len;
390 unsigned int user_error;
400 struct timer_list keepalive_timer;
401 unsigned int total_bytes;
402 struct timer_list output_timer;
404 unsigned int nr_keepalives;
410 void (*real_data_ready)(struct sock *sk, int space);
411 void (*real_state_change)(struct sock *sk);
412 void (*real_write_space)(struct sock *sk);
413 void (*real_error_report)(struct sock *sk);
414 void (*real_destruct)(struct sock *sk);
416 void (*ftp_real_data_ready)(struct sock *sk, int space);
417 void (*ftp_real_state_change)(struct sock *sk);
418 void (*ftp_real_write_space)(struct sock *sk);
419 void (*ftp_real_error_report)(struct sock *sk);
420 void (*ftp_real_create_child)(struct sock *sk, struct sock *newsk);
421 void (*ftp_real_destruct)(struct sock *sk);
423 #ifdef CONFIG_TUX_EXTENDED_LOG
424 unsigned long accept_timestamp;
425 unsigned long parse_timestamp;
426 unsigned long output_timestamp;
427 unsigned long flush_timestamp;
428 # define SET_TIMESTAMP(x) do { (x) = jiffies; } while (0)
430 # define SET_TIMESTAMP(x) do { } while (0)
435 extern void add_tux_atom (tux_req_t *req, atom_func_t *event_done);
436 extern void del_tux_atom (tux_req_t *req);
437 extern void tux_schedule_atom (tux_req_t *req, int cachemiss);
438 extern void add_req_to_workqueue (tux_req_t *req);
441 typedef struct iothread_s
443 spinlock_t async_lock;
445 struct list_head async_queue;
446 wait_queue_head_t async_sleep;
447 unsigned int nr_async_pending;
448 unsigned int threads;
449 unsigned int shutdown;
450 wait_queue_head_t wait_shutdown;
453 typedef struct tux_listen_s
460 struct tux_threadinfo
462 tux_req_t *userspace_req;
463 unsigned int started;
464 struct task_struct *thread;
466 wait_queue_t wait_event [CONFIG_TUX_NUMSOCKETS];
470 struct page *header_cache;
471 unsigned int header_offset;
473 unsigned int nr_requests;
474 struct list_head all_requests;
476 unsigned int nr_free_requests;
477 spinlock_t free_requests_lock;
478 struct list_head free_requests;
480 spinlock_t work_lock;
481 struct list_head work_pending;
482 struct list_head lru;
485 unsigned int listen_error;
486 tux_listen_t listen[CONFIG_TUX_NUMSOCKETS];
488 struct semaphore gzip_sem;
492 unsigned int __padding[16];
495 typedef enum special_mimetypes {
500 } special_mimetypes_t;
502 #ifdef CONFIG_TUX_DEBUG
504 extern inline void url_hist_hit (int size)
506 unsigned int idx = size/1024;
508 if (idx >= URL_HIST_SIZE)
509 idx = URL_HIST_SIZE-1;
510 kstat.url_hist_hits[idx]++;
512 extern inline void url_hist_miss (int size)
514 unsigned int idx = size/1024;
516 if (idx >= URL_HIST_SIZE)
517 idx = URL_HIST_SIZE-1;
518 kstat.url_hist_misses[idx]++;
521 extern void __check_req_list (tux_req_t *req, struct list_head *list);
522 # define check_req_list __check_req_list
524 # define check_req_list(req, list) do { } while (0)
527 #define url_hist_hit(size) do { } while (0)
528 #define url_hist_miss(size) do { } while (0)
530 extern char tux_common_docroot[200];
531 extern char tux_http_subdocroot[200];
532 extern char tux_ftp_subdocroot[200];
533 extern char tux_logfile[200];
534 extern char tux_cgiroot[200];
535 extern char tux_404_page[200];
536 extern char tux_default_vhost[200];
537 extern char tux_extra_html_header[600];
538 extern unsigned int tux_extra_html_header_size;
539 extern int tux_cgi_uid;
540 extern int tux_cgi_gid;
541 extern unsigned int tux_clientport;
542 extern unsigned int tux_logging;
543 extern unsigned int tux_threads;
544 extern unsigned int tux_keepalive_timeout;
545 extern unsigned int tux_max_output_bandwidth;
546 extern unsigned int tux_max_backlog;
547 extern unsigned int tux_max_connect;
548 extern unsigned int tux_mode_forbidden;
549 extern unsigned int tux_mode_allowed;
550 extern unsigned int tux_logentry_align_order;
551 extern unsigned int tux_nonagle;
552 extern unsigned int tux_ack_pingpong;
553 extern unsigned int tux_push_all;
554 extern unsigned int tux_zerocopy_parse;
555 extern unsigned int tux_generate_etags;
556 extern unsigned int tux_generate_last_mod;
557 extern unsigned int tux_generate_cache_control;
558 extern unsigned int tux_ip_logging;
559 extern unsigned int tux_ftp_wait_close;
560 extern unsigned int tux_ftp_log_retr_only;
561 extern unsigned int tux_hide_unreadable;
563 typedef enum virtual_server {
570 extern unsigned int tux_virtual_server;
571 extern unsigned int mass_hosting_hash;
572 extern unsigned int strip_host_tail;
573 extern unsigned int tux_ftp_virtual_server;
575 extern unsigned int tux_max_object_size;
576 extern unsigned int tux_max_free_requests;
577 extern unsigned int tux_defer_accept;
579 extern struct socket * start_listening(tux_socket_t *listen, int nr);
580 extern void stop_listening(struct socket **sock);
581 extern void start_sysctl(void);
582 extern void end_sysctl(void);
583 extern void flush_request (tux_req_t *req, int cachemiss);
584 extern void unlink_tux_socket (tux_req_t *req);
585 extern void unlink_tux_data_socket (tux_req_t *req);
586 extern void unlink_tux_listen_socket (tux_req_t *req);
587 extern void link_tux_ftp_accept_socket (tux_req_t *req, struct socket *sock);
588 extern void link_tux_data_socket (tux_req_t *req, struct socket *sock);
589 extern void tux_push_req (tux_req_t *req);
590 extern int send_sync_buf (tux_req_t *req, struct socket *sock, const char *buf, const size_t length, unsigned long flags);
591 extern void __send_async_message (tux_req_t *req, const char *message, int status, unsigned int size, int push);
592 #define send_async_message(req,str,status,push) \
593 __send_async_message(req,str,status,strlen(str),push)
595 extern void send_success (tux_req_t *req, struct socket *sock);
596 extern void send_async_err_not_found (tux_req_t *req);
597 extern void send_async_timed_out (tux_req_t *req);
599 extern void kfree_req (tux_req_t *req);
600 extern int accept_requests (threadinfo_t *ti);
601 extern int process_requests (threadinfo_t *ti, tux_req_t **user_req);
602 extern int flush_freequeue (threadinfo_t * ti);
603 extern int tux_flush_workqueue (threadinfo_t *ti);
604 extern tux_req_t * pick_userspace_req (threadinfo_t *ti);
605 extern atom_func_t redirect_request;
606 extern atom_func_t parse_request;
607 extern void queue_cachemiss (tux_req_t *req);
608 extern int start_cachemiss_threads (threadinfo_t *ti);
609 extern void stop_cachemiss_threads (threadinfo_t *ti);
610 struct file * tux_open_file(char *filename, int mode);
611 extern void start_log_thread (void);
612 extern void stop_log_thread (void);
613 extern void add_mimetype (char *new_ext, char *new_type, char *new_expire);
614 extern void free_mimetypes (void);
615 extern int lookup_object (tux_req_t *req, const unsigned int flag);
616 extern int handle_gzip_req (tux_req_t *req, unsigned int flags);
617 extern struct dentry * tux_lookup (tux_req_t *req, const char *filename, const unsigned int flag, struct vfsmount **mnt);
618 extern tcapi_template_t * lookup_tuxmodule (const char *filename);
619 extern int register_tuxmodule (tcapi_template_t *tcapi);
620 extern tcapi_template_t * unregister_tuxmodule (char *vfs_name);
621 extern tcapi_template_t * get_first_usermodule (void);
622 extern int user_register_module (user_req_t *u_info);
623 extern int user_unregister_module (user_req_t *u_info);
624 extern void unregister_all_tuxmodules (void);
626 typedef struct exec_param_s {
630 unsigned int pipe_fds;
633 extern pid_t tux_exec_process (char *command, char **argv, char **envp, int pipe_fds, exec_param_t *param, int wait);
635 extern void start_external_cgi (tux_req_t *req);
636 extern tcapi_template_t extcgi_tcapi;
638 extern void queue_output_req (tux_req_t *req, threadinfo_t *ti);
639 extern void queue_userspace_req (tux_req_t *req, threadinfo_t *ti);
642 extern void __log_request (tux_req_t *req);
643 extern inline void log_request (tux_req_t *req)
649 extern int __connection_too_fast (tux_req_t *req);
651 #define connection_too_fast(req) \
654 if (unlikely(tux_max_output_bandwidth)) \
655 __ret = __connection_too_fast(req); \
659 extern void trunc_headers (tux_req_t *req);
660 extern int generic_send_file (tux_req_t *req, struct socket *sock, int cachemiss);
661 extern int tux_fetch_file (tux_req_t *req, int nonblock);
663 extern void postpone_request (tux_req_t *req);
664 extern int continue_request (int fd);
665 extern void tux_push_pending (struct sock *sk);
666 extern void zap_request (tux_req_t *req, int cachemiss);
667 extern int add_output_space_event (tux_req_t *req, struct socket *sock);
669 extern void reap_kids (void);
670 extern void unuse_frag (struct sk_buff *skb, skb_frag_t *frag);
671 extern skb_frag_t * build_dynbuf_frag (tux_req_t *req, unsigned int size);
672 extern int tux_permission (struct inode *inode);
673 extern void flush_all_signals (void);
675 #define D() Dprintk("{%s:%d}\n", __FILE__, __LINE__)
677 extern int nr_async_io_pending (void);
679 extern void __add_keepalive_timer (tux_req_t *req);
680 #define add_keepalive_timer(req) \
682 if (tux_keepalive_timeout) { \
683 Dprintk("add_keepalive_timer(%p).\n", (req)); \
684 __add_keepalive_timer(req); \
687 extern void __del_keepalive_timer (tux_req_t *req);
688 #define del_keepalive_timer(req) \
690 if (tux_keepalive_timeout) { \
691 Dprintk("del_keepalive_timer(%p).\n", (req)); \
692 __del_keepalive_timer(req); \
696 extern void del_output_timer (tux_req_t *req);
697 extern void output_timeout (tux_req_t *req);
699 extern void print_req (tux_req_t *req);
701 extern char tux_date [DATE_LEN];
704 extern int nr_async_io_pending (void);
705 extern void tux_exit (void);
706 extern char * get_abuf (tux_req_t *req, unsigned int max_size);
707 extern void send_abuf (tux_req_t *req, unsigned int size, unsigned long flags);
710 extern int idle_event (tux_req_t *req);
711 extern int output_space_event (tux_req_t *req);
712 extern cpumask_t tux_log_cpu_mask;
713 extern unsigned int tux_compression;
714 extern unsigned int tux_noid;
715 extern unsigned int tux_cgi_inherit_cpu;
716 extern unsigned int tux_zerocopy_header;
717 extern unsigned int tux_zerocopy_sendfile;
718 extern cpumask_t tux_cgi_cpu_mask;
719 extern tux_proto_t tux_proto_http;
720 extern tux_proto_t tux_proto_ftp;
721 extern unsigned int tux_all_userspace;
722 extern unsigned int tux_ignore_query;
723 extern unsigned int tux_redirect_logging;
724 extern unsigned int tux_referer_logging;
725 extern unsigned int tux_log_incomplete;
726 extern unsigned int tux_max_header_len;
727 extern unsigned int tux_cpu_offset;
728 extern unsigned int tux_ftp_login_message;
730 extern void drop_permissions (void);
731 extern int query_extcgi (tux_req_t *req);
732 extern int tux_chroot (char *dir);
734 extern void install_req_dentry (tux_req_t *req, struct dentry *dentry, struct vfsmount *mnt);
735 extern void release_req_dentry (tux_req_t *req);
736 extern void unidle_req (tux_req_t *req);
737 extern int nr_requests_used (void);
739 #define req_err(req) do { (req)->error = 1; Dprintk("request %p error at %s:%d.\n", req, __FILE__, __LINE__); } while (0)
741 #define enough_wspace(sk) (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
742 #define clear_keepalive(req) do { (req)->keep_alive = 0; Dprintk("keepalive cleared for req %p.\n", req); } while (0)
744 extern int print_all_requests (threadinfo_t *ti);
745 extern unsigned int tux_max_keepalives;
746 extern int time_unix2ls (time_t zulu, char *buf);
747 extern void last_mod_time(char * curr, const time_t t);
748 extern int mdtm_time(char * curr, const time_t t);
749 extern time_t parse_time(const char *str, const int str_len);
751 extern unsigned int nr_tux_threads;
752 extern threadinfo_t threadinfo[CONFIG_TUX_NUMTHREADS];
754 #define switch_docroot(req) do { if (((req)->docroot_dentry != current->fs->root) || ((req)->docroot_mnt != current->fs->rootmnt)) __switch_docroot(req); } while (0)
755 extern void __switch_docroot(tux_req_t *req);
756 extern void list_directory (tux_req_t *req, int cachemiss);
757 extern char * tux_print_path (tux_req_t *req, struct dentry *dentry, struct vfsmount *mnt, char *buf, unsigned int max_len);
759 extern unsigned int tux_http_dir_indexing;
761 int tux_gzip_compress (tux_req_t *req, unsigned char *data_in, unsigned char *data_out, __u32 *in_len, __u32 *out_len);
763 struct dentry * __tux_lookup (tux_req_t *req, const char *filename,
764 struct nameidata *base, struct vfsmount **mnt);
766 /* error codes for req->error */
767 #define TUX_ERROR_REDIRECT 1
768 #define TUX_ERROR_UNUSED 2
769 #define TUX_ERROR_CONN_CLOSE 3
770 #define TUX_ERROR_CONN_TIMEOUT 4
772 extern void __put_data_sock (tux_req_t *req);
774 static inline void put_data_sock (tux_req_t *req)
777 __put_data_sock(req);
780 #define socket_input(sock) \
781 (!skb_queue_empty(&(sock)->sk->sk_receive_queue) || \
782 !skb_queue_empty(&(sock)->sk->sk_error_queue))
784 #define tux_kmalloc(size) \
788 while (!(__ptr = kmalloc(size, GFP_KERNEL))) { \
789 if (net_ratelimit()) \
790 printk(KERN_WARNING "tux: OOM at %s:%d (%d bytes).\n", \
791 __FILE__, __LINE__, size); \
792 current->state = TASK_UNINTERRUPTIBLE; \
793 schedule_timeout(1); \
798 #define tux_close(fd) sys_close(fd)
800 extern int init_tux_request_slabs(void);
801 extern void free_tux_request_slabs(void);