From 7121425eb599ad42f6e070d4edd8b879ba75748d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 20 Oct 2005 16:34:18 +0000 Subject: [PATCH] Turns out we could remove a mount point... Under BeOS remove_vnode() is failing in this case, which looks like a good idea to imitate. Also, pipefs/rootfs didn't handle that case - they even removed the entry before calling remove_vnode() - they now behave correctly. And also BFS now returns the actual error code received from remove_vnode() instead of B_ERROR. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14456 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/file_systems/bfs/Inode.cpp | 5 +++-- src/system/kernel/fs/pipefs.cpp | 8 +++++--- src/system/kernel/fs/rootfs.c | 14 +++++++++----- src/system/kernel/fs/vfs.cpp | 6 ++++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index d68a872f1f..65191b23bc 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -2043,8 +2043,9 @@ Inode::Remove(Transaction &transaction, const char *name, off_t *_id, bool isDir } // remove_vnode() allows the inode to be accessed until the last put_vnode() - if (remove_vnode(fVolume->ID(), id) != B_OK) - return B_ERROR; + status = remove_vnode(fVolume->ID(), id); + if (status != B_OK) + return status; if (tree->Remove(transaction, name, id) < B_OK) { unremove_vnode(fVolume->ID(), id); diff --git a/src/system/kernel/fs/pipefs.cpp b/src/system/kernel/fs/pipefs.cpp index 6b1e6c928c..916e30fb4f 100644 --- a/src/system/kernel/fs/pipefs.cpp +++ b/src/system/kernel/fs/pipefs.cpp @@ -513,12 +513,14 @@ Volume::RemoveNode(Inode *directory, const char *name) if (status < B_OK) goto err; + // schedule this vnode to be removed when it's ref goes to zero + status = remove_vnode(ID(), inode->ID()); + if (status < B_OK) + goto err; + RemoveNode(inode); notify_entry_removed(ID(), directory->ID(), name, inode->ID()); - // schedule this vnode to be removed when it's ref goes to zero - remove_vnode(ID(), inode->ID()); - err: Unlock(); diff --git a/src/system/kernel/fs/rootfs.c b/src/system/kernel/fs/rootfs.c index 703ac2592c..222113079c 100644 --- a/src/system/kernel/fs/rootfs.c +++ b/src/system/kernel/fs/rootfs.c @@ -257,11 +257,15 @@ rootfs_is_dir_empty(struct rootfs_vnode *dir) static status_t remove_node(struct rootfs *fs, struct rootfs_vnode *directory, struct rootfs_vnode *vnode) { + // schedule this vnode to be removed when it's ref goes to zero + status_t status = remove_vnode(fs->id, vnode->id); + if (status < B_OK) + return status; + rootfs_remove_from_dir(fs, directory, vnode); notify_entry_removed(fs->id, directory->id, vnode->name, vnode->id); - // schedule this vnode to be removed when it's ref goes to zero - return remove_vnode(fs->id, vnode->id); + return B_OK; } @@ -286,7 +290,7 @@ rootfs_remove(struct rootfs *fs, struct rootfs_vnode *dir, const char *name, boo if (status < B_OK) goto err; - remove_node(fs, dir, vnode); + status = remove_node(fs, dir, vnode); err: mutex_unlock(&fs->lock); @@ -481,14 +485,14 @@ rootfs_remove_vnode(fs_volume _fs, fs_vnode _vnode, bool reenter) struct rootfs *fs = (struct rootfs *)_fs; struct rootfs_vnode *vnode = (struct rootfs_vnode *)_vnode; - TRACE(("rootfs_removevnode: remove %p (0x%Lx), r %d\n", vnode, vnode->id, reenter)); + TRACE(("rootfs_remove_vnode: remove %p (0x%Lx), r %d\n", vnode, vnode->id, reenter)); if (!reenter) mutex_lock(&fs->lock); if (vnode->dir_next) { // can't remove node if it's linked to the dir - panic("rootfs_removevnode: vnode %p asked to be removed is present in dir\n", vnode); + panic("rootfs_remove_vnode: vnode %p asked to be removed is present in dir\n", vnode); } rootfs_delete_vnode(fs, vnode, false); diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 119fceefb0..04f3cdd193 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -2342,6 +2342,12 @@ remove_vnode(mount_id mountID, vnode_id vnodeID) vnode = lookup_vnode(mountID, vnodeID); if (vnode != NULL) { + if (vnode->covered_by != NULL) { + // this vnode is in use + mutex_unlock(&sVnodeMutex); + return B_BUSY; + } + vnode->remove = true; if (vnode->unpublished) { // prepare the vnode for deletion