mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Some efforts to adding better support for readdir
This commit is contained in:
2
README
2
README
@@ -46,7 +46,7 @@ MM0 is the systm task that implements memory management. It contains memory and
|
||||
page allocators. It implements demand paging by managing page faults, physical
|
||||
pages and their file/task associations.
|
||||
|
||||
FS0 is the system task implements a simple, modern virtual filesystem layer.
|
||||
FS0 is the system task that implements a simple, modern virtual filesystem layer.
|
||||
Since it abstracts the low-level filesystem details, it is a relatively easy job
|
||||
to port a new filesystem to be used under FS0.
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ struct file_ops {
|
||||
struct vnode_ops {
|
||||
vnode_op_t create;
|
||||
struct vnode *(*lookup)(struct vnode *root, char *path);
|
||||
void * (*readdir)(struct vnode *v, void *dirbuf);
|
||||
void *(*readdir)(struct vnode *v, void *dirbuf);
|
||||
vnode_op_t link;
|
||||
vnode_op_t unlink;
|
||||
vnode_op_t mkdir;
|
||||
@@ -97,6 +97,7 @@ struct vnode {
|
||||
struct file_ops fops; /* File-related operations on this vnode */
|
||||
struct list_head dentries; /* Dirents that refer to this vnode */
|
||||
struct list_head state_list; /* List for vnode's dirty/clean state */
|
||||
struct list_head cache_list; /* For adding the vnode to vnode cache */
|
||||
u32 type; /* Vnode type, dev? socket? dir? ... */
|
||||
u32 mode; /* Permissions */
|
||||
u32 owner; /* Owner */
|
||||
|
||||
@@ -75,8 +75,9 @@ struct memfs_superblock {
|
||||
|
||||
#define MEMFS_DNAME_MAX 32
|
||||
struct memfs_dentry {
|
||||
u32 inum; /* Inode number */
|
||||
u32 nlength; /* Name length */
|
||||
u32 inum; /* Inode number */
|
||||
u32 offset; /* Dentry offset in its buffer */
|
||||
u32 rlength; /* Record length */
|
||||
u8 name[MEMFS_DNAME_MAX]; /* Name string */
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,17 @@
|
||||
#include <l4/lib/list.h>
|
||||
#include <memfs/memfs.h>
|
||||
|
||||
/* Buffer to keep directory content. This is the only vnode content
|
||||
* that fs0 maintains. All other file data is in mm0 page cache.
|
||||
*/
|
||||
struct dirbuf {
|
||||
struct list_head list;
|
||||
unsigned long bufsize;
|
||||
u8 *buffer;
|
||||
};
|
||||
extern struct list_head vnode_cache;
|
||||
extern struct list_head dentry_cache;
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
* These ought to be strings and split/comparison functions should
|
||||
@@ -58,12 +69,16 @@ static inline struct vnode *vfs_alloc_vnode(void)
|
||||
|
||||
INIT_LIST_HEAD(&v->dentries);
|
||||
INIT_LIST_HEAD(&v->state_list);
|
||||
INIT_LIST_HEAD(&v->cache_list);
|
||||
list_add(&v->cache_list, &vnode_cache);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void vfs_free_vnode(struct vnode *v)
|
||||
{
|
||||
BUG(); /* Are the dentries freed ??? */
|
||||
list_del(&v->cache_list);
|
||||
kfree(v);
|
||||
}
|
||||
|
||||
@@ -84,6 +99,7 @@ extern struct vfs_mountpoint vfs_root;
|
||||
|
||||
int vfs_mount_root(struct superblock *sb);
|
||||
struct vnode *generic_vnode_lookup(struct vnode *thisnode, char *path);
|
||||
struct vnode *vfs_lookup(struct superblock *sb, char *path);
|
||||
struct vnode *vfs_lookup_bypath(struct superblock *sb, char *path);
|
||||
struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum);
|
||||
|
||||
#endif /* __VFS_H__ */
|
||||
|
||||
@@ -16,6 +16,19 @@
|
||||
#include <syscalls.h>
|
||||
#include <task.h>
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Have a dentry cache searchable by name
|
||||
* - Have a vnode cache searchable by vnum (and name?)
|
||||
* - fs-specific readdir would read contents by page range, and add vnodes/dentries
|
||||
* to their caches, while populating the directory vnode being read.
|
||||
* - Have 2 vfs_lookup() flavors, one that searches a path, one that searches a vnum.
|
||||
* - dirbuf is either allocated by low-level readdir, or else by a higher level, i.e.
|
||||
* either high-level vfs code, or the mm0 page cache.
|
||||
* - readdir provides a posix-compliant dirent structure list in dirbuf.
|
||||
* - memfs dentries should be identical to posix struct dirents.
|
||||
*/
|
||||
|
||||
/* Synchronise with pager via a `wait' tagged ipc with destination as pager */
|
||||
void wait_pager(l4id_t partner)
|
||||
{
|
||||
|
||||
@@ -75,6 +75,8 @@ int initialise(void)
|
||||
memfs_format_filesystem(rootdev_blocks);
|
||||
|
||||
INIT_LIST_HEAD(&vm_file_list);
|
||||
INIT_LIST_HEAD(&vnode_cache);
|
||||
INIT_LIST_HEAD(&dentry_cache);
|
||||
|
||||
/* Search for a filesystem on the root device */
|
||||
BUG_ON(IS_ERR(root_sb = vfs_probe_filesystems(rootdev_blocks)));
|
||||
|
||||
@@ -91,6 +91,7 @@ int sys_read(l4id_t sender, int fd, void *buf, int count)
|
||||
int sys_readdir(l4id_t sender, int fd, void *buf, int count)
|
||||
{
|
||||
struct vnode *v;
|
||||
struct tcb *t;
|
||||
|
||||
/* Get the task */
|
||||
BUG_ON(!(t = find_task(sender)));
|
||||
@@ -104,7 +105,7 @@ int sys_readdir(l4id_t sender, int fd, void *buf, int count)
|
||||
|
||||
/* Simply read its contents */
|
||||
v->ops.readdir(v, buf, count);
|
||||
`
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,49 @@
|
||||
#include <fs.h>
|
||||
#include <vfs.h>
|
||||
|
||||
struct vnode *vfs_lookup(struct superblock *sb, char *path)
|
||||
struct list_head vnode_cache;
|
||||
struct list_head dentry_cache;
|
||||
|
||||
/*
|
||||
* Vnodes in the vnode cache have 2 keys. One is their dentry names, the other
|
||||
* is their vnum. This one checks the vnode cache by the given vnum first.
|
||||
* If nothing is found, it reads the vnode from disk into cache.
|
||||
*/
|
||||
struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum)
|
||||
{
|
||||
struct vnode *v;
|
||||
|
||||
/* Check the vnode cache by vnum */
|
||||
list_for_each_entry(v, vnode_cache, cache_list)
|
||||
if (v->vnum == vnum)
|
||||
return v;
|
||||
|
||||
/* Otherwise ask the filesystem:
|
||||
* TODO:
|
||||
* vfs_alloc_vnode() -> This should also add the empty vnode to vnode cache.
|
||||
* read_vnode() -> read it from filesystem.
|
||||
* return what's read.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Vnodes in the vnode cache have 2 keys. One is their dentry name, the
|
||||
* other is their vnum. This one checks the vnode cache by the path first.
|
||||
* If nothing is found, it reads the vnode from disk into the cache.
|
||||
*/
|
||||
struct vnode *vfs_lookup_bypath(struct superblock *sb, char *path)
|
||||
{
|
||||
/* If it's just / we already got it. */
|
||||
if (!strcmp(path, "/"))
|
||||
return sb->root;
|
||||
|
||||
/* TODO: Check the vnode cache by path component
|
||||
*
|
||||
* This should split the path into components and compare
|
||||
* each of them with each vnode's dentry list.
|
||||
*/
|
||||
|
||||
/* It's not in the cache, look it up from filesystem. */
|
||||
return sb->root->ops.lookup(sb->root, path);
|
||||
}
|
||||
|
||||
@@ -28,7 +65,7 @@ struct vfs_mountpoint vfs_root;
|
||||
int vfs_mount_root(struct superblock *sb)
|
||||
{
|
||||
/* Lookup the root vnode of this superblock */
|
||||
vfs_root.pivot = vfs_lookup(sb, "/");
|
||||
vfs_root.pivot = vfs_lookup_bypath(sb, "/");
|
||||
vfs_root.sb = sb;
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user