📄 disk.c
字号:
if (q == NULL) /* Someone aborted then write completed */ return; if (len == -2 && errcode == -2) { /* Write cancelled - cleanup */ do { fdd->write_q = q->next; if (q->free_func) (q->free_func) (q->buf); safe_free(q); } while ((q = fdd->write_q)); return; } fd_bytes(fd, len, FD_WRITE); if (len < 0) { if (!ignoreErrno(errno)) { status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; debug(50, 1) ("diskHandleWrite: FD %d: disk write error: %s\n", fd, xstrerror()); /* * If there is no write callback, then this file is * most likely something important like a log file, or * an interprocess pipe. Its not a swapfile. We feel * that a write failure on a log file is rather important, * and Squid doesn't otherwise deal with this condition. * So to get the administrators attention, we exit with * a fatal message. */ if (fdd->wrt_handle == NULL) fatal("Write failure -- check your disk space and cache.log"); /* * If there is a write failure, then we notify the * upper layer via the callback, at the end of this * function. Meanwhile, flush all pending buffers * here. Let the upper layer decide how to handle the * failure. This will prevent experiencing multiple, * repeated write failures for the same FD because of * the queued data. */ do { fdd->write_q = q->next; if (q->free_func) (q->free_func) (q->buf); safe_free(q); } while ((q = fdd->write_q)); } len = 0; } if (q != NULL) { /* q might become NULL from write failure above */ q->buf_offset += len; if (q->buf_offset > q->len) debug(50, 1) ("diskHandleWriteComplete: q->buf_offset > q->len (%p,%d, %d, %d FD %d)\n", q, (int) q->buf_offset, q->len, len, fd); assert(q->buf_offset <= q->len); if (q->buf_offset == q->len) { /* complete write */ fdd->write_q = q->next; if (q->free_func) (q->free_func) (q->buf); safe_free(q); } } if (fdd->write_q == NULL) { /* no more data */ fdd->write_q_tail = NULL; F->flags.write_daemon = 0; } else { /* another block is queued */ diskCombineWrites(fdd); cbdataLock(fdd->wrt_handle_data); commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0); F->flags.write_daemon = 1; } do_close = F->flags.close_request; if (fdd->wrt_handle) { if (fdd->wrt_handle_data == NULL) do_callback = 1; else if (cbdataValid(fdd->wrt_handle_data)) do_callback = 1; else do_callback = 0; if (fdd->wrt_handle_data != NULL) cbdataUnlock(fdd->wrt_handle_data); if (do_callback) {#ifdef OPTIMISTIC_IO F->flags.calling_io_handler = 1;#endif fdd->wrt_handle(fd, status, len, fdd->wrt_handle_data); /* * NOTE, this callback can close the FD, so we must * not touch 'F', 'fdd', etc. after this. */#ifdef OPTIMISTIC_IO F->flags.calling_io_handler = 0;#endif return; } } if (do_close) file_close(fd);}/* write block to a file *//* write back queue. Only one writer at a time. *//* call a handle when writing is complete. */voidfile_write(int fd, off_t file_offset, void *ptr_to_buf, int len, DWCB handle, void *handle_data, FREE * free_func){ dwrite_q *wq = NULL; fde *F = &fd_table[fd]; assert(fd >= 0); assert(F->flags.open); /* if we got here. Caller is eligible to write. */ wq = xcalloc(1, sizeof(dwrite_q)); wq->file_offset = file_offset; wq->buf = ptr_to_buf; wq->len = len; wq->buf_offset = 0; wq->next = NULL; wq->free_func = free_func; F->disk.wrt_handle = handle; F->disk.wrt_handle_data = handle_data; /* add to queue */ if (F->disk.write_q == NULL) { /* empty queue */ F->disk.write_q = F->disk.write_q_tail = wq; } else { F->disk.write_q_tail->next = wq; F->disk.write_q_tail = wq; } if (!F->flags.write_daemon) { cbdataLock(F->disk.wrt_handle_data);#if USE_ASYNC_IO diskHandleWrite(fd, NULL);#else#ifdef OPTIMISTIC_IO if (F->flags.calling_io_handler)#endif commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0);#ifdef OPTIMISTIC_IO else diskHandleWrite(fd, NULL);#endif#endif#ifndef OPTIMISTIC_IO F->flags.write_daemon = 1;#endif }}/* * a wrapper around file_write to allow for MemBuf to be file_written * in a snap */voidfile_write_mbuf(int fd, off_t off, MemBuf mb, DWCB * handler, void *handler_data){ file_write(fd, off, mb.buf, mb.size, handler, handler_data, memBufFreeFunc(&mb));}/* Read from FD */static voiddiskHandleRead(int fd, void *data){ dread_ctrl *ctrl_dat = data;#if !USE_ASYNC_IO fde *F = &fd_table[fd]; int len;#endif#ifdef OPTIMISTIC_IO assert(!F->flags.calling_io_handler);#endif /* OPTIMISTIC_IO */ /* * FD < 0 indicates premature close; we just have to free * the state data. */ if (fd < 0) { memFree(ctrl_dat, MEM_DREAD_CTRL); return; }#if USE_ASYNC_IO aioRead(fd, ctrl_dat->offset, ctrl_dat->buf, ctrl_dat->req_len, diskHandleReadComplete, ctrl_dat);#else if (F->disk.offset != ctrl_dat->offset) { debug(6, 3) ("diskHandleRead: FD %d seeking to offset %d\n", fd, (int) ctrl_dat->offset); lseek(fd, ctrl_dat->offset, SEEK_SET); /* XXX ignore return? */ Counter.syscalls.disk.seeks++; F->disk.offset = ctrl_dat->offset; } errno = 0; len = read(fd, ctrl_dat->buf, ctrl_dat->req_len); if (len > 0) F->disk.offset += len; diskHandleReadComplete(fd, ctrl_dat, len, errno);#endif}static voiddiskHandleReadComplete(int fd, void *data, int len, int errcode){ dread_ctrl *ctrl_dat = data; int rc = DISK_OK;#ifdef OPTIMISTIC_IO fde *F = &fd_table[fd];#endif /* OPTIMISTIC_IO */ Counter.syscalls.disk.reads++; errno = errcode; if (len == -2 && errcode == -2) { /* Read cancelled - cleanup */ cbdataUnlock(ctrl_dat->client_data); memFree(ctrl_dat, MEM_DREAD_CTRL); return; } fd_bytes(fd, len, FD_READ); if (len < 0) { if (ignoreErrno(errno)) { commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0); return; } debug(50, 1) ("diskHandleRead: FD %d: %s\n", fd, xstrerror()); len = 0; rc = DISK_ERROR; } else if (len == 0) { rc = DISK_EOF; }#ifdef OPTIMISTIC_IO F->flags.calling_io_handler = 1;#endif /* OPTIMISTIC_IO */ if (cbdataValid(ctrl_dat->client_data)) ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data);#ifdef OPTIMISTIC_IO F->flags.calling_io_handler = 0;#endif /* OPTIMISTIC_IO */ cbdataUnlock(ctrl_dat->client_data); memFree(ctrl_dat, MEM_DREAD_CTRL);}/* start read operation *//* buffer must be allocated from the caller. * It must have at least req_len space in there. * call handler when a reading is complete. */intfile_read(int fd, char *buf, int req_len, off_t offset, DRCB * handler, void *client_data){ dread_ctrl *ctrl_dat;#ifdef OPTIMISTIC_IO fde *F = &fd_table[fd];#endif /* OPTIMISTIC_IO */ assert(fd >= 0); ctrl_dat = memAllocate(MEM_DREAD_CTRL); ctrl_dat->fd = fd; ctrl_dat->offset = offset; ctrl_dat->req_len = req_len; ctrl_dat->buf = buf; ctrl_dat->end_of_file = 0; ctrl_dat->handler = handler; ctrl_dat->client_data = client_data; cbdataLock(client_data);#if USE_ASYNC_IO diskHandleRead(fd, ctrl_dat);#else#ifndef OPTIMISTIC_IO commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0);#else if (F->flags.calling_io_handler) commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0); else diskHandleRead(fd, ctrl_dat);#endif /* OPTIMISTIC_IO */#endif return DISK_OK;}intdiskWriteIsComplete(int fd){ return fd_table[fd].disk.write_q ? 0 : 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -