Пример #1
0
/**
 * Wait for the completion of a request and acknowledges upper layer it was
 * done. This function is blocking in case there are actually pending IO. If
 * not, it immediatly returns RDEV_REQUEST_ALL_ENDED.
 *
 * @param disk_device  disk on which the request is.
 *
 * return RDEV_REQUEST_END_ERROR, RDEV_REQUEST_END_OK or RDEV_REQUEST_ALL_ENDED
 */
static int wait_and_complete_one_io(device_t *disk_device)
{
    header_t *req;
    int err = exa_rdev_wait_one_request((void *)&req, disk_device->handle);

    EXA_ASSERT(err == RDEV_REQUEST_ALL_ENDED || err == RDEV_REQUEST_END_ERROR
               || err == RDEV_REQUEST_END_OK);

    if (!means_finished(err))
        return err;

    req->io.desc.result = err == RDEV_REQUEST_END_OK ? 0 : -EIO;

    handle_completed_io(disk_device, req);

    return err;
}
Пример #2
0
static void async_op(rdev_op_t op, uint64_t offset, uint64_t size_in_bytes,
                     exa_rdev_handle_t *dev_req)
{
    int retval;
    void *nbd_private;
    char *buffer;
    uint64_t chunk_size;
    uint64_t size_in_sectors;
    bool quit = false;

    size_in_sectors = (size_in_bytes / SECTOR_SIZE) + 1;

    chunk_size = (size_in_bytes > EXA_RDEV_READ_WRITE_FRAGMENT) ?
	EXA_RDEV_READ_WRITE_FRAGMENT : size_in_bytes;
    chunk_size /= SECTOR_SIZE;
    if (chunk_size == 0)
	chunk_size = 1;

    /* Prepare buffer to do requests, exa_rdev requires it to be aligned */
    buffer = os_aligned_malloc(size_in_sectors * SECTOR_SIZE, PAGE_SIZE, NULL);
    memset(buffer, 0, size_in_sectors * SECTOR_SIZE);

    retval = RDEV_REQUEST_ALL_ENDED;

    while (!quit)
    {
	switch (retval)
	{
	case RDEV_REQUEST_ALL_ENDED:
	    if (size_in_sectors <= 0)
		quit = true;
	    /* fallthrough */
	case RDEV_REQUEST_NONE_ENDED:
	    if (size_in_sectors > 0)
	    {
		if (op == RDEV_OP_WRITE)
		    memset(buffer, 'E', size_in_bytes);
		else
		    memset(buffer, 0, chunk_size);

		nbd_private = buffer;

                /* Be carefull the 'nbd_private' pointer can be modified */
		retval = exa_rdev_make_request_new(op, &nbd_private, offset,
						   chunk_size, buffer, dev_req);
		if (retval == RDEV_REQUEST_NOT_ENOUGH_FREE_REQ)
		{
 		    fprintf(stderr, "Overflow of exa_rdev, try later\n");
		    /* retry */
		    break;
		}

		if (retval < 0)
		{
		    fprintf(stderr, "Error %d\n", retval);
		    retval = RDEV_REQUEST_END_ERROR;
		    break;
		}

		size_in_sectors -= chunk_size;
		if ((size_in_sectors > 0) && (size_in_sectors < chunk_size))
		    chunk_size = size_in_sectors;
		offset += (chunk_size * SECTOR_SIZE);
		buffer = (char *)buffer + (chunk_size * SECTOR_SIZE);
	    }
	    else
	    {
		retval = RDEV_REQUEST_NOT_ENOUGH_FREE_REQ;
	    }
	    break;

	case RDEV_REQUEST_NOT_ENOUGH_FREE_REQ:
	    buffer = NULL;
	    retval = exa_rdev_wait_one_request((void **)&buffer, dev_req);
	    break;

	case RDEV_REQUEST_END_OK:
	case RDEV_REQUEST_END_ERROR:
	    if (retval == RDEV_REQUEST_END_ERROR)
		fprintf(stderr, "Request ended with error\n");
	    retval = RDEV_REQUEST_NONE_ENDED;
	    break;
	}
    }
}