/*
- * $Id: aiops.cc,v 1.17 2002/11/09 09:35:26 hno Exp $
+ * $Id: aiops.cc,v 1.18 2002/11/10 02:29:58 hno Exp $
*
* DEBUG: section 43 AIOPS
* AUTHOR: Stewart Forster <slf@connect.com.au>
return p;
}
-static void *
+void *
squidaio_xmalloc(int size)
{
void *p;
return p;
}
-static void
+void
squidaio_xfree(void *p, int size)
{
MemPool *pool;
squidaio_xstrfree(requestp->path);
break;
case _AIO_OP_READ:
- if (!cancelled && requestp->ret > 0)
- xmemcpy(requestp->bufferp, requestp->tmpbufp, requestp->ret);
- squidaio_xfree(requestp->tmpbufp, requestp->buflen);
break;
case _AIO_OP_WRITE:
squidaio_xfree(requestp->tmpbufp, requestp->buflen);
requestp = (squidaio_request_t *)memPoolAlloc(squidaio_request_pool);
requestp->fd = fd;
requestp->bufferp = bufp;
- requestp->tmpbufp = (char *) squidaio_xmalloc(bufs);
requestp->buflen = bufs;
requestp->offset = offset;
requestp->whence = whence;
squidaio_do_read(squidaio_request_t * requestp)
{
lseek(requestp->fd, requestp->offset, requestp->whence);
- requestp->ret = read(requestp->fd, requestp->tmpbufp, requestp->buflen);
+ requestp->ret = read(requestp->fd, requestp->bufferp, requestp->buflen);
requestp->err = errno;
}
/*
- * $Id: async_io.cc,v 1.16 2002/10/13 20:35:24 robertc Exp $
+ * $Id: async_io.cc,v 1.17 2002/11/10 02:29:58 hno Exp $
*
* DEBUG: section 32 Asynchronous Disk I/O
* AUTHOR: Pete Bentley <pete@demon.net>
AIOCB *done_handler;
void *done_handler_data;
squidaio_result_t result;
+ int len;
char *bufp;
FREE *free_func;
dlink_node node;
} squidaio_ctrl_t;
static struct {
- int open_start;
- int open_finish;
- int close_start;
- int close_finish;
- int cancel;
- int write_start;
- int write_finish;
- int read_start;
- int read_finish;
- int stat_start;
- int stat_finish;
- int unlink_start;
- int unlink_finish;
- int check_callback;
+ int open_start;
+ int open_finish;
+ int close_start;
+ int close_finish;
+ int cancel;
+ int write_start;
+ int write_finish;
+ int read_start;
+ int read_finish;
+ int stat_start;
+ int stat_finish;
+ int unlink_start;
+ int unlink_finish;
+ int check_callback;
} squidaio_counts;
typedef struct squidaio_unlinkq_t {
void
aioCancel(int fd)
{
- squidaio_ctrl_t *curr;
+ squidaio_ctrl_t *ctrlp;
dlink_node *m, *next;
assert(initialised);
squidaio_counts.cancel++;
for (m = used_list.head; m; m = next) {
next = m->next;
- curr = (squidaio_ctrl_t *)m->data;
- if (curr->fd != fd)
+ ctrlp = (squidaio_ctrl_t *)m->data;
+ if (ctrlp->fd != fd)
continue;
- squidaio_cancel(&curr->result);
+ squidaio_cancel(&ctrlp->result);
- if (curr->done_handler) {
- AIOCB *callback = curr->done_handler;
+ if (ctrlp->done_handler) {
+ AIOCB *callback = ctrlp->done_handler;
void *cbdata;
- curr->done_handler = NULL;
+ ctrlp->done_handler = NULL;
debug(32, 2) ("this be aioCancel\n");
- if (cbdataReferenceValidDone(curr->done_handler_data, &cbdata))
- callback(fd, cbdata, -2, -2);
+ if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata))
+ callback(fd, cbdata, NULL, -2, -2);
+ /* free data if requested to aioWrite() */
+ if (ctrlp->free_func)
+ ctrlp->free_func(ctrlp->bufp);
+ /* free temporary read buffer */
+ if (ctrlp->operation == _AIO_READ)
+ squidaio_xfree(ctrlp->bufp, ctrlp->len);
}
dlinkDelete(m, &used_list);
- memPoolFree(squidaio_ctrl_pool, curr);
+ memPoolFree(squidaio_ctrl_pool, ctrlp);
}
}
void
-aioRead(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data)
+aioRead(int fd, int offset, int len, AIOCB * callback, void *callback_data)
{
squidaio_ctrl_t *ctrlp;
int seekmode;
ctrlp->done_handler = callback;
ctrlp->done_handler_data = cbdataReference(callback_data);
ctrlp->operation = _AIO_READ;
+ ctrlp->len = len;
+ ctrlp->bufp = squidaio_xmalloc(len);
if (offset >= 0)
seekmode = SEEK_SET;
else {
offset = 0;
}
ctrlp->result.data = ctrlp;
- squidaio_read(fd, bufp, len, offset, seekmode, &ctrlp->result);
+ squidaio_read(fd, ctrlp->bufp, len, offset, seekmode, &ctrlp->result);
dlinkAdd(ctrlp, &ctrlp->node, &used_list);
return;
} /* aioRead */
if ((resultp = squidaio_poll_done()) == NULL)
break;
ctrlp = (squidaio_ctrl_t *) resultp->data;
- switch (resultp->result_type){
- case _AIO_OP_NONE:
- case _AIO_OP_TRUNCATE:
- case _AIO_OP_OPENDIR:
- break;
- case _AIO_OP_OPEN:
- ++squidaio_counts.open_finish;
- break;
- case _AIO_OP_READ:
- ++squidaio_counts.read_finish;
- break;
- case _AIO_OP_WRITE:
- ++squidaio_counts.write_finish;
- break;
- case _AIO_OP_CLOSE:
- ++squidaio_counts.close_finish;
- break;
- case _AIO_OP_UNLINK:
- ++squidaio_counts.unlink_finish;
- break;
- case _AIO_OP_STAT:
- ++squidaio_counts.stat_finish;
- break;
+ switch (resultp->result_type) {
+ case _AIO_OP_NONE:
+ case _AIO_OP_TRUNCATE:
+ case _AIO_OP_OPENDIR:
+ break;
+ case _AIO_OP_OPEN:
+ ++squidaio_counts.open_finish;
+ break;
+ case _AIO_OP_READ:
+ ++squidaio_counts.read_finish;
+ break;
+ case _AIO_OP_WRITE:
+ ++squidaio_counts.write_finish;
+ break;
+ case _AIO_OP_CLOSE:
+ ++squidaio_counts.close_finish;
+ break;
+ case _AIO_OP_UNLINK:
+ ++squidaio_counts.unlink_finish;
+ break;
+ case _AIO_OP_STAT:
+ ++squidaio_counts.stat_finish;
+ break;
}
if (ctrlp == NULL)
continue; /* XXX Should not happen */
ctrlp->done_handler = NULL;
if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) {
retval = 1; /* Return that we've actually done some work */
- callback(ctrlp->fd, cbdata,
+ callback(ctrlp->fd, cbdata, ctrlp->bufp,
ctrlp->result.aio_return, ctrlp->result.aio_errno);
+ } else {
+ if (ctrlp->operation == _AIO_OPEN) {
+ /* The open operation was aborted.. */
+ int fd = ctrlp->result.aio_return;
+ if (fd >= 0)
+ aioClose(fd);
+ }
}
}
/* free data if requested to aioWrite() */
if (ctrlp->free_func)
ctrlp->free_func(ctrlp->bufp);
+ /* free temporary read buffer */
+ if (ctrlp->operation == _AIO_READ)
+ squidaio_xfree(ctrlp->bufp, ctrlp->len);
if (ctrlp->operation == _AIO_CLOSE)
aioFDWasClosed(ctrlp->fd);
memPoolFree(squidaio_ctrl_pool, ctrlp);
{
storeAppendPrintf(sentry, "ASYNC IO Counters:\n");
storeAppendPrintf(sentry, "Operation\t# Requests\tNumber serviced\n");
- storeAppendPrintf(sentry, "open\t%d\t%d\n", squidaio_counts.open_start,squidaio_counts.open_finish);
- storeAppendPrintf(sentry, "close\t%d\t%d\n", squidaio_counts.close_start,squidaio_counts.close_finish);
+ storeAppendPrintf(sentry, "open\t%d\t%d\n", squidaio_counts.open_start, squidaio_counts.open_finish);
+ storeAppendPrintf(sentry, "close\t%d\t%d\n", squidaio_counts.close_start, squidaio_counts.close_finish);
storeAppendPrintf(sentry, "cancel\t%d\t-\n", squidaio_counts.cancel);
- storeAppendPrintf(sentry, "write\t%d\t%d\n", squidaio_counts.write_start,squidaio_counts.write_finish);
- storeAppendPrintf(sentry, "read\t%d\t%d\n", squidaio_counts.read_start,squidaio_counts.read_finish);
- storeAppendPrintf(sentry, "stat\t%d\t%d\n", squidaio_counts.stat_start,squidaio_counts.stat_finish);
- storeAppendPrintf(sentry, "unlink\t%d\t%d\n", squidaio_counts.unlink_start,squidaio_counts.unlink_finish);
+ storeAppendPrintf(sentry, "write\t%d\t%d\n", squidaio_counts.write_start, squidaio_counts.write_finish);
+ storeAppendPrintf(sentry, "read\t%d\t%d\n", squidaio_counts.read_start, squidaio_counts.read_finish);
+ storeAppendPrintf(sentry, "stat\t%d\t%d\n", squidaio_counts.stat_start, squidaio_counts.stat_finish);
+ storeAppendPrintf(sentry, "unlink\t%d\t%d\n", squidaio_counts.unlink_start, squidaio_counts.unlink_finish);
storeAppendPrintf(sentry, "check_callback\t%d\t-\n", squidaio_counts.check_callback);
storeAppendPrintf(sentry, "queue\t%d\t-\n", squidaio_get_queue_len());
}
typedef struct _squidaio_result_t squidaio_result_t;
-typedef void AIOCB(int fd, void *, int aio_return, int aio_errno);
+typedef void AIOCB(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno);
int squidaio_cancel(squidaio_result_t *);
int squidaio_open(const char *, int, mode_t, squidaio_result_t *);
int squidaio_operations_pending(void);
int squidaio_sync(void);
int squidaio_get_queue_len(void);
+void *squidaio_xmalloc(int size);
+void squidaio_xfree(void *p, int size);
void aioInit(void);
void aioDone(void);
void aioOpen(const char *, int, mode_t, AIOCB *, void *);
void aioClose(int);
void aioWrite(int, int offset, char *, int size, AIOCB *, void *, FREE *);
-void aioRead(int, int offset, char *, int size, AIOCB *, void *);
+void aioRead(int, int offset, int size, AIOCB *, void *);
void aioStat(char *, struct stat *, AIOCB *, void *);
void aioUnlink(const char *, AIOCB *, void *);
void aioTruncate(const char *, off_t length, AIOCB *, void *);
unsigned int read_kicking:1;
unsigned int inreaddone:1;
} flags;
- const char *read_buf;
+ char *read_buf;
link_list *pending_writes;
link_list *pending_reads;
};
/*
- * $Id: store_dir_aufs.cc,v 1.51 2002/10/13 20:35:24 robertc Exp $
+ * $Id: store_dir_aufs.cc,v 1.52 2002/11/10 02:29:58 hno Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
void
storeAufsDirDump(StoreEntry * entry, SwapDir * s)
{
- commonUfsDirDump (entry, s);
+ commonUfsDirDump(entry, s);
dump_cachedir_options(entry, options, s);
}
#endif
static void storeAufsIOCallback(storeIOState * sio, int errflag);
static AIOCB storeAufsOpenDone;
-static int storeAufsSomethingPending(storeIOState *);
+static int storeAufsNeedCompletetion(storeIOState *);
static int storeAufsKickWriteQueue(storeIOState * sio);
static CBDUNL storeAufsIOFreeEntry;
squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
debug(79, 3) ("storeAufsClose: dirno %d, fileno %08X, FD %d\n",
sio->swap_dirn, sio->swap_filen, aiostate->fd);
- if (storeAufsSomethingPending(sio)) {
+ if (storeAufsNeedCompletetion(sio)) {
aiostate->flags.close_request = 1;
return;
}
q->size = size;
q->offset = offset;
q->callback = callback;
- q->callback_data = callback_data;
+ q->callback_data = cbdataReference(callback_data);
linklistPush(&(aiostate->pending_reads), q);
return;
}
sio->offset = offset;
aiostate->flags.reading = 1;
#if ASYNC_READ
- aioRead(aiostate->fd, offset, buf, size, storeAufsReadDone, sio);
+ aioRead(aiostate->fd, offset, size, storeAufsReadDone, sio);
#else
file_read(aiostate->fd, buf, size, offset, storeAufsReadDone, sio);
#endif
{
squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
struct _queued_read *q = (struct _queued_read *)linklistShift(&(aiostate->pending_reads));
+ void *cbdata;
if (NULL == q)
return 0;
debug(79, 3) ("storeAufsKickReadQueue: reading queued request of %ld bytes\n",
(long int) q->size);
- storeAufsRead(INDEXSD(sio->swap_dirn), sio, q->buf, q->size, q->offset, q->callback, q->callback_data);
+ if (cbdataReferenceValidDone(q->callback_data, &cbdata))
+ storeAufsRead(INDEXSD(sio->swap_dirn), sio, q->buf, q->size, q->offset, q->callback, cbdata);
memPoolFree(aufs_qread_pool, q);
return 1;
}
static void
-storeAufsOpenDone(int unused, void *my_data, int fd, int errflag)
+storeAufsOpenDone(int unused, void *my_data, const char *unused2, int fd, int errflag)
{
storeIOState *sio = (storeIOState *)my_data;
squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
if (FILE_MODE(sio->mode) == O_WRONLY) {
if (storeAufsKickWriteQueue(sio))
return;
- } else if (FILE_MODE(sio->mode) == O_RDONLY) {
+ } else if ((FILE_MODE(sio->mode) == O_RDONLY) && !aiostate->flags.close_request) {
if (storeAufsKickReadQueue(sio))
return;
}
#if ASYNC_READ
static void
-storeAufsReadDone(int fd, void *my_data, int len, int errflag)
+storeAufsReadDone(int fd, void *my_data, const char *buf, int len, int errflag)
#else
static void
storeAufsReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
STRCB *callback = sio->read.callback;
void *cbdata;
ssize_t rlen;
+ int inreaddone = aiostate->flags.inreaddone; /* Protect from callback loops */
debug(79, 3) ("storeAufsReadDone: dirno %d, fileno %08X, FD %d, len %d\n",
sio->swap_dirn, sio->swap_filen, fd, len);
aiostate->flags.inreaddone = 1;
#endif
assert(callback);
sio->read.callback = NULL;
- if (cbdataReferenceValidDone(sio->read.callback_data, &cbdata))
+ if (!aiostate->flags.close_request && cbdataReferenceValidDone(sio->read.callback_data, &cbdata)) {
+#if ASYNC_READ
+ if (rlen > 0)
+ memcpy(aiostate->read_buf, buf, rlen);
+#endif
callback(cbdata, aiostate->read_buf, rlen);
+ }
aiostate->flags.inreaddone = 0;
- if (aiostate->flags.close_request)
+ if (aiostate->flags.close_request && !inreaddone)
storeAufsIOCallback(sio, errflag);
}
squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
int fd = aiostate->fd;
debug(79, 3) ("storeAufsIOCallback: errflag=%d\n", errflag);
- debug(79, 3) ("%s:%d\n", __FILE__, __LINE__);
+ debug(79, 9) ("%s:%d\n", __FILE__, __LINE__);
if (callback) {
void *cbdata;
sio->callback = NULL;
if (cbdataReferenceValidDone(sio->callback_data, &cbdata))
callback(cbdata, errflag, sio);
}
- debug(79, 3) ("%s:%d\n", __FILE__, __LINE__);
+ debug(79, 9) ("%s:%d\n", __FILE__, __LINE__);
aiostate->fd = -1;
cbdataFree(sio);
if (fd < 0)
return;
- debug(79, 3) ("%s:%d\n", __FILE__, __LINE__);
+ debug(79, 9) ("%s:%d\n", __FILE__, __LINE__);
aioClose(fd);
fd_close(fd);
store_open_disk_fd--;
- debug(79, 3) ("%s:%d\n", __FILE__, __LINE__);
+ debug(79, 9) ("%s:%d\n", __FILE__, __LINE__);
}
static int
-storeAufsSomethingPending(storeIOState * sio)
+storeAufsNeedCompletetion(storeIOState * sio)
{
squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
- if (aiostate->flags.reading)
- return 1;
+
if (aiostate->flags.writing)
return 1;
- if (aiostate->flags.opening)
+ if (aiostate->flags.opening && FILE_MODE(sio->mode) == O_WRONLY)
return 1;
if (aiostate->flags.inreaddone)
return 1;
+
+ /* Note: Pending read operations are silently cancelled on close */
return 0;
}
* to bother with that.
*/
static void
-storeAufsIOFreeEntry(void *sio)
+storeAufsIOFreeEntry(void *siop)
{
- memPoolFree(squidaio_state_pool, ((storeIOState *) sio)->fsstate);
+ storeIOState *sio = (storeIOState *) siop;
+ squidaiostate_t *aiostate = (squidaiostate_t *) sio->fsstate;
+ struct _queued_write *qw;
+ struct _queued_read *qr;
+ while ((qw = linklistShift(&aiostate->pending_writes))) {
+ if (qw->free_func)
+ qw->free_func(qw->buf);
+ memPoolFree(aufs_qwrite_pool, qw);
+ }
+ while ((qr = linklistShift(&aiostate->pending_reads))) {
+ cbdataReferenceDone(qr->callback_data);
+ memPoolFree(aufs_qread_pool, qr);
+ }
+ if (sio->read.callback_data)
+ cbdataReferenceDone(sio->read.callback_data);
+ if (sio->callback_data)
+ cbdataReferenceDone(sio->callback_data);
+ memPoolFree(squidaio_state_pool, aiostate);
}