Merge "Fix reading extents file if not start from the beginning of a extent."
diff --git a/extents_file.cc b/extents_file.cc
index 2d2ea83..01d31a6 100644
--- a/extents_file.cc
+++ b/extents_file.cc
@@ -86,14 +86,15 @@
   AdvancePos(0);
   while (count > 0 && curr_ex_idx_ < extents_.size()) {
     const ex_t& ex = extents_[curr_ex_idx_];
-    size_t chunk_size = std::min(static_cast<uint64_t>(count), ex.len);
+    off_t curr_ex_off = curr_pos_ - acc_len_[curr_ex_idx_];
+    size_t chunk_size =
+        std::min(static_cast<uint64_t>(count), ex.len - curr_ex_off);
     size_t chunk_processed = 0;
     if (ex.off < 0) {
       chunk_processed = chunk_size;
     } else {
-      uint64_t file_pos = ex.off + (curr_pos_ - acc_len_[curr_ex_idx_]);
-      if (!file_->Seek(file_pos) ||
-          !((file_.get()->*io_op))(buf, chunk_size, &chunk_processed)) {
+      if (!file_->Seek(ex.off + curr_ex_off) ||
+          !(file_.get()->*io_op)(buf, chunk_size, &chunk_processed)) {
         processed += chunk_processed;
         result = processed > 0;
         break;
diff --git a/extents_file_unittest.cc b/extents_file_unittest.cc
index fa9ed22..73cedb2 100644
--- a/extents_file_unittest.cc
+++ b/extents_file_unittest.cc
@@ -128,6 +128,32 @@
   EXPECT_EQ(15U, bytes_read);
 }
 
+TEST_F(ExtentsFileTest, MultiReadAcrossAllExtents) {
+  ExtentsFile file(std::move(mock_file_ptr_),
+                   {ex_t{10, 5}, ex_t{20, 7}, {27, 3}});
+  InSequence s;
+  char* buf = reinterpret_cast<char*>(0x1234);
+
+  EXPECT_CALL(*mock_file_, Seek(10)).WillOnce(Return(true));
+  EXPECT_CALL(*mock_file_, Read(buf, 2, _)).WillOnce(SucceedIO());
+  EXPECT_CALL(*mock_file_, Seek(12)).WillOnce(Return(true));
+  EXPECT_CALL(*mock_file_, Read(buf, 3, _)).WillOnce(SucceedIO());
+  EXPECT_CALL(*mock_file_, Seek(20)).WillOnce(Return(true));
+  EXPECT_CALL(*mock_file_, Read(buf + 3, 5, _)).WillOnce(SucceedIO());
+  EXPECT_CALL(*mock_file_, Seek(25)).WillOnce(Return(true));
+  EXPECT_CALL(*mock_file_, Read(buf, 2, _)).WillOnce(SucceedIO());
+  EXPECT_CALL(*mock_file_, Seek(27)).WillOnce(Return(true));
+  EXPECT_CALL(*mock_file_, Read(buf + 2, 3, _)).WillOnce(SucceedIO());
+
+  size_t bytes_read = 0;
+  EXPECT_TRUE(file.Read(buf, 2, &bytes_read));
+  EXPECT_EQ(2U, bytes_read);
+  EXPECT_TRUE(file.Read(buf, 8, &bytes_read));
+  EXPECT_EQ(8U, bytes_read);
+  EXPECT_TRUE(file.Read(buf, 100, &bytes_read));
+  EXPECT_EQ(5U, bytes_read);
+}
+
 TEST_F(ExtentsFileTest, ReadSmallChunks) {
   ExtentsFile file(std::move(mock_file_ptr_), {ex_t{10, 1}, ex_t{20, 10}});
   InSequence s;