From e04fced505f274f2a5600efa5eaa874ecc74f211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 25 Sep 2002 14:10:50 +0000 Subject: [PATCH] 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 --- src/kernel/core/fs/bootfs.c | 4 +- src/kernel/core/fs/devfs.c | 4 +- src/kernel/core/fs/rootfs.c | 4 +- src/kernel/core/fs/vfs.c | 467 +++++++++++++++++++++--------------- 4 files changed, 281 insertions(+), 198 deletions(-) diff --git a/src/kernel/core/fs/bootfs.c b/src/kernel/core/fs/bootfs.c index 86a211c508..9d210132bb 100755 --- a/src/kernel/core/fs/bootfs.c +++ b/src/kernel/core/fs/bootfs.c @@ -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; diff --git a/src/kernel/core/fs/devfs.c b/src/kernel/core/fs/devfs.c index fca256f91f..8e5996303f 100755 --- a/src/kernel/core/fs/devfs.c +++ b/src/kernel/core/fs/devfs.c @@ -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; diff --git a/src/kernel/core/fs/rootfs.c b/src/kernel/core/fs/rootfs.c index 0c80c8073f..f9aab43537 100755 --- a/src/kernel/core/fs/rootfs.c +++ b/src/kernel/core/fs/rootfs.c @@ -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; diff --git a/src/kernel/core/fs/vfs.c b/src/kernel/core/fs/vfs.c index bc68050d1a..c2566b244c 100755 --- a/src/kernel/core/fs/vfs.c +++ b/src/kernel/core/fs/vfs.c @@ -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);