sapling/eden/docs/InodeLocks.md
Chad Austin d4e186f995 store FileInode and TreeInode timestamps in the InodeTable
Summary: Store tree and file timestamps in the InodeTable so they persist across runs.

Reviewed By: simpkins

Differential Revision: D6891479

fbshipit-source-id: 1c9e6266375aceeaf293a81e73cf7f5334dbc32d
2018-05-22 11:22:19 -07:00

4.3 KiB

InodeBase's location_ lock:

No other locks should be acquired while holding this lock. Two location_ locks should never be held at the same time.

This field cannot be updated without holding both the EdenMount's rename lock and the location_ lock for the InodeBase in question.

Note that InodeBase::getLogPath() acquires location_ locks. This function is used in log statements in many places, including in places where other locks are held. It is therefore important to ensure that the location_ lock remains at the very bottom of our lock-ordering stack.

InodeMap data_ lock:

No other locks should be acquired while holding this lock, apart from InodeBase location_ locks. (InodeBase location_ locks are only held with the InodeMap lock already held for the purpose of calling inode->getLogPath() in logging statements.)

In general it should only be held very briefly while doing lookups/inserts on the map data structures. Once we need to load an Inode the InodeMap lock is released for the duration of the load operation itself. It is re-acquired when the load completes so we can insert the new Inode into the map.

InodeMetadataTable state_ lock:

No other locks should be acquired while holding this lock.

In general it should only be held very briefly while doing lookups/inserts on InodeTable's index data structures.

FileInode lock:

The InodeBase location_ lock may be acquired while holding a FileInode's lock.

TreeInode contents_ lock:

  • The InodeMap lock may be acquired while holding a TreeInode's contents_ lock.

  • The InodeBase location_ lock may be acquired while holding a TreeInode's contents_ lock.

  • A FileInode's lock may be acquired while holding its parent TreeInode's contents_ lock.

In some situations the same thread acquires multiple contents_ locks together.

  • Some code paths hold a parent TreeInode's contents_ lock while accessing its children, and then acquire a child TreeInode's contents_ lock while still holding the parent TreeInode's lock.

  • The rename() code may hold up to 3 TreeInode locks. It always holds the contents_ lock on both the source TreeInode and the destination TreeInode. Additionally, if the destination name refers to an existing TreeInode, the rename() holds its contents_ lock as well, to ensure that it is empty, and to prevent new entries from being created inside this directory once the rename starts.

To prevent deadlocks, the lock ordering constraints for TreeInode contents_ are as follows:

  • If you are not holding the mountpoint rename lock, you can only acquire a TreeInode contents_ lock if the other contents_ locks you are holding are for this TreeInode's immediate parents. (e.g., if you are already holding another contents_ lock it must be for this TreeInode's parent. If you are holding two other contents_ locks it must be for this TreeInode's parent and grandparent.)

    Note however that acquiring multiple TreeInode contents locks discouraged. When possible it is preferred to release the lock on the parent TreeInode before locking the child. Acquiring locks on more than 2 levels of the tree hierarchy is technically safe from a lock ordering perspective, but is also strongly discouraged.

  • If you are holding the mountpoint rename lock, it is safe to acquire multiple TreeInode locks at a time. However, if there is an ancestor/child relationship between any of the TreeInode's, the ancestor lock must be acquired first. This avoids lock ordering issues with other threads that are not holding the rename lock. Among unrelated TreeInodes no particular ordering is required.

EdenMount's rename lock:

This lock is a very high level lock in our lock ordering stack--it is acquired before any other individual inode-specific locks.

This lock is held for the duration of a rename or unlink operation. No InodeBase location_ fields may be updated without holding this lock.

EdenMount's current snapshot lock:

This lock is also a very high level lock in our lock ordering stack. It is acquired for the duration of any operation that updates the current snapshot that is checked out.

Checkout operations acquire both the current snapshot lock and the rename lock. The snapshot lock is always acquired before the rename lock.