mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Implemented vfs_lookup_byvnum() close to what it should look like.
This commit is contained in:
@@ -45,6 +45,12 @@ int memfs_write_block(struct vnode *v, int blknum, void *buf)
|
||||
|
||||
/*
|
||||
* Handles both read and writes since most details are common.
|
||||
*
|
||||
* TODO: Think about whether to use inode or the vnode's fields (e.g. size)
|
||||
* and when updated, which one is to be updated first. Normally if you use and
|
||||
* update inode, then you sync vnode via read_vnode. but this is not really meant for
|
||||
* this use, its meant for retrieving an unknown inode under the vnode with valid vnum.
|
||||
* here we already have the inode.
|
||||
*/
|
||||
int memfs_file_read_write(struct vnode *v, unsigned long pfn,
|
||||
unsigned long npages, void *buf, int wr)
|
||||
@@ -86,29 +92,29 @@ int memfs_file_read_write(struct vnode *v, unsigned long pfn,
|
||||
&i->block[x], blocksize);
|
||||
} else { /* Write-specific operations */
|
||||
/* Is the write beyond current file size? */
|
||||
if (i->size < ((pfn + npages) * (blocksize))) {
|
||||
unsigned long diff = pfn + npages - __pfn(i->size);
|
||||
if (v->size < ((pfn + npages) * (blocksize))) {
|
||||
unsigned long diff = pfn + npages - __pfn(v->size);
|
||||
unsigned long holes;
|
||||
|
||||
/*
|
||||
* If write is not consecutively after the currently
|
||||
* last file block, the gap must be filled in by holes.
|
||||
*/
|
||||
if (pfn > __pfn(i->size))
|
||||
holes = pfn - __pfn(i->size);
|
||||
if (pfn > __pfn(v->size))
|
||||
holes = pfn - __pfn(v->size);
|
||||
|
||||
/* Allocate new blocks */
|
||||
for (int x = 0; x < diff; x++)
|
||||
if (!(i->block[__pfn(i->size) + x] = memfs_alloc_block(memfs_sb)))
|
||||
if (!(i->block[__pfn(v->size) + x] = memfs_alloc_block(memfs_sb)))
|
||||
return -ENOSPC;
|
||||
|
||||
/* Zero out the holes. FIXME: How do we zero out non-page-aligned bytes?` */
|
||||
for (int x = 0; x < holes; x++)
|
||||
memset(i->block[__pfn(i->size) + x], 0, blocksize);
|
||||
memset(i->block[__pfn(v->size) + x], 0, blocksize);
|
||||
|
||||
/* Update size and the vnode. FIXME: How do we handle non page-aligned size */
|
||||
i->size = (pfn + npages) * blocksize;
|
||||
v->sb->ops->read_vnode(v->sb, v);
|
||||
/* Update size and the inode. FIXME: How do we handle non page-aligned size */
|
||||
v->size = (pfn + npages) * blocksize;
|
||||
v->sb->ops->write_vnode(v->sb, v);
|
||||
}
|
||||
|
||||
/* Copy the data from page buffer into inode blocks */
|
||||
|
||||
@@ -106,6 +106,7 @@ int memfs_destroy_inode(struct memfs_superblock *sb, struct memfs_inode *i)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocates both an inode and a vnode and associates the two together */
|
||||
struct vnode *memfs_alloc_vnode(struct superblock *sb)
|
||||
{
|
||||
struct memfs_inode *i;
|
||||
@@ -131,6 +132,7 @@ struct vnode *memfs_alloc_vnode(struct superblock *sb)
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Frees the inode and the corresponding vnode */
|
||||
int memfs_free_vnode(struct superblock *sb, struct vnode *v)
|
||||
{
|
||||
struct memfs_inode *i = v->inode;
|
||||
@@ -182,6 +184,7 @@ int memfs_read_vnode(struct superblock *sb, struct vnode *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Writes a valid vnode's fields back to its fs-specific inode */
|
||||
int memfs_write_vnode(struct superblock *sb, struct vnode *v)
|
||||
{
|
||||
struct memfs_inode *i = v->inode;
|
||||
|
||||
@@ -93,7 +93,6 @@ int sys_readdir(l4id_t sender, int fd, void *buf, int count)
|
||||
unsigned long vnum;
|
||||
struct vnode *v;
|
||||
struct tcb *t;
|
||||
struct dirbuf *db;
|
||||
unsigned long nbytes;
|
||||
int err;
|
||||
|
||||
|
||||
@@ -12,29 +12,45 @@ 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.
|
||||
* If nothing is found, it reads the vnode from disk into cache. This is called
|
||||
* by system calls since tasks keep an fd-to-vnum table.
|
||||
*/
|
||||
struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum)
|
||||
{
|
||||
struct vnode *v;
|
||||
int err;
|
||||
|
||||
/* 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.
|
||||
/*
|
||||
* In the future it will be possible that a vnum known by the fd table
|
||||
* is not in the cache, because the cache will be able to grow and shrink.
|
||||
* But currently it just grows, so its a bug that a known vnum is not in
|
||||
* the cache.
|
||||
*/
|
||||
BUG();
|
||||
|
||||
/* Check the actual filesystem for the vnode */
|
||||
v = vfs_alloc_vnode();
|
||||
v->vnum = vnum;
|
||||
if ((err = v->read_vnode(sb, v)) < 0) {
|
||||
vfs_free_vnode(v);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Add the vnode back to vnode cache */
|
||||
list_add(&v->cache_list, &vnode_cache);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Vnodes in the vnode cache have 2 keys. One is the set of dentry names they
|
||||
* have, 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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user