JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_submitWrite
  (JNIEnv * env, jclass clazz, jint fileHandle, jobject contextPointer, jlong position, jint size, jobject bufferWrite, jobject callback) {
    struct io_control * theControl = getIOControl(env, contextPointer);
    if (theControl == NULL) {
      return;
    }

    #ifdef DEBUG
       fprintf (stdout, "submitWrite position %ld, size %d\n", position, size);
    #endif

    struct iocb * iocb = getIOCB(theControl);

    if (iocb == NULL) {
        throwIOException(env, "Not enough space in libaio queue");
        return;
    }

    io_prep_pwrite(iocb, fileHandle, getBuffer(env, bufferWrite), (size_t)size, position);

    // The GlobalRef will be deleted when poll is called. this is done so
    // the vm wouldn't crash if the Callback passed by the user is GCed between submission
    // and callback.
    // also as the real intention is to hold the reference until the life cycle is complete
    iocb->data = (void *) (*env)->NewGlobalRef(env, callback);

    submit(env, theControl, iocb);
}
Ejemplo n.º 2
0
int o2test_aio_pwrite(struct o2test_aio *o2a, int fd, void *buf, size_t count,
		      off_t offset)
{
	int ret = 0;
	struct iocb *iocbs[] = { o2a->o2a_iocbs[o2a->o2a_cr_event] };

	if (o2a->o2a_cr_event >= o2a->o2a_nr_events) {
		fprintf(stderr, "current aio context didn't support %d "
			"requests\n", o2a->o2a_cr_event);
		return -1;
	}

	io_prep_pwrite(o2a->o2a_iocbs[o2a->o2a_cr_event], fd, buf,
		       count, offset);
	ret = io_submit(o2a->o2a_ctx, 1, iocbs);
	if (ret != 1) {
		ret = errno;
		fprintf(stderr, "error %s during %s\n", strerror(errno),
			"io_submit");
		ret = -1;
	}

	o2a->o2a_cr_event++;

	return ret;
}
Ejemplo n.º 3
0
/*
 * Read complete callback.
 * Change read iocb into a write iocb and start it.
 */
static void rd_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
	/* library needs accessors to look at iocb? */
	int iosize = iocb->u.c.nbytes;
	char *buf = iocb->u.c.buf;
	off_t offset = iocb->u.c.offset;

	if (res2 != 0)
		io_error("aio read", res2);
	if (res != iosize) {
		fprintf(stderr, "read missing bytes expect %lu got %ld\n",
			iocb->u.c.nbytes, res);
		exit(1);
	}


	/* turn read into write */
	if (no_write) {
		--tocopy;
		--busy;
		free_iocb(iocb);
	} else {
		io_prep_pwrite(iocb, dstfd, buf, iosize, offset);
		io_set_callback(iocb, wr_done);
		if (1 != (res = io_submit(ctx, 1, &iocb)))
			io_error("io_submit write", res);
	}
	if (debug)
		write(2, "r", 1);
	if (debug > 1)
		printf("%d", iosize);
}
Ejemplo n.º 4
0
ssize_t file_pwrite(unsigned int file_id, void *buf, ssize_t count,
                    long long offset, int thread_id)
{
  FILE_DESCRIPTOR fd = files[file_id];
#ifdef HAVE_MMAP
  void        *start;
  size_t       page_addr;
  size_t       page_offset;
#endif  
#ifdef HAVE_LIBAIO
  struct iocb iocb;
#else  
  (void)thread_id; /* unused */
#endif
  
  if (file_io_mode == FILE_IO_MODE_SYNC)
    return pwrite(fd, buf, count, offset);
#ifdef HAVE_LIBAIO
  else if (file_io_mode == FILE_IO_MODE_ASYNC)
  {
    /* Use asynchronous write */
    io_prep_pwrite(&iocb, fd, buf, count, offset);

    if (file_submit_or_wait(&iocb, FILE_OP_TYPE_WRITE, count, thread_id))
      return 0;

    return count;
  }
#endif
#ifdef HAVE_MMAP
  else if (file_io_mode == FILE_IO_MODE_MMAP)
  {
# if SIZEOF_SIZE_T == 4
    /* Create file mapping for each I/O operation on 32-bit platforms */
    page_addr = offset & file_page_mask;
    page_offset = offset - page_addr;
    start = mmap(NULL, count + page_offset, PROT_READ | PROT_WRITE, MAP_SHARED,
                 fd, page_addr);
    if (start == MAP_FAILED)
      return 0;
    memcpy((char *)start + page_offset, buffer, count);
    munmap(start, count + page_offset);

    return count;
# else
    (void)start; /* unused */
    (void)page_addr; /* unused */
    (void)page_offset; /* unused */

    /* We already have all files mapped on 64-bit platforms */
    memcpy((char *)mmaps[file_id] + offset, buffer, count);

    return count;
# endif    
  }
#endif /* HAVE_MMAP */

  return 0; /* Unknown I/O mode */
}
Ejemplo n.º 5
0
static int
sector_io(struct sbd_context *st, int sector, void *data, int rw)
{
	struct timespec	timeout;
	struct io_event event;
	struct iocb	*ios[1] = { &st->io };
	long		r;

	timeout.tv_sec  = timeout_io;
	timeout.tv_nsec = 0;

	memset(&st->io, 0, sizeof(struct iocb));
	if (rw) {
		io_prep_pwrite(&st->io, st->devfd, data, sector_size, sector_size * sector);
	} else {
		io_prep_pread(&st->io, st->devfd, data, sector_size, sector_size * sector);
	}

	if (io_submit(st->ioctx, 1, ios) != 1) {
		cl_log(LOG_ERR, "Failed to submit IO request! (rw=%d)", rw);
		return -1;
	}

	errno = 0;
	r = io_getevents(st->ioctx, 1L, 1L, &event, &timeout);

	if (r < 0 ) {
		cl_log(LOG_ERR, "Failed to retrieve IO events (rw=%d)", rw);
		return -1;
	} else if (r < 1L) {
		cl_log(LOG_INFO, "Cancelling IO request due to timeout (rw=%d)", rw);
		r = io_cancel(st->ioctx, ios[0], &event);
		if (r) {
			DBGLOG(LOG_INFO, "Could not cancel IO request (rw=%d)", rw);
			/* Doesn't really matter, debugging information.
			 */
		}
		return -1;
	} else if (r > 1L) {
		cl_log(LOG_ERR, "More than one IO was returned (r=%ld)", r);
		return -1;
	}

	
	/* IO is happy */
	if (event.res == sector_size) {
		return 0;
	} else {
		cl_log(LOG_ERR, "Short IO (rw=%d, res=%lu, sector_size=%d)",
				rw, event.res, sector_size);
		return -1;
	}
}
Ejemplo n.º 6
0
/* 
 * build an aio iocb for an operation, based on oper->rw and the
 * last offset used.  This finds the struct io_unit that will be attached
 * to the iocb, and things are ready for submission to aio after this
 * is called.
 *
 * returns null on error
 */
static struct io_unit *build_iocb(struct thread_info *t, struct io_oper *oper)
{
    struct io_unit *io;
    off_t rand_byte;

    io = find_iou(t, oper);
    if (!io) {
        fprintf(stderr, "unable to find io unit\n");
	return NULL;
    }

    switch(oper->rw) {
    case WRITE:
        io_prep_pwrite(&io->iocb,oper->fd, io->buf, oper->reclen, 
	               oper->last_offset);
	oper->last_offset += oper->reclen;
	break;
    case READ:
        io_prep_pread(&io->iocb,oper->fd, io->buf, oper->reclen, 
	              oper->last_offset);
	oper->last_offset += oper->reclen;
	break;
    case RREAD:
	rand_byte = random_byte_offset(oper);
	oper->last_offset = rand_byte;
        io_prep_pread(&io->iocb,oper->fd, io->buf, oper->reclen, 
	              rand_byte);
        break;
    case RWRITE:
	rand_byte = random_byte_offset(oper);
	oper->last_offset = rand_byte;
        io_prep_pwrite(&io->iocb,oper->fd, io->buf, oper->reclen, 
	              rand_byte);
        
        break;
    }

