Integrated vm_files with vnodes. execve is not working as expected.

This commit is contained in:
Bahadir Balban
2009-10-13 11:33:25 +03:00
parent f54747a208
commit a249105969
21 changed files with 400 additions and 375 deletions

View File

@@ -358,7 +358,7 @@ int memfs_vnode_readdir(struct vnode *v)
* in the vnode cache. If it's not there, the lookup function
* allocates and reads it for us as well.
*/
newv = newd->vnode = vfs_lookup_byvnum(v->sb, memfsd[i].inum);
newv = newd->vnode = vfs_vnode_lookup_byvnum(v->sb, memfsd[i].inum);
if (!newv) {
printf("Filesystem seems to be broken. Directory has"
"inode number: %d, but no such inode found.\n",

View File

@@ -20,7 +20,7 @@ struct id_pool *vfs_fsidx_pool;
* 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_vnode_lookup_byvnum(struct superblock *sb, unsigned long vnum)
{
struct vnode *v;
int err;
@@ -51,7 +51,7 @@ struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum)
* 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 pathdata *pdata)
struct vnode *vfs_vnode_lookup_bypath(struct pathdata *pdata)
{
const char *firstcomp;
@@ -69,7 +69,7 @@ int vfs_mount_root(struct superblock *sb)
* Lookup the root vnode of this superblock.
* The root superblock has vnode number 0.
*/
vfs_root.pivot = vfs_lookup_byvnum(sb, sb->fsidx | 0);
vfs_root.pivot = vfs_vnode_lookup_byvnum(sb, sb->fsidx | 0);
vfs_root.sb = sb;
return 0;

View File

@@ -6,10 +6,10 @@
#include <posix/sys/types.h> /* FIXME: Remove this and refer to internal headers */
#include <task.h>
int vfs_read(unsigned long vnum, unsigned long f_offset, unsigned long npages,
void *pagebuf);
int vfs_write(unsigned long vnum, unsigned long f_offset, unsigned long npages,
void *pagebuf);
int vfs_read(struct vnode *v, unsigned long f_offset,
unsigned long npages, void *pagebuf);
int vfs_write(struct vnode *v, unsigned long f_offset,
unsigned long npages, void *pagebuf);
int sys_read(struct tcb *sender, int fd, void *buf, int count);
int sys_write(struct tcb *sender, int fd, void *buf, int count);
int sys_lseek(struct tcb *sender, int fd, off_t offset, int whence);
@@ -24,12 +24,6 @@ int flush_file_pages(struct vm_file *f);
int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
unsigned long pfn_end);
struct vfs_file_data {
unsigned long vnum;
};
#define vm_file_to_vnum(f) \
(((struct vfs_file_data *)((f)->priv_data))->vnum)
struct vm_file *vfs_file_create(void);

View File

@@ -40,7 +40,6 @@
struct vm_file;
struct file_descriptor {
unsigned long vnum;
unsigned long cursor;
struct vm_file *vmfile;
};

View File

@@ -93,8 +93,8 @@ extern struct vfs_mountpoint vfs_root;
int vfs_mount_root(struct superblock *sb);
struct vnode *generic_vnode_lookup(struct vnode *thisnode, struct pathdata *p,
const char *component);
struct vnode *vfs_lookup_bypath(struct pathdata *p);
struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum);
struct vnode *vfs_vnode_lookup_bypath(struct pathdata *p);
struct vnode *vfs_vnode_lookup_byvnum(struct superblock *sb, unsigned long vnum);
int vfs_init(void);

View File

@@ -47,7 +47,6 @@
enum VM_FILE_TYPE {
VM_FILE_DEVZERO = 1,
VM_FILE_VFS,
VM_FILE_BOOTFILE,
VM_FILE_SHM,
};
@@ -66,17 +65,10 @@ struct page {
};
extern struct page *page_array;
/*
* A suggestion to how a non-page_array (i.e. a device)
* page could tell its physical address.
*/
struct devpage {
struct page page;
unsigned long phys;
};
#define page_refcnt(x) ((x)->count + 1)
#define virtual(x) ((x)->virtual)
/* TODO: Calculate these by indexing each bank according to pfn */
#define phys_to_page(x) (page_array + __pfn((x) - membank[0].start))
#define page_to_phys(x) (__pfn_to_addr((((void *)(x)) - \
(void *)page_array) / \
@@ -131,11 +123,12 @@ struct vm_object {
struct vm_file {
int openers;
struct link list;
unsigned long length;
unsigned int type;
unsigned long length;
struct vm_object vm_obj;
void (*destroy_priv_data)(struct vm_file *f);
void *priv_data; /* Device pagers use to access device info */
struct vnode *vnode;
void *private_file_data; /* FIXME: To be removed and placed into vnode!!! */
};
/* To create per-vma vm_object lists */
@@ -210,7 +203,6 @@ struct page *find_page(struct vm_object *obj, unsigned long pfn);
/* Pagers */
extern struct vm_pager file_pager;
extern struct vm_pager bootfile_pager;
extern struct vm_pager devzero_pager;
extern struct vm_pager swap_pager;

View File

@@ -153,11 +153,6 @@ void handle_requests(void)
return; /* else we're done */
}
/*
* FIXME: Fix all these syscalls to read any
* buffer data from the caller task's utcb.
*/
/* FS0 System calls */
case L4_IPC_TAG_OPEN:
ret = sys_open(sender, utcb_full_buffer(), (int)mr[0], (unsigned int)mr[1]);

