2 * TUX - Integrated Application Protocols Layer and Object Cache
4 * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
6 * abuf.c: async buffer-sending
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 * get_abuf (tux_req_t *req, unsigned int max_size)
30 threadinfo_t *ti = req->ti;
36 if (req->abuf.page || req->abuf.buf || req->abuf.size)
39 if (max_size > PAGE_SIZE)
41 offset = ti->header_offset;
42 if (offset > PAGE_SIZE)
44 left = PAGE_SIZE - offset;
47 page = ti->header_cache;
48 if ((left < max_size) || !page) {
49 while (!(page = alloc_pages(GFP_KERNEL, 0))) {
51 printk(KERN_WARNING "tux: OOM in get_abuf()!\n");
52 current->state = TASK_UNINTERRUPTIBLE;
57 __free_page(ti->header_cache);
58 ti->header_cache = page;
59 ti->header_offset = 0;
62 buf = page_address(page) + offset;
66 req->abuf.page = page;
69 req->abuf.offset = offset;
71 get_page(req->abuf.page);
76 static void do_send_abuf (tux_req_t *req, int cachemiss);
78 void send_abuf (tux_req_t *req, unsigned int size, unsigned long flags)
80 threadinfo_t *ti = req->ti;
82 Dprintk("send_abuf(req: %p, sock: %p): %p(%p), size:%d, off:%d, flags:%08lx\n", req, req->sock, req->abuf.page, req->abuf.buf, size, req->abuf.offset, flags);
84 ti->header_offset += size;
85 if (ti->header_offset > PAGE_SIZE)
87 if (req->abuf.offset + req->abuf.size > PAGE_SIZE)
90 req->abuf.flags = flags | MSG_NOSIGNAL;
91 req->abuf.size = size;
93 add_tux_atom(req, do_send_abuf);
96 static void do_send_abuf (tux_req_t *req, int cachemiss)
100 if (req->magic != TUX_MAGIC)
104 tcp_sk(req->sock->sk)->nonagle = 2;
107 Dprintk("do_send_abuf(%p,%d): %p(%p), size:%d, off:%d, flags:%08lx\n",
109 req->abuf.page, req->abuf.buf, req->abuf.size,
110 req->abuf.offset, req->abuf.flags);
112 if (tux_zerocopy_header)
113 ret = tcp_sendpage(req->sock, req->abuf.page,
114 req->abuf.offset, req->abuf.size, req->abuf.flags);
117 oldmm = get_fs(); set_fs(KERNEL_DS);
118 ret = send_sync_buf(req, req->sock, req->abuf.buf,
119 req->abuf.size, req->abuf.flags);
124 Dprintk("do_send_abuf: ret: %d\n", ret);
129 if (ret != -EAGAIN) {
130 TDprintk("ret: %d, req->error = TUX_ERROR_CONN_CLOSE.\n", ret);
131 req->error = TUX_ERROR_CONN_CLOSE;
133 req->in_file.f_pos = 0;
134 __free_page(req->abuf.page);
135 memset(&req->abuf, 0, sizeof(req->abuf));
136 zap_request(req, cachemiss);
139 add_tux_atom(req, do_send_abuf);
140 if (add_output_space_event(req, req->sock)) {
147 req->abuf.buf += ret;
148 req->abuf.offset += ret;
149 req->abuf.size -= ret;
151 if ((int)req->abuf.size < 0)
153 if (req->abuf.size > 0)
156 Dprintk("DONE do_send_abuf: %p(%p), size:%d, off:%d, flags:%08lx\n",
157 req->abuf.page, req->abuf.buf, req->abuf.size,
158 req->abuf.offset, req->abuf.flags);
160 __free_page(req->abuf.page);
162 memset(&req->abuf, 0, sizeof(req->abuf));
164 add_req_to_workqueue(req);
167 void __send_async_message (tux_req_t *req, const char *message,
168 int status, unsigned int size, int push)
173 Dprintk("TUX: sending %d reply (%d bytes)!\n", status, size);
174 Dprintk("request %p, reply: %s\n", req, message);
177 buf = get_abuf(req, size);
178 memcpy(buf, message, size);
180 req->status = status;
181 flags = MSG_DONTWAIT;
184 send_abuf(req, size, flags);
185 add_req_to_workqueue(req);