worker_thread (void *indexp)
{
  uintptr_t index = (uintptr_t) indexp;
  uint64_t offset, count;
  extent_list exts = empty_vector;

  while (get_next_offset (&offset, &count)) {
    size_t i;

    assert (0 < count && count <= THREAD_WORK_SIZE);
    if (extents)
      src->ops->get_extents (src, index, offset, count, &exts);
    else
      default_get_extents (src, index, offset, count, &exts);

    for (i = 0; i < exts.len; ++i) {
      struct command *command;
      struct buffer *buffer;
      char *data;
      size_t len;

      if (exts.ptr[i].zero) {
        /* The source is zero so we can proceed directly to skipping,
         * fast zeroing, or writing zeroes at the destination.
         */
        command = calloc (1, sizeof *command);
        if (command == NULL) {
          perror ("malloc");
          exit (EXIT_FAILURE);
        }
        command->offset = exts.ptr[i].offset;
        command->slice.len = exts.ptr[i].length;
        command->slice.base = 0;
        command->index = index;
        fill_dst_range_with_zeroes (command);
      }

      else /* data */ {
        /* As the extent might be larger than permitted for a single
         * command, we may have to split this into multiple read
         * requests.
         */
        while (exts.ptr[i].length > 0) {
          len = exts.ptr[i].length;
          if (len > request_size)
            len = request_size;
          data = malloc (len);
          if (data == NULL) {
            perror ("malloc");
            exit (EXIT_FAILURE);
          }
          buffer = calloc (1, sizeof *buffer);
          if (buffer == NULL) {
            perror ("malloc");
            exit (EXIT_FAILURE);
          }
          buffer->data = data;
          buffer->refs = 1;
          command = calloc (1, sizeof *command);
          if (command == NULL) {
            perror ("malloc");
            exit (EXIT_FAILURE);
          }
          command->offset = exts.ptr[i].offset;
          command->slice.len = len;
          command->slice.base = 0;
          command->slice.buffer = buffer;
          command->index = index;

          wait_for_request_slots (index);

          /* Begin the asynch read operation. */
          src->ops->asynch_read (src, command,
                                 (nbd_completion_callback) {
                                   .callback = finished_read,
                                   .user_data = command,
                                 });

          exts.ptr[i].offset += len;
          exts.ptr[i].length -= len;
        }
      }

      offset += count;
      count = 0;
    } /* for extents */
  }

  /* Wait for in flight NBD requests to finish. */
  while (in_flight (index) > 0)
    poll_both_ends (index);

  free (exts.ptr);
  return NULL;
}
worker_thread (void *indexp)
{
  uintptr_t index = (uintptr_t) indexp;
  uint64_t offset, count;
  extent_list exts = empty_vector;

  while (get_next_offset (&offset, &count)) {
    size_t i;

    assert (0 < count && count <= THREAD_WORK_SIZE);
    if (extents)
      src->ops->get_extents (src, index, offset, count, &exts);
    else
      default_get_extents (src, index, offset, count, &exts);

    for (i = 0; i < exts.len; ++i) {
      struct command *command;
      struct buffer *buffer;
      char *data;
      size_t len;

      if (exts.ptr[i].zero) {
         
        command = calloc (1, sizeof *command);
        if (command == NULL) {
          perror ("malloc");
          exit (EXIT_FAILURE);
        }
        command->offset = exts.ptr[i].offset;
        command->slice.len = exts.ptr[i].length;
        command->slice.base = 0;
        command->index = index;
        fill_dst_range_with_zeroes (command);
      }

      else   {
         
        while (exts.ptr[i].length > 0) {
          len = exts.ptr[i].length;
          if (len > request_size)
            len = request_size;
          data = malloc (len);
          if (data == NULL) {
            perror ("malloc");
            exit (EXIT_FAILURE);
          }
          buffer = calloc (1, sizeof *buffer);
          if (buffer == NULL) {
            perror ("malloc");
            exit (EXIT_FAILURE);
          }
          buffer->data = data;
          buffer->refs = 1;
          command = calloc (1, sizeof *command);
          if (command == NULL) {
            perror ("malloc");
            exit (EXIT_FAILURE);
          }
          command->offset = exts.ptr[i].offset;
          command->slice.len = len;
          command->slice.base = 0;
          command->slice.buffer = buffer;
          command->index = index;

          wait_for_request_slots (index);

           
          src->ops->asynch_read (src, command,
                                 (nbd_completion_callback) {
                                   .callback = finished_read,
                                   .user_data = command,
                                 });

          exts.ptr[i].offset += len;
          exts.ptr[i].length -= len;
        }
      }

      offset += count;
      count = 0;
    }  
  }

   
  while (in_flight (index) > 0)
    poll_both_ends (index);

  free (exts.ptr);
  return NULL;
}