    return io;
}
Ejemplo n.º 7
0
int aio_write(int fd, void *buffer, size_t length, off_t offset, aio_callback_t cb){
	struct iocb iocb;
	struct iocb *piocb = &iocb;
	int resp;
	
	io_prep_pwrite(&iocb, fd, buffer, length, offset);
	iocb.data = cb;
	io_set_eventfd(&iocb, aio_fd);
	

	resp = io_submit(aio_ctx,1, &piocb);
	
	return resp;
}
JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_deleteContext(JNIEnv* env, jclass clazz, jobject contextPointer) {
    int i;
    struct io_control * theControl = getIOControl(env, contextPointer);
    if (theControl == NULL) {
      return;
    }

    struct iocb * iocb = getIOCB(theControl);

    if (iocb == NULL) {
        throwIOException(env, "Not enough space in libaio queue");
        return;
    }

    // Submitting a dumb write so the loop finishes
    io_prep_pwrite(iocb, dumbWriteHandler, 0, 0, 0);
    iocb->data = (void *) -1;
    if (!submit(env, theControl, iocb)) {
        return;
    }

    // to make sure the poll has finished
    pthread_mutex_lock(&(theControl->pollLock));
    pthread_mutex_unlock(&(theControl->pollLock));

    // To return any pending IOCBs
    int result = io_getevents(theControl->ioContext, 0, 1, theControl->events, 0);
    for (i = 0; i < result; i++) {
        struct io_event * event = &(theControl->events[i]);
        struct iocb * iocbp = event->obj;
        putIOCB(theControl, iocbp);
    }

    io_queue_release(theControl->ioContext);

    pthread_mutex_destroy(&(theControl->pollLock));
    pthread_mutex_destroy(&(theControl->iocbLock));

    // Releasing each individual iocb
    for (i = 0; i < theControl->queueSize; i++) {
       free(theControl->iocb[i]);
    }

    (*env)->DeleteGlobalRef(env, theControl->thisObject);

    free(theControl->iocb);
    free(theControl->events);
    free(theControl);
}
Ejemplo n.º 9
0
static void aiobe_pwrite(struct device* dev, void* buf, size_t size, off64_t offset, dev_callback_t cb, void* cookie) {
	int ret;
	struct aiobe_request* req=(struct aiobe_request*)malloc(sizeof(struct aiobe_request));
	struct iocb* iocb = &req->iocb;
	memset(req, 0, sizeof(*req));

	io_prep_pwrite(iocb, D(dev)->fd, buf, size, offset);
	req->cb=cb;
	req->cookie=cookie;
	iocb->data = req;

	ret=io_submit(D(dev)->ctx, 1, &iocb);
	if (ret!=1)
		aiobe_complete(req, -1);
}
Ejemplo n.º 10
0
aiom_cb_t *
mb_aiom_prep_pwrite  (mb_aiom_t *aiom, int fd,
                      void *buf, size_t count, long long offset)
{
    aiom_cb_t *aiom_cb;
    if (NULL == (aiom_cb = mb_res_pool_pop(aiom->cbpool))) {
        return NULL;
    }
    io_prep_pwrite(&aiom_cb->iocb, fd, buf, count, offset);
    GETTIMEOFDAY(&aiom_cb->submit_time);

    aiom->pending[aiom->nr_pending++] = aiom_cb;

    return aiom_cb;
}
Ejemplo n.º 11
0
/*
 * Test whether counter overflow is detected and handled correctly.
 *
 * It is not possible to directly overflow the counter using the
 * write() syscall. Overflows occur when the counter is incremented
 * from kernel space, in an irq context, when it is not possible to
 * block the calling thread of execution.
 *
 * The AIO subsystem internally uses eventfd mechanism for
 * notification of completion of read or write requests. In this test
 * we trigger a counter overflow, by setting the counter value to the
 * max possible value initially. When the AIO subsystem notifies
 * through the eventfd counter, the counter overflows.
 *
 * NOTE: If the the counter starts from an initial value of 0, it will
 * take decades for an overflow to occur. But since we set the initial
 * value to the max possible counter value, we are able to cause it to
 * overflow with a single increment.
 *
 * When the counter overflows, the following are tested
 *   1. Check whether POLLERR event occurs in poll() for the eventfd.
 *   2. Check whether readfd_set/writefd_set is set in select() for the
        eventfd.
 *   3. The counter value is UINT64_MAX.
 */
