2 * TUX - Integrated Application Protocols Layer and Object Cache
4 * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
6 * output.c: Send data to clients
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 int send_sync_buf (tux_req_t *req, struct socket *sock, const char *buf, const size_t length, unsigned long flags)
32 int len, written = 0, left = length;
33 struct tcp_opt *tp = tcp_sk(sock->sk);
41 msg.msg_control = NULL;
42 msg.msg_controllen = 0;
43 msg.msg_flags = flags | MSG_NOSIGNAL;
45 msg.msg_iov->iov_len = left;
46 msg.msg_iov->iov_base = (char *) buf + written;
48 len = sock_sendmsg(sock, &msg, left);
50 Dprintk("sendmsg ret: %d, written: %d, left: %d.\n", len,written,left);
51 if ((len == -ERESTARTSYS) || (!(flags & MSG_DONTWAIT) &&
63 if (written != length)
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;
74 unsigned int tux_zerocopy_sendfile = 1;
76 typedef struct sock_send_desc
82 static int sock_send_actor (read_descriptor_t * desc, struct page *page,
83 unsigned long offset, unsigned long orig_size)
85 sock_send_desc_t *sock_desc = (sock_send_desc_t *)desc->buf;
86 struct socket *sock = sock_desc->sock;
87 tux_req_t *req = sock_desc->req;
93 flags = MSG_DONTWAIT | MSG_NOSIGNAL;
94 if (desc->count < orig_size)
95 orig_size = desc->count;
96 if (desc->count > orig_size)
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);
100 if (req->content_gzipped >= 2) {
101 unsigned int gzip_left;
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);
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;
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);
120 buf[11] = 0x79; buf[12] = 0x00;
122 Dprintk("post-compress: in_len: %d, out_len: %d, gzip_left: %d, compressed size: %d.\n", in_len, out_len, gzip_left, size);
128 msg.msg_control = NULL;
129 msg.msg_controllen = 0;
130 flags &= ~MSG_DONTWAIT;
131 msg.msg_flags = flags;
135 oldmm = get_fs(); set_fs(KERNEL_DS);
136 written = sock_sendmsg(sock, &msg, size);
139 Dprintk("buf: %p, offset: %ld, size: %d, written: %d.\n", buf, offset, size, written);
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);
156 if (offset+size > PAGE_SIZE)
165 msg.msg_control = NULL;
166 msg.msg_controllen = 0;
167 msg.msg_flags = flags;
168 iov.iov_base = kaddr + offset;
171 oldmm = get_fs(); set_fs(KERNEL_DS);
172 written = sock_sendmsg(sock, &msg, size);
175 Dprintk("kaddr: %p, offset: %ld, size: %d, written: %d.\n", kaddr, offset, size, written);
180 desc->error = written;
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)
187 desc->written += written;
196 * Return 1 if the output space condition went away
197 * before adding the handler.
199 int add_output_space_event (tux_req_t *req, struct socket *sock)
201 struct sock *sk = sock->sk;
203 * blocked due to socket IO?
205 spin_lock_irq(&req->ti->work_lock);
206 add_keepalive_timer(req);
207 if (test_and_set_bit(0,&req->wait_output_space))
209 INC_STAT(nr_output_space_pending);
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);
219 spin_unlock_irq(&req->ti->work_lock);
224 #define SEND_BLOCKSIZE (164*1024)
226 int generic_send_file (tux_req_t *req, struct socket *sock, int cachemiss)
228 sock_send_desc_t sock_desc;
229 int len, want, nonblock = !cachemiss;
230 struct tcp_opt *tp = tcp_sk(sock->sk);
234 sock_desc.sock = sock;
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);
240 if (req->proto->check_req_err(req, cachemiss))
242 if (connection_too_fast(req) == 2) {
246 if (req->total_file_len < req->in_file.f_pos)
249 req->desc.written = 0;
251 * Careful, output_len can be 64-bit, while 'want' can be 32-bit.
253 if (req->output_len > SEND_BLOCKSIZE)
254 want = SEND_BLOCKSIZE;
256 want = req->output_len;
257 req->desc.count = want;
258 req->desc.buf = (char *) &sock_desc;
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;
266 if (!nonblock && (req->desc.error == -EWOULDBLOCKIO))
268 Dprintk("sendfile() wrote: %d bytes.\n", req->desc.written);
269 if (req->output_len && !req->desc.written && !req->desc.error) {
271 req->bytes_expected = 0;
273 req->in_file.f_pos = 0;
274 req->error = TUX_ERROR_CONN_CLOSE;
275 zap_request(req, cachemiss);
279 switch (req->desc.error) {
286 Dprintk("sk->wmem_queued: %d, sk->sndbuf: %d.\n",
287 sock->sk->sk_wmem_queued, sock->sk->sk_sndbuf);
291 len = req->desc.written;
294 TDprintk("TUX: sendfile() returned error %d (signals pending: %08lx)!\n", req->desc.error, current->pending.signal.sig[0]);
296 if (!req->desc.error) {
297 if (req->output_len < 0)
299 if (req->output_len) {
300 if (test_bit(SOCK_NOSPACE, &sock->flags))
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]);
309 Dprintk("TUX: sendfile() FINISHED for req %p, wrote %d bytes.\n", req, req->desc.written);
310 req->bytes_expected = 0;
316 Dprintk("sendfile() wrote %d bytes.\n", len);
321 static int file_fetch_actor (read_descriptor_t * desc, struct page *page,
322 unsigned long offset, unsigned long size)
324 if (desc->count < size)
328 desc->written += size;
333 int tux_fetch_file (tux_req_t *req, int nonblock)
337 req->desc.written = 0;
338 req->desc.count = req->output_len;
339 req->desc.buf = NULL;
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))
346 len = req->desc.written;
348 Dprintk("fetchfile() returned %d error!\n", req->desc.error);
349 Dprintk("fetchfile() fetched %d bytes.\n", len);