Back to index

glibc  2.9
tst-aio.c
Go to the documentation of this file.
00001 /* Tests for AIO in librt.
00002    Copyright (C) 1998,2000,02 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <aio.h>
00022 #include <errno.h>
00023 #include <error.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <unistd.h>
00027 #include <sys/stat.h>
00028 
00029 
00030 /* Prototype for our test function.  */
00031 extern void do_prepare (int argc, char *argv[]);
00032 extern int do_test (int argc, char *argv[]);
00033 
00034 /* We have a preparation function.  */
00035 #define PREPARE do_prepare
00036 
00037 /* We might need a bit longer timeout.  */
00038 #define TIMEOUT 20 /* sec */
00039 
00040 /* This defines the `main' function and some more.  */
00041 #include <test-skeleton.c>
00042 
00043 
00044 /* These are for the temporary file we generate.  */
00045 char *name;
00046 int fd;
00047 
00048 void
00049 do_prepare (int argc, char *argv[])
00050 {
00051   size_t name_len;
00052 
00053   name_len = strlen (test_dir);
00054   name = malloc (name_len + sizeof ("/aioXXXXXX"));
00055   mempcpy (mempcpy (name, test_dir, name_len),
00056           "/aioXXXXXX", sizeof ("/aioXXXXXX"));
00057   add_temp_file (name);
00058 
00059   /* Open our test file.   */
00060   fd = mkstemp (name);
00061   if (fd == -1)
00062     error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
00063 }
00064 
00065 
00066 static int
00067 test_file (const void *buf, size_t size, int fd, const char *msg)
00068 {
00069   struct stat st;
00070   char tmp[size];
00071 
00072   errno = 0;
00073   if (fstat (fd, &st) < 0)
00074     {
00075       error (0, errno, "%s: failed stat", msg);
00076       return 1;
00077     }
00078 
00079   if (st.st_size != (off_t) size)
00080     {
00081       error (0, errno, "%s: wrong size: %lu, should be %lu",
00082             msg, (unsigned long int) st.st_size, (unsigned long int) size);
00083       return 1;
00084     }
00085 
00086   if (pread (fd, tmp, size, 0) != (ssize_t) size)
00087     {
00088       error (0, errno, "%s: failed pread", msg);
00089       return 1;
00090     }
00091 
00092   if (memcmp (buf, tmp, size) != 0)
00093     {
00094       error (0, errno, "%s: failed comparison", msg);
00095       return 1;
00096     }
00097 
00098   printf ("%s test ok\n", msg);
00099 
00100   return 0;
00101 }
00102 
00103 
00104 static int
00105 do_wait (struct aiocb **cbp, size_t nent, int allowed_err)
00106 {
00107   int go_on;
00108   size_t cnt;
00109   int result = 0;
00110 
00111   do
00112     {
00113       aio_suspend ((const struct aiocb *const *) cbp, nent, NULL);
00114       go_on = 0;
00115       for (cnt = 0; cnt < nent; ++cnt)
00116        if (cbp[cnt] != NULL)
00117          {
00118            if (aio_error (cbp[cnt]) == EINPROGRESS)
00119              go_on = 1;
00120            else
00121              {
00122               if (aio_return (cbp[cnt]) == -1
00123                   && (allowed_err == 0
00124                      || aio_error (cbp[cnt]) != allowed_err))
00125                 {
00126                   error (0, aio_error (cbp[cnt]), "Operation failed\n");
00127                   result = 1;
00128                 }
00129               cbp[cnt] = NULL;
00130              }
00131          }
00132     }
00133   while (go_on);
00134 
00135   return result;
00136 }
00137 
00138 
00139 int
00140 do_test (int argc, char *argv[])
00141 {
00142   struct aiocb cbs[10];
00143   struct aiocb cbs_fsync;
00144   struct aiocb *cbp[10];
00145   struct aiocb *cbp_fsync[1];
00146   char buf[1000];
00147   size_t cnt;
00148   int result = 0;
00149 
00150   /* Preparation.  */
00151   for (cnt = 0; cnt < 10; ++cnt)
00152     {
00153       cbs[cnt].aio_fildes = fd;
00154       cbs[cnt].aio_reqprio = 0;
00155       cbs[cnt].aio_buf = memset (&buf[cnt * 100], '0' + cnt, 100);
00156       cbs[cnt].aio_nbytes = 100;
00157       cbs[cnt].aio_offset = cnt * 100;
00158       cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE;
00159 
00160       cbp[cnt] = &cbs[cnt];
00161     }
00162 
00163   /* First a simple test.  */
00164   for (cnt = 10; cnt > 0; )
00165     if (aio_write (cbp[--cnt]) < 0 && errno == ENOSYS)
00166       {
00167        error (0, 0, "no aio support in this configuration");
00168        return 0;
00169       }
00170   /* Wait 'til the results are there.  */
00171   result |= do_wait (cbp, 10, 0);
00172   /* Test this.  */
00173   result |= test_file (buf, sizeof (buf), fd, "aio_write");
00174 
00175   /* Read now as we've written it.  */
00176   memset (buf, '\0', sizeof (buf));
00177   /* Issue the commands.  */
00178   for (cnt = 10; cnt > 0; )
00179     {
00180       --cnt;
00181       cbp[cnt] = &cbs[cnt];
00182       aio_read (cbp[cnt]);
00183     }
00184   /* Wait 'til the results are there.  */
00185   result |= do_wait (cbp, 10, 0);
00186   /* Test this.  */
00187   for (cnt = 0; cnt < 1000; ++cnt)
00188     if (buf[cnt] != '0' + (cnt / 100))
00189       {
00190        result = 1;
00191        error (0, 0, "comparison failed for aio_read test");
00192        break;
00193       }
00194 
00195   if (cnt == 1000)
00196     puts ("aio_read test ok");
00197 
00198   /* Remove the test file contents.  */
00199   if (ftruncate (fd, 0) < 0)
00200     {
00201       error (0, errno, "ftruncate failed\n");
00202       result = 1;
00203     }
00204 
00205   /* Test lio_listio.  */
00206   for (cnt = 0; cnt < 10; ++cnt)
00207     {
00208       cbs[cnt].aio_lio_opcode = LIO_WRITE;
00209       cbp[cnt] = &cbs[cnt];
00210     }
00211   /* Issue the command.  */
00212   lio_listio (LIO_WAIT, cbp, 10, NULL);
00213   /* ...and immediately test it since we started it in wait mode.  */
00214   result |= test_file (buf, sizeof (buf), fd, "lio_listio (write)");
00215 
00216   /* Test aio_fsync.  */
00217   cbs_fsync.aio_fildes = fd;
00218   cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE;
00219   cbp_fsync[0] = &cbs_fsync;
00220 
00221   /* Remove the test file contents first.  */
00222   if (ftruncate (fd, 0) < 0)
00223     {
00224       error (0, errno, "ftruncate failed\n");
00225       result = 1;
00226     }
00227 
00228   /* Write again.  */
00229   for (cnt = 10; cnt > 0; )
00230     aio_write (cbp[--cnt]);
00231 
00232   if (aio_fsync (O_SYNC, &cbs_fsync) < 0)
00233     {
00234       error (0, errno, "aio_fsync failed\n");
00235       result = 1;
00236     }
00237   result |= do_wait (cbp_fsync, 1, 0);
00238 
00239   /* ...and test since all data should be on disk now.  */
00240   result |= test_file (buf, sizeof (buf), fd, "aio_fsync (aio_write)");
00241 
00242   /* Test aio_cancel.  */
00243   /* Remove the test file contents first.  */
00244   if (ftruncate (fd, 0) < 0)
00245     {
00246       error (0, errno, "ftruncate failed\n");
00247       result = 1;
00248     }
00249 
00250   /* Write again.  */
00251   for (cnt = 10; cnt > 0; )
00252     aio_write (cbp[--cnt]);
00253 
00254   /* Cancel all requests.  */
00255   if (aio_cancel (fd, NULL) == -1)
00256     printf ("aio_cancel (fd, NULL) cannot cancel anything\n");
00257 
00258   result |= do_wait (cbp, 10, ECANCELED);
00259 
00260   /* Another test for aio_cancel.  */
00261   /* Remove the test file contents first.  */
00262   if (ftruncate (fd, 0) < 0)
00263     {
00264       error (0, errno, "ftruncate failed\n");
00265       result = 1;
00266     }
00267 
00268   /* Write again.  */
00269   for (cnt = 10; cnt > 0; )
00270     {
00271       --cnt;
00272       cbp[cnt] = &cbs[cnt];
00273       aio_write (cbp[cnt]);
00274     }
00275   puts ("finished3");
00276 
00277   /* Cancel all requests.  */
00278   for (cnt = 10; cnt > 0; )
00279     if (aio_cancel (fd, cbp[--cnt]) == -1)
00280       /* This is not an error.  The request can simply be finished.  */
00281       printf ("aio_cancel (fd, cbp[%Zd]) cannot be canceled\n", cnt);
00282   puts ("finished2");
00283 
00284   result |= do_wait (cbp, 10, ECANCELED);
00285 
00286   puts ("finished");
00287 
00288   return result;
00289 }