From 525e12bbc2aed72c53528d6bd7f993d5477e85ef Mon Sep 17 00:00:00 2001 From: Greg Farnum Date: Fri, 22 Feb 2013 15:04:34 -0800 Subject: mds: update CInode snapids (first & last) during replay A user reported on the mailing list that they were hitting the assert assert(in->first == p->dnfirst || (in->is_multiversion() && in->first > p->dnfirst)); in EMetablob::replay. It turned out that it was on an unlink operation (which moved the inode into a straydir), and the stray dentry had a first of 4 while the inode had a first of 2. Investigation revealed that we weren't updating "first" or "last" of the CInode for any CInodes that existed in cache before the replay! (Non-existent inodes had the correct values set from the p->dnfirst and p->dnlast on construction). To fix this, we modify EMetaBlob::fullbit::update_inode() so that, *if* old_inodes is non-empty, we set in->first as 1 past the last entry's "last" value. This is good because old_inodes will have been modified any time the inode was (assuming it was already multi-version). Signed-off-by: Greg Farnum --- src/mds/journal.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mds/journal.cc b/src/mds/journal.cc index 09072cef0d8..e19b5c5a179 100644 --- a/src/mds/journal.cc +++ b/src/mds/journal.cc @@ -516,6 +516,11 @@ void EMetaBlob::fullbit::update_inode(MDS *mds, CInode *in) in->symlink = symlink; } in->old_inodes = old_inodes; + if (!in->old_inodes.empty()) { + map::iterator p = in->old_inodes.end(); + --p; // get the actual last entry + in->first = p->first + 1; + } } // EMetaBlob::remotebit -- cgit v1.2.1