]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/fs/aufs/async_io.cc
Import of fix-ranges branch
[thirdparty/squid.git] / src / fs / aufs / async_io.cc
index 084b4c6130e3a746d70a9eb6c35cb8c82f26289c..02fe2020f2a75cb47592fb236e3971c62d862909 100644 (file)
@@ -1,22 +1,22 @@
 
 /*
- * $Id: async_io.cc,v 1.1 2000/05/03 17:15:46 adrian Exp $
+ * $Id: async_io.cc,v 1.22 2003/01/23 00:38:09 robertc Exp $
  *
  * DEBUG: section 32    Asynchronous Disk I/O
  * AUTHOR: Pete Bentley <pete@demon.net>
  * AUTHOR: Stewart Forster <slf@connect.com.au>
  *
- * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
  * ----------------------------------------------------------
  *
- *  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.
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; 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
 
 #include "squid.h"
 #include "store_asyncufs.h"
+#include "Store.h"
+#include "fde.h"
 
 #define _AIO_OPEN      0
 #define _AIO_READ      1
 #define _AIO_WRITE     2
 #define _AIO_CLOSE     3
 #define _AIO_UNLINK    4
+#define _AIO_TRUNCATE  4
 #define _AIO_OPENDIR   5
 #define _AIO_STAT      6
 
-typedef struct aio_ctrl_t {
-    struct aio_ctrl_t *next;
+typedef struct squidaio_ctrl_t {
+    struct squidaio_ctrl_t *next;
     int fd;
     int operation;
     AIOCB *done_handler;
     void *done_handler_data;
-    aio_result_t result;
-} aio_ctrl_t;
-
-struct {
-    int open;
-    int close;
+    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;
-    int read;
-    int stat;
-    int unlink;
+    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;
-} aio_counts;
+} squidaio_counts;
 
-typedef struct aio_unlinkq_t {
+typedef struct squidaio_unlinkq_t {
     char *path;
-    struct aio_unlinkq_t *next;
-} aio_unlinkq_t;
+    struct squidaio_unlinkq_t *next;
+} squidaio_unlinkq_t;
 
-static aio_ctrl_t *used_list = NULL;
+static dlink_list used_list;
 static int initialised = 0;
 static OBJH aioStats;
-static MemPool *aio_ctrl_pool;
+static MemPool *squidaio_ctrl_pool;
 static void aioFDWasClosed(int fd);
 
-MemPool * aio_state_pool;
-
 static void
 aioFDWasClosed(int fd)
 {
@@ -85,119 +96,94 @@ aioFDWasClosed(int fd)
        fd_close(fd);
 }
 
+
 void
 aioInit(void)
 {
     if (initialised)
        return;
-    aio_ctrl_pool = memPoolCreate("aio_ctrl", sizeof(aio_ctrl_t));
-    aio_state_pool = memPoolCreate("Async UFS IO State data", sizeof(aiostate_t));
-    cachemgrRegister("aio_counts", "Async IO Function Counters",
+    squidaio_ctrl_pool = memPoolCreate("aio_ctrl", sizeof(squidaio_ctrl_t));
+    cachemgrRegister("squidaio_counts", "Async IO Function Counters",
        aioStats, 0, 1);
     initialised = 1;
-    comm_quick_poll_required();
 }
 
 void
 aioDone(void)
 {
-    memPoolDestroy(aio_ctrl_pool);
-    memPoolDestroy(aio_state_pool);
+    memPoolDestroy(&squidaio_ctrl_pool);
     initialised = 0;
 }
 
 void
 aioOpen(const char *path, int oflag, mode_t mode, AIOCB * callback, void *callback_data)
 {
-    aio_ctrl_t *ctrlp;
-    int ret;
+    squidaio_ctrl_t *ctrlp;
 
     assert(initialised);
-    aio_counts.open++;
-    ctrlp = memPoolAlloc(aio_ctrl_pool);
+    squidaio_counts.open_start++;
+    ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool);
     ctrlp->fd = -2;
     ctrlp->done_handler = callback;
-    ctrlp->done_handler_data = callback_data;
+    ctrlp->done_handler_data = cbdataReference(callback_data);
     ctrlp->operation = _AIO_OPEN;
-    cbdataLock(callback_data);
-    if (aio_open(path, oflag, mode, &ctrlp->result) < 0) {
-       ret = open(path, oflag, mode);
-       if (callback)
-           (callback) (ctrlp->fd, callback_data, ret, errno);
-       cbdataUnlock(callback_data);
-       memPoolFree(aio_ctrl_pool, ctrlp);
-       return;
-    }
-    ctrlp->next = used_list;
-    used_list = ctrlp;
+    ctrlp->result.data = ctrlp;
+    squidaio_open(path, oflag, mode, &ctrlp->result);
+    dlinkAdd(ctrlp, &ctrlp->node, &used_list);
     return;
 }
 
 void
 aioClose(int fd)
 {
-    aio_ctrl_t *ctrlp;
+    squidaio_ctrl_t *ctrlp;
 
     assert(initialised);
-    aio_counts.close++;
+    squidaio_counts.close_start++;
     aioCancel(fd);
-    ctrlp = memPoolAlloc(aio_ctrl_pool);
+    ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool);
     ctrlp->fd = fd;
     ctrlp->done_handler = NULL;
     ctrlp->done_handler_data = NULL;
     ctrlp->operation = _AIO_CLOSE;
-    if (aio_close(fd, &ctrlp->result) < 0) {
-       close(fd);              /* Can't create thread - do a normal close */
-       memPoolFree(aio_ctrl_pool, ctrlp);
-       aioFDWasClosed(fd);
-       return;
-    }
-    ctrlp->next = used_list;
-    used_list = ctrlp;
+    ctrlp->result.data = ctrlp;
+    squidaio_close(fd, &ctrlp->result);
+    dlinkAdd(ctrlp, &ctrlp->node, &used_list);
     return;
 }
 
 void
 aioCancel(int fd)
 {
-    aio_ctrl_t *curr;
-    aio_ctrl_t *prev;
-    aio_ctrl_t *next;
-    AIOCB *done_handler;
-    void *their_data;
+    squidaio_ctrl_t *ctrlp;
+    dlink_node *m, *next;
 
     assert(initialised);
-    aio_counts.cancel++;
-    prev = NULL;
-    curr = used_list;
-    for (curr = used_list;; curr = next) {
-       while (curr != NULL) {
-           if (curr->fd == fd)
-               break;
-           prev = curr;
-           curr = curr->next;
-       }
-       if (curr == NULL)
-           break;
+    squidaio_counts.cancel++;
+    for (m = used_list.head; m; m = next) {
+       next = m->next;
+       ctrlp = (squidaio_ctrl_t *)m->data;
+       if (ctrlp->fd != fd)
+           continue;
 
-       aio_cancel(&curr->result);
+       squidaio_cancel(&ctrlp->result);
 
-       if ((done_handler = curr->done_handler)) {
-           their_data = curr->done_handler_data;
-           curr->done_handler = NULL;
-           curr->done_handler_data = NULL;
-           debug(0, 0) ("this be aioCancel\n");
-           if (cbdataValid(their_data))
-               done_handler(fd, their_data, -2, -2);
-           cbdataUnlock(their_data);
+       if (ctrlp->done_handler) {
+           AIOCB *callback = ctrlp->done_handler;
+           void *cbdata;
+           ctrlp->done_handler = NULL;
+           debug(32, 1) ("this be aioCancel. Danger ahead!\n");
+           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);
        }
-       next = curr->next;
-       if (prev == NULL)
-           used_list = next;
-       else
-           prev->next = next;
-
-       memPoolFree(aio_ctrl_pool, curr);
+       dlinkDelete(m, &used_list);
+       memPoolFree(squidaio_ctrl_pool, ctrlp);
     }
 }
 
@@ -205,222 +191,210 @@ aioCancel(int fd)
 void
 aioWrite(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data, FREE * free_func)
 {
-    aio_ctrl_t *ctrlp;
+    squidaio_ctrl_t *ctrlp;
     int seekmode;
 
     assert(initialised);
-    aio_counts.write++;
-    for (ctrlp = used_list; ctrlp != NULL; ctrlp = ctrlp->next)
-       if (ctrlp->fd == fd)
-           break;
-    if (ctrlp != NULL) {
-       debug(0, 0) ("aioWrite: EWOULDBLOCK\n");
-       errno = EWOULDBLOCK;
-       if (callback)
-           (callback) (fd, callback_data, -1, errno);
-       if (free_func)
-            free_func(bufp);
-       return;
-    }
-    ctrlp = memPoolAlloc(aio_ctrl_pool);
+    squidaio_counts.write_start++;
+    ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool);
     ctrlp->fd = fd;
     ctrlp->done_handler = callback;
-    ctrlp->done_handler_data = callback_data;
+    ctrlp->done_handler_data = cbdataReference(callback_data);
     ctrlp->operation = _AIO_WRITE;
+    ctrlp->bufp = bufp;
+    ctrlp->free_func = free_func;
     if (offset >= 0)
        seekmode = SEEK_SET;
     else {
        seekmode = SEEK_END;
        offset = 0;
     }
-    cbdataLock(callback_data);
-    if (aio_write(fd, bufp, len, offset, seekmode, &ctrlp->result) < 0) {
-       if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL)
-           errno = EWOULDBLOCK;
-       if (callback)
-           (callback) (fd, callback_data, -1, errno);
-       cbdataUnlock(callback_data);
-       memPoolFree(aio_ctrl_pool, ctrlp);
-    } else {
-       ctrlp->next = used_list;
-       used_list = ctrlp;
-    }
-    /*
-     * aio_write copies the buffer so we can free it here
-     */
-    if (free_func)
-        free_func(bufp);
+    ctrlp->result.data = ctrlp;
+    squidaio_write(fd, bufp, len, offset, seekmode, &ctrlp->result);
+    dlinkAdd(ctrlp, &ctrlp->node, &used_list);
 }                              /* aioWrite */
 
 
 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)
 {
-    aio_ctrl_t *ctrlp;
+    squidaio_ctrl_t *ctrlp;
     int seekmode;
 
     assert(initialised);
-    aio_counts.read++;
-    for (ctrlp = used_list; ctrlp != NULL; ctrlp = ctrlp->next)
-       if (ctrlp->fd == fd)
-           break;
-    if (ctrlp != NULL) {
-       errno = EWOULDBLOCK;
-       if (callback)
-           (callback) (fd, callback_data, -1, errno);
-       return;
-    }
-    ctrlp = memPoolAlloc(aio_ctrl_pool);
+    squidaio_counts.read_start++;
+    ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool);
     ctrlp->fd = fd;
     ctrlp->done_handler = callback;