static int trigger_eventfd_overflow(int evfd, int *fd, io_context_t * ctx)
{
    int ret;
    struct iocb iocb;
    struct iocb *iocbap[1];
    static char buf[4 * 1024];

    *ctx = 0;
    ret = io_setup(16, ctx);
    if (ret < 0) {
        errno = -ret;
        tst_resm(TINFO | TERRNO, "io_setup error");
        return -1;
    }

    *fd = open("testfile", O_RDWR | O_CREAT, 0644);
    if (*fd == -1) {
        tst_resm(TINFO | TERRNO, "open(testfile) failed");
        goto err_io_destroy;
    }

    ret = set_counter(evfd, UINT64_MAX - 1);
    if (ret == -1) {
        tst_resm(TINFO, "error setting counter to UINT64_MAX-1");
        goto err_close_file;
    }

    io_prep_pwrite(&iocb, *fd, buf, sizeof(buf), 0);
    io_set_eventfd(&iocb, evfd);

    iocbap[0] = &iocb;
    ret = io_submit(*ctx, 1, iocbap);
    if (ret < 0) {
        errno = -ret;
        tst_resm(TINFO | TERRNO, "error submitting iocb");
        goto err_close_file;
    }

    return 0;

err_close_file:
    close(*fd);

err_io_destroy:
    io_destroy(*ctx);

    return -1;
}
void RandomAccessFileDevice::prepareTransfer(RandomAccessRequest &request)
{
    assert(request.pDevice == this);

#ifdef USE_AIO_H
    int aio_lio_opcode =
        (request.type == RandomAccessRequest::READ)
        ? LIO_READ : LIO_WRITE;
    FileSize cbOffset = request.cbOffset;
    for (RandomAccessRequest::BindingListIter
             bindingIter(request.bindingList);
         bindingIter; ++bindingIter)
    {
        RandomAccessRequestBinding *pBinding = bindingIter;
        pBinding->aio_fildes = handle;
        pBinding->aio_lio_opcode = aio_lio_opcode;
        // TODO:  initialize constant fields below only once
        pBinding->aio_buf = pBinding->getBuffer();
        pBinding->aio_nbytes = pBinding->getBufferSize();
        pBinding->aio_reqprio = 0;
        pBinding->aio_offset = cbOffset;
        cbOffset += pBinding->aio_nbytes;
    }
    assert(cbOffset == request.cbOffset + request.cbTransfer);
#endif

#ifdef USE_LIBAIO_H
    FileSize cbOffset = request.cbOffset;
    for (RandomAccessRequest::BindingListIter
             bindingIter(request.bindingList);
         bindingIter; ++bindingIter)
    {
        RandomAccessRequestBinding *pBinding = bindingIter;

        if (request.type == RandomAccessRequest::READ) {
            io_prep_pread(
                pBinding, handle, pBinding->getBuffer(),
                pBinding->getBufferSize(), cbOffset);
        } else {
            io_prep_pwrite(
                pBinding, handle, pBinding->getBuffer(),
                pBinding->getBufferSize(), cbOffset);
        }
        cbOffset += pBinding->getBufferSize();
    }
    assert(cbOffset == request.cbOffset + request.cbTransfer);
#endif
}
Ejemplo n.º 13
0
Archivo: io_aio.c Proyecto: choki/wlg
int aio_enqueue(
	int fd, 
	char *buf, 
	unsigned long size, 
	unsigned long start_addr, 
	OPERATION_TYPE op
	)
{
    int rtn;
    int queue_id;
    struct iocb *cb;
    int i;


retry:
    queue_id = find_and_set_id();
    if(queue_id == -1){
	PRINT("Qbusy ");
	usleep(10);
	goto retry;
    }
    my_iocbp[queue_id].qid = queue_id;
    cb = &my_iocbp[queue_id].iocbp;

    switch (op){
	case WG_READ:
	    io_prep_pread(cb, fd, buf, size, start_addr);
	    break;
	case WG_WRITE:
	    io_prep_pwrite(cb, fd, buf, size, start_addr);
	    break;
	default:
	    PRINT("Error not supported I/O operation file:%s, line:%d\n", __func__, __LINE__);
	    exit(1);
    }
    rtn = io_submit(context, 1, &cb);
    if(rtn<0){
	PRINT("Error on I/O submission, line:%d, errno:%d\n", __LINE__, rtn);
	exit(1);
    }
    pthread_mutex_lock(&aio_req_num_mutex);
    req_num++;
    pthread_mutex_unlock(&aio_req_num_mutex);
    return rtn;
}
Ejemplo n.º 14
0
int
aioperf_libaio_write(aioperf_io_task_t *io_task)
{
    struct iocb             *libaio_req = NULL;
    aioperf_repository_t    *repository = NULL;
    aioperf_conf_info_t     *conf_info = NULL;
    unsigned long            left_size = 0;
    unsigned int             count = 0;

    repository = io_task->repository;
    conf_info = repository->conf_info;
    left_size = io_task->file_size - io_task->offset;
        
    if (!(libaio_req = (struct iocb *)aioperf_memory_pool_alloc(repository->pool, 
        sizeof(struct iocb)))) {
        printf("alloc error\n");
        return AIOPERF_ERROR;
    }

    aioperf_memory_set(libaio_req, 0, sizeof(struct iocb));

    io_task->data = libaio_req;
    

    if (left_size > conf_info->buf_size) {
        count = conf_info->buf_size;
    } else {
        count = left_size;
    }

    io_prep_pwrite(libaio_req, io_task->fd, repository->buf, count, 
        io_task->offset);
    libaio_req->data = io_task;
    
    io_set_eventfd(libaio_req, io_task->repository->signal_fd);
    
    
    if (io_submit(*(io_context_t *)repository->mgr->data, 1, &libaio_req) < 0) {
        printf("io_submit error\n");
    }

    return AIOPERF_OK;
}
Ejemplo n.º 15
0
static int do_aio_loop(int fd, void *buf)
{
	int err, ret;
	struct io_context *ctx = NULL;
	struct io_event ev;
	struct iocb iocb, *iocbs[] = { &iocb };
	struct timeval start, now, delta = { 0, 0 };

	ret = 0;
	err = io_setup(1, &ctx);
	if (err) {
		fprintf(stderr, "error %s during %s\n",
			strerror(-err), "io_setup" );
		return 1;
	}
	gettimeofday(&start, NULL);
	while (1) {
		io_prep_pwrite(&iocb, fd, buf, BUF_SIZE, BUF_SIZE);
		err = io_submit(ctx, 1, iocbs);
		if (err != 1) {
			fprintf(stderr, "error %s during %s\n",
				strerror(-err),
				"io_submit");
			ret = 1;
			break;
		}
		err = io_getevents(ctx, 1, 1, &ev, NULL);
		if (err != 1) {
			fprintf(stderr, "error %s during %s\n",
				strerror(-err),
				"io_getevents");
			ret = 1;
			break;
		}
		gettimeofday(&now, NULL);
		timersub(&now, &start, &delta);
		if (delta.tv_sec >= LOOP_SECONDS)
			break;
	}
	io_destroy(ctx);
	return ret;
}
Ejemplo n.º 16
0
static void rd_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
	/*library needs accessors to look at iocb*/
	int iosize = iocb->u.c.nbytes;
	char *buf = (char *)iocb->u.c.buf;
	off_t offset = iocb->u.c.offset;
	int  tmp;
	char *wrbuff = NULL;

	if(res2 != 0)
	{
		printf("aio read\n");
	}
	if(res != iosize)
	{
		printf("read missing bytes expect %lu got %ld", iocb->u.c.nbytes, res);
		//exit(1);
	}

	/*turn read into write*/
	tmp = posix_memalign((void **)&wrbuff, getpagesize(), AIO_BLKSIZE);
	if(tmp < 0)
	{
		printf("posix_memalign222\n");
		exit(1);
	}

	snprintf(wrbuff, iosize + 1, "%s", buf);

	printf("wrbuff-len = %lu:%s\n", strlen(wrbuff), wrbuff);
	printf("wrbuff_len = %lu\n", strlen(wrbuff));
	free(buf);

	io_prep_pwrite(iocb, odsfd, wrbuff, iosize, offset);
	io_set_callback(iocb, wr_done);

	if(1!= (res=io_submit(ctx, 1, &iocb)))
		printf("io_submit write error\n");

	printf("\nsubmit  %ld  write request\n", res);
}
Ejemplo n.º 17
0
static void do_io_async(void)
{
	size_t n_files = sizeof(files) / sizeof(files[0]);
	size_t i;
	io_context_t ctx = 0;
	struct iocb *iocb;
	struct iocb **piocb;
	int n_aio_ops, rc;

	/* TODO 1 - allocate iocb and piocb */
	iocb = (struct iocb *) malloc(n_files * sizeof(*iocb));
	DIE(iocb == NULL, "malloc");

	piocb = (struct iocb **) malloc(n_files * sizeof(*piocb));
	DIE(piocb == NULL, "malloc");

	/* TODO 1 - initialiaze iocb and piocb */
	for (i = 0; i < n_files; i++) {
		io_prep_pwrite(&iocb[i], fds[i], g_buffer, BUFSIZ, 0);
		piocb[i] = &iocb[i];

#ifdef USE_EVENTFD
		/* TODO 2 - set up eventfd notification */
		io_set_eventfd(&iocb[i], efd);
#endif		
	}

	/* TODO 1 - setup aio context */
	rc = io_setup(n_files, &ctx);
	DIE(rc < 0, "io_setup");

	/* TODO 1 - submit aio */
	n_aio_ops = io_submit(ctx, n_files, piocb);
	DIE(n_aio_ops < 0, "io_submit");

	/* wait for completion*/
	wait_aio(ctx, n_files);

	/* TODO 1 - destroy aio context */
	io_destroy(ctx);
}
Ejemplo n.º 18
0
inline void
prep_aio (struct iocb *this_iocb, const struct trace_entry *request)
{
    struct object *obj = getobj (request->item->obj);

    char *ptr;
    if (request->rwType == 'R')
	io_prep_pread (this_iocb, lfs_n.fd, obj->obj_data->data,
		       request->bytecount, request->startbyte);
    else if (request->rwType == 'W')
      {
	  ptr = request->item->_ptr = getshmptr (request->item->shmid);
	  if (ptr == NULL)
	    {
		lfs_printf ("pre_aio failed");
		assert (0);
		return;
	    }

	  lfs_printf ("prep_aio write\n");
	  io_prep_pwrite (this_iocb, lfs_n.fd, ptr,
			  request->bytecount, request->startbyte);
      }
}
Ejemplo n.º 19
0
int main(int argc, char *argv[])
{
  io_context_t ctx;
  struct io_event event;
  int io_event_cnt = 10;
  int fd;
  char *file = "hello.txt";
  char *content = "1234567890";
  char *content2 = "abcdefg";
  struct timespec timeout;
  struct iocb io;
  struct iocb io2;
  struct iocb *p[2];
  int ret;
  int total_write, finished;

  printf("hello aio.\n");

  memset(&ctx, 0x0, sizeof(ctx));
  if (0 != (ret = io_setup(io_event_cnt, &ctx)))
  {
    io_setup_error(ret);
    return -1;
  }

  if ((fd = open(file, O_CREAT|O_WRONLY, 0644)) < 0)
  {
    printf("open 1 error");
    io_destroy(ctx);
    return -1;
  }

  io_prep_pwrite(&io, fd, content, strlen(content), 0);
  io_prep_pwrite(&io2, fd, content2, strlen(content2), 20);
  p[0] = &io;
  p[1] = &io2;
  total_write = 2;  //进行两个文件的写入
  finished = 0;

  if (2 != io_submit(ctx, 2, p))
  {
    io_destroy(ctx);
    printf("io_submit error\n");
    return -1;
  }
  printf("submitted\n");

  timeout.tv_sec = 0;
  timeout.tv_nsec = 500000000;
  while(1)
  {
    if (1 == io_getevents(ctx, 0, 1, &event, &timeout))
    {
      if (event.obj == &io)
      {
        printf("io 1 finished\n");
      }
      if (event.obj == &io2)
      {
        printf("io 2 finished\n");
      }
      finished++;
      if (finished == total_write)
      {
        break;
      }
    }
  }
  printf("finish write.\n");

  close(fd);
  io_destroy(ctx);

  return 0;
}
Ejemplo n.º 20
0
/* 一次提交多个io请求的操作 */
int io_tio(char *pathname, int flag, int n, int operation)
{
	int res, fd = 0, i = 0;
	void *bufptr = NULL;
	off_t offset = 0;
	struct timespec timeout;

	io_context_t myctx;
	struct iocb iocb_array[AIO_MAXIO];
	struct iocb *iocbps[AIO_MAXIO];

	fd = open(pathname, flag, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
	if (fd <= 0) {
		printf("open for %s failed: %s\n", pathname, strerror(errno));
		return -1;
	}

	res = io_queue_init(n, &myctx);
	//printf (" res = %d \n", res);

	for (i = 0; i < AIO_MAXIO; i++) {

		switch (operation) {
		case IO_CMD_PWRITE:
			if (posix_memalign(&bufptr, alignment, AIO_BLKSIZE)) {
				perror(" posix_memalign failed ");
				return -1;
			}
			memset(bufptr, 0, AIO_BLKSIZE);

			io_prep_pwrite(&iocb_array[i], fd, bufptr,
				       AIO_BLKSIZE, offset);
			io_set_callback(&iocb_array[i], work_done);
			iocbps[i] = &iocb_array[i];
			offset += AIO_BLKSIZE;

			break;
		case IO_CMD_PREAD:
			if (posix_memalign(&bufptr, alignment, AIO_BLKSIZE)) {
				perror(" posix_memalign failed ");
				return -1;
			}
			memset(bufptr, 0, AIO_BLKSIZE);

			io_prep_pread(&iocb_array[i], fd, bufptr,
				      AIO_BLKSIZE, offset);
			io_set_callback(&iocb_array[i], work_done);
			iocbps[i] = &iocb_array[i];
			offset += AIO_BLKSIZE;
			break;
		case IO_CMD_POLL:
		case IO_CMD_NOOP:
			break;
		default:
			tst_resm(TFAIL,
				 "Command failed; opcode returned: %d\n",
				 operation);
			return -1;
			break;
		}
	}

	do {
		res = io_submit(myctx, AIO_MAXIO, iocbps);
	} while (res == -EAGAIN);
	if (res < 0) {
		io_error("io_submit tio", res);
	}

	/*
	 * We have submitted all the i/o requests. Wait for at least one to complete
	 * and call the callbacks.
	 */
	wait_count = AIO_MAXIO;

	timeout.tv_sec = 30;
	timeout.tv_nsec = 0;

	switch (operation) {
	case IO_CMD_PREAD:
	case IO_CMD_PWRITE:
		{
			while (wait_count) {
				res = io_wait_run(myctx, &timeout);
				if (res < 0)
					io_error("io_wait_run", res);
			}
		}
		break;
	}

	close(fd);

	for (i = 0; i < AIO_MAXIO; i++) {
		if (iocb_array[i].u.c.buf != NULL) {
			free(iocb_array[i].u.c.buf);
		}
	}

	io_queue_release(myctx);

	return 0;
}
Ejemplo n.º 21
0
int main(int argc, char **argv)
{
	int i, j, sec, usec;
	int failflag=0;
	int bflag=0, nflag=0, Fflag=0;
	char *optb, *optn, *optF;
	char *msg;	/* for parse_opts */
	struct io_event event;
	static struct timespec ts;
	struct timeval stv, etv;

	option_t options[] = {
		{ "b:", &bflag, &optb },
		{ "n:", &nflag, &optn },
		{ "F:", &Fflag, &optF },
		{ NULL, NULL, NULL}
	};

	msg = parse_opts(argc, argv, options, &help);
	if (msg != (char *) NULL) {
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
		tst_exit();
	}

	bufsize = (bflag ? atoi(optb):8192);
	nr = (nflag ? atoi(optn):10);
	if (Fflag) {
		sprintf(fname, optF);
	} else {
		sprintf(fname, "aiofile");
	}

	setup();

/* TEST 1 */
	pos = 0;
	gettimeofday(&stv, NULL);
	io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos);
	for (i = 0; i< nr; i++) {
		ts.tv_sec = 30;
		ts.tv_nsec = 0;
		do {
			TEST(io_submit(io_ctx, 1, iocbs));
		} while (TEST_RETURN == -EAGAIN);
		if (TEST_RETURN < 0) {
			TEST_ERROR_LOG(TEST_ERRNO);
			tst_resm(TFAIL, "Test 1: io_submit failed - retval=%d, "
					"errno=%d", TEST_RETURN, TEST_ERRNO);
			failflag=1;
			continue;
		}
		while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1);
		gettimeofday(&etv, NULL);
	}
	if (!failflag) {
		sec = etv.tv_sec - stv.tv_sec;
		usec = etv.tv_usec - stv.tv_usec;
		if (usec < 0) {
			usec += 1000000;
			sec--;
		}
		tst_resm(TPASS, "Test 1: %d writes in %3d.%06d sec",
				nr, sec, usec);
	}

