Example #1
0
int aio_read_random(char* file_name)
{
	int ret = 0;
	
	int fd = -1;
	fd = ::open(file_name, O_RDONLY);
	fprintf(stdout, "open %s, fd %d\n", file_name, fd);

	int64_t file_length = ::lseek(fd, 0, SEEK_END);
	int piece_num = (file_length + PIECE_LEN - 1)/ PIECE_LEN;
	int bitfield_size = (piece_num + 8 - 1)/8;
	u_int8_t* bitfield = (u_int8_t*)malloc(bitfield_size);
	memset(bitfield, 0, bitfield_size);

	fprintf(stdout, "file_length=%ld, piece_num=%d, bitfield_size=%d\n", file_length, piece_num, bitfield_size);

	io_context_t myctx;
	memset(&myctx, 0, sizeof(myctx));
    io_queue_init(AIO_MAXIO, &myctx);

	while(1)
	{
		// read piece by random
		int piece_index = rand_index(piece_num);
		int piece_pos = bitfield_find_unset(bitfield, piece_num, piece_index);
		if(piece_pos == -1)
		{
			break;
		}
		//printf("read piece=%d\n", piece_pos);
		struct iocb* io2 = (struct iocb*)malloc(sizeof(struct iocb));
		memset(io2, 0, sizeof(struct iocb));

		u_int8_t* buff = NULL;
		posix_memalign((void **)&buff, getpagesize(), PIECE_LEN);
		io_prep_pread(io2, fd, buff, PIECE_LEN, PIECE_LEN*piece_pos);
		io2->data = (void*)piece_pos;
		io_submit(myctx, 1, &io2);

		struct io_event events[AIO_MAXIO];
		int num = io_getevents(myctx, 0, AIO_MAXIO, events, NULL);
	    //printf("io_request completed %d\n", num);
		for(int i=0;i<num;i++)
		{
			struct iocb *objp = events[i].obj;
			int finish_piece_pos = (int)(long)objp->data;
			//printf("done_piece=%d, res=%ld, res2=%ld\n", finish_piece_pos, events[i].res, events[i].res2);
			//cb(myctx, io2, events[i].res, events[i].res2);
			bitfield_set_one(bitfield, piece_num, finish_piece_pos);
			free(objp->u.c.buf);
			free(objp);
		}
		
	}
	
	close(fd);
	fd = -1;
	
	return 0;
}
Example #2
0
int file_async_init(void)
{
  unsigned int i;

  if (file_io_mode != FILE_IO_MODE_ASYNC)
    return 0;
  
  file_async_backlog = sb_get_value_int("file-async-backlog");
  if (file_async_backlog <= 0) {
    log_text(LOG_FATAL, "Invalid value of file-async-backlog: %d",
             file_async_backlog);
    return 1;
  }

  aio_ctxts = (sb_aio_context_t *)calloc(sb_globals.num_threads,
                                         sizeof(sb_aio_context_t));
  for (i = 0; i < sb_globals.num_threads; i++)
  {
    if (io_queue_init(file_async_backlog, &aio_ctxts[i].io_ctxt))
    {
      log_errno(LOG_FATAL, "io_queue_init() failed!");
      return 1;
    }
      
    aio_ctxts[i].events = (struct io_event *)malloc(file_async_backlog *
                                                    sizeof(struct io_event));
    if (aio_ctxts[i].events == NULL)
    {
      log_errno(LOG_FATAL, "Failed to allocate async I/O context!");
      return 1;
    }
  }

  return 0;
}
Example #3
0
AsyncFile::AsyncFile(std::string & _fileName, AIOController * _controller, int _maxIO) : aioContext(0), events(0), fileHandle(0), controller(_controller), pollerRunning(0)
{
	::pthread_mutex_init(&fileMutex,0);
	::pthread_mutex_init(&pollerMutex,0);

	maxIO = _maxIO;
	fileName = _fileName;
	if (io_queue_init(maxIO, &aioContext))
	{
		throw AIOException(NATIVE_ERROR_CANT_INITIALIZE_AIO, "Can't initialize aio, out of AIO Handlers");
	}

	fileHandle = ::open(fileName.data(),  O_RDWR | O_CREAT | O_DIRECT, 0666);
	if (fileHandle < 0)
	{
		io_queue_release(aioContext);
		throw AIOException(NATIVE_ERROR_CANT_OPEN_CLOSE_FILE, "Can't open file");
	}

#ifdef DEBUG
	fprintf (stderr,"File Handle %d", fileHandle);
#endif

	events = (struct io_event *)malloc (maxIO * sizeof (struct io_event));

	if (events == 0)
	{
		throw AIOException (NATIVE_ERROR_CANT_ALLOCATE_QUEUE, "Can't allocate ioEvents");
	}

}
Example #4
0
/*
 * do async DIO writes to a sparse file
 */
