Beispiel #1
0
Datei: 8-1.c Projekt: kraj/ltp
int main(void)
{
#define BUF_SIZE 512
	char buf[BUF_SIZE];
	struct aiocb aiocb;
	int ret = 0;
	struct timespec completion_wait_ts = {0, 10000000};

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

	memset(buf, 0xaa, BUF_SIZE);
	memset(&aiocb, 0, sizeof(struct aiocb));
	aiocb.aio_fildes = -1;
	aiocb.aio_buf = buf;
	aiocb.aio_nbytes = BUF_SIZE;

	/*
	 * EBADF is encountered at a later stage
	 * and should be collected by aio_error()
	 */

	if (aio_write(&aiocb) != 0) {
		printf(TNAME " bad aio_write return value()\n");
		exit(PTS_FAIL);
	}

	do {
		nanosleep(&completion_wait_ts, NULL);
		ret = aio_error(&aiocb);
	} while (ret == EINPROGRESS);

	if (ret != EBADF) {
		printf(TNAME " errno is not EBADF %s\n", strerror(errno));
		exit(PTS_FAIL);
	}

	printf("Test PASSED\n");
	return PTS_PASS;
}
Beispiel #2
0
		void _write(string path, string src) {
			char buff[BUF_SIZE];
			strcpy(buff, src.c_str());
			int fd = open(path.c_str(), O_RDWR | O_EXCL | O_APPEND, S_IRUSR | S_IWUSR);
			if(fd == -1) {
				string error = "fail to open: ";
				error += path;
				error += ", fileAsync.cpp::write(string) - ";
				error += strerror(errno);
				Debug::error(error);
				return;
			}
			struct aiocb aio;
			aio.aio_fildes = fd;
			aio.aio_buf = buff;
			aio.aio_nbytes = BUF_SIZE;

			if(aio_write(&aio) == -1) {
				string error = "fileAsync.cpp::aio_write()::==-1 - ";
				error += strerror(errno); 
				Debug::error(error);
				return;
			}
			int err;
			int ret;
			while(aio_write(&aio) == EINPROGRESS);
			err = aio_error(&aio);
			if(!err) {
				string error = "fileAsync.cpp::aio_write()::!err - ";
				error += strerror(errno); 
				Debug::error(error);
				return;
			}
			if(ret!=BUF_SIZE) {
				string error = "fileAsync.cpp::aio_write()::ret!=BUF_SIZE - ";
				error += strerror(errno); 
				Debug::error(error);
				return;
			}
		}
