summaryrefslogtreecommitdiff
path: root/fs/afs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2025-01-05 21:33:17 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2025-01-27 19:25:24 -0500
commit30d61efe118cad1a73ad2ad66a3298e4abdf9f41 (patch)
treea282341626aed194b55d1be64776ff3ca67b9805 /fs/afs
parent90341f22c364d8ad55184ce2b8777545942dc5cf (diff)
9p: fix ->rename_sem exclusion
9p wants to be able to build a path from given dentry to fs root and keep it valid over a blocking operation. ->s_vfs_rename_mutex would be a natural candidate, but there are places where we need that and where we have no way to tell if ->s_vfs_rename_mutex is already held deeper in callchain. Moreover, it's only held for cross-directory renames; name changes within the same directory happen without it. Solution: * have d_move() done in ->rename() rather than in its caller * maintain a 9p-private rwsem (per-filesystem) * hold it exclusive over the relevant part of ->rename() * hold it shared over the places where we want the path. That almost works. FS_RENAME_DOES_D_MOVE is enough to put all d_move() and d_exchange() calls under filesystem's control. However, there's also __d_unalias(), which isn't covered by any of that. If ->lookup() hits a directory inode with preexisting dentry elsewhere (due to e.g. rename done on server behind our back), d_splice_alias() called by ->lookup() will move/rename that alias. Add a couple of optional methods, so that __d_unalias() would do if alias->d_op->d_unalias_trylock != NULL if (!alias->d_op->d_unalias_trylock(alias)) fail (resulting in -ESTALE from lookup) __d_move(...) if alias->d_op->d_unalias_unlock != NULL alias->d_unalias_unlock(alias) where it currently does __d_move(). 9p instances do down_write_trylock() and up_write() of ->rename_mutex. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/afs')
0 files changed, 0 insertions, 0 deletions