]>
Commit | Line | Data |
---|---|---|
b224ea98 | 1 | |
30a4f2a8 | 2 | /* |
5999b776 | 3 | * $Id: disk.cc,v 1.116 1998/05/22 23:44:03 wessels Exp $ |
30a4f2a8 | 4 | * |
5 | * DEBUG: section 6 Disk I/O Routines | |
6 | * AUTHOR: Harvest Derived | |
7 | * | |
42c04c16 | 8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
30a4f2a8 | 9 | * -------------------------------------------------------- |
10 | * | |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
13 | * National Laboratory for Applied Network Research and funded by | |
14 | * the National Science Foundation. | |
15 | * | |
16 | * This program is free software; you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation; either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * This program is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU General Public License | |
27 | * along with this program; if not, write to the Free Software | |
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
29 | * | |
30 | */ | |
31 | ||
32 | /* | |
33 | * Copyright (c) 1994, 1995. All rights reserved. | |
34 | * | |
35 | * The Harvest software was developed by the Internet Research Task | |
36 | * Force Research Group on Resource Discovery (IRTF-RD): | |
37 | * | |
38 | * Mic Bowman of Transarc Corporation. | |
39 | * Peter Danzig of the University of Southern California. | |
40 | * Darren R. Hardy of the University of Colorado at Boulder. | |
41 | * Udi Manber of the University of Arizona. | |
42 | * Michael F. Schwartz of the University of Colorado at Boulder. | |
43 | * Duane Wessels of the University of Colorado at Boulder. | |
44 | * | |
45 | * This copyright notice applies to software in the Harvest | |
46 | * ``src/'' directory only. Users should consult the individual | |
47 | * copyright notices in the ``components/'' subdirectories for | |
48 | * copyright information about other software bundled with the | |
49 | * Harvest source code distribution. | |
50 | * | |
51 | * TERMS OF USE | |
52 | * | |
53 | * The Harvest software may be used and re-distributed without | |
54 | * charge, provided that the software origin and research team are | |
55 | * cited in any use of the system. Most commonly this is | |
56 | * accomplished by including a link to the Harvest Home Page | |
57 | * (http://harvest.cs.colorado.edu/) from the query page of any | |
58 | * Broker you deploy, as well as in the query result pages. These | |
59 | * links are generated automatically by the standard Broker | |
60 | * software distribution. | |
61 | * | |
62 | * The Harvest software is provided ``as is'', without express or | |
63 | * implied warranty, and with no support nor obligation to assist | |
64 | * in its use, correction, modification or enhancement. We assume | |
65 | * no liability with respect to the infringement of copyrights, | |
66 | * trade secrets, or any patents, and are not responsible for | |
67 | * consequential damages. Proper use of the Harvest software is | |
68 | * entirely the responsibility of the user. | |
69 | * | |
70 | * DERIVATIVE WORKS | |
71 | * | |
72 | * Users may make derivative works from the Harvest software, subject | |
73 | * to the following constraints: | |
74 | * | |
75 | * - You must include the above copyright notice and these | |
76 | * accompanying paragraphs in all forms of derivative works, | |
77 | * and any documentation and other materials related to such | |
78 | * distribution and use acknowledge that the software was | |
79 | * developed at the above institutions. | |
80 | * | |
81 | * - You must notify IRTF-RD regarding your distribution of | |
82 | * the derivative work. | |
83 | * | |
84 | * - You must clearly notify users that your are distributing | |
85 | * a modified version and not the original Harvest software. | |
86 | * | |
87 | * - Any derivative product is also subject to these copyright | |
88 | * and use restrictions. | |
89 | * | |
90 | * Note that the Harvest software is NOT in the public domain. We | |
91 | * retain copyright, as specified above. | |
92 | * | |
93 | * HISTORY OF FREE SOFTWARE STATUS | |
94 | * | |
95 | * Originally we required sites to license the software in cases | |
96 | * where they were going to build commercial products/services | |
97 | * around Harvest. In June 1995 we changed this policy. We now | |
98 | * allow people to use the core Harvest software (the code found in | |
99 | * the Harvest ``src/'' directory) for free. We made this change | |
100 | * in the interest of encouraging the widest possible deployment of | |
101 | * the technology. The Harvest software is really a reference | |
102 | * implementation of a set of protocols and formats, some of which | |
103 | * we intend to standardize. We encourage commercial | |
104 | * re-implementations of code complying to this set of standards. | |
105 | */ | |
ed43818f | 106 | |
44a47c6e | 107 | #include "squid.h" |
090089c4 | 108 | |
109 | #define DISK_LINE_LEN 1024 | |
090089c4 | 110 | |
0a0bf5db | 111 | typedef struct disk_ctrl_t { |
112 | int fd; | |
113 | void *data; | |
114 | } disk_ctrl_t; | |
115 | ||
116 | ||
117 | typedef struct open_ctrl_t { | |
f17936ab | 118 | FOCB *callback; |
0a0bf5db | 119 | void *callback_data; |
120 | char *path; | |
121 | } open_ctrl_t; | |
122 | ||
de866d20 | 123 | static AIOCB diskHandleWriteComplete; |
124 | static AIOCB diskHandleReadComplete; | |
95d15928 | 125 | static PF diskHandleRead; |
126 | static PF diskHandleWrite; | |
f5b8bbc4 | 127 | static void file_open_complete(void *, int, int); |
24382924 | 128 | |
04cece06 | 129 | void |
0673c0ba | 130 | disk_init(void) |
090089c4 | 131 | { |
04cece06 | 132 | #if USE_ASYNC_IO |
133 | aioClose(dup(0)); | |
134 | #endif | |
090089c4 | 135 | } |
136 | ||
137 | /* Open a disk file. Return a file descriptor */ | |
684c2720 | 138 | int |
6cf028ab | 139 | file_open(const char *path, int mode, FOCB * callback, void *callback_data, void *tag) |
090089c4 | 140 | { |
090089c4 | 141 | int fd; |
0a0bf5db | 142 | open_ctrl_t *ctrlp; |
143 | ||
144 | ctrlp = xmalloc(sizeof(open_ctrl_t)); | |
145 | ctrlp->path = xstrdup(path); | |
146 | ctrlp->callback = callback; | |
147 | ctrlp->callback_data = callback_data; | |
090089c4 | 148 | |
b59c7120 | 149 | if (mode & O_WRONLY) |
150 | mode |= O_APPEND; | |
4f92c80c | 151 | mode |= SQUID_NONBLOCK; |
b59c7120 | 152 | |
090089c4 | 153 | /* Open file */ |
0a0bf5db | 154 | #if USE_ASYNC_IO |
f17936ab | 155 | if (callback != NULL) { |
6cf028ab | 156 | aioOpen(path, mode, 0644, file_open_complete, ctrlp, tag); |
9e4ad609 | 157 | return DISK_OK; |
0a0bf5db | 158 | } |
f17936ab | 159 | #endif |
0a0bf5db | 160 | fd = open(path, mode, 0644); |
161 | file_open_complete(ctrlp, fd, errno); | |
162 | if (fd < 0) | |
163 | return DISK_ERROR; | |
164 | return fd; | |
0a0bf5db | 165 | } |
166 | ||
167 | ||
168 | static void | |
95d15928 | 169 | file_open_complete(void *data, int fd, int errcode) |
0a0bf5db | 170 | { |
171 | open_ctrl_t *ctrlp = (open_ctrl_t *) data; | |
6cf028ab | 172 | |
0e473d70 | 173 | if (fd == -2 && errcode == -2) { /* Cancelled - clean up */ |
6cf028ab | 174 | if (ctrlp->callback) |
175 | (ctrlp->callback) (ctrlp->callback_data, fd, errcode); | |
176 | xfree(ctrlp->path); | |
177 | xfree(ctrlp); | |
178 | return; | |
179 | } | |
0a0bf5db | 180 | if (fd < 0) { |
181 | errno = errcode; | |
af95908a | 182 | debug(50, 3) ("file_open: error opening file %s: %s\n", ctrlp->path, |
0a0bf5db | 183 | xstrerror()); |
184 | if (ctrlp->callback) | |
6cf028ab | 185 | (ctrlp->callback) (ctrlp->callback_data, DISK_ERROR, errcode); |
0a0bf5db | 186 | xfree(ctrlp->path); |
187 | xfree(ctrlp); | |
188 | return; | |
090089c4 | 189 | } |
365e5b34 | 190 | debug(6, 5) ("file_open: FD %d\n", fd); |
3ca60c86 | 191 | commSetCloseOnExec(fd); |
5c5783a2 | 192 | fd_open(fd, FD_FILE, ctrlp->path); |
0a0bf5db | 193 | if (ctrlp->callback) |
6cf028ab | 194 | (ctrlp->callback) (ctrlp->callback_data, fd, errcode); |
0a0bf5db | 195 | xfree(ctrlp->path); |
196 | xfree(ctrlp); | |
197 | } | |
198 | ||
090089c4 | 199 | /* close a disk file. */ |
95d15928 | 200 | void |
b8d8561b | 201 | file_close(int fd) |
090089c4 | 202 | { |
76f87348 | 203 | fde *F = &fd_table[fd]; |
25354045 | 204 | #if USE_ASYNC_IO |
0e473d70 | 205 | if (fd < 0) { |
6cf028ab | 206 | debug(6, 0) ("file_close: FD less than zero: %d\n", fd); |
207 | return; | |
208 | } | |
25354045 | 209 | #else |
210 | assert(fd >= 0); | |
211 | #endif | |
76f87348 | 212 | assert(F->open); |
0cd30ba5 | 213 | if (F->flags.write_daemon) { |
214 | F->flags.close_request = 1; | |
66979cec | 215 | debug(6, 2) ("file_close: FD %d, delaying close\n", fd); |
95d15928 | 216 | return; |
fb247d78 | 217 | } |
0a0bf5db | 218 | #if USE_ASYNC_IO |
95d15928 | 219 | aioClose(fd); |
0a0bf5db | 220 | #else |
95d15928 | 221 | close(fd); |
0a0bf5db | 222 | #endif |
0cd30ba5 | 223 | debug(6, F->flags.close_request ? 2 : 5) |
5ac0b6e7 | 224 | ("file_close: FD %d, really closing\n", fd); |
6cf028ab | 225 | fd_close(fd); |
090089c4 | 226 | } |
227 | ||
090089c4 | 228 | |
229 | /* write handler */ | |
582b6456 | 230 | static void |
79d39a72 | 231 | diskHandleWrite(int fd, void *notused) |
090089c4 | 232 | { |
4a86108c | 233 | int len = 0; |
0a0bf5db | 234 | disk_ctrl_t *ctrlp; |
235 | dwrite_q *q = NULL; | |
236 | dwrite_q *wq = NULL; | |
76f87348 | 237 | fde *F = &fd_table[fd]; |
238 | struct _fde_disk *fdd = &F->disk; | |
de866d20 | 239 | if (!fdd->write_q) |
582b6456 | 240 | return; |
ba7b771e | 241 | debug(6, 3) ("diskHandleWrite: FD %d\n", fd); |
0a0bf5db | 242 | /* We need to combine subsequent write requests after the first */ |
d377699f | 243 | /* But only if we don't need to seek() in betwen them, ugh! */ |
20f92343 | 244 | /* XXX This currently ignores any seeks (file_offset) */ |
de866d20 | 245 | if (fdd->write_q->next != NULL && fdd->write_q->next->next != NULL) { |
246 | len = 0; | |
247 | for (q = fdd->write_q->next; q != NULL; q = q->next) | |
d377699f | 248 | len += q->len - q->buf_offset; |
0a0bf5db | 249 | wq = xcalloc(1, sizeof(dwrite_q)); |
250 | wq->buf = xmalloc(len); | |
251 | wq->len = 0; | |
d377699f | 252 | wq->buf_offset = 0; |
0a0bf5db | 253 | wq->next = NULL; |
ed7f0b6a | 254 | wq->free_func = xfree; |
0a0bf5db | 255 | do { |
de866d20 | 256 | q = fdd->write_q->next; |
d377699f | 257 | len = q->len - q->buf_offset; |
258 | xmemcpy(wq->buf + wq->len, q->buf + q->buf_offset, len); | |
0a0bf5db | 259 | wq->len += len; |
de866d20 | 260 | fdd->write_q->next = q->next; |
ed7f0b6a | 261 | if (q->free_func) |
262 | (q->free_func) (q->buf); | |
0a0bf5db | 263 | safe_free(q); |
de866d20 | 264 | } while (fdd->write_q->next != NULL); |
265 | fdd->write_q_tail = wq; | |
266 | fdd->write_q->next = wq; | |
0a0bf5db | 267 | } |
268 | ctrlp = xcalloc(1, sizeof(disk_ctrl_t)); | |
269 | ctrlp->fd = fd; | |
f0027316 | 270 | #if USE_ASYNC_IO |
271 | ctrlp->data = fdd->write_q; | |
272 | #endif | |
8350fe9b | 273 | assert(fdd->write_q != NULL); |
d377699f | 274 | assert(fdd->write_q->len > fdd->write_q->buf_offset); |
0a0bf5db | 275 | #if USE_ASYNC_IO |
276 | aioWrite(fd, | |
5999b776 | 277 | -1, /* seek offset, -1 == append */ |
d377699f | 278 | fdd->write_q->buf + fdd->write_q->buf_offset, |
279 | fdd->write_q->len - fdd->write_q->buf_offset, | |
0a0bf5db | 280 | diskHandleWriteComplete, |
cd1fb0eb | 281 | ctrlp); |
0a0bf5db | 282 | #else |
ba7b771e | 283 | debug(6, 3) ("diskHandleWrite: FD %d writing %d bytes\n", |
5f6ac48b | 284 | fd, (int) (fdd->write_q->len - fdd->write_q->buf_offset)); |
0a0bf5db | 285 | len = write(fd, |
d377699f | 286 | fdd->write_q->buf + fdd->write_q->buf_offset, |
287 | fdd->write_q->len - fdd->write_q->buf_offset); | |
582b6456 | 288 | diskHandleWriteComplete(ctrlp, len, errno); |
0a0bf5db | 289 | #endif |
290 | } | |
291 | ||
de866d20 | 292 | static void |
b69f7771 | 293 | diskHandleWriteComplete(void *data, int len, int errcode) |
0a0bf5db | 294 | { |
295 | disk_ctrl_t *ctrlp = data; | |
0a0bf5db | 296 | int fd = ctrlp->fd; |
76f87348 | 297 | fde *F = &fd_table[fd]; |
298 | struct _fde_disk *fdd = &F->disk; | |
de866d20 | 299 | dwrite_q *q = fdd->write_q; |
300 | int status = DISK_OK; | |
ba7b771e | 301 | int do_callback; |
68c21f71 | 302 | int do_close; |
0a0bf5db | 303 | errno = errcode; |
ba7b771e | 304 | debug(6, 3) ("diskHandleWriteComplete: FD %d len = %d\n", fd, len); |
f0027316 | 305 | #if USE_ASYNC_IO |
306 | /* | |
307 | * From: "Michael O'Reilly" <michael@metal.iinet.net.au> | |
308 | * Date: 24 Feb 1998 15:12:06 +0800 | |
309 | * | |
310 | * A small patch to improve the AIO sanity. the patch below makes sure | |
311 | * the write request really does match the data passed back from the | |
312 | * async IO call. note that I haven't actually rebooted with this | |
313 | * patch yet, so 'provisional' is an understatement. | |
314 | */ | |
315 | if (q && q != ctrlp->data) { | |
316 | dwrite_q *p = ctrlp->data; | |
317 | debug(50, 0) ("KARMA: q != data (%p, %p)\n", q, p); | |
318 | debug(50, 0) ("KARMA: (%d, %d, %d FD %d)\n", | |
319 | q->buf_offset, q->len, len, fd); | |
320 | debug(50, 0) ("KARMA: desc %s, type %d, open %d, flags 0x%x\n", | |
321 | F->desc, F->type, F->open, F->flags); | |
322 | debug(50, 0) ("KARMA: (%d, %d)\n", p->buf_offset, p->len); | |
323 | len = -1; | |
324 | errcode = EFAULT; | |
325 | } | |
326 | #endif | |
0a0bf5db | 327 | safe_free(data); |
de866d20 | 328 | if (q == NULL) /* Someone aborted then write completed */ |
329 | return; | |
6cf028ab | 330 | |
0e473d70 | 331 | if (len == -2 && errcode == -2) { /* Write cancelled - cleanup */ |
6cf028ab | 332 | do { |
333 | fdd->write_q = q->next; | |
ed7f0b6a | 334 | if (q->free_func) |
335 | (q->free_func) (q->buf); | |
6cf028ab | 336 | safe_free(q); |
337 | } while ((q = fdd->write_q)); | |
338 | return; | |
339 | } | |
6cf028ab | 340 | fd_bytes(fd, len, FD_WRITE); |
0a0bf5db | 341 | if (len < 0) { |
b224ea98 | 342 | if (!ignoreErrno(errno)) { |
de866d20 | 343 | status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; |
a3d5953d | 344 | debug(50, 1) ("diskHandleWrite: FD %d: disk write error: %s\n", |
0c77d853 | 345 | fd, xstrerror()); |
25354045 | 346 | /* |
347 | * If there is no write callback, then this file is | |
348 | * most likely something important like a log file, or | |
349 | * an interprocess pipe. Its not a swapfile. We feel | |
350 | * that a write failure on a log file is rather important, | |
351 | * and Squid doesn't otherwise deal with this condition. | |
352 | * So to get the administrators attention, we exit with | |
353 | * a fatal message. | |
354 | */ | |
355 | if (fdd->wrt_handle == NULL) | |
356 | fatal("Write failure -- check your disk space and cache.log"); | |
357 | /* | |
358 | * If there is a write failure, then we notify the | |
359 | * upper layer via the callback, at the end of this | |
360 | * function. Meanwhile, flush all pending buffers | |
361 | * here. Let the upper layer decide how to handle the | |
362 | * failure. This will prevent experiencing multiple, | |
363 | * repeated write failures for the same FD because of | |
364 | * the queued data. | |
365 | */ | |
366 | do { | |
367 | fdd->write_q = q->next; | |
368 | if (q->free_func) | |
369 | (q->free_func) (q->buf); | |
370 | safe_free(q); | |
371 | } while ((q = fdd->write_q)); | |
0c77d853 | 372 | } |
de866d20 | 373 | len = 0; |
0a0bf5db | 374 | } |
8350fe9b | 375 | if (q != NULL) { |
376 | /* q might become NULL from write failure above */ | |
d377699f | 377 | q->buf_offset += len; |
6cf028ab | 378 | if (q->buf_offset > q->len) |
379 | debug(50, 1) ("diskHandleWriteComplete: q->buf_offset > q->len (%p,%d, %d, %d FD %d)\n", | |
5f6ac48b | 380 | q, (int) q->buf_offset, q->len, len, fd); |
d377699f | 381 | assert(q->buf_offset <= q->len); |
382 | if (q->buf_offset == q->len) { | |
56878878 | 383 | /* complete write */ |
384 | fdd->write_q = q->next; | |
ed7f0b6a | 385 | if (q->free_func) |
386 | (q->free_func) (q->buf); | |
56878878 | 387 | safe_free(q); |
388 | } | |
090089c4 | 389 | } |
de866d20 | 390 | if (fdd->write_q == NULL) { |
391 | /* no more data */ | |
392 | fdd->write_q_tail = NULL; | |
0cd30ba5 | 393 | F->flags.write_daemon = 0; |
de866d20 | 394 | } else { |
0a0bf5db | 395 | /* another block is queued */ |
25354045 | 396 | cbdataLock(fdd->wrt_handle_data); |
de866d20 | 397 | commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0); |
0cd30ba5 | 398 | F->flags.write_daemon = 1; |
4a86108c | 399 | } |
0cd30ba5 | 400 | do_close = F->flags.close_request; |
25354045 | 401 | if (fdd->wrt_handle) { |
ba7b771e | 402 | if (fdd->wrt_handle_data == NULL) |
403 | do_callback = 1; | |
404 | else if (cbdataValid(fdd->wrt_handle_data)) | |
405 | do_callback = 1; | |
406 | else | |
407 | do_callback = 0; | |
25354045 | 408 | if (fdd->wrt_handle_data != NULL) |
409 | cbdataUnlock(fdd->wrt_handle_data); | |
26720a7c | 410 | if (do_callback) { |
ba7b771e | 411 | fdd->wrt_handle(fd, status, len, fdd->wrt_handle_data); |
26720a7c | 412 | /* |
413 | * NOTE, this callback can close the FD, so we must | |
414 | * not touch 'F', 'fdd', etc. after this. | |
415 | */ | |
416 | return; | |
417 | } | |
25354045 | 418 | } |
68c21f71 | 419 | if (do_close) |
b59c7120 | 420 | file_close(fd); |
090089c4 | 421 | } |
422 | ||
423 | ||
090089c4 | 424 | /* write block to a file */ |
425 | /* write back queue. Only one writer at a time. */ | |
426 | /* call a handle when writing is complete. */ | |
e3ef2b09 | 427 | void |
3ebcfaa1 | 428 | file_write(int fd, |
d377699f | 429 | off_t file_offset, |
5830cdb3 | 430 | void *ptr_to_buf, |
684c2720 | 431 | int len, |
d89d1fb6 | 432 | DWCB handle, |
684c2720 | 433 | void *handle_data, |
9e4ad609 | 434 | FREE * free_func) |
090089c4 | 435 | { |
c6ac7aae | 436 | dwrite_q *wq = NULL; |
48cc3fcf | 437 | fde *F = &fd_table[fd]; |
438 | assert(fd >= 0); | |
439 | assert(F->open); | |
090089c4 | 440 | /* if we got here. Caller is eligible to write. */ |
30a4f2a8 | 441 | wq = xcalloc(1, sizeof(dwrite_q)); |
d377699f | 442 | wq->file_offset = file_offset; |
090089c4 | 443 | wq->buf = ptr_to_buf; |
090089c4 | 444 | wq->len = len; |
d377699f | 445 | wq->buf_offset = 0; |
090089c4 | 446 | wq->next = NULL; |
ed7f0b6a | 447 | wq->free_func = free_func; |
76f87348 | 448 | F->disk.wrt_handle = handle; |
449 | F->disk.wrt_handle_data = handle_data; | |
090089c4 | 450 | /* add to queue */ |
48cc3fcf | 451 | if (F->disk.write_q == NULL) { |
090089c4 | 452 | /* empty queue */ |
76f87348 | 453 | F->disk.write_q = F->disk.write_q_tail = wq; |
090089c4 | 454 | } else { |
76f87348 | 455 | F->disk.write_q_tail->next = wq; |
456 | F->disk.write_q_tail = wq; | |
090089c4 | 457 | } |
0cd30ba5 | 458 | if (!F->flags.write_daemon) { |
25354045 | 459 | cbdataLock(F->disk.wrt_handle_data); |
0a0bf5db | 460 | #if USE_ASYNC_IO |
95d15928 | 461 | diskHandleWrite(fd, NULL); |
0a0bf5db | 462 | #else |
95d15928 | 463 | commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0); |
0a0bf5db | 464 | #endif |
0cd30ba5 | 465 | F->flags.write_daemon = 1; |
429fdbec | 466 | } |
090089c4 | 467 | } |
468 | ||
469 | ||
470 | ||
471 | /* Read from FD */ | |
582b6456 | 472 | static void |
473 | diskHandleRead(int fd, void *data) | |
090089c4 | 474 | { |
582b6456 | 475 | dread_ctrl *ctrl_dat = data; |
606bd3b5 | 476 | #if !USE_ASYNC_IO |
edd2eb63 | 477 | fde *F = &fd_table[fd]; |
090089c4 | 478 | int len; |
606bd3b5 | 479 | #endif |
480 | disk_ctrl_t *ctrlp = xcalloc(1, sizeof(disk_ctrl_t)); | |
0a0bf5db | 481 | ctrlp->fd = fd; |
cd1fb0eb | 482 | ctrlp->data = ctrl_dat; |
0a0bf5db | 483 | #if USE_ASYNC_IO |
484 | aioRead(fd, | |
20f92343 | 485 | ctrl_dat->offset, |
711982d8 | 486 | ctrl_dat->buf, |
487 | ctrl_dat->req_len, | |
0a0bf5db | 488 | diskHandleReadComplete, |
cd1fb0eb | 489 | ctrlp); |
0a0bf5db | 490 | #else |
711982d8 | 491 | if (F->disk.offset != ctrl_dat->offset) { |
f2b30883 | 492 | debug(6, 3) ("diskHandleRead: FD %d seeking to offset %d\n", |
343c257b | 493 | fd, (int) ctrl_dat->offset); |
711982d8 | 494 | lseek(fd, ctrl_dat->offset, SEEK_SET); /* XXX ignore return? */ |
556c33d5 | 495 | F->disk.offset = ctrl_dat->offset; |
711982d8 | 496 | } |
497 | len = read(fd, ctrl_dat->buf, ctrl_dat->req_len); | |
498 | F->disk.offset += len; | |
582b6456 | 499 | diskHandleReadComplete(ctrlp, len, errno); |
090089c4 | 500 | #endif |
0a0bf5db | 501 | } |
502 | ||
de866d20 | 503 | static void |
4f92c80c | 504 | diskHandleReadComplete(void *data, int len, int errcode) |
0a0bf5db | 505 | { |
506 | disk_ctrl_t *ctrlp = data; | |
507 | dread_ctrl *ctrl_dat = ctrlp->data; | |
508 | int fd = ctrlp->fd; | |
901a2a3c | 509 | int rc = DISK_OK; |
0a0bf5db | 510 | errno = errcode; |
6cf028ab | 511 | |
0a0bf5db | 512 | xfree(data); |
6cf028ab | 513 | |
0e473d70 | 514 | if (len == -2 && errcode == -2) { /* Read cancelled - cleanup */ |
6cf028ab | 515 | cbdataUnlock(ctrl_dat->client_data); |
516 | safe_free(ctrl_dat); | |
517 | return; | |
518 | } | |
4f92c80c | 519 | fd_bytes(fd, len, FD_READ); |
0a0bf5db | 520 | if (len < 0) { |
b224ea98 | 521 | if (ignoreErrno(errno)) { |
901a2a3c | 522 | commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0); |
de866d20 | 523 | return; |
0a0bf5db | 524 | } |
901a2a3c | 525 | debug(50, 1) ("diskHandleRead: FD %d: %s\n", fd, xstrerror()); |
526 | len = 0; | |
527 | rc = DISK_ERROR; | |
090089c4 | 528 | } else if (len == 0) { |
901a2a3c | 529 | rc = DISK_EOF; |
090089c4 | 530 | } |
901a2a3c | 531 | if (cbdataValid(ctrl_dat->client_data)) |
5d86029a | 532 | ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data); |
901a2a3c | 533 | cbdataUnlock(ctrl_dat->client_data); |
6a54c60e | 534 | safe_free(ctrl_dat); |
090089c4 | 535 | } |
536 | ||
537 | ||
538 | /* start read operation */ | |
539 | /* buffer must be allocated from the caller. | |
540 | * It must have at least req_len space in there. | |
541 | * call handler when a reading is complete. */ | |
b8d8561b | 542 | int |
d377699f | 543 | file_read(int fd, char *buf, int req_len, off_t offset, DRCB * handler, void *client_data) |
090089c4 | 544 | { |
545 | dread_ctrl *ctrl_dat; | |
711982d8 | 546 | assert(fd >= 0); |
30a4f2a8 | 547 | ctrl_dat = xcalloc(1, sizeof(dread_ctrl)); |
090089c4 | 548 | ctrl_dat->fd = fd; |
549 | ctrl_dat->offset = offset; | |
550 | ctrl_dat->req_len = req_len; | |
551 | ctrl_dat->buf = buf; | |
090089c4 | 552 | ctrl_dat->end_of_file = 0; |
553 | ctrl_dat->handler = handler; | |
554 | ctrl_dat->client_data = client_data; | |
901a2a3c | 555 | cbdataLock(client_data); |
0a0bf5db | 556 | #if USE_ASYNC_IO |
557 | diskHandleRead(fd, ctrl_dat); | |
558 | #else | |
b177367b | 559 | commSetSelect(fd, |
234967c9 | 560 | COMM_SELECT_READ, |
cd1fb0eb | 561 | diskHandleRead, |
562 | ctrl_dat, | |
b177367b | 563 | 0); |
0a0bf5db | 564 | #endif |
090089c4 | 565 | return DISK_OK; |
566 | } | |
567 | ||
b8d8561b | 568 | int |
569 | diskWriteIsComplete(int fd) | |
b59c7120 | 570 | { |
95d15928 | 571 | return fd_table[fd].disk.write_q ? 0 : 1; |
0a21bd84 | 572 | } |