This is a multi-part message in MIME format.
--------------61503C0C19036D7147A0C340
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Oops ;-)
Here is a in large parts reworked patch for async I/O. This replaces all
of my previous async-io patch (which was messy and broken).
* The read offset was not preserved, corrupting deferred hits on
pipelined connections.
* Main <-> I/O thread communication is done using a single request
pointer, optionally protected by a mutex.
* CPU spin situation solved in two possible ways: Either by properly
protecting the condition variable using a mutex, or by increasing the
timeout-time on each timeout instead of relying on squid_curtime.
* Use a 50 msec select timeout for ASYNC_IO to keep things flowing
nicely.
* Check for completed threads when the request queue grows. Completed
requests are put on a FIFO queue until processed from the main loop.
This is done to more quickly reuse of finished threads.
* Fixed a silly bug in my last version of this patch. No idea how the
last patch could pass my tests...
* Avoid pointer aliasing. Some compilers/optimisations have trouble with
this (the old code was probably safe, but..).
* Some minor code cleanups.
* This patch is not messed up ;-)
* Removed compiler warnings
- No more SIGCONT signal hack or cross-level hints. This was a bad move
both on performance and code design.
- Mutex signalling is optional (-DAIO_PROPER_MUTEX). Using a volatile
pointer should be safe on most/all platforms.
This patch is quite heavily tested, and seems to perform well.
I still haven't found the cause to another async-io problem. When
async-io is enabled Squid only caches about 1/2 of the requests in my
tests. Without async-io everything gets cached as expected. I have
verified that this problem in present in a unpatched b20-1 and is not
caused by this patch or any of the other 1.2b20-1 changes I have made.
Comments are welcome, as always.
/Henrik
--------------61503C0C19036D7147A0C340
Content-Type: text/plain; charset=us-ascii; name="squid-1.2.beta20-1.asyncio.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="squid-1.2.beta20-1.asyncio.patch"
Index: squid/src/protos.h
diff -u squid/src/protos.h:1.1.1.19 squid/src/protos.h:1.1.1.19.2.3
--- squid/src/protos.h:1.1.1.19	Sat Apr 25 14:47:53 1998
+++ squid/src/protos.h	Mon May  4 22:42:54 1998
@@ -48,8 +48,8 @@
 extern void aioCancel(int, void *);
 extern void aioOpen(const char *, int, mode_t, AIOCB *, void *, void *);
 extern void aioClose(int);
-extern void aioWrite(int, char *, int, AIOCB *, void *);
-extern void aioRead(int, char *, int, AIOCB *, void *);
+extern void aioWrite(int, int offset, char *, int size, AIOCB *, void *);
+extern void aioRead(int, int offset, char *, int size, AIOCB *, void *);
 extern void aioStat(char *, struct stat *, AIOCB *, void *, void *);
 extern void aioUnlink(const char *, AIOCB *, void *);
 extern void aioCheckCallbacks(void);