Beispiel #3
0
static int swAioGcc_onFinish(swReactor *reactor, swEvent *event)
{
    swAio_gcc_t *req = swAioGcc_request;
    swAio_event aio_ev;
    char finished_aio;
    int ret;

    if (read(event->fd, &finished_aio, sizeof(finished_aio)) != sizeof(finished_aio))
    {
        swWarn("read failed. Error: %s[%d]", strerror(errno), errno);
        return SW_ERR;
    }

    while (1)
    {
        if (aio_error(&req->aiocb) == 0)
        {
            ret = aio_return(&req->aiocb);
            aio_ev.ret = ret;
            aio_ev.fd = req->aiocb.aio_fildes;
            aio_ev.type = req->aiocb.aio_lio_opcode == LIO_READ ? SW_AIO_READ : SW_AIO_WRITE;
            aio_ev.nbytes = ret;
            aio_ev.offset = req->aiocb.aio_offset;
            aio_ev.buf = (void *) req->aiocb.aio_buf;
            SwooleAIO.callback(&aio_ev);
        }

        if (req->next == NULL)
        {
            sw_free(req);
            break;
        }
        else
        {
            req = req->next;
        }
        sw_free(req);
    }
    return SW_OK;
}
Beispiel #4
0
void
on_input(int sig)
{
	int c;
	char *cp = (char *) kbcbuf.aio_buf;

	if (aio_error(&kbcbuf) != 0) {
		perror("aio_read() failed:");
	} else {
		/* get number of chars to read */
		if (aio_return(&kbcbuf) == 1) {
			c = *cp;
			if (c == 'Q' || c == EOF)
				done = 1;
			else if (c == ' ')
				dir = -dir;
		}
	}

	/* place new request */
	aio_read(&kbcbuf);
}
Beispiel #5
0
Datei: scan.c Projekt: afb/ddar
static void finish_aio(struct scan_ctx *scan) {
    int bytes_read;
    off_t required_offset, lseek_result;

    const struct aiocb *cblist[1] = { &scan->aiocb };
    if (TEMP_FAILURE_RETRY(aio_suspend(cblist, 1, 0))) {
	longjmp(scan->jmp_env, 1);
    }
    if (aio_error(&scan->aiocb)) {
	longjmp(scan->jmp_env, 1);
    }
    bytes_read = aio_return(&scan->aiocb);
    if (!bytes_read) {
	scan->eof = 1;
	return;
    } else if (bytes_read != scan->buffer_size / 3) {
	required_offset = scan->source_offset + bytes_read;
	/* If we have been reading from a regular file, then the current
	   offset will not match the data we have read in using aio_read,
	   since that doesn't alter the offset, so we need to seek to the
	   correct offset. However, we could have been reading from a pipe, in
	   which case this lseek will fail because of ESPIPE, which is fine
	   since there is no "offset" to be misaligned and we should
	   still fill the buffer. Any other failure is an error */
	lseek_result = lseek(scan->fd, required_offset, SEEK_SET);
	if ((lseek_result == required_offset) ||
		(lseek_result < 0 && errno == ESPIPE))
	    bytes_read += retry_read(scan,
				     scan->io_destination + bytes_read,
				     scan->buffer_size / 3 - bytes_read);
	else
	    longjmp(scan->jmp_env, 1);
    }

    posix_fadvise(scan->fd, scan->source_offset, bytes_read, POSIX_FADV_DONTNEED);
    scan->source_offset += bytes_read;
    scan->bytes_left += bytes_read;
}
void TFileAioWriter::flush()
{
    if (!isOpen()) {
        return;
    }

    if (d->syncBuffer.count() == 0) {
        return;
    }

    QMutexLocker locker(&d->mutex);
    struct aiocb *headcb;

    while (d->syncBuffer.count() > 0) {
        if (d->syncBuffer.head(headcb) && aio_error(headcb) != EINPROGRESS) {
            // Dequeue
            if (d->syncBuffer.dequeue(headcb)) {
                delete[] (char *)headcb->aio_buf;
                delete headcb;
            }
        }
    }
}
Beispiel #7
0
// aio 요청이 완료되면 실행되는 스레드
static void thread_func(sigval_t sv)
{
	struct aiocb *my_aiocb = sv.sival_ptr;
	ssize_t numwrite;

/*
	aio 요청 상태 확인한다. 다음 중 하나의 값을 리턴함.
	- EINPROGRESS: aio가 아직 완료되지 않음
	- ECANCELED: aio 요청이 취소됨.
	- 0: aio 요청이 성공적으로 완료됨.
*/
	if(aio_error(my_aiocb) != EINPROGRESS) {
/*
		aio 요청의 완료 상태를 확인한다.
		aio_error가 EINPROGRESS가 아닌 값을 리턴했을 때 확인해야 한다.
		write나 read 요청과 같은 값을 리턴한다.
*/
		if((numwrite = aio_return(my_aiocb)) == -1)
			errexit("aio_return");

		printf("write bytes = %ld, %s\n", numwrite, (char *)my_aiocb->aio_buf);
	}
}
Beispiel #8
0
static void
async_append_wait(struct async_append *ap)
{
    int n = 0;

    while (!async_append_is_empty(ap)) {
        struct aiocb *aiocb = &ap->aiocbs[ap->aiocb_tail & (MAX_CBS - 1)];
        int error = aio_error(aiocb);

        if (error == EINPROGRESS) {
            const struct aiocb *p = aiocb;
            if (n > 0) {
                return;
            }
            aio_suspend(&p, 1, NULL);
        } else {
            ignore(aio_return(aiocb));
            ap->aiocb_tail++;
            byteq_advance_tail(&ap->byteq, aiocb->aio_nbytes);
            n++;
        }
    }
}
Beispiel #9
0
int main(void)
{
	int fd, ret;
	struct aiocb my_aiocb;

	fd = open("file.txt",O_RDONLY);
	if (fd < 0)
		perror("open");

	bzero((char*) &my_aiocb, sizeof(struct aiocb));

	my_aiocb.aio_buf = malloc(BUFSIZE + 1);
	if (!my_aiocb.aio_buf)
		perror("malloc");

	my_aiocb.aio_fildes = fd;
	my_aiocb.aio_nbytes = BUFSIZE;
	my_aiocb.aio_offset = 0;

	ret = aio_read(&my_aiocb);
	if (ret < 0)
		perror("aio_read");

	while (aio_error(&my_aiocb) == EINPROGRESS)
		continue;

	if((ret = aio_return(&my_aiocb)))
	{
		printf("ret:%d,read:%s\n",ret,my_aiocb.aio_buf);
	} else {
		printf("read 0\n");	
	}

	
	close(fd);
	return 0;
}
Beispiel #10
0
// handle a completed write operation
// put error codes into future->aio_rc and future->write_rc
// always succeeds
void md_cache_aio_write_completion( sigval_t sigval ) {
   
   struct md_syndicate_cache_aio_write_args* wargs = (struct md_syndicate_cache_aio_write_args*)sigval.sival_ptr;
   
   struct md_syndicate_cache* cache = wargs->cache;
   struct md_cache_block_future* future = wargs->future;
   
   // successful completion?
   int write_rc = 0;
   int aio_rc = aio_error( &future->aio );
   if( aio_rc == 0 ) {
      
      // yup!
      write_rc = aio_return( &future->aio );
      
      if( write_rc == -1 ) {
         write_rc = -errno;
      }
      else {
         // rewind file handle, so other subsystems (i.e. replication) can access it 
         lseek( future->block_fd, 0, SEEK_SET );
      }
   }
   else {
      write_rc = -aio_rc;
   }
   
   future->aio_rc = aio_rc;
   future->write_rc = write_rc;
   
   // enqueue for reaping
   md_cache_completed_wlock( cache );
   
   cache->completed->push_back( future );
   
   md_cache_completed_unlock( cache );
}
Beispiel #11
0
void check_reqs() {
    while (reqs) {
        int val = aio_error(reqs->aio);
        if (val != EINPROGRESS) {
            enum atypes type =  (reqs->type);
            reqs->type = done;
            switch (type) {
                case aread:
                    handle_read(reqs, val);
                    break;
                case awrite:
                    handle_write(reqs, val);
                    break;
#ifdef F_ASYNC_GETDIR
                case agetdir:
                    handle_getdir(reqs, val);
                    break;
#endif
                case done:
                    //must have had an error while handling it before.
                    break;
                default:
                    fatal("unknown async type\n");
            }
            struct request *here = reqs;
            reqs = reqs->next;
            if(!reqs)
                lastreq = reqs;
            free_aiob(here->aio);
            free_funp(here->fun->f.fp);
            free_cb(here->fun);
            free_req(here);
        } else
            return;
    }
}
Beispiel #12
0
void aio_read_completion_handler(sigval_t sigval)
{
    api_stream_file_read_t* read = (api_stream_file_read_t*)sigval.sival_ptr;
    ssize_t result;
    int error = aio_error(&read->aio);

    if (error == 0)
    {
        result = aio_return(&read->aio);
        if (result < 0)
        {
            read->error = api_error_translate(result);
            result = 0;
        }

        read->done = result;
    }
    else
    {
        read->error = api_error_translate(error);
    }

    api_async_wakeup(read->loop, read->task);
}
Beispiel #13
0
static int a_wait(struct aio_ring *ring, int blk)
{
	struct aio_block *b = &ring->blocks[blk % ring->num_blocks];

	if (b->blk != blk) return -1;

	if (b->done) return 0;

	if (aio_suspend(&b->cb, 1, NULL) != 0 ||
	    aio_error(b->cb) != 0) {
		free(b->buffer);
		free(b->cb);
		b->buffer = NULL;
		b->cb     = NULL;
		b->blk    = -1;
		return -1;
	}

	b->done = 1;
	b->nread = aio_return(b->cb);
	if (b->nread < 0) return -1;

	return 0;
}
Beispiel #14
0
IoObject *IoAsyncRequest_error(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
{
	/*doc AsyncRequest error
	Returns sequence containing the last error or nil otherwise. 
	*/
	int r;

	errno = 0;

	r = aio_error(IOCB(self));

	if (r == -1)
	{
		char *s = strerror(errno);

		if (errno == 22)
		{
			s = "The iocb argument does not reference an outstanding asynchronous I/O request.";
			printf("AsyncRequest error: %s\n", s);
			//return IOSYMBOL("The iocb argument does not reference an outstanding asynchronous I/O request.");
			return IONIL(self);
		}

		printf("AsyncRequest errno %i : %s' EINVAL = %i\n", errno, s, EINVAL);
		return IOSYMBOL(s);
	}

	if (r != 0 && r != EINPROGRESS)
	{
		char *s = strerror(r);
		printf("AsyncRequest error %i\n", r);
		return IOSYMBOL(s);
	}

	return IONIL(self);
}
Beispiel #15
0
static void aio_posix_signal_handler(struct tevent_context *ev,
				     struct tevent_signal *se,
				     int signum, int count,
				     void *_info, void *private_data)
{
	siginfo_t *info;
	struct tevent_req *req;
	struct aio_posix_state *state;
	int err;

	info = (siginfo_t *)_info;
	req = talloc_get_type_abort(info->si_value.sival_ptr,
				    struct tevent_req);
	state = tevent_req_data(req, struct aio_posix_state);

	err = aio_error(&state->acb);
	if (err == EINPROGRESS) {
		DEBUG(10, ("aio_posix_signal_handler: operation req %p "
			   "still in progress\n", req));
		return;
	}
	if (err == ECANCELED) {
		DEBUG(10, ("aio_posix_signal_handler: operation req %p "
			   "canceled\n", req));
		return;
	}

	/*
	 * No need to suspend for this in the destructor anymore
	 */
	talloc_set_destructor(state, NULL);

	state->ret = aio_return(&state->acb);
	state->err = err;
	tevent_req_done(req);
}
/* ARGSUSED */
static void aiohandler(int signo, siginfo_t *info, void *context) {
   int  myerrno, mystatus, serrno;
   serrno = errno;
   myerrno = aio_error(&aiocb);
   if (myerrno == EINPROGRESS) {
      errno = serrno;
      return;
   }
   if (myerrno) {
      seterror(myerrno);
      errno = serrno;
      return;
   }
   mystatus = aio_return(&aiocb);
   totalbytes += mystatus;
   aiocb.aio_offset += mystatus;
   if (mystatus == 0) 
      doneflag = 1;
   else if (r_write(fdout, (char *)aiocb.aio_buf, mystatus) == -1) 
      seterror(errno);
   else if (readstart() == -1)
      seterror(errno);
   errno = serrno;
}
Beispiel #17
0
void RecData::RecordThread()
{
	lt_info("%s: begin\n", __func__);
	hal_set_threadname("hal:record");
	const int readsize = bufsize / 16;
	int buf_pos = 0;
	int queued = 0;
	struct aiocb a;

	int val = fcntl(file_fd, F_GETFL);
	if (fcntl(file_fd, F_SETFL, val|O_APPEND))
		lt_info("%s: O_APPEND? (%m)\n", __func__);

	memset(&a, 0, sizeof(a));
	a.aio_fildes = file_fd;
	a.aio_sigevent.sigev_notify = SIGEV_NONE;

	dmx->Start();
	int overflow_count = 0;
	bool overflow = false;
	int r = 0;
	while (exit_flag == RECORD_RUNNING)
	{
		if (buf_pos < bufsize)
		{
			if (overflow_count) {
				lt_info("%s: Overflow cleared after %d iterations\n", __func__, overflow_count);
				overflow_count = 0;
			}
			int toread = bufsize - buf_pos;
			if (toread > readsize)
				toread = readsize;
			ssize_t s = dmx->Read(buf + buf_pos, toread, 50);
			lt_debug("%s: buf_pos %6d s %6d / %6d\n", __func__,
				buf_pos, (int)s, bufsize - buf_pos);
			if (s < 0)
			{
				if (errno != EAGAIN && (errno != EOVERFLOW || !overflow))
				{
					lt_info("%s: read failed: %m\n", __func__);
					exit_flag = RECORD_FAILED_READ;
					state = REC_STATUS_OVERFLOW;
					break;
				}
			}
			else
			{
				overflow = false;
				buf_pos += s;
			}
		}
		else
		{
			if (!overflow)
				overflow_count = 0;
			overflow = true;
			if (!(overflow_count % 10))
				lt_info("%s: buffer full! Overflow? (%d)\n", __func__, ++overflow_count);
			state = REC_STATUS_SLOW;
		}
		r = aio_error(&a);
		if (r == EINPROGRESS)
		{
			lt_debug("%s: aio in progress, free: %d\n", __func__, bufsize - buf_pos);
			continue;
		}
		// not calling aio_return causes a memory leak  --martii
		r = aio_return(&a);
		if (r < 0)
		{
			exit_flag = RECORD_FAILED_FILE;
			lt_debug("%s: aio_return = %d (%m)\n", __func__, r);
			break;
		}
		else
			lt_debug("%s: aio_return = %d, free: %d\n", __func__, r, bufsize - buf_pos);
		if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED))
			perror("posix_fadvise");
		if (queued)
		{
			memmove(buf, buf + queued, buf_pos - queued);
			buf_pos -= queued;
		}
		queued = buf_pos;
		a.aio_buf = buf;
		a.aio_nbytes = queued;
		r = aio_write(&a);
		if (r)
		{
			lt_info("%s: aio_write %d (%m)\n", __func__, r);
			exit_flag = RECORD_FAILED_FILE;
			break;
		}
	}
	dmx->Stop();
	while (true) /* write out the unwritten buffer content */
	{
		lt_debug("%s: run-out write, buf_pos %d\n", __func__, buf_pos);
		r = aio_error(&a);
		if (r == EINPROGRESS)
		{
			usleep(50000);
			continue;
		}
		r = aio_return(&a);
		if (r < 0)
		{
			exit_flag = RECORD_FAILED_FILE;
			lt_info("%s: aio_result: %d (%m)\n", __func__, r);
			break;
		}
		if (!queued)
			break;
		memmove(buf, buf + queued, buf_pos - queued);
		buf_pos -= queued;
		queued = buf_pos;
		a.aio_buf = buf;
		a.aio_nbytes = queued;
		r = aio_write(&a);
	}

