Update.
authorUlrich Drepper <drepper@redhat.com>
Thu, 27 Jul 2000 09:43:12 +0000 (09:43 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 27 Jul 2000 09:43:12 +0000 (09:43 +0000)
2000-07-26  Andreas Jaeger  <aj@suse.de>

* rt/tst-aio.c: Add tests for aio_fsync and aio_cancel.
(do_wait): Test requests with aio_return.
(do_test): Change callers of do_wait.

2000-07-27  Ulrich Drepper  <drepper@redhat.com>

* rt/aio_misc.c (__aio_remove_request): New function.  Handle removing
from request list.  Don't do the list handling here, call
__aio_remove_request.
* rt/aio_misc.h: Add prototype for __aio_remove_request.
* rt/aio_cancel.c: Don't assume __aio_find_req_fd succeeds since the
request might already be processed.  Don't do the list handling
here, call __aio_remove_request.

* rt/aio_misc.c: Don't depend on aio_reqprio field for LIO_SYNC and
LIO_DSYNC.

* rt/aio_misc.c: Add comment explaining why writer memory barriers
are missing.

ChangeLog
rt/aio_misc.c
rt/aio_misc.h
rt/tst-aio.c

index 3b9deb2..e9dc264 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2000-07-26  Andreas Jaeger  <aj@suse.de>
+
+       * rt/tst-aio.c: Add tests for aio_fsync and aio_cancel.
+       (do_wait): Test requests with aio_return.
+       (do_test): Change callers of do_wait.
+
+2000-07-27  Ulrich Drepper  <drepper@redhat.com>
+
+       * rt/aio_misc.c (__aio_remove_request): New function.  Handle removing
+       from request list.  Don't do the list handling here, call
+       __aio_remove_request.
+       * rt/aio_misc.h: Add prototype for __aio_remove_request.
+       * rt/aio_cancel.c: Don't assume __aio_find_req_fd succeeds since the
+       request might already be processed.  Don't do the list handling
+       here, call __aio_remove_request.
+
+       * rt/aio_misc.c: Don't depend on aio_reqprio field for LIO_SYNC and
+       LIO_DSYNC.
+
+       * rt/aio_misc.c: Add comment explaining why writer memory barriers
+       are missing.
+
 2000-07-27  Greg McGary  <greg@mcgary.org>
 
        * sysdeps/generic/bp-checks.h (BOUNDED_N): Make it work for void*.
index a9fe359..af3e90f 100644 (file)
@@ -205,6 +205,64 @@ __aio_find_req_fd (int fildes)
 }
 
 
+void
+internal_function
+__aio_remove_request (struct requestlist *last, struct requestlist *req,
+                     int all)
+{
+  if (last != NULL)
+    last->next_prio = req->next_prio;
+  else
+    {
+      if (all || req->next_prio == NULL)
+       {
+         if (req->last_fd != NULL)
+           req->last_fd->next_fd = req->next_fd;
+         else
+           requests = req->next_fd;
+         if (req->next_fd != NULL)
+           req->next_fd->last_fd = req->last_fd;
+       }
+      else
+       {
+         if (req->last_fd != NULL)
+           req->last_fd->next_fd = req->next_prio;
+         else
+           requests = req->next_prio;
+
+         if (req->next_fd != NULL)
+           req->next_fd->last_fd = req->next_prio;
+
+         req->next_prio->last_fd = req->last_fd;
+         req->next_prio->next_fd = req->next_fd;
+
+         /* Mark this entry as runnable.  */
+         req->next_prio->running = yes;
+       }
+
+      if (req->running == yes)
+       {
+         struct requestlist *runp = runlist;
+
+         last = NULL;
+         while (runp != NULL)
+           {
+             if (runp == req)
+               {
+                 if (last == NULL)
+                   runlist = runp->next_run;
+                 else
+                   last->next_run = runp->next_run;
+                 break;
+               }
+             last = runp;
+             runp = runp->next_run;
+           }
+       }
+    }
+}
+
+
 /* The thread handler.  */
 static void *handle_fildes_io (void *arg);
 
