Loading Documentation/filesystems/porting.rst +34 −0 Original line number Diff line number Diff line Loading @@ -1061,3 +1061,37 @@ export_operations ->encode_fh() no longer has a default implementation to encode FILEID_INO32_GEN* file handles. Filesystems that used the default implementation may use the generic helper generic_encode_ino32_fh() explicitly. --- **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. arch/powerpc/platforms/cell/spufs/inode.c +3 −2 Original line number Diff line number Diff line Loading @@ -145,10 +145,11 @@ spufs_evict_inode(struct inode *inode) static void spufs_prune_dir(struct dentry *dir) { struct dentry *dentry, *tmp; struct dentry *dentry; struct hlist_node *n; inode_lock(d_inode(dir)); list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) { hlist_for_each_entry_safe(dentry, n, &dir->d_children, d_sib) { spin_lock(&dentry->d_lock); if (simple_positive(dentry)) { dget_dlock(dentry); Loading fs/afs/dynroot.c +3 −2 Original line number Diff line number Diff line Loading @@ -370,7 +370,7 @@ int afs_dynroot_populate(struct super_block *sb) void afs_dynroot_depopulate(struct super_block *sb) { struct afs_net *net = afs_sb2net(sb); struct dentry *root = sb->s_root, *subdir, *tmp; struct dentry *root = sb->s_root, *subdir; /* Prevent more subdirs from being created */ mutex_lock(&net->proc_cells_lock); Loading @@ -379,10 +379,11 @@ void afs_dynroot_depopulate(struct super_block *sb) mutex_unlock(&net->proc_cells_lock); if (root) { struct hlist_node *n; inode_lock(root->d_inode); /* Remove all the pins for dirs created for manually added cells */ list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) { hlist_for_each_entry_safe(subdir, n, &root->d_children, d_sib) { if (subdir->d_fsdata) { subdir->d_fsdata = NULL; dput(subdir); Loading fs/autofs/expire.c +2 −5 Original line number Diff line number Diff line Loading @@ -73,12 +73,9 @@ static int autofs_mount_busy(struct vfsmount *mnt, /* p->d_lock held */ static struct dentry *positive_after(struct dentry *p, struct dentry *child) { if (child) child = list_next_entry(child, d_child); else child = list_first_entry(&p->d_subdirs, struct dentry, d_child); child = child ? d_next_sibling(child) : d_first_child(p); list_for_each_entry_from(child, &p->d_subdirs, d_child) { hlist_for_each_entry_from(child, d_sib) { spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); if (simple_positive(child)) { dget_dlock(child); Loading fs/ceph/dir.c +1 −1 Original line number Diff line number Diff line Loading @@ -174,7 +174,7 @@ __dcache_find_get_entry(struct dentry *parent, u64 idx, /* * When possible, we try to satisfy a readdir by peeking at the * dcache. We make this work by carefully ordering dentries on * d_child when we initially get results back from the MDS, and * d_children when we initially get results back from the MDS, and * falling back to a "normal" sync readdir if any dentries in the dir * are dropped. * Loading Loading
Documentation/filesystems/porting.rst +34 −0 Original line number Diff line number Diff line Loading @@ -1061,3 +1061,37 @@ export_operations ->encode_fh() no longer has a default implementation to encode FILEID_INO32_GEN* file handles. Filesystems that used the default implementation may use the generic helper generic_encode_ino32_fh() explicitly. --- **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.
arch/powerpc/platforms/cell/spufs/inode.c +3 −2 Original line number Diff line number Diff line Loading @@ -145,10 +145,11 @@ spufs_evict_inode(struct inode *inode) static void spufs_prune_dir(struct dentry *dir) { struct dentry *dentry, *tmp; struct dentry *dentry; struct hlist_node *n; inode_lock(d_inode(dir)); list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) { hlist_for_each_entry_safe(dentry, n, &dir->d_children, d_sib) { spin_lock(&dentry->d_lock); if (simple_positive(dentry)) { dget_dlock(dentry); Loading
fs/afs/dynroot.c +3 −2 Original line number Diff line number Diff line Loading @@ -370,7 +370,7 @@ int afs_dynroot_populate(struct super_block *sb) void afs_dynroot_depopulate(struct super_block *sb) { struct afs_net *net = afs_sb2net(sb); struct dentry *root = sb->s_root, *subdir, *tmp; struct dentry *root = sb->s_root, *subdir; /* Prevent more subdirs from being created */ mutex_lock(&net->proc_cells_lock); Loading @@ -379,10 +379,11 @@ void afs_dynroot_depopulate(struct super_block *sb) mutex_unlock(&net->proc_cells_lock); if (root) { struct hlist_node *n; inode_lock(root->d_inode); /* Remove all the pins for dirs created for manually added cells */ list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) { hlist_for_each_entry_safe(subdir, n, &root->d_children, d_sib) { if (subdir->d_fsdata) { subdir->d_fsdata = NULL; dput(subdir); Loading
fs/autofs/expire.c +2 −5 Original line number Diff line number Diff line Loading @@ -73,12 +73,9 @@ static int autofs_mount_busy(struct vfsmount *mnt, /* p->d_lock held */ static struct dentry *positive_after(struct dentry *p, struct dentry *child) { if (child) child = list_next_entry(child, d_child); else child = list_first_entry(&p->d_subdirs, struct dentry, d_child); child = child ? d_next_sibling(child) : d_first_child(p); list_for_each_entry_from(child, &p->d_subdirs, d_child) { hlist_for_each_entry_from(child, d_sib) { spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); if (simple_positive(child)) { dget_dlock(child); Loading
fs/ceph/dir.c +1 −1 Original line number Diff line number Diff line Loading @@ -174,7 +174,7 @@ __dcache_find_get_entry(struct dentry *parent, u64 idx, /* * When possible, we try to satisfy a readdir by peeking at the * dcache. We make this work by carefully ordering dentries on * d_child when we initially get results back from the MDS, and * d_children when we initially get results back from the MDS, and * falling back to a "normal" sync readdir if any dentries in the dir * are dropped. * Loading