aio and Posix.4 in Solaris 2.6

aio and Posix.4 in Solaris 2.6

Post by marcpo » Sat, 22 Jun 2002 11:24:27



(Apologies if this is a repost, my newsreader is giving me trouble)

I wrote the following to experiment with async io on Solaris 2.6, but oddly,
when ever I try to dispatch an asynchronous IO request, I receive a 0 return
code and errno is set to 48 (ENOTSUPPORTED).  This is an undocumented
response.  Can someone tell me if there's a Solaris 2.6 issue with the
Posix.4 interfaces or if I'm doing something wrong?

Thanks,

Marc

#define _POSIX_C_SOURCE 199309L

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#ifdef _POSIX_ASYNCHRONOUS_IO
#include <aio.h>
#else
ERROR: no asynchronous IO
#endif

#ifndef _POSIX_REALTIME_SIGNALS
ERROR: need queued signals!
#endif

#define SIG_AIO_WRITE_COMPLETED (SIGRTMAX-10)
#define SIG_AIO_READ_COMPLETED  (SIGRTMAX-11)

#define DATACHUNK 1

off_t nOutSeekPtr = 0;
off_t nInSeekPtr = 0;

int infd;
int outfd;
class AsyncDataBuf {
public:
    char data[DATACHUNK];
    struct aiocb acb;

Quote:};

void InitiateRead(void) {
    AsyncDataBuf* thisBuf = new AsyncDataBuf();
    thisBuf->acb.aio_fildes = infd;
    thisBuf->acb.aio_offset = nInSeekPtr;
    nInSeekPtr+=DATACHUNK;
    thisBuf->acb.aio_buf = thisBuf->data;
    thisBuf->acb.aio_nbytes = DATACHUNK;
    thisBuf->acb.aio_reqprio = 0;
    thisBuf->acb.aio_sigevent.sigev_notify= SIGEV_SIGNAL;
    thisBuf->acb.aio_sigevent.sigev_signo= SIG_AIO_READ_COMPLETED;
    thisBuf->acb.aio_sigevent.sigev_value.sival_ptr = static_cast<void*>(
thisBuf );
    errno = 0;
    int nRead = aio_read(&thisBuf->acb);
    printf("%d %d\n",nRead,errno);

Quote:}

void InitiateWrite(char* buf) {
    AsyncDataBuf* thisBuf = new AsyncDataBuf();
    thisBuf->acb.aio_fildes = outfd;
    thisBuf->acb.aio_offset = nOutSeekPtr;
    nOutSeekPtr+=DATACHUNK;
    memcpy(thisBuf->data,buf,DATACHUNK);
    thisBuf->acb.aio_buf = thisBuf->data;
    thisBuf->acb.aio_nbytes = DATACHUNK;
    thisBuf->acb.aio_reqprio = 0;
    thisBuf->acb.aio_sigevent.sigev_notify= SIGEV_SIGNAL;
    thisBuf->acb.aio_sigevent.sigev_signo= SIG_AIO_WRITE_COMPLETED;
    thisBuf->acb.aio_sigevent.sigev_value.sival_ptr = static_cast<void*>(
thisBuf );
    errno = 0;
    printf("%d %d\n",aio_write(&thisBuf->acb),errno);

Quote:}

void write_done(siginfo_t *info) {
    AsyncDataBuf* thisBuf = (AsyncDataBuf*) info->si_value.sival_ptr;
    delete thisBuf;
    return;

Quote:}

void read_done(siginfo_t *info) {
    printf("Read done\n");
    AsyncDataBuf* thisBuf = (AsyncDataBuf*) info->si_value.sival_ptr;
    InitiateWrite(thisBuf->data);
    delete thisBuf;
    InitiateRead();
    return;

Quote:}