@@ -246,8 +304,10 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
   struct requestlist *last, *runp, *newp;
   int running = no;
 
-  if (aiocbp->aiocb.aio_reqprio < 0
-      || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX)
+  if (operation == LIO_SYNC || operation == LIO_DSYNC)
+    aiocbp->aiocb.aio_reqprio = 0;
+  else if (aiocbp->aiocb.aio_reqprio < 0
+          || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX)
     {
       /* Invalid priority value.  */
       __set_errno (EINVAL);
@@ -507,6 +567,14 @@ handle_fildes_io (void *arg)
          /* Get the mutex.  */
          pthread_mutex_lock (&__aio_requests_mutex);
 
+         /* In theory we would need here a write memory barrier since the
+            callers test using aio_error() whether the request finished
+            and once this value != EINPROGRESS the field __return_value
+            must be committed to memory.
+
+            But since the pthread_mutex_lock call involves write memory
+            barriers as well it is not necessary.  */
+
          if (aiocbp->aiocb.__return_value == -1)
            aiocbp->aiocb.__error_code = errno;
          else
@@ -517,30 +585,9 @@ handle_fildes_io (void *arg)
          __aio_notify (runp);
 
          /* Now dequeue the current request.  */
-         if (runp->next_prio == NULL)
-           {
-             /* No outstanding request for this descriptor.  Remove this
-                descriptor from the list.  */
-             if (runp->next_fd != NULL)
-               runp->next_fd->last_fd = runp->last_fd;
-             if (runp->last_fd != NULL)
-               runp->last_fd->next_fd = runp->next_fd;
-             else
-               requests = runp->next_fd;
-           }
-         else
-           {
-             runp->next_prio->last_fd = runp->last_fd;
-             runp->next_prio->next_fd = runp->next_fd;
-             runp->next_prio->running = yes;
-             if (runp->next_fd != NULL)
-               runp->next_fd->last_fd = runp->next_prio;
-             if (runp->last_fd != NULL)
-               runp->last_fd->next_fd = runp->next_prio;
-             else
-               requests = runp->next_prio;
-             add_request_to_runlist (runp->next_prio);
-           }
+         __aio_remove_request (NULL, runp, 0);
+         if (runp->next_prio != NULL)
+           add_request_to_runlist (runp->next_prio);
 
          /* Free the old element.  */
          __aio_free_request (runp);
index e3c93be..eda0654 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -104,6 +104,11 @@ extern struct requestlist *__aio_find_req (aiocb_union *elem)
 /* Find request entry for given file descriptor.  */
 extern struct requestlist *__aio_find_req_fd (int fildes) internal_function;
 
+/* Remove request from the list.  */
+extern void __aio_remove_request (struct requestlist *last,
+                                 struct requestlist *req, int all)
+     internal_function;
+
 /* Release the entry for the request.  */
 extern void __aio_free_request (struct requestlist *req) internal_function;
 
index 9a83a27..8a6f103 100644 (file)
@@ -100,23 +100,38 @@ test_file (const void *buf, size_t size, int fd, const char *msg)
 }
 
 
-void
-do_wait (struct aiocb **cbp, size_t nent)
+int
+do_wait (struct aiocb **cbp, size_t nent, int allowed_err)
 {
   int go_on;
+  size_t cnt;
+  int result = 0;
+
   do
     {
-      size_t cnt;
-
       aio_suspend ((const struct aiocb *const *) cbp, nent, NULL);
       go_on = 0;
       for (cnt = 0; cnt < nent; ++cnt)
-       if (cbp[cnt] != NULL && aio_error (cbp[cnt]) == EINPROGRESS)
-         go_on = 1;
-       else
-         cbp[cnt] = NULL;
+       if (cbp[cnt] != NULL)
+         {
+           if (aio_error (cbp[cnt]) == EINPROGRESS)
+             go_on = 1;
+           else
+             {
+               if (aio_return (cbp[cnt]) == -1
+                   && (allowed_err == 0
+                       || aio_error (cbp[cnt]) != allowed_err))
+                 {
+                   error (0, aio_error (cbp[cnt]), "Operation failed\n");
+                   result = 1;
+                 }
+               cbp[cnt] = NULL;
+             }
+         }
     }
   while (go_on);
+
+  return result;
 }
 
 
