From b52bfe6b443f0ff88c8614441752102058063699 Mon Sep 17 00:00:00 2001 From: Ning Yao Date: Thu, 6 Apr 2017 11:12:04 +0000 Subject: [PATCH] os/filestore: fix infinit loops in fiemap() since fiemap can get extents based on offset --> len but we should consider last extents is retrieved when len == 0 even though it is not last fiemap extents Signed-off-by: Ning Yao (cherry picked from commit 36f6b668a8910d76847674086cbc86910c78faee) --- src/os/filestore/FileStore.cc | 13 +++++-------- src/test/objectstore/store_test.cc | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/os/filestore/FileStore.cc b/src/os/filestore/FileStore.cc index c47b0d0d2eae..95f48cdf4960 100644 --- a/src/os/filestore/FileStore.cc +++ b/src/os/filestore/FileStore.cc @@ -3102,17 +3102,14 @@ int FileStore::_do_fiemap(int fd, uint64_t offset, size_t len, i++; last = extent++; } - const bool is_last = last->fe_flags & FIEMAP_EXTENT_LAST; + uint64_t xoffset = last->fe_logical + last->fe_length - offset; + offset = last->fe_logical + last->fe_length; + len -= xoffset; + const bool is_last = (last->fe_flags & FIEMAP_EXTENT_LAST) || (len == 0); + free(fiemap); if (!is_last) { - uint64_t xoffset = last->fe_logical + last->fe_length - offset; - offset = last->fe_logical + last->fe_length; - len -= xoffset; - free(fiemap); /* fix clang warn: use-after-free */ goto more; } - else { - free(fiemap); - } return r; } diff --git a/src/test/objectstore/store_test.cc b/src/test/objectstore/store_test.cc index 5ab011ad17d8..4cada7e2e435 100644 --- a/src/test/objectstore/store_test.cc +++ b/src/test/objectstore/store_test.cc @@ -279,6 +279,7 @@ TEST_P(StoreTest, FiemapHoles) { ASSERT_EQ(r, 0); } { + //fiemap test from 0 to SKIP_STEP * (MAX_EXTENTS - 1) + 3 bufferlist bl; store->fiemap(cid, oid, 0, SKIP_STEP * (MAX_EXTENTS - 1) + 3, bl); map m, e; @@ -295,6 +296,26 @@ TEST_P(StoreTest, FiemapHoles) { ASSERT_TRUE((m.size() == 1 && m[0] > SKIP_STEP * (MAX_EXTENTS - 1)) || (m.size() == MAX_EXTENTS && extents_exist)); + + // fiemap test from SKIP_STEP to SKIP_STEP * (MAX_EXTENTS - 2) + 3 + // reset bufferlist and map + bl.clear(); + m.clear(); + e.clear(); + store->fiemap(cid, oid, SKIP_STEP, SKIP_STEP * (MAX_EXTENTS - 2) + 3, bl); + p = bl.begin(); + ::decode(m, p); + cout << " got " << m << std::endl; + ASSERT_TRUE(!m.empty()); + ASSERT_GE(m[SKIP_STEP], 3u); + extents_exist = true; + if (m.size() == (MAX_EXTENTS - 2)) { + for (uint64_t i = 1; i < MAX_EXTENTS - 1; i++) + extents_exist = extents_exist && m.count(SKIP_STEP*i); + } + ASSERT_TRUE((m.size() == 1 && + m[SKIP_STEP] > SKIP_STEP * (MAX_EXTENTS - 2)) || + (m.size() == (MAX_EXTENTS - 1) && extents_exist)); } { ObjectStore::Transaction t;