};
+/* for more info on scatterlocks, see comments by Locker::scatter_writebehind */
+
void CInode::decode_lock_state(int type, bufferlist& bl)
{
bufferlist::iterator p = bl.begin();
* when we initially scatter a lock, we need to check if any of the dirfrags
* have out of date accounted_rstat/fragstat. if so, mark the lock stale.
*/
+/* for more info on scatterlocks, see comments by Locker::scatter_writebehind */
void CInode::start_scatter(ScatterLock *lock)
{
dout(10) << "start_scatter " << *lock << " on " << *this << dendl;
* because the frag is auth and frozen, or that the replica couldn't for the same
* reason. hopefully it will get updated the next time the lock cycles.
*/
+/* for more info on scatterlocks, see comments by Locker::scatter_writebehind */
void CInode::finish_scatter_gather_update(int type)
{
dout(10) << "finish_scatter_gather_update " << type << " on " << *this << dendl;
// ==========================================================================
// scatter lock
+/*
+
+Some notes on scatterlocks.
+
+ - The scatter/gather is driven by the inode lock. The scatter always
+ brings in the latest metadata from the fragments.
+
+ - When in a scattered/MIX state, fragments are only allowed to
+ update/be written to if the accounted stat matches the inode's
+ current version.
+
+ - That means, on gather, we _only_ assimilate diffs for frag metadata
+ that match the current version, because those are the only ones
+ written during this scatter/gather cycle. (Others didn't permit
+ it.) We increment the version and journal this to disk.
+
+ - When possible, we also simultaneously update our local frag
+ accounted stats to match.
+
+ - On scatter, the new inode info is broadcast to frags, both local
+ and remote. If possible (auth and !frozen), the dirfrag auth
+ should update the accounted state (if it isn't already up to date).
+ Note that this may occur on both the local inode auth node and
+ inode replicas, so there are two potential paths. If it is NOT
+ possible, they need to mark_stale to prevent any possible writes.
+
+ - A scatter can be to MIX (potentially writeable) or to SYNC (read
+ only). Both are opportunities to update the frag accounted stats,
+ even though only the MIX case is affected by a stale dirfrag.
+
+ - Because many scatter/gather cycles can potentially go by without a
+ frag being able to update its accounted stats (due to being frozen
+ by exports/refragments in progress), the frag may have (even very)
+ old stat versions. That's fine. It is always stale (MIX_STALE
+ instead of MIX) as a result, and then ignored by the gather.
+
+*/
+
void Locker::scatter_writebehind(ScatterLock *lock)
{
CInode *in = (CInode*)lock->get_parent();