/* TEST 2 */
	pos = 0;
	failflag=0;
	gettimeofday(&stv, NULL);
	io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos);
	for (i = 0; i< nr; i++) {
		ts.tv_sec = 30;
		ts.tv_nsec = 0;
		do {
			TEST(io_submit(io_ctx, 1, iocbs));
		} while (TEST_RETURN == -EAGAIN);
		if (TEST_RETURN < 0) {
			TEST_ERROR_LOG(TEST_ERRNO);
			tst_resm(TFAIL, "Test 2: io_submit failed - retval=%d, "
					"errno=%d", TEST_RETURN, TEST_ERRNO);
			failflag=1;
			continue;
		}
		while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1);
		gettimeofday(&etv, NULL);
	}
	if (!failflag) {
		sec = etv.tv_sec - stv.tv_sec;
		usec = etv.tv_usec - stv.tv_usec;
		if (usec < 0) {
			usec += 1000000;
			sec--;
		}
		tst_resm(TPASS, "Test 2: %d reads in %3d.%06d sec",
				nr, sec, usec);
	}

/* TEST 3 */
	pos = 0;
	failflag=0;
	gettimeofday(&stv, NULL);
	for (i = 0; i< nr; i++) {
		io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos);
		ts.tv_sec = 30;
		ts.tv_nsec = 0;
		do {
			TEST(io_submit(io_ctx, 1, iocbs));
		} while (TEST_RETURN == -EAGAIN);
		if (TEST_RETURN < 0) {
			TEST_ERROR_LOG(TEST_ERRNO);
			tst_resm(TFAIL, "Test 3: io_submit failed - retval=%d, "
					"errno=%d", TEST_RETURN, TEST_ERRNO);
			failflag=1;
			continue;
		}
		while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1);
		gettimeofday(&etv, NULL);
	}
	if (!failflag) {
		sec = etv.tv_sec - stv.tv_sec;
		usec = etv.tv_usec - stv.tv_usec;
		if (usec < 0) {
			usec += 1000000;
			sec--;
		}
		tst_resm(TPASS, "Test 3: %d prep,writes in %3d.%06d sec",
				nr, sec, usec);
	}

/* TEST 4 */
	pos = 0;
	failflag=0;
	gettimeofday(&stv, NULL);
	for (i = 0; i< nr; i++) {
		io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos);
		ts.tv_sec = 30;
		ts.tv_nsec = 0;
		do {
			TEST(io_submit(io_ctx, 1, iocbs));
		} while (TEST_RETURN == -EAGAIN);
		if (TEST_RETURN < 0) {
			TEST_ERROR_LOG(TEST_ERRNO);
			tst_resm(TFAIL, "Test 4: io_submit failed - retval=%d, "
					"errno=%d", TEST_RETURN, TEST_ERRNO);
			failflag=1;
			continue;
		}
		while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1);
		gettimeofday(&etv, NULL);
	}
	if (!failflag) {
		sec = etv.tv_sec - stv.tv_sec;
		usec = etv.tv_usec - stv.tv_usec;
		if (usec < 0) {
			usec += 1000000;
			sec--;
		}
		tst_resm(TPASS, "Test 4: %d prep,reads in %3d.%06d sec",
				nr, sec, usec);
	}

/* TEST 5 */
	pos = 0;
	failflag=0;
	gettimeofday(&stv, NULL);
	for (i = 0; i< nr; i++) {
		io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos);
		ts.tv_sec = 30;
		ts.tv_nsec = 0;
		do {
			TEST(io_submit(io_ctx, 1, iocbs));
		} while (TEST_RETURN == -EAGAIN);
		if (TEST_RETURN < 0) {
			TEST_ERROR_LOG(TEST_ERRNO);
			tst_resm(TFAIL, "Test 5: write io_submit failed - "
					"retval=%d, errno=%d", TEST_RETURN,
					TEST_ERRNO);
			failflag=1;
			continue;
		}
		while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1);
		io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos);
		ts.tv_sec = 30;
		ts.tv_nsec = 0;
		do {
			TEST(io_submit(io_ctx, 1, iocbs));
		} while (TEST_RETURN == -EAGAIN);
		if (TEST_RETURN < 0) {
			TEST_ERROR_LOG(TEST_ERRNO);
			tst_resm(TFAIL, "Test 5: read io_submit failed - "
					"retval=%d, errno=%d", TEST_RETURN,
					TEST_ERRNO);
			failflag=1;
			continue;
		}
		while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1);
		gettimeofday(&etv, NULL);
	}
	if (!failflag) {
		sec = etv.tv_sec - stv.tv_sec;
		usec = etv.tv_usec - stv.tv_usec;
		if (usec < 0) {
			usec += 1000000;
			sec--;
		}
		tst_resm(TPASS, "Test 5: %d reads and writes in %3d.%06d sec",
				nr, sec, usec);
	}

