message: storage: optimize FileCacheEntry::read() for common case
  Optimize FileCacheEntry::read() for common case.
diff: @@ -335,11 +335,19 @@ impl BlobCache for FileCacheEntry {
  self.metrics.total.inc();
  self.workers.consume_prefetch_budget(buffers);
  - // TODO: Single bio optimization here? So we don't have to involve other management
  - // structures.
  + if iovec.bi_vec.len() == 0 {
  + Ok(0)
  + } else if iovec.bi_vec.len() == 1 {
  + let mut state = FileIoMergeState::new();
  + let mut cursor = MemSliceCursor::new(buffers);
  + let req = BlobIoRange::new(&iovec.bi_vec[0], 1);
  +
  + self.dispatch_one_range(&req, &mut cursor, &mut state)
  + } else {
  self.read_iter(&iovec.bi_vec, buffers)
  }
  }
  +}
  impl AsRawFd for FileCacheEntry {
  fn as_raw_fd(&self) -> RawFd {
  @@ -460,7 +468,22 @@ impl FileCacheEntry {
  let mut total_read: usize = 0;
  for req in requests {
  - debug!("A merged request {:?}", req);
  + total_read += self.dispatch_one_range(&req, &mut cursor, &mut state)?;
  + state.reset();
  + }
  +
  + Ok(total_read)
  + }
  +
  + fn dispatch_one_range(
  + &self,
  + req: &BlobIoRange,
  + cursor: &mut MemSliceCursor,
  + state: &mut FileIoMergeState,
  + ) -> Result<usize> {
  + let mut total_read: usize = 0;
  +
  + debug!("dispatch a blob io range {:?}", req);
  for (i, chunk) in req.chunks.iter().enumerate() {
  let is_ready = self
  .chunk_map
  @@ -521,13 +544,10 @@ impl FileCacheEntry {
  use RegionType::*;
  total_read += match r.r#type {
  - CacheFast => self.dispatch_cache_fast(&mut cursor, r)?,
  - CacheSlow => self.dispatch_cache_slow(&mut cursor, r)?,
  - Backend => self.dispatch_backend(&mut cursor, r)?,
  - }
  + CacheFast => self.dispatch_cache_fast(cursor, r)?,
  + CacheSlow => self.dispatch_cache_slow(cursor, r)?,
  + Backend => self.dispatch_backend(cursor, r)?,
  }
  -
  - state.reset();
  }
  Ok(total_read)
  