#if 0
	// TODO: do we need to notify neutrino about failing recording?
	CEventServer eventServer;
	eventServer.registerEvent2(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, "/tmp/neutrino.sock");
	stream2file_status2_t s;
	s.status = exit_flag;
	strncpy(s.filename,basename(myfilename),512);
	s.filename[511] = '\0';
	strncpy(s.dir,dirname(myfilename),100);
	s.dir[99] = '\0';
	eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s));
	printf("[stream2file]: pthreads exit code: %i, dir: '%s', filename: '%s' myfilename: '%s'\n", exit_flag, s.dir, s.filename, myfilename);
#endif

	lt_info("%s: end\n", __func__);
	pthread_exit(NULL);
}
Beispiel #18
0
int
main(int argc, char *argv[])
{
   struct ioRequest *ioList;
   struct aiocb *aiocbList;
   struct sigaction sa;
   int s, j;
   int numReqs;        /* Total number of queued I/O requests */
   int openReqs;       /* Number of I/O requests still in progress */

   if (argc < 2) {
       fprintf(stderr, "Usage: %s <pathname> <pathname>...\n",
               argv[0]);
       exit(EXIT_FAILURE);
   }

   numReqs = argc - 1;

   /* Allocate our arrays */

   ioList = calloc(numReqs, sizeof(struct ioRequest));
   if (ioList == NULL)
       errExit("calloc");

   aiocbList = calloc(numReqs, sizeof(struct aiocb));
   if (aiocbList == NULL)
       errExit("calloc");

   /* Establish handlers for SIGQUIT and the I/O completion signal */

   sa.sa_flags = SA_RESTART;
   sigemptyset(&sa.sa_mask);

   sa.sa_handler = quitHandler;
   if (sigaction(SIGQUIT, &sa, NULL) == -1)
       errExit("sigaction");

   sa.sa_flags = SA_RESTART | SA_SIGINFO;
   sa.sa_sigaction = aioSigHandler;
   if (sigaction(IO_SIGNAL, &sa, NULL) == -1)
       errExit("sigaction");

   /* Open each file specified on the command line, and queue
      a read request on the resulting file descriptor */

   for (j = 0; j < numReqs; j++) {
       ioList[j].reqNum = j;
       ioList[j].status = EINPROGRESS;
       ioList[j].aiocbp = &aiocbList[j];

       ioList[j].aiocbp->aio_fildes = open(argv[j + 1], O_RDONLY);
       if (ioList[j].aiocbp->aio_fildes == -1)
           errExit("open");
       printf("opened %s on descriptor %d\n", argv[j + 1],
               ioList[j].aiocbp->aio_fildes);

       ioList[j].aiocbp->aio_buf = malloc(BUF_SIZE);
       if (ioList[j].aiocbp->aio_buf == NULL)
           errExit("malloc");

       ioList[j].aiocbp->aio_nbytes = BUF_SIZE;
       ioList[j].aiocbp->aio_reqprio = 0;
       ioList[j].aiocbp->aio_offset = 0;
       ioList[j].aiocbp->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
       ioList[j].aiocbp->aio_sigevent.sigev_signo = IO_SIGNAL;
       ioList[j].aiocbp->aio_sigevent.sigev_value.sival_ptr =
                               &ioList[j];

       s = aio_read(ioList[j].aiocbp);
       if (s == -1)
           errExit("aio_read");
   }

   openReqs = numReqs;

   /* Loop, monitoring status of I/O requests */

   while (openReqs > 0) {
       sleep(3);       /* Delay between each monitoring step */

       if (gotSIGQUIT) {

           /* On receipt of SIGQUIT, attempt to cancel each of the
              outstanding I/O requests, and display status returned
              from the cancellation requests */

           printf("got SIGQUIT; canceling I/O requests: \n");

           for (j = 0; j < numReqs; j++) {
               if (ioList[j].status == EINPROGRESS) {
                   printf("    Request %d on descriptor %d:", j,
                           ioList[j].aiocbp->aio_fildes);
                   s = aio_cancel(ioList[j].aiocbp->aio_fildes,
                           ioList[j].aiocbp);
                   if (s == AIO_CANCELED)
                       printf("I/O canceled\n");
                   else if (s == AIO_NOTCANCELED)
                           printf("I/O not canceled\n");
                   else if (s == AIO_ALLDONE)
                       printf("I/O all done\n");
                   else
                       errMsg("aio_cancel");
               }
           }

           gotSIGQUIT = 0;
       }

       /* Check the status of each I/O request that is still
          in progress */

       printf("aio_error():\n");
       for (j = 0; j < numReqs; j++) {
           if (ioList[j].status == EINPROGRESS) {
               printf("    for request %d (descriptor %d): ",
                       j, ioList[j].aiocbp->aio_fildes);
               ioList[j].status = aio_error(ioList[j].aiocbp);

               switch (ioList[j].status) {
               case 0:
                   printf("I/O succeeded\n");
                   break;
               case EINPROGRESS:
                   printf("In progress\n");
                   break;
               case ECANCELED:
                   printf("Canceled\n");
                   break;
               default:
                   errMsg("aio_error");
                   break;
               }

               if (ioList[j].status != EINPROGRESS)
                   openReqs--;
           }
       }
   }

   printf("All I/O requests completed\n");

   /* Check status return of all I/O requests */

   printf("aio_return():\n");
   for (j = 0; j < numReqs; j++) {
       ssize_t s;

       s = aio_return(ioList[j].aiocbp);
       printf("    for request %d (descriptor %d): %zd\n",
               j, ioList[j].aiocbp->aio_fildes, s);
   }

   exit(EXIT_SUCCESS);
}
// Òì²½IO
ssize_t
ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size)
{
    int           n;
    ngx_event_t  *rev;

    rev = c->read;

    if (!rev->ready) {
        ngx_log_error(NGX_LOG_ALERT, c->log, 0, "second aio post");
        return NGX_AGAIN;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   "rev->complete: %d", rev->complete);
    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   "aio size: %d", size);

    if (!rev->complete) {
        ngx_memzero(&rev->aiocb, sizeof(struct aiocb));

        rev->aiocb.aio_fildes = c->fd;
        rev->aiocb.aio_buf = buf;
        rev->aiocb.aio_nbytes = size;

#if (NGX_HAVE_KQUEUE)
        rev->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue;
        rev->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
        rev->aiocb.aio_sigevent.sigev_value.sigval_ptr = rev;
#endif

        if (aio_read(&rev->aiocb) == -1) {
            ngx_log_error(NGX_LOG_CRIT, rev->log, ngx_errno,
                          "aio_read() failed");
            rev->error = 1;
            return NGX_ERROR;
        }

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                       "aio_read: #%d OK", c->fd);

        rev->active = 1;
        rev->ready = 0;
    }

    rev->complete = 0;

    n = aio_error(&rev->aiocb);
    if (n == -1) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "aio_error() failed");
        rev->error = 1;
        return NGX_ERROR;
    }

    if (n != 0) {
        if (n == NGX_EINPROGRESS) {
            if (rev->ready) {
                ngx_log_error(NGX_LOG_ALERT, c->log, n,
                              "aio_read() still in progress");
                rev->ready = 0;
            }
            return NGX_AGAIN;
        }

        ngx_log_error(NGX_LOG_CRIT, c->log, n, "aio_read() failed");
        rev->error = 1;
        rev->ready = 0;
        return NGX_ERROR;
    }

    n = aio_return(&rev->aiocb);
    if (n == -1) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      "aio_return() failed");

        rev->error = 1;
        rev->ready = 0;
        return NGX_ERROR;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, rev->log, 0,
                   "aio_read: #%d %d", c->fd, n);

    if (n == 0) {
        rev->eof = 1;
        rev->ready = 0;
    } else {
        rev->ready = 1;
    }

    rev->active = 0;

    return n;
}
Beispiel #20
0
int
main ()
{
	char tmpfname[256];
	int fd;

	struct aiocb **aiocbs;
	struct aiocb *plist[2];
	char *bufs;
	struct sigaction action;
	struct sigevent event;
	int errors = 0;
	int ret;
	int err;
	int i;

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

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_suspend_8_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);

	bufs = (char *) malloc (NUM_AIOCBS*BUF_SIZE);

	if (bufs == NULL) {
		printf (TNAME " Error at malloc(): %s\n", strerror (errno));
		close (fd);
		exit(PTS_UNRESOLVED);
	}

	if (write (fd, bufs, NUM_AIOCBS*BUF_SIZE) != (NUM_AIOCBS*BUF_SIZE)) {
		printf(TNAME " Error at write(): %s\n", strerror(errno));
		free (bufs);
		close (fd);
		exit(PTS_UNRESOLVED);
	}



	aiocbs = (struct aiocb**)malloc(sizeof(struct aiocb *) * NUM_AIOCBS);

	/* Queue up a bunch of aio reads */
	for (i = 0; i < NUM_AIOCBS; i++) {

		aiocbs[i] = (struct aiocb*)malloc(sizeof(struct aiocb));
		memset(aiocbs[i], 0, sizeof(struct aiocb));

		aiocbs[i]->aio_fildes = fd;
		aiocbs[i]->aio_offset = i * BUF_SIZE;
		aiocbs[i]->aio_buf = &bufs[i*BUF_SIZE];
		aiocbs[i]->aio_nbytes = BUF_SIZE;
		aiocbs[i]->aio_lio_opcode = LIO_READ;

		/* Use SIRTMIN+1 for individual completions */
		aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
		aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN+1;
		aiocbs[i]->aio_sigevent.sigev_value.sival_int = i;
	}

	/* Use SIGRTMIN+2 for list completion */
	event.sigev_notify = SIGEV_SIGNAL;
	event.sigev_signo = SIGRTMIN+2;
	event.sigev_value.sival_ptr = NULL;

	/* Setup handler for individual operation completion */
	action.sa_sigaction = sigrt1_handler;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_SIGINFO|SA_RESTART;
	sigaction(SIGRTMIN+1, &action, NULL);

	/* Setup handler for list completion */
	action.sa_sigaction = sigrt2_handler;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_SIGINFO|SA_RESTART;
	sigaction(SIGRTMIN+2, &action, NULL);

	/* Setup suspend list */
	plist[0] = NULL;
	plist[1] = aiocbs[WAIT_FOR_AIOCB];

	/* Submit request list */
	ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);

	if (ret) {
		printf(TNAME " Error at lio_listio() %d: %s\n", errno, strerror(errno));
		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		free (aiocbs);
		close (fd);
		exit (PTS_UNRESOLVED);
	}

	/* Check selected request has not completed yet */
	if (received_selected) {
		printf (TNAME " Error : AIOCB %d already completed before suspend\n",
			WAIT_FOR_AIOCB);
		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		free (aiocbs);
		close (fd);
		exit (PTS_FAIL);
	}

	/* Suspend on selected request */
	ret = aio_suspend((const struct aiocb **)plist, 2, NULL);

	if (ret) {
		printf (TNAME " Error at aio_suspend() %d: %s\n", errno, strerror (errno));
		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		free (aiocbs);
		close (fd);
		exit (PTS_FAIL);
	}

	/* Check selected request has completed */
	err = aio_error (aiocbs[WAIT_FOR_AIOCB]);
	ret = aio_return (aiocbs[WAIT_FOR_AIOCB]);
	
	if ((err != 0) && (ret !=  BUF_SIZE)) {
		printf (TNAME " Error : AIOCB %d should have completed after suspend\n",
			WAIT_FOR_AIOCB);
		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		free (aiocbs);
		close (fd);
		exit (PTS_FAIL);
	}


	/* Wait for list processing completion */
	while (!received_all)
		sleep (1);

	/* Check return code and free things */
	for (i = 0; i < NUM_AIOCBS; i++) {
		if (i == WAIT_FOR_AIOCB)
			continue;

	  	err = aio_error(aiocbs[i]);
		ret = aio_return(aiocbs[i]);

		if ((err != 0) && (ret != BUF_SIZE)) {
			printf(TNAME " req %d: error = %d - return = %d\n", i, err, ret);
			errors++;
		}

		free (aiocbs[i]);
	}

	free (bufs);
	free (aiocbs);

	close(fd);

	if (errors != 0)
		exit (PTS_FAIL);

	printf (TNAME " PASSED\n");

	return PTS_PASS;
}
Beispiel #21
0
// Set the necessary things for the AIO stuff.
// Write the buffer asynchly.hmm Disable signals.
// Go on aio_suspend. Wait for completion.
// Print out the result.
int
Test_Aio::do_aio (void)
{
  // = Write to the file.

  // Setup AIOCB.
  this->aiocb_write_->aio_fildes = this->out_fd_;
  this->aiocb_write_->aio_offset = 0;
  this->aiocb_write_->aio_buf = this->buffer_write_;
  this->aiocb_write_->aio_nbytes = strlen (this->buffer_write_);
  this->aiocb_write_->aio_reqprio = 0;
  this->aiocb_write_->aio_sigevent.sigev_notify = SIGEV_NONE;
  //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX;
  this->aiocb_write_->aio_sigevent.sigev_value.sival_ptr =
    (void *) this->aiocb_write_;

  // Fire off the aio write.
  if (aio_write (this->aiocb_write_) != 0)
    {
      perror ("aio_write");
      return -1;
    }

  // = Read from that file.

  // Setup AIOCB.
  this->aiocb_read_->aio_fildes = this->out_fd_;
  this->aiocb_read_->aio_offset = 0;
  this->aiocb_read_->aio_buf = this->buffer_read_;
  this->aiocb_read_->aio_nbytes = strlen (this->buffer_write_);
  this->aiocb_read_->aio_reqprio = 0;
  this->aiocb_read_->aio_sigevent.sigev_notify = SIGEV_NONE;
  //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX;
  this->aiocb_read_->aio_sigevent.sigev_value.sival_ptr =
    (void *) this->aiocb_read_;

  // Fire off the aio write. If it doesnt get queued, carry on to get
  // the completion for the first one.
  if (aio_read (this->aiocb_read_) < 0)
    perror ("aio_read");
  
  // Wait for the completion on aio_suspend.
  struct aiocb *list_aiocb[2];
  list_aiocb [0] = this->aiocb_write_;
  list_aiocb [1] = this->aiocb_read_;

  // Do suspend till all the aiocbs in the list are done.
  int done = 0;
  int return_val = 0;
  while (!done)
    {
      return_val = aio_suspend (list_aiocb,
                                2,
                                0);
      cerr << "Return value :" << return_val << endl;

      // Analyze return and error values.
      if (aio_error (list_aiocb [0]) != EINPROGRESS)
        {
          if (aio_return (list_aiocb [0]) == -1)
            {
              perror ("aio_return");
              return -1;
            }
          else
            {
              // Successful. Store the pointer somewhere and make the
              // entry NULL in the list.
              this->aiocb_write_ = list_aiocb [0];
              list_aiocb [0] = 0;
            }
        }
      else
        cout << "AIO in progress" << endl;

      if (aio_error (list_aiocb [1]) != EINPROGRESS)
        {
          if (aio_return (list_aiocb [1]) == -1)
            {
              perror ("aio_return");
              return -1;
            }
          else
            {
              // Successful. Store the pointer somewhere and make the
              // entry NULL in the list.
              this->aiocb_read_ = list_aiocb [1];
              list_aiocb [1] = 0;
            }
        }
      else
        cout << "AIO in progress" << endl;

      // Is it done?
      if ((list_aiocb [0] == 0) && (list_aiocb [1] == 0))
        done = 1;
    }

  cout << "Both the AIO operations done." << endl;
  cout << "The buffer is :" << this->buffer_read_ << endl;
  
  return 0;
}
Beispiel #22
0
int main()
{
	char tmpfname[256];
#define BUF_SIZE 512
	unsigned char buf[BUF_SIZE];
	unsigned char check[BUF_SIZE];
	int fd;
	struct aiocb aiocb;
	struct aiocb *list[1];
	int err;
	int ret;
	int i;

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

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_lio_listio_9_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);

	for (i = 0; i < BUF_SIZE; i++)
		buf[i] = i;

	memset(&aiocb, 0, sizeof(struct aiocb));
	aiocb.aio_fildes = fd;
	aiocb.aio_buf = buf;
	aiocb.aio_nbytes = BUF_SIZE;
	aiocb.aio_lio_opcode = LIO_WRITE;

	list[0] = &aiocb;

	if (lio_listio(LIO_WAIT, list, 1, NULL) == -1) {
		printf(TNAME " Error at lio_listio(): %s\n", strerror(errno));
		exit(PTS_FAIL);
	}

	/* Check return values */
	err = aio_error(&aiocb);
	ret = aio_return(&aiocb);

	if (err != 0) {
		printf(TNAME " Error at aio_error(): %s\n", strerror(errno));

		close(fd);
		exit(PTS_FAIL);
	}

	if (ret != BUF_SIZE) {
		printf(TNAME " Error at aio_return(): %d\n", ret);

		close(fd);
		exit(PTS_FAIL);
	}

	memset(check, 0xaa, BUF_SIZE);

	if (read(fd, check, BUF_SIZE) != BUF_SIZE) {
		printf(TNAME " Error at read(): %s\n", strerror(errno));

		close(fd);
		exit(PTS_UNRESOLVED);
	}

	/* check it */

	for (i = 0; i < BUF_SIZE; i++) {
		if (buf[i] != check[i]) {
			printf(TNAME " read values are corrupted\n");
			exit(PTS_FAIL);
		}
	}

	close(fd);
	printf("Test PASSED\n");
	return PTS_PASS;
}
Beispiel #23
0
Datei: 9-1.c Projekt: 1587/ltp
int main(void)
{
	char tmpfname[256];
#define BUF_SIZE 111
	char buf[BUF_SIZE];
	int fd;
	struct aiocb aiocb;

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

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_write_9_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, 0, sizeof(struct aiocb));
	aiocb.aio_fildes = fd;
	aiocb.aio_buf = buf;
	aiocb.aio_offset = -1;
	aiocb.aio_nbytes = BUF_SIZE;

	if (aio_write(&aiocb) != -1) {
		int err;
		do {
			usleep(10000);
			err = aio_error(&aiocb);
		} while (err == EINPROGRESS);

		int ret = aio_return(&aiocb);

		if (ret != -1) {
			printf(TNAME " bad aio_write return value\n");
			close(fd);
			exit(PTS_FAIL);
		} else if (err != EINVAL) {
			printf(TNAME " error code is not EINVAL %s\n",
			       strerror(errno));
			close(fd);
			exit(PTS_FAIL);
		}
	} else {

		if (errno != EINVAL) {
			printf(TNAME " errno is not EINVAL %s\n",
			       strerror(errno));
			close(fd);
			exit(PTS_FAIL);
		}
	}

	close(fd);
	printf("Test PASSED\n");
	return PTS_PASS;
}
Beispiel #24
0
int main()
{
	char tmpfname[256];
	int fd;

	struct aiocb *aiocbs[NUM_AIOCBS];
	char *bufs;
	struct sigaction action;
	struct sigevent event;
	int errors = 0;
	int ret;
	int err;
	int i;

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

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_lio_listio_15_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);

	bufs = (char *) malloc (NUM_AIOCBS*BUF_SIZE);

	if (bufs == NULL) {
		printf (TNAME " Error at malloc(): %s\n", strerror (errno));
		close (fd);
		exit(PTS_UNRESOLVED);
	}

	/* Queue up a bunch of aio writes */
	for (i = 0; i < NUM_AIOCBS; i++) {

		aiocbs[i] = (struct aiocb *)malloc(sizeof(struct aiocb));
		memset(aiocbs[i], 0, sizeof(struct aiocb));

		aiocbs[i]->aio_fildes = fd;
		aiocbs[i]->aio_offset = 0;
		aiocbs[i]->aio_buf = &bufs[i*BUF_SIZE];
		aiocbs[i]->aio_nbytes = BUF_SIZE;

		if (i > 3)
			aiocbs[i]->aio_lio_opcode = LIO_READ;
		else
			aiocbs[i]->aio_lio_opcode = LIO_WRITE;

		/* Use SIRTMIN+1 for individual completions */
		aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
		aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN+1;
		aiocbs[i]->aio_sigevent.sigev_value.sival_int = i;
	}

	/* Use SIGRTMIN+2 for list completion */
	event.sigev_notify = SIGEV_SIGNAL;
	event.sigev_signo = SIGRTMIN+2;
	event.sigev_value.sival_ptr = NULL;

	/* Setup handler for individual operation completion */
	action.sa_sigaction = sigrt1_handler;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_SIGINFO|SA_RESTART;
	sigaction(SIGRTMIN+1, &action, NULL);

	/* Setup handler for list completion */
	action.sa_sigaction = sigrt2_handler;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_SIGINFO|SA_RESTART;
	sigaction(SIGRTMIN+2, &action, NULL);

	/* Submit request list */
	ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);

	if (ret != 0) {
		printf(TNAME " Error lio_listio() returned %d (%s)\n",
		       errno, strerror(errno));

		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		close (fd);
		exit (PTS_FAIL);
	}

	while (received_all == 0)
		sleep (1);

	if (num_received != NUM_AIOCBS) {
		printf(TNAME " Error wrong number of completed requests %d\n",	
			num_received);

		for (i=0; i<NUM_AIOCBS; i++)
			free (aiocbs[i]);
		free (bufs);
		close (fd);
		exit (PTS_FAIL);
	}

	/* Check return code and free things */
	for (i = 0; i < NUM_AIOCBS; i++) {

	  	err = aio_error(aiocbs[i]);
		ret = aio_return(aiocbs[i]);

		if ((err != 0) && (ret != BUF_SIZE)) {
			printf(TNAME " req %d: error = %d - return = %d\n", i, err, ret);
			errors++;
		}

		free (aiocbs[i]);
	}

	free (bufs);

	close(fd);

	if (errors != 0)
		exit (PTS_FAIL);

	printf (TNAME " PASSED\n");

	return PTS_PASS;
}
Beispiel #25
0
/*
 * Note: we grab the state and free the state before calling the callback
 * because this allows us to cut down the amount of time it'll take
 * to find a free slot (since if we call the callback first, we're going
 * to probably be allocated the slot _after_ this one..)
 *
 * I'll make it much more optimal later.
 */
