Beispiel #1
0
int main()
{
	char tmpfname[256];
#define BUF_SIZE 111
	char buf[BUF_SIZE];
	int fd;
	struct aiocb aiocb_write;
	struct aiocb aiocb_fsync;

#if _POSIX_ASYNCHRONOUS_IO != 200112L
	exit(PTS_UNSUPPORTED);
#endif

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_4_2_%d", 
		  getpid());
	unlink(tmpfname);
	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL,
		  S_IRUSR | S_IWUSR);
	if (fd == -1)
	{
		printf(TNAME " Error at open(): %s\n",
		       strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	memset(&aiocb_write, 0, sizeof(aiocb_write));
	aiocb_write.aio_fildes = fd;
	aiocb_write.aio_buf = buf;
	aiocb_write.aio_nbytes = BUF_SIZE;

	if (aio_write(&aiocb_write) == -1)
	{
		printf(TNAME " Error at aio_write(): %s\n",
		       strerror(errno));
		exit(PTS_FAIL);
	}

	memset(&aiocb_fsync, 0, sizeof(aiocb_fsync));
	aiocb_fsync.aio_fildes = fd;

	if (aio_fsync(O_SYNC, &aiocb_fsync) != 0)
	{
		printf(TNAME " Error at aio_fsync()\n");
		exit(PTS_FAIL);
	}

	errno = 0;
	aio_return(&aiocb_fsync);
	if (errno != 0)
	{
		printf(TNAME " Error at aio_return() : %s\n", strerror(errno));
		exit(PTS_FAIL);
	}
	close(fd);
	printf ("Test PASSED\n");
	return PTS_PASS;
}
Beispiel #2
0
int main()
{
	char tmpfname[256];
#define BUF_SIZE 111
	char buf[BUF_SIZE];
	int fd;
	int ret;
	struct aiocb aiocb_write;
	struct aiocb aiocb_fsync;

	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
		return PTS_UNSUPPORTED;

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_8_2_%d",
		  getpid());
	unlink(tmpfname);
	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL,
		  S_IRUSR | S_IWUSR);
	if (fd == -1) {
		printf(TNAME " Error at open(): %s\n",
		       strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	memset(&aiocb_write, 0, sizeof(aiocb_write));
	aiocb_write.aio_fildes = fd;
	aiocb_write.aio_buf = buf;
	aiocb_write.aio_nbytes = BUF_SIZE;

	if (aio_write(&aiocb_write) == -1) {
		printf(TNAME " Error at aio_write(): %s\n",
		       strerror(errno));
		exit(PTS_FAIL);
	}

	do {
		usleep(10000);
		ret = aio_error(&aiocb_write);
	} while (ret == EINPROGRESS);
	if (ret < 0) {
		printf(TNAME " Error at aio_error() : %s\n", strerror(ret));
		exit(PTS_FAIL);
	}

	memset(&aiocb_fsync, 0, sizeof(aiocb_fsync));
	aiocb_fsync.aio_fildes = fd;
	aiocb_fsync.aio_buf = NULL;

	if (aio_fsync(O_SYNC, &aiocb_fsync) != 0) {
		printf(TNAME " Error at aio_fsync(): %s\n", strerror(errno));
		exit(PTS_FAIL);
	}

	close(fd);
	printf("Test PASSED\n");
	return PTS_PASS;
}
Beispiel #3
0
IoObject *IoAsyncRequest_sync(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
{
	/*doc AsyncRequest sync
	Waits for the request to complete. Returns nil on error or self otherwise.
	*/
	int r = aio_fsync(O_SYNC, IOCB(self));
	return r == 0 ? self : IONIL(self);
}
Beispiel #4
0
static VALUE 
rb_aio_sync(int op, aiocb_t *cb)
{ 
    int ret;
    TRAP_BEG;
    ret = aio_fsync( op, cb );
    TRAP_END;
    if (ret != 0) rb_aio_sync_error();
    return INT2FIX(ret);
}
Beispiel #5
0
int
main (void)
{
	char tmpfname[256];
	char buf[BUF_SIZE];
	int fd;
	struct aiocb aiocb_write;
	struct aiocb aiocb_fsync;

	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
		return PTS_UNSUPPORTED;

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_2_1_%d",
		  getpid());
	unlink(tmpfname);
	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL,
		  S_IRUSR | S_IWUSR);
	if (fd == -1)
	{
		printf(TNAME " Error at open(): %s\n",
		       strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	memset(&aiocb_write, 0, sizeof(aiocb_write));
	aiocb_write.aio_fildes = fd;
	aiocb_write.aio_buf = buf;
	aiocb_write.aio_nbytes = BUF_SIZE;

	if (aio_write(&aiocb_write) == -1)
	{
		printf(TNAME " Error at aio_write(): %s\n",
		       strerror(errno));
		exit(PTS_FAIL);
	}

	memset(&aiocb_fsync, 0, sizeof(aiocb_fsync));
	aiocb_fsync.aio_fildes = fd;

	if (aio_fsync(O_DSYNC, &aiocb_fsync) != 0)
	{
		printf(TNAME " Error at aio_fsync(): %s\n", strerror(errno));
		exit(PTS_FAIL);
	}

	close(fd);

	/* we didn't check if the operation is really performed */

	return PTS_UNTESTED;
}
Beispiel #6
0
void aio_check_functions(struct aiocb *ai)
{
    (void)aio_cancel(0, ai);
    (void)aio_error(ai);
#if _POSIX_FSYNC > 0 || _POSIX_SYNCHRONIZED_IO > 0
    (void)aio_fsync(0, ai);
#endif
    (void)aio_read(ai);
    (void)aio_return(ai);
    (void)aio_suspend((const struct aiocb * const *)1234, 0, (struct timespec *)0);
    (void)aio_write(ai);
    (void)lio_listio(0, (struct aiocb * const *)1234, 0, (struct sigevent *)0);
}
Beispiel #7
0
static struct tevent_req *aio_posix_fsync_send(
	struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
	struct tevent_context *ev, struct files_struct *fsp)
{
	struct tevent_req *req;
	struct aio_posix_state *state;
	struct aiocb *a;
	int ret;

	req = tevent_req_create(mem_ctx, &state, struct aio_posix_state);
	if (req == NULL) {
		return NULL;
	}

	a = &state->acb;

	a->aio_fildes = fsp->fh->fd;
	a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
	a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
	a->aio_sigevent.sigev_value.sival_ptr = req;

	ret = aio_fsync(O_SYNC, a);
	if (ret == 0) {
		talloc_set_destructor(state, aio_posix_state_destructor);
		return req;
	}

	if (errno == EAGAIN) {
		/*
		 * aio overloaded, do the sync fallback
		 */
		state->ret = fsync(fsp->fh->fd);
		if (state->ret == -1) {
			state->err = errno;
		}
		tevent_req_done(req);
		return tevent_req_post(req, ev);
	}

	tevent_req_error(req, errno);
	return tevent_req_post(req, ev);
}
Beispiel #8
0
void *
POSIX_Init (void *argument)
{
  int result, fd;
  struct aiocb *aiocbp;
  int status;

  rtems_aio_init ();

  status = mkdir ("/tmp", S_IRWXU);
  rtems_test_assert (!status);
  
  fd = open ("/tmp/aio_fildes", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
  rtems_test_assert ( fd != -1);

  TEST_BEGIN();

  puts (" Init: EBADF TESTS ");

  aiocbp = create_aiocb (WRONG_FD);
  status = aio_write (aiocbp);
  rtems_test_assert (status == -1);

  /* Bad file descriptor */
  puts ("Init: aio_write() - EBADF ");

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EBADF);

  status = aio_read (aiocbp);
  rtems_test_assert (status == -1);

  /* Bad file descriptor */
  puts ("Init: aio_read() - EBADF ");

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EBADF);

  status = aio_cancel (WRONG_FD, NULL);
  rtems_test_assert (status == -1);

  /* Bad file descriptor */
  puts ("Init: aio_cancel() - EBADF ");
  
  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EBADF);

  status = aio_fsync (O_SYNC, aiocbp);
  rtems_test_assert (status == -1);
  
  /* Bad file descriptor */
  puts ("Init: aio_fsync() - EBADF ");

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EBADF);
  
  free_aiocb (aiocbp);

  /* Invalid offset */
  puts ("Init: aio_write() - EINVAL [aio_offset]");

  aiocbp = create_aiocb (fd);
  aiocbp->aio_offset = -1;
  status = aio_write (aiocbp);
  rtems_test_assert (status == -1);

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EINVAL);

    /* Invalid offset */
  puts ("Init: aio_read() - EINVAL [aio_offset]");

  status = aio_read (aiocbp);
  rtems_test_assert (status == -1);

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EINVAL);

  free_aiocb (aiocbp);

  /* Invalid request priority */
  puts ("Init: aio_write() - EINVAL [aio_reqprio]");

  aiocbp = create_aiocb (fd);
  aiocbp->aio_reqprio = AIO_PRIO_DELTA_MAX + 1;
  status = aio_write (aiocbp);
  rtems_test_assert (status == -1);

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EINVAL);

   /* Invalid request priority */
  puts ("Init: aio_read() - EINVAL [aio_reqprio]");

  status = aio_read (aiocbp);
  rtems_test_assert (status == -1);

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EINVAL);

  /* Invalid request aio_cancel */
  puts ("Init: aio_cancel() - EINVAL ");

  status = aio_cancel (WRONG_FD, aiocbp);
  rtems_test_assert (status == -1);

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EINVAL);

  /* Invalid operation to aio_fsync */
  puts ("Init: aio_fsync() - EINVAL ");
  status = aio_fsync (-1, aiocbp);
  rtems_test_assert (status == -1);

  result = aio_return (aiocbp);
  rtems_test_assert (result == -1);
  status = aio_error (aiocbp);
  rtems_test_assert (status == EINVAL);

  free_aiocb (aiocbp);

  TEST_END();

  close (fd);
  rtems_test_exit (0);

  return NULL;

}
Beispiel #9
0
int main(int argc, char *argv[])
{
	int			ifd, ofd, i, j, n, err, numop;
	struct stat		sbuf;
	const struct aiocb	*aiolist[NBUF];
	off_t			off = 0;

	if (argc != 3)
		err_quit("usage: rot13 infile outfile");
	if ((ifd = open(argv[1], O_RDONLY)) < 0)
		err_sys("can't open %s", argv[1]);
	if ((ofd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) < 0)
		err_sys("can't create %s", argv[2]);
	if (fstat(ifd, &sbuf) < 0)
		err_sys("fstat error");

	/* initialize the buffers */
	for (i = 0; i < NBUF; i++) {
		bufs[i].op				= UNUSED;
		bufs[i].aiocb.aio_buf			= bufs[i].data;
		bufs[i].aiocb.aio_sigevent.sigev_notify	= SIGEV_NONE;
		aiolist[i]				= NULL;
	}

	numop = 0;
	for (;;) {
		for (i = 0; i < NBUF; i++) {
			switch (bufs[i].op) {
			case UNUSED:
				/*
				 * Read from the input file if more data
				 * remains unread
				 */
				if (off < sbuf.st_size) {
					bufs[i].op		 = READ_PENDING;
					bufs[i].aiocb.aio_fildes = ifd;
					bufs[i].aiocb.aio_offset = off;
					off += BSZ;
					if (off >= sbuf.st_size)
						bufs[i].last = 1;
					bufs[i].aiocb.aio_nbytes = BSZ;
					if (aio_read(&bufs[i].aiocb) < 0)
						err_sys("aio_read failed");
					aiolist[i] = &bufs[i].aiocb;
					numop++;
				}
				break;

			case READ_PENDING:
				if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS)
					continue;
				if (err != 0) {
					if (err == 1)
						err_sys("aio_error failed");
					else
						err_exit(err, "read failed");
				}

				/*
				 * A read is complete; tranlate the buffer
				 * and write it
				 */
				if ((n = aio_return(&bufs[i].aiocb)) < 0)
					err_sys("aio_return failed");
				if (n != BSZ && !bufs[i].last)
					err_quit("short read (%d/%d)", n, BSZ);
				for (j = 0; j < n; j++)
					bufs[i].data[j] = tranlate(bufs[i].data[j]);
				bufs[i].op		 = WRITE_PENDING;
				bufs[i].aiocb.aio_fildes = ofd;
				bufs[i].aiocb.aio_nbytes = n;
				if (aio_write(&bufs[i].aiocb) < 0)
					err_sys("aio_write failed");
				/* retain(保持) our spot(地点) in aiolis */
				break;

			case WRITE_PENDING:
				if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS)
					continue;
				if (err != 0) {
					if (err == -1)
						err_sys("aio_error failed");
					else
						err_exit(err, "write failed");
				}

				/* 
				 * A write is complete; mark the buffer as unused
				 */
				if ((n = aio_return(&bufs[i].aiocb)) < 0)
					err_sys("aio_return failed");
				if (n != bufs[i].aiocb.aio_nbytes)
					err_quit("short write (%d/%d)", n, BSZ);
				aiolist[i] = NULL;
				bufs[i].op = UNUSED;
				numop--;
				break;
			}
		}
		if (numop == 0) {
			if (off >= sbuf.st_size)
				break;
		} else {
			if (aio_suspend(aiolist, NBUF, NULL) < 0)
				err_sys("aio_suspend failed");
		}
	}

	bufs[0].aiocb.aio_fildes = ofd;
	if (aio_fsync(O_SYNC, &bufs[0].aiocb) < 0)
		err_sys("aio_fsync failed");
	exit(0);
}
Beispiel #10
0
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;
  size_t cnt;
  int result = 0;

  buf = mmap (NULL, 20 * blksz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
  tmpbuf = buf + 10 * blksz;
  if (buf == MAP_FAILED)
    {
      error (0, errno, "mmap failed");
      return 1;
    }

  /* Preparation.  */
  for (cnt = 0; cnt < 10; ++cnt)
    {
      cbs[cnt].aio_fildes = fd;
      cbs[cnt].aio_reqprio = 0;
      cbs[cnt].aio_buf = memset (&buf[cnt * blksz], '0' + cnt, blksz);
      cbs[cnt].aio_nbytes = blksz;
      cbs[cnt].aio_offset = cnt * blksz;
      cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE;

      cbp[cnt] = &cbs[cnt];
    }

  /* First a simple test.  */
  for (cnt = 10; cnt > 0; )
    if (aio_write (cbp[--cnt]) < 0 && errno == ENOSYS)
      {
	error (0, 0, "no aio support in this configuration");
	return 0;
      }
  /* Wait 'til the results are there.  */
  result |= do_wait (cbp, 10, 0);
  /* Test this.  */
  result |= test_file (buf, 10 * blksz, fd, "aio_write");

  /* Read now as we've written it.  */
  memset (buf, '\0', 10 * blksz);
  /* Issue the commands.  */
  for (cnt = 10; cnt > 0; )
    {
      --cnt;
      cbp[cnt] = &cbs[cnt];
      aio_read (cbp[cnt]);
    }
  /* Wait 'til the results are there.  */
  result |= do_wait (cbp, 10, 0);
  /* Test this.  */
  for (cnt = 0; cnt < 10 * blksz; ++cnt)
    if (buf[cnt] != '0' + (cnt / blksz))
      {
	result = 1;
	error (0, 0, "comparison failed for aio_read test");
	break;
      }

  if (cnt == 10 * blksz)
    puts ("aio_read test ok");

  /* Remove the test file contents.  */
  if (ftruncate (fd, 0) < 0)
    {
      error (0, errno, "ftruncate failed\n");
      result = 1;
    }

  /* Test lio_listio.  */
  for (cnt = 0; cnt < 10; ++cnt)
    {
      cbs[cnt].aio_lio_opcode = LIO_WRITE;
      cbp[cnt] = &cbs[cnt];
    }
  /* Issue the command.  */
  lio_listio (LIO_WAIT, cbp, 10, NULL);
  /* ...and immediately test it since we started it in wait mode.  */
  result |= test_file (buf, 10 * blksz, 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, 10 * blksz, 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;
}
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
{
    int rc = VINF_SUCCESS;
    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;

    /* Parameter checks */
    AssertPtrReturn(pCtxInt, VERR_INVALID_HANDLE);
    AssertReturn(cReqs != 0, VERR_INVALID_POINTER);
    AssertPtrReturn(pahReqs,  VERR_INVALID_PARAMETER);

    rtFileAioCtxDump(pCtxInt);

    /* Check that we don't exceed the limit */
    if (ASMAtomicUoReadS32(&pCtxInt->cRequests) + cReqs > pCtxInt->cMaxRequests)
        return VERR_FILE_AIO_LIMIT_EXCEEDED;

    PRTFILEAIOREQINTERNAL pHead = NULL;

    do
    {
        int rcPosix = 0;
        size_t cReqsSubmit = 0;
        size_t i = 0;
        PRTFILEAIOREQINTERNAL pReqInt;

        while (   (i < cReqs)
               && (i < AIO_LISTIO_MAX))
        {
            pReqInt = pahReqs[i];
            if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
            {
                /* Undo everything and stop submitting. */
                for (size_t iUndo = 0; iUndo < i; iUndo++)
                {
                    pReqInt = pahReqs[iUndo];
                    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                    pReqInt->pCtxInt = NULL;

                    /* Unlink from the list again. */
                    PRTFILEAIOREQINTERNAL pNext, pPrev;
                    pNext = pReqInt->pNext;
                    pPrev = pReqInt->pPrev;
                    if (pNext)
                        pNext->pPrev = pPrev;
                    if (pPrev)
                        pPrev->pNext = pNext;
                    else
                        pHead = pNext;
                }
                rc = VERR_INVALID_HANDLE;
                break;
            }

            pReqInt->pCtxInt = pCtxInt;

            if (pReqInt->fFlush)
                break;

            /* Link them together. */
            pReqInt->pNext = pHead;
            if (pHead)
                pHead->pPrev = pReqInt;
            pReqInt->pPrev = NULL;
            pHead = pReqInt;
            RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);

            cReqsSubmit++;
            i++;
        }

        if (cReqsSubmit)
        {
            rcPosix = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL);
            if (RT_UNLIKELY(rcPosix < 0))
            {
                size_t cReqsSubmitted = cReqsSubmit;

                if (errno == EAGAIN)
                    rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                else
                    rc = RTErrConvertFromErrno(errno);

                /* Check which ones were not submitted. */
                for (i = 0; i < cReqsSubmit; i++)
                {
                    pReqInt = pahReqs[i];

                    rcPosix = aio_error(&pReqInt->AioCB);

                    if ((rcPosix != EINPROGRESS) && (rcPosix != 0))
                    {
                        cReqsSubmitted--;

#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
                        if (errno == EINVAL)
#else
                        if (rcPosix == EINVAL)
#endif
                        {
                            /* Was not submitted. */
                            RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                        }
                        else
                        {
                            /* An error occurred. */
                            RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);

                            /*
                             * Looks like Apple and glibc interpret the standard in different ways.
                             * glibc returns the error code which would be in errno but Apple returns
                             * -1 and sets errno to the appropriate value
                             */
#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
                            Assert(rcPosix == -1);
                            pReqInt->Rc = RTErrConvertFromErrno(errno);
#elif defined(RT_OS_LINUX)
                            pReqInt->Rc = RTErrConvertFromErrno(rcPosix);
#endif
                            pReqInt->cbTransfered = 0;
                        }
                        /* Unlink from the list. */
                        PRTFILEAIOREQINTERNAL pNext, pPrev;
                        pNext = pReqInt->pNext;
                        pPrev = pReqInt->pPrev;
                        if (pNext)
                            pNext->pPrev = pPrev;
                        if (pPrev)
                            pPrev->pNext = pNext;
                        else
                            pHead = pNext;

                        pReqInt->pNext = NULL;
                        pReqInt->pPrev = NULL;
                    }
                }
                ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted);
                AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n"));
                break;
            }

            ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit);
            AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n"));
            cReqs   -= cReqsSubmit;
            pahReqs += cReqsSubmit;
        }

        /*
         * Check if we have a flush request now.
         * If not we hit the AIO_LISTIO_MAX limit
         * and will continue submitting requests
         * above.
         */
        if (cReqs && RT_SUCCESS_NP(rc))
        {
            pReqInt = pahReqs[0];

            if (pReqInt->fFlush)
            {
                /*
                 * lio_listio does not work with flush requests so
                 * we have to use aio_fsync directly.
                 */
                rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB);
                if (RT_UNLIKELY(rcPosix < 0))
                {
                    if (errno == EAGAIN)
                    {
                        rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                    }
                    else
                    {
                        rc = RTErrConvertFromErrno(errno);
                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                        pReqInt->Rc = rc;
                    }
                    pReqInt->cbTransfered = 0;
                    break;
                }

                /* Link them together. */
                pReqInt->pNext = pHead;
                if (pHead)
                    pHead->pPrev = pReqInt;
                pReqInt->pPrev = NULL;
                pHead = pReqInt;
                RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);

                ASMAtomicIncS32(&pCtxInt->cRequests);
                AssertMsg(pCtxInt->cRequests >= 0, ("Adding requests resulted in overflow\n"));
                cReqs--;
                pahReqs++;
            }
        }
    } while (   cReqs
             && RT_SUCCESS_NP(rc));

    if (pHead)
    {
        /*
         * Forward successfully submitted requests to the thread waiting for requests.
         * We search for a free slot first and if we don't find one
         * we will grab the first one and append our list to the existing entries.
         */
        unsigned iSlot = 0;
        while (  (iSlot < RT_ELEMENTS(pCtxInt->apReqsNewHead))
               && !ASMAtomicCmpXchgPtr(&pCtxInt->apReqsNewHead[iSlot], pHead, NULL))
            iSlot++;

        if (iSlot == RT_ELEMENTS(pCtxInt->apReqsNewHead))
        {
            /* Nothing found. */
            PRTFILEAIOREQINTERNAL pOldHead = ASMAtomicXchgPtrT(&pCtxInt->apReqsNewHead[0], NULL, PRTFILEAIOREQINTERNAL);

            /* Find the end of the current head and link the old list to the current. */
            PRTFILEAIOREQINTERNAL pTail = pHead;
            while (pTail->pNext)
                pTail = pTail->pNext;

            pTail->pNext = pOldHead;

            ASMAtomicWritePtr(&pCtxInt->apReqsNewHead[0], pHead);
        }

        /* Set the internal wakeup flag and wakeup the thread if possible. */
        bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUpInternal, true);
        if (!fWokenUp)
            rtFileAioCtxWakeup(pCtxInt);
    }

    rtFileAioCtxDump(pCtxInt);

    return rc;
}
Beispiel #12
0
int main()
{
	char tmpfname[256];
	char buf[BUF_SIZE];
	int fd;
	struct aiocb aiocb_write;
	struct aiocb aiocb_fsync;
	int ret;

#if _POSIX_ASYNCHRONOUS_IO != 200112L
	exit(PTS_UNSUPPORTED);
#endif

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_5_1_%d", 
		  getpid());
	unlink(tmpfname);
	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL,
		  S_IRUSR | S_IWUSR);
	if (fd == -1)
	{
		printf(TNAME " Error at open(): %s\n",
		       strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	memset(&aiocb_write, 0, sizeof(aiocb_write));
	aiocb_write.aio_fildes = fd;
	aiocb_write.aio_buf = buf;
	aiocb_write.aio_nbytes = BUF_SIZE;

	if (aio_write(&aiocb_write) == -1)
	{
		printf(TNAME " Error at aio_write(): %s\n",
		       strerror(errno));
		exit(PTS_FAIL);
	}

	memset(&aiocb_fsync, 0, sizeof(aiocb_fsync));
	aiocb_fsync.aio_fildes = fd;

	if (aio_fsync(O_SYNC, &aiocb_fsync) != 0)
	{
		printf(TNAME " Error at aio_fsync(): %s\n", strerror(errno));
		exit(PTS_FAIL);
	}

	ret = PTS_UNTESTED;
	if (aio_error(&aiocb_fsync) == EINPROGRESS)
		ret = PTS_PASS;

	/* allow to check if aio_error() move from EINPROGRESS to
	 * something else
	 * otherwise test hangs
	 */

	while (aio_error(&aiocb_fsync) == EINPROGRESS);

	close(fd);

	/* we didn't check if the operation is really performed */

	return ret;
}
Beispiel #13
0
int main(int argc, const char *argv[]) {
	int ifd, ofd, i, j, n, err, numop;
	struct stat sbuf;
	const struct aiocb *aiolist[NBUF];
	off_t off = 0;
	
	if (argc != 3)
		err_quit("usage: rot13 infile outfile");
	if ((ifd = open(argv[1], O_RDONLY)) < 0)
		err_sys("can`t open %s", argv[1]);
	if ((ofd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) < 0)
		err_sys("cna`t create %s", argv[2]);
	if (fstat(ifd, &sbuf) < 0)
		err_sys("fstat failed");
	
	for (i = 0; i < NBUF; i ++) {
		bufs[i].op = UNUSED;
		bufs[i].aiocb.aio_buf = bufs[i].data;
		bufs[i].aiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
		aiolist[i] = NULL;
	}
	
	numop = 0;
	while (1) {
		for (i = 0; i < NBUF; i ++) {
			switch (bufs[i].op) {
			case UNUSED:
				if (off < sbuf.st_size) {
					bufs[i].op = READ_PENDING;
					bufs[i].aiocb.aio_fildes = ifd;
					bufs[i].aiocb.aio_offset = off;
					off += BSZ;
					if (off >= sbuf.st_size)
						bufs[i].last = 1;
					bufs[i].aiocb.aio_nbytes = BSZ;
					if (aio_read(&bufs[i].aiocb) < 0)
						err_sys("aio_read failed");
					aiolist[i] = &bufs[i].aiocb;
					numop ++;
				}
				break;
			case READ_PENDING:
				if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS)
					continue;
				if (err != 0) {
					if (err == -1)
						err_sys("aio_error failed");
					else
						err_exit(err, "read failed");
				}
				
				if ((n = aio_return(&bufs[i].aiocb)) < 0)
					err_sys("aio_return failed");
				if (n != BSZ && !bufs[i].last)
					err_quit("short read (%d/%d)", n, BSZ);
				for (j = 0; j < n; j ++)
					bufs[i].data[j] = translate(bufs[i].data[j]);
				bufs[i].op = WRITE_PENDING;
				bufs[i].aiocb.aio_fildes = ofd;
				bufs[i].aiocb.aio_nbytes = n;
				if (aio_write(&bufs[i].aiocb) < 0)
					err_sys("aio_write failed");
				break;
			case WRITE_PENDING:
				if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS)
					continue;
				if (err != 0) {
					if (err == -1)
						err_sys("aio_error failed");
					else
						err_exit(err, "write failed");
				}
				
				if ((n = aio_return(&bufs[i].aiocb)) < 0)
					err_sys("aio_return failed");
				if (n != bufs[i].aiocb.aio_nbytes)
					err_quit("short write (%d/%d)", n, BSZ);
				aiolist[i] = NULL;
				bufs[i].op = UNUSED;
				numop --;
				break;
			}
		}
		if (numop == 0) {
			if (off >= sbuf.st_size)
				break;
		} else {
			if (aio_suspend(aiolist, NBUF, NULL) < 0)
				err_sys("aio_suspend failed");
		}
	}
	bufs[0].aiocb.aio_fildes = ofd;
	if (aio_fsync(O_SYNC, &bufs[0].aiocb) < 0)
		err_sys("aio_fsync failed");
	exit(0);
}
Beispiel #14
0
static STATUS
DI_force(
    DI_IO	*f,
    DI_OP	*diop,
    CL_ERR_DESC	*err_code)
{

    STATUS	big_status = OK, small_status = OK, intern_status = OK;
    register DI_SLAVE_CB	*disl;

    do
    {
        if (Di_slave)
	{
	    disl = diop->di_evcb;
	    disl->file_op = DI_SL_SYNC;
	    /* Send file properties to slave */
	    FPROP_COPY(f->io_fprop,disl->io_fprop);

	    DI_slave_send( disl->dest_slave_no, diop,
			   &big_status, &small_status, &intern_status);

	    if (big_status != OK )
	        break;

	    if ( small_status == OK )
	    {
	        if ((small_status = disl->status) != OK )
	        {
		    STRUCT_ASSIGN_MACRO(disl->errcode, *err_code);
		}
	    }
	}
	else
	{
	    /* 
	    ** put code in here for fsync issues 
	    */
#ifdef xCL_ASYNC_IO
            if( Di_async_io)
	    {
                DI_AIOCB *aio;
                aio=DI_get_aiocb();
#ifdef dr6_us5
                aio->aio.aio_filedes=diop->di_fd;
#else
                aio->aio.aio_fildes=diop->di_fd;
#endif /* dr6_us5 */
#ifdef LARGEFILE64
                if(aio_fsync64( O_SYNC, &aio->aio))
#elif defined(any_aix)
                if(fsync( aio->aio.aio_fildes ))
#else
                if(aio_fsync( O_SYNC, &aio->aio))
#endif /* LARGEFILE64 */
                {
	        SETCLERR(err_code, 0, ER_fsync);
                    small_status = FAIL;
                    break;
                }
                else
                {
                    if( (small_status=CSsuspend( CS_DIOW_MASK, 0, 0) ) != OK)
                    {
                        DIlru_set_di_error( &small_status, err_code, 
				DI_LRU_CSSUSPEND_ERR, DI_GENERAL_ERR);
		        break;
                    }
#if defined(axp_osf) 
                    if (  (aio_error(&aio->aio)) != 0 )
#else
#ifdef LARGEFILE64
                    if (  (aio_error64(&aio->aio)) != 0 )
#else /* LARGEFILE64 */
                    if (  (aio_error(&aio->aio)) != 0 )
#endif /* LARGEFILE64 */
#endif
                    {
	                SETCLERR(err_code, 0, ER_fsync);
	                small_status = FAIL;
                        break;
                    }
                }
            }
            else 
#endif /* xCL_ASYNC_IO */
	    if (FSYNC(diop->di_fd) < 0)
	    {
#ifdef xCL_092_NO_RAW_FSYNC
		/* AIX returns EINVAL on character special files */
		if (errno != EINVAL) 
#endif /* xCL_092_NO_RAW_FSYNC */
		{
	            SETCLERR(err_code, 0, ER_fsync);
	            small_status = FAIL;
		}
	    }
	}

    } while (FALSE);

    if ( big_status != OK )
	small_status = big_status;

    if ( small_status != OK  )
        DIlru_set_di_error( &small_status, err_code, intern_status,
			    DI_GENERAL_ERR);

    return( small_status );
}
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
{
    /*
     * Parameter validation.
     */
    int rc = VINF_SUCCESS;
    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    RTFILEAIOCTX_VALID_RETURN(pCtxInt);
    AssertReturn(cReqs > 0,  VERR_INVALID_PARAMETER);
    AssertPtrReturn(pahReqs, VERR_INVALID_POINTER);
    size_t i = cReqs;

    do
    {
        int rcSol = 0;
        size_t cReqsSubmit = 0;
        PRTFILEAIOREQINTERNAL pReqInt;

        while(i-- > 0)
        {
            pReqInt = pahReqs[i];
            if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
            {
                /* Undo everything and stop submitting. */
                for (size_t iUndo = 0; iUndo < i; iUndo++)
                {
                    pReqInt = pahReqs[iUndo];
                    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                    pReqInt->pCtxInt = NULL;
                }
                rc = VERR_INVALID_HANDLE;
                break;
            }

            pReqInt->PortNotifier.portnfy_port = pCtxInt->iPort;
            pReqInt->pCtxInt                   = pCtxInt;
            RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);

            if (pReqInt->fFlush)
                break;

            cReqsSubmit++;
        }

        if (cReqsSubmit)
        {
            rcSol = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL);
            if (RT_UNLIKELY(rcSol < 0))
            {
                if (rcSol == EAGAIN)
                    rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                else
                    rc = RTErrConvertFromErrno(errno);

                /* Check which requests got actually submitted and which not. */
                for (i = 0; i < cReqs; i++)
                {
                    pReqInt = pahReqs[i];
                    rcSol = aio_error(&pReqInt->AioCB);
                    if (rcSol == EINVAL)
                    {
                        /* Was not submitted. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                        pReqInt->pCtxInt = NULL;
                    }
                    else if (rcSol != EINPROGRESS)
                    {
                        /* The request encountered an error. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                    }
                }
                break;
            }

            ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit);
            cReqs   -= cReqsSubmit;
            pahReqs += cReqsSubmit;
        }

        if (cReqs)
        {
            pReqInt = pahReqs[0];
            RTFILEAIOREQ_VALID_RETURN(pReqInt);

            /*
             * If there are still requests left we have a flush request.
             * lio_listio does not work with this requests so
             * we have to use aio_fsync directly.
             */
            rcSol = aio_fsync(O_SYNC, &pReqInt->AioCB);
            if (RT_UNLIKELY(rcSol < 0))
            {
                RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                rc = RTErrConvertFromErrno(errno);
                break;
            }

            ASMAtomicIncS32(&pCtxInt->cRequests);
            cReqs--;
            pahReqs++;
        }
    } while (cReqs);

    return rc;
}
Beispiel #16
0
int main(void)
{
	char tmpfname[256];
	char buf[BUF_SIZE];
	int fd, ret;
	struct aiocb aiocb_write;
	struct aiocb aiocb_fsync;

	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
		return PTS_UNSUPPORTED;

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_fsync_2_1_%d",
		 getpid());
	unlink(tmpfname);
	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
	if (fd == -1) {
		printf(TNAME " Error at open(): %s\n", strerror(errno));
		exit(PTS_UNRESOLVED);
	}

	unlink(tmpfname);

	memset(&aiocb_write, 0, sizeof(aiocb_write));
	aiocb_write.aio_fildes = fd;
	aiocb_write.aio_buf = buf;
	aiocb_write.aio_nbytes = BUF_SIZE;

	if (aio_write(&aiocb_write) == -1) {
		printf(TNAME " Error at aio_write(): %s\n", strerror(errno));
		exit(PTS_FAIL);
	}

	memset(&aiocb_fsync, 0, sizeof(aiocb_fsync));
	aiocb_fsync.aio_fildes = fd;

	if (aio_fsync(O_DSYNC, &aiocb_fsync) != 0) {
		printf(TNAME " Error at aio_fsync(): %s\n", strerror(errno));
		exit(PTS_FAIL);
	}

	/* wait for aio_fsync */
	do {
		usleep(10000);
		ret = aio_error(&aiocb_fsync);
	} while (ret == EINPROGRESS);

	ret = aio_return(&aiocb_fsync);
	if (ret) {
		printf(TNAME " Error at aio_return(): %d (%s)\n",
			ret, strerror(errno));
		close(fd);
		return PTS_FAIL;
	}

	/* check that aio_write is completed at this point */
	ret = aio_error(&aiocb_write);
	if (ret == EINPROGRESS) {
		printf(TNAME " aiocb_write still in progress\n");
		close(fd);
		return PTS_FAIL;
	}
	close(fd);
	return PTS_PASS;
}
Beispiel #17
0
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
{
    /*
     * Parameter validation.
     */
    int rc = VINF_SUCCESS;
    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    RTFILEAIOCTX_VALID_RETURN(pCtxInt);
    AssertReturn(cReqs > 0,  VERR_INVALID_PARAMETER);
    AssertPtrReturn(pahReqs, VERR_INVALID_POINTER);

    do
    {
        int rcBSD = 0;
        size_t cReqsSubmit = 0;
        size_t i = 0;
        PRTFILEAIOREQINTERNAL pReqInt;

        while (   (i < cReqs)
               && (i < AIO_LISTIO_MAX))
        {
            pReqInt = pahReqs[i];
            if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
            {
                /* Undo everything and stop submitting. */
                for (size_t iUndo = 0; iUndo < i; iUndo++)
                {
                    pReqInt = pahReqs[iUndo];
                    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                    pReqInt->pCtxInt = NULL;
                    pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = 0;
                }
                rc = VERR_INVALID_HANDLE;
                break;
            }

            pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = pCtxInt->iKQueue;
            pReqInt->pCtxInt                                = pCtxInt;
            RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);

            if (pReqInt->fFlush)
                break;

            cReqsSubmit++;
            i++;
        }

        if (cReqsSubmit)
        {
            rcBSD = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL);
            if (RT_UNLIKELY(rcBSD < 0))
            {
                if (errno == EAGAIN)
                    rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                else
                    rc = RTErrConvertFromErrno(errno);

                /* Check which requests got actually submitted and which not. */
                for (i = 0; i < cReqs; i++)
                {
                    pReqInt = pahReqs[i];
                    rcBSD = aio_error(&pReqInt->AioCB);
                    if (   rcBSD == -1
                        && errno == EINVAL)
                    {
                        /* Was not submitted. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                        pReqInt->pCtxInt = NULL;
                    }
                    else if (rcBSD != EINPROGRESS)
                    {
                        /* The request encountered an error. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                        pReqInt->Rc = RTErrConvertFromErrno(rcBSD);
                        pReqInt->pCtxInt      = NULL;
                        pReqInt->cbTransfered = 0;
                    }
                }
                break;
            }

            ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit);
            cReqs   -= cReqsSubmit;
            pahReqs += cReqsSubmit;
        }

        /* Check if we have a flush request now. */
        if (cReqs && RT_SUCCESS_NP(rc))
        {
            pReqInt = pahReqs[0];
            RTFILEAIOREQ_VALID_RETURN(pReqInt);

            if (pReqInt->fFlush)
            {
                /*
                 * lio_listio does not work with flush requests so
                 * we have to use aio_fsync directly.
                 */
                 rcBSD = aio_fsync(O_SYNC, &pReqInt->AioCB);
                 if (RT_UNLIKELY(rcBSD < 0))
                 {
                    if (rcBSD == EAGAIN)
                    {
                        /* Was not submitted. */
                        RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
                        pReqInt->pCtxInt = NULL;
                        return VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
                    }
                    else
                    {
                        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
                        pReqInt->Rc = RTErrConvertFromErrno(errno);
                        pReqInt->cbTransfered = 0;
                        return pReqInt->Rc;
                    }
                 }

                ASMAtomicIncS32(&pCtxInt->cRequests);
                cReqs--;
                pahReqs++;
            }
        }
    } while (cReqs);

    return rc;
}
Beispiel #18
0
int main(void)
{
  aio_fsync(1, &iocb);
  return 0;
}
Beispiel #19
0
int main(int argc, char *argv[])
{
	int ifd, ofd, i, j, n, err, numop;
	struct stat sbuf;
	struct aiocb *aiolist[NBUF];
	off_t off=0;

	printf("SIGEV_NODE:%d\n", SIGEV_NONE);
	if (argc != 3) {
		printf("usage: rot13 infile outfile");
		return -1;
	}
	if ((ifd = open(argv[1], O_RDONLY)) < 0) {
		printf("cant't open %s", argv[1]);
		return -1;
	}
	if ((ofd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) {
		printf("Cant't create %s", argv[2]);
		return -1;
	}
	if (fstat(ifd, &sbuf) < 0) {
		printf("fstat failed");
		return -1;
	}

	/* initialize the buffers */
	for (i = 0; i < NBUF; i++) {
		bufs[i].op = UNUSED;
		bufs[i].aiocb.aio_buf = bufs[i].data;
		bufs[i].aiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
		aiolist[i] = NULL;
	}

	numop = 0;
	printf("sbuf.st_size:%d\n", sbuf.st_size);
	for (;;) {
		for (i = 0; i < 1; i++) {
			switch (bufs[i].op) {
				case UNUSED:
					/*
					 * Read from the input file if more data
					 * remains unread
					 */
					if (off < sbuf.st_size) {
						bufs[i].op = 1;
						bufs[i].aiocb.aio_fildes = ifd;
						bufs[i].aiocb.aio_offset = off;
						off += BSZ;
						if (off >= sbuf.st_size)
							bufs[i].last = 1;
						bufs[i].aiocb.aio_nbytes = BSZ;
						if (aio_read(&bufs[i].aiocb) < 0)
							printf("aio_read failed");
						printf("Start aio\n");
						aiolist[i] = &bufs[i].aiocb;
						numop++;
					}
				break;
				case READ_PENDING:
					if ((err = aio_error(&bufs[i].aiocb)) == EINPROGRESS) {
						printf("Pending\n");
						continue;
					}
					if (err != 0) {
						if (err == -1)	printf("aio_error failed");
						else printf("read failed");
					}

					if ((n = aio_return(&bufs[i].aiocb)) < 0) /* A read is complete; translate the buffer and write it */
						printf("aio_return failed");
					if (n != BSZ && !bufs[i].last)
						printf("short read (%d/%d)", n, BSZ);
					for (j = 0; j < n; j++)
						bufs[i].data[j] = bufs[i].data[j];
					bufs[i].op = WRITE_PENDING;
					bufs[i].aiocb.aio_fildes = ofd;
					bufs[i].aiocb.aio_nbytes = n;
					if (aio_write(&bufs[i].aiocb) < 0)
						printf("aio_write failed");
					/* retain out spot in aiolist */
					break;
				case WRITE_PENDING:
					if ((err = aio_error(&bufs[i].aiocb)) ==  EINPROGRESS)
						continue;
					if (err != 0) {
						if (err == -1)
							printf("aio_error failed");
						else
							printf("write failed");
					}
					/*
					 * A write is complete; mark the buffer as unused.
					 */
					if ((n = aio_return(&bufs[i].aiocb)) < 0)
						printf("aio_return failed");
					if (n != bufs[i].aiocb.aio_nbytes)
						printf("short write (%d/%d)", n, BSZ);
					aiolist[i] = NULL;
					bufs[i].op = UNUSED;
					numop--;
					break;
			printf("switch ..\n");

			} //switch 
		} // small for

		if (numop == 0) {
			if (off >= sbuf.st_size)
				break;
		} else {
			if (aio_suspend(aiolist, NBUF, NULL) < 0)
				printf("aio_suspend failed");
		}

	} // big for

		bufs[0].aiocb.aio_fildes = ofd;
		if (aio_fsync(O_SYNC, &bufs[0].aiocb) <0)
			printf("aio_fsync failed");
		exit(0);
	return 0;
}
Beispiel #20
0
void *
POSIX_Init (void *argument)
{
  int fd[MAX];
  struct aiocb *aiocbp[MAX+1];
  int status, i, policy = SCHED_FIFO;
  char filename[BUFSIZE];
  struct sched_param param;

  status = rtems_aio_init ();
  rtems_test_assert (status == 0);

  param.sched_priority = 30;
  status = pthread_setschedparam (pthread_self(), policy, &param);
  rtems_test_assert (status == 0);
 
  status = mkdir ("/tmp", S_IRWXU);
  rtems_test_assert (!status);
  
  puts ("\n\n*** POSIX AIO TEST 02 ***");
  
  puts ("Init: Open files");

  for (i=0; i<MAX; i++)
    {
      sprintf (filename, "/tmp/aio_fildes%d",i);
      fd[i] = open (filename, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
      rtems_test_assert ( fd[i] != -1);
    }
  
  puts ("Init: [WQ] aio_write on 1st file");
  aiocbp[0] = create_aiocb (fd[0]);
  status = aio_write (aiocbp[0]);
  rtems_test_assert (status != -1);

  puts ("Init: [WQ] aio_write on 2nd file");
  aiocbp[1] = create_aiocb (fd[1]);
  status = aio_write (aiocbp[1]);
  rtems_test_assert (status != -1);
  
  puts ("Init: [WQ] aio_read on 2nd file add by priority");
  aiocbp[2] = create_aiocb (fd[1]);
  status = aio_read (aiocbp[2]);
  rtems_test_assert (status != -1);
  
  puts ("Init: [WQ] aio_write on 3rd file");
  aiocbp[3] = create_aiocb (fd[2]);
  status = aio_write (aiocbp[3]);
  rtems_test_assert (status != -1);
  
  puts ("Init: [WQ] aio_write on 4th file");
  aiocbp[4] = create_aiocb (fd[3]);
  status = aio_write (aiocbp[4]);
  rtems_test_assert (status != -1);
  
  puts ("Init: [WQ] aio_write on 5th file  -- [WQ] full");
  aiocbp[5] = create_aiocb (fd[4]);
  status = aio_write (aiocbp[5]);
  rtems_test_assert (status != -1);
  
  puts ("Init: [IQ] aio_write on 6th file");
  aiocbp[6] = create_aiocb (fd[5]);
  status = aio_write (aiocbp[6]);
  rtems_test_assert (status != -1);
  
  puts ("Init: [IQ] aio_write on 7th file");
  aiocbp[7] = create_aiocb (fd[6]);
  status = aio_write (aiocbp[7]);
  rtems_test_assert (status != -1);

  puts ("Init: [IQ] aio_read on 7th file add by priority");
  aiocbp[8] = create_aiocb (fd[6]); 
  status = aio_read (aiocbp[8]);
  rtems_test_assert (status != -1);

  puts ("Init: [WQ] aio_sync on 1st file add by priority");
  aiocbp[9] = create_aiocb (fd[0]); 
  status = aio_fsync (O_SYNC, aiocbp[9]);
  rtems_test_assert (status != -1);

  puts ("Init: [NONE] aio_cancel aiocbp=NULL and invalid fildes");
  status = aio_cancel (WRONG_FD, NULL);
  rtems_test_assert (status == -1);

  puts ("Init: [NONE] aio_cancel aiocbp=NULL valid fildes not in queue");
  status = aio_cancel (fd[7], NULL);
  rtems_test_assert (status == AIO_ALLDONE);

  puts ("Init: [WQ] aio_cancel aiocbp=NULL fildes=fd[1]");
  status = aio_cancel (fd[1], NULL);
  rtems_test_assert (status == AIO_CANCELED);

  puts ("Init: [IQ] aio_cancel aiocbp=NULL fildes=fd[6]");
  status = aio_cancel (fd[6], NULL);
  rtems_test_assert (status == AIO_CANCELED);

  puts ("Init: [NONE] aio_cancel aiocbp->aio_fildes != fildes");
  status = aio_cancel (fd[4],aiocbp[4]);
  rtems_test_assert (status == -1 );
 
  puts ("Init: [NONE] aio_cancel FD on [IQ], aiocb not on chain");
  aiocbp[10] = create_aiocb (fd[9]);
  status = aio_cancel (fd[9], aiocbp[10]);
  rtems_test_assert (status == -1);

  puts ("Init: [IQ] aio_cancel 6th file only one request");
  status = aio_cancel (fd[5], aiocbp[6]);
  rtems_test_assert (status == AIO_CANCELED);

  puts ("Init: [WQ] aio_cancel 1st file only one request");
  status = aio_cancel (fd[0], aiocbp[9]);
  rtems_test_assert (status == AIO_CANCELED);

  puts ("Init: [NONE] aio_cancel empty [IQ]");
  status = aio_cancel (fd[5], aiocbp[6]);
  rtems_test_assert (status == AIO_ALLDONE);

  puts ("*** END OF POSIX AIO TEST 02 ***");

  for (i = 0; i < MAX; i++)
    {
      close (fd[i]);
      free_aiocb (aiocbp[i]);      
    }
  free_aiocb (aiocbp[i]);
  rtems_test_exit (0);

  return NULL;

}
Beispiel #21
0
static int
do_test (void)
{
  int result = 0;
  int piped[2];

  /* Make a pipe that we will never write to, so we can block reading it.  */
  if (pipe (piped) < 0)
    {
      perror ("pipe");
      return 1;
    }

  /* Test for aio_cancel() detecting invalid file descriptor.  */
  {
    struct aiocb cb;
    int fd = -1;

    cb.aio_fildes = fd;
    cb.aio_offset = 0;
    cb.aio_buf = NULL;
    cb.aio_nbytes = 0;
    cb.aio_reqprio = 0;
    cb.aio_sigevent.sigev_notify = SIGEV_NONE;

    errno = 0;

    /* Case one: invalid fds that match.  */
    if (aio_cancel (fd, &cb) != -1 || errno != EBADF)
      {
	if (errno == ENOSYS)
	  {
	    puts ("no aio support in this configuration");
	    return 0;
	  }

	puts ("aio_cancel( -1, {-1..} ) did not return -1 or errno != EBADF");
	++result;
      }

    cb.aio_fildes = -2;
    errno = 0;

    /* Case two: invalid fds that do not match; just print warning.  */
    if (aio_cancel (fd, &cb) != -1 || errno != EBADF)
      puts ("aio_cancel( -1, {-2..} ) did not return -1 or errno != EBADF");
  }

  /* Test for aio_fsync() detecting bad fd.  */
  {
    struct aiocb cb;
    int fd = -1;

    cb.aio_fildes = fd;
    cb.aio_offset = 0;
    cb.aio_buf = NULL;
    cb.aio_nbytes = 0;
    cb.aio_reqprio = 0;
    cb.aio_sigevent.sigev_notify = SIGEV_NONE;

    errno = 0;

    /* Case one: invalid fd.  */
    if (aio_fsync (O_SYNC, &cb) != -1 || errno != EBADF)
      {
	puts ("aio_fsync( op, {-1..} ) did not return -1 or errno != EBADF");
	++result;
      }
  }

  /* Test for aio_suspend() suspending even if completed elements in list.  */
  {
#define BYTES 8
    const int ELEMS = 2;
    int i, r, fd;
    static char buff[BYTES];
    char name[] = "/tmp/aio7.XXXXXX";
    struct timespec timeout;
    static struct aiocb cb0, cb1;
    struct aiocb *list[ELEMS];

    fd = mkstemp (name);
    if (fd < 0)
      error (1, errno, "creating temp file");

    if (unlink (name))
      error (1, errno, "unlinking temp file");

    if (write (fd, "01234567", BYTES) != BYTES)
      error (1, errno, "writing to temp file");

    cb0.aio_fildes = fd;
    cb0.aio_offset = 0;
    cb0.aio_buf = buff;
    cb0.aio_nbytes = BYTES;
    cb0.aio_reqprio = 0;
    cb0.aio_sigevent.sigev_notify = SIGEV_NONE;

    r = aio_read (&cb0);
    if (r != 0)
      error (1, errno, "reading from file");

    while (aio_error (&(cb0)) == EINPROGRESS)
      usleep (10);

    for (i = 0; i < BYTES; i++)
      printf ("%c ", buff[i]);
    printf ("\n");

    /* At this point, the first read is completed, so start another one on
       the read half of a pipe on which nothing will be written.  */
    cb1.aio_fildes = piped[0];
    cb1.aio_offset = 0;
    cb1.aio_buf = buff;
    cb1.aio_nbytes = BYTES;
    cb1.aio_reqprio = 0;
    cb1.aio_sigevent.sigev_notify = SIGEV_NONE;

    r = aio_read (&cb1);
    if (r != 0)
      error (1, errno, "reading from file");

    /* Now call aio_suspend() with the two reads.  It should return
     * immediately according to the POSIX spec.
     */
    list[0] = &cb0;
    list[1] = &cb1;
    timeout.tv_sec = 3;
    timeout.tv_nsec = 0;
    r = aio_suspend ((const struct aiocb * const *) list, ELEMS, &timeout);

    if (r == -1 && errno == EAGAIN)
      {
	puts ("aio_suspend([done,blocked],2,3) suspended thread");
	++result;
      }

    /* Note that CB1 is still pending, and so cannot be an auto variable.
       Thus we also test that exiting with an outstanding request works.  */
  }

  return result;
}