/* TEST 6 */
	pos = 0;
	failflag=0;
	gettimeofday(&stv, NULL);
	for (i = 0; i< nr; i++) {
		io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos);
		ts.tv_sec = 30;
		ts.tv_nsec = 0;
		do {
			TEST(io_submit(io_ctx, 1, iocbs));
		} while (TEST_RETURN == -EAGAIN);
		if (TEST_RETURN < 0) {
			TEST_ERROR_LOG(TEST_ERRNO);
			tst_resm(TFAIL, "Test 6: write io_submit failed - "
					"retval=%d, errno=%d", TEST_RETURN,
					TEST_ERRNO);
			failflag=1;
			continue;
		}
		while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1);
		io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos);
		ts.tv_sec = 30;
		ts.tv_nsec = 0;
		do {
			TEST(io_submit(io_ctx, 1, iocbs));
		} while (TEST_RETURN == -EAGAIN);
		if (TEST_RETURN < 0) {
			TEST_ERROR_LOG(TEST_ERRNO);
			tst_resm(TFAIL, "Test 6: read io_submit failed - "
					"retval=%d, errno=%d", TEST_RETURN,
					TEST_ERRNO);
			failflag=1;
			continue;
		}
		while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1);
		for (j = 0; j < bufsize; j++) {
			if (srcbuf[j] != dstbuf[j])
				tst_resm(TFAIL, "Test 6: compare failed - "
						"read: %c, " "actual: %c",
						dstbuf[j], srcbuf[j]);
				break;
		}
		gettimeofday(&etv, NULL);
	}
	if (!failflag) {
		sec = etv.tv_sec - stv.tv_sec;
		usec = etv.tv_usec - stv.tv_usec;
		if (usec < 0) {
			usec += 1000000;
			sec--;
		}
		tst_resm(TPASS, "Test 6: %d read,write,verify in %d.%06d sec",
				i, sec, usec);
	}

	cleanup();

	tst_exit();
}
Ejemplo n.º 22
0
void AsyncIOOp::pwrite(int fd, const void* buf, size_t size, off_t start) {
  init();
  io_prep_pwrite(&iocb_, fd, const_cast<void*>(buf), size, start);
}
Ejemplo n.º 23
0
int main(int argc, char *argv[])
{
    int fd, rc, j, k, nbytes = NBYTES, maxevents = NBUF;
    char *buf[NBUF], *filename = "/dev/mycdrv";
    struct iocb *iocbray[NBUF], *iocb;
    off_t offset;
    io_context_t ctx = 0;
    struct io_event events[2 * NBUF];
    struct timespec timeout = { 0, 0 };

    /* open or create the file and fill it with a pattern */

    if (argc > 1)
        filename = argv[1];

    printf("opening %s\n", filename);

    /* notice opening with these flags won't hurt a device node! */

    if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC,
                   S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) < 0) {
        printf("couldn't open %s, ABORTING\n", filename);
        exit(-1);
    }

    /* write initial data out, clear buffers, allocate iocb's */

    for (j = 0; j < NBUF; j++) {
        /* no need to zero iocbs; will be done in io_prep_pread */
        iocbray[j] = malloc(sizeof(struct iocb));
        buf[j] = malloc(nbytes);
        sprintf(buf[j], "%4d%4d%4d%4d%4d%4d%4d%4d", j, j, j, j, j, j, j,
                j);
        write(fd, buf[j], nbytes);
        memset(buf[j], 0, nbytes);
    }
    printf("\n");

    /* prepare the context */

    rc = io_setup(maxevents, &ctx);
    printf(" rc from io_setup = %d\n", rc);

    /* (async) read the data from the file */

    printf(" reading initial data from the file:\n");

    for (j = 0; j < NBUF; j++) {
        iocb = iocbray[j];
        offset = j * nbytes;
        io_prep_pread(iocb, fd, (void *)buf[j], nbytes, offset);
        rc = io_submit(ctx, 1, &iocb);
    }

    /* sync up and print out the readin data */

    while ((rc = io_getevents(ctx, NBUF, NBUF, events, &timeout)) > 0) {
        printf(" rc from io_getevents on the read = %d\n\n", rc);
    }

    printbufs(buf, nbytes);

    /* filling in the buffers before the write */

    for (j = 0; j < NBUF; j++) {
        char *tmp = buf[j];
        for (k = 0; k < nbytes; k++) {
            sprintf((tmp + k), "%1d", j);
        }
    }

    /* write the changed buffers out */

    printf(" writing new data to the file:\n");
    for (j = 0; j < NBUF; j++) {
        iocb = iocbray[j];
        offset = j * nbytes;
        io_prep_pwrite(iocb, fd, buf[j], nbytes, offset);
        rc = io_submit(ctx, 1, &iocb);
    }

    /* sync up again */

    while ((rc = io_getevents(ctx, NBUF, NBUF, events, &timeout)) > 0) {
        printf(" rc from io_getevents on the write = %d\n\n", rc);
    }

    printbufs(buf, nbytes);

    /* clean up */
    rc = io_destroy(ctx);
    close(fd);
    exit(0);
}
Ejemplo n.º 24
0
int main() {

  size_t i;
  
  /* Attempt to read the MBR magic number from the device as a sanity check */
  FILE *file = fopen("/dev/sdd", "r");
  if (file == NULL) FATAL("Unable to open the device");
  for (i = 0; i < SZ; i++) dest[0][i] = JUNK_VAL;
  size_t nr = fread(dest[0], SZ, 1, file);
  if (nr != 1) FATAL("Unable to read from the device");
  fclose(file);
  if(dest[0][MAG_NUM_OFFSET1] != MAG_NUM_VAL1 || dest[0][MAG_NUM_OFFSET2] != MAG_NUM_VAL2)
    printf("Warning: Magic number not found during sanity check\n");
  
  /* Open the device again, but get ready to use async IO this time */
  int fd = open("/dev/sdd", O_NONBLOCK | O_DIRECT | O_RDWR, 0);
  if (fd < 0) FATAL("Error opening file");

  /* Now use *real* asynchronous IO to read multiple chunks in parallel */
  io_context_t ctx;
  memset(&ctx, 0, sizeof(ctx));
  IO_RUN (__LINE__, io_queue_init, maxEvents, &ctx);

  /* This is the read job we asynchronously run */
  struct iocb job_data[NUM_JOBS];
  struct iocb *job = job_data;
  struct iocb *q[NUM_JOBS];
  for (i = 0; i < SZ; i++) dest[0][i] = JUNK_VAL;
  for (i = 0; i < NUM_JOBS; i++,job++) {
    if (i & 1)
       io_prep_pread(job, fd, dest[i], SZ, i * SZ);
    else
       io_prep_pwrite(job, fd, dest[i], SZ, i * SZ);
    q[i] = job;
  }
  
  /* Issue it now */
  job = job_data;
  IO_RUN (__LINE__, io_submit, ctx, NUM_JOBS, q);

  /* Wait for it */
  struct timespec timeout;
  timeout.tv_sec = 5;
  timeout.tv_nsec = 0;
  struct io_event evts[NUM_JOBS];
  IO_RUN (__LINE__, io_getevents, ctx, NUM_JOBS, NUM_JOBS, evts, &timeout);
  for (i = 0; i < NUM_JOBS; i++) {
    /* Confirm that the IOs completed successfully */
    check(ctx, evts[i].obj, evts[i].res, evts[i].res2);
  }
  
  /* Only checking the first buffer, since the other ones were read from
  other locations */
  if(dest[0][MAG_NUM_OFFSET1] != MAG_NUM_VAL1 || dest[0][MAG_NUM_OFFSET2] != MAG_NUM_VAL2)
    printf("Warning: Magic number not found during async read\n");

  close(fd);
  io_destroy(ctx);
  
  return 0;
  
}
Ejemplo n.º 25
0
int main(int argc, char **argv)
{
	int run_time = 30;
	int op = O_RDONLY;
	int qd = 4;
	int end_of_device = 0;
	int opt, i, j, max_req, rc, ios_ready, in_flight, count;
	unsigned long arena_size;
	unsigned long seed = time(NULL);
	unsigned long mix_seed = time(NULL);
	unsigned long random_range = 0;
	unsigned char *arena;
	struct iocb *iocbs;
	struct iocb *ioptr;
	struct iocb **iolist;
	struct iocb **iolist_ptr;
	struct io_event *events;
	struct timespec start, end, now;
	unsigned long total_data, total_writes, total_count;
	int min_data, max_data;
	io_context_t ioctx;
	double mbs, actual_time;

	struct option options[] = {
		{ "help", no_argument, NULL, 'h' },
		{ "write", optional_argument, NULL, 'w' },
		{ "loop", no_argument, NULL, 'l' },
		{ "mixseed", required_argument, NULL, 'm' },
		{ "qd", required_argument, NULL, 'q' },
		{ "random", optional_argument, NULL, 'r' },
		{ "range", required_argument, NULL, 'a' },
		{ "size", required_argument, NULL, 's' },
		{ "time", required_argument, NULL, 't' },
		{ NULL }
	};

	req_size = 1024 * 1024;
	write_pct = 0.0;

	for (;;) {
		opt = getopt_long(argc, argv, "hwlq:s:t:", options, NULL);

		if (opt == -1)
			break;

		switch (opt) {
		case 'w':
			op = O_RDWR;
			write_pct = 1.0;
			if (optarg)
				write_pct = strtod(optarg, NULL) / 100.0;
			if (write_pct < 1.0)
				random_offsets = 1;
			break;
		case 'l':
			loop_at_end = 1;
			break;
		case 'm':
			mix_seed = strtoul(optarg, NULL, 0);
			break;
		case 'q':
			qd = atoi(optarg);
			break;
		case 't':
			run_time = atoi(optarg);
			break;
		case 's':
			req_size = strtoul(optarg, NULL, 0);
			break;
		case 'r':
			random_offsets = 1;
			if (optarg)
				seed = strtoul(optarg, NULL, 0);
			else
				seed = time(NULL);
			break;
		case 'a':
			random_range = strtoul(optarg, NULL, 0);
			break;
		case 'h':
		case '?':
		default:
			usage(argv[0]);
			break;
		}
	}

	if (run_time < 1) {
		fprintf(stderr, "%s: run time must be at least 1 second\n",
				argv[0]);
		exit(1);
	}

	if (qd < 0 || qd > 64) {
		fprintf(stderr, "%s: queue depth must be between 1 and 64\n",
				argv[0]);
		exit(1);
	}

	if (req_size < 4096 || req_size > (16 * 1024 * 1024)) {
		fprintf(stderr, "%s: request size must be between 4K and 16M\n",
				argv[0]);
		exit(1);
	}

	/* Always do a multiple of a page for direct IO.
	 */
	req_size &= ~4095;

	if (random_range) {
		random_range /= req_size;
		if (random_range < 2) {
			fprintf(stderr, "%s: random range gives no "
					"randomness\n", argv[0]);
			exit(1);
		}
	}

	if (optind == argc) {
		fprintf(stderr, "%s: need devices to benchmark\n", argv[0]);
		exit(1);
	}

	ndev = argc - optind;
	devs = malloc(ndev * sizeof(*devs));
	if (!ndev) {
		fprintf(stderr, "%s: no memory for devices\n", argv[0]);
		exit(1);
	}

	for (i = 0; i < ndev; i++) {
		devs[i].replace = -1;
		devs[i].io_base = NULL;
		devs[i].offset = 0;
		devs[i].count = 0;
		devs[i].writes = 0;
		devs[i].status = ' ';
		devs[i].name = argv[optind++];
		devs[i].fd = open(devs[i].name, op|O_DIRECT|O_SYNC);
		if (devs[i].fd < 0) {
			fprintf(stderr, "%s: opening ", argv[0]);
			perror(devs[i].name);
			exit(1);
		}
		devs[i].size = lseek(devs[i].fd, 0, SEEK_END);
		if (devs[i].size < 0) {
			fprintf(stderr, "%s: lseek ", argv[0]);
			perror(devs[i].name);
			exit(1);
		}
		if (random_offsets) {
			unsigned long t = seed + i;

			devs[i].random_range = devs[i].size / req_size;
			if (random_range && devs[i].random_range > random_range)
				devs[i].random_range = random_range;

			devs[i].off_rand_state[2] = t >> 16;
			devs[i].off_rand_state[1] = t & 0xffff;
			devs[i].off_rand_state[0] = 0x330e;

			t = mix_seed + i;
			devs[i].rw_rand_state[2] = t >> 16;
			devs[i].rw_rand_state[1] = t & 0xffff;
			devs[i].rw_rand_state[0] = 0x330e;
		}
	}

	/* The arena needs to be big enough to host the maximum number of
	 * requests possible, plus an extra set of requests to pass around
	 * the devices to fairly share any memory fragmentation seen.
	 */
	max_req = ndev * qd;
	arena_size = (max_req + qd) * req_size;
	arena = mmap(NULL, arena_size, PROT_READ|PROT_WRITE,
			MAP_ANONYMOUS|MAP_POPULATE|MAP_PRIVATE, -1, 0);
	if (arena == MAP_FAILED) {
		fprintf(stderr, "%s: unable to allocate arena\n", argv[0]);
		exit(1);
	}

	memset(arena, 0, arena_size);

	iocbs = malloc(max_req * sizeof(*iocbs));
	if (!iocbs) {
		fprintf(stderr, "%s: no memory for IOCBs\n", argv[0]);
		exit(1);
	}

	iolist = malloc(max_req * sizeof(*iocbs));
	if (!iolist) {
		fprintf(stderr, "%s: no memory for IOCB list\n", argv[0]);
		exit(1);
	}

	events = malloc(max_req * sizeof(*events));
	if (!iolist) {
		fprintf(stderr, "%s: no memory for IOCB list\n", argv[0]);
		exit(1);
	}

	rc = io_queue_init(max_req, &ioctx);
	if (rc < 0) {
		fprintf(stderr, "%s: unable to initialize IO context: %s\n",
				argv[0], strerror(-rc));
		exit(1);
	}

	/* Prepopulate our IO requests
	 */
	ios_ready = 0;
	ioptr = iocbs;
	iolist_ptr = iolist;
	for (i = 0; i < qd; i++) {
		for (j = 0; j < ndev; j++) {
			if (!devs[j].io_base)
				devs[j].io_base = ioptr;

			/* Initial iocb prep, will be overwritten in
			 * prepare_request() with proper offset and operation.
			 */
			io_prep_pwrite(ioptr, devs[j].fd, arena, req_size, 0);
			ioptr->data = &devs[j];
			arena += req_size;

			if (prepare_request(&devs[j], ioptr)) {
				fprintf(stderr, "Premature end of device for "
						"%s\n", devs[j].name);
				exit(1);
			}

			*iolist_ptr++ = ioptr++;
			ios_ready++;
		}
	}

	/* Populate the replacement list
	 */
	buf_dev = 0;
	buf_next = NULL;
	buf_ready = NULL;
	for (i = 0; i < qd; i++) {
		buf_p = (struct buf_list *) arena;
		buf_p->next = buf_ready;
		buf_ready = buf_p;
		arena += req_size;
	}

	clock_gettime(CLOCK_MONOTONIC_HR, &now);
	end.tv_sec = now.tv_sec + run_time;
	end.tv_nsec = now.tv_nsec;

	devs[0].replace = 0;
	in_flight = 0;
	clock_gettime(CLOCK_MONOTONIC_HR, &start);

	/* Prime the IO pump with our prepared requests
	 */
	rc = io_submit(ioctx, ios_ready, iolist);
	if (rc < 0) {
		fprintf(stderr, "%s: io_submit() failed: %s\n",
				argv[0], strerror(-rc));
		exit(1);
	}

	in_flight += ios_ready;
	iolist_ptr = iolist;
	ios_ready = 0;

	/* Main IO loop
	 */
	while (time_before(&now, &end) && !end_of_device) {
		count = io_getevents(ioctx, 1, in_flight, events, NULL);
		if (count <= 0) {
			fprintf(stderr, "%s: io_getevents() failed: "
					"%s\n", argv[0], strerror(-rc));
			exit(1);
		}

		for (i = 0; i < count && !end_of_device; i++) {
			struct iocb *iocb = events[i].obj;
			struct dev_info *dev = iocb->data;

			if (events[i].res2) {
				fprintf(stderr, "%s: got error for %s:"
						" %lu\n", argv[0],
						dev->name, 
						events[i].res2);
				exit(1);
			}

			end_of_device = prepare_request(dev, iocb);
			if (!end_of_device) {
				*iolist_ptr++ = iocb;
				ios_ready++;
			}

			in_flight--;
		}

		/* If we're here, then odds are good we have IO to submit.
		 * Check just in case something woke us up other than an
		 * IO completion.
		 */
		if (ios_ready) {
			rc = io_submit(ioctx, ios_ready, iolist);
			if (rc < 0) {
				fprintf(stderr, "%s: io_submit() failed: %s\n",
						argv[0], strerror(-rc));
				exit(1);
			}

			in_flight += ios_ready;
			iolist_ptr = iolist;
			ios_ready = 0;
		}

		clock_gettime(CLOCK_MONOTONIC_HR, &now);
	}

	if (end_of_device) {
		actual_time = now.tv_nsec - start.tv_nsec;
		actual_time /= 10e9;
		actual_time += now.tv_sec - start.tv_sec;
	} else
		actual_time = run_time;

	/* Ok, test time is finished, drain outstanding requests
	 */
	while (in_flight) {
		count = io_getevents(ioctx, 1, in_flight, events, NULL);
		if (count <= 0) {
			fprintf(stderr, "%s: draining io_getevents() failed: "
					"%s\n", argv[0], strerror(-rc));
			exit(1);
		}

		for (i = 0; i < count; i++) {
			struct iocb *iocb = events[i].obj;
			struct dev_info *dev = iocb->data;

			if (events[i].res2) {
				fprintf(stderr, "%s: draining got error for %s:"
						" %lu\n", argv[0],
						dev->name, 
						events[i].res2);
				exit(1);
			}

			in_flight--;
		}
	}

	/* Find the targets that wrote the min and max data so we can
	 * calculate the skew.
	 */
	min_data = max_data = 0;
	total_data = total_writes = total_count= 0;
	for (i = 0; i < ndev; i++) {
		if (devs[i].count < devs[min_data].count)
			min_data = i;
		if (devs[i].count > devs[max_data].count)
			max_data = i;
		total_data += devs[i].count * req_size;
		total_writes += devs[i].writes;
		total_count += devs[i].count;
	}
	devs[min_data].status = 'm';
	devs[max_data].status = 'M';

	printf("run time: %.6f seconds%s\n", actual_time,
	       end_of_device ? " (end of device reached)" : "");
	printf("queue depth: %d\n", qd);
	printf("operation: %s ", random_offsets ? "random" : "sequential");
	if (write_pct >= 1.0)
		printf("write\n");
	else if (write_pct == 0.0)
		printf("read\n");
	else {
		printf("mixed (goal %.02f%% writes)\n", write_pct * 100);
		printf("random request seed: %lu\n", mix_seed);
	}
	if (random_offsets)
		printf("random offset seed: %lu\n", seed);
	if (random_range)
		printf("random range: %lu bytes\n", random_range * req_size);
	printf("request size: %lu bytes\n\n", req_size);

	for (i = 0; i < ndev; i++) {
		mbs = ((double) devs[i].count * req_size) / actual_time;
		mbs /= 1024 * 1024;
		printf("%c %s: %lu %.2f MB/s", devs[i].status,
			devs[i].name, devs[i].count * req_size, mbs);
		if (write_pct != 0.0 && write_pct < 1.0) {
			printf("  %02.f%% writes",
				100.0 * devs[i].writes / devs[i].count);
		}
		printf("\n");
	}

	mbs = (double) total_data / actual_time;
	mbs /= 1024 * 1024;
	printf("total: %lu %.2f MB/s", total_data, mbs);
	mbs = (double) (devs[max_data].count - devs[min_data].count);
	mbs *= req_size;
	mbs /= actual_time;
	mbs /= 1024 * 1024;
	printf(" skew %.2f MB/s", mbs);
	if (write_pct != 0.0 && write_pct < 1.0)
		printf("  %02.f%% writes", 100.0 * total_writes / total_count);
	printf("\n");

	return 0;
}
Ejemplo n.º 26
0
/*
 * append to the end of a file using AIO DIRECT.
 */