int
a_file_callback(async_queue_t * q)
{
    int i;
    int completed = 0;
    int retval, reterr;
    DRCB *rc;
    DWCB *wc;
    FREE *freefunc;
    void *callback_data;
    void *buf;
    int fd;
    async_queue_entry_t *aqe;
    async_queue_entry_type_t type;

    assert(q->aq_state == AQ_STATE_SETUP);

    /* Loop through all slots */
    for (i = 0; i < MAX_ASYNCOP; i++) {
	if (q->aq_queue[i].aq_e_state == AQ_ENTRY_USED) {
	    aqe = &q->aq_queue[i];
	    /* Active, get status */
	    reterr = aio_error(&aqe->aq_e_aiocb);
	    if (reterr < 0) {
		fatal("aio_error returned an error!\n");
	    }
	    if (reterr != EINPROGRESS) {
		/* Get the return code */
		retval = aio_return(&aqe->aq_e_aiocb);

		/* Get the callback parameters */
		callback_data = aqe->aq_e_callback_data;
		freefunc = aqe->aq_e_free;
		rc = aqe->aq_e_callback.read;
		wc = aqe->aq_e_callback.write;
		buf = aqe->aq_e_buf;
		fd = aqe->aq_e_fd;
		type = aqe->aq_e_type;

		/* debugging assert */
		assert(reterr == 0);

		/* Free slot */
		memset(aqe, 0, sizeof(async_queue_entry_t));
		aqe->aq_e_state = AQ_ENTRY_FREE;
		q->aq_numpending--;

		/* Callback */
		if (cbdataValid(callback_data)) {
		    if (type == AQ_ENTRY_READ)
			rc(fd, buf, retval, reterr, callback_data);
		    if (type == AQ_ENTRY_WRITE)
			wc(fd, reterr, retval, callback_data);
		}
		cbdataUnlock(callback_data);
		if (type == AQ_ENTRY_WRITE && freefunc)
		    freefunc(buf);
	    }
	}
    }
    return completed;
}
Beispiel #26
0
/*
 * The main event loop.
 */
