Merge pull request #11554 from mslovy/wip-fix-fiemap

os/FileStore: fix fiemap issue in xfs when #extents > 1364 

Reviewed-by: Sage Weil <sage@redhat.com>
This commit is contained in:
Sage Weil 2016-11-03 13:19:37 -05:00 committed by GitHub
commit ab0b6dffed
2 changed files with 22 additions and 11 deletions

View File

@ -3170,11 +3170,13 @@ int FileStore::read(
int FileStore::_do_fiemap(int fd, uint64_t offset, size_t len,
map<uint64_t, uint64_t> *m)
{
struct fiemap *fiemap = NULL;
uint64_t i;
struct fiemap_extent *extent = NULL;
struct fiemap_extent *last = NULL;
struct fiemap *fiemap = NULL;
int r = 0;
more:
r = backend->do_fiemap(fd, offset, len, &fiemap);
if (r < 0)
return r;
@ -3214,9 +3216,15 @@ int FileStore::_do_fiemap(int fd, uint64_t offset, size_t len,
extent->fe_length = offset + len - extent->fe_logical;
(*m)[extent->fe_logical] = extent->fe_length;
i++;
extent++;
last = extent++;
}
free(fiemap);
if (!(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;
goto more;
}
return r;
}

View File

@ -295,6 +295,8 @@ TEST_P(StoreTest, FiemapEmpty) {
TEST_P(StoreTest, FiemapHoles) {
ObjectStore::Sequencer osr("test");
const uint64_t MAX_EXTENTS = 4000;
const uint64_t SKIP_STEP = 65536;
coll_t cid;
int r = 0;
ghobject_t oid(hobject_t(sobject_t("fiemap_object", CEPH_NOSNAP)));
@ -304,27 +306,28 @@ TEST_P(StoreTest, FiemapHoles) {
ObjectStore::Transaction t;
t.create_collection(cid, 0);
t.touch(cid, oid);
t.write(cid, oid, 0, 3, bl);
t.write(cid, oid, 1048576, 3, bl);
t.write(cid, oid, 4194304, 3, bl);
for (uint64_t i = 0; i < MAX_EXTENTS; i++)
t.write(cid, oid, SKIP_STEP * i, 3, bl);
r = apply_transaction(store, &osr, std::move(t));
ASSERT_EQ(r, 0);
}
{
bufferlist bl;
store->fiemap(cid, oid, 0, 4194307, bl);
store->fiemap(cid, oid, 0, SKIP_STEP * (MAX_EXTENTS - 1) + 3, bl);
map<uint64_t,uint64_t> m, e;
bufferlist::iterator p = bl.begin();
::decode(m, p);
cout << " got " << m << std::endl;
ASSERT_TRUE(!m.empty());
ASSERT_GE(m[0], 3u);
bool extents_exist = true;
if (m.size() == MAX_EXTENTS) {
for (uint64_t i = 0; i < MAX_EXTENTS; i++)
extents_exist = extents_exist && m.count(SKIP_STEP*i);
}
ASSERT_TRUE((m.size() == 1 &&
m[0] > 4194304u) ||
(m.size() == 3 &&
m.count(0) &&
m.count(1048576) &&
m.count(4194304)));
m[0] > SKIP_STEP * (MAX_EXTENTS - 1)) ||
(m.size() == MAX_EXTENTS && extents_exist));
}
{
ObjectStore::Transaction t;