]>
Commit | Line | Data |
---|---|---|
b224ea98 | 1 | |
95e36d02 | 2 | |
30a4f2a8 | 3 | /* |
0a5bc521 | 4 | * $Id: disk.cc,v 1.123 1998/08/12 16:15:23 wessels Exp $ |
30a4f2a8 | 5 | * |
6 | * DEBUG: section 6 Disk I/O Routines | |
7 | * AUTHOR: Harvest Derived | |
8 | * | |
42c04c16 | 9 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
e25c139f | 10 | * ---------------------------------------------------------- |
30a4f2a8 | 11 | * |
12 | * Squid is the result of efforts by numerous individuals from the | |
13 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 14 | * National Laboratory for Applied Network Research and funded by the |
15 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
16 | * Duane Wessels and the University of California San Diego. Please | |
17 | * see the COPYRIGHT file for full details. Squid incorporates | |
18 | * software developed and/or copyrighted by other sources. Please see | |
19 | * the CREDITS file for full details. | |
30a4f2a8 | 20 | * |
21 | * This program is free software; you can redistribute it and/or modify | |
22 | * it under the terms of the GNU General Public License as published by | |
23 | * the Free Software Foundation; either version 2 of the License, or | |
24 | * (at your option) any later version. | |
25 | * | |
26 | * This program is distributed in the hope that it will be useful, | |
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
29 | * GNU General Public License for more details. | |
30 | * | |
31 | * You should have received a copy of the GNU General Public License | |
32 | * along with this program; if not, write to the Free Software | |
cbdec147 | 33 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 34 | * |
30a4f2a8 | 35 | */ |
ed43818f | 36 | |
44a47c6e | 37 | #include "squid.h" |
090089c4 | 38 | |
39 | #define DISK_LINE_LEN 1024 | |
090089c4 | 40 | |
0a0bf5db | 41 | typedef struct disk_ctrl_t { |
42 | int fd; | |
43 | void *data; | |
44 | } disk_ctrl_t; | |
45 | ||
46 | ||
47 | typedef struct open_ctrl_t { | |
f17936ab | 48 | FOCB *callback; |
0a0bf5db | 49 | void *callback_data; |
50 | char *path; | |
51 | } open_ctrl_t; | |
52 | ||
de866d20 | 53 | static AIOCB diskHandleWriteComplete; |
54 | static AIOCB diskHandleReadComplete; | |
95d15928 | 55 | static PF diskHandleRead; |
56 | static PF diskHandleWrite; | |
f5b8bbc4 | 57 | static void file_open_complete(void *, int, int); |
24382924 | 58 | |
04cece06 | 59 | void |
0673c0ba | 60 | disk_init(void) |
090089c4 | 61 | { |
04cece06 | 62 | #if USE_ASYNC_IO |
63 | aioClose(dup(0)); | |
64 | #endif | |
090089c4 | 65 | } |
66 | ||
67 | /* Open a disk file. Return a file descriptor */ | |
684c2720 | 68 | int |
6cf028ab | 69 | file_open(const char *path, int mode, FOCB * callback, void *callback_data, void *tag) |
090089c4 | 70 | { |
090089c4 | 71 | int fd; |
0a0bf5db | 72 | open_ctrl_t *ctrlp; |
73 | ||
74 | ctrlp = xmalloc(sizeof(open_ctrl_t)); | |
75 | ctrlp->path = xstrdup(path); | |
76 | ctrlp->callback = callback; | |
77 | ctrlp->callback_data = callback_data; | |
090089c4 | 78 | |
b59c7120 | 79 | if (mode & O_WRONLY) |
80 | mode |= O_APPEND; | |
4f92c80c | 81 | mode |= SQUID_NONBLOCK; |
b59c7120 | 82 | |
090089c4 | 83 | /* Open file */ |
0a0bf5db | 84 | #if USE_ASYNC_IO |
f17936ab | 85 | if (callback != NULL) { |
6cf028ab | 86 | aioOpen(path, mode, 0644, file_open_complete, ctrlp, tag); |
9e4ad609 | 87 | return DISK_OK; |
0a0bf5db | 88 | } |
f17936ab | 89 | #endif |
0a0bf5db | 90 | fd = open(path, mode, 0644); |
91 | file_open_complete(ctrlp, fd, errno); | |
92 | if (fd < 0) | |
93 | return DISK_ERROR; | |
94 | return fd; | |
0a0bf5db | 95 | } |
96 | ||
97 | ||
98 | static void | |
95d15928 | 99 | file_open_complete(void *data, int fd, int errcode) |
0a0bf5db | 100 | { |
101 | open_ctrl_t *ctrlp = (open_ctrl_t *) data; | |
6cf028ab | 102 | |
0e473d70 | 103 | if (fd == -2 && errcode == -2) { /* Cancelled - clean up */ |
6cf028ab | 104 | if (ctrlp->callback) |
105 | (ctrlp->callback) (ctrlp->callback_data, fd, errcode); | |
106 | xfree(ctrlp->path); | |
107 | xfree(ctrlp); | |
108 | return; | |
109 | } | |
0a0bf5db | 110 | if (fd < 0) { |
111 | errno = errcode; | |
af95908a | 112 | debug(50, 3) ("file_open: error opening file %s: %s\n", ctrlp->path, |
0a0bf5db | 113 | xstrerror()); |
114 | if (ctrlp->callback) | |
6cf028ab | 115 | (ctrlp->callback) (ctrlp->callback_data, DISK_ERROR, errcode); |
0a0bf5db | 116 | xfree(ctrlp->path); |
117 | xfree(ctrlp); | |
118 | return; | |
090089c4 | 119 | } |
365e5b34 | 120 | debug(6, 5) ("file_open: FD %d\n", fd); |
3ca60c86 | 121 | commSetCloseOnExec(fd); |
5c5783a2 | 122 | fd_open(fd, FD_FILE, ctrlp->path); |
0a0bf5db | 123 | if (ctrlp->callback) |
6cf028ab | 124 | (ctrlp->callback) (ctrlp->callback_data, fd, errcode); |
0a0bf5db | 125 | xfree(ctrlp->path); |
126 | xfree(ctrlp); | |
127 | } | |
128 | ||
090089c4 | 129 | /* close a disk file. */ |
95d15928 | 130 | void |
b8d8561b | 131 | file_close(int fd) |
090089c4 | 132 | { |
76f87348 | 133 | fde *F = &fd_table[fd]; |
25354045 | 134 | #if USE_ASYNC_IO |
0e473d70 | 135 | if (fd < 0) { |
6cf028ab | 136 | debug(6, 0) ("file_close: FD less than zero: %d\n", fd); |
137 | return; | |
138 | } | |
25354045 | 139 | #else |
140 | assert(fd >= 0); | |
141 | #endif | |
76f87348 | 142 | assert(F->open); |
0cd30ba5 | 143 | if (F->flags.write_daemon) { |
144 | F->flags.close_request = 1; | |
66979cec | 145 | debug(6, 2) ("file_close: FD %d, delaying close\n", fd); |
95d15928 | 146 | return; |
fb247d78 | 147 | } |
0a0bf5db | 148 | #if USE_ASYNC_IO |
95d15928 | 149 | aioClose(fd); |
0a0bf5db | 150 | #else |
42f99d0d | 151 | #if CALL_FSYNC_BEFORE_CLOSE |
152 | fsync(fd); | |
153 | #endif | |
95d15928 | 154 | close(fd); |
0a0bf5db | 155 | #endif |
0cd30ba5 | 156 | debug(6, F->flags.close_request ? 2 : 5) |
5ac0b6e7 | 157 | ("file_close: FD %d, really closing\n", fd); |
6cf028ab | 158 | fd_close(fd); |
090089c4 | 159 | } |
160 | ||
090089c4 | 161 | |
162 | /* write handler */ | |
582b6456 | 163 | static void |
79d39a72 | 164 | diskHandleWrite(int fd, void *notused) |
090089c4 | 165 | { |
4a86108c | 166 | int len = 0; |
0a0bf5db | 167 | disk_ctrl_t *ctrlp; |
168 | dwrite_q *q = NULL; | |
169 | dwrite_q *wq = NULL; | |
76f87348 | 170 | fde *F = &fd_table[fd]; |
171 | struct _fde_disk *fdd = &F->disk; | |
de866d20 | 172 | if (!fdd->write_q) |
582b6456 | 173 | return; |
ba7b771e | 174 | debug(6, 3) ("diskHandleWrite: FD %d\n", fd); |
0a0bf5db | 175 | /* We need to combine subsequent write requests after the first */ |
eb139d08 | 176 | /* But only if we don't need to seek() in between them, ugh! */ |
20f92343 | 177 | /* XXX This currently ignores any seeks (file_offset) */ |
de866d20 | 178 | if (fdd->write_q->next != NULL && fdd->write_q->next->next != NULL) { |
179 | len = 0; | |
180 | for (q = fdd->write_q->next; q != NULL; q = q->next) | |
d377699f | 181 | len += q->len - q->buf_offset; |
0a0bf5db | 182 | wq = xcalloc(1, sizeof(dwrite_q)); |
183 | wq->buf = xmalloc(len); | |
184 | wq->len = 0; | |
d377699f | 185 | wq->buf_offset = 0; |
0a0bf5db | 186 | wq->next = NULL; |
ed7f0b6a | 187 | wq->free_func = xfree; |
0a0bf5db | 188 | do { |
de866d20 | 189 | q = fdd->write_q->next; |
d377699f | 190 | len = q->len - q->buf_offset; |
191 | xmemcpy(wq->buf + wq->len, q->buf + q->buf_offset, len); | |
0a0bf5db | 192 | wq->len += len; |
de866d20 | 193 | fdd->write_q->next = q->next; |
ed7f0b6a | 194 | if (q->free_func) |
195 | (q->free_func) (q->buf); | |
0a0bf5db | 196 | safe_free(q); |
de866d20 | 197 | } while (fdd->write_q->next != NULL); |
198 | fdd->write_q_tail = wq; | |
199 | fdd->write_q->next = wq; | |
0a0bf5db | 200 | } |
201 | ctrlp = xcalloc(1, sizeof(disk_ctrl_t)); | |
202 | ctrlp->fd = fd; | |
f0027316 | 203 | #if USE_ASYNC_IO |
204 | ctrlp->data = fdd->write_q; | |
205 | #endif | |
8350fe9b | 206 | assert(fdd->write_q != NULL); |
d377699f | 207 | assert(fdd->write_q->len > fdd->write_q->buf_offset); |
0a0bf5db | 208 | #if USE_ASYNC_IO |
209 | aioWrite(fd, | |
5999b776 | 210 | -1, /* seek offset, -1 == append */ |
d377699f | 211 | fdd->write_q->buf + fdd->write_q->buf_offset, |
212 | fdd->write_q->len - fdd->write_q->buf_offset, | |
0a0bf5db | 213 | diskHandleWriteComplete, |
cd1fb0eb | 214 | ctrlp); |
0a0bf5db | 215 | #else |
ba7b771e | 216 | debug(6, 3) ("diskHandleWrite: FD %d writing %d bytes\n", |
5f6ac48b | 217 | fd, (int) (fdd->write_q->len - fdd->write_q->buf_offset)); |
0a0bf5db | 218 | len = write(fd, |
d377699f | 219 | fdd->write_q->buf + fdd->write_q->buf_offset, |
220 | fdd->write_q->len - fdd->write_q->buf_offset); | |
582b6456 | 221 | diskHandleWriteComplete(ctrlp, len, errno); |
0a0bf5db | 222 | #endif |
223 | } | |
224 | ||
de866d20 | 225 | static void |
b69f7771 | 226 | diskHandleWriteComplete(void *data, int len, int errcode) |
0a0bf5db | 227 | { |
228 | disk_ctrl_t *ctrlp = data; | |
0a0bf5db | 229 | int fd = ctrlp->fd; |
76f87348 | 230 | fde *F = &fd_table[fd]; |
231 | struct _fde_disk *fdd = &F->disk; | |
de866d20 | 232 | dwrite_q *q = fdd->write_q; |
233 | int status = DISK_OK; | |
ba7b771e | 234 | int do_callback; |
68c21f71 | 235 | int do_close; |
0a0bf5db | 236 | errno = errcode; |
ba7b771e | 237 | debug(6, 3) ("diskHandleWriteComplete: FD %d len = %d\n", fd, len); |
f0027316 | 238 | #if USE_ASYNC_IO |
239 | /* | |
240 | * From: "Michael O'Reilly" <michael@metal.iinet.net.au> | |
241 | * Date: 24 Feb 1998 15:12:06 +0800 | |
242 | * | |
243 | * A small patch to improve the AIO sanity. the patch below makes sure | |
244 | * the write request really does match the data passed back from the | |
245 | * async IO call. note that I haven't actually rebooted with this | |
246 | * patch yet, so 'provisional' is an understatement. | |
247 | */ | |
248 | if (q && q != ctrlp->data) { | |
249 | dwrite_q *p = ctrlp->data; | |
250 | debug(50, 0) ("KARMA: q != data (%p, %p)\n", q, p); | |
251 | debug(50, 0) ("KARMA: (%d, %d, %d FD %d)\n", | |
252 | q->buf_offset, q->len, len, fd); | |
253 | debug(50, 0) ("KARMA: desc %s, type %d, open %d, flags 0x%x\n", | |
254 | F->desc, F->type, F->open, F->flags); | |
255 | debug(50, 0) ("KARMA: (%d, %d)\n", p->buf_offset, p->len); | |
256 | len = -1; | |
257 | errcode = EFAULT; | |
258 | } | |
259 | #endif | |
0a0bf5db | 260 | safe_free(data); |
de866d20 | 261 | if (q == NULL) /* Someone aborted then write completed */ |
262 | return; | |
6cf028ab | 263 | |
0e473d70 | 264 | if (len == -2 && errcode == -2) { /* Write cancelled - cleanup */ |
6cf028ab | 265 | do { |
266 | fdd->write_q = q->next; | |
ed7f0b6a | 267 | if (q->free_func) |
268 | (q->free_func) (q->buf); | |
6cf028ab | 269 | safe_free(q); |
270 | } while ((q = fdd->write_q)); | |
271 | return; | |
272 | } | |
6cf028ab | 273 | fd_bytes(fd, len, FD_WRITE); |
0a0bf5db | 274 | if (len < 0) { |
b224ea98 | 275 | if (!ignoreErrno(errno)) { |
de866d20 | 276 | status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; |
a3d5953d | 277 | debug(50, 1) ("diskHandleWrite: FD %d: disk write error: %s\n", |
0c77d853 | 278 | fd, xstrerror()); |
25354045 | 279 | /* |
280 | * If there is no write callback, then this file is | |
281 | * most likely something important like a log file, or | |
282 | * an interprocess pipe. Its not a swapfile. We feel | |
283 | * that a write failure on a log file is rather important, | |
284 | * and Squid doesn't otherwise deal with this condition. | |
285 | * So to get the administrators attention, we exit with | |
286 | * a fatal message. | |
287 | */ | |
288 | if (fdd->wrt_handle == NULL) | |
289 | fatal("Write failure -- check your disk space and cache.log"); | |
290 | /* | |
291 | * If there is a write failure, then we notify the | |
292 | * upper layer via the callback, at the end of this | |
293 | * function. Meanwhile, flush all pending buffers | |
294 | * here. Let the upper layer decide how to handle the | |
295 | * failure. This will prevent experiencing multiple, | |
296 | * repeated write failures for the same FD because of | |
297 | * the queued data. | |
298 | */ | |
299 | do { | |
300 | fdd->write_q = q->next; | |
301 | if (q->free_func) | |
302 | (q->free_func) (q->buf); | |
303 | safe_free(q); | |
304 | } while ((q = fdd->write_q)); | |
0c77d853 | 305 | } |
de866d20 | 306 | len = 0; |
0a0bf5db | 307 | } |
8350fe9b | 308 | if (q != NULL) { |
309 | /* q might become NULL from write failure above */ | |
d377699f | 310 | q->buf_offset += len; |
6cf028ab | 311 | if (q->buf_offset > q->len) |
312 | debug(50, 1) ("diskHandleWriteComplete: q->buf_offset > q->len (%p,%d, %d, %d FD %d)\n", | |
5f6ac48b | 313 | q, (int) q->buf_offset, q->len, len, fd); |
d377699f | 314 | assert(q->buf_offset <= q->len); |
315 | if (q->buf_offset == q->len) { | |
56878878 | 316 | /* complete write */ |
317 | fdd->write_q = q->next; | |
ed7f0b6a | 318 | if (q->free_func) |
319 | (q->free_func) (q->buf); | |
56878878 | 320 | safe_free(q); |
321 | } | |
090089c4 | 322 | } |
de866d20 | 323 | if (fdd->write_q == NULL) { |
324 | /* no more data */ | |
325 | fdd->write_q_tail = NULL; | |
0cd30ba5 | 326 | F->flags.write_daemon = 0; |
de866d20 | 327 | } else { |
0a0bf5db | 328 | /* another block is queued */ |
25354045 | 329 | cbdataLock(fdd->wrt_handle_data); |
de866d20 | 330 | commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0); |
0cd30ba5 | 331 | F->flags.write_daemon = 1; |
4a86108c | 332 | } |
0cd30ba5 | 333 | do_close = F->flags.close_request; |
25354045 | 334 | if (fdd->wrt_handle) { |
ba7b771e | 335 | if (fdd->wrt_handle_data == NULL) |
336 | do_callback = 1; | |
337 | else if (cbdataValid(fdd->wrt_handle_data)) | |
338 | do_callback = 1; | |
339 | else | |
340 | do_callback = 0; | |
25354045 | 341 | if (fdd->wrt_handle_data != NULL) |
342 | cbdataUnlock(fdd->wrt_handle_data); | |
26720a7c | 343 | if (do_callback) { |
ba7b771e | 344 | fdd->wrt_handle(fd, status, len, fdd->wrt_handle_data); |
26720a7c | 345 | /* |
346 | * NOTE, this callback can close the FD, so we must | |
347 | * not touch 'F', 'fdd', etc. after this. | |
348 | */ | |
349 | return; | |
350 | } | |
25354045 | 351 | } |
68c21f71 | 352 | if (do_close) |
b59c7120 | 353 | file_close(fd); |
090089c4 | 354 | } |
355 | ||
356 | ||
090089c4 | 357 | /* write block to a file */ |
358 | /* write back queue. Only one writer at a time. */ | |
359 | /* call a handle when writing is complete. */ | |
e3ef2b09 | 360 | void |
3ebcfaa1 | 361 | file_write(int fd, |
d377699f | 362 | off_t file_offset, |
5830cdb3 | 363 | void *ptr_to_buf, |
684c2720 | 364 | int len, |
d89d1fb6 | 365 | DWCB handle, |
684c2720 | 366 | void *handle_data, |
9e4ad609 | 367 | FREE * free_func) |
090089c4 | 368 | { |
c6ac7aae | 369 | dwrite_q *wq = NULL; |
48cc3fcf | 370 | fde *F = &fd_table[fd]; |
371 | assert(fd >= 0); | |
372 | assert(F->open); | |
090089c4 | 373 | /* if we got here. Caller is eligible to write. */ |
30a4f2a8 | 374 | wq = xcalloc(1, sizeof(dwrite_q)); |
d377699f | 375 | wq->file_offset = file_offset; |
090089c4 | 376 | wq->buf = ptr_to_buf; |
090089c4 | 377 | wq->len = len; |
d377699f | 378 | wq->buf_offset = 0; |
090089c4 | 379 | wq->next = NULL; |
ed7f0b6a | 380 | wq->free_func = free_func; |
76f87348 | 381 | F->disk.wrt_handle = handle; |
382 | F->disk.wrt_handle_data = handle_data; | |
090089c4 | 383 | /* add to queue */ |
48cc3fcf | 384 | if (F->disk.write_q == NULL) { |
090089c4 | 385 | /* empty queue */ |
76f87348 | 386 | F->disk.write_q = F->disk.write_q_tail = wq; |
090089c4 | 387 | } else { |
76f87348 | 388 | F->disk.write_q_tail->next = wq; |
389 | F->disk.write_q_tail = wq; | |
090089c4 | 390 | } |
0cd30ba5 | 391 | if (!F->flags.write_daemon) { |
25354045 | 392 | cbdataLock(F->disk.wrt_handle_data); |
0a0bf5db | 393 | #if USE_ASYNC_IO |
95d15928 | 394 | diskHandleWrite(fd, NULL); |
0a0bf5db | 395 | #else |
95d15928 | 396 | commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0); |
0a0bf5db | 397 | #endif |
0cd30ba5 | 398 | F->flags.write_daemon = 1; |
429fdbec | 399 | } |
090089c4 | 400 | } |
401 | ||
137ee196 | 402 | /* a wrapper around file_write to allow for MemBuf to be file_written in a snap */ |
403 | void | |
404 | file_write_mbuf(int fd, off_t off, MemBuf mb, DWCB * handler, void *handler_data) | |
405 | { | |
406 | file_write(fd, off, mb.buf, mb.size, handler, handler_data, memBufFreeFunc(&mb)); | |
407 | } | |
090089c4 | 408 | |
409 | /* Read from FD */ | |
582b6456 | 410 | static void |
411 | diskHandleRead(int fd, void *data) | |
090089c4 | 412 | { |
582b6456 | 413 | dread_ctrl *ctrl_dat = data; |
606bd3b5 | 414 | #if !USE_ASYNC_IO |
edd2eb63 | 415 | fde *F = &fd_table[fd]; |
090089c4 | 416 | int len; |
606bd3b5 | 417 | #endif |
418 | disk_ctrl_t *ctrlp = xcalloc(1, sizeof(disk_ctrl_t)); | |
0a0bf5db | 419 | ctrlp->fd = fd; |
cd1fb0eb | 420 | ctrlp->data = ctrl_dat; |
0a0bf5db | 421 | #if USE_ASYNC_IO |
422 | aioRead(fd, | |
20f92343 | 423 | ctrl_dat->offset, |
711982d8 | 424 | ctrl_dat->buf, |
425 | ctrl_dat->req_len, | |
0a0bf5db | 426 | diskHandleReadComplete, |
cd1fb0eb | 427 | ctrlp); |
0a0bf5db | 428 | #else |
711982d8 | 429 | if (F->disk.offset != ctrl_dat->offset) { |
f2b30883 | 430 | debug(6, 3) ("diskHandleRead: FD %d seeking to offset %d\n", |
343c257b | 431 | fd, (int) ctrl_dat->offset); |
711982d8 | 432 | lseek(fd, ctrl_dat->offset, SEEK_SET); /* XXX ignore return? */ |
556c33d5 | 433 | F->disk.offset = ctrl_dat->offset; |
711982d8 | 434 | } |
435 | len = read(fd, ctrl_dat->buf, ctrl_dat->req_len); | |
436 | F->disk.offset += len; | |
582b6456 | 437 | diskHandleReadComplete(ctrlp, len, errno); |
090089c4 | 438 | #endif |
0a0bf5db | 439 | } |
440 | ||
de866d20 | 441 | static void |
4f92c80c | 442 | diskHandleReadComplete(void *data, int len, int errcode) |
0a0bf5db | 443 | { |
444 | disk_ctrl_t *ctrlp = data; | |
445 | dread_ctrl *ctrl_dat = ctrlp->data; | |
446 | int fd = ctrlp->fd; | |
901a2a3c | 447 | int rc = DISK_OK; |
0a0bf5db | 448 | errno = errcode; |
6cf028ab | 449 | |
0a0bf5db | 450 | xfree(data); |
6cf028ab | 451 | |
0e473d70 | 452 | if (len == -2 && errcode == -2) { /* Read cancelled - cleanup */ |
6cf028ab | 453 | cbdataUnlock(ctrl_dat->client_data); |
0a5bc521 | 454 | memFree(MEM_DREAD_CTRL, ctrl_dat); |
6cf028ab | 455 | return; |
456 | } | |
4f92c80c | 457 | fd_bytes(fd, len, FD_READ); |
0a0bf5db | 458 | if (len < 0) { |
b224ea98 | 459 | if (ignoreErrno(errno)) { |
901a2a3c | 460 | commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0); |
de866d20 | 461 | return; |
0a0bf5db | 462 | } |
901a2a3c | 463 | debug(50, 1) ("diskHandleRead: FD %d: %s\n", fd, xstrerror()); |
464 | len = 0; | |
465 | rc = DISK_ERROR; | |
090089c4 | 466 | } else if (len == 0) { |
901a2a3c | 467 | rc = DISK_EOF; |
090089c4 | 468 | } |
901a2a3c | 469 | if (cbdataValid(ctrl_dat->client_data)) |
5d86029a | 470 | ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data); |
901a2a3c | 471 | cbdataUnlock(ctrl_dat->client_data); |
0a5bc521 | 472 | memFree(MEM_DREAD_CTRL, ctrl_dat); |
090089c4 | 473 | } |
474 | ||
475 | ||
476 | /* start read operation */ | |
477 | /* buffer must be allocated from the caller. | |
478 | * It must have at least req_len space in there. | |
479 | * call handler when a reading is complete. */ | |
b8d8561b | 480 | int |
d377699f | 481 | file_read(int fd, char *buf, int req_len, off_t offset, DRCB * handler, void *client_data) |
090089c4 | 482 | { |
483 | dread_ctrl *ctrl_dat; | |
711982d8 | 484 | assert(fd >= 0); |
0a5bc521 | 485 | ctrl_dat = memAllocate(MEM_DREAD_CTRL); |
090089c4 | 486 | ctrl_dat->fd = fd; |
487 | ctrl_dat->offset = offset; | |
488 | ctrl_dat->req_len = req_len; | |
489 | ctrl_dat->buf = buf; | |
090089c4 | 490 | ctrl_dat->end_of_file = 0; |
491 | ctrl_dat->handler = handler; | |
492 | ctrl_dat->client_data = client_data; | |
901a2a3c | 493 | cbdataLock(client_data); |
0a0bf5db | 494 | #if USE_ASYNC_IO |
495 | diskHandleRead(fd, ctrl_dat); | |
496 | #else | |
b177367b | 497 | commSetSelect(fd, |
234967c9 | 498 | COMM_SELECT_READ, |
cd1fb0eb | 499 | diskHandleRead, |
500 | ctrl_dat, | |
b177367b | 501 | 0); |
0a0bf5db | 502 | #endif |
090089c4 | 503 | return DISK_OK; |
504 | } | |
505 | ||
b8d8561b | 506 | int |
507 | diskWriteIsComplete(int fd) | |
b59c7120 | 508 | { |
95d15928 | 509 | return fd_table[fd].disk.write_q ? 0 : 1; |
0a21bd84 | 510 | } |