📄 disk.c
字号:
/* * $Id: disk.c,v 1.141.2.1 1999/02/12 22:32:15 wessels Exp $ * * DEBUG: section 6 Disk I/O Routines * AUTHOR: Harvest Derived * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"#define DISK_LINE_LEN 1024typedef struct open_ctrl_t { FOCB *callback; void *callback_data; char *path;} open_ctrl_t;static AIOCB diskHandleWriteComplete;static AIOCB diskHandleReadComplete;static PF diskHandleRead;static PF diskHandleWrite;static AIOCB fileOpenComplete;voiddisk_init(void){#if USE_ASYNC_IO aioClose(dup(0));#endif}/* Open a disk file. Return a file descriptor */intfile_open(const char *path, int mode, FOCB * callback, void *callback_data, void *tag){ int fd; open_ctrl_t *ctrlp; ctrlp = xmalloc(sizeof(open_ctrl_t)); ctrlp->path = xstrdup(path); ctrlp->callback = callback; ctrlp->callback_data = callback_data; if (mode & O_WRONLY) mode |= O_APPEND; mode |= SQUID_NONBLOCK; /* Open file */ Opening_FD++;#if USE_ASYNC_IO if (callback != NULL) { aioOpen(path, mode, 0644, fileOpenComplete, ctrlp, tag); return DISK_OK; }#endif errno = 0; fd = open(path, mode, 0644); fileOpenComplete(-1, ctrlp, fd, errno); if (fd < 0) return DISK_ERROR; return fd;}static voidfileOpenComplete(int unused, void *data, int fd, int errcode){ open_ctrl_t *ctrlp = (open_ctrl_t *) data; debug(6, 5) ("fileOpenComplete: FD %d, data %p, errcode %d\n", fd, data, errcode); Counter.syscalls.disk.opens++; Opening_FD--; if (fd == -2 && errcode == -2) { /* Cancelled - clean up */ if (ctrlp->callback) (ctrlp->callback) (ctrlp->callback_data, fd, errcode); xfree(ctrlp->path); xfree(ctrlp); return; } if (fd < 0) { errno = errcode; debug(50, 3) ("fileOpenComplete: error opening file %s: %s\n", ctrlp->path, xstrerror()); if (ctrlp->callback) (ctrlp->callback) (ctrlp->callback_data, DISK_ERROR, errcode); xfree(ctrlp->path); xfree(ctrlp); return; } debug(6, 5) ("fileOpenComplete: FD %d\n", fd); commSetCloseOnExec(fd); fd_open(fd, FD_FILE, ctrlp->path); if (ctrlp->callback) (ctrlp->callback) (ctrlp->callback_data, fd, errcode); xfree(ctrlp->path); xfree(ctrlp);}/* close a disk file. */voidfile_close(int fd){ fde *F = &fd_table[fd]; PF *callback;#if USE_ASYNC_IO if (fd < 0) { debug(6, 0) ("file_close: FD less than zero: %d\n", fd); return; }#else assert(fd >= 0);#endif assert(F->flags.open); if ((callback = F->read_handler)) { F->read_handler = NULL; callback(-1, F->read_data); } if (F->flags.write_daemon) {#if defined(_SQUID_MSWIN_) || defined(_SQUID_OS2_) /* * on some operating systems, you can not delete or rename * open files, so we won't allow delayed close. */ while (!diskWriteIsComplete(fd)) diskHandleWrite(fd, NULL);#else F->flags.close_request = 1; debug(6, 2) ("file_close: FD %d, delaying close\n", fd); return;#endif } /* * Assert there is no write callback. Otherwise we might be * leaking write state data by closing the descriptor */ assert(F->write_handler == NULL); F->flags.closing = 1;#if USE_ASYNC_IO aioClose(fd);#else#if CALL_FSYNC_BEFORE_CLOSE fsync(fd);#endif close(fd);#endif debug(6, F->flags.close_request ? 2 : 5) ("file_close: FD %d, really closing\n", fd);#if !USE_ASYNC_IO fd_close(fd);#endif Counter.syscalls.disk.closes++;}/* * This function has the purpose of combining multiple writes. This is * to facilitate the ASYNC_IO option since it can only guarantee 1 * write to a file per trip around the comm.c select() loop. That's bad * because more than 1 write can be made to the access.log file per * trip, and so this code is purely designed to help batch multiple * sequential writes to the access.log file. Squid will never issue * multiple writes for any other file type during 1 trip around the * select() loop. --SLF */static voiddiskCombineWrites(struct _fde_disk *fdd){ int len = 0; dwrite_q *q = NULL; dwrite_q *wq = NULL; /* * We need to combine multiple write requests on an FD's write * queue But only if we don't need to seek() in between them, ugh! * XXX This currently ignores any seeks (file_offset) */ if (fdd->write_q != NULL && fdd->write_q->next != NULL) { len = 0; for (q = fdd->write_q; q != NULL; q = q->next) len += q->len - q->buf_offset; wq = xcalloc(1, sizeof(dwrite_q)); wq->buf = xmalloc(len); wq->len = 0; wq->buf_offset = 0; wq->next = NULL; wq->free_func = xfree; do { q = fdd->write_q; len = q->len - q->buf_offset; xmemcpy(wq->buf + wq->len, q->buf + q->buf_offset, len); wq->len += len; fdd->write_q = q->next; if (q->free_func) (q->free_func) (q->buf); safe_free(q); } while (fdd->write_q != NULL); fdd->write_q_tail = wq; fdd->write_q = wq; }}/* write handler */static voiddiskHandleWrite(int fd, void *notused){#if !USE_ASYNC_IO int len = 0;#endif fde *F = &fd_table[fd]; struct _fde_disk *fdd = &F->disk; if (!fdd->write_q) return;#ifdef OPTIMISTIC_IO assert(!F->flags.calling_io_handler);#endif debug(6, 3) ("diskHandleWrite: FD %d\n", fd); assert(fdd->write_q != NULL); assert(fdd->write_q->len > fdd->write_q->buf_offset);#if USE_ASYNC_IO aioWrite(fd, -1, /* seek offset, -1 == append */ fdd->write_q->buf + fdd->write_q->buf_offset, fdd->write_q->len - fdd->write_q->buf_offset, diskHandleWriteComplete, fdd->write_q);#else debug(6, 3) ("diskHandleWrite: FD %d writing %d bytes\n", fd, (int) (fdd->write_q->len - fdd->write_q->buf_offset)); errno = 0; len = write(fd, fdd->write_q->buf + fdd->write_q->buf_offset, fdd->write_q->len - fdd->write_q->buf_offset); diskHandleWriteComplete(fd, fdd->write_q, len, errno);#endif}static voiddiskHandleWriteComplete(int fd, void *data, int len, int errcode){ fde *F = &fd_table[fd]; struct _fde_disk *fdd = &F->disk; dwrite_q *q = fdd->write_q; int status = DISK_OK; int do_callback; int do_close; errno = errcode; debug(6, 3) ("diskHandleWriteComplete: FD %d len = %d\n", fd, len); Counter.syscalls.disk.writes++;#if USE_ASYNC_IO/* * From: "Michael O'Reilly" <michael@metal.iinet.net.au> * Date: 24 Feb 1998 15:12:06 +0800 * * A small patch to improve the AIO sanity. the patch below makes sure * the write request really does match the data passed back from the * async IO call. note that I haven't actually rebooted with this * patch yet, so 'provisional' is an understatement. */ if (q && q != data) { dwrite_q *p = data; debug(50, 0) ("KARMA: q != data (%p, %p)\n", q, p); debug(50, 0) ("KARMA: (%d, %d, %d FD %d)\n", q->buf_offset, q->len, len, fd); debug(50, 0) ("KARMA: desc %s, type %d, open %d, flags 0x%x\n", F->desc, F->type, F->flags.open, F->flags); debug(50, 0) ("KARMA: (%d, %d)\n", p->buf_offset, p->len); len = -1; errcode = EFAULT; }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -