mirror of
https://github.com/drasko/codezero.git
synced 2026-10-01 09:39:27 +02:00
Integrated vm_files with vnodes. execve is not working as expected.
This commit is contained in:
@@ -358,7 +358,7 @@ int memfs_vnode_readdir(struct vnode *v)
|
|||||||
* in the vnode cache. If it's not there, the lookup function
|
* in the vnode cache. If it's not there, the lookup function
|
||||||
* allocates and reads it for us as well.
|
* 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) {
|
if (!newv) {
|
||||||
printf("Filesystem seems to be broken. Directory has"
|
printf("Filesystem seems to be broken. Directory has"
|
||||||
"inode number: %d, but no such inode found.\n",
|
"inode number: %d, but no such inode found.\n",
|
||||||
|
|||||||
@@ -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
|
* 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.
|
* 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;
|
struct vnode *v;
|
||||||
int err;
|
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
|
* 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.
|
* 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;
|
const char *firstcomp;
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ int vfs_mount_root(struct superblock *sb)
|
|||||||
* Lookup the root vnode of this superblock.
|
* Lookup the root vnode of this superblock.
|
||||||
* The root superblock has vnode number 0.
|
* 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;
|
vfs_root.sb = sb;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
#include <posix/sys/types.h> /* FIXME: Remove this and refer to internal headers */
|
#include <posix/sys/types.h> /* FIXME: Remove this and refer to internal headers */
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
|
|
||||||
int vfs_read(unsigned long vnum, unsigned long f_offset, unsigned long npages,
|
int vfs_read(struct vnode *v, unsigned long f_offset,
|
||||||
void *pagebuf);
|
unsigned long npages, void *pagebuf);
|
||||||
int vfs_write(unsigned long vnum, unsigned long f_offset, unsigned long npages,
|
int vfs_write(struct vnode *v, unsigned long f_offset,
|
||||||
void *pagebuf);
|
unsigned long npages, void *pagebuf);
|
||||||
int sys_read(struct tcb *sender, int fd, void *buf, int count);
|
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_write(struct tcb *sender, int fd, void *buf, int count);
|
||||||
int sys_lseek(struct tcb *sender, int fd, off_t offset, int whence);
|
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,
|
int read_file_pages(struct vm_file *vmfile, unsigned long pfn_start,
|
||||||
unsigned long pfn_end);
|
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);
|
struct vm_file *vfs_file_create(void);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
struct vm_file;
|
struct vm_file;
|
||||||
|
|
||||||
struct file_descriptor {
|
struct file_descriptor {
|
||||||
unsigned long vnum;
|
|
||||||
unsigned long cursor;
|
unsigned long cursor;
|
||||||
struct vm_file *vmfile;
|
struct vm_file *vmfile;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ extern struct vfs_mountpoint vfs_root;
|
|||||||
int vfs_mount_root(struct superblock *sb);
|
int vfs_mount_root(struct superblock *sb);
|
||||||
struct vnode *generic_vnode_lookup(struct vnode *thisnode, struct pathdata *p,
|
struct vnode *generic_vnode_lookup(struct vnode *thisnode, struct pathdata *p,
|
||||||
const char *component);
|
const char *component);
|
||||||
struct vnode *vfs_lookup_bypath(struct pathdata *p);
|
struct vnode *vfs_vnode_lookup_bypath(struct pathdata *p);
|
||||||
struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum);
|
struct vnode *vfs_vnode_lookup_byvnum(struct superblock *sb, unsigned long vnum);
|
||||||
|
|
||||||
int vfs_init(void);
|
int vfs_init(void);
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,6 @@
|
|||||||
enum VM_FILE_TYPE {
|
enum VM_FILE_TYPE {
|
||||||
VM_FILE_DEVZERO = 1,
|
VM_FILE_DEVZERO = 1,
|
||||||
VM_FILE_VFS,
|
VM_FILE_VFS,
|
||||||
VM_FILE_BOOTFILE,
|
|
||||||
VM_FILE_SHM,
|
VM_FILE_SHM,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,17 +65,10 @@ struct page {
|
|||||||
};
|
};
|
||||||
extern struct page *page_array;
|
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 page_refcnt(x) ((x)->count + 1)
|
||||||
#define virtual(x) ((x)->virtual)
|
#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 phys_to_page(x) (page_array + __pfn((x) - membank[0].start))
|
||||||
#define page_to_phys(x) (__pfn_to_addr((((void *)(x)) - \
|
#define page_to_phys(x) (__pfn_to_addr((((void *)(x)) - \
|
||||||
(void *)page_array) / \
|
(void *)page_array) / \
|
||||||
@@ -131,11 +123,12 @@ struct vm_object {
|
|||||||
struct vm_file {
|
struct vm_file {
|
||||||
int openers;
|
int openers;
|
||||||
struct link list;
|
struct link list;
|
||||||
unsigned long length;
|
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
|
unsigned long length;
|
||||||
struct vm_object vm_obj;
|
struct vm_object vm_obj;
|
||||||
void (*destroy_priv_data)(struct vm_file *f);
|
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 */
|
/* To create per-vma vm_object lists */
|
||||||
@@ -210,7 +203,6 @@ struct page *find_page(struct vm_object *obj, unsigned long pfn);
|
|||||||
|
|
||||||
/* Pagers */
|
/* Pagers */
|
||||||
extern struct vm_pager file_pager;
|
extern struct vm_pager file_pager;
|
||||||
extern struct vm_pager bootfile_pager;
|
|
||||||
extern struct vm_pager devzero_pager;
|
extern struct vm_pager devzero_pager;
|
||||||
extern struct vm_pager swap_pager;
|
extern struct vm_pager swap_pager;
|
||||||
|
|
||||||
|
|||||||
@@ -153,11 +153,6 @@ void handle_requests(void)
|
|||||||
return; /* else we're done */
|
return; /* else we're done */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: Fix all these syscalls to read any
|
|
||||||
* buffer data from the caller task's utcb.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* FS0 System calls */
|
/* FS0 System calls */
|
||||||
case L4_IPC_TAG_OPEN:
|
case L4_IPC_TAG_OPEN:
|
||||||
ret = sys_open(sender, utcb_full_buffer(), (int)mr[0], (unsigned int)mr[1]);
|
ret = sys_open(sender, utcb_full_buffer(), (int)mr[0], (unsigned int)mr[1]);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <l4/lib/list.h>
|
#include <l4/lib/list.h>
|
||||||
#include <vm_area.h>
|
#include <vm_area.h>
|
||||||
#include <lib/malloc.h>
|
#include <lib/malloc.h>
|
||||||
|
#include <fs.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is yet unused, it is more of an anticipation
|
* 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)
|
unsigned long pfn_offset)
|
||||||
{
|
{
|
||||||
struct vm_file *f = vm_object_to_file(vm_obj);
|
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;
|
struct page *page;
|
||||||
|
|
||||||
/* Check if its within device boundary */
|
/* Check if its within device boundary */
|
||||||
|
|||||||
+20
-28
@@ -37,13 +37,13 @@ int task_setup_from_executable(struct vm_file *vmfile, struct tcb *task,
|
|||||||
|
|
||||||
int init_execve(char *filepath)
|
int init_execve(char *filepath)
|
||||||
{
|
{
|
||||||
unsigned long vnum, length;
|
|
||||||
struct vm_file *vmfile;
|
struct vm_file *vmfile;
|
||||||
struct exec_file_desc efd;
|
struct exec_file_desc efd;
|
||||||
struct tcb *new_task;
|
struct tcb *new_task, *self;
|
||||||
struct args_struct args, env;
|
struct args_struct args, env;
|
||||||
char *env_string = "pagerid=0";
|
char *env_string = "pagerid=0";
|
||||||
int err;
|
int err;
|
||||||
|
int fd;
|
||||||
|
|
||||||
struct task_ids ids = {
|
struct task_ids ids = {
|
||||||
.tid = TASK_ID_INVALID,
|
.tid = TASK_ID_INVALID,
|
||||||
@@ -65,33 +65,26 @@ int init_execve(char *filepath)
|
|||||||
strncpy(env.argv[0], env_string, strlen(env_string) + 1);
|
strncpy(env.argv[0], env_string, strlen(env_string) + 1);
|
||||||
env.size = sizeof(env.argv) + strlen(env_string) + 1;
|
env.size = sizeof(env.argv) + strlen(env_string) + 1;
|
||||||
|
|
||||||
/* Get file info from vfs */
|
self = find_task(self_tid());
|
||||||
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
|
|
||||||
if ((fd = sys_open(self, filepath,
|
if ((fd = sys_open(self, filepath,
|
||||||
O_RDONLY, 0)) < 0) {
|
O_RDONLY, 0)) < 0) {
|
||||||
printf("FATAL: Could not open file "
|
printf("FATAL: Could not open file "
|
||||||
"to execute initial task.\n");
|
"to write initial task.\n");
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
#endif
|
/* Get the low-level vmfile */
|
||||||
|
vmfile = self->files->fd[fd].vmfile;
|
||||||
|
|
||||||
if (IS_ERR(new_task = task_create(0, &ids,
|
if (IS_ERR(new_task = task_create(0, &ids,
|
||||||
THREAD_NEW_SPACE,
|
THREAD_NEW_SPACE,
|
||||||
TCB_NO_SHARING))) {
|
TCB_NO_SHARING))) {
|
||||||
vm_file_put(vmfile); /* FIXME: sys_close() ??? */
|
sys_close(self, fd);
|
||||||
return (int)new_task;
|
return (int)new_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill and validate tcb memory segment markers from executable file */
|
/* Fill and validate tcb memory segment markers from executable file */
|
||||||
if ((err = task_setup_from_executable(vmfile, new_task, &efd)) < 0) {
|
if ((err = task_setup_from_executable(vmfile, new_task, &efd)) < 0) {
|
||||||
vm_file_put(vmfile);
|
sys_close(self, fd);
|
||||||
kfree(new_task);
|
kfree(new_task);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -99,7 +92,7 @@ int init_execve(char *filepath)
|
|||||||
/* Map task's new segment markers as virtual memory regions */
|
/* Map task's new segment markers as virtual memory regions */
|
||||||
if ((err = task_mmap_segments(new_task, vmfile,
|
if ((err = task_mmap_segments(new_task, vmfile,
|
||||||
&efd, &args, &env)) < 0) {
|
&efd, &args, &env)) < 0) {
|
||||||
vm_file_put(vmfile);
|
sys_close(self, fd);
|
||||||
kfree(new_task);
|
kfree(new_task);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -123,29 +116,28 @@ int init_execve(char *filepath)
|
|||||||
int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
|
int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
|
||||||
struct args_struct *env)
|
struct args_struct *env)
|
||||||
{
|
{
|
||||||
unsigned long vnum, length;
|
|
||||||
struct vm_file *vmfile;
|
struct vm_file *vmfile;
|
||||||
struct exec_file_desc efd;
|
struct exec_file_desc efd;
|
||||||
struct tcb *new_task, *tgleader;
|
struct tcb *new_task, *tgleader, *self;
|
||||||
int err;
|
int err;
|
||||||
|
int fd;
|
||||||
|
|
||||||
/* Get file info from vfs */
|
self = find_task(self_tid());
|
||||||
if ((err = vfs_open_bypath(filename, &vnum, &length)) < 0)
|
if ((fd = sys_open(self, filename, O_RDONLY, 0)) < 0)
|
||||||
return err;
|
return fd;
|
||||||
|
|
||||||
/* Create and get the file structure */
|
/* Get the low-level vmfile */
|
||||||
if (IS_ERR(vmfile = do_open2(0, 0, vnum, length)))
|
vmfile = self->files->fd[fd].vmfile;
|
||||||
return (int)vmfile;
|
|
||||||
|
|
||||||
/* Create a new tcb */
|
/* Create a new tcb */
|
||||||
if (IS_ERR(new_task = tcb_alloc_init(TCB_NO_SHARING))) {
|
if (IS_ERR(new_task = tcb_alloc_init(TCB_NO_SHARING))) {
|
||||||
vm_file_put(vmfile);
|
sys_close(self, fd);
|
||||||
return (int)new_task;
|
return (int)new_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill and validate tcb memory segment markers from executable file */
|
/* Fill and validate tcb memory segment markers from executable file */
|
||||||
if ((err = task_setup_from_executable(vmfile, new_task, &efd)) < 0) {
|
if ((err = task_setup_from_executable(vmfile, new_task, &efd)) < 0) {
|
||||||
vm_file_put(vmfile);
|
sys_close(self, fd);
|
||||||
kfree(new_task);
|
kfree(new_task);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -175,7 +167,7 @@ int do_execve(struct tcb *sender, char *filename, struct args_struct *args,
|
|||||||
* exit() except destroying the actual thread.
|
* exit() except destroying the actual thread.
|
||||||
*/
|
*/
|
||||||
if ((err = execve_recycle_task(new_task, tgleader)) < 0) {
|
if ((err = execve_recycle_task(new_task, tgleader)) < 0) {
|
||||||
vm_file_put(vmfile);
|
sys_close(self, fd);
|
||||||
kfree(new_task);
|
kfree(new_task);
|
||||||
return err;
|
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 */
|
/* Map task's new segment markers as virtual memory regions */
|
||||||
if ((err = task_mmap_segments(new_task, vmfile,
|
if ((err = task_mmap_segments(new_task, vmfile,
|
||||||
&efd, args, env)) < 0) {
|
&efd, args, env)) < 0) {
|
||||||
vm_file_put(vmfile);
|
sys_close(self, fd);
|
||||||
kfree(new_task);
|
kfree(new_task);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -330,8 +330,7 @@ int vm_object_is_deletable(struct vm_object *obj)
|
|||||||
return 0;
|
return 0;
|
||||||
else if (f->type == VM_FILE_SHM)
|
else if (f->type == VM_FILE_SHM)
|
||||||
return 1;
|
return 1;
|
||||||
else if (f->type == VM_FILE_BOOTFILE ||
|
else if (f->type == VM_FILE_VFS) {
|
||||||
f->type == VM_FILE_VFS) {
|
|
||||||
if (f->openers == 0)
|
if (f->openers == 0)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
|
|||||||
+286
-276
@@ -64,15 +64,9 @@ int page_copy(struct page *dst, struct page *src,
|
|||||||
return 0;
|
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)
|
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 */
|
/* Ensure vnode is not a directory */
|
||||||
if (vfs_isdir(v))
|
if (vfs_isdir(v))
|
||||||
return -EISDIR;
|
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. */
|
/* Creates a node under a directory, e.g. a file, directory. */
|
||||||
struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata,
|
struct vnode *vfs_vnode_create(struct tcb *task, struct pathdata *pdata,
|
||||||
unsigned int mode)
|
unsigned int mode)
|
||||||
{
|
{
|
||||||
struct vnode *vparent, *newnode;
|
struct vnode *vparent, *newnode;
|
||||||
const char *nodename;
|
const char *nodename;
|
||||||
@@ -143,7 +100,7 @@ struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata,
|
|||||||
nodename = pathdata_last_component(pdata);
|
nodename = pathdata_last_component(pdata);
|
||||||
|
|
||||||
/* Check that the parent directory exists. */
|
/* 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;
|
return vparent;
|
||||||
|
|
||||||
/* The parent vnode must be a directory. */
|
/* The parent vnode must be a directory. */
|
||||||
@@ -158,62 +115,6 @@ struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata,
|
|||||||
return newnode;
|
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)
|
int sys_mkdir(struct tcb *task, const char *pathname, unsigned int mode)
|
||||||
{
|
{
|
||||||
struct pathdata *pdata;
|
struct pathdata *pdata;
|
||||||
@@ -230,7 +131,7 @@ int sys_mkdir(struct tcb *task, const char *pathname, unsigned int mode)
|
|||||||
mode |= S_IFDIR;
|
mode |= S_IFDIR;
|
||||||
|
|
||||||
/* Create the directory or fail */
|
/* 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;
|
ret = (int)v;
|
||||||
|
|
||||||
/* Destroy extracted path data */
|
/* Destroy extracted path data */
|
||||||
@@ -251,7 +152,7 @@ int sys_chdir(struct tcb *task, const char *pathname)
|
|||||||
return (int)pdata;
|
return (int)pdata;
|
||||||
|
|
||||||
/* Get the vnode */
|
/* Get the vnode */
|
||||||
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
|
if (IS_ERR(v = vfs_vnode_lookup_bypath(pdata))) {
|
||||||
ret = (int)v;
|
ret = (int)v;
|
||||||
goto out;
|
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)
|
int sys_fstat(struct tcb *task, int fd, void *statbuf)
|
||||||
{
|
{
|
||||||
struct vnode *v;
|
/* Check that fd is valid */
|
||||||
unsigned long vnum;
|
if (fd < 0 || fd > TASK_FILES_MAX ||
|
||||||
|
!task->files->fd[fd].vmfile)
|
||||||
/* Get the vnum */
|
|
||||||
if (fd < 0 || fd > TASK_FILES_MAX || !task->files->fd[fd].vnum)
|
|
||||||
return -EBADF;
|
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 in the c0-style stat structure */
|
||||||
fill_kstat(v, statbuf);
|
fill_kstat(task->files->fd[fd].vmfile->vnode, statbuf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -325,7 +217,7 @@ int sys_stat(struct tcb *task, const char *pathname, void *statbuf)
|
|||||||
return (int)pdata;
|
return (int)pdata;
|
||||||
|
|
||||||
/* Get the vnode */
|
/* Get the vnode */
|
||||||
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
|
if (IS_ERR(v = vfs_vnode_lookup_bypath(pdata))) {
|
||||||
ret = (int)v;
|
ret = (int)v;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -339,121 +231,6 @@ out:
|
|||||||
return ret;
|
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.
|
* 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)) {
|
if (IS_ERR(page)) {
|
||||||
printf("%s: %s:Could not read page %d "
|
printf("%s: %s:Could not read page %d "
|
||||||
"from file with vnum: 0x%lu\n", __TASKNAME__,
|
"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;
|
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.
|
* 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)
|
unsigned long npages, void *pagebuf)
|
||||||
{
|
{
|
||||||
struct vnode *v;
|
|
||||||
int fwrite_end;
|
int fwrite_end;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
// printf("%s/%s\n", __TASKNAME__, __FUNCTION__);
|
// 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 */
|
/* Ensure vnode is not a directory */
|
||||||
if (vfs_isdir(v))
|
if (vfs_isdir(v))
|
||||||
return -EISDIR;
|
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) */
|
/* Writes updated file stats back to vfs. (e.g. new file size) */
|
||||||
int vfs_update_file_stats(struct vm_file *f)
|
int vfs_update_file_stats(struct vm_file *f)
|
||||||
{
|
{
|
||||||
unsigned long vnum = vm_file_to_vnum(f);
|
struct vnode *v = f->vnode;
|
||||||
struct vnode *v;
|
|
||||||
|
|
||||||
/* Lookup vnode */
|
|
||||||
if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum)))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
v->size = f->length;
|
v->size = f->length;
|
||||||
v->sb->ops->write_vnode(v->sb, v);
|
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) {
|
if (err < 0) {
|
||||||
printf("%s: %s:Could not write page %d "
|
printf("%s: %s:Could not write page %d "
|
||||||
"to file with vnum: 0x%lu\n", __TASKNAME__,
|
"to file with vnum: 0x%lu\n", __TASKNAME__,
|
||||||
__FUNCTION__, f_offset, vm_file_to_vnum(f));
|
__FUNCTION__, f_offset, f->vnode->vnum);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -635,6 +402,10 @@ int fsync_common(struct tcb *task, int fd)
|
|||||||
if (!task->files->fd[fd].vmfile)
|
if (!task->files->fd[fd].vmfile)
|
||||||
return 0;
|
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 */
|
/* Finish I/O on file */
|
||||||
if ((err = flush_file_pages(task->files->fd[fd].vmfile)) < 0)
|
if ((err = flush_file_pages(task->files->fd[fd].vmfile)) < 0)
|
||||||
return err;
|
return err;
|
||||||
@@ -651,6 +422,9 @@ void vm_file_put(struct vm_file *file)
|
|||||||
/* No links or openers, delete the file */
|
/* No links or openers, delete the file */
|
||||||
vm_file_delete(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;
|
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)
|
if (!task->files->fd[fd].vmfile)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reduce file refcount etc. */
|
/* Reduce file refcount etc. */
|
||||||
vm_file_put(task->files->fd[fd].vmfile);
|
vm_file_put(task->files->fd[fd].vmfile);
|
||||||
|
|
||||||
task->files->fd[fd].vnum = 0;
|
|
||||||
task->files->fd[fd].cursor = 0;
|
task->files->fd[fd].cursor = 0;
|
||||||
task->files->fd[fd].vmfile = 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;
|
left = count;
|
||||||
|
|
||||||
/* Copy the first page and unmap. */
|
/* 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;
|
copy_offset = (unsigned long)buf;
|
||||||
page_copy(head, task_virt_to_page(task, copy_offset),
|
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->flags |= VM_DIRTY;
|
||||||
head->owner->flags |= VM_DIRTY;
|
head->owner->flags |= VM_DIRTY;
|
||||||
left -= copysize;
|
left -= copysize;
|
||||||
@@ -928,10 +705,10 @@ int sys_read(struct tcb *task, int fd, void *buf, int count)
|
|||||||
struct vm_file *vmfile;
|
struct vm_file *vmfile;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* Check fd validity */
|
/* Check that fd is valid */
|
||||||
if (!task->files->fd[fd].vmfile)
|
if (fd < 0 || fd > TASK_FILES_MAX ||
|
||||||
if ((ret = file_open(task, fd)) < 0)
|
!task->files->fd[fd].vmfile)
|
||||||
return ret;
|
return -EBADF;
|
||||||
|
|
||||||
|
|
||||||
/* Check count validity */
|
/* Check count validity */
|
||||||
@@ -998,10 +775,10 @@ int sys_write(struct tcb *task, int fd, void *buf, int count)
|
|||||||
struct vm_file *vmfile;
|
struct vm_file *vmfile;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* Check fd validity */
|
/* Check that fd is valid */
|
||||||
if (!task->files->fd[fd].vmfile)
|
if (fd < 0 || fd > TASK_FILES_MAX ||
|
||||||
if ((ret = file_open(task, fd)) < 0)
|
!task->files->fd[fd].vmfile)
|
||||||
return ret;
|
return -EBADF;
|
||||||
|
|
||||||
/* Check count validity */
|
/* Check count validity */
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
@@ -1009,7 +786,6 @@ int sys_write(struct tcb *task, int fd, void *buf, int count)
|
|||||||
else if (!count)
|
else if (!count)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
/* Check user buffer validity. */
|
/* Check user buffer validity. */
|
||||||
if ((ret = pager_validate_user_range(task, buf,
|
if ((ret = pager_validate_user_range(task, buf,
|
||||||
(unsigned long)count,
|
(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;
|
vmfile = task->files->fd[fd].vmfile;
|
||||||
cursor = task->files->fd[fd].cursor;
|
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 */
|
/* See what pages user wants to write */
|
||||||
pfn_wstart = __pfn(cursor);
|
pfn_wstart = __pfn(cursor);
|
||||||
pfn_wend = __pfn(page_align_up(cursor + count));
|
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;
|
int retval = 0;
|
||||||
unsigned long long total, cursor;
|
unsigned long long total, cursor;
|
||||||
|
|
||||||
/* Check fd validity */
|
/* Check that fd is valid */
|
||||||
if (!task->files->fd[fd].vmfile)
|
if (fd < 0 || fd > TASK_FILES_MAX ||
|
||||||
if ((retval = file_open(task, fd)) < 0)
|
!task->files->fd[fd].vmfile)
|
||||||
return retval;
|
return -EBADF;
|
||||||
|
|
||||||
/* Offset validity */
|
/* Offset validity */
|
||||||
if (offset < 0)
|
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 dirent_size = sizeof(struct dirent);
|
||||||
int total = 0, nbytes = 0;
|
int total = 0, nbytes = 0;
|
||||||
unsigned long vnum;
|
|
||||||
struct vnode *v;
|
struct vnode *v;
|
||||||
struct dentry *d;
|
struct dentry *d;
|
||||||
char *buf = dirbuf;
|
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 */
|
/* 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;
|
return -EBADF;
|
||||||
|
|
||||||
vnum = t->files->fd[fd].vnum;
|
v = t->files->fd[fd].vmfile->vnode;
|
||||||
|
|
||||||
/* Lookup vnode */
|
|
||||||
if (!(v = vfs_lookup_byvnum(vfs_root.pivot->sb, vnum)))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
d = link_to_struct(v->dentries.next, struct dentry, vref);
|
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;
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -328,13 +328,12 @@ void *__sys_mmap(struct tcb *task, void *start, size_t length, int prot,
|
|||||||
{
|
{
|
||||||
unsigned int vmflags = 0;
|
unsigned int vmflags = 0;
|
||||||
struct vm_file *file = 0;
|
struct vm_file *file = 0;
|
||||||
int err;
|
|
||||||
|
|
||||||
/* Check file validity */
|
/* Check file validity */
|
||||||
if (!(flags & MAP_ANONYMOUS))
|
if (!(flags & MAP_ANONYMOUS))
|
||||||
if (!task->files->fd[fd].vmfile)
|
if (fd < 0 || fd > TASK_FILES_MAX ||
|
||||||
if ((err = file_open(task, fd)) < 0)
|
!task->files->fd[fd].vmfile)
|
||||||
return PTR_ERR(err);
|
return PTR_ERR(-EBADF);
|
||||||
|
|
||||||
/* Check file offset is page aligned */
|
/* Check file offset is page aligned */
|
||||||
if (!is_page_aligned(file_offset))
|
if (!is_page_aligned(file_offset))
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <file.h>
|
#include <file.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <l4/api/errno.h>
|
#include <l4/api/errno.h>
|
||||||
|
#include <fs.h>
|
||||||
|
|
||||||
struct page *page_init(struct page *page)
|
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 */
|
/* Map the page to self */
|
||||||
l4_map(paddr, vaddr, 1, MAP_USR_RW_FLAGS, self_tid());
|
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",
|
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);
|
__TASKNAME__, __FUNCTION__, f->vnode->vnum, page_offset, 1, vaddr);
|
||||||
|
|
||||||
/* Syscall to vfs to write page back to file. */
|
/* 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;
|
goto out_err;
|
||||||
|
|
||||||
/* Unmap it from self */
|
/* 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());
|
l4_map(paddr, vaddr, 1, MAP_USR_RW_FLAGS, self_tid());
|
||||||
|
|
||||||
/* Syscall to vfs to read into the page. */
|
/* 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)
|
1, vaddr)) < 0)
|
||||||
goto out_err;
|
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 */
|
/* Unmap it from vfs */
|
||||||
l4_unmap(vaddr, 1, self_tid());
|
l4_unmap(vaddr, 1, self_tid());
|
||||||
l4_del_virtual(vaddr, 1);
|
l4_del_virtual(vaddr, 1);
|
||||||
@@ -249,6 +253,7 @@ int bootfile_release_pages(struct vm_object *vm_obj)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Returns the page with given offset in this vm_object */
|
/* Returns the page with given offset in this vm_object */
|
||||||
struct page *bootfile_page_in(struct vm_object *vm_obj,
|
struct page *bootfile_page_in(struct vm_object *vm_obj,
|
||||||
unsigned long offset)
|
unsigned long offset)
|
||||||
@@ -330,13 +335,26 @@ int init_boot_files(struct initdata *initdata)
|
|||||||
|
|
||||||
return 0;
|
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 */
|
/* Returns the page with given offset in this vm_object */
|
||||||
struct page *devzero_page_in(struct vm_object *vm_obj,
|
struct page *devzero_page_in(struct vm_object *vm_obj,
|
||||||
unsigned long page_offset)
|
unsigned long page_offset)
|
||||||
{
|
{
|
||||||
struct vm_file *devzero = vm_object_to_file(vm_obj);
|
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));
|
BUG_ON(!(devzero->type & VM_FILE_DEVZERO));
|
||||||
|
|
||||||
@@ -381,7 +399,7 @@ int init_devzero(void)
|
|||||||
/* Allocate and initialise devzero file */
|
/* Allocate and initialise devzero file */
|
||||||
devzero = vm_file_create();
|
devzero = vm_file_create();
|
||||||
devzero->type = VM_FILE_DEVZERO;
|
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->length = page_align(~0UL); /* So we dont wraparound to 0! */
|
||||||
devzero->vm_obj.npages = __pfn(devzero->length);
|
devzero->vm_obj.npages = __pfn(devzero->length);
|
||||||
devzero->vm_obj.pager = &devzero_pager;
|
devzero->vm_obj.pager = &devzero_pager;
|
||||||
|
|||||||
@@ -25,8 +25,15 @@
|
|||||||
#include <posix/sys/shm.h>
|
#include <posix/sys/shm.h>
|
||||||
#include <posix/sys/types.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) \
|
#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 */
|
/* Unique shared memory ids */
|
||||||
static struct id_pool *shm_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);
|
BUG_ON(id_del(shm_ids, shm_desc->shmid) < 0);
|
||||||
|
|
||||||
/* Now delete the private data itself */
|
/* 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 */
|
/* 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 */
|
/* Initialise the file */
|
||||||
shm_file->length = __pfn_to_addr(npages);
|
shm_file->length = __pfn_to_addr(npages);
|
||||||
shm_file->type = VM_FILE_SHM;
|
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;
|
shm_file->destroy_priv_data = shm_destroy_priv_data;
|
||||||
|
|
||||||
/* Initialise the vm object */
|
/* Initialise the vm object */
|
||||||
|
|||||||
@@ -80,8 +80,6 @@ int mm0_test_global_vm_integrity(void)
|
|||||||
vmstat.vm_files++;
|
vmstat.vm_files++;
|
||||||
if (f->type == VM_FILE_SHM)
|
if (f->type == VM_FILE_SHM)
|
||||||
vmstat.shm_files++;
|
vmstat.shm_files++;
|
||||||
else if (f->type == VM_FILE_BOOTFILE)
|
|
||||||
vmstat.boot_files++;
|
|
||||||
else if (f->type == VM_FILE_VFS)
|
else if (f->type == VM_FILE_VFS)
|
||||||
vmstat.vfs_files++;
|
vmstat.vfs_files++;
|
||||||
else if (f->type == VM_FILE_DEVZERO)
|
else if (f->type == VM_FILE_DEVZERO)
|
||||||
|
|||||||
@@ -82,8 +82,6 @@ void vm_object_print(struct vm_object *vmo)
|
|||||||
|
|
||||||
if (f->type == VM_FILE_DEVZERO)
|
if (f->type == VM_FILE_DEVZERO)
|
||||||
ftype = "devzero";
|
ftype = "devzero";
|
||||||
else if (f->type == VM_FILE_BOOTFILE)
|
|
||||||
ftype = "bootfile";
|
|
||||||
else if (f->type == VM_FILE_SHM)
|
else if (f->type == VM_FILE_SHM)
|
||||||
ftype = "shm file";
|
ftype = "shm file";
|
||||||
else if (f->type == VM_FILE_VFS)
|
else if (f->type == VM_FILE_VFS)
|
||||||
@@ -160,7 +158,6 @@ struct vm_file *vfs_file_create(void)
|
|||||||
if (IS_ERR(f))
|
if (IS_ERR(f))
|
||||||
return f;
|
return f;
|
||||||
|
|
||||||
f->priv_data = kzalloc(sizeof(struct vfs_file_data));
|
|
||||||
f->type = VM_FILE_VFS;
|
f->type = VM_FILE_VFS;
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
@@ -195,11 +192,11 @@ int vm_object_delete(struct vm_object *vmo)
|
|||||||
if (vmo->flags & VM_OBJ_FILE) {
|
if (vmo->flags & VM_OBJ_FILE) {
|
||||||
f = vm_object_to_file(vmo);
|
f = vm_object_to_file(vmo);
|
||||||
BUG_ON(!list_empty(&f->list));
|
BUG_ON(!list_empty(&f->list));
|
||||||
if (f->priv_data) {
|
if (f->private_file_data) {
|
||||||
if (f->destroy_priv_data)
|
if (f->destroy_priv_data)
|
||||||
f->destroy_priv_data(f);
|
f->destroy_priv_data(f);
|
||||||
else
|
else
|
||||||
kfree(f->priv_data);
|
kfree(f->private_file_data);
|
||||||
}
|
}
|
||||||
kfree(f);
|
kfree(f);
|
||||||
} else if (vmo->flags & VM_OBJ_SHADOW)
|
} else if (vmo->flags & VM_OBJ_SHADOW)
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ int main(int argc, char *argv[]);
|
|||||||
int __container_init(int argc, char **argv)
|
int __container_init(int argc, char **argv)
|
||||||
{
|
{
|
||||||
void *envp = &argv[argc + 1];
|
void *envp = &argv[argc + 1];
|
||||||
char *pagerval;
|
// char *pagerval;
|
||||||
|
|
||||||
if ((char *)envp == *argv)
|
if ((char *)envp == *argv)
|
||||||
envp = &argv[argc];
|
envp = &argv[argc];
|
||||||
|
|
||||||
__libposix_init(envp);
|
__libposix_init(envp);
|
||||||
|
|
||||||
pagerval = getenv("pagerid");
|
//pagerval = getenv("pagerid");
|
||||||
printf("Pager id: %s\n", pagerval);
|
//printf("Pager id: %s\n", pagerval);
|
||||||
|
|
||||||
/* Generic L4 thread initialisation */
|
/* Generic L4 thread initialisation */
|
||||||
__l4_init();
|
__l4_init();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#define __TASKNAME__ "test0"
|
#define __TASKNAME__ "test0"
|
||||||
|
|
||||||
//#define TEST_VERBOSE_PRINT
|
#define TEST_VERBOSE_PRINT
|
||||||
#if defined (TEST_VERBOSE_PRINT)
|
#if defined (TEST_VERBOSE_PRINT)
|
||||||
#define test_printf(...) printf(__VA_ARGS__)
|
#define test_printf(...) printf(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
printf("\n%s: Running POSIX API tests.\n", __TASKNAME__);
|
printf("\n%s: Running POSIX API tests.\n", __TASKNAME__);
|
||||||
|
|
||||||
|
/*
|
||||||
dirtest();
|
dirtest();
|
||||||
|
|
||||||
mmaptest();
|
mmaptest();
|
||||||
@@ -55,7 +56,7 @@ int main(int argc, char *argv[])
|
|||||||
if (parent_of_all == getpid()) {
|
if (parent_of_all == getpid()) {
|
||||||
user_mutex_test();
|
user_mutex_test();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
exectest(parent_of_all);
|
exectest(parent_of_all);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Execve test.
|
* Execve test.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <tests.h>
|
#include <tests.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <alloca.h>
|
||||||
|
|
||||||
|
#define PAGE_SIZE 0x1000
|
||||||
|
|
||||||
extern char _start_test_exec[];
|
extern char _start_test_exec[];
|
||||||
extern char _end_test_exec[];
|
extern char _end_test_exec[];
|
||||||
@@ -19,20 +21,25 @@ int exectest(pid_t parent_of_all)
|
|||||||
int fd, err;
|
int fd, err;
|
||||||
void *exec_start = (void *)_start_test_exec;
|
void *exec_start = (void *)_start_test_exec;
|
||||||
unsigned long size = _end_test_exec - _start_test_exec;
|
unsigned long size = _end_test_exec - _start_test_exec;
|
||||||
|
char filename[128];
|
||||||
|
char env_string[30];
|
||||||
int left, cnt;
|
int left, cnt;
|
||||||
char *argv[5];
|
char *argv[5];
|
||||||
char filename[128];
|
|
||||||
char *envp[2];
|
char *envp[2];
|
||||||
char env_string[30];
|
void *buf;
|
||||||
|
|
||||||
memset(filename, 0, 128);
|
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 */
|
/* 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) {
|
if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)) < 0) {
|
||||||
err = errno;
|
err = errno;
|
||||||
test_printf("OPEN: %d, for %s\n", errno, filename);
|
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) {
|
if (errno == EEXIST) {
|
||||||
sprintf(filename, "/home/bahadir/execfile%d-2",
|
sprintf(filename, "/home/bahadir/execfile%d-2",
|
||||||
getpid());
|
getpid());
|
||||||
@@ -49,7 +56,7 @@ int exectest(pid_t parent_of_all)
|
|||||||
}
|
}
|
||||||
|
|
||||||
left = size;
|
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) {
|
while (left != 0) {
|
||||||
if ((cnt = write(fd, exec_start, left)) < 0)
|
if ((cnt = write(fd, exec_start, left)) < 0)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
@@ -60,6 +67,22 @@ int exectest(pid_t parent_of_all)
|
|||||||
goto out_err;
|
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 */
|
/* Set up some arguments */
|
||||||
argv[0] = "FIRST ARG";
|
argv[0] = "FIRST ARG";
|
||||||
argv[1] = "SECOND ARG";
|
argv[1] = "SECOND ARG";
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ int forktest(void)
|
|||||||
|
|
||||||
|
|
||||||
/* 16 forks */
|
/* 16 forks */
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 1; i++) {
|
||||||
test_printf("%d: Forking...\n", getpid());
|
test_printf("%d: Forking...\n", getpid());
|
||||||
if (fork() < 0)
|
if (fork() < 0)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|||||||
Reference in New Issue
Block a user