void aiodio_append(char *filename)
{
	int fd;
	void *bufptr;
	int i;
	int w;
	struct iocb iocb_array[NUM_AIO];
	struct iocb *iocbs[NUM_AIO];
	off_t offset = 0;
	io_context_t myctx;
	struct io_event event;
    struct timespec timeout;

	fd = open(filename, O_DIRECT|O_WRONLY|O_CREAT, 0666);
	if (fd < 0) {
		perror("cannot create file");
		return;
	}

	memset(&myctx, 0, sizeof(myctx));
	io_queue_init(NUM_AIO, &myctx);

	for (i = 0; i < NUM_AIO; i++ ) {
		if (posix_memalign(&bufptr, 4096, AIO_SIZE)) {
			perror("cannot malloc aligned memory");
			return;
		}
		memset(bufptr, 0, AIO_SIZE);
		io_prep_pwrite(&iocb_array[i], fd, bufptr, AIO_SIZE, offset);
		iocbs[i] = &iocb_array[i];
		offset += AIO_SIZE;
	}

	/*
	 * Start the 1st NUM_AIO requests
	 */
	if ((w = io_submit(myctx, NUM_AIO, iocbs)) < 0) {
		fprintf(stderr, "io_submit write returned %d\n", w);
	}

	/*
	 * As AIO requests finish, keep issuing more AIOs.
	 */
	for (; i < 1000; i++) {
		int n = 0;
		struct iocb *iocbp;
	
		n = io_getevents(myctx, 1, 1, &event, &timeout);
                if (n > 0) {
		  iocbp = (struct iocb *)event.obj;

		if( n > 0){
		io_prep_pwrite(iocbp, fd, iocbp->u.c.buf, AIO_SIZE, offset);
		offset += AIO_SIZE;
		if ((w = io_submit(myctx, 1, &iocbp)) < 0) {
			fprintf(stderr, "write %d returned %d\n", i, w);
		  }
		 }
		}
	}
}
Ejemplo n.º 27
0
int main(int argc, char **argv)
{
	io_context_t ctx;
	struct iocb iocb;
	struct iocb *iocbs[1];
	struct io_event event;
	struct stat st;
	char *ptr, *buf, one[PATH_MAX], two[PATH_MAX];
	size_t buflen, ptrlen;
	long rc;
	int fd1, fd2;

	if ((argc < 2) || (strcmp(argv[1],"-h") == 0)) {
		printf("Usage: partial_aio_direct <filename>\n");
		exit(1);
	}

	snprintf(one, sizeof(one), "%s-1", argv[1]);
	snprintf(two, sizeof(two), "%s-2", argv[1]);

	unlink(one);
	unlink(two);

	fd1 = open(one, O_CREAT|O_RDWR|O_DIRECT, 0644);
	if (fd1 < 0) {
		perror("open");
		exit(1);
	}

	fd2 = open(two, O_CREAT|O_RDWR|O_DIRECT, 0644);
	if (fd2 < 0) {
		perror("open");
		exit(1);
	}

	if (fstat(fd1, &st)) {
		perror("open");
		exit(1);
	}

	if (ftruncate(fd1, st.st_blksize)) {
		perror("ftruncate()");
		exit(1);
	}
	if (ftruncate(fd2, st.st_blksize)) {
		perror("ftruncate()");
		exit(1);
	}
	if (ftruncate(fd1, st.st_blksize * 2)) {
		perror("ftruncate()");
		exit(1);
	}
	if (ftruncate(fd2, st.st_blksize * 2)) {
		perror("ftruncate()");
		exit(1);
	}

	/* assumes this is a power of two */
	buflen = st.st_blksize * 2;
	ptrlen = st.st_blksize * 4;

	/* some slop */
	ptr = calloc(1, ptrlen);
	if (ptr == NULL) {
		perror("calloc");
		exit(1);
	}

	/* align buf to the next natural buflen alignment after ptr */
	buf = align_pow2(ptr, st.st_blksize);

	rc = io_queue_init(100, &ctx);
	if (rc) {
		printf("queue_init: %ld\n", rc);
		exit(1);
	}

	io_prep_pwrite(&iocb, fd1, buf, buflen, 0);

	memset(ptr, 0x42, ptrlen);

	printf("saw block size %lu, writing with buflen %lu\n", st.st_blksize,
		buflen);

	iocbs[0] = &iocb;

	rc = io_submit(ctx, 1, iocbs);
	if (rc != 1) {
		printf("submit: %ld\n", rc);
		exit(1);
	}

	rc = io_getevents(ctx, 1, 1, &event, NULL);
	printf("got %ld: data %p iocb %p res %ld res2 %ld\n", rc,
			event.data, event.obj, event.res, event.res2);

	return 0;
}
Ejemplo n.º 28
0
Archivo: usb.c Proyecto: helaibai/usbip
static void *aio_in_thread (void *param)
{
	char		*name = (char *) param;
	int		status;
	io_context_t	ctx = 0;
	struct iocb	*queue, *iocb;
	unsigned	i;

	status = source_open (name);
	if (status < 0)
		return 0;
	source_fd = status;
	pthread_cleanup_push (close_fd, &source_fd);

	/* initialize i/o queue */
	status = io_setup (aio_in, &ctx);
	if (status < 0) {
		perror ("aio_in_thread, io_setup");
		return 0;
	}
	pthread_cleanup_push (queue_release, &ctx);

	if (aio_in == 0)
		aio_in = 1;
	queue = alloca (aio_in * sizeof *iocb);

	/* populate and (re)run the queue */
	for (i = 0, iocb = queue; i < aio_in; i++, iocb++) {
		char *buf = malloc (iosize);

		if (!buf) {
			fprintf(stderr, "%s can't get buffer[%d]\n",
				__FUNCTION__, i);
			return 0;
		}

		/* host receives the data we're writing */
		io_prep_pwrite (iocb, source_fd,
			buf, fill_in_buf (buf, iosize),
			0);
		io_set_callback (iocb, in_complete);
		iocb->key = USB_DIR_IN;

		status = io_submit (ctx, 1, &iocb);
		if (status < 0) {
			perror (__FUNCTION__);
			break;
		}
		aio_in_pending++;
		if (verbose > 2)
			fprintf(stderr, "%s submit uiocb %p\n",
				__FUNCTION__, iocb);
	}

	status = io_run (ctx, &aio_in_pending);
	if (status < 0)
		perror ("aio_in_thread, io_run");

	/* clean up */
	fflush (stderr);
	pthread_cleanup_pop (1);
	pthread_cleanup_pop (1);

	return 0;
}
Ejemplo n.º 29
0
static int
vdev_file_io_start(zio_t *zio)
{
	vdev_t *vd = zio->io_vd;
	vdev_file_t *vf = vd->vdev_tsd;
#ifdef LINUX_AIO
	struct iocb *iocbp = &zio->io_aio;
#endif

	ssize_t resid;
	int error;

	if (zio->io_type == ZIO_TYPE_IOCTL) {
		zio_vdev_io_bypass(zio);

		/* XXPOLICY */
		if (!vdev_readable(vd)) {
			zio->io_error = ENXIO;
			return (ZIO_PIPELINE_CONTINUE);
		}

		switch (zio->io_cmd) {
		case DKIOCFLUSHWRITECACHE:
			if (zfs_nocacheflush)
				break;

			/* This doesn't actually do much with O_DIRECT... */
			zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC,
			    kcred, NULL);
			dprintf("fsync(%s) = %d\n", vdev_description(vd),
			    zio->io_error);

			if (vd->vdev_nowritecache) {
				zio->io_error = ENOTSUP;
				break;
			}

			/* Flush the write cache */
			error = flushwc(vf->vf_vnode);
			dprintf("flushwc(%s) = %d\n", vdev_description(vd),
			    error);

			if (error) {
#ifdef _KERNEL
				cmn_err(CE_WARN, "Failed to flush write cache "
				    "on device '%s'. Data on pool '%s' may be lost "
				    "if power fails. No further warnings will "
				    "be given.", vdev_description(vd),
				    spa_name(vd->vdev_spa));
#endif

				vd->vdev_nowritecache = B_TRUE;
				zio->io_error = error;
			}

			break;
		default:
			zio->io_error = ENOTSUP;
		}

		return (ZIO_PIPELINE_CONTINUE);
	}

	/*
	 * In the kernel, don't bother double-caching, but in userland,
	 * we want to test the vdev_cache code.
	 */
	if (zio->io_type == ZIO_TYPE_READ && vdev_cache_read(zio) == 0)
		return (ZIO_PIPELINE_STOP);

	if ((zio = vdev_queue_io(zio)) == NULL)
		return (ZIO_PIPELINE_STOP);

	/* XXPOLICY */
	if (zio->io_type == ZIO_TYPE_WRITE)
		error = vdev_writeable(vd) ? vdev_error_inject(vd, zio) : ENXIO;
	else
		error = vdev_readable(vd) ? vdev_error_inject(vd, zio) : ENXIO;
	error = (vd->vdev_remove_wanted || vd->vdev_is_failing) ? ENXIO : error;
	if (error) {
		zio->io_error = error;
		zio_interrupt(zio);
		return (ZIO_PIPELINE_STOP);
	}

