Example #1
0
/**
 * send one request to device, it validate there is no problem with the
 *
 * @header IN request to do
 *         OUT last request done
 * @return EXA_RDEV_REQUEST_END_OK       new request submitted successfully and header
 *                                       contains an old request succesfully done
 *         EXA_RDEV_REQUEST_END_ERROR    new request submitted successfully
 *                                       and header contains an old request that fail
 *         RDEV_REQUEST_NOT_ENOUGH_FREE_REQ not enough resources to submit a new request
 */
static int exa_td_process_one_request(header_t **header,
                                      device_t *disk_device)
{
  void * buffer;
  int sector_nb;
  uint64_t sector;
  int retval;
  header_t *req_header = *header;

  /* FIXME this is a ugly hack to prevent compiler to complain about
   * uninitialized variable. Actually, this is because the request type
   * itself is f***ed up (no type and the funky use os bit masks...)
   * Please remove this whe reworking header_t content... */
  rdev_op_t op = (rdev_op_t)-1;

  /* submit this new request to exa_rdev and so to the disk driver */
  sector_nb = req_header->io.desc.sector_nb;

  buffer = req_header->io.buf;

  sector = req_header->io.desc.sector;

  EXA_ASSERT(NBD_REQ_TYPE_IS_VALID(req_header->io.desc.request_type));
  switch (req_header->io.desc.request_type)
  {
  case NBD_REQ_TYPE_READ:
      EXA_ASSERT(!req_header->io.desc.flush_cache);
      op = RDEV_OP_READ;
      break;
  case NBD_REQ_TYPE_WRITE:
      if (req_header->io.desc.flush_cache)
          op = RDEV_OP_WRITE_BARRIER;
      else
          op = RDEV_OP_WRITE;
      break;
  }

  /* Be carefull the 'header' pointer can be modified */
  retval = exa_rdev_make_request_new(op, (void *)header,
                                     sector + RDEV_RESERVED_AREA_IN_SECTORS,
                                     sector_nb, buffer, disk_device->handle);

  if (retval == RDEV_REQUEST_NOT_ENOUGH_FREE_REQ)
    return RDEV_REQUEST_NOT_ENOUGH_FREE_REQ;

  if (*header != NULL)
      (*header)->io.desc.result = retval == RDEV_REQUEST_END_OK ? 0 : -EIO;

  if (retval < 0)
    return RDEV_REQUEST_END_ERROR;

  return retval;
}
Example #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;
	}
    }
}