Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os/ObjectStore: properly clear object map when replaying OP_REMOVE #11388

Merged
merged 2 commits into from Oct 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/os/filestore/DBObjectMap.cc
Expand Up @@ -902,10 +902,10 @@ int DBObjectMap::clone(const ghobject_t &oid,
{
Header destination = lookup_map_header(*ltarget, target);
if (destination) {
remove_map_header(*ltarget, target, destination, t);
if (check_spos(target, destination, spos))
return 0;
destination->num_children--;
remove_map_header(*ltarget, target, destination, t);
_clear(destination, t);
}
}
Expand Down
69 changes: 43 additions & 26 deletions src/os/filestore/FileStore.cc
Expand Up @@ -472,13 +472,7 @@ int FileStore::lfn_unlink(const coll_t& cid, const ghobject_t& o,
}

if (!force_clear_omap) {
if (hardlink == 0) {
if (!m_disable_wbthrottle) {
wbthrottle.clear_object(o); // should be only non-cache ref
}
fdcache.clear(o);
return 0;
} else if (hardlink == 1) {
if (hardlink == 0 || hardlink == 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we always clear omap first, and then unlink the object file. so, if the hardlink is 1 here, we should have cleared the omap already, am i right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? we get object file's hardlink count before clearing omap and unlinking object file. hardlink == 1 is the most common case

Copy link
Member

@liewegas liewegas Oct 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So to clarify the situation is

  • clear omap
  • unlink
  • unlink persists to disk, but omap does not
  • crash
  • replay sees hardlink 0 and doesn't clear omap

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

force_clear_omap = true;
}
}
Expand All @@ -505,6 +499,12 @@ int FileStore::lfn_unlink(const coll_t& cid, const ghobject_t& o,
if (!backend->can_checkpoint())
object_map->sync(&o, &spos);
}
if (hardlink == 0) {
if (!m_disable_wbthrottle) {
wbthrottle.clear_object(o); // should be only non-cache ref
}
return 0;
}
}
r = index->unlink(o);
if (r < 0) {
Expand Down Expand Up @@ -2343,10 +2343,12 @@ void FileStore::_set_replay_guard(int fd,
// first make sure the previous operation commits
::fsync(fd);

// sync object_map too. even if this object has a header or keys,
// it have had them in the past and then removed them, so always
// sync.
object_map->sync(hoid, &spos);
if (!in_progress) {
// sync object_map too. even if this object has a header or keys,
// it have had them in the past and then removed them, so always
// sync.
object_map->sync(hoid, &spos);
}

_inject_failure();

Expand Down Expand Up @@ -2384,7 +2386,8 @@ void FileStore::_close_replay_guard(const coll_t& cid,
VOID_TEMP_FAILURE_RETRY(::close(fd));
}

void FileStore::_close_replay_guard(int fd, const SequencerPosition& spos)
void FileStore::_close_replay_guard(int fd, const SequencerPosition& spos,
const ghobject_t *hoid)
{
if (backend->can_checkpoint())
return;
Expand All @@ -2393,6 +2396,11 @@ void FileStore::_close_replay_guard(int fd, const SequencerPosition& spos)

_inject_failure();

// sync object_map too. even if this object has a header or keys,
// it have had them in the past and then removed them, so always
// sync.
object_map->sync(hoid, &spos);

// then record that we are done with this operation
bufferlist v(40);
::encode(spos, v);
Expand Down Expand Up @@ -5158,18 +5166,30 @@ int FileStore::_collection_move_rename(const coll_t& oldcid, const ghobject_t& o
} else {
assert(0 == "ERROR: source must exist");
}
return 0;
}
if (dstcmp > 0) { // if dstcmp == 0 the guard already says "in-progress"
_set_replay_guard(**fd, spos, &o, true);
}

r = lfn_link(oldcid, c, oldoid, o);
if (replaying && !backend->can_checkpoint() &&
r == -EEXIST) // crashed between link() and set_replay_guard()
r = 0;
if (!replaying) {
return 0;
}
if (allow_enoent && dstcmp > 0) { // if dstcmp == 0, try_rename was started.
return 0;
}

_inject_failure();
r = 0; // don't know if object_map was cloned
} else {
if (dstcmp > 0) { // if dstcmp == 0 the guard already says "in-progress"
_set_replay_guard(**fd, spos, &o, true);
}

r = lfn_link(oldcid, c, oldoid, o);
if (replaying && !backend->can_checkpoint() &&
r == -EEXIST) // crashed between link() and set_replay_guard()
r = 0;

lfn_close(fd);
fd = FDRef();

_inject_failure();
}

if (r == 0) {
// the name changed; link the omap content
Expand All @@ -5180,9 +5200,6 @@ int FileStore::_collection_move_rename(const coll_t& oldcid, const ghobject_t& o

_inject_failure();

lfn_close(fd);
fd = FDRef();

if (r == 0)
r = lfn_unlink(oldcid, oldoid, spos, true);

Expand All @@ -5191,7 +5208,7 @@ int FileStore::_collection_move_rename(const coll_t& oldcid, const ghobject_t& o

// close guard on object so we don't do this again
if (r == 0) {
_close_replay_guard(**fd, spos);
_close_replay_guard(**fd, spos, &o);
lfn_close(fd);
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/os/filestore/FileStore.h
Expand Up @@ -497,7 +497,8 @@ class FileStore : public JournalingObjectStore,
const SequencerPosition &spos);

/// close a replay guard opened with in_progress=true
void _close_replay_guard(int fd, const SequencerPosition& spos);
void _close_replay_guard(int fd, const SequencerPosition& spos,
const ghobject_t *oid=0);
void _close_replay_guard(const coll_t& cid, const SequencerPosition& spos);

/**
Expand Down