We were already checking that we _can_ wrlock before doing the rstat
projection (if we can't, we mark_dirty_rstat() on the inode), but we
weren't actually taking the wrlock to prevent lock state changes while
that happened.
This bug eventually manifested itself as a failed assertion at the
now familiar
mds/CInode.cc: In function 'virtual void CInode::decode_lock_state(int, ceph::bufferlist&)':
mds/CInode.cc:1364: FAILED assert(pf->rstat == rstat)
Signed-off-by: Sage Weil <sage@newdream.net>
<< ", marking dirty rstat on " << *cur << dendl;
cur->mark_dirty_rstat();
} else {
+ // if we don't hold a wrlock reference on this nestlock, take one,
+ // because we are about to write into the dirfrag fnode and that needs
+ // to commit before the lock can cycle.
+ if (mut->wrlocks.count(&parent->inode->nestlock) == 0) {
+ dout(10) << " taking wrlock on " << parent->inode->nestlock << " on " << *parent->inode << dendl;
+ mds->locker->wrlock_force(&parent->inode->nestlock, mut);
+ }
+
+ // now we can project the inode rstat diff the dirfrag
SnapRealm *prealm = parent->inode->find_snaprealm();
snapid_t follows = cfollows;