-    ctrlp->done_handler_data = callback_data;
+    ctrlp->done_handler_data = cbdataReference(callback_data);
     ctrlp->operation = _AIO_READ;
+    ctrlp->len = len;
+    ctrlp->bufp = (char *)squidaio_xmalloc(len);
     if (offset >= 0)
        seekmode = SEEK_SET;
     else {
        seekmode = SEEK_CUR;
        offset = 0;
     }
-    cbdataLock(callback_data);
-    if (aio_read(fd, bufp, len, offset, seekmode, &ctrlp->result) < 0) {
-       if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL)
-           errno = EWOULDBLOCK;
-       if (callback)
-           (callback) (fd, callback_data, -1, errno);
-       cbdataUnlock(callback_data);
-       memPoolFree(aio_ctrl_pool, ctrlp);
-       return;
-    }
-    ctrlp->next = used_list;
-    used_list = ctrlp;
+    ctrlp->result.data = ctrlp;
+    squidaio_read(fd, ctrlp->bufp, len, offset, seekmode, &ctrlp->result);
+    dlinkAdd(ctrlp, &ctrlp->node, &used_list);
     return;
 }                              /* aioRead */
 
 void
 aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data)
 {
-    aio_ctrl_t *ctrlp;
+    squidaio_ctrl_t *ctrlp;
 
     assert(initialised);
-    aio_counts.stat++;
-    ctrlp = memPoolAlloc(aio_ctrl_pool);
+    squidaio_counts.stat_start++;
+    ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool);
     ctrlp->fd = -2;
     ctrlp->done_handler = callback;
