From f09ed66826b4223c034c6385527a33d5953858c5 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 18 Jan 2005 22:00:00 -0500 Subject: [PATCH] Import backup from 2005-01-18 --- kernel/fs/ext2.c | 174 ++++++++++++++++------------------- kernel/fs/ext2.h | 16 ++-- kernel/fs/vfs.c | 229 +++++++---------------------------------------- kernel/fs/vfs.h | 42 ++++----- kernel/kernel.c | 4 +- 5 files changed, 137 insertions(+), 328 deletions(-) diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c index cdacdfa..510bb1d 100644 --- a/kernel/fs/ext2.c +++ b/kernel/fs/ext2.c @@ -18,6 +18,7 @@ */ vfs_fs_t ext2_driver = {ext2_mount_super, ext2_umount_super, ext2_stat, + ext2__get_root_dir_inode, ext2__open_dir, ext2__read_dir, ext2__close_dir, ext2__open_file, ext2__read_file, ext2__close_file, ext2__open_block_file, ext2__read_block_file, ext2__block_file_seek, ext2__close_block_file}; @@ -36,93 +37,6 @@ int ext2_init(int fsID) } -// mount the superblock of the filesystem and return a pointer to it, if valid -void *ext2_mount_super(major_t major, minor_t minor) -{ - ext2_super_block_t *super = kmalloc(1024); - block_read(major, minor, 2, 2, super); - if (super->s_magic != EXT2_MAGIC) // not an ext2 filesystem - { - kfree(super); - return NULL; - } - return super; -} - - -// called when we are unmounting this filesystem mount -int ext2_umount_super(vfs_mount_t *mount) -{ - return kfree(mount->super); // free memory that the superblock was taking -} - - -// stat a file, return a structure of info about it -int ext2_stat(vfs_mount_t *mount, char *file, vfs_stat_t *stat) -{ - u32_t inode_number = ext2_get_inode_number(mount, file); - if (!inode_number) - return -1; - ext2_inode_t *inode = New(ext2_inode_t); - if ( ext2_read_inode(mount, inode_number, inode) ) - { - kfree(inode); - return -2; - } - - stat->dev = 0; - switch(inode->i_mode & EXT2_I_MODE_TYPE_MASK) - { - case EXT2_I_MODE_FIFO: stat->type = VFS_FT_FIFO; break; - case EXT2_I_MODE_CHAR: stat->type = VFS_FT_CHAR; stat->dev = inode->i_block[0]; break; - case EXT2_I_MODE_DIR: stat->type = VFS_FT_DIR; break; - case EXT2_I_MODE_BLOCK: stat->type = VFS_FT_BLOCK; stat->dev = inode->i_block[0]; break; - case EXT2_I_MODE_FILE: stat->type = VFS_FT_FILE; break; - case EXT2_I_MODE_SYM: stat->type = VFS_FT_SYMLINK; break; - case EXT2_I_MODE_SOCK: stat->type = VFS_FT_SOCK; break; - default: stat->type = VFS_FT_UNKNOWN; break; - } - stat->size = inode->i_size; - stat->inode = inode_number; - stat->permissions = inode->i_mode & EXT2_I_MODE_ATTR_MASK; - stat->uid = inode->i_uid; - stat->gid = inode->i_gid; - stat->atime = inode->i_atime; - stat->mtime = inode->i_mtime; - stat->ctime = inode->i_ctime; - stat->links = inode->i_links_count; - kfree(inode); - return 0; -} - -// returns the inode number that the given file name points to -u32_t ext2_get_inode_number(vfs_mount_t *mount, char *file) -{ - if (file[0] != '/') - return 0; - if (strlen(file) == 1) - return 2; // root inode number - char *fil = kmalloc(strlen(file)); - strcpy(fil, file + 1); - int subs = str_split(fil, '/'); // how many levels are there to do lookups on? - u32_t on_dir = 2; // start on the root directory - char *lookupName = fil; - ext2_dir_entry_t dentry; - while (subs--) - { - if (ext2_dir_lookup(mount, on_dir, lookupName, &dentry)) - { - kfree(fil); - return 0; // entry not found - } - on_dir = dentry.inode; - lookupName = str_advance(lookupName); - } - kfree(fil); - return on_dir; -} - - // lookup a file name in a directory and store the directory entry for it int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry) { @@ -391,13 +305,77 @@ u32_t ext2_alloc_inode(vfs_mount_t *mount) /***************** VFS INTERFACE FUNCTIONS *******************/ -// VFS interface function to open a directory -int ext2__open_dir(vfs_mount_t *mount, char *file, vfs_open_file_t *dir) +// mount the superblock of the filesystem and return a pointer to it, if valid +void *ext2_mount_super(major_t major, minor_t minor) { - u32_t dir_inode = ext2_get_inode_number(mount, file); - if (!dir_inode) + ext2_super_block_t *super = kmalloc(1024); + block_read(major, minor, 2, 2, super); + if (super->s_magic != EXT2_MAGIC) // not an ext2 filesystem + { + kfree(super); + return NULL; + } + return super; +} + + +// called when we are unmounting this filesystem mount +int ext2_umount_super(vfs_mount_t *mount) +{ + return kfree(mount->super); // free memory that the superblock was taking +} + + +// stat a file, return a structure of info about it +int ext2_stat(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat) +{ + if (ext2_inode_status(mount, inode_number) != 1) return -1; - ext2_open_dir_t *open_dir = ext2_open_dir(mount, dir_inode); + ext2_inode_t *inode = New(ext2_inode_t); + if ( ext2_read_inode(mount, inode_number, inode) ) + { + kfree(inode); + return -2; + } + + stat->dev = 0; + switch(inode->i_mode & EXT2_I_MODE_TYPE_MASK) + { + case EXT2_I_MODE_FIFO: stat->type = VFS_FT_FIFO; break; + case EXT2_I_MODE_CHAR: stat->type = VFS_FT_CHAR; stat->dev = inode->i_block[0]; break; + case EXT2_I_MODE_DIR: stat->type = VFS_FT_DIR; break; + case EXT2_I_MODE_BLOCK: stat->type = VFS_FT_BLOCK; stat->dev = inode->i_block[0]; break; + case EXT2_I_MODE_FILE: stat->type = VFS_FT_FILE; break; + case EXT2_I_MODE_SYM: stat->type = VFS_FT_SYMLINK; break; + case EXT2_I_MODE_SOCK: stat->type = VFS_FT_SOCK; break; + default: stat->type = VFS_FT_UNKNOWN; break; + } + stat->size = inode->i_size; + stat->inode = inode_number; + stat->permissions = inode->i_mode & EXT2_I_MODE_ATTR_MASK; + stat->uid = inode->i_uid; + stat->gid = inode->i_gid; + stat->atime = inode->i_atime; + stat->mtime = inode->i_mtime; + stat->ctime = inode->i_ctime; + stat->links = inode->i_links_count; + kfree(inode); + return 0; +} + +// what is the inode of the root directory? +u32_t ext2__get_root_dir_inode(vfs_mount_t *mount) +{ + return 2; +} + + +// VFS interface function to open a directory +int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir) +{ + if (ext2_inode_status(mount, inode_number) != 1) + return -1; + ext2_open_dir_t *open_dir = ext2_open_dir(mount, inode_number); if (!open_dir) return -2; dir->fs_data = open_dir; @@ -413,6 +391,7 @@ int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *de return status; memcpy(dentry->name, t_dentry.name, t_dentry.name_length); dentry->name[t_dentry.name_length] = 0; + dentry->inode_number = t_dentry.inode; return 0; } @@ -424,8 +403,10 @@ int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir) // VFS interface function to open a file for reading a byte at a time -int ext2__open_file(vfs_mount_t *mount, char *file, vfs_open_file_t *open_file) +int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file) { + if (ext2_inode_status(mount, inode_number) != 1) + return -1; return 0; } @@ -443,12 +424,11 @@ int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file) // VFS interface function to open a file for reading 512-byte blocks at a time -int ext2__open_block_file(vfs_mount_t *mount, char *file, vfs_open_file_t *open_file) +int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file) { - u32_t file_inode = ext2_get_inode_number(mount, file); - if (!file_inode) + if (ext2_inode_status(mount, inode_number) != 1) return -1; - ext2_open_inode_t *open_inode = ext2_open_inode(mount, file_inode); + ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number); if (!open_inode) return -2; if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_FILE) diff --git a/kernel/fs/ext2.h b/kernel/fs/ext2.h index 09bc164..0d99495 100644 --- a/kernel/fs/ext2.h +++ b/kernel/fs/ext2.h @@ -182,16 +182,12 @@ static inline u32_t ext2_FSToDiskBlock(u32_t block, ext2_super_block_t *super) int ext2_init(int fsID); -void *ext2_mount_super(major_t major, minor_t minor); -int ext2_umount_super(vfs_mount_t *mount); int ext2_read_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat); ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group); -int ext2_stat(vfs_mount_t *mount, char *file, vfs_stat_t *stat); ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number); int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode); int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block); u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode); -u32_t ext2_get_inode_number(vfs_mount_t *mount, char *file); int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number); int ext2_inode_status(vfs_mount_t *mount, u32_t inode_number); int ext2_block_status(vfs_mount_t *mount, u32_t block_number); @@ -203,15 +199,21 @@ int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_ int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir); int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry); -int ext2__open_dir(vfs_mount_t *mount, char *file, vfs_open_file_t *dir); + +void *ext2_mount_super(major_t major, minor_t minor); +int ext2_umount_super(vfs_mount_t *mount); +int ext2_stat(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat); +u32_t ext2__get_root_dir_inode(vfs_mount_t *mount); + +int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir); int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry); int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir); -int ext2__open_file(vfs_mount_t *mount, char *file, vfs_open_file_t *open_file); +int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file); int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file); int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file); -int ext2__open_block_file(vfs_mount_t *mount, char *file, vfs_open_file_t *open_file); +int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file); int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer); int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number); int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file); diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index d5e0c5f..00f8056 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -12,7 +12,7 @@ #include "lang/lang.h" vfs_fs_t *fses[VFS_MAX_FS]; // a vfs_fs structure for every filesystem we support -vfs_node_t *vfsMountTree; // points to the root node ('/') of the VFS Mount Tree +vfs_mount_node_t *mounts; // basic initialization routine, init all filesystem drivers int vfs_init() @@ -36,208 +36,42 @@ int vfs_register_fs(int fsn, vfs_fs_t *fs) // called to mount a block device with a certain filesystem to a part of our VFS Mount Tree int vfs_mount(major_t maj, minor_t min, int fsType, char *mountPoint) { - if (mountPoint[0] != '/') - return -1; // mount point must be absolute - int l = strlen(mountPoint); - if (l < 1) - return -7; // mount point must be non-null string - if (mountPoint[l-1] != '/') - return -8; // mount point must end with a '/' character if (fsType < 0 || fsType >= VFS_MAX_FS || !fses[fsType]) - return -2; // invalid filesystem type - if (vfs_find_mount(mountPoint)) - return -5; // mount point already mounted - void *super = fses[fsType]->mount_super(maj, min); - if (!super) - return -6; // filesystem superblock not correctly identified - vfs_mount_t *mnt = New(vfs_mount_t); - if (!mnt) - return -3; // could not allocate memory - mnt->refs = 0; - mnt->fs = fsType; - mnt->major = maj; - mnt->minor = min; - mnt->super = super; - if (vfs_add_mount(mnt, mountPoint)) + return -1; // invalid filesystem type + if (!strcmp("/", mountPoint)) { - kfree(mnt); - return -4; // could not add mount - } - - return 0; -} - -// invoked by vfs_mount to do the "dirty work" of adding the nodes to the tree -int vfs_add_mount(vfs_mount_t *mnt, char *mountPoint) -{ - vfs_node_t *node = vfsMountTree; - char *mp = mountPoint; - if (!vfsMountTree) - { - vfsMountTree = New(vfs_node_t); - node = vfsMountTree; - node->chr = *mp; - node->up = NULL; + if (mounts) + return -2; // root already mounted + void *super = fses[fsType]->mount_super(maj, min); + vfs_mount_t *mnt = New(vfs_mount_t); + mnt->refs = 0; + mnt->fs = fsType; + mnt->major = maj; + mnt->minor = min; + mnt->super = super; + vfs_mount_node_t *node = New(vfs_mount_node_t); + mount = node; node->next = NULL; - node->down = NULL; - node->mount = NULL; + node->mount = mnt; + node->vfs_inode = 0; + return 0; } - for (;;) - { - if (node->chr == *mp) // got a match - { - mp++; - if (*mp == 0) - { - if (node->mount) - return -1; // mount point already taken - node->mount = mnt; - return 0; - } - if (node->down) - node = node->down; - else - { - node->down = New(vfs_node_t); - node->down->up = node; - node = node->down; - node->next = NULL; - node->down = NULL; - node->mount = NULL; - node->chr = *mp; - } - } - else if (node->next) - { - node = node->next; - } - else // add a node for this character - { - node->next = New(vfs_node_t); - node->next->up = node->up; - node = node->next; - node->next = NULL; - node->down = NULL; - node->mount = NULL; - node->chr = *mp; - } - } + if (mountPoint[0] != '/') + return -3; // mount point must be absolute + int l = strlen(mountPoint); + if (l < 2) + return -4; // mount point must be non-null string + return -5; } -// lookup a path and return the match structure for the deepest path matched -vfs_mount_match_t vfs_get_rel_path(char *path) +vfs_inode_t vfs_get_inode_number(char *path) { - vfs_mount_match_t matched = {NULL, 0}; - char *pp = path; - int length = 0; - vfs_node_t *node = vfsMountTree; - while (*pp) - { - if (!node) - break; - if (node->chr == *pp) // got a character match - { - length++; - if (node->mount) // and there is something mounted here - { - matched.mount = node->mount; - matched.length = length; - } - pp++; - node = node->down; - } - else - node = node->next; - } - return matched; -} + if (path[0] != '/') + return 0; + vfs_file_addr_t file_addr; + file_addr.mount = mounts->mount; + file_addr.inode = fses[file_addr.mount->fsType]->get_root_inode(file_addr.mount); -// is mountPoint a valid mount point? -// returns a pointer to the mount structure if so -vfs_mount_t *vfs_find_mount(char *mountPoint) -{ - char *mp = mountPoint; - vfs_node_t *node = vfsMountTree; - while (node) - { - if (node->chr == *mp) - { - mp++; - if (*mp == 0) // we matched the whole mount point string - return node->mount; - node = node->down; - } - else - node = node->next; - } - return NULL; -} - -// unmount the mountPoint, remove nodes from tree that aren't used anymore -int vfs_umount(char *mountPoint) -{ - char *mp = mountPoint; - vfs_node_t *node = vfsMountTree; - while (node) - { - if (node->chr == *mp) - { - mp++; - if (*mp == 0) // we matched the whole mount point string - { - // is there something mounted underneath this directory? - if (node->down) - return -3; // yes, don't umount - if (!node->mount) - return -4; // no mount here - if (node->mount->refs) - return -5; // still refs open to mount - fses[node->mount->fs]->umount_super(node->mount); - kfree(node->mount); - node->mount = NULL; - return vfs_retire_node(node); - } - node = node->down; - } - else - node = node->next; - } - return -2; // mount point does not exist -} - -// remove this node from the tree if it is not needed anymore -int vfs_retire_node(vfs_node_t *node) -{ - if (node->down) - return 0; // node is part of another mount point, don't remove - if (node->mount) - return 0; // something is still mounted here - if (!node->up) - { - kfree(node); - vfsMountTree = NULL; - return 0; // we unmounted the root directory - } - // 3 cases left: node is first child (or only child), middle child, or last child - if (node->up->down == node) // first child - { - node->up->down = node->next; // re-point parent to next child - int r = vfs_retire_node(node->up); // retire parent if we were an only-child - kfree(node); - return r; - } - vfs_node_t *onode = node->up->down; // onode points to first child - while (onode) - { - if (onode->next == node) // onode is child before node - { - onode->next = node->next; - kfree(node); - return 0; - } - onode = onode->next; - } - return -1; // node wasn't found following onode } @@ -253,11 +87,8 @@ int vfs_stat(char *file, vfs_stat_t *stat) } -vfs_open_file_t *vfs_open_dir(char *file) +vfs_open_file_t *vfs_open_dir(vfs_inode_t inode) { - vfs_mount_match_t match = vfs_get_rel_path(file); - if (match.mount == NULL) - return NULL; vfs_open_file_t *open_dir = New(vfs_open_file_t); if (fses[match.mount->fs]->open_dir && !(fses[match.mount->fs]->open_dir(match.mount, file + match.length - 1, open_dir))) { diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index fd6d715..68142fb 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -36,37 +36,31 @@ #define EOF 1000000 +typedef u64_t vfs_inode_t; + /* Structure to hold information about a mount point */ typedef struct { - int refs; - void *super; - int fs; + int refs; + void *super; + int fs; major_t major; minor_t minor; } vfs_mount_t; -/* This structure represents a node of the "VFS Mount Tree" */ -struct vfs_node_s +struct vfs_mount_node_s { - char chr; // the character we are at - vfs_mount_t *mount; // is there a mount at this character? - struct vfs_node_s *up; // the parent - struct vfs_node_s *next; // the next sibling - struct vfs_node_s *down; // subtree for submounts + vfs_mount_t *mount; + vfs_inode_t vfs_inode; + struct vfs_mount_node_s *next; }; +typedef struct vfs_mount_node_s vfs_mount_node_t; -typedef struct vfs_node_s vfs_node_t; - -/* This structure is generated when a path is matched. For example, if /dev is mounted on - device (4,2) and '/dev/yoda' is looked up, the structure returned would be - {4, 2, 4} and then the lookup could continue on device (4,2) with 4 characters stripped - off the front of the initial path (ex '/yoda') */ typedef struct { vfs_mount_t *mount; - int length; -} vfs_mount_match_t; + u32_t inode; +} vfs_file_addr_t; typedef struct { @@ -91,7 +85,8 @@ typedef struct typedef struct { - char name[257]; + char name[257]; + u32_t inode_number; } vfs_dir_entry_t; /* Every filesystem must provide pointers to its respective functions in a structure like this */ @@ -99,17 +94,18 @@ typedef struct { void *(*mount_super)(major_t major, minor_t minor); int (*umount_super)(vfs_mount_t *mount); - int (*stat)(vfs_mount_t *mount, char *file, vfs_stat_t *stat); + int (*stat)(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat); + u32_t (*get_root_inode)(vfs_mount_t *mount); - int (*open_dir)(vfs_mount_t *mount, char *file, vfs_open_file_t *dir); + int (*open_dir)(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir); int (*read_dir)(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry); int (*close_dir)(vfs_mount_t *mount, vfs_open_file_t *dir); - int (*open_file)(vfs_mount_t *mount, char *file, vfs_open_file_t *open_file); + int (*open_file)(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file); int (*read_file)(vfs_mount_t *mount, vfs_open_file_t *open_file); int (*close_file)(vfs_mount_t *mount, vfs_open_file_t *open_file); - int (*open_block_file)(vfs_mount_t *mount, char *file, vfs_open_file_t *open_file); + int (*open_block_file)(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file); int (*read_block_file)(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer); int (*block_file_seek)(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number); int (*close_block_file)(vfs_mount_t *mount, vfs_open_file_t *open_file); diff --git a/kernel/kernel.c b/kernel/kernel.c index e81a6ab..fff1b5a 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -136,7 +136,7 @@ void k_init() } } - vfs_open_file_t *root = vfs_open_dir("/"); +/* vfs_open_file_t *root = vfs_open_dir("/"); if (root) { vfs_dir_entry_t dentry; @@ -169,7 +169,7 @@ void k_init() } else kprintf("Error: Could not open /txt/Makefile!\n"); - +*/ criticalCounter--; }