void aiodio_sparse(char *filename, int align, int writesize, int filesize, int num_aio)
{
    int fd;
    int i;
    int w;
    static struct sigaction s;
    struct iocb **iocbs;
    off_t offset;
    io_context_t myctx;
    struct io_event event;
    int aio_inflight;

    s.sa_sigaction = sig_term_func;
    s.sa_flags = SA_SIGINFO;
    sigaction(SIGTERM, &s, 0);

    if ((num_aio * writesize) > filesize) {
        num_aio = filesize / writesize;
    }
    memset(&myctx, 0, sizeof(myctx));
    io_queue_init(num_aio, &myctx);

    iocbs = (struct iocb **)malloc(sizeof(struct iocb *) * num_aio);
    for (i = 0; i < num_aio; i++) {
        if ((iocbs[i] = (struct iocb *)malloc(sizeof(struct iocb))) == 0) {
            perror("cannot malloc iocb");
            return;
        }
    }

    WITH_SIGNALS_BLOCKED(
        fd = open(filename, O_DIRECT|O_WRONLY|O_CREAT|O_EXCL, 0600);
        if (fd > 0)
        filename1=filename;
    );
Example #5
0
void AsyncIO::initializeContext() {
  if (!ctxSet_.load(std::memory_order_acquire)) {
    std::lock_guard<std::mutex> lock(initMutex_);
    if (!ctxSet_.load(std::memory_order_relaxed)) {
      int rc = io_queue_init(capacity_, &ctx_);
      // returns negative errno
      if (rc == -EAGAIN) {
        long aio_nr, aio_max;
        std::unique_ptr<FILE, int(*)(FILE*)>
          fp(fopen("/proc/sys/fs/aio-nr", "r"), fclose);
        PCHECK(fp);
        CHECK_EQ(fscanf(fp.get(), "%ld", &aio_nr), 1);

        std::unique_ptr<FILE, int(*)(FILE*)>
          aio_max_fp(fopen("/proc/sys/fs/aio-max-nr", "r"), fclose);
        PCHECK(aio_max_fp);
        CHECK_EQ(fscanf(aio_max_fp.get(), "%ld", &aio_max), 1);

        LOG(ERROR) << "No resources for requested capacity of " << capacity_;
        LOG(ERROR) << "aio_nr " << aio_nr << ", aio_max_nr " << aio_max;
      }

      checkKernelError(rc, "AsyncIO: io_queue_init failed");
      DCHECK(ctx_);
      ctxSet_.store(true, std::memory_order_release);
    }
  }
}
Example #6
0
void AsyncIO::initializeContext() {
  if (!ctx_) {
    int rc = io_queue_init(capacity_, &ctx_);
    // returns negative errno
    checkKernelError(rc, "AsyncIO: io_queue_init failed");
    DCHECK(ctx_);
  }
}
Example #7
0
static errcode_t unix_vec_read_blocks(io_channel *channel,
				      struct io_vec_unit *ivus, int count)
{
	int i;
	int ret;
	io_context_t io_ctx;
	struct iocb *iocb = NULL, **iocbs = NULL;
	struct io_event *events = NULL;
	int64_t offset;
	int submitted, completed = 0;

	ret = OCFS2_ET_NO_MEMORY;
	iocb = malloc((sizeof(struct iocb) * count));
	iocbs = malloc((sizeof(struct iocb *) * count));
	events = malloc((sizeof(struct io_event) * count));
	if (!iocb || !iocbs || !events)
		goto out;

	memset(&io_ctx, 0, sizeof(io_ctx));
	ret = io_queue_init(count, &io_ctx);
	if (ret)
		return ret;

	for (i = 0; i < count; ++i) {
		offset = ivus[i].ivu_blkno * channel->io_blksize;
		io_prep_pread(&(iocb[i]), channel->io_fd, ivus[i].ivu_buf,
			      ivus[i].ivu_buflen, offset);
		iocbs[i] = &iocb[i];
	}

resubmit:
	ret = io_submit(io_ctx, count - completed, &iocbs[completed]);
	if (!ret && (count - completed))
		ret = OCFS2_ET_SHORT_READ;
	if (ret < 0)
		goto out;
	submitted = ret;

	ret = io_getevents(io_ctx, submitted, submitted, events, NULL);
	if (ret < 0)
		goto out;

	completed += submitted;
	if (completed < count)
		goto resubmit;

out:
	if (ret >= 0)
		ret = 0;
	if (!ret)
		channel->io_bytes_read += (count * channel->io_blksize);
	free(iocb);
	free(iocbs);
	free(events);
	io_queue_release(io_ctx);

	return ret;
}
Example #8
0
void aio_setup(io_context_t *io_ctx, int n)
{
    int res = io_queue_init(n, io_ctx);
    if (res != 0) {
	fprintf(stderr, "io_queue_setup(%d) returned %d (%s)\n",
		n, res, strerror(-res));
	exit(3);
    }
}
Example #9
0
static bool init_aio_linux(struct vfs_handle_struct *handle)
{
	struct tevent_timer *te = NULL;

	if (event_fd != -1) {
		/* Already initialized. */
		return true;
	}

	/* Schedule a shutdown event for 30 seconds from now. */
	te = tevent_add_timer(handle->conn->sconn->ev_ctx,
				NULL,
				timeval_current_ofs(30, 0),
				aio_linux_housekeeping,
				NULL);

	if (te == NULL) {
		goto fail;
	}

	event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
	if (event_fd == -1) {
		goto fail;
	}

	aio_read_event = tevent_add_fd(server_event_context(),
				NULL,
				event_fd,
				TEVENT_FD_READ,
				aio_linux_done,
				NULL);
	if (aio_read_event == NULL) {
		goto fail;
	}

	if (io_queue_init(lp_aio_max_threads(), &io_ctx)) {
		goto fail;
	}

	DEBUG(10,("init_aio_linux: initialized with up to %d events\n",
		  (int)lp_aio_max_threads()));

	return true;

  fail:

	DEBUG(10,("init_aio_linux: initialization failed\n"));

	TALLOC_FREE(te);
	TALLOC_FREE(aio_read_event);
	if (event_fd != -1) {
		close(event_fd);
		event_fd = -1;
	}
	memset(&io_ctx, '\0', sizeof(io_ctx));
	return false;
}
Example #10
0
static void setup(void)
{
	int ret;

	tst_sig(NOFORK, DEF_HANDLER, cleanup);

	/* Pause if option was specified */
	TEST_PAUSE;

	tst_tmpdir();
	/* 创建aiofile文件 */
	if ((fd = open(fname, O_RDWR | O_CREAT, 0600)) < 0)
		tst_brkm(TFAIL, cleanup, "failed to open %s "
			 "file, errno: %d", fname, errno);
	stat(fname, &s);
	/* 分配iocbs数组 */
	if ((iocbs = malloc(sizeof(int) * nr)) == NULL)
		tst_brkm(TFAIL, cleanup, "malloc for iocbs failed - "
			 "errno: %d", errno);
	/* 分配iocb对象 */
	if ((iocbs[0] = malloc(sizeof(struct iocb))) == NULL)
		tst_brkm(TFAIL, cleanup, "malloc for iocbs elements failed - "
			 "errno: %d", errno);
	if (S_ISCHR(s.st_mode)) {
		if ((ret =
		     posix_memalign((void **)&srcbuf, bufsize, bufsize)) != 0) /* 分配源buf */
			tst_brkm(TFAIL, cleanup,
				 "posix_memalign for srcbuf "
				 "failed - errno: %d", errno);
		if ((ret =
		     posix_memalign((void **)&dstbuf, bufsize, bufsize)) != 0) /* 分配目标buf */
			tst_brkm(TFAIL, cleanup,
				 "posix_memalign for dstbuf "
				 "failed - errno: %d", errno);
	} else {
		if ((srcbuf = malloc(sizeof(char) * bufsize)) == NULL)
			tst_brkm(TFAIL, cleanup, "malloc for srcbuf "
				 "failed - errno: %d", errno);
		if ((dstbuf = malloc(sizeof(char) * bufsize)) == NULL)
			tst_brkm(TFAIL, cleanup, "malloc for dstbuf "
				 "failed - errno: %d", errno);
	}
	memset((void *)srcbuf, 65, bufsize); /* 源buf赋值 */
	if ((ret = io_queue_init(1, &io_ctx)) != 0) /* 初始化IO上下文对象 */
		tst_brkm(TFAIL, cleanup, "io_queue_init failed: %s",
			 strerror(ret));
}
Example #11
0
static int io_async_sendfile_init(struct iothread *t)
{
	memset(&aio_ctx, 0, sizeof(aio_ctx));
	if ( io_queue_init(AIO_QUEUE_SIZE, &aio_ctx) ) {
		fprintf(stderr, "io_queue_init: %s\n", os_err());
		return 0;
	}

	aio_iocbs = hgang_new(sizeof(struct iocb), 0);
	if ( NULL == aio_iocbs )
		return 0;

	efd = nbio_eventfd_new(0, aio_event, NULL);
	if ( NULL == efd )
		return 0;
	nbio_eventfd_add(t, efd);
	return 1;
}
Example #12
0
int aiobe_open(struct device* dev, const char* path, int flags, mode_t mode) {
	int i;

	dev->ops = &aiobe_device_ops;
	dev->data = malloc(sizeof(struct aiobe_data));

	int ret = open(path, flags, mode);
	if (ret<0) {
		free(dev->data);
		return -1;
	}

	D(dev)->fd = ret;

	if (io_queue_init(1000, &D(dev)->ctx)) {
		close(D(dev)->fd);
		free(dev->data);
		return -1;
	}

	for(i=0;i<10;i++)
		pthread_create(&D(dev)->cbt[i], NULL, aiobe_thread, dev);
	return 0;
}
Example #13
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);
		  }
		 }
		}
	}
}
Example #14
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;
}
Example #15
0
int test_aio(char* src_file, char* dst_file)
{
    int length = sizeof("abcdefg");
    char* content = (char*)malloc(length);
    io_context_t myctx;
    int rc;
    char* buff = NULL;
    int offset = 0;
    int num, i, tmp;
    
    if((srcfd=open(src_file, O_CREAT|O_RDWR, 0666))<0)
	{
		printf("open srcfile error\n");
		exit(1);
	}

	printf("srcfd=%d\n", srcfd);
	lseek(srcfd, 0, SEEK_SET);
	write(srcfd, "abcdefg", length);
	
	lseek(srcfd, 0, SEEK_SET);
    read(srcfd, content, length);

    printf("write in the srcfile successful, content is [%s]\n", content);

	if((odsfd=open(dst_file, O_CREAT|O_RDWR, 0666))<0)
	{
		close(srcfd);
		printf("open odsfile error\n");
		exit(1);
	}
	
    memset(&myctx, 0, sizeof(myctx));
    io_queue_init(AIO_MAXIO, &myctx);

    struct iocb *io = (struct iocb*)malloc(sizeof(struct iocb));
    int iosize = AIO_BLKSIZE;
    tmp = posix_memalign((void **)&buff, getpagesize(), AIO_BLKSIZE);
	if(tmp < 0)
	{
		printf("posix_memalign error\n");
		exit(1);
	}
	if(NULL == io)
	{
		printf("io out of memeory\n");
		exit(1);
	}

	io_prep_pread(io, srcfd, buff, iosize, offset);
	io_set_callback(io, rd_done);

	printf("START...\n\n");
	rc = io_submit(myctx, 1, &io);
	if(rc < 0)
		printf("io_submit read error\n");

   	printf("\nsubmit  %d  read request\n", rc);

    //m_io_queue_run(myctx);
    struct io_event events[AIO_MAXIO];
    io_callback_t cb;

    int finish_count = 0;
    
    while(1)
    {
    	num = io_getevents(myctx, 0, AIO_MAXIO, events, NULL);
	    printf("\n%d io_request completed\n\n", num);
		for(i=0;i<num;i++)
		{
			cb = (io_callback_t)events[i].data;
			struct iocb *io = events[i].obj;
			printf("events[%d].data = %lX, res = %ld, res2 = %ld\n", i, cb, events[i].res, events[i].res2);
			cb(myctx, io, events[i].res, events[i].res2);
		}

		finish_count += num;
		if(finish_count >= 2)
		{
			break;
		}
	}

	return 0;
}
Example #16
0
File: aio02.c Project: kraj/ltp
static int io_tio(char *pathname, int flag, int operation)
{
	int res, fd = 0, i = 0;
	void *bufptr = NULL;
	off_t offset = 0;
	struct timespec timeout;
	struct stat fi_stat;
	size_t alignment;

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

	fd = SAFE_OPEN(pathname, flag, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

	/* determine the alignment from the blksize of the underlying device */
	SAFE_FSTAT(fd, &fi_stat);
	alignment = fi_stat.st_blksize;

	res = io_queue_init(AIO_MAXIO, &myctx);

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

		switch (operation) {
		case IO_CMD_PWRITE:
			if (posix_memalign(&bufptr, alignment, AIO_BLKSIZE)) {
				tst_brk(TBROK | TERRNO, "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)) {
				tst_brk(TBROK | TERRNO, "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;
		default:
			tst_res(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 them 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;
	}

	SAFE_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;
}
Example #17
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;
}
/**
 * Everything that is allocated here will be freed at deleteContext when the class is unloaded.
 */
JNIEXPORT jobject JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_newContext(JNIEnv* env, jobject thisObject, jint queueSize) {
    io_context_t libaioContext;
    int i = 0;

    #ifdef DEBUG
        fprintf (stdout, "Initializing context\n");
    #endif

    int res = io_queue_init(queueSize, &libaioContext);
    if (res) {
        // Error, so need to release whatever was done before
        free(libaioContext);

        throwRuntimeExceptionErrorNo(env, "Cannot initialize queue:", res);
        return NULL;
    }

    struct iocb ** iocb = (struct iocb **)malloc((sizeof(struct iocb *) * (size_t)queueSize));
    if (iocb == NULL) {
       throwOutOfMemoryError(env);
       return NULL;
    }

    for (i = 0; i < queueSize; i++) {
       iocb[i] = (struct iocb *)malloc(sizeof(struct iocb));
       if (iocb[i] == NULL) {
           // it's unlikely this would happen at this point
           // for that reason I'm not cleaning up individual IOCBs here
           // we could increase support here with a cleanup of any previously allocated iocb
           // But I'm afraid of adding not needed complexity here
           throwOutOfMemoryError(env);
           return NULL;
       }
    }

    struct io_control * theControl = (struct io_control *) malloc(sizeof(struct io_control));
    if (theControl == NULL) {
        throwOutOfMemoryError(env);
        return NULL;
    }

    res = pthread_mutex_init(&(theControl->iocbLock), 0);
    if (res) {
        free(theControl);
        free(libaioContext);
        throwRuntimeExceptionErrorNo(env, "Can't initialize mutext:", res);
        return NULL;
    }

    res = pthread_mutex_init(&(theControl->pollLock), 0);
    if (res) {
        free(theControl);
        free(libaioContext);
        throwRuntimeExceptionErrorNo(env, "Can't initialize mutext:", res);
        return NULL;
    }

    struct io_event * events = (struct io_event *)malloc(sizeof(struct io_event) * (size_t)queueSize);

    theControl->ioContext = libaioContext;
    theControl->events = events;
    theControl->iocb = iocb;
    theControl->queueSize = queueSize;
    theControl->iocbPut = 0;
    theControl->iocbGet = 0;
    theControl->used = 0;
    theControl->thisObject = (*env)->NewGlobalRef(env, thisObject);

    return (*env)->NewDirectByteBuffer(env, theControl, sizeof(struct io_control));
}
Example #19
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;
}
Example #20
0
int main(int argc, char *const *argv)
{
	struct stat st;
	off_t length = 0, offset = 0;
	io_context_t myctx;
	int c;
	extern char *optarg;
	extern int optind, opterr, optopt;

	while ((c = getopt(argc, argv, "a:b:df:n:s:wzD:")) != -1) {
		char *endp;

		switch (c) {
		case 'a':	/* alignment of data buffer */
			alignment = strtol(optarg, &endp, 0);
			alignment = (long)scale_by_kmg((long long)alignment,
							*endp);
			break;
		case 'f':	/* use these open flags */
			if (strcmp(optarg, "LARGEFILE") == 0 ||
			    strcmp(optarg, "O_LARGEFILE") == 0) {
				source_open_flag |= O_LARGEFILE;
				dest_open_flag |= O_LARGEFILE;
			} else if (strcmp(optarg, "TRUNC") == 0 ||
			           strcmp(optarg, "O_TRUNC") == 0) {
				dest_open_flag |= O_TRUNC;
			} else if (strcmp(optarg, "SYNC") == 0 ||
				   strcmp(optarg, "O_SYNC") == 0) {
				dest_open_flag |= O_SYNC;
			} else if (strcmp(optarg, "DIRECT") == 0 ||
				   strcmp(optarg, "O_DIRECT") == 0) {
				source_open_flag |= O_DIRECT;
				dest_open_flag |= O_DIRECT;
			} else if (strncmp(optarg, "CREAT", 5) == 0 ||
				   strncmp(optarg, "O_CREAT", 5) == 0) {
				dest_open_flag |= O_CREAT;
			}
			break;
		case 'd':
			debug++;
			break;
		case 'D':
			delay.tv_usec = atoi(optarg);
			break;
		case 'b':	/* block size */
			aio_blksize = strtol(optarg, &endp, 0);
			aio_blksize = (long)scale_by_kmg((long long)aio_blksize, *endp);
			break;

		case 'n':	/* num io */
			aio_maxio = strtol(optarg, &endp, 0);
			break;
		case 's':	/* size to transfer */
			length = strtoll(optarg, &endp, 0);
			length = scale_by_kmg(length, *endp);
			break;
		case 'w':	/* no write */
			no_write = 1;
			break;
		case 'z':	/* write zero's */
			zero = 1;
			break;

		default:
			usage();
		}
	}

	argc -= optind;
	argv += optind;
	
#ifndef DEBUG
	if (argc < 1) {
		usage();
	}
#else
    source_open_flag |= O_DIRECT;
    dest_open_flag |= O_DIRECT;
    aio_blksize = 1;
    aio_maxio=1;
    srcname = "junkdata";
    dstname = "ff2";
#endif
	if (!zero) {
#ifndef DEBUG
	       	if ((srcfd = open(srcname = *argv, source_open_flag)) < 0) {
#else
                if ((srcfd = open(srcname, source_open_flag)) < 0) {
#endif
			perror(srcname);
			exit(1);
		}
		argv++;
		argc--;
		length = 1073741824;
#if 0
		if (fstat(srcfd, &st) < 0) {
			perror("fstat");
			exit(1);
		}
		if (length == 0)
			length = st.st_size;
#endif
	}

	if (!no_write) {
		/*
		 * We are either copying or writing zeros to dstname
		 */
#ifndef DEBUG
		if (argc < 1) {
			usage();
		}
		if ((dstfd = open(dstname = *argv, dest_open_flag, 0666)) < 0) {
#else
            if ((dstfd = open(dstname, dest_open_flag, 0666)) < 0) {
#endif
			perror(dstname);
			exit(1);
		}
		if (zero) {
			/*
			 * get size of dest, if we are zeroing it.
			 * TODO: handle devices.
			 */
			if (fstat(dstfd, &st) < 0) {
				perror("fstat");
				exit(1);
			}
			if (length == 0)
				length = st.st_size;
		}
	}

	/* initialize state machine */
	memset(&myctx, 0, sizeof(myctx));
	io_queue_init(aio_maxio, &myctx);
	tocopy = howmany(length, aio_blksize);

	if (init_iocb(aio_maxio, aio_blksize) < 0) {
		fprintf(stderr, "Error allocating the i/o buffers\n");
		exit(1);
	}

	while (tocopy > 0) {
		int i, rc;
		/* Submit as many reads as once as possible upto aio_maxio */
		int n = MIN(MIN(aio_maxio - busy, aio_maxio),
				howmany(length - offset, aio_blksize));
		if (n > 0) {
			struct iocb *ioq[n];

			for (i = 0; i < n; i++) {
				struct iocb *io = alloc_iocb();
				int iosize = MIN(length - offset, aio_blksize);

				if (zero) {
					/*
					 * We are writing zero's to dstfd
					 */
					io_prep_pwrite(io, dstfd, io->u.c.buf,
							iosize, offset);
					io_set_callback(io, wr_done);
				} else {
					io_prep_pread(io, srcfd, io->u.c.buf,
							iosize, offset);
					io_set_callback(io, rd_done);
				}
				ioq[i] = io;
				offset += iosize;
			}

			rc = io_submit(myctx, n, ioq);
			if (rc < 0)
				io_error("io_submit", rc);

			busy += n;
			if (debug > 1)
				printf("io_submit(%d) busy:%d\n", n, busy);
			if (delay.tv_usec) {
				struct timeval t = delay;
				(void)select(0,0,0,0,&t);
			}
		}

		/*
		 * We have submitted all the i/o requests. Wait for at least one to complete
		 * and call the callbacks.
		 */
		count_io_q_waits++;
		rc = io_wait_run(myctx, 0);
		if (rc < 0)
			io_error("io_wait_run", rc);

		if (debug > 1) {
			printf("io_wait_run: rc == %d\n", rc);
			printf("busy:%d aio_maxio:%d tocopy:%d\n",
					busy, aio_maxio, tocopy);
		}
	}

	if (srcfd != -1)
		close(srcfd);
	if (dstfd != -1)
		close(dstfd);
	exit(0);
}
Example #21
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;
}
Example #22
0
void loop_aio(int fd, void *buf)
{
  int res;
  unsigned int elapsed;

  /* i/o context initialization */
  io_context_t myctx;
  memset(&myctx, 0, sizeof(myctx));
  if ((res = io_queue_init(maxinflight, &myctx)))
    io_error("io_queue_init", res);

  copied = 0;
  inflight = 0;

  if (opt_verbose)
    printf("[run %d] start\n", runid);

  while (copied < mycount)
  {
    struct iocb *ioq[maxsubmit];
    int tosubmit = 0;
    unsigned long long int index;
    struct iocb *iocb;
    struct timeval tv1, tv2;

    /* filling a context with io queries */
    while (copied + inflight + tosubmit < mycount &&
      inflight + tosubmit < maxinflight &&
      tosubmit < maxsubmit)
    {
      /* Simultaneous asynchronous operations using the same iocb produce undefined results. */
      iocb = calloc(1, sizeof(struct iocb));

      if (mode_rnd)
        index = (mydevsize / myiosize) * random() / RAND_MAX;
      else
        index = copied + inflight + tosubmit;

      if (mode_write)
        io_prep_pwrite(iocb, fd, buf, myiosize, index * myiosize);
      else
        io_prep_pread(iocb, fd, buf, myiosize, index * myiosize);

      io_set_callback(iocb, io_done);
      ioq[tosubmit] = iocb;
      tosubmit += 1;
    }

    /* if there are available slots for submitting queries, do it */
    if (tosubmit)
    {
      /* submit io and check elapsed time */
      gettimeofday(&tv1, NULL);
      if ((res = io_submit(myctx, tosubmit, ioq)) != tosubmit)
      {
        printf("only %d io submitted\n", res);
        io_error("io_submit write", res);
      }
      gettimeofday(&tv2, NULL);
      elapsed = (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000;
      if (elapsed > 200)
        printf("warning: io_submit() took %d ms, this is suspicious, maybe nr_request is too low.\n", elapsed);

      /* inflight io += newly submitted io */
      inflight += tosubmit;
    }

    /* handle completed io events */
    if ((res = io_queue_run(myctx)) < 0)
      io_error("io_queue_run", res);

    if (inflight == maxinflight ||
      (inflight && copied + inflight == mycount))
    {
      struct io_event event;
      if ((res = io_getevents(myctx, 1, 1, &event, NULL)) < 0)
        io_error("io_getevents", res);
      if (res != 1)
        errx(1, "no events?");
      ((io_callback_t)event.obj->data)(myctx, event.obj, event.res, event.res2);
    }
  }

  io_queue_release(myctx);
}
Example #23
0
int
main(int argc, char *const *argv)
{
	int srcfd;
	struct stat st;
	off_t length = 0, offset = 0;
	io_context_t myctx;

	if (argc != 2 || argv[1][0] == '-') {
		fprintf(stderr, "Usage: aioread SOURCE");
		exit(1);
	}
	
	if ((srcfd = open(srcname = argv[1], O_RDONLY)) < 0) {
		perror(srcname);
		exit(1);
	}
	
	if (fstat(srcfd, &st) < 0) {
		perror("fstat");
		exit(1);
	}

	length = st.st_size;
	
	/* initialize state machine */
	memset(&myctx, 0, sizeof(myctx));
	io_queue_init(AIO_MAXIO, &myctx);
	tocopy = howmany(length, AIO_BLKSIZE);
	
	printf("tocopy: %ld times\n", tocopy);
	
	
	int i, j;
	for (i = 0; i < AIO_MAXIO; i ++)
		memset(&aiobuf[i], '\0', sizeof(struct mybuf));
	
	int ps = getpagesize();
	
	while (tocopy > 0) {
		rc;
	
		/* Submit as many reads as once as possible upto AIO_MAXIO */
		int n = MIN(MIN(AIO_MAXIO - busy, AIO_MAXIO / 2), \
			howmany(length - offset, AIO_BLKSIZE));
		
		if (n > 0) {
			struct iocb *ioq[n];

			for (i = 0; i < n; i++) {
				struct iocb *io = (struct iocb *) malloc(sizeof(struct iocb));
				int iosize = MIN(length - offset, AIO_BLKSIZE);
				
				for (j = 0; j < AIO_MAXIO; j ++) {
					
				}
				
				char *buf;
				
				posix_memalign(&buf, ps, iosize);
				if (NULL == buf || NULL == io) {
					fprintf(stderr, "out of memory\n");
					exit(1);
				}
				
				io_prep_pread(io, srcfd, buf, iosize, offset);
				io_set_callback(io, rd_done);
				
				ioq[i] = io;
				offset += iosize;
			}
		
			rc = io_submit(myctx, n, ioq);
			
			if (rc < 0)
				io_error("io_submit", rc);
			
			busy += n;
		}
		
		// Handle IO’s that have completed
		rc = io_queue_run(myctx);
		if (rc < 0)
			io_error("io_queue_run", rc);

		// if we have maximum number of i/o’s in flight
		// then wait for one to complete
		
		if (busy == AIO_MAXIO) {
			rc = io_queue_wait(myctx, NULL);
			if (rc < 0)
				io_error("io_queue_wait", rc);
		}
	}
	
	close(srcfd);
	
	exit(0);
}