void sig_received(int signo, siginfo_t *info, void* ignored) {
    if (info->si_code == SI_ASYNCIO) {
 AsyncDataBuf* thisBuf = (AsyncDataBuf*) info->si_value.sival_ptr;
 if (aio_error(&thisBuf->acb) != EINPROGRESS) {
     if (aio_return(&thisBuf->acb) == DATACHUNK) {
  printf("Got one\n");

  if (signo == SIG_AIO_READ_COMPLETED) {
      read_done(info);
  }
  else {
      write_done(info);
  }
     }
     else {
  printf("AIO Error\n");
     }
 }
 else {
     printf("In Progress\n");
 }
    }

Quote:}

int handlesignals(void) {

        sigset_t prevmask;

 sigset_t aio_completion_signals;
 sigemptyset(&aio_completion_signals);
 sigaddset(&aio_completion_signals,SIG_AIO_READ_COMPLETED);
 sigaddset(&aio_completion_signals,SIG_AIO_WRITE_COMPLETED);

 struct sigaction sa;
 sa.sa_flags = SA_SIGINFO;
 sigemptyset(&sa.sa_mask);
 sa.sa_sigaction = sig_received;
 sigaction(SIG_AIO_READ_COMPLETED,&sa,NULL);
 sigaction(SIG_AIO_WRITE_COMPLETED,&sa, NULL);

 sigprocmask(SIG_BLOCK,&aio_completion_signals,&prevmask);
 for (;;) {
     if (sigsuspend(&prevmask) == -1) {
  printf("Dying %d\n",errno);
  break;
     }
     printf("I woke up!\n");
 }

    return 0;

Quote:}

