diff --git a/fs/refs.c b/fs/refs.c index 4b45fd9..c10be5a 100644 --- a/fs/refs.c +++ b/fs/refs.c @@ -131,8 +131,11 @@ void vfs_entry_replace_children(struct vfs_entry* dst, struct vfs_entry* src) { tailq_head(struct vfs_entry) stale; tailq_init(&stale); - mutex_lock(&src->lock); - mutex_lock(&dst->lock); + // Avoid a potential deadlock when this function is called with (a, b) and (b, a) at the same time. + 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; while ((child = tailq_first(&dst->children))) { 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); tailq_insert_tail(&dst->children, child, child_link); } - mutex_unlock(&dst->lock); - mutex_unlock(&src->lock); + mutex_unlock(&second->lock); + mutex_unlock(&first->lock); while ((child = tailq_first(&stale))) { tailq_remove(&stale, child, child_link);