From 1b387a17043a3166f2779320a80defade9db45f7 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Thu, 14 Feb 2008 15:46:30 +0000 Subject: [PATCH] Implemented vfs_lookup_byvnum() close to what it should look like. --- tasks/fs0/src/memfs/file.c | 24 +++++++++++++++--------- tasks/fs0/src/memfs/vnode.c | 3 +++ tasks/fs0/src/syscalls.c | 1 - tasks/fs0/src/vfs.c | 34 +++++++++++++++++++++++++--------- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/tasks/fs0/src/memfs/file.c b/tasks/fs0/src/memfs/file.c index 558c9d4..3f8a069 100644 --- a/tasks/fs0/src/memfs/file.c +++ b/tasks/fs0/src/memfs/file.c @@ -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 */ diff --git a/tasks/fs0/src/memfs/vnode.c b/tasks/fs0/src/memfs/vnode.c index 1565b8d..334d489 100644 --- a/tasks/fs0/src/memfs/vnode.c +++ b/tasks/fs0/src/memfs/vnode.c @@ -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; diff --git a/tasks/fs0/src/syscalls.c b/tasks/fs0/src/syscalls.c index 88cd27f..e95001f 100644 --- a/tasks/fs0/src/syscalls.c +++ b/tasks/fs0/src/syscalls.c @@ -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; diff --git a/tasks/fs0/src/vfs.c b/tasks/fs0/src/vfs.c index 27e2734..26a4c89 100644 --- a/tasks/fs0/src/vfs.c +++ b/tasks/fs0/src/vfs.c @@ -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) {