Back to index

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