#ifdef LINUX_AIO
	if (zio->io_aio_ctx && zio->io_aio_ctx->zac_enabled) {
		if (zio->io_type == ZIO_TYPE_READ)
			io_prep_pread(&zio->io_aio, vf->vf_vnode->v_fd,
			    zio->io_data, zio->io_size, zio->io_offset);
		else
			io_prep_pwrite(&zio->io_aio, vf->vf_vnode->v_fd,
			    zio->io_data, zio->io_size, zio->io_offset);

		zio->io_aio.data = zio;

		do {
			error = io_submit(zio->io_aio_ctx->zac_ctx, 1, &iocbp);
		} while (error == -EINTR);

		if (error < 0) {
			zio->io_error = -error;
			zio_interrupt(zio);
		} else
			VERIFY(error == 1);

		return (ZIO_PIPELINE_STOP);
	}
#endif

	zio->io_error = vn_rdwr(zio->io_type == ZIO_TYPE_READ ?
	    UIO_READ : UIO_WRITE, vf->vf_vnode, zio->io_data,
	    zio->io_size, zio->io_offset, UIO_SYSSPACE,
	    0, RLIM64_INFINITY, kcred, &resid);

	if (resid != 0 && zio->io_error == 0)
		zio->io_error = ENOSPC;

	zio_interrupt(zio);

	return (ZIO_PIPELINE_STOP);
}
Ejemplo n.º 30
0
int main(int argc, char * argv[])
{
    int sg_fd, k, ok;
    unsigned char inqCmdBlk [INQ_CMD_LEN] =
                                {0x12, 0, 0, 0, INQ_REPLY_LEN, 0};
    unsigned char turCmdBlk [TUR_CMD_LEN] =
                                {0x00, 0, 0, 0, 0, 0};
    unsigned char inqBuff[INQ_REPLY_LEN];
    sg_io_hdr_t io_hdr;
    char * file_name = 0;
    char ebuff[EBUFF_SZ];
    unsigned char sense_buffer[32];
    int do_extra = 0;

    for (k = 1; k < argc; ++k) {
        if (0 == memcmp("-x", argv[k], 2))
            do_extra = 1;
        else if (*argv[k] == '-') {
            printf("Unrecognized switch: %s\n", argv[k]);
            file_name = 0;
            break;
        }
        else if (0 == file_name)
            file_name = argv[k];
        else {
            printf("too many arguments\n");
            file_name = 0;
            break;
        }
    }
    if (0 == file_name) {
        printf("Usage: 'sg_simple_aio [-x] <sg_device>'\n");
        return 1;
    }

    /* An access mode of O_RDWR is required for write()/read() interface */
    if ((sg_fd = open(file_name, O_RDWR)) < 0) {
        snprintf(ebuff, EBUFF_SZ,
		 "sg_simple_aio: error opening file: %s", file_name);
        perror(ebuff);
        return 1;
    }
    /* Just to be safe, check we have a new sg device by trying an ioctl */
    if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
        printf("sg_simple_aio: %s doesn't seem to be an new sg device\n",
               file_name);
        close(sg_fd);
        return 1;
    }

    /* Prepare INQUIRY command */
    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
    io_hdr.interface_id = 'S';
    io_hdr.cmd_len = sizeof(inqCmdBlk);
    /* io_hdr.iovec_count = 0; */  /* memset takes care of this */
    io_hdr.mx_sb_len = sizeof(sense_buffer);
    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
    io_hdr.dxfer_len = INQ_REPLY_LEN;
    io_hdr.dxferp = inqBuff;
    io_hdr.cmdp = inqCmdBlk;
    io_hdr.sbp = sense_buffer;
    io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */
    /* io_hdr.flags = 0; */     /* take defaults: indirect IO, etc */
    /* io_hdr.pack_id = 0; */
    /* io_hdr.usr_ptr = NULL; */