-    ctrlp->done_handler_data = callback_data;
+    ctrlp->done_handler_data = cbdataReference(callback_data);
     ctrlp->operation = _AIO_STAT;
-    cbdataLock(callback_data);
-    if (aio_stat(path, sb, &ctrlp->result) < 0) {
-       if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL)
-           errno = EWOULDBLOCK;
-       if (callback)
-           (callback) (ctrlp->fd, callback_data, -1, errno);
-       cbdataUnlock(callback_data);
-       memPoolFree(aio_ctrl_pool, ctrlp);
-       return;
-    }
-    ctrlp->next = used_list;
-    used_list = ctrlp;
+    ctrlp->result.data = ctrlp;
+    squidaio_stat(path, sb, &ctrlp->result);
+    dlinkAdd(ctrlp, &ctrlp->node, &used_list);
     return;
 }                              /* aioStat */
 
 void
-aioUnlink(const char *pathname, AIOCB * callback, void *callback_data)
+aioUnlink(const char *path, AIOCB * callback, void *callback_data)
 {
-    aio_ctrl_t *ctrlp;
-    char *path;
+    squidaio_ctrl_t *ctrlp;
     assert(initialised);
-    aio_counts.unlink++;
-    ctrlp = memPoolAlloc(aio_ctrl_pool);
+    squidaio_counts.unlink_start++;
+    ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool);
     ctrlp->fd = -2;
     ctrlp->done_handler = callback;
