Some efforts to adding better support for readdir

This commit is contained in:
Bahadir Balban
2008-02-14 12:08:21 +00:00
parent 60cce15a4d
commit 2440b5be61
8 changed files with 79 additions and 8 deletions

2
README
View File

@@ -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.

View File

@@ -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 */

View File

@@ -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 */
};

View File

@@ -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__ */

View File

@@ -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)
{

View File

@@ -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)));

View File

@@ -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;
}

View File

@@ -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;