From abb84c7d51dcaaeacc7a3a0f75404f18b10167a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 8 Mar 2006 22:57:53 +0000 Subject: [PATCH] Removing the nodes from the unused list in fs_unmount() had the side effect that the root vnode was tried to be removed as well (which resulted in a crash). Since playing with the root node reference count is a bad idea anyway and opens a big race condition (with regards to the unused list), we no longer do that now, until it's safe. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16665 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/fs/vfs.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 6c5b00eaa7..d3cd2ce203 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -5252,10 +5252,6 @@ fs_unmount(char *path, uint32 flags, bool kernel) // a vnode while we're figuring out if we can continue mutex_lock(&sVnodeMutex); - // simplify the loop below: we decrement the root vnode ref_count - // by the known number of references: one for the file system, one - // from the path_to_vnode() call above - mount->root_vnode->ref_count -= 2; bool disconnectedDescriptors = false; @@ -5266,7 +5262,11 @@ fs_unmount(char *path, uint32 flags, bool kernel) // make sure all of them are not busy or have refs on them vnode = NULL; while ((vnode = (struct vnode *)list_get_next_item(&mount->vnodes, vnode)) != NULL) { - if (vnode->busy || vnode->ref_count != 0) { + // The root vnode ref_count needs to be 2 here: one for the file + // system, one from the path_to_vnode() call above + if (vnode->busy + || ((vnode->ref_count != 0 && mount->root_vnode != vnode) + || (vnode->ref_count != 2 && mount->root_vnode == vnode))) { // there are still vnodes in use on this mount, so we cannot // unmount yet busy = true; @@ -5278,7 +5278,6 @@ fs_unmount(char *path, uint32 flags, bool kernel) break; if ((flags & B_FORCE_UNMOUNT) == 0) { - mount->root_vnode->ref_count += 2; mutex_unlock(&sVnodeMutex); put_vnode(mount->root_vnode); @@ -5396,6 +5395,9 @@ fs_unmount(char *path, uint32 flags, bool kernel) } } + // The ref_count of the root node is 2 at this point, see above why this is + mount->root_vnode->ref_count -= 2; + mutex_unlock(&sVnodeMutex); mount->covers_vnode->covered_by = NULL;