mirror of
https://github.com/drasko/codezero.git
synced 2026-03-06 12:33:14 +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.
|
* 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,
|
int memfs_file_read_write(struct vnode *v, unsigned long pfn,
|
||||||
unsigned long npages, void *buf, int wr)
|
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);
|
&i->block[x], blocksize);
|
||||||
} else { /* Write-specific operations */
|
} else { /* Write-specific operations */
|
||||||
/* Is the write beyond current file size? */
|
/* Is the write beyond current file size? */
|
||||||
if (i->size < ((pfn + npages) * (blocksize))) {
|
if (v->size < ((pfn + npages) * (blocksize))) {
|
||||||
unsigned long diff = pfn + npages - __pfn(i->size);
|
unsigned long diff = pfn + npages - __pfn(v->size);
|
||||||
unsigned long holes;
|
unsigned long holes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If write is not consecutively after the currently
|
* If write is not consecutively after the currently
|
||||||
* last file block, the gap must be filled in by holes.
|
* last file block, the gap must be filled in by holes.
|
||||||
*/
|
*/
|
||||||
if (pfn > __pfn(i->size))
|
if (pfn > __pfn(v->size))
|
||||||
holes = pfn - __pfn(i->size);
|
holes = pfn - __pfn(v->size);
|
||||||
|
|
||||||
/* Allocate new blocks */
|
/* Allocate new blocks */
|
||||||
for (int x = 0; x < diff; x++)
|
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;
|
return -ENOSPC;
|
||||||
|
|
||||||
/* Zero out the holes. FIXME: How do we zero out non-page-aligned bytes?` */
|
/* Zero out the holes. FIXME: How do we zero out non-page-aligned bytes?` */
|
||||||
for (int x = 0; x < holes; x++)
|
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 */
|
/* Update size and the inode. FIXME: How do we handle non page-aligned size */
|
||||||
i->size = (pfn + npages) * blocksize;
|
v->size = (pfn + npages) * blocksize;
|
||||||
v->sb->ops->read_vnode(v->sb, v);
|
v->sb->ops->write_vnode(v->sb, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the data from page buffer into inode blocks */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocates both an inode and a vnode and associates the two together */
|
||||||
struct vnode *memfs_alloc_vnode(struct superblock *sb)
|
struct vnode *memfs_alloc_vnode(struct superblock *sb)
|
||||||
{
|
{
|
||||||
struct memfs_inode *i;
|
struct memfs_inode *i;
|
||||||
@@ -131,6 +132,7 @@ struct vnode *memfs_alloc_vnode(struct superblock *sb)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Frees the inode and the corresponding vnode */
|
||||||
int memfs_free_vnode(struct superblock *sb, struct vnode *v)
|
int memfs_free_vnode(struct superblock *sb, struct vnode *v)
|
||||||
{
|
{
|
||||||
struct memfs_inode *i = v->inode;
|
struct memfs_inode *i = v->inode;
|
||||||
@@ -182,6 +184,7 @@ int memfs_read_vnode(struct superblock *sb, struct vnode *v)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Writes a valid vnode's fields back to its fs-specific inode */
|
||||||
int memfs_write_vnode(struct superblock *sb, struct vnode *v)
|
int memfs_write_vnode(struct superblock *sb, struct vnode *v)
|
||||||
{
|
{
|
||||||
struct memfs_inode *i = v->inode;
|
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;
|
unsigned long vnum;
|
||||||
struct vnode *v;
|
struct vnode *v;
|
||||||
struct tcb *t;
|
struct tcb *t;
|
||||||
struct dirbuf *db;
|
|
||||||
unsigned long nbytes;
|
unsigned long nbytes;
|
||||||
int err;
|
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
|
* 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.
|
* 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 *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum)
|
||||||
{
|
{
|
||||||
struct vnode *v;
|
struct vnode *v;
|
||||||
|
int err;
|
||||||
|
|
||||||
/* Check the vnode cache by vnum */
|
/* Check the vnode cache by vnum */
|
||||||
list_for_each_entry(v, vnode_cache, cache_list)
|
list_for_each_entry(v, vnode_cache, cache_list)
|
||||||
if (v->vnum == vnum)
|
if (v->vnum == vnum)
|
||||||
return v;
|
return v;
|
||||||
|
|
||||||
/* Otherwise ask the filesystem:
|
/*
|
||||||
* TODO:
|
* In the future it will be possible that a vnum known by the fd table
|
||||||
* vfs_alloc_vnode() -> This should also add the empty vnode to vnode cache.
|
* is not in the cache, because the cache will be able to grow and shrink.
|
||||||
* read_vnode() -> read it from filesystem.
|
* But currently it just grows, so its a bug that a known vnum is not in
|
||||||
* return what's read.
|
* 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
|
* Vnodes in the vnode cache have 2 keys. One is the set of dentry names they
|
||||||
* other is their vnum. This one checks the vnode cache by the path first.
|
* have, the other is their vnum. This one checks the vnode cache by the path
|
||||||
* If nothing is found, it reads the vnode from disk into the cache.
|
* first. If nothing is found, it reads the vnode from disk into the cache.
|
||||||
*/
|
*/
|
||||||
struct vnode *vfs_lookup_bypath(struct superblock *sb, char *path)
|
struct vnode *vfs_lookup_bypath(struct superblock *sb, char *path)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user