Пример #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;
}
Пример #2
0
int o2test_aio_pread(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_pread(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;
}
Пример #3
0
//return eventfd
int AIORead(std::string path,void *buf,int epfd=-1)
{
    m_filefd = openFile(path);
    if (-1 == m_filefd) {
        return -1;
    }
    
    m_ctx = 0;
    if (io_setup(8192, &m_ctx)) {
        perror("io_setup");
        return -1;
    }

    if (posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE)) {
        perror("posix_memalign");
        return 5;
    }
    printf("buf: %p\n", buf);

    for (i = 0, iocbp = iocbs; i < NUM_EVENTS; ++i, ++iocbp) {
        iocbps[i] = &iocbp->iocb;
        io_prep_pread(&iocbp->iocb, fd, buf, RD_WR_SIZE, i * RD_WR_SIZE);
        io_set_eventfd(&iocbp->iocb, efd);
        io_set_callback(&iocbp->iocb, aio_callback);
        iocbp->nth_request = i + 1;
    }

    if (io_submit(ctx, NUM_EVENTS, iocbps) != NUM_EVENTS) {
        perror("io_submit");
        return 6;
    }
}
Пример #4
0
int init_iocb(int n, int iosize)
{
	void *buf;
	int i;

	if ((iocb_free = malloc(n * sizeof(struct iocb *))) == 0) {
		return -1;
	}

	for (i = 0; i < n; i++) {
		if (!(iocb_free[i] = (struct iocb *) malloc(sizeof(struct iocb))))
			return -1;
		if (posix_memalign(&buf, alignment, iosize))
			return -1;
		if (debug > 1) {
			printf("buf allocated at 0x%p, align:%d\n",
					buf, alignment);
		}
		if (zero) {
			/*
			 * We are writing zero's to dstfd
			 */
			memset(buf, 0, iosize);
		}
		io_prep_pread(iocb_free[i], -1, buf, iosize, 0);
	}
	iocb_free_count = i;
	return 0;
}
Пример #5
0
ssize_t file_pread(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;
  long long    page_addr;
  long long    page_offset;
#endif
#ifdef HAVE_LIBAIO
  struct iocb iocb;
#else
  (void)thread_id; /* unused */
#endif
    
  if (file_io_mode == FILE_IO_MODE_SYNC)
    return pread(fd, buf, count, offset);
#ifdef HAVE_LIBAIO
  else if (file_io_mode == FILE_IO_MODE_ASYNC)
  {
    /* Use asynchronous read */
    io_prep_pread(&iocb, fd, buf, count, offset);

    if (file_submit_or_wait(&iocb, FILE_OP_TYPE_READ, 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, MAP_SHARED,
                 fd, page_addr);
    if (start == MAP_FAILED)
      return 0;
    memcpy(buffer, (char *)start + page_offset, 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(buffer, (char *)mmaps[file_id] + offset, count);

    return count;
# endif
  }
#endif /* HAVE_MMAP */
  
  return 1; /* Unknown I/O mode */
}
Пример #6
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;
}
Пример #7
0
/* Submits the read IO request */
void SubmitRead(int offset){
	int x;
	struct iocb iocbr;
	struct iocb *iocbrp=&iocbr;
    /* Init iocb structure */
	io_prep_pread(&iocbr,filedes,buffer,BUFFERSIZE,BUFFERSIZE*offset);	
	iocbr.data=(void*)buffer;
	x=io_submit(context,1,&iocbrp);					/* Submit the request */
	if(x<0)
		printf("Error while submitting read request\n %d",x);
}
Пример #8
0
int aio_read(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_pread(&iocb, fd, buffer, length, offset);
        iocb.data = cb;
	io_set_eventfd(&iocb, aio_fd);

        resp = io_submit(aio_ctx,1, &piocb);
        return resp;
}
Пример #9
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;
	}
}
Пример #10
0
void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count)
{
	u64 offset;
	offset = sector * (s64)m_blocksize + m_dataoffset;

	u32 bytesToRead = count * m_blocksize;

	struct iocb iocb;
	struct iocb* iocbs = &iocb;

	io_prep_pread(&iocb, m_fd, pBuffer, bytesToRead, offset);
	io_submit(m_aio_context, 1, &iocbs);
}
Пример #11
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;
}
Пример #12
0
int file_aio_read(int fd, void *start, int size, long long offset)
{
	struct iocb *cb = malloc(sizeof(struct iocb)); /* remaind to free */
	if(!cb) 
	{
		printf("file_aio_write %s\n", strerror(errno));
		return -1;
	}

	io_prep_pread(cb, fd, start, size, offset);
	io_set_callback(cb, read_done);

	return io_submit(*aio_queue, 1, &cb);
}
Пример #13
0
void random_io(int fd, off_t ionum, int access_size, int num_requests)
{
  // (1) io_context_tの初期化
  io_context_t ctx;
  memset(&ctx, 0, sizeof(io_context_t));
  int r = io_setup(num_requests, &ctx);
  assert(r == 0);

  // (2) iocbs(I/O要求)の構築
  struct iocb **iocbs = new struct iocb*[num_requests];
  char **bufs = new char*[num_requests];
  for (int i = 0; i < num_requests; i++) {
    iocbs[i] = new struct iocb();
    posix_memalign((void **)&bufs[i], 512, access_size);

    off_t block_number = rand() % ionum;
    io_prep_pread(iocbs[i], fd, bufs[i], access_size, block_number * access_size);
    io_set_callback(iocbs[i], read_done);
  }

  // (3) I/O要求を投げる
  r = io_submit(ctx, num_requests, iocbs);
  assert(r == num_requests);

  // (4) 完了したI/O要求を待ち、終わったものについてはcallbackを呼び出す
  int cnt = 0;
  while (true) {
    struct io_event events[32];
    int n = io_getevents(ctx, 1, 32, events, NULL);
    if (n > 0)
      cnt += n;

    for (int i = 0; i < n; i++) {
      struct io_event *ev = events + i;
      io_callback_t callback = (io_callback_t)ev->data;
      struct iocb *iocb = ev->obj;
      callback(ctx, iocb, ev->res, ev->res2);
    }

    if (n == 0 || cnt == num_requests)
      break;
  }

  for (int i = 0; i < num_requests; i++) {
    delete iocbs[i];
    free(bufs[i]);
  }
  delete[] iocbs;
  delete[] bufs;
}
Пример #14
0
aiom_cb_t *
mb_aiom_prep_pread   (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_pread(&aiom_cb->iocb, fd, buf, count, offset);
    GETTIMEOFDAY(&aiom_cb->submit_time);

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

    return aiom_cb;
}
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
}
Пример #16
0
static void aiobe_pread(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_pread(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);
}
Пример #17
0
int
aioperf_libaio_read(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;
    }

    if (!(io_task->buf = (char *)aioperf_memory_memalign(512, 
        conf_info->buf_size))) {
        printf("memory memalign error\n");
    }
    

    io_task->data = libaio_req;

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

    io_prep_pread(libaio_req, io_task->fd, io_task->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;
}
Пример #18
0
Файл: io_aio.c Проект: 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;
}
JNIEXPORT void JNICALL Java_org_apache_activemq_artemis_jlibaio_LibaioContext_submitRead
  (JNIEnv * env, jclass clazz, jint fileHandle, jobject contextPointer, jlong position, jint size, jobject bufferRead, jobject callback) {
    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;
    }

    io_prep_pread(iocb, fileHandle, getBuffer(env, bufferRead), (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);
}
Пример #20
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);
      }
}
Пример #21
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);
}
Пример #22
0
static int
check_state(int fd, struct directio_context *ct, int sync, int timeout_secs)
{
	struct timespec	timeout = { .tv_nsec = 5 };
	struct io_event event;
	struct stat	sb;
	int		rc = PATH_UNCHECKED;
	long		r;

	if (fstat(fd, &sb) == 0) {
		LOG(4, "called for %x", (unsigned) sb.st_rdev);
	}
	if (sync > 0) {
		LOG(4, "called in synchronous mode");
		timeout.tv_sec  = timeout_secs;
		timeout.tv_nsec = 0;
	}

	if (!ct->running) {
		struct iocb *ios[1] = { &ct->io };

		LOG(3, "starting new request");
		memset(&ct->io, 0, sizeof(struct iocb));
		io_prep_pread(&ct->io, fd, ct->ptr, ct->blksize, 0);
		if (io_submit(ct->ioctx, 1, ios) != 1) {
			LOG(3, "io_submit error %i", errno);
			return PATH_UNCHECKED;
		}
	}
	ct->running++;

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

	if (r < 0 ) {
		LOG(3, "async io getevents returned %li (errno=%s)", r,
		    strerror(errno));
		ct->running = 0;
		rc = PATH_UNCHECKED;
	} else if (r < 1L) {
		if (ct->running > timeout_secs || sync) {
			struct iocb *ios[1] = { &ct->io };

			LOG(3, "abort check on timeout");
			r = io_cancel(ct->ioctx, ios[0], &event);
			/*
			 * Only reset ct->running if we really
			 * could abort the pending I/O
			 */
			if (r)
				LOG(3, "io_cancel error %i", errno);
			else
				ct->running = 0;
			rc = PATH_DOWN;
		} else {
			LOG(3, "async io pending");
			rc = PATH_PENDING;
		}
	} else {
		LOG(3, "io finished %lu/%lu", event.res, event.res2);
		ct->running = 0;
		rc = (event.res == ct->blksize) ? PATH_UP : PATH_DOWN;
	}

	return rc;
}

