Improved fs_unmount(): it will now free all vnodes directly via free_vnode(),

and no longer relies on put_vnode() for the root node. This will also call
the FS release/remove vnode calls. Extended comments.
Added "flags" parameter to unmount.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10289 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2004-11-29 22:45:27 +00:00
parent 4c8e8f2f19
commit b5d786bdac
+27 -27
View File
@@ -4086,11 +4086,11 @@ err1:
static status_t static status_t
fs_unmount(char *path, bool kernel) fs_unmount(char *path, uint32 flags, bool kernel)
{ {
struct fs_mount *mount; struct fs_mount *mount;
struct vnode *vnode; struct vnode *vnode;
int err; status_t err;
FUNCTION(("vfs_unmount: entry. path = '%s', kernel %d\n", path, kernel)); FUNCTION(("vfs_unmount: entry. path = '%s', kernel %d\n", path, kernel));
@@ -4132,12 +4132,13 @@ fs_unmount(char *path, bool kernel)
} }
} }
/* grab the vnode master mutex to keep someone from creating // grab the vnode master mutex to keep someone from creating
* 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);
/* simulate the root vnode having it's refcount decremented */ // simplify the loop below: we decrement the root vnode ref_count
// by the known number of references: one for the fs_mount, one
// from the path_to_vnode() call above
mount->root_vnode->ref_count -= 2; mount->root_vnode->ref_count -= 2;
// cycle through the list of vnodes associated with this mount and // cycle through the list of vnodes associated with this mount and
@@ -4145,39 +4146,38 @@ fs_unmount(char *path, bool kernel)
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) { if (vnode->busy || vnode->ref_count != 0) {
// there are still vnodes in use on this mount, so we cannot unmount yet
// ToDo: cut read/write access file descriptors, depending on the B_FORCE_UNMOUNT flag
mount->root_vnode->ref_count += 2; mount->root_vnode->ref_count += 2;
mutex_unlock(&sVnodeMutex); mutex_unlock(&sVnodeMutex);
put_vnode(mount->root_vnode); put_vnode(mount->root_vnode);
return EBUSY; return B_BUSY;
} }
} }
/* we can safely continue, mark all of the vnodes busy and this mount // we can safely continue, mark all of the vnodes busy and this mount
* structure in unmounting state // structure in unmounting state
*/
while ((vnode = (struct vnode *)list_get_next_item(&mount->vnodes, vnode)) != NULL) {
if (vnode != mount->root_vnode)
vnode->busy = true;
}
mount->unmounting = true; mount->unmounting = true;
/* add 2 back to the root vnode's ref */ while ((vnode = (struct vnode *)list_get_next_item(&mount->vnodes, vnode)) != NULL) {
mount->root_vnode->ref_count += 2; vnode->busy = true;
hash_remove(sVnodeTable, vnode);
}
mutex_unlock(&sVnodeMutex); mutex_unlock(&sVnodeMutex);
mount->covers_vnode->covered_by = NULL; mount->covers_vnode->covered_by = NULL;
put_vnode(mount->covers_vnode); put_vnode(mount->covers_vnode);
/* release the ref on the root vnode twice */ // Free all vnodes associated with this mount.
put_vnode(mount->root_vnode); // They will be removed from the mount list by free_vnode(), so
put_vnode(mount->root_vnode); // we don't have to do this.
while ((vnode = (struct vnode *)list_get_next_item(&mount->vnodes, NULL)) != NULL) {
free_vnode(vnode, false);
}
// ToDo: when full vnode cache in place, will need to force // remove the mount structure from the hash table
// a putvnode/removevnode here
/* remove the mount structure from the hash table */
mutex_lock(&sMountMutex); mutex_lock(&sMountMutex);
hash_remove(sMountsTable, mount); hash_remove(sMountsTable, mount);
mutex_unlock(&sMountMutex); mutex_unlock(&sMountMutex);
@@ -4405,12 +4405,12 @@ _kern_mount(const char *path, const char *device, const char *fs_name,
status_t status_t
_kern_unmount(const char *path) _kern_unmount(const char *path, uint32 flags)
{ {
char pathBuffer[B_PATH_NAME_LENGTH + 1]; char pathBuffer[B_PATH_NAME_LENGTH + 1];
strlcpy(pathBuffer, path, B_PATH_NAME_LENGTH); strlcpy(pathBuffer, path, B_PATH_NAME_LENGTH);
return fs_unmount(pathBuffer, true); return fs_unmount(pathBuffer, flags, true);
} }
@@ -5080,7 +5080,7 @@ _user_mount(const char *userPath, const char *userDevice, const char *userFileSy
status_t status_t
_user_unmount(const char *userPath) _user_unmount(const char *userPath, uint32 flags)
{ {
char path[B_PATH_NAME_LENGTH + 1]; char path[B_PATH_NAME_LENGTH + 1];
int status; int status;
@@ -5089,7 +5089,7 @@ _user_unmount(const char *userPath)
if (status < 0) if (status < 0)
return status; return status;
return fs_unmount(path, false); return fs_unmount(path, flags, false);
} }