#if 1
    {
        struct iocb a_iocb;
        struct iocb * iocb_arr[1];
        io_context_t io_ctx;
        int res;

        if (0 != (res = io_queue_init(1, &io_ctx))) {
            printf("io_queue_init: failed %s\n", strerror(-res));
            close(sg_fd);
            return 1;
        }
        iocb_arr[0] = &a_iocb;
        io_prep_pwrite(iocb_arr[0], sg_fd, &io_hdr, sizeof(io_hdr), 0);
        io_set_callback(iocb_arr[0], my_io_callback);
        res = io_submit(io_ctx, 1, iocb_arr);
        if (1 != res) {
            printf("io_submit: returned %d\n", res);
            close(sg_fd);
            return 1;
        }
    }
#else
    if (write(sg_fd, &io_hdr, sizeof(io_hdr)) < 0) {
        perror("sg_simple_aio: Inquiry write error");
        close(sg_fd);
        return 1;
    }
#endif
    /* sleep(3); */
    if (read(sg_fd, &io_hdr, sizeof(io_hdr)) < 0) {
        perror("sg_simple_aio: Inquiry read error");
        close(sg_fd);
        return 1;
    }

    /* now for the error processing */
    ok = 0;
    switch (sg_err_category3(&io_hdr)) {
    case SG_LIB_CAT_CLEAN:
        ok = 1;
        break;
    case SG_LIB_CAT_RECOVERED:
        printf("Recovered error on INQUIRY, continuing\n");
        ok = 1;
        break;
    default: /* won't bother decoding other categories */
        sg_chk_n_print3("INQUIRY command error", &io_hdr);
        break;
    }

    if (ok) { /* output result if it is available */
        char * p = (char *)inqBuff;
        int f = (int)*(p + 7);
        printf("Some of the INQUIRY command's results:\n");
        printf("    %.8s  %.16s  %.4s  ", p + 8, p + 16, p + 32);
        printf("[wide=%d sync=%d cmdque=%d sftre=%d]\n",
               !!(f & 0x20), !!(f & 0x10), !!(f & 2), !!(f & 1));
        /* Extra info, not necessary to look at */
        if (do_extra)
            printf("INQUIRY duration=%u millisecs, resid=%d, msg_status=%d\n",
                   io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
    }

    /* Prepare TEST UNIT READY command */
    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
    io_hdr.interface_id = 'S';
    io_hdr.cmd_len = sizeof(turCmdBlk);
    io_hdr.mx_sb_len = sizeof(sense_buffer);
    io_hdr.dxfer_direction = SG_DXFER_NONE;
    io_hdr.cmdp = turCmdBlk;
    io_hdr.sbp = sense_buffer;
    io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */

    if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
        perror("sg_simple_aio: Test Unit Ready SG_IO ioctl error");
        close(sg_fd);
        return 1;
    }

    /* now for the error processing */
    ok = 0;
    switch (sg_err_category3(&io_hdr)) {
    case SG_LIB_CAT_CLEAN:
        ok = 1;
        break;
    case SG_LIB_CAT_RECOVERED:
        printf("Recovered error on Test Unit Ready, continuing\n");
        ok = 1;
        break;
    default: /* won't bother decoding other categories */
        sg_chk_n_print3("Test Unit Ready command error", &io_hdr);
        break;
    }

    if (ok)
        printf("Test Unit Ready successful so unit is ready!\n");
    else
        printf("Test Unit Ready failed so unit may _not_ be ready!\n");

    if (do_extra)
        printf("TEST UNIT READY duration=%u millisecs, resid=%d, msg_status=%d\n",
               io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);

    close(sg_fd);
    return 0;
}