@@ -124,7 +139,9 @@ int
 do_test (int argc, char *argv[])
 {
   struct aiocb cbs[10];
+  struct aiocb cbs_fsync;
   struct aiocb *cbp[10];
+  struct aiocb *cbp_fsync[1];
   char buf[1000];
   size_t cnt;
   int result = 0;
@@ -146,7 +163,7 @@ do_test (int argc, char *argv[])
   for (cnt = 10; cnt > 0; )
     aio_write (cbp[--cnt]);
   /* Wait 'til the results are there.  */
-  do_wait (cbp, 10);
+  result |= do_wait (cbp, 10, 0);
   /* Test this.  */
   result |= test_file (buf, sizeof (buf), fd, "aio_write");
 
@@ -160,7 +177,7 @@ do_test (int argc, char *argv[])
       aio_read (cbp[cnt]);
     }
   /* Wait 'til the results are there.  */
-  do_wait (cbp, 10);
+  result |= do_wait (cbp, 10, 0);
   /* Test this.  */
   for (cnt = 0; cnt < 1000; ++cnt)
     if (buf[cnt] != '0' + (cnt / 100))
@@ -191,5 +208,77 @@ do_test (int argc, char *argv[])
   /* ...and immediately test it since we started it in wait mode.  */
   result |= test_file (buf, sizeof (buf), fd, "lio_listio (write)");
 
+  /* Test aio_fsync.  */
+  cbs_fsync.aio_fildes = fd;
+  cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE;
+  cbp_fsync[0] = &cbs_fsync;
+
+  /* Remove the test file contents first.  */
+  if (ftruncate (fd, 0) < 0)
+    {
+      error (0, errno, "ftruncate failed\n");
+      result = 1;
+    }
+
+  /* Write again.  */
+  for (cnt = 10; cnt > 0; )
+    aio_write (cbp[--cnt]);
+
+  if (aio_fsync (O_SYNC, &cbs_fsync) < 0)
+    {
+      error (0, errno, "aio_fsync failed\n");
+      result = 1;
+    }
+  result |= do_wait (cbp_fsync, 1, 0);
+
+  /* ...and test since all data should be on disk now.  */
+  result |= test_file (buf, sizeof (buf), fd, "aio_fsync (aio_write)");
+
+  /* Test aio_cancel.  */
+  /* Remove the test file contents first.  */
+  if (ftruncate (fd, 0) < 0)
+    {
+      error (0, errno, "ftruncate failed\n");
+      result = 1;
+    }
+
+  /* Write again.  */
+  for (cnt = 10; cnt > 0; )
+    aio_write (cbp[--cnt]);
+
+  /* Cancel all requests.  */
+  if (aio_cancel (fd, NULL) == -1)
+    printf ("aio_cancel (fd, NULL) cannot cancel anything\n");
+
+  result |= do_wait (cbp, 10, ECANCELED);
+
+  /* Another test for aio_cancel.  */
+  /* Remove the test file contents first.  */
+  if (ftruncate (fd, 0) < 0)
+    {
+      error (0, errno, "ftruncate failed\n");
+      result = 1;
+    }
+
+  /* Write again.  */
+  for (cnt = 10; cnt > 0; )
+    {
+      --cnt;
+      cbp[cnt] = &cbs[cnt];
+      aio_write (cbp[cnt]);
+    }
+  puts ("finished3");
+
+  /* Cancel all requests.  */
+  for (cnt = 10; cnt > 0; )
+    if (aio_cancel (fd, cbp[--cnt]) == -1)
+      /* This is not an error.  The request can simply be finished.  */
+      printf ("aio_cancel (fd, cbp[%Zd]) cannot be canceled\n", cnt);
+  puts ("finished2");
+
+  result |= do_wait (cbp, 10, ECANCELED);
+
+  puts ("finished");
+
   return result;
 }