fs: Avoid deadlock when renaming
This commit is contained in:
@@ -131,8 +131,11 @@ void vfs_entry_replace_children(struct vfs_entry* dst, struct vfs_entry* src) {
|
|||||||
tailq_head(struct vfs_entry) stale;
|
tailq_head(struct vfs_entry) stale;
|
||||||
tailq_init(&stale);
|
tailq_init(&stale);
|
||||||
|
|
||||||
mutex_lock(&src->lock);
|
// Avoid a potential deadlock when this function is called with (a, b) and (b, a) at the same time.
|
||||||
mutex_lock(&dst->lock);
|
struct vfs_entry* first = src < dst ? src : dst;
|
||||||
|
struct vfs_entry* second = src < dst ? dst : src;
|
||||||
|
mutex_lock(&first->lock);
|
||||||
|
mutex_lock(&second->lock);
|
||||||
struct vfs_entry* child;
|
struct vfs_entry* child;
|
||||||
while ((child = tailq_first(&dst->children))) {
|
while ((child = tailq_first(&dst->children))) {
|
||||||
tailq_remove(&dst->children, child, child_link);
|
tailq_remove(&dst->children, child, child_link);
|
||||||
@@ -145,8 +148,8 @@ void vfs_entry_replace_children(struct vfs_entry* dst, struct vfs_entry* src) {
|
|||||||
vfs_entry_unref(src);
|
vfs_entry_unref(src);
|
||||||
tailq_insert_tail(&dst->children, child, child_link);
|
tailq_insert_tail(&dst->children, child, child_link);
|
||||||
}
|
}
|
||||||
mutex_unlock(&dst->lock);
|
mutex_unlock(&second->lock);
|
||||||
mutex_unlock(&src->lock);
|
mutex_unlock(&first->lock);
|
||||||
|
|
||||||
while ((child = tailq_first(&stale))) {
|
while ((child = tailq_first(&stale))) {
|
||||||
tailq_remove(&stale, child, child_link);
|
tailq_remove(&stale, child, child_link);
|
||||||
|
|||||||
Reference in New Issue
Block a user