Index: squid/src/comm.c
diff -u squid/src/comm.c:1.1.1.19 squid/src/comm.c:1.1.1.19.2.2
--- squid/src/comm.c:1.1.1.19	Sat Apr 25 14:47:46 1998
+++ squid/src/comm.c	Thu May  7 19:59:53 1998
@@ -1066,8 +1066,13 @@
         if (nfds == 0)
             return COMM_SHUTDOWN;
         for (;;) {
+#if USE_ASYNC_IO
+	    poll_time.tv_sec = 0;
+	    poll_time.tv_usec = sec > 0 ? 50 : 0;
+#else
             poll_time.tv_sec = sec > 0 ? 1 : 0;
             poll_time.tv_usec = 0;
+#endif
             num = select(maxfd, &readfds, &writefds, NULL, &poll_time);
             Counter.select_loops++;
             if (num >= 0)
Index: squid/src/aiops.c
diff -u squid/src/aiops.c:1.1.1.7 squid/src/aiops.c:1.1.1.7.8.6
--- squid/src/aiops.c:1.1.1.7	Tue Mar 24 20:00:11 1998
+++ squid/src/aiops.c	Fri May  8 22:22:30 1998
@@ -1,4 +1,3 @@
-
 /*
  * $Id$
  *
@@ -43,22 +42,27 @@
 #define	NUMTHREADS		16
 #define RIDICULOUS_LENGTH	4096
 
-#define _THREAD_STARTING	0
-#define _THREAD_WAITING		1
-#define _THREAD_BUSY		2
-#define _THREAD_FAILED		3
-
-
-#define _AIO_OP_OPEN	0
-#define _AIO_OP_READ	1
-#define _AIO_OP_WRITE	2
-#define _AIO_OP_CLOSE	3
-#define _AIO_OP_UNLINK	4
-#define _AIO_OP_OPENDIR	5
-#define _AIO_OP_STAT	6
+enum _aio_thread_status {
+	_THREAD_STARTING=0,
+	_THREAD_WAITING,
+	_THREAD_BUSY,
+	_THREAD_FAILED,
+	_THREAD_DONE,
+};
+
+enum _aio_request_type {
+	_AIO_OP_NONE=0,
+	_AIO_OP_OPEN,
+	_AIO_OP_READ,
+	_AIO_OP_WRITE,
+	_AIO_OP_CLOSE,
+	_AIO_OP_UNLINK,
+	_AIO_OP_OPENDIR,
+	_AIO_OP_STAT,
+};
 
 typedef struct aio_request_t {
-    int request_type;
+    enum _aio_request_type request_type;
     int cancelled;
     char *path;
     int oflag;
@@ -80,11 +84,11 @@
 
 typedef struct aio_thread_t {
     pthread_t thread;
-    int status;
+    enum _aio_thread_status status;
     pthread_mutex_t mutex;	/* Mutex for testing condition variable */
     pthread_cond_t cond;	/* Condition variable */
-    struct aio_request_t *req;
-    struct aio_request_t *donereq;
+    struct aio_request_t *volatile req; /* set by main, cleared by thread */
+    struct aio_request_t *processed_req; /* reminder to main */
     struct aio_thread_t *next;
 } aio_thread_t;
 
@@ -99,22 +103,21 @@
 aio_result_t *aio_poll_done();
 
 static void aio_init(void);
-static void aio_free_thread(aio_thread_t *);
-static void aio_cleanup_and_free(aio_thread_t *);
 static void aio_queue_request(aio_request_t *);
 static void aio_process_request_queue(void);
 static void aio_cleanup_request(aio_request_t *);
 static void *aio_thread_loop(void *);
-static void aio_thread_open(aio_thread_t *);
-static void aio_thread_read(aio_thread_t *);
-static void aio_thread_write(aio_thread_t *);
-static void aio_thread_close(aio_thread_t *);
-static void aio_thread_stat(aio_thread_t *);
-static void aio_thread_unlink(aio_thread_t *);
+static void aio_do_open(aio_request_t *);
+static void aio_do_read(aio_request_t *);
+static void aio_do_write(aio_request_t *);
+static void aio_do_close(aio_request_t *);
+static void aio_do_stat(aio_request_t *);
+static void aio_do_unlink(aio_request_t *);
 #if AIO_OPENDIR
-static void *aio_thread_opendir(void *);
+static void *aio_do_opendir(aio_request_t *);
 #endif
 static void aio_debug(aio_request_t *);
+static void aio_poll_threads(void);
 
 static aio_thread_t thread[NUMTHREADS];
 static int aio_initialised = 0;
@@ -124,17 +127,19 @@
 static int num_free_requests = 0;
 static aio_request_t *request_queue_head = NULL;
 static aio_request_t *request_queue_tail = NULL;
+static aio_request_t *request_done_head = NULL;
+static aio_request_t *request_done_tail = NULL;
 static aio_thread_t *wait_threads = NULL;
 static aio_thread_t *busy_threads_head = NULL;
 static aio_thread_t *busy_threads_tail = NULL;
 static pthread_attr_t globattr;
 static struct sched_param globsched;
