We now have a consistent scheme what the file system should do with its root

node: like in BeOS, it *must* own the root node (ie. via publish_vnode()),
unlike in BeOS, it must also drop that reference on unmount (symmetrical
behaviour definitely makes more sense to me than the Be way).
Since all existing file systems for Haiku behaved differently, I brought them
in line (only pipefs already adhered to that new standard for some reason,
rootfs did only released the node, devfs did nothing - despite it's probably
not really useful to be able to unmount them).
fs_mount() will now panic if a file system does not do this correctly (useful
for file system developing).
Unmounting is now theoretically working again: when trying to unmount a BFS
volume, the kernel crashes in the block cache destruction... (but that's work
for tomorrow).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14017 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-08-21 00:41:16 +00:00
parent 8c1bec29de
commit 5b14757a30
4 changed files with 46 additions and 38 deletions
@@ -380,6 +380,9 @@ Volume::Mount(const char *deviceName, uint32 flags)
status_t
Volume::Unmount()
{
// Unlike in BeOS, we need to put the reference to our root node ourselves
put_vnode(fID, ToVnode(Root()));
// This will also flush the log & all blocks to disk
delete fJournal;
fJournal = NULL;
+4
View File
@@ -978,6 +978,7 @@ devfs_mount(mount_id id, const char *devfs, uint32 flags, const char *args,
fs->root_vnode = vnode;
hash_insert(fs->vnode_hash, vnode);
publish_vnode(id, vnode->id, vnode);
*root_vnid = vnode->id;
*_fs = fs;
@@ -1006,6 +1007,9 @@ devfs_unmount(fs_volume _fs)
TRACE(("devfs_unmount: entry fs = %p\n", fs));
// release the reference to the root
put_vnode(fs->id, fs->root_vnode->id);
// delete all of the vnodes
hash_open(fs->vnode_hash, &i);
while ((vnode = (devfs_vnode *)hash_next(fs->vnode_hash, &i)) != NULL) {
+2 -1
View File
@@ -336,6 +336,7 @@ rootfs_mount(mount_id id, const char *device, uint32 flags, const char *args,
fs->root_vnode = vnode;
hash_insert(fs->vnode_list_hash, vnode);
publish_vnode(id, vnode->id, vnode);
*root_vnid = vnode->id;
*_fs = fs;
@@ -362,7 +363,7 @@ rootfs_unmount(fs_volume _fs)
TRACE(("rootfs_unmount: entry fs = %p\n", fs));
// put_vnode on the root to release the ref to it
// release the reference to the root
put_vnode(fs->id, fs->root_vnode->id);
// delete all of the vnodes
+37 -37
View File
@@ -4804,9 +4804,7 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
const char *args, bool kernel)
{
struct fs_mount *mount;
struct vnode *covered_vnode = NULL;
vnode_id root_id;
int err = 0;
status_t status = 0;
FUNCTION(("fs_mount: entry. path = '%s', fs_name = '%s'\n", path, fsName));
@@ -4843,9 +4841,9 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
if (!(flags & B_MOUNT_VIRTUAL_DEVICE) && device) {
// normalize the device path
KPath normalizedDevice;
err = normalizedDevice.SetTo(device, true);
if (err != B_OK)
return err;
status = normalizedDevice.SetTo(device, true);
if (status != B_OK)
return status;
// get a corresponding partition from the DDM
partition = ddm->RegisterPartition(normalizedDevice.Path(), true);
@@ -4923,7 +4921,7 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
mount->fs_name = get_file_system_name(fsName);
if (mount->fs_name == NULL) {
err = B_NO_MEMORY;
status = B_NO_MEMORY;
goto err1;
}
@@ -4932,12 +4930,12 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
mount->fs = get_file_system(fsName);
if (mount->fs == NULL) {
err = ENODEV;
status = ENODEV;
goto err3;
}
err = recursive_lock_init(&mount->rlock, "mount rlock");
if (err < B_OK)
status = recursive_lock_init(&mount->rlock, "mount rlock");
if (status < B_OK)
goto err4;
mount->id = sNextMountID++;
@@ -4945,66 +4943,68 @@ fs_mount(char *path, const char *device, const char *fsName, uint32 flags,
mount->unmounting = false;
mount->owns_file_device = false;
mutex_lock(&sMountMutex);
// insert mount struct into list before we call fs mount()
mutex_lock(&sMountMutex);
hash_insert(sMountsTable, mount);
mutex_unlock(&sMountMutex);
vnode_id rootID;
if (!sRoot) {
// we haven't mounted anything yet
if (strcmp(path, "/") != 0) {
err = B_ERROR;
status = B_ERROR;
goto err5;
}
err = FS_MOUNT_CALL(mount, mount)(mount->id, device, flags, args, &mount->cookie, &root_id);
if (err < 0) {
status = FS_MOUNT_CALL(mount, mount)(mount->id, device, flags, args, &mount->cookie, &rootID);
if (status < 0) {
// ToDo: why should we hide the error code from the file system here?
//err = ERR_VFS_GENERAL;
//status = ERR_VFS_GENERAL;
goto err5;
}
mount->covers_vnode = NULL; // this is the root mount
} else {
err = path_to_vnode(path, true, &covered_vnode, NULL, kernel);
if (err < 0)
struct vnode *coveredVnode;
status = path_to_vnode(path, true, &coveredVnode, NULL, kernel);
if (status < B_OK)
goto err5;
if (!covered_vnode) {
err = B_ERROR;
goto err5;
}
// make sure covered_vnode is a DIR
struct stat coveredNodeStat;
err = FS_CALL(covered_vnode, read_stat)(covered_vnode->mount->cookie,
covered_vnode->private_node, &coveredNodeStat);
if (err < 0)
status = FS_CALL(coveredVnode, read_stat)(coveredVnode->mount->cookie,
coveredVnode->private_node, &coveredNodeStat);
if (status < B_OK)
goto err5;
if (!S_ISDIR(coveredNodeStat.st_mode)) {
err = B_NOT_A_DIRECTORY;
status = B_NOT_A_DIRECTORY;
goto err5;
}
if (covered_vnode->mount->root_vnode == covered_vnode) {
err = B_BUSY;
if (coveredVnode->mount->root_vnode == coveredVnode) {
// this is already a mount point
status = B_BUSY;
goto err5;
}
mount->covers_vnode = covered_vnode;
mount->covers_vnode = coveredVnode;
// mount it
err = FS_MOUNT_CALL(mount, mount)(mount->id, device, flags, args, &mount->cookie, &root_id);
if (err < 0)
status = FS_MOUNT_CALL(mount, mount)(mount->id, device, flags, args, &mount->cookie, &rootID);
if (status < B_OK)
goto err6;
}
err = get_vnode(mount->id, root_id, &mount->root_vnode, 0);
if (err < 0)
// the root node is supposed to be owned by the file system - it must
// exist at this point
mount->root_vnode = lookup_vnode(mount->id, rootID);
if (mount->root_vnode == NULL || mount->root_vnode->ref_count != 1) {
panic("fs_mount: file system does not own its root node!\n");
status = B_ERROR;
goto err7;
}
// No race here, since fs_mount() is the only function changing
// covers_vnode (and holds sMountOpLock at that time).
@@ -5047,7 +5047,7 @@ err3:
err1:
free(mount);
return err;
return status;
}
@@ -5103,7 +5103,7 @@ fs_unmount(char *path, uint32 flags, bool kernel)
mutex_lock(&sVnodeMutex);
// simplify the loop below: we decrement the root vnode ref_count
// by the known number of references: one for the fs_mount, one
// 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;