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 { struct bootfs {
fs_id id; mount_id id;
mutex lock; mutex lock;
int next_vnode_id; int next_vnode_id;
void *vnode_list_hash; void *vnode_list_hash;
@@ -387,7 +387,7 @@ bootfs_create_vnode_tree(struct bootfs *fs, struct bootfs_vnode *root)
static status_t 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 *fs;
struct bootfs_vnode *v; struct bootfs_vnode *v;
+2 -2
View File
@@ -79,7 +79,7 @@ struct devfs_vnode {
}; };
struct devfs { struct devfs {
fs_id id; mount_id id;
mutex lock; mutex lock;
int next_vnode_id; int next_vnode_id;
void *vnode_list_hash; void *vnode_list_hash;
@@ -406,7 +406,7 @@ err2:
static status_t 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 *fs;
struct devfs_vnode *v; struct devfs_vnode *v;
+2 -2
View File
@@ -54,7 +54,7 @@ struct rootfs_vnode {
}; };
struct rootfs { struct rootfs {
fs_id id; mount_id id;
mutex lock; mutex lock;
vnode_id next_vnode_id; vnode_id next_vnode_id;
void *vnode_list_hash; void *vnode_list_hash;
@@ -264,7 +264,7 @@ err:
static status_t 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 *fs;
struct rootfs_vnode *vnode; struct rootfs_vnode *vnode;
+275 -192
View File
@@ -64,52 +64,65 @@
((addr)(x) < KERNEL_BASE || (addr)(x) > KERNEL_TOP) ((addr)(x) < KERNEL_BASE || (addr)(x) > KERNEL_TOP)
struct vnode { struct vnode {
struct vnode *next; struct vnode *next;
struct vnode *mount_prev; struct vnode *mount_prev;
struct vnode *mount_next; struct vnode *mount_next;
struct vm_cache *cache; struct vm_cache *cache;
fs_id fs_id; mount_id mount_id;
vnode_id id; vnode_id id;
fs_vnode private_node; fs_vnode private_node;
struct fs_mount *mount; struct fs_mount *mount;
struct vnode *covered_by; struct vnode *covered_by;
int32 ref_count; int32 ref_count;
bool delete_me; bool delete_me;
bool busy; bool busy;
}; };
struct vnode_hash_key { struct vnode_hash_key {
fs_id fs_id; mount_id mount_id;
vnode_id vnode_id; vnode_id vnode_id;
}; };
struct fs_container { typedef struct file_system {
struct fs_container *next; struct file_system *next;
struct fs_calls *calls; struct fs_calls *calls;
const char *name; const char *name;
}; image_id image;
int32 ref_count;
} file_system;
#define FS_CALL(vnode,call) (vnode->mount->fs->calls->call) #define FS_CALL(vnode,call) (vnode->mount->fs->calls->call)
static struct fs_container *fs_list;
struct fs_mount { struct fs_mount {
struct fs_mount *next; struct fs_mount *next;
struct fs_container *fs; file_system *fs;
fs_id id; mount_id id;
void *cookie; void *cookie;
char *mount_point; char *mount_point;
recursive_lock rlock; recursive_lock rlock;
struct vnode *root_vnode; struct vnode *root_vnode;
struct vnode *covers_vnode; struct vnode *covers_vnode;
struct vnode *vnodes_head; struct vnode *vnodes_head;
struct vnode *vnodes_tail; struct vnode *vnodes_tail;
bool unmounting; bool unmounting;
}; };
static mutex gRegisterMutex; static file_system *gFileSystems;
static mutex gFileSystemsMutex;
static mutex gMountMutex; static mutex gMountMutex;
static mutex gMountOpMutex; static mutex gMountOpMutex;
static mutex gVnodeMutex; 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 */ /* function declarations */
static int vfs_mount(char *path, const char *device, const char *fs_name, void *args, bool kernel); 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); static int vfs_unmount(char *path, bool kernel);
@@ -188,21 +201,12 @@ struct fd_ops attr_ops = {
attr_free_fd 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 static int
mount_compare(void *_m, const void *_key) mount_compare(void *_m, const void *_key)
{ {
struct fs_mount *mount = _m; struct fs_mount *mount = _m;
const fs_id *id = _key; const mount_id *id = _key;
if (mount->id == *id) if (mount->id == *id)
return 0; return 0;
@@ -215,7 +219,7 @@ static unsigned int
mount_hash(void *_m, const void *_key, unsigned int range) mount_hash(void *_m, const void *_key, unsigned int range)
{ {
struct fs_mount *mount = _m; struct fs_mount *mount = _m;
const fs_id *id = _key; const mount_id *id = _key;
if (mount) if (mount)
return mount->id % range; 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 * static struct fs_mount *
find_mount(fs_id id) find_mount(mount_id id)
{ {
struct fs_mount *mount; struct fs_mount *mount;
mutex_lock(&gMountMutex); mutex_lock(&gMountMutex);
mount = hash_lookup(mounts_table, &id); mount = hash_lookup(gMountsTable, &id);
mutex_unlock(&gMountMutex); mutex_unlock(&gMountMutex);
@@ -245,7 +372,7 @@ vnode_compare(void *_v, const void *_key)
struct vnode *v = _v; struct vnode *v = _v;
const struct vnode_hash_key *key = _key; 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 0;
return -1; return -1;
@@ -258,12 +385,12 @@ vnode_hash(void *_v, const void *_key, unsigned int range)
struct vnode *vnode = _v; struct vnode *vnode = _v;
const struct vnode_hash_key *key = _key; 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) if (vnode != NULL)
return (VHASH(vnode->fs_id, vnode->id) % range); return (VHASH(vnode->mount_id, vnode->id) % range);
else else
return (VHASH(key->fs_id, key->vnode_id) % range); return (VHASH(key->mount_id, key->vnode_id) % range);
#undef VHASH #undef VHASH
} }
@@ -354,7 +481,7 @@ dec_vnode_ref_count(struct vnode *vnode, bool reenter)
remove_vnode_from_mount_list(vnode, vnode->mount); remove_vnode_from_mount_list(vnode, vnode->mount);
mutex_lock(&gVnodeMutex); mutex_lock(&gVnodeMutex);
hash_remove(vnode_table, vnode); hash_remove(gVnodeTable, vnode);
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
kfree(vnode); kfree(vnode);
@@ -377,29 +504,29 @@ inc_vnode_ref_count(struct vnode *vnode)
static struct 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; struct vnode_hash_key key;
key.fs_id = fsID; key.mount_id = mountID;
key.vnode_id = vnodeID; key.vnode_id = vnodeID;
return hash_lookup(vnode_table, &key); return hash_lookup(gVnodeTable, &key);
} }
static int 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; struct vnode *vnode;
int err; 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); mutex_lock(&gVnodeMutex);
do { do {
vnode = lookup_vnode(fsID, vnodeID); vnode = lookup_vnode(mountID, vnodeID);
if (vnode) { if (vnode) {
if (vnode->busy) { if (vnode->busy) {
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
@@ -421,15 +548,15 @@ get_vnode(fs_id fsID, vnode_id vnodeID, struct vnode **_vnode, int reenter)
err = ENOMEM; err = ENOMEM;
goto err; goto err;
} }
vnode->fs_id = fsID; vnode->mount_id = mountID;
vnode->id = vnodeID; vnode->id = vnodeID;
vnode->mount = find_mount(fsID); vnode->mount = find_mount(mountID);
if (!vnode->mount) { if (!vnode->mount) {
err = ERR_INVALID_HANDLE; err = ERR_INVALID_HANDLE;
goto err; goto err;
} }
vnode->busy = true; vnode->busy = true;
hash_insert(vnode_table, vnode); hash_insert(gVnodeTable, vnode);
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
add_vnode_to_mount_list(vnode, vnode->mount); 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; return B_OK;
err1: err1:
hash_remove(vnode_table, vnode); hash_remove(gVnodeTable, vnode);
err: err:
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
if (vnode) 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 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; struct vnode *directory, *vnode;
vnode_id id; vnode_id id;
int status; int status;
int type; int type;
status = get_vnode(fsID,directoryID,&directory,false); status = get_vnode(mountID, directoryID, &directory, false);
if (status < 0) if (status < 0)
return status; return status;
@@ -508,13 +620,13 @@ entry_ref_to_vnode(fs_id fsID,vnode_id directoryID,const char *name,struct vnode
return status; return status;
mutex_lock(&gVnodeMutex); mutex_lock(&gVnodeMutex);
vnode = lookup_vnode(fsID, id); vnode = lookup_vnode(mountID, id);
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
if (vnode == NULL) { if (vnode == NULL) {
// fs_lookup() should have left the vnode referenced, so chances // fs_lookup() should have left the vnode referenced, so chances
// are good that this will never happen // 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; 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 // from inside the filesystem, thus the vnode would have to be in the list and it's
// ref count incremented at this point // ref count incremented at this point
mutex_lock(&gVnodeMutex); mutex_lock(&gVnodeMutex);
nextVnode = lookup_vnode(vnode->fs_id, vnodeID); nextVnode = lookup_vnode(vnode->mount_id, vnodeID);
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
if (!nextVnode) { if (!nextVnode) {
// pretty screwed up here // 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); put_vnode(vnode);
return ERR_VFS_PATH_NOT_FOUND; return ERR_VFS_PATH_NOT_FOUND;
} }
@@ -624,7 +736,7 @@ resolve_link_error:
while (*++path == '/') while (*++path == '/')
; ;
vnode = root_vnode; vnode = gRoot;
inc_vnode_ref_count(vnode); inc_vnode_ref_count(vnode);
} }
@@ -672,7 +784,7 @@ path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode, bool kernel)
if (*path == '/') { if (*path == '/') {
while (*++path == '/') while (*++path == '/')
; ;
start = root_vnode; start = gRoot;
inc_vnode_ref_count(start); inc_vnode_ref_count(start);
} else { } else {
struct io_context *context = get_current_io_context(kernel); 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; goto out;
mutex_lock(&gVnodeMutex); mutex_lock(&gVnodeMutex);
parentVnode = lookup_vnode(vnode->fs_id, parentID); parentVnode = lookup_vnode(vnode->mount_id, parentID);
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
if (parentVnode == NULL) { 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; status = B_ENTRY_NOT_FOUND;
goto out; goto out;
} }
@@ -1004,11 +1116,11 @@ get_new_fd(int type, struct vnode *vnode, fs_cookie cookie, int openMode, bool k
int 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; struct vnode *vnode;
int status = get_vnode(fsID, vnodeID, &vnode, true); int status = get_vnode(mountID, vnodeID, &vnode, true);
if (status < 0) if (status < 0)
return status; return status;
@@ -1018,12 +1130,12 @@ vfs_get_vnode(fs_id fsID, vnode_id vnodeID, fs_vnode *_fsNode)
int int
vfs_put_vnode(fs_id fsID, vnode_id vnodeID) vfs_put_vnode(mount_id mountID, vnode_id vnodeID)
{ {
struct vnode *vnode; struct vnode *vnode;
mutex_lock(&gVnodeMutex); mutex_lock(&gVnodeMutex);
vnode = lookup_vnode(fsID, vnodeID); vnode = lookup_vnode(mountID, vnodeID);
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
if (vnode) if (vnode)
@@ -1050,13 +1162,13 @@ vfs_vnode_release_ref(void *vnode)
int int
vfs_remove_vnode(fs_id fsid, vnode_id vnid) vfs_remove_vnode(mount_id mountID, vnode_id vnodeID)
{ {
struct vnode *vnode; struct vnode *vnode;
mutex_lock(&gVnodeMutex); mutex_lock(&gVnodeMutex);
vnode = lookup_vnode(fsid, vnid); vnode = lookup_vnode(mountID, vnodeID);
if (vnode) if (vnode)
vnode->delete_me = true; vnode->delete_me = true;
@@ -1222,7 +1334,7 @@ vfs_new_io_context(void *_parentContext)
mutex_unlock(&parentContext->io_mutex); mutex_unlock(&parentContext->io_mutex);
} else { } else {
context->cwd = root_vnode; context->cwd = gRoot;
if (context->cwd) if (context->cwd)
inc_vnode_ref_count(context->cwd); inc_vnode_ref_count(context->cwd);
@@ -1477,29 +1589,6 @@ vfs_test(void)
#endif #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 int
vfs_bootstrap_all_filesystems(void) vfs_bootstrap_all_filesystems(void)
{ {
@@ -1531,18 +1620,6 @@ vfs_bootstrap_all_filesystems(void)
if (err < 0) if (err < 0)
panic("error mounting devfs\n"); 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; return B_NO_ERROR;
} }
@@ -1550,22 +1627,20 @@ vfs_bootstrap_all_filesystems(void)
int int
vfs_register_filesystem(const char *name, struct fs_calls *calls) 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 (name == NULL || *name == '\0' || calls == NULL)
if (container == NULL) return B_BAD_VALUE;
return ENOMEM;
container->name = name; mutex_lock(&gFileSystemsMutex);
container->calls = calls;
mutex_lock(&gRegisterMutex); fs = new_file_system(name, calls);
if (fs == NULL)
status = B_NO_MEMORY;
container->next = fs_list; mutex_unlock(&gFileSystemsMutex);
fs_list = container; return status;
mutex_unlock(&gRegisterMutex);
return 0;
} }
@@ -1574,32 +1649,32 @@ vfs_init(kernel_args *ka)
{ {
{ {
struct vnode *v; 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); &vnode_compare, &vnode_hash);
if (vnode_table == NULL) if (gVnodeTable == NULL)
panic("vfs_init: error creating vnode hash table\n"); panic("vfs_init: error creating vnode hash table\n");
} }
{ {
struct fs_mount *mount; 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); &mount_compare, &mount_hash);
if (mounts_table == NULL) if (gMountsTable == NULL)
panic("vfs_init: error creating mounts hash table\n"); panic("vfs_init: error creating mounts hash table\n");
} }
fs_list = NULL; gFileSystems = NULL;
root_vnode = NULL; gRoot = NULL;
if (mutex_init(&gRegisterMutex, "vfs_lock") < 0) if (mutex_init(&gFileSystemsMutex, "vfs_lock") < 0)
panic("vfs_init: error allocating vfs lock\n"); panic("vfs_init: error allocating file systems lock\n");
if (mutex_init(&gMountOpMutex, "vfs_mount_op_lock") < 0) 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) 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) 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; return 0;
} }
@@ -1629,7 +1704,7 @@ create_vnode(struct vnode *directory, const char *name, int openMode, int perms,
return status; return status;
mutex_lock(&gVnodeMutex); mutex_lock(&gVnodeMutex);
vnode = lookup_vnode(directory->fs_id, newID); vnode = lookup_vnode(directory->mount_id, newID);
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
if (vnode == NULL) { if (vnode == NULL) {
@@ -1703,19 +1778,19 @@ err:
static int 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; struct vnode *directory,*vnode;
int status; 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 // 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) if (status < B_OK)
return status; return status;
status = create_vnode(directory, name, omode, perms, kernel); status = create_vnode(directory, name, openMode, perms, kernel);
put_vnode(directory); put_vnode(directory);
return status; return status;
@@ -1746,7 +1821,7 @@ file_create(char *path, int openMode, int perms, bool kernel)
static int 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; struct vnode *vnode;
int status; 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")); FUNCTION(("file_open_entry_ref()\n"));
// get the vnode matching the entry_ref // 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) if (status < B_OK)
return status; return status;
status = open_vnode(vnode, omode, kernel); status = open_vnode(vnode, openMode, kernel);
if (status < B_OK) if (status < B_OK)
put_vnode(vnode); put_vnode(vnode);
@@ -1849,7 +1924,7 @@ file_seek(struct file_descriptor *descriptor, off_t pos, int seekType)
static int 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; struct vnode *vnode;
vnode_id newID; 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') if (name == NULL || *name == '\0')
return B_BAD_VALUE; 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) if (status < B_OK)
return status; return status;
@@ -1899,7 +1974,7 @@ dir_create(char *path, int perms, bool kernel)
static int 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; struct vnode *vnode;
int status; int status;
@@ -1907,7 +1982,7 @@ dir_open_node_ref(fs_id fsID, vnode_id directoryID, bool kernel)
FUNCTION(("dir_open_entry_ref()\n")); FUNCTION(("dir_open_entry_ref()\n"));
// get the vnode matching the node_ref // 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) if (status < B_OK)
return status; return status;
@@ -1920,7 +1995,7 @@ dir_open_node_ref(fs_id fsID, vnode_id directoryID, bool kernel)
static int 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; struct vnode *vnode;
int status; 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; return B_BAD_VALUE;
// get the vnode matching the entry_ref // 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) if (status < B_OK)
return status; return status;
@@ -2236,7 +2311,7 @@ common_rename(char *path, char *newPath, bool kernel)
if (status < 0) if (status < 0)
goto err; goto err;
if (fromVnode->fs_id != toVnode->fs_id) { if (fromVnode->mount_id != toVnode->mount_id) {
status = B_CROSS_DEVICE_LINK; status = B_CROSS_DEVICE_LINK;
goto err1; 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? // 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; status = B_CROSS_DEVICE_LINK;
goto err1; goto err1;
} }
@@ -2540,20 +2615,23 @@ err:
static int 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; struct fs_mount *mount;
int err = 0;
struct vnode *covered_vnode = NULL; struct vnode *covered_vnode = NULL;
vnode_id root_id; 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); mutex_lock(&gMountOpMutex);
mount = (struct fs_mount *)kmalloc(sizeof(struct fs_mount)); mount = (struct fs_mount *)kmalloc(sizeof(struct fs_mount));
if (mount == NULL) { if (mount == NULL) {
err = B_NO_MEMORY err = B_NO_MEMORY;
goto err; goto err;
} }
@@ -2565,17 +2643,17 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
goto err1; goto err1;
} }
mount->fs = find_fs(fs_name); mount->fs = get_file_system(fsName);
if (mount->fs == NULL) { if (mount->fs == NULL) {
err = ERR_VFS_INVALID_FS; err = ERR_VFS_INVALID_FS;
goto err2; goto err2;
} }
recursive_lock_create(&mount->rlock); recursive_lock_create(&mount->rlock);
mount->id = next_fsid++; mount->id = gNextMountID++;
mount->unmounting = false; mount->unmounting = false;
if (!root_vnode) { if (!gRoot) {
// we haven't mounted anything yet // we haven't mounted anything yet
if (strcmp(path, "/") != 0) { if (strcmp(path, "/") != 0) {
err = ERR_VFS_GENERAL; 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 // 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) { && covered_vnode->mount->root_vnode == covered_vnode) {
err = ERR_VFS_ALREADY_MOUNTPOINT; err = ERR_VFS_ALREADY_MOUNTPOINT;
goto err2; goto err2;
@@ -2618,7 +2696,7 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
mutex_lock(&gMountMutex); mutex_lock(&gMountMutex);
// insert mount struct into list // insert mount struct into list
hash_insert(mounts_table, mount); hash_insert(gMountsTable, mount);
mutex_unlock(&gMountMutex); 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) if (mount->covers_vnode)
mount->covers_vnode->covered_by = mount->root_vnode; mount->covers_vnode->covered_by = mount->root_vnode;
if (!root_vnode) if (!gRoot)
root_vnode = mount->root_vnode; gRoot = mount->root_vnode;
mutex_unlock(&gMountOpMutex); mutex_unlock(&gMountOpMutex);
@@ -2641,9 +2719,10 @@ err5:
mount->fs->calls->unmount(mount->cookie); mount->fs->calls->unmount(mount->cookie);
err4: err4:
if (mount->covers_vnode) if (mount->covers_vnode)
dec_vnode_ref_count(mount->covers_vnode, false); put_vnode(mount->covers_vnode);
err3: err3:
recursive_lock_destroy(&mount->rlock); recursive_lock_destroy(&mount->rlock);
put_file_system(mount->fs);
err2: err2:
kfree(mount->mount_point); kfree(mount->mount_point);
err1: err1:
@@ -2670,13 +2749,13 @@ fs_unmount(char *path, bool kernel)
mutex_lock(&gMountOpMutex); mutex_lock(&gMountOpMutex);
mount = find_mount(vnode->fs_id); mount = find_mount(vnode->mount_id);
if (!mount) 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) { if (mount->root_vnode != vnode) {
// not mountpoint // not mountpoint
dec_vnode_ref_count(vnode, false); put_vnode(vnode);
err = ERR_VFS_NOT_MOUNTPOINT; err = ERR_VFS_NOT_MOUNTPOINT;
goto err; goto err;
} }
@@ -2694,7 +2773,7 @@ fs_unmount(char *path, bool kernel)
if (vnode->busy || vnode->ref_count != 0) { if (vnode->busy || vnode->ref_count != 0) {
mount->root_vnode->ref_count += 2; mount->root_vnode->ref_count += 2;
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
dec_vnode_ref_count(mount->root_vnode, false); put_vnode(mount->root_vnode);
err = EBUSY; err = EBUSY;
goto err; 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 /* we can safely continue, mark all of the vnodes busy and this mount
structure in unmounting state */ 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) if (vnode != mount->root_vnode)
vnode->busy = true; vnode->busy = true;
}
mount->unmounting = true; mount->unmounting = true;
mutex_unlock(&gVnodeMutex); mutex_unlock(&gVnodeMutex);
mount->covers_vnode->covered_by = NULL; 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 */ /* release the ref on the root vnode twice */
dec_vnode_ref_count(mount->root_vnode, false); put_vnode(mount->root_vnode);
dec_vnode_ref_count(mount->root_vnode, false); put_vnode(mount->root_vnode);
// ToDo: when full vnode cache in place, will need to force // ToDo: when full vnode cache in place, will need to force
// a putvnode/removevnode here // a putvnode/removevnode here
/* remove the mount structure from the hash table */ /* remove the mount structure from the hash table */
mutex_lock(&gMountMutex); mutex_lock(&gMountMutex);
hash_remove(mounts_table, mount); hash_remove(gMountsTable, mount);
mutex_unlock(&gMountMutex); mutex_unlock(&gMountMutex);
mutex_unlock(&gMountOpMutex); mutex_unlock(&gMountOpMutex);
mount->fs->calls->unmount(mount->cookie); mount->fs->calls->unmount(mount->cookie);
// release the file system
put_file_system(mount->fs);
kfree(mount->mount_point); kfree(mount->mount_point);
kfree(mount); kfree(mount);
@@ -2752,11 +2835,11 @@ fs_sync(void)
mutex_lock(&gMountOpMutex); mutex_lock(&gMountOpMutex);
mutex_lock(&gMountMutex); mutex_lock(&gMountMutex);
hash_open(mounts_table, &iter); hash_open(gMountsTable, &iter);
while ((mount = hash_next(mounts_table, &iter))) { while ((mount = hash_next(gMountsTable, &iter))) {
mount->fs->calls->sync(mount->cookie); mount->fs->calls->sync(mount->cookie);
} }
hash_close(mounts_table, &iter, false); hash_close(gMountsTable, &iter, false);
mutex_unlock(&gMountMutex); mutex_unlock(&gMountMutex);
mutex_unlock(&gMountOpMutex); mutex_unlock(&gMountOpMutex);