+static pthread_t main_thread;
 
 static void
 aio_init(void)
 {
     int i;
-    pthread_t self;
     aio_thread_t *threadp;
 
     if (aio_initialised)
@@ -143,8 +148,8 @@
     pthread_attr_init(&globattr);
     pthread_attr_setscope(&globattr, PTHREAD_SCOPE_SYSTEM);
     globsched.sched_priority = 1;
-    self = pthread_self();
-    pthread_setschedparam(self, SCHED_OTHER, &globsched);
+    main_thread = pthread_self();
+    pthread_setschedparam(main_thread, SCHED_OTHER, &globsched);
     globsched.sched_priority = 2;
     pthread_attr_setschedparam(&globattr, &globsched);
 
@@ -162,7 +167,7 @@
             continue;
         }
         threadp->req = NULL;
-	threadp->donereq = NULL;
+	threadp->processed_req = NULL;
         if (pthread_create(&(threadp->thread), &globattr, aio_thread_loop, threadp)) {
             fprintf(stderr, "Thread creation failed\n");
             threadp->status = _THREAD_FAILED;
@@ -170,6 +175,9 @@
         }
         threadp->next = wait_threads;
         wait_threads = threadp;
+#if AIO_PROPER_MUTEX
+	pthread_mutex_lock(&threadp->mutex);
+#endif
     }
 
     aio_initialised = 1;
