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
This commit is contained in:
@@ -5252,10 +5252,6 @@ fs_unmount(char *path, uint32 flags, bool kernel)
|
|||||||
// a vnode while we're figuring out if we can continue
|
// a vnode while we're figuring out if we can continue
|
||||||
mutex_lock(&sVnodeMutex);
|
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;
|
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
|
// make sure all of them are not busy or have refs on them
|
||||||
vnode = NULL;
|
vnode = NULL;
|
||||||
while ((vnode = (struct vnode *)list_get_next_item(&mount->vnodes, 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
|
// there are still vnodes in use on this mount, so we cannot
|
||||||
// unmount yet
|
// unmount yet
|
||||||
busy = true;
|
busy = true;
|
||||||
@@ -5278,7 +5278,6 @@ fs_unmount(char *path, uint32 flags, bool kernel)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if ((flags & B_FORCE_UNMOUNT) == 0) {
|
if ((flags & B_FORCE_UNMOUNT) == 0) {
|
||||||
mount->root_vnode->ref_count += 2;
|
|
||||||
mutex_unlock(&sVnodeMutex);
|
mutex_unlock(&sVnodeMutex);
|
||||||
put_vnode(mount->root_vnode);
|
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);
|
mutex_unlock(&sVnodeMutex);
|
||||||
|
|
||||||
mount->covers_vnode->covered_by = NULL;
|
mount->covers_vnode->covered_by = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user