**mandatory**
---
+If ->rename() update of .. on cross-directory move needs an exclusion with
+directory modifications, do *not* lock the subdirectory in question in your
+->rename() - it's done by the caller now [that item should've been added in
+28eceeda130f "fs: Lock moved directories"].
+
+---
+
+**mandatory**
+
+On same-directory ->rename() the (tautological) update of .. is not protected
+by any locks; just don't do it if the old parent is the same as the new one.
+We really can't lock two subdirectories in same-directory rename - not without
+deadlocks.
+
+---
+
+**mandatory**
+
+lock_rename() and lock_rename_child() may fail in cross-directory case, if
+their arguments do not have a common ancestor. In that case ERR_PTR(-EXDEV)
+is returned, with no locks taken. In-tree users updated; out-of-tree ones
+would need to do so.
+
+---
+
++**mandatory**
++
+ The list of children anchored in parent dentry got turned into hlist now.
+ Field names got changed (->d_children/->d_sib instead of ->d_subdirs/->d_child
+ for anchor/entries resp.), so any affected places will be immediately caught
+ by compiler.
+
+ ---
+
+ **mandatory**
+
+ ->d_delete() instances are now called for dentries with ->d_lock held
+ and refcount equal to 0. They are not permitted to drop/regain ->d_lock.
+ None of in-tree instances did anything of that sort. Make sure yours do not...
+
++---
+
+ **mandatory**
+
+ ->d_prune() instances are now called without ->d_lock held on the parent.
+ ->d_lock on dentry itself is still held; if you need per-parent exclusions (none
+ of the in-tree instances did), use your own spinlock.
+
+ ->d_iput() and ->d_release() are called with victim dentry still in the
+ list of parent's children. It is still unhashed, marked killed, etc., just not
+ removed from parent's ->d_children yet.
+
+ Anyone iterating through the list of children needs to be aware of the
+ half-killed dentries that might be seen there; taking ->d_lock on those will
+ see them negative, unhashed and with negative refcount, which means that most
+ of the in-kernel users would've done the right thing anyway without any adjustment.
++
++---
++
+**recommended**
+
+Block device freezing and thawing have been moved to holder operations.
+
+Before this change, get_active_super() would only be able to find the
+superblock of the main block device, i.e., the one stored in sb->s_bdev. Block
+device freezing now works for any block device owned by a given superblock, not
+just the main block device. The get_active_super() helper and bd_fsfreeze_sb
+pointer are gone.
change_gid(this_parent, gid);
repeat:
- next = this_parent->d_subdirs.next;
+ dentry = d_first_child(this_parent);
resume:
- while (next != &this_parent->d_subdirs) {
+ hlist_for_each_entry_from(dentry, d_sib) {
+ struct tracefs_inode *ti;
- struct list_head *tmp = next;
- struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
- next = tmp->next;
+
+ /* Note, getdents() can add a cursor dentry with no inode */
+ if (!dentry->d_inode)
+ continue;
+
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
change_gid(dentry, gid);
- if (!list_empty(&dentry->d_subdirs)) {
+ /* If this is the events directory, update that too */
+ ti = get_tracefs(dentry->d_inode);
+ if (ti && (ti->flags & TRACEFS_EVENT_INODE))
+ eventfs_update_gid(dentry, gid);
+
+ if (!hlist_empty(&dentry->d_children)) {
spin_unlock(&this_parent->d_lock);
spin_release(&dentry->d_lock.dep_map, _RET_IP_);
this_parent = dentry;