View File

@@ -4,6 +4,7 @@
#include <l4/lib/list.h>
#include <vm_area.h>
#include <lib/malloc.h>
#include <fs.h>
/*
* This is yet unused, it is more of an anticipation
@@ -19,7 +20,7 @@ struct page *memdev_page_in(struct vm_object *vm_obj,
unsigned long pfn_offset)
{
struct vm_file *f = vm_object_to_file(vm_obj);
struct mmap_device *memdev = f->priv_data;
struct mmap_device *memdev = f->vnode->inode;
struct page *page;
/* Check if its within device boundary */

View File

@@ -37,13 +37,13 @@ int task_setup_from_executable(struct vm_file *vmfile, struct tcb *task,
int init_execve(char *filepath)
{
unsigned long vnum, length;
struct vm_file *vmfile;
struct exec_file_desc efd;
struct tcb *new_task;
struct tcb *new_task, *self;
struct args_struct args, env;
char *env_string = "pagerid=0";
int err;
int fd;
struct task_ids ids = {
.tid = TASK_ID_INVALID,
@@ -65,33 +65,26 @@ int init_execve(char *filepath)
strncpy(env.argv[0], env_string, strlen(env_string) + 1);
env.size = sizeof(env.argv) + strlen(env_string) + 1;
/* Get file info from vfs */
if ((err = vfs_open_bypath(filepath, &vnum, &length)) < 0)
return err;
/* Create and get the file structure */
if (IS_ERR(vmfile = do_open2(0, 0, vnum, length)))
return (int)vmfile;
#if 0
self = find_task(self_tid());
if ((fd = sys_open(self, filepath,
O_RDONLY, 0)) < 0) {
printf("FATAL: Could not open file "
"to execute initial task.\n");
"to write initial task.\n");
BUG();
}
#endif
/* Get the low-level vmfile */
vmfile = self->files->fd[fd].vmfile;
if (IS_ERR(new_task = task_create(0, &ids,
THREAD_NEW_SPACE,
TCB_NO_SHARING))) {
vm_file_put(vmfile); /* FIXME: sys_close() ??? */
sys_close(self, fd);
return (int)new_task;
}
/* Fill and validate tcb memory segment markers from executable file */
if ((err = task_setup_from_executable(vmfile, new_task, &efd)) < 0) {
vm_file_put(vmfile);
sys_close(self, fd);
kfree(new_task);
return err;
}
@@ -99,7 +92,7 @@ int init_execve(char *filepath)
/* Map task's new segment markers as virtual memory regions */
if ((err = task_mmap_segments(new_task, vmfile,
&efd, &args, &env)) < 0) {
vm_file_put(vmfile);
sys_close(self, fd);
kfree(new_task);
return err;
}
@@ -123,29 +116,28 @@ int init_execve(char *filepath)
int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
struct args_struct *env)
{
unsigned long vnum, length;
struct vm_file *vmfile;
struct exec_file_desc efd;
struct tcb *new_task, *tgleader;
struct tcb *new_task, *tgleader, *self;
int err;
int fd;
/* Get file info from vfs */
if ((err = vfs_open_bypath(filename, &vnum, &length)) < 0)
return err;
self = find_task(self_tid());
if ((fd = sys_open(self, filename, O_RDONLY, 0)) < 0)
return fd;
/* Create and get the file structure */
if (IS_ERR(vmfile = do_open2(0, 0, vnum, length)))
return (int)vmfile;
/* Get the low-level vmfile */
vmfile = self->files->fd[fd].vmfile;
/* Create a new tcb */
if (IS_ERR(new_task = tcb_alloc_init(TCB_NO_SHARING))) {
vm_file_put(vmfile);
sys_close(self, fd);
return (int)new_task;
}
/* Fill and validate tcb memory segment markers from executable file */
if ((err = task_setup_from_executable(vmfile, new_task, &efd)) < 0) {
vm_file_put(vmfile);
sys_close(self, fd);
kfree(new_task);
return err;
}
@@ -175,7 +167,7 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
* exit() except destroying the actual thread.
*/
if ((err = execve_recycle_task(new_task, tgleader)) < 0) {
vm_file_put(vmfile);
sys_close(self, fd);
kfree(new_task);
return err;
}
@@ -183,7 +175,7 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
/* Map task's new segment markers as virtual memory regions */
if ((err = task_mmap_segments(new_task, vmfile,
&efd, args, env)) < 0) {
vm_file_put(vmfile);
sys_close(self, fd);
kfree(new_task);
return err;
}

View File

@@ -330,8 +330,7 @@ int vm_object_is_deletable(struct vm_object *obj)
return 0;
else if (f->type == VM_FILE_SHM)
return 1;
else if (f->type == VM_FILE_BOOTFILE ||
f->type == VM_FILE_VFS) {
else if (f->type == VM_FILE_VFS) {
if (f->openers == 0)
return 1;
else

View File

@@ -64,15 +64,9 @@ int page_copy(struct page *dst, struct page *src,
return 0;
}
int vfs_read(unsigned long vnum, unsigned long file_offset,
int vfs_read(struct vnode *v, unsigned long file_offset,
unsigned long npages, void *pagebuf)
{
struct vnode *v;
/* Lookup vnode */
if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum)))
return -EINVAL;
/* Ensure vnode is not a directory */
if (vfs_isdir(v))
return -EISDIR;
@@ -95,46 +89,9 @@ void print_vnode(struct vnode *v)
}
/*
* Different from vfs_open(), which validates an already opened
* file descriptor, this call opens a new vfs file by the pager
* using the given path. The vnum handle and file length is returned
* since the pager uses this information to access file pages.
*/
int vfs_open_bypath(const char *pathname, unsigned long *vnum, unsigned long *length)
{
struct pathdata *pdata;
struct tcb *task = 0;
struct vnode *v;
int retval;
/* Parse path data */
if (IS_ERR(pdata = pathdata_parse(pathname,
alloca(strlen(pathname) + 1),
task)))
return (int)pdata;
/* Search the vnode by that path */
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
retval = (int)v;
goto out;
}
*vnum = v->vnum;
*length = v->size;
return 0;
out:
pathdata_destroy(pdata);
return retval;
}
/* Creates a node under a directory, e.g. a file, directory. */
struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata,
unsigned int mode)
struct vnode *vfs_vnode_create(struct tcb *task, struct pathdata *pdata,
unsigned int mode)
{
struct vnode *vparent, *newnode;
const char *nodename;
@@ -143,7 +100,7 @@ struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata,
nodename = pathdata_last_component(pdata);
/* Check that the parent directory exists. */
if (IS_ERR(vparent = vfs_lookup_bypath(pdata)))
if (IS_ERR(vparent = vfs_vnode_lookup_bypath(pdata)))
return vparent;
/* The parent vnode must be a directory. */
@@ -158,62 +115,6 @@ struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata,
return newnode;
}
/* FIXME:
* - Is it already open?
* - Allocate a copy of path string since lookup destroys it
* - Check flags and mode.
*/
int sys_open(struct tcb *task, const char *pathname, int flags, unsigned int mode)
{
struct pathdata *pdata;
struct vnode *v;
int fd;
int retval;
// printf("%s/%s\n", __TASKNAME__, __FUNCTION__);
/* Parse path data */
if (IS_ERR(pdata = pathdata_parse(pathname,
alloca(strlen(pathname) + 1),
task)))
return (int)pdata;
/* Creating new file */
if (flags & O_CREAT) {
/* Make sure mode identifies a file */
mode |= S_IFREG;
if (IS_ERR(v = vfs_create(task, pdata, mode))) {
retval = (int)v;
goto out;
}
} else {
/* Not creating, just opening, get the vnode */
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
retval = (int)v;
goto out;
}
}
/* Get a new fd */
BUG_ON((fd = id_new(task->files->fdpool)) < 0);
retval = fd;
/* TODO:
* Why assign just vnum? Why not vmfile, vnode etc?
*
* This is because vmfile is going to be created when
* the file pages are accessed. Need to trace this
* behaviour.
*/
/* Assign the new fd with the vnode's number */
task->files->fd[fd].vnum = v->vnum;
out:
pathdata_destroy(pdata);
return retval;
}
int sys_mkdir(struct tcb *task, const char *pathname, unsigned int mode)
{
struct pathdata *pdata;
@@ -230,7 +131,7 @@ int sys_mkdir(struct tcb *task, const char *pathname, unsigned int mode)
mode |= S_IFDIR;
/* Create the directory or fail */
if (IS_ERR(v = vfs_create(task, pdata, mode)))
if (IS_ERR(v = vfs_vnode_create(task, pdata, mode)))
ret = (int)v;
/* Destroy extracted path data */
@@ -251,7 +152,7 @@ int sys_chdir(struct tcb *task, const char *pathname)
return (int)pdata;
/* Get the vnode */
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
if (IS_ERR(v = vfs_vnode_lookup_bypath(pdata))) {
ret = (int)v;
goto out;
}
@@ -287,22 +188,13 @@ void fill_kstat(struct vnode *v, struct kstat *ks)
int sys_fstat(struct tcb *task, int fd, void *statbuf)
{
struct vnode *v;
unsigned long vnum;
/* Get the vnum */
if (fd < 0 || fd > TASK_FILES_MAX || !task->files->fd[fd].vnum)
/* Check that fd is valid */
if (fd < 0 || fd > TASK_FILES_MAX ||
!task->files->fd[fd].vmfile)
return -EBADF;
BUG(); /* Could just return vmfile->vnode here. */
vnum = task->files->fd[fd].vnum;
/* Lookup vnode */
if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum)))
return -EINVAL;
/* Fill in the c0-style stat structure */
fill_kstat(v, statbuf);
fill_kstat(task->files->fd[fd].vmfile->vnode, statbuf);
return 0;
}
@@ -325,7 +217,7 @@ int sys_stat(struct tcb *task, const char *pathname, void *statbuf)
return (int)pdata;
/* Get the vnode */
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
if (IS_ERR(v = vfs_vnode_lookup_bypath(pdata))) {
ret = (int)v;
goto out;
}
@@ -339,121 +231,6 @@ out:
return ret;
}
/*
* Initialise a new file and the descriptor for it from given file data.
* Could be called by an actual task or a pager
*/
struct vm_file *do_open2(struct tcb *task, int fd, unsigned long vnum, unsigned long length)
{
struct vm_file *vmfile;
/* Is this an open by a task (as opposed to by the pager)? */
if (task) {
/* fd slot must be empty */
BUG_ON(task->files->fd[fd].vnum != 0);
BUG_ON(task->files->fd[fd].cursor != 0);
/* Assign vnum to given fd on the task */
task->files->fd[fd].vnum = vnum;
task->files->fd[fd].cursor = 0;
}
/* Check if that vm_file is already in the list */
list_foreach_struct(vmfile, &global_vm_files.list, list) {
/* Check whether it is a vfs file and if so vnums match. */
if ((vmfile->type & VM_FILE_VFS) &&
vm_file_to_vnum(vmfile) == vnum) {
/* Task opener? */
if (task)
/* Add a reference to it from the task */
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
return vmfile;
}
}
/* Otherwise allocate a new one for this vnode */
if (IS_ERR(vmfile = vfs_file_create()))
return vmfile;
/* Initialise and add a reference to it from the task */
vm_file_to_vnum(vmfile) = vnum;
vmfile->length = length;
vmfile->vm_obj.pager = &file_pager;
/* Task opener? */
if (task)
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
/* Add to file list */
global_add_vm_file(vmfile);
return vmfile;
}
/*
* When a task does a read/write/mmap request on a file, if
* the file descriptor is unknown to the pager, this call
* asks vfs if that file has been opened, and any other
* relevant information.
*/
int file_open(struct tcb *task, int fd)
{
struct vnode *v;
struct vm_file *vmfile;
if (fd < 0 || fd > TASK_FILES_MAX)
return -EINVAL;
/* Check if that fd has been opened */
if (!task->files->fd[fd].vnum)
return -EBADF;
/* Search the vnode by that vnum */
if (IS_ERR(v = vfs_lookup_byvnum(vfs_root.pivot->sb,
task->files->fd[fd].vnum)))
return (int)v;
/* Cursor must be zero */
BUG_ON(task->files->fd[fd].cursor != 0);
/* Check that vm_file is already in the list */
list_foreach_struct(vmfile, &global_vm_files.list, list) {
/* Check whether it is a vfs file and if so vnums match. */
if ((vmfile->type & VM_FILE_VFS) &&
vm_file_to_vnum(vmfile) == v->vnum) {
/* Add a reference to it from the task */
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
return 0;
}
}
/* Otherwise allocate a new one for this vnode */
if (IS_ERR(vmfile = vfs_file_create()))
return (int)vmfile;
/* Assign file information */
vm_file_to_vnum(vmfile) = v->vnum;
vmfile->length = v->size;
/* Add a reference to it from the task */
vmfile->vm_obj.pager = &file_pager;
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
/* Add to file list */
global_add_vm_file(vmfile);
return 0;
}
/*
* Inserts the page to vmfile's list in order of page frame offset.
@@ -513,7 +290,7 @@ int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
if (IS_ERR(page)) {
printf("%s: %s:Could not read page %d "
"from file with vnum: 0x%lu\n", __TASKNAME__,
__FUNCTION__, f_offset, vm_file_to_vnum(vmfile));
__FUNCTION__, f_offset, vmfile->vnode->vnum);
return (int)page;
}
}
@@ -524,19 +301,14 @@ int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
/*
* The buffer must be contiguous by page, if npages > 1.
*/
int vfs_write(unsigned long vnum, unsigned long file_offset,
int vfs_write(struct vnode *v, unsigned long file_offset,
unsigned long npages, void *pagebuf)
{
struct vnode *v;
int fwrite_end;
int ret;
// printf("%s/%s\n", __TASKNAME__, __FUNCTION__);
/* Lookup vnode */
if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum)))
return -EINVAL;
/* Ensure vnode is not a directory */
if (vfs_isdir(v))
return -EISDIR;
@@ -564,12 +336,7 @@ int vfs_write(unsigned long vnum, unsigned long file_offset,
/* Writes updated file stats back to vfs. (e.g. new file size) */
int vfs_update_file_stats(struct vm_file *f)
{
unsigned long vnum = vm_file_to_vnum(f);
struct vnode *v;
/* Lookup vnode */
if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum)))
return -EINVAL;
struct vnode *v = f->vnode;
v->size = f->length;
v->sb->ops->write_vnode(v->sb, v);
@@ -596,7 +363,7 @@ int write_file_pages(struct vm_file *f, unsigned long pfn_start,
if (err < 0) {
printf("%s: %s:Could not write page %d "
"to file with vnum: 0x%lu\n", __TASKNAME__,
__FUNCTION__, f_offset, vm_file_to_vnum(f));
__FUNCTION__, f_offset, f->vnode->vnum);
return err;
}
}
@@ -635,6 +402,10 @@ int fsync_common(struct tcb *task, int fd)
if (!task->files->fd[fd].vmfile)
return 0;
printf("Thread %d flushing fd: %d, vnum: 0x%lx, vnode: %p\n",
task->tid, fd, task->files->fd[fd].vmfile->vnode->vnum,
task->files->fd[fd].vmfile->vnode);
/* Finish I/O on file */
if ((err = flush_file_pages(task->files->fd[fd].vmfile)) < 0)
return err;
@@ -651,6 +422,9 @@ void vm_file_put(struct vm_file *file)
/* No links or openers, delete the file */
vm_file_delete(file);
/* FIXME:
* Shall we delete the cached vnode here as well???
*/
}
/*
@@ -672,18 +446,12 @@ int do_close(struct tcb *task, int fd)
return err;
}
/*
* If there was no IO on it, we may not know the file,
* we simply return here. Since we notify VFS about the
* close, it can tell us if the fd was open or not.
*/
if (!task->files->fd[fd].vmfile)
return 0;
/* Reduce file refcount etc. */
vm_file_put(task->files->fd[fd].vmfile);
task->files->fd[fd].vnum = 0;
task->files->fd[fd].cursor = 0;
task->files->fd[fd].vmfile = 0;
@@ -824,10 +592,19 @@ int write_cache_pages(struct vm_file *vmfile, struct tcb *task, void *buf,
left = count;
/* Copy the first page and unmap. */
copysize = (left < PAGE_SIZE) ? left : PAGE_SIZE;
if (is_page_aligned(buf)) {
copysize = (left < PAGE_SIZE) ? left : PAGE_SIZE;
} else {
if (left < (PAGE_MASK & (unsigned long)buf))
copysize = left;
else
copysize = (PAGE_MASK &
(unsigned long)buf);
}
copy_offset = (unsigned long)buf;
page_copy(head, task_virt_to_page(task, copy_offset),
cursor_offset, copy_offset & PAGE_MASK, copysize);
cursor_offset, copy_offset & PAGE_MASK,
copysize);
head->flags |= VM_DIRTY;
head->owner->flags |= VM_DIRTY;
left -= copysize;
@@ -928,10 +705,10 @@ int sys_read(struct tcb *task, int fd, void *buf, int count)
struct vm_file *vmfile;
int ret = 0;
/* Check fd validity */
if (!task->files->fd[fd].vmfile)
if ((ret = file_open(task, fd)) < 0)
return ret;
/* Check that fd is valid */
if (fd < 0 || fd > TASK_FILES_MAX ||
!task->files->fd[fd].vmfile)
return -EBADF;
/* Check count validity */
@@ -998,10 +775,10 @@ int sys_write(struct tcb *task, int fd, void *buf, int count)
struct vm_file *vmfile;
int ret = 0;
/* Check fd validity */
if (!task->files->fd[fd].vmfile)
if ((ret = file_open(task, fd)) < 0)
return ret;
/* Check that fd is valid */
if (fd < 0 || fd > TASK_FILES_MAX ||
!task->files->fd[fd].vmfile)
return -EBADF;
/* Check count validity */
if (count < 0)
@@ -1009,7 +786,6 @@ int sys_write(struct tcb *task, int fd, void *buf, int count)
else if (!count)
return 0;
/* Check user buffer validity. */
if ((ret = pager_validate_user_range(task, buf,
(unsigned long)count,
@@ -1019,6 +795,8 @@ int sys_write(struct tcb *task, int fd, void *buf, int count)
vmfile = task->files->fd[fd].vmfile;
cursor = task->files->fd[fd].cursor;
printf("Thread %d writing to fd: %d, vnum: 0x%lx, vnode: %p\n", task->tid, fd, vmfile->vnode->vnum, vmfile->vnode);
/* See what pages user wants to write */
pfn_wstart = __pfn(cursor);
pfn_wend = __pfn(page_align_up(cursor + count));
@@ -1098,10 +876,10 @@ int sys_lseek(struct tcb *task, int fd, off_t offset, int whence)
int retval = 0;
unsigned long long total, cursor;
/* Check fd validity */
if (!task->files->fd[fd].vmfile)
if ((retval = file_open(task, fd)) < 0)
return retval;
/* Check that fd is valid */
if (fd < 0 || fd > TASK_FILES_MAX ||
!task->files->fd[fd].vmfile)
return -EBADF;
/* Offset validity */
if (offset < 0)
@@ -1179,7 +957,6 @@ int sys_readdir(struct tcb *t, int fd, int count, char *dirbuf)
{
int dirent_size = sizeof(struct dirent);
int total = 0, nbytes = 0;
unsigned long vnum;
struct vnode *v;
struct dentry *d;
char *buf = dirbuf;
@@ -1193,14 +970,11 @@ int sys_readdir(struct tcb *t, int fd, int count, char *dirbuf)
/* Check address is in task's utcb */
if (fd < 0 || fd > TASK_FILES_MAX || !t->files->fd[fd].vnum)
if (fd < 0 || fd > TASK_FILES_MAX ||
!t->files->fd[fd].vmfile->vnode)
return -EBADF;
vnum = t->files->fd[fd].vnum;
/* Lookup vnode */
if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum)))
return -EINVAL;
v = t->files->fd[fd].vmfile->vnode;
d = link_to_struct(v->dentries.next, struct dentry, vref);
@@ -1232,3 +1006,239 @@ int sys_readdir(struct tcb *t, int fd, int count, char *dirbuf)
return nbytes + total;
}
/* FIXME:
* - Is it already open?
* - Check flags and mode.
*/
int sys_open(struct tcb *task, const char *pathname,
int flags, unsigned int mode)
{
struct pathdata *pdata;
struct vnode *v;
struct vm_file *vmfile;
int retval;
int fd;
/* Parse path data */
if (IS_ERR(pdata = pathdata_parse(pathname,
alloca(strlen(pathname) + 1),
task)))
return (int)pdata;
/* Creating new file */
if (flags & O_CREAT) {
/* Make sure mode identifies a file */
mode |= S_IFREG;
/* Create new vnode */
if (IS_ERR(v = vfs_vnode_create(task, pdata, mode))) {
retval = (int)v;
goto out;
}
} else {
/* Not creating. Get the existing vnode */
if (IS_ERR(v = vfs_vnode_lookup_bypath(pdata))) {
retval = (int)v;
goto out;
}
}
/* Get a new fd */
BUG_ON((fd = id_new(task->files->fdpool)) < 0);
retval = fd;
/* Check if that vm_file is already in the list */
list_foreach_struct(vmfile, &global_vm_files.list, list) {
/* Compare vnode pointer */
if (vmfile->vnode == v) {
/* Add a reference to it from the task */
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
retval = 0;
goto out;
}
}
/* Create a new vm_file for this vnode */
if (IS_ERR(vmfile = vfs_file_create())) {
retval = (int)vmfile;
goto out;
}
/* Assign file information */
vmfile->vnode = v;
vmfile->length = vmfile->vnode->size;
/* Add a reference to it from the task */
vmfile->vm_obj.pager = &file_pager;
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
/* Add to file list */
global_add_vm_file(vmfile);
out:
if (retval < 0)
printf("Thread %d Opening %s, fd: %d, error: %d\n", task->tid, pathname, fd, retval);
else
printf("Thread %d Opening %s, fd: %d, vnum: %lx, vnode: %p\n", task->tid, pathname, fd, v->vnum, v);
pathdata_destroy(pdata);
return retval;
}
#if 0
/*
* Different from vfs_open(), which validates an already opened
* file descriptor, this call opens a new vfs file by the pager
* using the given path. The vnum handle and file length is returned
* since the pager uses this information to access file pages.
*/
int vfs_open_bypath(const char *pathname, unsigned long *vnum, unsigned long *length)
{
struct pathdata *pdata;
struct tcb *task = 0;
struct vnode *v;
int retval;
/* Parse path data */
if (IS_ERR(pdata = pathdata_parse(pathname,
alloca(strlen(pathname) + 1),
task)))
return (int)pdata;
/* Search the vnode by that path */
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
retval = (int)v;
goto out;
}
*vnum = v->vnum;
*length = v->size;
return 0;
out:
pathdata_destroy(pdata);
return retval;
}
/*
* Initialise a new file and the descriptor for it from given file data.
* Could be called by an actual task or a pager
*/
struct vm_file *do_open2(struct tcb *task, int fd, unsigned long vnum, unsigned long length)
{
struct vm_file *vmfile;
/* Is this an open by a task (as opposed to by the pager)? */
if (task) {
/* fd slot must be empty */
BUG_ON(task->files->fd[fd].vnum != 0);
BUG_ON(task->files->fd[fd].cursor != 0);
/* Assign vnum to given fd on the task */
task->files->fd[fd].vnum = vnum;
task->files->fd[fd].cursor = 0;
}
/* Check if that vm_file is already in the list */
list_foreach_struct(vmfile, &global_vm_files.list, list) {
/* Check whether it is a vfs file and if so vnums match. */
if ((vmfile->type & VM_FILE_VFS) &&
vm_file_to_vnum(vmfile) == vnum) {
/* Task opener? */
if (task)
/* Add a reference to it from the task */
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
return vmfile;
}
}
/* Otherwise allocate a new one for this vnode */
if (IS_ERR(vmfile = vfs_file_create()))
return vmfile;
/* Initialise and add a reference to it from the task */
vm_file_to_vnum(vmfile) = vnum;
vmfile->length = length;
vmfile->vm_obj.pager = &file_pager;
/* Task opener? */
if (task)
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
/* Add to file list */
global_add_vm_file(vmfile);
return vmfile;
}
/*
* When a task does a read/write/mmap request on a file, if
* the file descriptor is unknown to the pager, this call
* asks vfs if that file has been opened, and any other
* relevant information.
*/
int file_open(struct tcb *task, int fd)
{
struct vnode *v;
struct vm_file *vmfile;
if (fd < 0 || fd > TASK_FILES_MAX)
return -EINVAL;
/* Check if that fd has been opened */
if (!task->files->fd[fd].vnum)
return -EBADF;
/* Search the vnode by that vnum */
if (IS_ERR(v = vfs_lookup_byvnum(vfs_root.pivot->sb,
task->files->fd[fd].vnum)))
return (int)v;
/* Cursor must be zero */
BUG_ON(task->files->fd[fd].cursor != 0);
/* Check that vm_file is already in the list */
list_foreach_struct(vmfile, &global_vm_files.list, list) {
/* Check whether it is a vfs file and if so vnums match. */
if ((vmfile->type & VM_FILE_VFS) &&
vm_file_to_vnum(vmfile) == v->vnum) {
/* Add a reference to it from the task */
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
return 0;
}
}
/* Otherwise allocate a new one for this vnode */
if (IS_ERR(vmfile = vfs_file_create()))
return (int)vmfile;
/* Assign file information */
vm_file_to_vnum(vmfile) = v->vnum;
vmfile->length = v->size;
/* Add a reference to it from the task */
vmfile->vm_obj.pager = &file_pager;
task->files->fd[fd].vmfile = vmfile;
vmfile->openers++;
/* Add to file list */
global_add_vm_file(vmfile);
return 0;
}
#endif

