eden/fs/inodes/TreeInode.cpp
/**
 * Acquire the locks necessary for a rename operation.
 *
 * We acquire multiple locks here:
 *   A) Mountpoint rename lock
 *   B) Source directory contents_ lock
 *   C) Destination directory contents_ lock
 *   E) Destination child contents_ (assuming the destination name
 *      refers to an existing directory).
 *
 * This function ensures the locks are held with the proper ordering.
 * Since we hold the rename lock first, we can acquire multiple TreeInode
 * contents_ locks at once, but we must still ensure that we acquire locks on
 * ancestor TreeInode's before any of their descendants.
 */
Acquire the locks necessary for a rename operation.
We acquire multiple locks here:
A) Mountpoint rename lock
B) Source directory contents_ lock
C) Destination directory contents_ lock
E) Destination child contents_ (assuming the destination name
refers to an existing directory).

This function ensures the locks are held with the proper ordering.
Since we hold the rename lock first, we can acquire multiple TreeInode
contents_ locks at once, but we must still ensure that we acquire locks on
ancestor TreeInode's before any of their descendants.
Acquire the locks necessary for a rename operation . We acquire multiple locks here : A ) Mountpoint rename lock B ) Source directory contents_ lock C ) Destination directory contents_ lock E ) Destination child contents_ ( assuming the destination name refers to an existing directory ) . This function ensures the locks are held with the proper ordering . Since we hold the rename lock first we can acquire multiple TreeInode contents_ locks at once but we must still ensure that we acquire locks on ancestor TreeInode ' s before any of their descendants .
void TreeInode::TreeRenameLocks::acquireLocks(
    RenameLock&& renameLock,
    TreeInode* srcTree,
    TreeInode* destTree,
    PathComponentPiece destName) {
  renameLock_ = std::move(renameLock);
  if (srcTree == destTree) {
    srcContentsLock_ = srcTree->contents_.wlock();
    srcContents_ = &srcContentsLock_->entries;
    destContents_ = &srcContentsLock_->entries;
    lockDestChild(destName);
  } else if (isAncestor(renameLock_, srcTree, destTree)) {
    srcContentsLock_ = srcTree->contents_.wlock();
    srcContents_ = &srcContentsLock_->entries;
    destContentsLock_ = destTree->contents_.wlock();
    destContents_ = &destContentsLock_->entries;
    lockDestChild(destName);
  } else {
     It is not possible for srcTree to be an ancestor of destChild,
     since we have confirmed that srcTree is not destTree nor an ancestor of
     destTree.
    destContentsLock_ = destTree->contents_.wlock();
    destContents_ = &destContentsLock_->entries;
    lockDestChild(destName);
     While srcTree cannot be an ancestor of destChild, it might be the
     same inode.  Don't try to lock the same TreeInode twice in this case.
     The rename will be failed later since this must be an error, but for now
     we keep going and let the exact error be determined later.
     This will either be ENOENT (src entry doesn't exist) or ENOTEMPTY
     (destChild is not empty since the src entry exists).
    if (destChildExists() && destChild() == srcTree) {
      CHECK_NOTNULL(destChildContents_);
      srcContents_ = destChildContents_;
    } else {
      srcContentsLock_ = srcTree->contents_.wlock();
      srcContents_ = &srcContentsLock_->entries;
    }
  }
}
void TreeInode :: TreeRenameLocks :: acquireLocks ( RenameLock && renameLock , TreeInode * srcTree , TreeInode * destTree , PathComponentPiece destName ) { renameLock_ = std :: move ( renameLock ) ; if ( srcTree == destTree ) { srcContentsLock_ = srcTree -> contents_ . wlock ( ) ; srcContents_ = & srcContentsLock_ -> entries ; destContents_ = & srcContentsLock_ -> entries ; lockDestChild ( destName ) ; } else if ( isAncestor ( renameLock_ , srcTree , destTree ) ) { srcContentsLock_ = srcTree -> contents_ . wlock ( ) ; srcContents_ = & srcContentsLock_ -> entries ; destContentsLock_ = destTree -> contents_ . wlock ( ) ; destContents_ = & destContentsLock_ -> entries ; lockDestChild ( destName ) ; } else { destContentsLock_ = destTree -> contents_ . wlock ( ) ; destContents_ = & destContentsLock_ -> entries ; lockDestChild ( destName ) ; if ( destChildExists ( ) && destChild ( ) == srcTree ) { CHECK_NOTNULL ( destChildContents_ ) ; srcContents_ = destChildContents_ ; } else { srcContentsLock_ = srcTree -> contents_ . wlock ( ) ; srcContents_ = & srcContentsLock_ -> entries ; } } }
Acquire the locks necessary for a rename operation.
Acquire the locks necessary for a rename operation .
// Store the mountpoint-wide rename lock. // If the source and destination directories are the same, // then there is really only one parent directory to lock. // Look up the destination child entry, and lock it if is is a directory // If srcTree is an ancestor of destTree, we must acquire the lock on // srcTree first. // In all other cases, lock destTree and destChild before srcTree, // as long as we verify that destChild and srcTree are not the same. // // It is not possible for srcTree to be an ancestor of destChild, // since we have confirmed that srcTree is not destTree nor an ancestor of // destTree. // While srcTree cannot be an ancestor of destChild, it might be the // same inode.  Don't try to lock the same TreeInode twice in this case. // // The rename will be failed later since this must be an error, but for now // we keep going and let the exact error be determined later. // This will either be ENOENT (src entry doesn't exist) or ENOTEMPTY // (destChild is not empty since the src entry exists).