int libcheck_check (struct checker * c)
{
	int ret;
	struct directio_context * ct = (struct directio_context *)c->context;

	if (!ct)
		return PATH_UNCHECKED;

	ret = check_state(c->fd, ct, c->sync, c->timeout);

	switch (ret)
	{
	case PATH_UNCHECKED:
		MSG(c, MSG_DIRECTIO_UNKNOWN);
		break;
	case PATH_DOWN:
		MSG(c, MSG_DIRECTIO_DOWN);
		break;
	case PATH_UP:
		MSG(c, MSG_DIRECTIO_UP);
		break;
	case PATH_PENDING:
		MSG(c, MSG_DIRECTIO_PENDING);
		break;
	default:
		break;
	}
	return ret;
}
Пример #23
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;
}
Пример #24
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();
}
Пример #25
0
int main(int argc, char *argv[])
{
  int efd, fd, epfd;
  io_context_t ctx;
  struct timespec tms;
  struct io_event events[NUM_EVENTS];
  struct custom_iocb iocbs[NUM_EVENTS];
  struct iocb *iocbps[NUM_EVENTS];
  struct custom_iocb *iocbp;
  int i, j, r;
  void *buf;
  struct epoll_event epevent;

  // TODO:Used to record event?
  efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
  if (efd == -1) {
    perror("eventfd");
    return 2;
  }

  // File Open Operation
  fd = open(TEST_FILE, O_RDWR | O_CREAT | O_DIRECT, 0644);
  if (fd == -1) {
    perror("open");
    return 3;
  }
  // Init the file size first.
  ftruncate(fd, TEST_FILE_SIZE);
    
  
  ctx = 0;
  //  1. io_setup: Create an asynchronous I/O context capable of receiving
  //     at least nr_events.
  //  2. 8192: It could receive at least 8192 events??
  if (io_setup(8192, &ctx)) {
    perror("io_setup");
    return 4;
  }

  // Allocate RD_WR_SIZE bytes, and places the address of the allocated memory
  // in *buf. The address of the allocated memory will be a multiple of ALIGN_SIZE,
  if (posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE)) {
    perror("posix_memalign");
    return 5;
  }
  printf("buf: %p\n", buf);

  
  for (i = 0, iocbp = iocbs; i < NUM_EVENTS; ++i, ++iocbp) {
    iocbps[i] = &iocbp->iocb;
    
    // An inline convenience function designed to facilitate the initialization of the iocb for
    // an asynchronous read operation. When the function finished, the iocbp->iocb will be:
    //   iocb->u.c.nbytes= RD_WR_SIZE
    //   iocb->aio_fildes = fd
    //   iocb->u.c.buf = buf
    //   iocb->u.c.offset = i * RD_WR_SIZE
    io_prep_pread(&iocbp->iocb, fd, buf, RD_WR_SIZE, i * RD_WR_SIZE);
    io_set_eventfd(&iocbp->iocb, efd);

    // Set up io completion callback function.
    io_set_callback(&iocbp->iocb, aio_callback);
    iocbp->nth_request = i + 1;
  }

  // Submit asynchronous I/O blocks for processing. It will queue NUM_EVENTS
  // I/O request blocks for processing in the AIO context ctx.
  //  iocbps is an array of nr AIO control blocks, which will be submitted to context ctx.
  if (io_submit(ctx, NUM_EVENTS, iocbps) != NUM_EVENTS) {
    perror("io_submit");
    return 6;
  }

  // Open an epoll file descriptor ( epoll is I/O event notification facility).
  // It will returns a file descriptor referring to the new epoll instance.
  epfd = epoll_create(1);
  if (epfd == -1) {
    perror("epoll_create");
    return 7;
  }

  epevent.events = EPOLLIN | EPOLLET;
  epevent.data.ptr = NULL;
  // epoll_ctl: Control interface for an epoll descriptor.
  //      EPOLL_CTL_ADD:  the operation that will be performanced
  //      efd: The target file descriptor that the operation will be performed for.
  //      epevent: describle the object linked to the fle descriptor efd.
  if (epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent)) {
    perror("epoll_ctl");
    return 8;
  }

  i = 0;
  while (i < NUM_EVENTS) {
    uint64_t finished_aio;

    // epoll_wait: wait for an I/O event on an epoll file descriptor
    //   epfd: the file descriptor that the epoll instance refer to.
    //   epevent: points to the events that will be available for the caller.
    //   1: at most 1  are returned by the function
    //   -1: specifies the minimum number of milliseconds that epoll_wait() will block.
    //       -1 causes epoll_wait to block indefinitely.
    if (epoll_wait(epfd, &epevent, 1, -1) != 1) {
      perror("epoll_wait");
      return 9;
    }

    if (read(efd, &finished_aio, sizeof(finished_aio)) != sizeof(finished_aio)) {
      perror("read");
      return 10;
    }

    printf("finished io number: %"PRIu64"\n", finished_aio);
    
    while (finished_aio > 0) {
      tms.tv_sec = 0;
      tms.tv_nsec = 0;
      // read asynchronous I/O events from the completion queue.
      r = io_getevents(ctx, 1, NUM_EVENTS, events, &tms);
      if (r > 0) {
	for (j = 0; j < r; ++j) {
	  ((io_callback_t)(events[j].data))(ctx, events[j].obj, events[j].res, events[j].res2);
	}
	i += r;
	finished_aio -= r;
      }
    }
  }
    
  close(epfd);
  free(buf);

  // destroy an asynchronous I/O context
  io_destroy(ctx);
  close(fd);
  close(efd);
  remove(TEST_FILE);

  return 0;
}
Пример #26
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);
}
Пример #27
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;
  
}
Пример #28
0
static void *aio_out_thread (void *param)
{
	char		*name = (char *) param;
	int		status;
	io_context_t	ctx = 0;
	struct iocb	*queue, *iocb;
	unsigned	i;

	status = sink_open (name);
	if (status < 0)
		return 0;
	sink_fd = status;
	pthread_cleanup_push (close_fd, &sink_fd);

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

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

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

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

		/* data can be processed in out_complete() */
		io_prep_pread (iocb, sink_fd, buf, iosize, 0);
		io_set_callback (iocb, out_complete);
		iocb->key = USB_DIR_OUT;

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

	status = io_run (ctx, &aio_out_pending);
	if (status < 0)
		perror ("aio_out_thread, io_run");

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

	return 0;
}
Пример #29
0
void AsyncIOOp::pread(int fd, void* buf, size_t size, off_t start) {
  init();
  io_prep_pread(&iocb_, fd, buf, size, start);
}
Пример #30
0
int main(int argc, char *argv[])
{
    // 每次读入32K字节
    const int buffer_size = 0x8000;

    // 最大事件数 32
    const int nr_events   = 32;
    int rt;

    io_context_t ctx ={0};

    // 初使化 io_context_t
    rt = io_setup(nr_events, &ctx);
    if ( rt != 0 )
        perror("io_setup error");

    // 依次读取参数作为文件名加入提交到ctx
    int pagesize = sysconf(_SC_PAGESIZE);
    int i = 1;
    for ( i=1; i<argc; ++i) {
        struct iocb *cb = (struct iocb*)malloc(sizeof(struct iocb));
        void *buffer;
        // 要使用O_DIRECT, 必须要对齐
        posix_memalign(&buffer, pagesize, buffer_size);
        io_prep_pread(cb, open(argv[i], O_RDONLY | O_DIRECT), buffer, buffer_size, 0);
        rt = io_submit(ctx, 1, &cb);
        if (rt < 0)
            perror("io_submit ");;
    }

    printf("io_prep_pread over \n");
    struct io_event events[nr_events];
    struct iocb     *cbs[nr_events];

    int remain = argc - 1;
    int n      = 0;

    // 接收数据最小返回的请求数为1,最大为nr_events
    while (remain && (n = io_getevents(ctx, 1, nr_events, events, 0))) {
        int nr_cbs = 0;
        int i = 0 ;
        for (i=0; i<n; ++i) {
            struct io_event event = events[i];
            struct iocb     *cb    = event.obj;
            // event.res为unsigned
            //printf("%d receive %d bytes\n", cb->aio_fildes, event.res);
            if (event.res > buffer_size) {
                printf("%s\n", strerror(-event.res));
            }
            if (event.res != buffer_size || event.res2 != 0) {
                --remain;
                printf("if %s",cb->u.c.buf);
                // 释放buffer, fd 与 cb
                free(cb->u.c.buf);
                close(cb->aio_fildes);
                free(cb);
            } else {
                printf("else%s",cb->u.c.buf);
                // 更新cb的offset
                cb->u.c.offset += event.res;
                cbs[nr_cbs++] = cb;
            }
        }

        if (nr_cbs) {
            // 继续接收数据
            io_submit(ctx, nr_cbs, cbs);
        }
    }
    return 0;
}