Implemented vfs_lookup_byvnum() close to what it should look like.

This commit is contained in:
Bahadir Balban
2008-02-14 15:46:30 +00:00
parent d3b6817887
commit 1b387a1704
4 changed files with 43 additions and 19 deletions

View File

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

View File

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

View File

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

View File

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