@@ -181,9 +189,10 @@
 {
     aio_thread_t *threadp = (aio_thread_t *) ptr;
     aio_request_t *request;
-    struct timespec abstime;
-    int ret;
     sigset_t new;
+#if !AIO_PROPER_MUTEX
+    struct timespec wait_time;
+#endif
 
     /* Make sure to ignore signals which may possibly get sent to the parent */
     /* squid thread.  Causes havoc with mutex's and condition waits otherwise */
@@ -199,54 +208,66 @@
     sigaddset(&new, SIGALRM);
     pthread_sigmask(SIG_BLOCK, &new, NULL);
 
+    pthread_mutex_lock(&threadp->mutex);
     while (1) {
-	/* BELOW is done because Solaris 2.5.1 doesn't support semaphores!!! */
-	/* Use timed wait to avoid race where thread context switches after */
-	/* threadp->status gets set but before the condition wait happens. */
-	/* In that case, a race occurs when the parent signals the condition */
-	/* but this thread will never receive it.  Recheck every 2-3 secs. */
-	/* Also provides bonus of keeping thread contexts hot in CPU cache */
-	/* (ie. faster thread reactions) at slight expense of CPU time. */
+#if AIO_PROPER_MUTEX
+	while (threadp->req == NULL) {
+	    threadp->status = _THREAD_WAITING;
+	    pthread_cond_wait(&(threadp->cond), &(threadp->mutex));
+	}
+#else
+	/* The timeout is used to unlock the race condition where
+	 * ->req is set between the check and pthread_cond_wait.
+	 * The thread steps it's own clock on each timeout, to avoid a CPU
+	 * spin situation if the main thread is suspended (paging), and
+	 * squid_curtime is not being updated timely.
+	 */
+	wait_time.tv_sec = squid_curtime + 1; /* little quicker first time */
+	wait_time.tv_nsec = 0;
         while (threadp->req == NULL) {
-	    abstime.tv_sec = squid_curtime + 3;
-	    abstime.tv_nsec = 0;
             threadp->status = _THREAD_WAITING;
-	    ret = pthread_cond_timedwait(&(threadp->cond),
-		&(threadp->mutex),
-		&abstime);
+	    pthread_cond_timedwait(&(threadp->cond), &(threadp->mutex),
+		&wait_time);
+	    wait_time.tv_sec += 3; /* then wait 3 seconds between each check */
         }
+#endif
         request = threadp->req;
-	switch (request->request_type) {
-	case _AIO_OP_OPEN:
-	    aio_thread_open(threadp);
-	    break;
-	case _AIO_OP_READ:
-	    aio_thread_read(threadp);
-	    break;
-	case _AIO_OP_WRITE:
-	    aio_thread_write(threadp);
-	    break;
-	case _AIO_OP_CLOSE:
-	    aio_thread_close(threadp);
-	    break;
-	case _AIO_OP_UNLINK:
-	    aio_thread_unlink(threadp);
-	    break;
-#if AIO_OPENDIR
-	    /* Opendir not implemented yet */
-	case _AIO_OP_OPENDIR:
-	    aio_thread_opendir(threadp);
-	    break;
+	errno = 0;
+	if (!request->cancelled) {
+	    switch (request->request_type) {
+	    case _AIO_OP_OPEN:
+		aio_do_open(request);
+		break;
+	    case _AIO_OP_READ:
+		aio_do_read(request);
+		break;
+	    case _AIO_OP_WRITE:
+		aio_do_write(request);
+		break;
+	    case _AIO_OP_CLOSE:
+		aio_do_close(request);
+		break;
+	    case _AIO_OP_UNLINK:
+		aio_do_unlink(request);
+		break;
+#if AIO_OPENDIR /* Opendir not implemented yet */
+	    case _AIO_OP_OPENDIR:
+		aio_do_opendir(request);
+		break;
 #endif
-	case _AIO_OP_STAT:
-	    aio_thread_stat(threadp);
-	    break;
-	default:
-	    threadp->donereq->ret = -1;
-	    threadp->donereq->err = EINVAL;
-	    break;
+	    case _AIO_OP_STAT:
+		aio_do_stat(request);
+		break;
+	    default:
+		request->ret = -1;
+		request->err = EINVAL;
+		break;
+	    }
+	} else {  /* cancelled */
+	    request->ret = -1;
+	    request->err = EINTR;
         }
-	threadp->req = NULL;
+	threadp->req = NULL;	/* tells main thread that we are done */
     }				/* while */
 }				/* aio_thread_loop */
 
@@ -259,6 +280,7 @@
     if ((req = free_requests) != NULL) {
         free_requests = req->next;
         num_free_requests--;
+	req->next = NULL;
         return req;
     }
     return (aio_request_t *) xmalloc(sizeof(aio_request_t));
@@ -272,11 +294,13 @@
     /* it reflects the sort of load the squid server will experience.  A */
     /* higher load will mean a need for more threads, which will in turn mean */
     /* a need for a bigger free request pool. */
+    /* Threads <-> requests are now partially asyncronous, use NUMTHREADS * 2 */
 
-    if (num_free_requests >= NUMTHREADS) {
+    if (num_free_requests >= NUMTHREADS * 2) {
         xfree(req);
         return;
     }
+    memset(req,0,sizeof(*req));
     req->next = free_requests;
     free_requests = req;
     num_free_requests++;
@@ -286,8 +310,6 @@
 static void
 aio_do_request(aio_request_t * requestp)
 {
-    aio_thread_t *threadp;
-
     if (wait_threads == NULL && busy_threads_head == NULL) {
         fprintf(stderr, "PANIC: No threads to service requests with!\n");
         exit(-1);
@@ -312,9 +334,12 @@
         request_queue_tail = requestp;
     }
     requestp->next = NULL;
-    if (++request_queue_len > NUMTHREADS) {
+    request_queue_len += 1;
+    if (wait_threads==NULL)
+	aio_poll_threads();
+    if (wait_threads==NULL) {
         if (squid_curtime > (last_warn + 15)) {
-	    debug(43, 1) ("aio_queue_request: WARNING - Async request queue growing: Length = %d\n", request_queue_len);
+	    debug(43, 1) ("aio_queue_request: WARNING - Out of service threads. Queue Length = %d\n", request_queue_len);
             debug(43, 1) ("aio_queue_request: Perhaps you should increase NUMTHREADS in aiops.c\n");
             debug(43, 1) ("aio_queue_request: First %d items on request queue\n", NUMTHREADS);
             rp = request_queue_head;
@@ -367,8 +392,9 @@
             return;
 
         requestp = request_queue_head;
-	if ((request_queue_head = request_queue_head->next) == NULL)
+	if ((request_queue_head = requestp->next) == NULL)
             request_queue_tail = NULL;
+	requestp->next = NULL;
         request_queue_len--;
 
         if (requestp->cancelled) {
@@ -376,19 +402,21 @@
             continue;
         }
         threadp = wait_threads;
-	wait_threads = wait_threads->next;
+	wait_threads = threadp->next;
+	threadp->next = NULL;
 
-	threadp->req = requestp;
-	threadp->donereq = requestp;
         if (busy_threads_head != NULL)
             busy_threads_tail->next = threadp;
         else
             busy_threads_head = threadp;
         busy_threads_tail = threadp;
-	threadp->next = NULL;
 
         threadp->status = _THREAD_BUSY;
+	threadp->req = threadp->processed_req =  requestp;
         pthread_cond_signal(&(threadp->cond));
+#if AIO_PROPER_MUTEX
+	pthread_mutex_unlock(&threadp->mutex);
+#endif
     }
 }				/* aio_process_request_queue */
 
@@ -420,7 +448,7 @@
     default:
         break;
     }
-    if (!cancelled) {
+    if (resultp != NULL && !cancelled) {
         resultp->aio_return = requestp->ret;
         resultp->aio_errno = requestp->err;
     }
@@ -433,15 +461,26 @@
 {
     aio_thread_t *threadp;
     aio_request_t *requestp;
-    int ret;
 
     for (threadp = busy_threads_head; threadp != NULL; threadp = threadp->next)
-	if (threadp->donereq->resultp == resultp)
-	    threadp->donereq->cancelled = 1;
+	if (threadp->processed_req->resultp == resultp) {
+	    threadp->processed_req->cancelled = 1;
+	    threadp->processed_req->resultp = NULL;
+	    return 0;
+	}
     for (requestp = request_queue_head; requestp != NULL; requestp = requestp->next)
-	if (requestp->resultp == resultp)
+	if (requestp->resultp == resultp) {
             requestp->cancelled = 1;
-    return 0;
+	    requestp->resultp = NULL;
+	    return 0;
+	}
+    for (requestp = request_done_head; requestp != NULL; requestp = requestp->next)
+	if (requestp->resultp == resultp) {
+	    requestp->cancelled = 1;
+	    requestp->resultp = NULL;
+	    return 0;
+	}
+    return 1;
 }				/* aio_cancel */
 
 
@@ -476,10 +515,8 @@
 
 
 static void
-aio_thread_open(aio_thread_t * threadp)
+aio_do_open(aio_request_t *requestp)
 {
-    aio_request_t *requestp = threadp->req;
-
     requestp->ret = open(requestp->path, requestp->oflag, requestp->mode);
     requestp->err = errno;
 }
@@ -516,10 +553,8 @@
 
 
 static void
-aio_thread_read(aio_thread_t * threadp)
+aio_do_read(aio_request_t * requestp)
 {
-    aio_request_t *requestp = threadp->req;
-
     lseek(requestp->fd, requestp->offset, requestp->whence);
     requestp->ret = read(requestp->fd, requestp->tmpbufp, requestp->buflen);
     requestp->err = errno;
@@ -557,10 +592,8 @@
 
 
 static void
-aio_thread_write(aio_thread_t * threadp)
+aio_do_write(aio_request_t *requestp)
 {
-    aio_request_t *requestp = threadp->req;
-
     requestp->ret = write(requestp->fd, requestp->tmpbufp, requestp->buflen);
     requestp->err = errno;
 }
@@ -588,10 +621,8 @@
 
 
 static void
-aio_thread_close(aio_thread_t * threadp)
+aio_do_close(aio_request_t *requestp)
 {
-    aio_request_t *requestp = threadp->req;
-
     requestp->ret = close(requestp->fd);
     requestp->err = errno;
 }
@@ -633,10 +664,8 @@
 
 
 static void
-aio_thread_stat(aio_thread_t * threadp)
+aio_do_stat(aio_request_t *requestp)
 {
-    aio_request_t *requestp = threadp->req;
-
     requestp->ret = stat(requestp->path, requestp->tmpstatp);
     requestp->err = errno;
 }
@@ -671,10 +700,8 @@
 
 
 static void
-aio_thread_unlink(aio_thread_t * threadp)
+aio_do_unlink(aio_request_t *requestp)
 {
-    aio_request_t *requestp = threadp->req;
-
     requestp->ret = unlink(requestp->path);
     requestp->err = errno;
 }
@@ -698,60 +725,96 @@
     return -1;
 }
 
-static void *
-aio_thread_opendir(aio_thread_t * threadp)
+static void
+aio_do_opendir(aio_request_t *requestp)
 {
-    aio_request_t *requestp = threadp->req;
-    aio_result_t *resultp = requestp->resultp;
-
-    return threadp;
+    /* NOT IMPLEMENTED */
 }
 #endif
 
 
-aio_result_t *
-aio_poll_done()
+void
+aio_poll_threads(void)
 {
     aio_thread_t *prev;
     aio_thread_t *threadp;
     aio_request_t *requestp;
+
+    do { /* while found completed thread */
+	prev = NULL;
+	threadp = busy_threads_head;
+	while (threadp) {
+	    debug(43, 3) ("%d: %d -> %d\n",
+		threadp->thread,
+		threadp->req->request_type,
+		threadp->status);
+#if AIO_PROPER_MUTEX
+	    if (threadp->req == NULL)
+		if (pthread_mutex_trylock(&threadp->mutex) == 0)
+		    break;
+#else
+	    if (threadp->req == NULL)
+		break;
+#endif
+	    prev = threadp;
+	    threadp = threadp->next;
+	}
+	if (threadp == NULL)
+	    return;
+
+	if (prev == NULL)
+	    busy_threads_head = busy_threads_head->next;
+	else
+	    prev->next = threadp->next;
+
+	if (busy_threads_tail == threadp)
+	    busy_threads_tail = prev;
+
+	requestp = threadp->processed_req;
+	threadp->processed_req = NULL;
+
+	threadp->next = wait_threads;
+	wait_threads = threadp;
+
+	if (request_done_tail != NULL)
+	    request_done_tail->next = requestp;
+	else
+	    request_done_head = requestp;
+	request_done_tail = requestp;
+    } while(threadp);
+
+    aio_process_request_queue();
+}				/* aio_poll_threads */
+
+aio_result_t *
+aio_poll_done()
+{
+    aio_request_t *requestp, *prev;
     aio_result_t *resultp;
     int cancelled;
 
   AIO_REPOLL:
+    aio_poll_threads();
+    if (request_done_head == NULL) {
+	return NULL;
+    }
     prev = NULL;
-    threadp = busy_threads_head;
-    while (threadp) {
-	debug(43, 3) ("%d: %d -> %d\n",
-	    threadp->thread,
-	    threadp->donereq->request_type,
-	    threadp->status);
-	if (!threadp->req)
-	    break;
-	prev = threadp;
-	threadp = threadp->next;
+    requestp = request_done_head;
+    while (requestp->next) {
+	prev = requestp;
+	requestp = requestp->next;
     }
-    if (threadp == NULL)
-	return NULL;
-
     if (prev == NULL)
-	busy_threads_head = busy_threads_head->next;
+	request_done_head = requestp->next;
     else
-	prev->next = threadp->next;
+	prev->next = requestp->next;
+    request_done_tail = prev;
 
-    if (busy_threads_tail == threadp)
-	busy_threads_tail = prev;
-
-    requestp = threadp->donereq;
-    threadp->donereq = NULL;
     resultp = requestp->resultp;
+    cancelled = requestp->cancelled;
     aio_debug(requestp);
     debug(43, 3) ("DONE: %d -> %d\n", requestp->ret, requestp->err);
-    threadp->next = wait_threads;
-    wait_threads = threadp;
-    cancelled = requestp->cancelled;
     aio_cleanup_request(requestp);
-    aio_process_request_queue();
     if (cancelled)
         goto AIO_REPOLL;
     return resultp;
Index: squid/src/async_io.c
diff -u squid/src/async_io.c:1.1.1.4 squid/src/async_io.c:1.1.1.4.16.1
--- squid/src/async_io.c:1.1.1.4	Thu Feb  5 22:44:58 1998
+++ squid/src/async_io.c	Mon May  4 22:45:23 1998
@@ -189,9 +189,10 @@
 
 
 void
-aioWrite(int fd, char *bufp, int len, AIOCB * callback, void *callback_data)
+aioWrite(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data)
 {
     aio_ctrl_t *ctrlp;
+    int seekmode;
 
     if (!initialised)
         aioInit();
@@ -216,7 +217,13 @@
     ctrlp->done_handler = callback;
     ctrlp->done_handler_data = callback_data;
     ctrlp->operation = _AIO_WRITE;
-    if (aio_write(fd, bufp, len, 0, SEEK_END, &(ctrlp->result)) < 0) {
+    if (offset >= 0)
+	seekmode = SEEK_SET;
+    else {
+	seekmode = SEEK_END;
+	offset = 0;
+    }
+    if (aio_write(fd, bufp, len, offset, seekmode, &(ctrlp->result)) < 0) {
         if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL)
             errno = EWOULDBLOCK;
         if (callback)
@@ -231,9 +238,10 @@
 
 
 void
-aioRead(int fd, char *bufp, int len, AIOCB * callback, void *callback_data)
+aioRead(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data)
 {
     aio_ctrl_t *ctrlp;
+    int seekmode;
 
     if (!initialised)
         aioInit();
@@ -258,7 +266,13 @@
     ctrlp->done_handler = callback;
     ctrlp->done_handler_data = callback_data;
     ctrlp->operation = _AIO_READ;
-    if (aio_read(fd, bufp, len, 0, SEEK_CUR, &(ctrlp->result)) < 0) {
+    if (offset >= 0)
+	seekmode = SEEK_SET;
+    else {
+	seekmode = SEEK_CUR;
+	offset = 0;
+    }
+    if (aio_read(fd, bufp, len, offset, seekmode, &(ctrlp->result)) < 0) {
         if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL)
             errno = EWOULDBLOCK;
         if (callback)
Index: squid/src/disk.c
diff -u squid/src/disk.c:1.1.1.10 squid/src/disk.c:1.1.1.10.6.1
--- squid/src/disk.c:1.1.1.10	Wed Apr  8 22:07:11 1998
+++ squid/src/disk.c	Mon May  4 22:46:46 1998
@@ -241,6 +241,7 @@
     debug(6, 3) ("diskHandleWrite: FD %d\n", fd);
     /* We need to combine subsequent write requests after the first */
     /* But only if we don't need to seek() in betwen them, ugh! */
+    /* XXX This currently ignores any seeks (file_offset) */
     if (fdd->write_q->next != NULL && fdd->write_q->next->next != NULL) {
         len = 0;
         for (q = fdd->write_q->next; q != NULL; q = q->next)
@@ -273,6 +274,7 @@
     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,
@@ -480,6 +482,7 @@
     ctrlp->data = ctrl_dat;
 #if USE_ASYNC_IO
     aioRead(fd,
+	ctrl_dat->offset,
         ctrl_dat->buf,
         ctrl_dat->req_len,
         diskHandleReadComplete,
--------------61503C0C19036D7147A0C340--
Received on Tue Jul 29 2003 - 13:15:49 MDT
This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:11:47 MST