-    ctrlp->done_handler_data = callback_data;
+    ctrlp->done_handler_data = cbdataReference(callback_data);
     ctrlp->operation = _AIO_UNLINK;
-    path = xstrdup(pathname);
-    cbdataLock(callback_data);
-    if (aio_unlink(path, &ctrlp->result) < 0) {
-       int ret = unlink(path);
-       (callback) (ctrlp->fd, callback_data, ret, errno);
-       cbdataUnlock(callback_data);
-       memPoolFree(aio_ctrl_pool, ctrlp);
-       xfree(path);
-       return;
-    }
-    ctrlp->next = used_list;
-    used_list = ctrlp;
-    xfree(path);
+    ctrlp->result.data = ctrlp;
+    squidaio_unlink(path, &ctrlp->result);
+    dlinkAdd(ctrlp, &ctrlp->node, &used_list);
 }                              /* aioUnlink */
 
-
 void
-aioCheckCallbacks(SwapDir *SD)
+aioTruncate(const char *path, off_t length, AIOCB * callback, void *callback_data)
 {
-    aio_result_t *resultp;
-    aio_ctrl_t *ctrlp;
-    aio_ctrl_t *prev;
-    AIOCB *done_handler;
-    void *their_data;
+    squidaio_ctrl_t *ctrlp;
+    assert(initialised);
+    squidaio_counts.unlink_start++;
+    ctrlp = (squidaio_ctrl_t *)memPoolAlloc(squidaio_ctrl_pool);
+    ctrlp->fd = -2;
+    ctrlp->done_handler = callback;
+    ctrlp->done_handler_data = cbdataReference(callback_data);
+    ctrlp->operation = _AIO_TRUNCATE;
+    ctrlp->result.data = ctrlp;
+    squidaio_truncate(path, length, &ctrlp->result);
+    dlinkAdd(ctrlp, &ctrlp->node, &used_list);
+}                              /* aioTruncate */
+
+
+int
+AUFSSwapDir::callback()
+{
+    squidaio_result_t *resultp;
+    squidaio_ctrl_t *ctrlp;
+    int retval = 0;
 
     assert(initialised);
-    aio_counts.check_callback++;
+    squidaio_counts.check_callback++;
     for (;;) {
-       if ((resultp = aio_poll_done()) == NULL)
+       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;
-       prev = NULL;
-       for (ctrlp = used_list; ctrlp != NULL; prev = ctrlp, ctrlp = ctrlp->next)
-           if (&ctrlp->result == resultp)
-               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;
-       if (prev == NULL)
-           used_list = ctrlp->next;
-       else
-           prev->next = ctrlp->next;
-       if ((done_handler = ctrlp->done_handler)) {
-           their_data = ctrlp->done_handler_data;
+           continue;           /* XXX Should not happen */
+       dlinkDelete(&ctrlp->node, &used_list);
+       if (ctrlp->done_handler) {
+           AIOCB *callback = ctrlp->done_handler;
+           void *cbdata;
            ctrlp->done_handler = NULL;
-           ctrlp->done_handler_data = NULL;
-           if (cbdataValid(their_data))
-               done_handler(ctrlp->fd, their_data,
+           if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) {
+               retval = 1;     /* Return that we've actually done some work */
+               callback(ctrlp->fd, cbdata, ctrlp->bufp,
                    ctrlp->result.aio_return, ctrlp->result.aio_errno);
-           cbdataUnlock(their_data);
+           } 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(aio_ctrl_pool, ctrlp);
+       memPoolFree(squidaio_ctrl_pool, ctrlp);
     }
+    return retval;
 }
 
 void
 aioStats(StoreEntry * sentry)
 {
     storeAppendPrintf(sentry, "ASYNC IO Counters:\n");
-    storeAppendPrintf(sentry, "open\t%d\n", aio_counts.open);
-    storeAppendPrintf(sentry, "close\t%d\n", aio_counts.close);
-    storeAppendPrintf(sentry, "cancel\t%d\n", aio_counts.cancel);
-    storeAppendPrintf(sentry, "write\t%d\n", aio_counts.write);
-    storeAppendPrintf(sentry, "read\t%d\n", aio_counts.read);
-    storeAppendPrintf(sentry, "stat\t%d\n", aio_counts.stat);
-    storeAppendPrintf(sentry, "unlink\t%d\n", aio_counts.unlink);
-    storeAppendPrintf(sentry, "check_callback\t%d\n", aio_counts.check_callback);
-    storeAppendPrintf(sentry, "queue\t%d\n", aio_get_queue_len());
+    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, "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, "check_callback\t%d\t-\n", squidaio_counts.check_callback);
+    storeAppendPrintf(sentry, "queue\t%d\t-\n", squidaio_get_queue_len());
 }
 
 /* Flush all pending I/O */
 void
-aioSync(SwapDir *SD)
+AUFSSwapDir::sync()
 {
     if (!initialised)
        return;                 /* nothing to do then */
     /* Flush all pending operations */
     debug(32, 1) ("aioSync: flushing pending I/O operations\n");
     do {
-       aioCheckCallbacks(SD);
-    } while (aio_sync());
+       callback();
+    } while (squidaio_sync());
     debug(32, 1) ("aioSync: done\n");
 }
 
 int
 aioQueueSize(void)
 {
-    return memPoolInUseCount(aio_ctrl_pool);
+    return memPoolInUseCount(squidaio_ctrl_pool);
 }