static void
event_loop(void)
{
	node_mask_t old_connected_nodes = 0;
	int old_shut_down = 0;

	while (!old_shut_down ||
	       joined_lockspaces ||
	       !list_empty(&aio_pending) ||
	       !list_empty(&aio_completed)) {
		int ret, n;

		if (connected_nodes != old_connected_nodes) {
			if (verbose) {
				print_nodes(stdout, connected_nodes);
				printf("\n");
				fflush(stdout);
			}
			if (connected_nodes == all_nodes) {
				printf("DLM ready\n");
				fflush(stdout);
			} else if (old_connected_nodes == all_nodes) {
				printf("DLM not ready\n");
				fflush(stdout);
			}
			old_connected_nodes = connected_nodes;
		}

		if (old_shut_down != shut_down) {
			switch(shut_down) {
			case 1:
				printf("Shutting down (press ^C to enforce)\n");
				break;
			case 2:
				printf("Shutting down\n");
				break;
			default:
				printf("Aborting\n");
				break;
			}
			fflush(stdout);
			close_all_connections();
			if (joined_lockspaces && shut_down <= 2)
				release_lockspaces(shut_down > 1);
			else
				break;
			old_shut_down = shut_down;
			continue;
		}

		if (!list_empty(&aio_completed)) {
			while (!list_empty(&aio_completed)) {
				struct aio_request *req =
					list_first_entry(&aio_completed,
							 struct aio_request,
							 list);
				int err;

				list_del(&req->list);
				err = aio_error(&req->aiocb);
				if (err > 0)
					errno = err;
				req->complete(req);
			}
			continue;
		}

		ret = poll(cbs.pollfds, cbs.num, -1);
		if (ret == -1) {
			if (errno == EINTR)
				continue;
			fail(NULL);
		}

		for (n = 0; n < cbs.num; n++) {
			struct pollfd *pfd = &cbs.pollfds[n];

			if (pfd->revents) {
				struct poll_callback *pcb = &cbs.callbacks[n];

				pcb->callback(pfd->fd, pfd->revents, pcb->arg);
			}
		}
	}
}
Beispiel #27
0
int main(void)
{
	char tmpfname[256];
	char buf[BUF_SIZE];
	struct aiocb aiocb;
	struct aiocb aiocb2;
	int fd, retval;

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

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_return_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(buf, 0xaa, BUF_SIZE);
	memset(&aiocb, 0, sizeof(struct aiocb));
	aiocb.aio_fildes = fd;
	aiocb.aio_buf    = buf;
	aiocb.aio_nbytes = BUF_SIZE;

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

	do {
		retval = aio_error( &aiocb);
		if (retval == -1) {
			close(fd);
			printf(TNAME " Error at aio_error(): %s\n",
				strerror(errno));
			exit(PTS_FAIL);
		}
	} while (retval == EINPROGRESS);

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

	retval = aio_return(&aiocb2);

	if (retval != -1) {
		close(fd);
		printf(TNAME " aio_return() should fail\n");
		exit(PTS_FAIL);
	}

	retval = aio_return(&aiocb);
	
	if (retval != BUF_SIZE) {
		close(fd);
		printf(TNAME " Error at aio_return(): %d, %s\n", retval,
		       strerror(errno));
		exit(PTS_FAIL);
	}

	close(fd);
	printf("Test PASSED\n");
	exit(PTS_PASS);
}
int MtpFfsCompatHandle::sendFile(mtp_file_range mfr) {
    uint64_t file_length = mfr.length;
    uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
            file_length + sizeof(mtp_data_header));
    uint64_t offset = mfr.offset;
    int packet_size = getPacketSize(mBulkIn);

    // If file_length is larger than a size_t, truncating would produce the wrong comparison.
    // Instead, promote the left side to 64 bits, then truncate the small result.
    int init_read_len = std::min(
            static_cast<uint64_t>(packet_size - sizeof(mtp_data_header)), file_length);

    unsigned char *data = mIobuf[0].bufs.data();
    unsigned char *data2 = mIobuf[1].bufs.data();

    posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);

    struct aiocb aio;
    aio.aio_fildes = mfr.fd;
    struct aiocb *aiol[] = {&aio};
    int ret, length;
    int error = 0;
    bool read = false;
    bool write = false;

    // Send the header data
    mtp_data_header *header = reinterpret_cast<mtp_data_header*>(data);
    header->length = htole32(given_length);
    header->type = htole16(2); /* data packet */
    header->command = htole16(mfr.command);
    header->transaction_id = htole32(mfr.transaction_id);

    // Some hosts don't support header/data separation even though MTP allows it
    // Handle by filling first packet with initial file data
    if (TEMP_FAILURE_RETRY(pread(mfr.fd, reinterpret_cast<char*>(data) +
                    sizeof(mtp_data_header), init_read_len, offset))
            != init_read_len) return -1;
    if (writeHandle(mBulkIn, data, sizeof(mtp_data_header) + init_read_len) == -1) return -1;
    file_length -= init_read_len;
    offset += init_read_len;
    ret = init_read_len + sizeof(mtp_data_header);

    // Break down the file into pieces that fit in buffers
    while (file_length > 0) {
        if (read) {
            // Wait for the previous read to finish
            aio_suspend(aiol, 1, nullptr);
            ret = aio_return(&aio);
            if (ret == -1) {
                errno = aio_error(&aio);
                return -1;
            }
            if (static_cast<size_t>(ret) < aio.aio_nbytes) {
                errno = EIO;
                return -1;
            }

            file_length -= ret;
            offset += ret;
            std::swap(data, data2);
            read = false;
            write = true;
        }

        if (error == -1) {
            return -1;
        }

        if (file_length > 0) {
            length = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length);
            // Queue up another read
            aio_prepare(&aio, data, length, offset);
            aio_read(&aio);
            read = true;
        }

        if (write) {
            if (writeHandle(mBulkIn, data2, ret) == -1) {
                error = -1;
            }
            write = false;
        }
    }

    if (ret % packet_size == 0) {
        // If the last packet wasn't short, send a final empty packet
        if (TEMP_FAILURE_RETRY(::write(mBulkIn, data, 0)) != 0) {
            return -1;
        }
    }

    return 0;
}
int MtpFfsCompatHandle::receiveFile(mtp_file_range mfr, bool zero_packet) {
    // When receiving files, the incoming length is given in 32 bits.
    // A >4G file is given as 0xFFFFFFFF
    uint32_t file_length = mfr.length;
    uint64_t offset = mfr.offset;
    int packet_size = getPacketSize(mBulkOut);

    unsigned char *data = mIobuf[0].bufs.data();
    unsigned char *data2 = mIobuf[1].bufs.data();

    struct aiocb aio;
    aio.aio_fildes = mfr.fd;
    aio.aio_buf = nullptr;
    struct aiocb *aiol[] = {&aio};
    int ret = -1;
    size_t length;
    bool read = false;
    bool write = false;

    posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);

    // Break down the file into pieces that fit in buffers
    while (file_length > 0 || write) {
        if (file_length > 0) {
            length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);

            // Read data from USB, handle errors after waiting for write thread.
            ret = readHandle(mBulkOut, data, length);

            if (file_length != MAX_MTP_FILE_SIZE && ret < static_cast<int>(length)) {
                ret = -1;
                errno = EIO;
            }
            read = true;
        }

        if (write) {
            // get the return status of the last write request
            aio_suspend(aiol, 1, nullptr);

            int written = aio_return(&aio);
            if (written == -1) {
                errno = aio_error(&aio);
                return -1;
            }
            if (static_cast<size_t>(written) < aio.aio_nbytes) {
                errno = EIO;
                return -1;
            }
            write = false;
        }

        // If there was an error reading above
        if (ret == -1) {
            return -1;
        }

        if (read) {
            if (file_length == MAX_MTP_FILE_SIZE) {
                // For larger files, receive until a short packet is received.
                if (static_cast<size_t>(ret) < length) {
                    file_length = 0;
                }
            } else {
                file_length -= ret;
            }
            // Enqueue a new write request
            aio_prepare(&aio, data, length, offset);
            aio_write(&aio);

            offset += ret;
            std::swap(data, data2);

            write = true;
            read = false;
        }
    }
    // Receive an empty packet if size is a multiple of the endpoint size.
    if (ret % packet_size == 0 || zero_packet) {
        if (TEMP_FAILURE_RETRY(::read(mBulkOut, data, packet_size)) != 0) {
            return -1;
        }
    }
    return 0;
}
Beispiel #30
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;
}