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

View File

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

View File

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

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