Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / net / tux / output.c
1 /*
2  * TUX - Integrated Application Protocols Layer and Object Cache
3  *
4  * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
5  *
6  * output.c: Send data to clients
7  */
8
9 #include <net/tux.h>
10
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)
15  *      any later version.
16  *
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.
21  *
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.
25  *
26  ****************************************************************/
27
28 int send_sync_buf (tux_req_t *req, struct socket *sock, const char *buf, const size_t length, unsigned long flags)
29 {
30         struct msghdr msg;
31         struct iovec iov;
32         int len, written = 0, left = length;
33         struct tcp_sock *tp = tcp_sk(sock->sk);
34
35         tp->nonagle = 2;
36
37         msg.msg_name     = NULL;
38         msg.msg_namelen  = 0;
39         msg.msg_iov      = &iov;
40         msg.msg_iovlen   = 1;
41         msg.msg_control  = NULL;
42         msg.msg_controllen = 0;
43         msg.msg_flags    = flags | MSG_NOSIGNAL;
44 repeat_send:
45         msg.msg_iov->iov_len = left;
46         msg.msg_iov->iov_base = (char *) buf + written;
47
48         len = sock_sendmsg(sock, &msg, left);
49
50         Dprintk("sendmsg ret: %d, written: %d, left: %d.\n", len,written,left);
51         if ((len == -ERESTARTSYS) || (!(flags & MSG_DONTWAIT) &&
52                          (len == -EAGAIN))) {
53                 flush_all_signals();
54                 goto repeat_send;
55         }
56         if (len > 0) {
57                 written += len;
58                 left -= len;
59                 if (left)
60                         goto repeat_send;
61         }
62         if (len >= 0) {
63                 if (written != length)
64                         TUX_BUG();
65                 if (left)
66                         TUX_BUG();
67         }
68         if (req && (written > 0))
69                 req->bytes_sent += written;
70         Dprintk("sendmsg FINAL ret: %d, written: %d, left: %d.\n", len,written,left);
71         return written ? written : len;
72 }
73
74 unsigned int tux_zerocopy_sendfile = 1;
75
76 typedef struct sock_send_desc
77 {
78         struct socket *sock;
79         tux_req_t *req;
80 } sock_send_desc_t;
81
82 static int sock_send_actor (read_descriptor_t * desc, struct page *page,
83                                 unsigned long offset, unsigned long orig_size)
84 {
85         sock_send_desc_t *sock_desc = (sock_send_desc_t *)desc->arg.buf;
86         struct socket *sock = sock_desc->sock;
87         tux_req_t *req = sock_desc->req;
88         unsigned int flags;
89         ssize_t written;
90         char *buf = NULL;
91         unsigned int size;
92
93         flags = MSG_DONTWAIT | MSG_NOSIGNAL;
94         if (desc->count < orig_size)
95                 orig_size = desc->count;
96         if (desc->count > orig_size)
97                 flags |= MSG_MORE;
98         Dprintk("sock_send_actor(), page: %p, offset: %ld, orig_size: %ld, sock: %p, desc->count: %d, desc->written: %d, MSG_MORE: %d.\n", page, offset, orig_size, sock, desc->count, desc->written, flags & MSG_MORE);
99
100         if (req->content_gzipped >= 2) {
101                 unsigned int gzip_left;
102                 struct msghdr msg;
103                 struct iovec iov;
104                 mm_segment_t oldmm;
105                 char *kaddr = kmap(page);
106                 __u32 in_len, out_len;
107                 out_len = orig_size*101/100 + 12;
108                 buf = tux_kmalloc(out_len);
109                 in_len = orig_size;
110                 size = out_len;
111                 gzip_left = 0;
112 // 8b1f 0808 fdc4 3bd8 0300 79
113 buf[1] = 0x8b; buf[0] = 0x1f; buf[3] = 0x08; buf[2] = 0x08;
114 buf[5] = 0xfd; buf[4] = 0xc4; buf[7] = 0x3b; buf[6] = 0xd8;
115 buf[9] = 0x03; buf[8] = 0x00; buf[10] = 0x79;
116                 size += 11;
117                 Dprintk("pre-compress: in_len: %d, out_len: %d, gzip_left: %d, uncompressed size: %d.\n", in_len, out_len, gzip_left, size);
118                 gzip_left = tux_gzip_compress(req, kaddr, buf+11, &in_len, &out_len);
119                 size -= out_len;
120  buf[11] = 0x79; buf[12] = 0x00;
121
122                 Dprintk("post-compress: in_len: %d, out_len: %d, gzip_left: %d, compressed size: %d.\n", in_len, out_len, gzip_left, size);
123                 kunmap(page);
124                 msg.msg_name = NULL;
125                 msg.msg_namelen = 0;
126                 msg.msg_iov = &iov;
127                 msg.msg_iovlen = 1;
128                 msg.msg_control = NULL;
129                 msg.msg_controllen = 0;
130                 flags &= ~MSG_DONTWAIT;
131                 msg.msg_flags = flags;
132                 iov.iov_base = buf;
133                 iov.iov_len = size;
134
135                 oldmm = get_fs(); set_fs(KERNEL_DS);
136                 written = sock_sendmsg(sock, &msg, size);
137                 set_fs(oldmm);
138
139                 Dprintk("buf: %p, offset: %ld, size: %d, written: %d.\n", buf, offset, size, written);
140                 if (written == size)
141                         written = orig_size;
142                 else
143                         written = size;
144
145         } else {
146                 size = orig_size;
147                 if (tux_zerocopy_sendfile && sock->ops->sendpage &&
148                     (sock->sk->sk_route_caps&NETIF_F_SG)) {
149                         written = sock->ops->sendpage(sock, page, offset, size, flags);
150                 } else {
151                         struct msghdr msg;
152                         struct iovec iov;
153                         char *kaddr;
154                         mm_segment_t oldmm;
155
156                         if (offset+size > PAGE_SIZE)
157                                 return -EFAULT;
158
159                         kaddr = kmap(page);
160
161                         msg.msg_name = NULL;
162                         msg.msg_namelen = 0;
163                         msg.msg_iov = &iov;
164                         msg.msg_iovlen = 1;
165                         msg.msg_control = NULL;
166                         msg.msg_controllen = 0;
167                         msg.msg_flags = flags;
168                         iov.iov_base = kaddr + offset;
169                         iov.iov_len = size;
170
171                         oldmm = get_fs(); set_fs(KERNEL_DS);
172                         written = sock_sendmsg(sock, &msg, size);
173                         set_fs(oldmm);
174
175                         Dprintk("kaddr: %p, offset: %ld, size: %d, written: %d.\n", kaddr, offset, size, written);
176                         kunmap(page);
177                 }
178         }
179         if (written < 0) {
180                 desc->error = written;
181                 written = 0;
182         }
183         Dprintk("desc->count: %d, desc->written: %d, written: %d.\n", desc->count, desc->written, written);
184         desc->count -= written;
185         if ((int)desc->count < 0)
186                 TUX_BUG();
187         desc->written += written;
188
189         if (buf)
190                 kfree(buf);
191
192         return written;
193 }
194
195 /*
196  * Return 1 if the output space condition went away
197  * before adding the handler.
198  */
199 int add_output_space_event (tux_req_t *req, struct socket *sock)
200 {
201         struct sock *sk = sock->sk;
202         /*
203          * blocked due to socket IO?
204          */
205         spin_lock_irq(&req->ti->work_lock);
206         add_keepalive_timer(req);
207         if (test_and_set_bit(0,&req->wait_output_space))
208                 TUX_BUG();
209         INC_STAT(nr_output_space_pending);
210
211         if ((sk->sk_state == TCP_ESTABLISHED) && enough_wspace(sk)) {
212                 if (test_and_clear_bit(0, &req->wait_output_space)) {
213                         DEC_STAT(nr_output_space_pending);
214                         del_keepalive_timer(req);
215                         spin_unlock_irq(&req->ti->work_lock);
216                         return 1;
217                 }
218         }
219         spin_unlock_irq(&req->ti->work_lock);
220
221         return 0;
222 }
223
224 #define SEND_BLOCKSIZE (164*1024)
225
226 int generic_send_file (tux_req_t *req, struct socket *sock, int cachemiss)
227 {
228         sock_send_desc_t sock_desc;
229         int len, want, nonblock = !cachemiss;
230         struct tcp_sock *tp = tcp_sk(sock->sk);
231
232         tp->nonagle = 2;
233
234         sock_desc.sock = sock;
235         sock_desc.req = req;
236
237 repeat:
238         Dprintk("generic_send_file(%p,%d,%p) called, f_pos: %Ld, output_len: %Ld.\n", req, nonblock, sock, req->in_file->f_pos, req->output_len);
239
240         if (req->proto->check_req_err(req, cachemiss))
241                 return -1;
242         if (connection_too_fast(req) == 2) {
243                 len = -5;
244                 goto out;
245         }
246         if (req->total_file_len < req->in_file->f_pos)
247                 TUX_BUG();
248
249         req->desc.written = 0;
250         /*
251          * Careful, output_len can be 64-bit, while 'want' can be 32-bit.
252          */
253         if (req->output_len > SEND_BLOCKSIZE)
254                 want = SEND_BLOCKSIZE;
255         else
256                 want = req->output_len;
257         req->desc.count = want;
258         req->desc.arg.buf = (char *) &sock_desc;
259         req->desc.error = 0;
260         Dprintk("sendfile(), desc.count: %d.\n", req->desc.count);
261         do_generic_file_read(req->in_file, &req->in_file->f_pos, &req->desc, sock_send_actor, nonblock);
262         if (req->desc.written > 0) {
263                 req->bytes_sent += req->desc.written;
264                 req->output_len -= req->desc.written;
265         }
266         if (!nonblock && (req->desc.error == -EWOULDBLOCKIO))
267                 TUX_BUG();
268         Dprintk("sendfile() wrote: %d bytes.\n", req->desc.written);
269         if (req->output_len && !req->desc.written && !req->desc.error) {
270 #ifdef CONFIG_TUX_DEBUG
271                 req->bytes_expected = 0;
272 #endif
273                 req->in_file->f_pos = 0;
274                 req->error = TUX_ERROR_CONN_CLOSE;
275                 zap_request(req, cachemiss);
276                 return -1;
277         }
278
279         switch (req->desc.error) {
280
281         case -EWOULDBLOCKIO:
282                 len = -3;
283                 break;
284         case -EAGAIN:
285 no_write_space:
286                 Dprintk("sk->wmem_queued: %d, sk->sndbuf: %d.\n",
287                         sock->sk->sk_wmem_queued, sock->sk->sk_sndbuf);
288                 len = -4;
289                 break;
290         default:
291                 len = req->desc.written;
292 #ifdef CONFIG_TUX_DEBUG
293                 if (req->desc.error)
294                         TDprintk("TUX: sendfile() returned error %d (signals pending: %08lx)!\n", req->desc.error, current->pending.signal.sig[0]);
295 #endif
296                 if (!req->desc.error) {
297                         if (req->output_len < 0)
298                                 BUG();
299                         if (req->output_len) {
300                                 if (test_bit(SOCK_NOSPACE, &sock->flags))
301                                         goto no_write_space;
302                                 goto repeat;
303                         }
304                 }
305 #ifdef CONFIG_TUX_DEBUG
306                 if (req->desc.written != want)
307                         TDprintk("TUX: sendfile() wrote %d bytes, wanted %d! (pos %Ld) (signals pending: %08lx).\n", req->desc.written, want, req->in_file->f_pos, current->pending.signal.sig[0]);
308                 else
309                         Dprintk("TUX: sendfile() FINISHED for req %p, wrote %d bytes.\n", req, req->desc.written);
310                 req->bytes_expected = 0;
311 #endif
312                 break;
313         }
314
315 out:
316         Dprintk("sendfile() wrote %d bytes.\n", len);
317
318         return len;
319 }
320
321 static int file_fetch_actor (read_descriptor_t * desc, struct page *page,
322                                 unsigned long offset, unsigned long size)
323 {
324         if (desc->count < size)
325                 size = desc->count;
326
327         desc->count -= size;
328         desc->written += size;
329
330         return size;
331 }
332
333 int tux_fetch_file (tux_req_t *req, int nonblock)
334 {
335         int len;
336
337         req->desc.written = 0;
338         req->desc.count = req->output_len;
339         req->desc.arg.buf = NULL;
340         req->desc.error = 0;
341
342         do_generic_file_read(req->in_file, &req->in_file->f_pos, &req->desc,
343                                         file_fetch_actor, nonblock);
344         if (nonblock && (req->desc.error == -EWOULDBLOCKIO))
345                 return 1;
346         len = req->desc.written;
347         if (req->desc.error)
348                 Dprintk("fetchfile() returned %d error!\n", req->desc.error);
349         Dprintk("fetchfile() fetched %d bytes.\n", len);
350         return 0;
351 }
352