int main(int argc, char** argv) {

    infd = open("/u/marcpow/atest/bob1",O_RDONLY,
  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    outfd = open("/u/marcpow/atest/bob", O_CREAT | O_APPEND | O_WRONLY,
   S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);

    InitiateRead();
    //InitiateWrite("Hello Bob without one");

    return handlesignals();

Quote:}

 
 
 

aio and Posix.4 in Solaris 2.6

Post by marcpo » Mon, 24 Jun 2002 16:39:36


Just to post a reponse to what was causing me issues ( I know how I hate
finding group posts that ask the same questions I am but that aren't
answered).  Solaris returns the si_code for sigqueue, rather than aio
completion.  Also, I shouldn't have checked for the -1 as a return code for
sigsuspend.

Oh, and one more thing:  Those of you looking to use sigwaitinfo to wait for
the completion signals -- you have to set up the async signal handler like
you would normally, then BLOCK the signals and then sigwait.  (The blocking
makes sense, the sigaction setup doesn't -- sometimes Solaris is a little
brainless, especially in that I can't find this documented anywhere).


Quote:> (Apologies if this is a repost, my newsreader is giving me trouble)

> I wrote the following to experiment with async io on Solaris 2.6, but
oddly,
> when ever I try to dispatch an asynchronous IO request, I receive a 0
return
> code and errno is set to 48 (ENOTSUPPORTED).  This is an undocumented
> response.  Can someone tell me if there's a Solaris 2.6 issue with the
> Posix.4 interfaces or if I'm doing something wrong?

> Thanks,

> Marc

> #define _POSIX_C_SOURCE 199309L

> #include <unistd.h>
> #include <fcntl.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <signal.h>
> #include <string.h>
> #include <errno.h>
> #include <stdio.h>

> #ifdef _POSIX_ASYNCHRONOUS_IO
> #include <aio.h>
> #else
> ERROR: no asynchronous IO
> #endif

> #ifndef _POSIX_REALTIME_SIGNALS
> ERROR: need queued signals!
> #endif

> #define SIG_AIO_WRITE_COMPLETED (SIGRTMAX-10)
> #define SIG_AIO_READ_COMPLETED  (SIGRTMAX-11)

> #define DATACHUNK 1

> off_t nOutSeekPtr = 0;
> off_t nInSeekPtr = 0;

> int infd;
> int outfd;
> class AsyncDataBuf {
> public:
>     char data[DATACHUNK];
>     struct aiocb acb;
> };

> void InitiateRead(void) {
>     AsyncDataBuf* thisBuf = new AsyncDataBuf();
>     thisBuf->acb.aio_fildes = infd;
>     thisBuf->acb.aio_offset = nInSeekPtr;
>     nInSeekPtr+=DATACHUNK;
>     thisBuf->acb.aio_buf = thisBuf->data;
>     thisBuf->acb.aio_nbytes = DATACHUNK;
>     thisBuf->acb.aio_reqprio = 0;
>     thisBuf->acb.aio_sigevent.sigev_notify= SIGEV_SIGNAL;
>     thisBuf->acb.aio_sigevent.sigev_signo= SIG_AIO_READ_COMPLETED;
>     thisBuf->acb.aio_sigevent.sigev_value.sival_ptr = static_cast<void*>(
> thisBuf );
>     errno = 0;
>     int nRead = aio_read(&thisBuf->acb);
>     printf("%d %d\n",nRead,errno);

> }
> void InitiateWrite(char* buf) {
>     AsyncDataBuf* thisBuf = new AsyncDataBuf();
>     thisBuf->acb.aio_fildes = outfd;
>     thisBuf->acb.aio_offset = nOutSeekPtr;
>     nOutSeekPtr+=DATACHUNK;
>     memcpy(thisBuf->data,buf,DATACHUNK);
>     thisBuf->acb.aio_buf = thisBuf->data;
>     thisBuf->acb.aio_nbytes = DATACHUNK;
>     thisBuf->acb.aio_reqprio = 0;
>     thisBuf->acb.aio_sigevent.sigev_notify= SIGEV_SIGNAL;
>     thisBuf->acb.aio_sigevent.sigev_signo= SIG_AIO_WRITE_COMPLETED;
>     thisBuf->acb.aio_sigevent.sigev_value.sival_ptr = static_cast<void*>(
> thisBuf );
>     errno = 0;
>     printf("%d %d\n",aio_write(&thisBuf->acb),errno);
> }

> void write_done(siginfo_t *info) {
>     AsyncDataBuf* thisBuf = (AsyncDataBuf*) info->si_value.sival_ptr;
>     delete thisBuf;
>     return;
> }

> void read_done(siginfo_t *info) {
>     printf("Read done\n");
>     AsyncDataBuf* thisBuf = (AsyncDataBuf*) info->si_value.sival_ptr;
>     InitiateWrite(thisBuf->data);
>     delete thisBuf;
>     InitiateRead();
>     return;
> }

> void sig_received(int signo, siginfo_t *info, void* ignored) {
>     if (info->si_code == SI_ASYNCIO) {
>  AsyncDataBuf* thisBuf = (AsyncDataBuf*) info->si_value.sival_ptr;
>  if (aio_error(&thisBuf->acb) != EINPROGRESS) {
>      if (aio_return(&thisBuf->acb) == DATACHUNK) {
>   printf("Got one\n");

>   if (signo == SIG_AIO_READ_COMPLETED) {
>       read_done(info);
>   }
>   else {
>       write_done(info);
>   }
>      }
>      else {
>   printf("AIO Error\n");
>      }
>  }
>  else {
>      printf("In Progress\n");
>  }
>     }
> }

> int handlesignals(void) {

>         sigset_t prevmask;

>  sigset_t aio_completion_signals;
>  sigemptyset(&aio_completion_signals);
>  sigaddset(&aio_completion_signals,SIG_AIO_READ_COMPLETED);
>  sigaddset(&aio_completion_signals,SIG_AIO_WRITE_COMPLETED);

>  struct sigaction sa;
>  sa.sa_flags = SA_SIGINFO;
>  sigemptyset(&sa.sa_mask);
>  sa.sa_sigaction = sig_received;
>  sigaction(SIG_AIO_READ_COMPLETED,&sa,NULL);
>  sigaction(SIG_AIO_WRITE_COMPLETED,&sa, NULL);

>  sigprocmask(SIG_BLOCK,&aio_completion_signals,&prevmask);
>  for (;;) {
>      if (sigsuspend(&prevmask) == -1) {
>   printf("Dying %d\n",errno);
>   break;
>      }
>      printf("I woke up!\n");
>  }

>     return 0;
> }

> int main(int argc, char** argv) {

>     infd = open("/u/marcpow/atest/bob1",O_RDONLY,
>   S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
>     outfd = open("/u/marcpow/atest/bob", O_CREAT | O_APPEND | O_WRONLY,
>    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);

>     InitiateRead();
>     //InitiateWrite("Hello Bob without one");

>     return handlesignals();
> }


 
 
 

1. LFS and AIO on Solaris 2.6 and 7?

                Hi,

I have encountered a problem with lio_listio(3RT) C function when used
together with large file support. The affected platforms are running
Solaris 2.6 and Solaris 7. The code works perfectly on our Solaris 8
machines.

Basically, when I issue lio_listio(LIO,WAIT,...) call with lio_aio_opcode
set to LIO_READ, I get -1 as a result but errno is equal 0. If I use
aio_error(3RT) and aio_return(3RT) functions to fetch errnos and return
values of embedded read calls, they all return non-negative values.

Now, if I _don't_ define  _FILE_OFFSET_BITS and  _LARGEFILE_SOURCE, the
complied code works fine both on Solaris 2.6 and Solaris 7. Unfortunately,
my program has to handle the files larger than 2GB.

If I define aforementioned macros, the code doesn't even compile on Solaris
2.6 machine. Here is the message

$ gcc -Wall -g -O2    acp.c  -lrt -o acp
In file included from acp.c:18:
/usr/include/aio.h:68: conflicting types for `aio_read64'
/usr/include/aio.h:56: previous declaration of `aio_read64'
/usr/include/aio.h:69: conflicting types for `aio_write64'
/usr/include/aio.h:57: previous declaration of `aio_write64'
/usr/include/aio.h:71: conflicting types for `lio_listio64'
/usr/include/aio.h:59: previous declaration of `lio_listio64'
/usr/include/aio.h:72: conflicting types for `aio_error64'
/usr/include/aio.h:60: previous declaration of `aio_error64'
/usr/include/aio.h:73: conflicting types for `aio_return64'
/usr/include/aio.h:61: previous declaration of `aio_return64'
/usr/include/aio.h:74: conflicting types for `aio_cancel64'
/usr/include/aio.h:62: previous declaration of `aio_cancel64'
/usr/include/aio.h:76: conflicting types for `aio_suspend64'
/usr/include/aio.h:64: previous declaration of `aio_suspend64'
/usr/include/aio.h:77: conflicting types for `aio_fsync64'
/usr/include/aio.h:65: previous declaration of `aio_fsync64'

As I mentioned already, the code works perfect on Solaris 8.

Is this a known issue and is there some patch or a workaround for that
problem? I see that our Solaris 7 machine has kernel patch 106541-04
installed and that -17 is the latest version. Should I install that patch?
Any other suggestion?

Thanx in advance.

Dragan

--
Dragan Cvetkovic,

To be or not to be is true. G. Boole

2. rsh connection refused

3. Q. POSIX aio on Solaris 2.3 broken ?

4. MTRR error in Dual CPU system.

5. posix vs. solaris aio

6. Any information regarding peerless unix?

7. POSIX.4 Async I/O on Solaris 2.6 (long)

8. per packet QoS (DSCP)

9. Posix threads under Solaris 2.6

10. POSIX IPC message queues implementation error on Solaris 2.6

11. POSIX process-shared synchronization variables on Solaris 2.6

12. POSIX queued signals and Solaris 2.6

13. can't read Solaris 2.6 x86 hard disk on Solaris 2.6 Ultra-1 ?!?