View File

@@ -328,13 +328,12 @@ void *__sys_mmap(struct tcb *task, void *start, size_t length, int prot,
{
unsigned int vmflags = 0;
struct vm_file *file = 0;
int err;
/* Check file validity */
if (!(flags & MAP_ANONYMOUS))
if (!task->files->fd[fd].vmfile)
if ((err = file_open(task, fd)) < 0)
return PTR_ERR(err);
if (fd < 0 || fd > TASK_FILES_MAX ||
!task->files->fd[fd].vmfile)
return PTR_ERR(-EBADF);
/* Check file offset is page aligned */
if (!is_page_aligned(file_offset))

View File

@@ -13,6 +13,7 @@
#include <file.h>
#include <init.h>
#include <l4/api/errno.h>
#include <fs.h>
struct page *page_init(struct page *page)
{
@@ -97,11 +98,11 @@ int file_page_out(struct vm_object *vm_obj, unsigned long page_offset)
/* Map the page to self */
l4_map(paddr, vaddr, 1, MAP_USR_RW_FLAGS, self_tid());
//printf("%s/%s: Writing to vnode %lu, at pgoff 0x%lu, %d pages, buf at %p\n",
// __TASKNAME__, __FUNCTION__, vm_file_to_vnum(f), page_offset, 1, vaddr);
printf("%s/%s: Writing to vnode %lu, at pgoff 0x%lu, %d pages, buf at %p\n",
__TASKNAME__, __FUNCTION__, f->vnode->vnum, page_offset, 1, vaddr);
/* Syscall to vfs to write page back to file. */
if ((err = vfs_write(vm_file_to_vnum(f), page_offset, 1, vaddr)) < 0)
if ((err = vfs_write(f->vnode, page_offset, 1, vaddr)) < 0)
goto out_err;
/* Unmap it from self */
@@ -146,10 +147,13 @@ struct page *file_page_in(struct vm_object *vm_obj, unsigned long page_offset)
l4_map(paddr, vaddr, 1, MAP_USR_RW_FLAGS, self_tid());
/* Syscall to vfs to read into the page. */
if ((err = vfs_read(vm_file_to_vnum(f), page_offset,
if ((err = vfs_read(f->vnode, page_offset,
1, vaddr)) < 0)
goto out_err;
printf("%s/%s: Reading into vnode %lu, at pgoff 0x%lu, %d pages, buf at %p\n",
__TASKNAME__, __FUNCTION__, f->vnode->vnum, page_offset, 1, vaddr);
/* Unmap it from vfs */
l4_unmap(vaddr, 1, self_tid());
l4_del_virtual(vaddr, 1);
@@ -249,6 +253,7 @@ int bootfile_release_pages(struct vm_object *vm_obj)
return 0;
}
#if 0
/* Returns the page with given offset in this vm_object */
struct page *bootfile_page_in(struct vm_object *vm_obj,
unsigned long offset)
@@ -330,13 +335,26 @@ int init_boot_files(struct initdata *initdata)
return 0;
}
#endif
/*
* FIXME:
* Problem is that devzero is a character device and we don't have a
* character device subsystem yet.
*
* Therefore even though the vm_file for devzero requires a vnode,
* currently it has no vnode field, and the information (the zero page)
* that needs to be stored in the dynamic vnode is now stored in the
* field file_private_data in the vm_file, which really needs to be
* removed.
*/
/* Returns the page with given offset in this vm_object */
struct page *devzero_page_in(struct vm_object *vm_obj,
unsigned long page_offset)
{
struct vm_file *devzero = vm_object_to_file(vm_obj);
struct page *zpage = devzero->priv_data;
struct page *zpage = devzero->private_file_data;
BUG_ON(!(devzero->type & VM_FILE_DEVZERO));
@@ -381,7 +399,7 @@ int init_devzero(void)
/* Allocate and initialise devzero file */
devzero = vm_file_create();
devzero->type = VM_FILE_DEVZERO;
devzero->priv_data = zpage;
devzero->private_file_data = zpage;
devzero->length = page_align(~0UL); /* So we dont wraparound to 0! */
devzero->vm_obj.npages = __pfn(devzero->length);
devzero->vm_obj.pager = &devzero_pager;

View File

@@ -25,8 +25,15 @@
#include <posix/sys/shm.h>
#include <posix/sys/types.h>
/*
* FIXME:
*
* All this stuff is stored as file_private_data in the vm_file.
* However they need to have a pseudo-fs infrastructure that
* stores all internals under the vnode->inode field.
*/
#define shm_file_to_desc(shm_file) \
((struct shm_descriptor *)shm_file->priv_data)
((struct shm_descriptor *)(shm_file)->private_file_data)
/* Unique shared memory ids */
static struct id_pool *shm_ids;
@@ -181,7 +188,7 @@ void shm_destroy_priv_data(struct vm_file *shm_file)
BUG_ON(id_del(shm_ids, shm_desc->shmid) < 0);
/* Now delete the private data itself */
kfree(shm_file->priv_data);
kfree(shm_file_to_desc(shm_file));
}
/* Creates an shm area and glues its details with shm pager and devzero */
@@ -213,7 +220,7 @@ struct vm_file *shm_new(key_t key, unsigned long npages)
/* Initialise the file */
shm_file->length = __pfn_to_addr(npages);
shm_file->type = VM_FILE_SHM;
shm_file->priv_data = shm_desc;
shm_file->private_file_data = shm_desc;
shm_file->destroy_priv_data = shm_destroy_priv_data;
/* Initialise the vm object */

View File

@@ -80,8 +80,6 @@ int mm0_test_global_vm_integrity(void)
vmstat.vm_files++;
if (f->type == VM_FILE_SHM)
vmstat.shm_files++;
else if (f->type == VM_FILE_BOOTFILE)
vmstat.boot_files++;
else if (f->type == VM_FILE_VFS)
vmstat.vfs_files++;
else if (f->type == VM_FILE_DEVZERO)

View File

@@ -82,8 +82,6 @@ void vm_object_print(struct vm_object *vmo)
if (f->type == VM_FILE_DEVZERO)
ftype = "devzero";
else if (f->type == VM_FILE_BOOTFILE)
ftype = "bootfile";
else if (f->type == VM_FILE_SHM)
ftype = "shm file";
else if (f->type == VM_FILE_VFS)
@@ -160,7 +158,6 @@ struct vm_file *vfs_file_create(void)
if (IS_ERR(f))
return f;
f->priv_data = kzalloc(sizeof(struct vfs_file_data));
f->type = VM_FILE_VFS;
return f;
@@ -195,11 +192,11 @@ int vm_object_delete(struct vm_object *vmo)
if (vmo->flags & VM_OBJ_FILE) {
f = vm_object_to_file(vmo);
BUG_ON(!list_empty(&f->list));
if (f->priv_data) {
if (f->private_file_data) {
if (f->destroy_priv_data)
f->destroy_priv_data(f);
else
kfree(f->priv_data);
kfree(f->private_file_data);
}
kfree(f);
} else if (vmo->flags & VM_OBJ_SHADOW)

View File

@@ -15,15 +15,15 @@ int main(int argc, char *argv[]);
int __container_init(int argc, char **argv)
{
void *envp = &argv[argc + 1];
char *pagerval;
// char *pagerval;
if ((char *)envp == *argv)
envp = &argv[argc];
__libposix_init(envp);
pagerval = getenv("pagerid");
printf("Pager id: %s\n", pagerval);
//pagerval = getenv("pagerid");
//printf("Pager id: %s\n", pagerval);
/* Generic L4 thread initialisation */
__l4_init();

View File

@@ -3,7 +3,7 @@
#define __TASKNAME__ "test0"
//#define TEST_VERBOSE_PRINT
#define TEST_VERBOSE_PRINT
#if defined (TEST_VERBOSE_PRINT)
#define test_printf(...) printf(__VA_ARGS__)
#else

View File

@@ -36,6 +36,7 @@ int main(int argc, char *argv[])
printf("\n%s: Running POSIX API tests.\n", __TASKNAME__);
/*
dirtest();
mmaptest();
@@ -55,7 +56,7 @@ int main(int argc, char *argv[])
if (parent_of_all == getpid()) {
user_mutex_test();
}
*/
exectest(parent_of_all);
while (1)

View File

@@ -1,15 +1,17 @@
/*
* Execve test.
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <tests.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <alloca.h>
#define PAGE_SIZE 0x1000
extern char _start_test_exec[];
extern char _end_test_exec[];
@@ -19,20 +21,25 @@ int exectest(pid_t parent_of_all)
int fd, err;
void *exec_start = (void *)_start_test_exec;
unsigned long size = _end_test_exec - _start_test_exec;
char filename[128];
char env_string[30];
int left, cnt;
char *argv[5];
char filename[128];
char *envp[2];
char env_string[30];
void *buf;
memset(filename, 0, 128);
sprintf(filename, "/home/bahadir/execfile%d", getpid());
sprintf(filename, "/execfile%d", getpid());
/* First create a new file and write the executable data to that file */
if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)) < 0) {
err = errno;
test_printf("OPEN: %d, for %s\n", errno, filename);
/* If it is a minor error like EEXIST, create one with different name */
/*
* If it is a minor error like EEXIST,
* create one with different name
*/
if (errno == EEXIST) {
sprintf(filename, "/home/bahadir/execfile%d-2",
getpid());
@@ -49,7 +56,7 @@ int exectest(pid_t parent_of_all)
}
left = size;
test_printf("Writing %d bytes to %s\n", left, filename);
test_printf("Writing %x bytes to %s\n", left, filename);
while (left != 0) {
if ((cnt = write(fd, exec_start, left)) < 0)
goto out_err;
@@ -60,6 +67,22 @@ int exectest(pid_t parent_of_all)
goto out_err;
}
/* Reopen */
if ((fd = open(filename, O_RDONLY, S_IRWXU)) < 0) {
err = errno;
test_printf("OPEN: %d, for %s\n", errno, filename);
}
printf("Reopened %s\n", filename);
buf = alloca(PAGE_SIZE);
read(fd, buf, PAGE_SIZE);
if (memcmp(exec_start, buf, PAGE_SIZE))
printf("First page of read and written file doesn't match\n");
else
printf("First page matches.\n");
/* Set up some arguments */
argv[0] = "FIRST ARG";
argv[1] = "SECOND ARG";

View File

@@ -17,7 +17,7 @@ int forktest(void)
/* 16 forks */
for (int i = 0; i < 3; i++) {
for (int i = 0; i < 1; i++) {
test_printf("%d: Forking...\n", getpid());
if (fork() < 0)
goto out_err;