The available file systems aren't load anymore on startup.

Reimplemented file system handling, it's now loading file systems on an
on-demand basis - code is not tested yet, but should work!
That also fixed a bug that was in that code before (the image was not
unloaded in case of an error in vfs_load_fs_module()).
Renamed fs_id to mount_id.
Renamed all global variables to have the 'g' prefix in vfs.c.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1175 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-09-25 14:10:50 +00:00
parent 62781e5bc4
commit e04fced505
4 changed files with 281 additions and 198 deletions
+2 -2
View File
@@ -63,7 +63,7 @@ struct bootfs_vnode {
};
struct bootfs {
fs_id id;
mount_id id;
mutex lock;
int next_vnode_id;
void *vnode_list_hash;
@@ -387,7 +387,7 @@ bootfs_create_vnode_tree(struct bootfs *fs, struct bootfs_vnode *root)
static status_t
bootfs_mount(fs_id id, const char *device, void *args, fs_volume *_fs, vnode_id *root_vnid)
bootfs_mount(mount_id id, const char *device, void *args, fs_volume *_fs, vnode_id *root_vnid)
{
struct bootfs *fs;
struct bootfs_vnode *v;
+2 -2
View File
@@ -79,7 +79,7 @@ struct devfs_vnode {
};
struct devfs {
fs_id id;
mount_id id;
mutex lock;
int next_vnode_id;
void *vnode_list_hash;
@@ -406,7 +406,7 @@ err2:
static status_t
devfs_mount(fs_id id, const char *devfs, void *args, fs_volume *_fs, vnode_id *root_vnid)
devfs_mount(mount_id id, const char *devfs, void *args, fs_volume *_fs, vnode_id *root_vnid)
{
struct devfs *fs;
struct devfs_vnode *v;
+2 -2
View File
@@ -54,7 +54,7 @@ struct rootfs_vnode {
};
struct rootfs {
fs_id id;
mount_id id;
mutex lock;
vnode_id next_vnode_id;
void *vnode_list_hash;
@@ -264,7 +264,7 @@ err:
static status_t
rootfs_mount(fs_id id, const char *device, void *args, fs_volume *_fs, vnode_id *root_vnid)
rootfs_mount(mount_id id, const char *device, void *args, fs_volume *_fs, vnode_id *root_vnid)
{
struct rootfs *fs;
struct rootfs_vnode *vnode;
+275 -192
View File
@@ -64,52 +64,65 @@
((addr)(x) < KERNEL_BASE || (addr)(x) > KERNEL_TOP)
struct vnode {
struct vnode *next;
struct vnode *mount_prev;
struct vnode *mount_next;
struct vm_cache *cache;
fs_id fs_id;
vnode_id id;
fs_vnode private_node;
struct fs_mount *mount;
struct vnode *covered_by;
int32 ref_count;
bool delete_me;
bool busy;
struct vnode *next;
struct vnode *mount_prev;
struct vnode *mount_next;
struct vm_cache *cache;
mount_id mount_id;
vnode_id id;
fs_vnode private_node;
struct fs_mount *mount;
struct vnode *covered_by;
int32 ref_count;
bool delete_me;
bool busy;
};
struct vnode_hash_key {
fs_id fs_id;
vnode_id vnode_id;
mount_id mount_id;
vnode_id vnode_id;
};
struct fs_container {
struct fs_container *next;
struct fs_calls *calls;
const char *name;
};
typedef struct file_system {
struct file_system *next;
struct fs_calls *calls;
const char *name;
image_id image;
int32 ref_count;
} file_system;
#define FS_CALL(vnode,call) (vnode->mount->fs->calls->call)
static struct fs_container *fs_list;
struct fs_mount {
struct fs_mount *next;
struct fs_container *fs;
fs_id id;
void *cookie;
char *mount_point;
recursive_lock rlock;
struct vnode *root_vnode;
struct vnode *covers_vnode;
struct vnode *vnodes_head;
struct vnode *vnodes_tail;
bool unmounting;
struct fs_mount *next;
file_system *fs;
mount_id id;
void *cookie;
char *mount_point;
recursive_lock rlock;
struct vnode *root_vnode;
struct vnode *covers_vnode;
struct vnode *vnodes_head;
struct vnode *vnodes_tail;
bool unmounting;
};
static mutex gRegisterMutex;
static file_system *gFileSystems;
static mutex gFileSystemsMutex;
static mutex gMountMutex;
static mutex gMountOpMutex;
static mutex gVnodeMutex;
#define VNODE_HASH_TABLE_SIZE 1024
static void *gVnodeTable;
static struct vnode *gRoot;
#define MOUNTS_HASH_TABLE_SIZE 16
static void *gMountsTable;
static mount_id gNextMountID = 0;
/* function declarations */
static int vfs_mount(char *path, const char *device, const char *fs_name, void *args, bool kernel);
static int vfs_unmount(char *path, bool kernel);
@@ -188,21 +201,12 @@ struct fd_ops attr_ops = {
attr_free_fd
};
#define VNODE_HASH_TABLE_SIZE 1024
static void *vnode_table;
static struct vnode *root_vnode;
static vnode_id next_vnode_id = 0;
#define MOUNTS_HASH_TABLE_SIZE 16
static void *mounts_table;
static fs_id next_fsid = 0;
static int
mount_compare(void *_m, const void *_key)
{
struct fs_mount *mount = _m;
const fs_id *id = _key;
const mount_id *id = _key;
if (mount->id == *id)
return 0;
@@ -215,7 +219,7 @@ static unsigned int
mount_hash(void *_m, const void *_key, unsigned int range)
{
struct fs_mount *mount = _m;
const fs_id *id = _key;
const mount_id *id = _key;
if (mount)
return mount->id % range;
@@ -224,14 +228,137 @@ mount_hash(void *_m, const void *_key, unsigned int range)
}
/** Creates a new file_system structure.
* The gFileSystems lock must be hold when you call this function.
*/
static file_system *
new_file_system(const char *name, struct fs_calls *calls)
{
file_system *fs;
ASSERT_LOCKED_MUTEX(&gFileSystemsMutex);
fs = (struct file_system *)kmalloc(sizeof(struct file_system));
if (fs == NULL)
return NULL;
fs->name = name;
fs->calls = calls;
fs->image = -1;
fs->ref_count = 0;
// add it to the queue
fs->next = gFileSystems;
gFileSystems = fs;
return B_OK;
}
static status_t
unload_file_system(file_system *fs)
{
void (*uninit)();
// The image_id is invalid if it's an internal file system
if (fs->image < B_OK)
return B_OK;
uninit = (void *)elf_lookup_symbol(fs->image, "uninit_file_system");
if (uninit != NULL)
uninit();
// ToDo: unloading is not yet supported - we need a unload image_id first...
kfree(fs);
return B_OK;
}
static file_system *
load_file_system(const char *name)
{
char path[SYS_MAX_PATH_LEN];
struct fs_calls **calls;
uint32 *version;
void (*init)();
image_id image;
// search in the user directory
sprintf(path, "/boot/home/config/add-ons/kernel/file_systems/%s", name);
image = elf_load_kspace(path, "");
if (image == B_ENTRY_NOT_FOUND) {
// search in the system directory
sprintf(path, "/boot/addons/fs/%s", name);
//sprintf(path, "/boot/beos/system/add-ons/kernel/file_systems/%s", name);
image = elf_load_kspace(path, "");
}
if (image < B_OK)
return NULL;
init = (void *)elf_lookup_symbol(image, "init_file_system");
if (!init)
goto err;
init();
err:
elf_unload_kspace(path);
return NULL;
}
static status_t
put_file_system(file_system *fs)
{
status_t status;
mutex_lock(&gFileSystemsMutex);
if (--fs->ref_count == 0)
status = unload_file_system(fs);
else
status = B_OK;
mutex_unlock(&gFileSystemsMutex);
return status;
}
static file_system *
get_file_system(const char *name)
{
file_system *fs;
mutex_lock(&gFileSystemsMutex);
for (fs = gFileSystems; fs != NULL; fs = fs->next) {
if (!strcmp(name, fs->name))
break;
}
if (fs == NULL)
fs = load_file_system(name);
// if we find a suitable file system, increment its reference counter
if (fs)
fs->ref_count++;
mutex_unlock(&gFileSystemsMutex);
return fs;
}
static struct fs_mount *
find_mount(fs_id id)
find_mount(mount_id id)
{
struct fs_mount *mount;
mutex_lock(&gMountMutex);
mount = hash_lookup(mounts_table, &id);
mount = hash_lookup(gMountsTable, &id);
mutex_unlock(&gMountMutex);
@@ -245,7 +372,7 @@ vnode_compare(void *_v, const void *_key)
struct vnode *v = _v;
const struct vnode_hash_key *key = _key;
if (v->fs_id == key->fs_id && v->id == key->vnode_id)
if (v->mount_id == key->mount_id && v->id == key->vnode_id)
return 0;
return -1;
@@ -258,12 +385,12 @@ vnode_hash(void *_v, const void *_key, unsigned int range)
struct vnode *vnode = _v;
const struct vnode_hash_key *key = _key;
#define VHASH(fsid, vnid) (((uint32)((vnid)>>32) + (uint32)(vnid)) ^ (uint32)(fsid))
#define VHASH(mountid, vnodeid) (((uint32)((vnodeid) >> 32) + (uint32)(vnodeid)) ^ (uint32)(mountid))
if (vnode != NULL)
return (VHASH(vnode->fs_id, vnode->id) % range);
return (VHASH(vnode->mount_id, vnode->id) % range);
else
return (VHASH(key->fs_id, key->vnode_id) % range);
return (VHASH(key->mount_id, key->vnode_id) % range);
#undef VHASH
}
@@ -354,7 +481,7 @@ dec_vnode_ref_count(struct vnode *vnode, bool reenter)
remove_vnode_from_mount_list(vnode, vnode->mount);
mutex_lock(&gVnodeMutex);
hash_remove(vnode_table, vnode);
hash_remove(gVnodeTable, vnode);
mutex_unlock(&gVnodeMutex);
kfree(vnode);
@@ -377,29 +504,29 @@ inc_vnode_ref_count(struct vnode *vnode)
static struct vnode *
lookup_vnode(fs_id fsID, vnode_id vnodeID)
lookup_vnode(mount_id mountID, vnode_id vnodeID)
{
struct vnode_hash_key key;
key.fs_id = fsID;
key.mount_id = mountID;
key.vnode_id = vnodeID;
return hash_lookup(vnode_table, &key);
return hash_lookup(gVnodeTable, &key);
}
static int
get_vnode(fs_id fsID, vnode_id vnodeID, struct vnode **_vnode, int reenter)
get_vnode(mount_id mountID, vnode_id vnodeID, struct vnode **_vnode, int reenter)
{
struct vnode *vnode;
int err;
FUNCTION(("get_vnode: fsid %ld vnid 0x%Lx %p\n", fsID, vnodeID, _vnode));
FUNCTION(("get_vnode: mountid %ld vnid 0x%Lx %p\n", mountID, vnodeID, _vnode));
mutex_lock(&gVnodeMutex);
do {
vnode = lookup_vnode(fsID, vnodeID);
vnode = lookup_vnode(mountID, vnodeID);
if (vnode) {
if (vnode->busy) {
mutex_unlock(&gVnodeMutex);
@@ -421,15 +548,15 @@ get_vnode(fs_id fsID, vnode_id vnodeID, struct vnode **_vnode, int reenter)
err = ENOMEM;
goto err;
}
vnode->fs_id = fsID;
vnode->mount_id = mountID;
vnode->id = vnodeID;
vnode->mount = find_mount(fsID);
vnode->mount = find_mount(mountID);
if (!vnode->mount) {
err = ERR_INVALID_HANDLE;
goto err;
}
vnode->busy = true;
hash_insert(vnode_table, vnode);
hash_insert(gVnodeTable, vnode);
mutex_unlock(&gVnodeMutex);
add_vnode_to_mount_list(vnode, vnode->mount);
@@ -456,7 +583,7 @@ get_vnode(fs_id fsID, vnode_id vnodeID, struct vnode **_vnode, int reenter)
return B_OK;
err1:
hash_remove(vnode_table, vnode);
hash_remove(gVnodeTable, vnode);
err:
mutex_unlock(&gVnodeMutex);
if (vnode)
@@ -473,30 +600,15 @@ put_vnode(struct vnode *vnode)
}
static struct fs_container *
find_fs(const char *fs_name)
{
struct fs_container *fs = fs_list;
while (fs != NULL) {
if (strcmp(fs_name, fs->name) == 0)
return fs;
fs = fs->next;
}
return NULL;
}
static status_t
entry_ref_to_vnode(fs_id fsID,vnode_id directoryID,const char *name,struct vnode **_vnode)
entry_ref_to_vnode(mount_id mountID, vnode_id directoryID, const char *name, struct vnode **_vnode)
{
struct vnode *directory, *vnode;
vnode_id id;
int status;
int type;
status = get_vnode(fsID,directoryID,&directory,false);
status = get_vnode(mountID, directoryID, &directory, false);
if (status < 0)
return status;
@@ -508,13 +620,13 @@ entry_ref_to_vnode(fs_id fsID,vnode_id directoryID,const char *name,struct vnode
return status;
mutex_lock(&gVnodeMutex);
vnode = lookup_vnode(fsID, id);
vnode = lookup_vnode(mountID, id);
mutex_unlock(&gVnodeMutex);
if (vnode == NULL) {
// fs_lookup() should have left the vnode referenced, so chances
// are good that this will never happen
panic("entry_ref_to_vnode: could not lookup vnode (fsid 0x%lx vnid 0x%Lx)\n", fsID, id);
panic("entry_ref_to_vnode: could not lookup vnode (mountid 0x%lx vnid 0x%Lx)\n", mountID, id);
return B_ENTRY_NOT_FOUND;
}
@@ -576,12 +688,12 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink, stru
// from inside the filesystem, thus the vnode would have to be in the list and it's
// ref count incremented at this point
mutex_lock(&gVnodeMutex);
nextVnode = lookup_vnode(vnode->fs_id, vnodeID);
nextVnode = lookup_vnode(vnode->mount_id, vnodeID);
mutex_unlock(&gVnodeMutex);
if (!nextVnode) {
// pretty screwed up here
panic("path_to_vnode: could not lookup vnode (fsid 0x%lx vnid 0x%Lx)\n", vnode->fs_id, vnodeID);
panic("path_to_vnode: could not lookup vnode (mountid 0x%lx vnid 0x%Lx)\n", vnode->mount_id, vnodeID);
put_vnode(vnode);
return ERR_VFS_PATH_NOT_FOUND;
}
@@ -624,7 +736,7 @@ resolve_link_error:
while (*++path == '/')
;
vnode = root_vnode;
vnode = gRoot;
inc_vnode_ref_count(vnode);
}
@@ -672,7 +784,7 @@ path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode, bool kernel)
if (*path == '/') {
while (*++path == '/')
;
start = root_vnode;
start = gRoot;
inc_vnode_ref_count(start);
} else {
struct io_context *context = get_current_io_context(kernel);
@@ -764,11 +876,11 @@ dir_vnode_to_path(struct vnode *vnode, char *buffer, size_t bufferSize)
goto out;
mutex_lock(&gVnodeMutex);
parentVnode = lookup_vnode(vnode->fs_id, parentID);
parentVnode = lookup_vnode(vnode->mount_id, parentID);
mutex_unlock(&gVnodeMutex);
if (parentVnode == NULL) {
panic("dir_vnode_to_path: could not lookup vnode (fsid 0x%lx vnid 0x%Lx)\n", vnode->fs_id, parentID);
panic("dir_vnode_to_path: could not lookup vnode (mountid 0x%lx vnid 0x%Lx)\n", vnode->mount_id, parentID);
status = B_ENTRY_NOT_FOUND;
goto out;
}
@@ -1004,11 +1116,11 @@ get_new_fd(int type, struct vnode *vnode, fs_cookie cookie, int openMode, bool k
int
vfs_get_vnode(fs_id fsID, vnode_id vnodeID, fs_vnode *_fsNode)
vfs_get_vnode(mount_id mountID, vnode_id vnodeID, fs_vnode *_fsNode)
{
struct vnode *vnode;
int status = get_vnode(fsID, vnodeID, &vnode, true);
int status = get_vnode(mountID, vnodeID, &vnode, true);
if (status < 0)
return status;
@@ -1018,12 +1130,12 @@ vfs_get_vnode(fs_id fsID, vnode_id vnodeID, fs_vnode *_fsNode)
int
vfs_put_vnode(fs_id fsID, vnode_id vnodeID)
vfs_put_vnode(mount_id mountID, vnode_id vnodeID)
{
struct vnode *vnode;
mutex_lock(&gVnodeMutex);
vnode = lookup_vnode(fsID, vnodeID);
vnode = lookup_vnode(mountID, vnodeID);
mutex_unlock(&gVnodeMutex);
if (vnode)
@@ -1050,13 +1162,13 @@ vfs_vnode_release_ref(void *vnode)
int
vfs_remove_vnode(fs_id fsid, vnode_id vnid)
vfs_remove_vnode(mount_id mountID, vnode_id vnodeID)
{
struct vnode *vnode;
mutex_lock(&gVnodeMutex);
vnode = lookup_vnode(fsid, vnid);
vnode = lookup_vnode(mountID, vnodeID);
if (vnode)
vnode->delete_me = true;
@@ -1222,7 +1334,7 @@ vfs_new_io_context(void *_parentContext)
mutex_unlock(&parentContext->io_mutex);
} else {
context->cwd = root_vnode;
context->cwd = gRoot;
if (context->cwd)
inc_vnode_ref_count(context->cwd);
@@ -1477,29 +1589,6 @@ vfs_test(void)
#endif
image_id
vfs_load_fs_module(const char *name)
{
image_id id;
void (*bootstrap)();
char path[SYS_MAX_PATH_LEN];
// sprintf(path, "/boot/addons/fs/%s", name);
id = elf_load_kspace(path, "");
if (id < 0)
return id;
bootstrap = (void *)elf_lookup_symbol(id, "fs_bootstrap");
if (!bootstrap)
return ERR_VFS_INVALID_FS;
bootstrap();
return id;
}
int
vfs_bootstrap_all_filesystems(void)
{
@@ -1531,18 +1620,6 @@ vfs_bootstrap_all_filesystems(void)
if (err < 0)
panic("error mounting devfs\n");
fd = sys_open_dir("/boot/addons/fs");
if (fd >= 0) {
char buffer[sizeof(struct dirent) + 1 + SYS_MAX_NAME_LEN];
struct dirent *dirent = (struct dirent *)buffer;
ssize_t length;
while ((length = sys_read_dir(fd, dirent, sizeof(buffer), 1)) > 0)
vfs_load_fs_module(dirent->d_name);
sys_close(fd);
}
return B_NO_ERROR;
}
@@ -1550,22 +1627,20 @@ vfs_bootstrap_all_filesystems(void)
int
vfs_register_filesystem(const char *name, struct fs_calls *calls)
{
struct fs_container *container;
status_t status = B_OK;
file_system *fs;
container = (struct fs_container *)kmalloc(sizeof(struct fs_container));
if (container == NULL)
return ENOMEM;
if (name == NULL || *name == '\0' || calls == NULL)
return B_BAD_VALUE;
container->name = name;
container->calls = calls;
mutex_lock(&gFileSystemsMutex);
mutex_lock(&gRegisterMutex);
fs = new_file_system(name, calls);
if (fs == NULL)
status = B_NO_MEMORY;
container->next = fs_list;
fs_list = container;
mutex_unlock(&gRegisterMutex);
return 0;
mutex_unlock(&gFileSystemsMutex);
return status;
}
@@ -1574,32 +1649,32 @@ vfs_init(kernel_args *ka)
{
{
struct vnode *v;
vnode_table = hash_init(VNODE_HASH_TABLE_SIZE, (addr)&v->next - (addr)v,
gVnodeTable = hash_init(VNODE_HASH_TABLE_SIZE, (addr)&v->next - (addr)v,
&vnode_compare, &vnode_hash);
if (vnode_table == NULL)
if (gVnodeTable == NULL)
panic("vfs_init: error creating vnode hash table\n");
}
{
struct fs_mount *mount;
mounts_table = hash_init(MOUNTS_HASH_TABLE_SIZE, (addr)&mount->next - (addr)mount,
gMountsTable = hash_init(MOUNTS_HASH_TABLE_SIZE, (addr)&mount->next - (addr)mount,
&mount_compare, &mount_hash);
if (mounts_table == NULL)
if (gMountsTable == NULL)
panic("vfs_init: error creating mounts hash table\n");
}
fs_list = NULL;
root_vnode = NULL;
gFileSystems = NULL;
gRoot = NULL;
if (mutex_init(&gRegisterMutex, "vfs_lock") < 0)
panic("vfs_init: error allocating vfs lock\n");
if (mutex_init(&gFileSystemsMutex, "vfs_lock") < 0)
panic("vfs_init: error allocating file systems lock\n");
if (mutex_init(&gMountOpMutex, "vfs_mount_op_lock") < 0)
panic("vfs_init: error allocating vfs_mount_op lock\n");
panic("vfs_init: error allocating mount op lock\n");
if (mutex_init(&gMountMutex, "vfs_mount_lock") < 0)
panic("vfs_init: error allocating vfs_mount lock\n");
panic("vfs_init: error allocating mount lock\n");
if (mutex_init(&gVnodeMutex, "vfs_vnode_lock") < 0)
panic("vfs_init: error allocating vfs_vnode lock\n");
panic("vfs_init: error allocating vnode lock\n");
return 0;
}
@@ -1629,7 +1704,7 @@ create_vnode(struct vnode *directory, const char *name, int openMode, int perms,
return status;
mutex_lock(&gVnodeMutex);
vnode = lookup_vnode(directory->fs_id, newID);
vnode = lookup_vnode(directory->mount_id, newID);
mutex_unlock(&gVnodeMutex);
if (vnode == NULL) {
@@ -1703,19 +1778,19 @@ err:
static int
file_create_entry_ref(fs_id fsID, vnode_id directoryID, const char *name, int omode, int perms, bool kernel)
file_create_entry_ref(mount_id mountID, vnode_id directoryID, const char *name, int openMode, int perms, bool kernel)
{
struct vnode *directory,*vnode;
int status;
FUNCTION(("file_create_entry_ref: name = '%s', omode %x, perms %d, kernel %d\n", name, omode, perms, kernel));
FUNCTION(("file_create_entry_ref: name = '%s', omode %x, perms %d, kernel %d\n", name, openMode, perms, kernel));
// get directory to put the new file in
status = get_vnode(fsID,directoryID,&directory,false);
status = get_vnode(mountID, directoryID, &directory, false);
if (status < B_OK)
return status;
status = create_vnode(directory, name, omode, perms, kernel);
status = create_vnode(directory, name, openMode, perms, kernel);
put_vnode(directory);
return status;
@@ -1746,7 +1821,7 @@ file_create(char *path, int openMode, int perms, bool kernel)
static int
file_open_entry_ref(fs_id fsID, vnode_id directoryID, const char *name, int omode, bool kernel)
file_open_entry_ref(mount_id mountID, vnode_id directoryID, const char *name, int openMode, bool kernel)
{
struct vnode *vnode;
int status;
@@ -1757,11 +1832,11 @@ file_open_entry_ref(fs_id fsID, vnode_id directoryID, const char *name, int omod
FUNCTION(("file_open_entry_ref()\n"));
// get the vnode matching the entry_ref
status = entry_ref_to_vnode(fsID, directoryID, name, &vnode);
status = entry_ref_to_vnode(mountID, directoryID, name, &vnode);
if (status < B_OK)
return status;
status = open_vnode(vnode, omode, kernel);
status = open_vnode(vnode, openMode, kernel);
if (status < B_OK)
put_vnode(vnode);
@@ -1849,7 +1924,7 @@ file_seek(struct file_descriptor *descriptor, off_t pos, int seekType)
static int
dir_create_entry_ref(fs_id fsID, vnode_id parentID, const char *name, int perms, bool kernel)
dir_create_entry_ref(mount_id mountID, vnode_id parentID, const char *name, int perms, bool kernel)
{
struct vnode *vnode;
vnode_id newID;
@@ -1858,9 +1933,9 @@ dir_create_entry_ref(fs_id fsID, vnode_id parentID, const char *name, int perms,
if (name == NULL || *name == '\0')
return B_BAD_VALUE;
FUNCTION(("dir_create_entry_ref(dev = %ld, ino = %Ld, name = '%s', perms = %d)\n", fsID, parentID, name, perms));
FUNCTION(("dir_create_entry_ref(dev = %ld, ino = %Ld, name = '%s', perms = %d)\n", mountID, parentID, name, perms));
status = get_vnode(fsID, parentID, &vnode, kernel);
status = get_vnode(mountID, parentID, &vnode, kernel);
if (status < B_OK)
return status;
@@ -1899,7 +1974,7 @@ dir_create(char *path, int perms, bool kernel)
static int
dir_open_node_ref(fs_id fsID, vnode_id directoryID, bool kernel)
dir_open_node_ref(mount_id mountID, vnode_id directoryID, bool kernel)
{
struct vnode *vnode;
int status;
@@ -1907,7 +1982,7 @@ dir_open_node_ref(fs_id fsID, vnode_id directoryID, bool kernel)
FUNCTION(("dir_open_entry_ref()\n"));
// get the vnode matching the node_ref
status = get_vnode(fsID, directoryID, &vnode, false);
status = get_vnode(mountID, directoryID, &vnode, false);
if (status < B_OK)
return status;
@@ -1920,7 +1995,7 @@ dir_open_node_ref(fs_id fsID, vnode_id directoryID, bool kernel)
static int
dir_open_entry_ref(fs_id fsID, vnode_id parentID, const char *name, bool kernel)
dir_open_entry_ref(mount_id mountID, vnode_id parentID, const char *name, bool kernel)
{
struct vnode *vnode;
int status;
@@ -1931,7 +2006,7 @@ dir_open_entry_ref(fs_id fsID, vnode_id parentID, const char *name, bool kernel)
return B_BAD_VALUE;
// get the vnode matching the entry_ref
status = entry_ref_to_vnode(fsID, parentID, name, &vnode);
status = entry_ref_to_vnode(mountID, parentID, name, &vnode);
if (status < B_OK)
return status;
@@ -2236,7 +2311,7 @@ common_rename(char *path, char *newPath, bool kernel)
if (status < 0)
goto err;
if (fromVnode->fs_id != toVnode->fs_id) {
if (fromVnode->mount_id != toVnode->mount_id) {
status = B_CROSS_DEVICE_LINK;
goto err1;
}
@@ -2516,7 +2591,7 @@ attr_rename(int fromfd, const char *fromName, int tofd, const char *toName, bool
}
// are the files on the same volume?
if (fromVnode->fs_id != toVnode->fs_id) {
if (fromVnode->mount_id != toVnode->mount_id) {
status = B_CROSS_DEVICE_LINK;
goto err1;
}
@@ -2540,20 +2615,23 @@ err:
static int
fs_mount(char *path, const char *device, const char *fs_name, void *args, bool kernel)
fs_mount(char *path, const char *device, const char *fsName, void *args, bool kernel)
{
struct fs_mount *mount;
int err = 0;
struct vnode *covered_vnode = NULL;
vnode_id root_id;
int err = 0;
FUNCTION(("vfs_mount: entry. path = '%s', fs_name = '%s'\n", path, fs_name));
FUNCTION(("vfs_mount: entry. path = '%s', fs_name = '%s'\n", path, fsName));
if (device[0] == '\0' || fsName[0] == '\0')
return B_BAD_VALUE;
mutex_lock(&gMountOpMutex);
mount = (struct fs_mount *)kmalloc(sizeof(struct fs_mount));
if (mount == NULL) {
err = B_NO_MEMORY
if (mount == NULL) {
err = B_NO_MEMORY;
goto err;
}
@@ -2565,17 +2643,17 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
goto err1;
}
mount->fs = find_fs(fs_name);
mount->fs = get_file_system(fsName);
if (mount->fs == NULL) {
err = ERR_VFS_INVALID_FS;
goto err2;
}
recursive_lock_create(&mount->rlock);
mount->id = next_fsid++;
mount->id = gNextMountID++;
mount->unmounting = false;
if (!root_vnode) {
if (!gRoot) {
// we haven't mounted anything yet
if (strcmp(path, "/") != 0) {
err = ERR_VFS_GENERAL;
@@ -2601,7 +2679,7 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
// XXX insert check to make sure covered_vnode is a DIR, or maybe it's okay for it not to be
if (covered_vnode != root_vnode
if (covered_vnode != gRoot
&& covered_vnode->mount->root_vnode == covered_vnode) {
err = ERR_VFS_ALREADY_MOUNTPOINT;
goto err2;
@@ -2618,7 +2696,7 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
mutex_lock(&gMountMutex);
// insert mount struct into list
hash_insert(mounts_table, mount);
hash_insert(gMountsTable, mount);
mutex_unlock(&gMountMutex);
@@ -2630,8 +2708,8 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
if (mount->covers_vnode)
mount->covers_vnode->covered_by = mount->root_vnode;
if (!root_vnode)
root_vnode = mount->root_vnode;
if (!gRoot)
gRoot = mount->root_vnode;
mutex_unlock(&gMountOpMutex);
@@ -2641,9 +2719,10 @@ err5:
mount->fs->calls->unmount(mount->cookie);
err4:
if (mount->covers_vnode)
dec_vnode_ref_count(mount->covers_vnode, false);
put_vnode(mount->covers_vnode);
err3:
recursive_lock_destroy(&mount->rlock);
put_file_system(mount->fs);
err2:
kfree(mount->mount_point);
err1:
@@ -2670,13 +2749,13 @@ fs_unmount(char *path, bool kernel)
mutex_lock(&gMountOpMutex);
mount = find_mount(vnode->fs_id);
mount = find_mount(vnode->mount_id);
if (!mount)
panic("vfs_unmount: fsid_to_mount failed on root vnode @%p of mount\n", vnode);
panic("vfs_unmount: find_mount() failed on root vnode @%p of mount\n", vnode);
if (mount->root_vnode != vnode) {
// not mountpoint
dec_vnode_ref_count(vnode, false);
put_vnode(vnode);
err = ERR_VFS_NOT_MOUNTPOINT;
goto err;
}
@@ -2694,7 +2773,7 @@ fs_unmount(char *path, bool kernel)
if (vnode->busy || vnode->ref_count != 0) {
mount->root_vnode->ref_count += 2;
mutex_unlock(&gVnodeMutex);
dec_vnode_ref_count(mount->root_vnode, false);
put_vnode(mount->root_vnode);
err = EBUSY;
goto err;
@@ -2703,32 +2782,36 @@ fs_unmount(char *path, bool kernel)
/* we can safely continue, mark all of the vnodes busy and this mount
structure in unmounting state */
for (vnode = mount->vnodes_head; vnode; vnode = vnode->mount_next)
for (vnode = mount->vnodes_head; vnode; vnode = vnode->mount_next) {
if (vnode != mount->root_vnode)
vnode->busy = true;
}
mount->unmounting = true;
mutex_unlock(&gVnodeMutex);
mount->covers_vnode->covered_by = NULL;
dec_vnode_ref_count(mount->covers_vnode, false);
put_vnode(mount->covers_vnode);
/* release the ref on the root vnode twice */
dec_vnode_ref_count(mount->root_vnode, false);
dec_vnode_ref_count(mount->root_vnode, false);
put_vnode(mount->root_vnode);
put_vnode(mount->root_vnode);
// ToDo: when full vnode cache in place, will need to force
// a putvnode/removevnode here
/* remove the mount structure from the hash table */
mutex_lock(&gMountMutex);
hash_remove(mounts_table, mount);
hash_remove(gMountsTable, mount);
mutex_unlock(&gMountMutex);
mutex_unlock(&gMountOpMutex);
mount->fs->calls->unmount(mount->cookie);
// release the file system
put_file_system(mount->fs);
kfree(mount->mount_point);
kfree(mount);
@@ -2752,11 +2835,11 @@ fs_sync(void)
mutex_lock(&gMountOpMutex);
mutex_lock(&gMountMutex);
hash_open(mounts_table, &iter);
while ((mount = hash_next(mounts_table, &iter))) {
hash_open(gMountsTable, &iter);
while ((mount = hash_next(gMountsTable, &iter))) {
mount->fs->calls->sync(mount->cookie);
}
hash_close(mounts_table, &iter, false);
hash_close(gMountsTable, &iter, false);
mutex_unlock(&gMountMutex);
mutex_unlock(&gMountOpMutex);