Added posix code

This commit is contained in:
Bahadir Balban
2009-09-29 21:55:59 +03:00
parent 54272ccb63
commit f0bb0a4657
478 changed files with 63161 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
#ifndef __BDEV_H__
#define __BDEV_H__
/*
* This is a mock-up compiled in blockdev buffer, to be used temporarily.
*/
void *vfs_rootdev_open(void);
#endif/* __BDEV_H__ */

View File

@@ -0,0 +1,6 @@
#ifndef __FS0_MM_H__
#define __FS0_MM_H__
#endif /* __FS0_MM_H__ */

View File

@@ -0,0 +1,171 @@
/*
* VFS definitions.
*
* Copyright (C) 2007, 2008 Bahadir Balban.
*/
#ifndef __FS_H__
#define __FS_H__
#include <l4/lib/list.h>
#include <l4/macros.h>
#include <l4lib/types.h>
#include <stat.h>
#include <path.h>
typedef void (*vnode_op_t)(void);
typedef void (*file_op_t)(void);
struct dentry;
struct file;
struct file_system_type;
struct superblock;
struct vnode;
struct dentry_ops {
int (*compare)(struct dentry *d, const char *n);
};
/* Operations that work on file content */
struct file_ops {
/* Read a vnode's contents by page range */
int (*read)(struct vnode *v, unsigned long pfn,
unsigned long npages, void *buf);
/* Write a vnode's contents by page range */
int (*write)(struct vnode *v, unsigned long pfn,
unsigned long npages, void *buf);
file_op_t open;
file_op_t close;
file_op_t mmap;
file_op_t lseek;
file_op_t flush;
file_op_t fsync;
};
/* Operations that work on vnode fields and associations between vnodes */
struct vnode_ops {
vnode_op_t create;
struct vnode *(*lookup)(struct vnode *root, struct pathdata *pdata,
const char *component);
int (*readdir)(struct vnode *v);
int (*filldir)(void *buf, struct vnode *v, int count);
vnode_op_t link;
vnode_op_t unlink;
int (*mkdir)(struct vnode *parent, const char *name);
struct vnode *(*mknod)(struct vnode *parent, const char *name,
unsigned int mode);
vnode_op_t rmdir;
vnode_op_t rename;
vnode_op_t getattr;
vnode_op_t setattr;
};
struct superblock_ops {
int (*write_sb)(struct superblock *sb);
/*
* Given a vnum, reads the disk-inode and copies its data
* into the vnode's generic fields
*/
int (*read_vnode)(struct superblock *sb, struct vnode *v);
/* Writes vnode's generic fields into the disk-inode structure */
int (*write_vnode)(struct superblock *sb, struct vnode *v);
/* Allocates a disk-inode along with a vnode, and associates the two */
struct vnode *(*alloc_vnode)(struct superblock *sb);
/* Frees the vnode and the corresponding on-disk inode */
int (*free_vnode)(struct superblock *sb, struct vnode *v);
};
#define VFS_DNAME_MAX 256
struct dentry {
int refcnt;
char name[VFS_DNAME_MAX];
struct dentry *parent; /* Parent dentry */
struct link child; /* List of dentries with same parent */
struct link children; /* List of children dentries */
struct link vref; /* For vnode's dirent reference list */
struct link cache_list; /* Dentry cache reference */
struct vnode *vnode; /* The vnode associated with dentry */
struct dentry_ops ops;
};
/*
* Buffer that maintains directory content for a directory vnode. This is the
* only vnode content that fs0 maintains. All other file data is in mm0 page
* cache.
*/
struct dirbuf {
unsigned long npages;
int dirty;
u8 *buffer;
};
/* Posix-style dirent format used by userspace. Returned by sys_readdir() */
#define DIRENT_NAME_MAX 32
struct dirent {
u32 inum; /* Inode number */
u32 offset; /* Dentry offset in its buffer */
u16 rlength; /* Record length */
u8 name[DIRENT_NAME_MAX]; /* Name string */
};
struct vnode {
unsigned long vnum; /* Filesystem-wide unique vnode id */
int refcnt; /* Reference counter */
int links; /* Number of hard links */
struct superblock *sb; /* Reference to superblock */
struct vnode_ops ops; /* Operations on this vnode */
struct file_ops fops; /* File-related operations on this vnode */
struct link dentries; /* Dirents that refer to this vnode */
struct link cache_list; /* For adding the vnode to vnode cache */
struct dirbuf dirbuf; /* Only directory buffers are kept */
u32 mode; /* Permissions and vnode type */
u32 owner; /* Owner */
u64 atime; /* Last access time */
u64 mtime; /* Last content modification */
u64 ctime; /* Last vnode modification */
u64 size; /* Size of contents */
void *inode; /* Ptr to fs-specific inode */
};
/* FS0 vfs specific macros */
/* Check if directory */
#define vfs_isdir(v) S_ISDIR((v)->mode)
/* Set vnode type */
#define vfs_set_type(v, type) {v->mode &= ~S_IFMT; v->mode |= S_IFMT & type; }
struct fstype_ops {
struct superblock *(*get_superblock)(void *buf);
};
#define VFS_FSNAME_MAX 256
struct file_system_type {
char name[VFS_FSNAME_MAX];
unsigned long magic;
struct fstype_ops ops;
struct link list; /* Member of list of all fs types */
struct link sblist; /* List of superblocks with this type */
};
struct superblock *get_superblock(void *buf);
struct superblock {
u64 fssize;
unsigned int blocksize;
struct link list;
struct file_system_type *fs;
struct superblock_ops *ops;
struct vnode *root;
void *fs_super;
};
void vfs_mount_fs(struct superblock *sb);
extern struct dentry_ops generic_dentry_operations;
#endif /* __FS_H__ */

View File

@@ -0,0 +1,13 @@
#ifndef __GLOBALS_H__
#define __GLOBALS_H__
struct global_list {
int total;
struct link list;
};
extern struct global_list global_vm_files;
extern struct global_list global_vm_objects;
extern struct global_list global_tasks;
#endif /* __GLOBALS_H__ */

View File

@@ -0,0 +1,7 @@
#ifndef __INIT_H__
#define __INIT_H__
/* FS0 initialisation */
int initialise(void);
#endif /* __INIT_H__ */

View File

@@ -0,0 +1,44 @@
#ifndef __LIB_BIT_H__
#define __LIB_BIT_H__
#include <l4lib/types.h>
unsigned int __clz(unsigned int bitvector);
int find_and_set_first_free_bit(u32 *word, unsigned int lastbit);
int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit,
int nbits);
int check_and_clear_bit(u32 *word, int bit);
int check_and_clear_contig_bits(u32 *word, int first, int nbits);
int check_and_set_bit(u32 *word, int bit);
/* Set */
static inline void setbit(unsigned int *w, unsigned int flags)
{
*w |= flags;
}
/* Clear */
static inline void clrbit(unsigned int *w, unsigned int flags)
{
*w &= ~flags;
}
/* Test */
static inline int tstbit(unsigned int *w, unsigned int flags)
{
return *w & flags;
}
/* Test and clear */
static inline int tstclr(unsigned int *w, unsigned int flags)
{
int res = tstbit(w, flags);
clrbit(w, flags);
return res;
}
#endif /* __LIB_BIT_H__ */

View File

@@ -0,0 +1,29 @@
#ifndef __MM0_IDPOOL_H__
#define __MM0_IDPOOL_H__
#include <lib/bit.h>
#include <l4/macros.h>
#include INC_GLUE(memory.h)
#include <string.h>
struct id_pool {
int nwords;
u32 bitmap[];
};
/* Copy one id pool to another by calculating its size */
static inline void id_pool_copy(struct id_pool *to, struct id_pool *from, int totalbits)
{
int nwords = BITWISE_GETWORD(totalbits);
memcpy(to, from, nwords * SZ_WORD + sizeof(struct id_pool));
}
struct id_pool *id_pool_new_init(int mapsize);
int id_new(struct id_pool *pool);
int id_del(struct id_pool *pool, int id);
int id_get(struct id_pool *pool, int id);
int ids_new_contiguous(struct id_pool *pool, int numids);
int ids_del_contiguous(struct id_pool *pool, int first, int numids);
#endif /* __MM0_IDPOOL_H__ */

View File

@@ -0,0 +1,19 @@
#ifndef __PRIVATE_MALLOC_H__
#define __PRIVATE_MALLOC_H__
#include <stddef.h>
#include <string.h>
void *kmalloc(size_t size);
void kfree(void *blk);
static inline void *kzalloc(size_t size)
{
void *buf = kmalloc(size);
memset(buf, 0, size);
return buf;
}
#endif /*__PRIVATE_MALLOC_H__ */

View File

@@ -0,0 +1,9 @@
#ifndef __LIB_PATHSTR_H__
#define __LIB_PATHSTR_H__
char *strreverse(char *str);
char *splitpath_end(char **path, char sep);
char *splitpath(char **str, char sep);
#endif /* __LIB_PATHSTR_H__ */

View File

@@ -0,0 +1,15 @@
/*
* Fake spinlock for future multi-threaded mm0
*/
#ifndef __MM0_SPINLOCK_H__
#define __MM0_SPINLOCK_H__
struct spinlock {
int lock;
};
static inline void spin_lock_init(struct spinlock *s) { }
static inline void spin_lock(struct spinlock *s) { }
static inline void spin_unlock(struct spinlock *s) { }
#endif /* __MM0_SPINLOCK_H__ */

View File

@@ -0,0 +1,17 @@
/*
* Virtual address allocation pool (for shm)
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __VADDR_H__
#define __VADDR_H__
#include <lib/idpool.h>
void vaddr_pool_init(struct id_pool *pool, unsigned long start,
unsigned long end);
void *vaddr_new(struct id_pool *pool, int npages);
int vaddr_del(struct id_pool *, void *vaddr, int npages);
#endif /* __VADDR_H__ */

View File

@@ -0,0 +1,49 @@
/*
* Simple linker script for userspace or svc tasks.
*
* Copyright (C) 2007 Bahadir Balban
*/
/*
* The only catch with this linker script is that everything
* is linked starting at virtual_base, and loaded starting
* at physical_base. virtual_base is the predefined region
* of virtual memory for userland applications. physical_base
* is determined at build-time, it is one of the subsequent pages
* that come after the kernel image's load area.
*/
/* USER_AREA_START, see memlayout.h */
virtual_base = 0x10000000;
physical_base = 0x8000;
__stack = (0x20000000 - 0x1000 - 8); /* First page before env/args page */
/* INCLUDE "include/physical_base.lds" */
/* physical_base = 0x228000; */
offset = virtual_base - physical_base;
ENTRY(_start)
SECTIONS
{
. = virtual_base;
_start_text = .;
.text : AT (ADDR(.text) - offset) { *(.text.head) *(.text) }
/* rodata is needed else your strings will link at physical! */
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
.data : AT (ADDR(.data) - offset)
{
. = ALIGN(4K); /* Align UTCB to page boundary */
_start_utcb = .;
*(.utcb)
_end_utcb = .;
. = ALIGN(4K);
_start_bdev = .;
*(.data.memfs)
_end_bdev = .;
*(.data)
}
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
_end = .;
}

View File

@@ -0,0 +1,7 @@
#ifndef __MEMFS_FILE_H__
#define __MEMFS_FILE_H__
extern struct file_ops memfs_file_operations;
extern struct dentry_ops memfs_dentry_operations;
#endif /* __MEMFS_FILE_H__ */

View File

@@ -0,0 +1,97 @@
/*
* The disk layout of our simple unix-like filesystem.
*
* Copyright (C) 2007, 2008 Bahadir Balban
*/
#ifndef __MEMFS_LAYOUT_H__
#define __MEMFS_LAYOUT_H__
#include <l4lib/types.h>
#include <l4/lib/list.h>
#include <l4/macros.h>
#include <l4/config.h>
#include INC_GLUE(memory.h)
#include <memcache/memcache.h>
#include <lib/idpool.h>
/*
*
* Filesystem layout:
*
* |---------------|
* | Superblock |
* |---------------|
*
* Superblock layout:
*
* |---------------|
* | inode cache |
* |---------------|
* | dentry cache |
* |---------------|
* | block cache |
* |---------------|
*
*/
/*
* These fixed filesystem limits make it much easier to implement
* filesystem space allocation.
*/
#define MEMFS_TOTAL_SIZE SZ_4MB
#define MEMFS_TOTAL_INODES 128
#define MEMFS_TOTAL_BLOCKS 2000
#define MEMFS_FMAX_BLOCKS 40
#define MEMFS_BLOCK_SIZE PAGE_SIZE
#define MEMFS_MAGIC 0xB
#define MEMFS_NAME "memfs"
#define MEMFS_NAME_SIZE 8
struct memfs_inode {
u32 inum; /* Inode number */
u32 mode; /* File permissions */
u32 owner; /* File owner */
u64 atime; /* Last access time */
u64 mtime; /* Last content modification */
u64 ctime; /* Last inode modification */
u64 size; /* Size of contents */
void *block[MEMFS_FMAX_BLOCKS]; /* Number of blocks */
};
struct memfs_superblock {
u32 magic; /* Filesystem magic number */
char name[8];
u32 blocksize; /* Filesystem block size */
u64 fmaxblocks; /* Maximum number of blocks per file */
u64 fssize; /* Total size of filesystem */
unsigned long root_vnum; /* The root vnum of this superblock */
struct link inode_cache_list; /* Chain of alloc caches */
struct link block_cache_list; /* Chain of alloc caches */
struct id_pool *ipool; /* Index pool for inodes */
struct id_pool *bpool; /* Index pool for blocks */
struct memfs_inode *inode[MEMFS_TOTAL_INODES]; /* Table of inodes */
void *block[MEMFS_TOTAL_BLOCKS]; /* Table of fs blocks */
} __attribute__ ((__packed__));
#define MEMFS_DNAME_MAX 32
struct memfs_dentry {
u32 inum; /* Inode number */
u32 offset; /* Dentry offset in its buffer */
u16 rlength; /* Record length */
u8 name[MEMFS_DNAME_MAX]; /* Name string */
};
extern struct vnode_ops memfs_vnode_operations;
extern struct superblock_ops memfs_superblock_operations;
extern struct file_ops memfs_file_operations;
int memfs_format_filesystem(void *buffer);
struct memfs_inode *memfs_create_inode(struct memfs_superblock *sb);
void memfs_register_fstype(struct link *);
struct superblock *memfs_get_superblock(void *block);
int memfs_generate_superblock(void *block);
void *memfs_alloc_block(struct memfs_superblock *sb);
int memfs_free_block(struct memfs_superblock *sb, void *block);
#endif /* __MEMFS_LAYOUT_H__ */

View File

@@ -0,0 +1,7 @@
#ifndef __MEMFS_VNODE_H__
#define __MEMFS_VNODE_H__
#include <fs.h>
#endif /* __MEMFS_VNODE_H__ */

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2008 Bahadir Balban
*
* Path lookup related information
*/
#ifndef __PATH_H__
#define __PATH_H__
#include <l4/lib/list.h>
#include <task.h>
/*
* FIXME:
* These ought to be strings and split/comparison functions should
* always use strings because formats like UTF-8 wouldn't work.
*/
#define VFS_CHAR_SEP '/'
#define VFS_STR_ROOTDIR "/"
#define VFS_STR_PARDIR ".."
#define VFS_STR_CURDIR "."
#define VFS_STR_XATDIR "...."
struct pathdata {
struct link list;
struct vnode *vstart;
};
struct pathcomp {
struct link list;
const char *str;
};
struct pathdata *pathdata_parse(const char *pathname, char *pathbuf,
struct tcb *task);
void pathdata_destroy(struct pathdata *p);
/* Destructive, i.e. unlinks those components from list */
const char *pathdata_next_component(struct pathdata *pdata);
const char *pathdata_last_component(struct pathdata *pdata);
#endif /* __PATH_H__ */

View File

@@ -0,0 +1,82 @@
#ifndef __FS0_STAT_H__
#define __FS0_STAT_H__
/* Posix definitions for file mode flags (covers type and access permissions) */
#define S_IFMT 00170000
#define S_IFSOCK 0140000
#define S_IFLNK 0120000
#define S_IFREG 0100000
#define S_IFBLK 0060000
#define S_IFDIR 0040000
#define S_IFCHR 0020000
#define S_IFIFO 0010000
#define S_ISUID 0004000
#define S_ISGID 0002000
#define S_ISVTX 0001000
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
#define O_ACCMODE 00000003
#define O_RDONLY 00000000
#define O_WRONLY 00000001
#define O_RDWR 00000002
#define O_CREAT 00000100
#define O_EXCL 00000200
#define O_NOCTTY 00000400
#define O_TRUNC 00001000
#define O_APPEND 00002000
#define O_NONBLOCK 00004000
#define O_SYNC 00010000
#define FASYNC 00020000
#define O_DIRECT 00040000
#define O_LARGEFILE 00100000
#define O_DIRECTORY 00200000
#define O_NOFOLLOW 00400000
#define O_NOATIME 01000000
#define O_NDELAY O_NONBLOCK
/*
* Internal codezero-specific stat structure.
* This is converted to posix stat in userspace
*/
struct kstat {
u64 vnum;
u32 mode;
int links;
u16 uid;
u16 gid;
u64 size;
int blksize;
u64 atime;
u64 mtime;
u64 ctime;
};
#endif /* __FS0_STAT_H__ */

View File

@@ -0,0 +1,35 @@
/*
* System call function signatures.
*
* Copyright (C) 2007, 2008 Bahadir Balban
*/
#ifndef __FS0_SYSCALLS_H__
#define __FS0_SYSCALLS_H__
#include <task.h>
/* Posix calls */
int sys_open(struct tcb *sender, const char *pathname, int flags, u32 mode);
int sys_readdir(struct tcb *sender, int fd, void *buf, int count);
int sys_mkdir(struct tcb *sender, const char *pathname, unsigned int mode);
int sys_chdir(struct tcb *sender, const char *pathname);
/* Calls from pager that completes a posix call */
int pager_open_bypath(struct tcb *pager, char *pathname);
int pager_sys_open(struct tcb *sender, l4id_t opener, int fd);
int pager_sys_read(struct tcb *sender, unsigned long vnum, unsigned long f_offset,
unsigned long npages, void *pagebuf);
int pager_sys_write(struct tcb *sender, unsigned long vnum, unsigned long f_offset,
unsigned long npages, void *pagebuf);
int pager_sys_close(struct tcb *sender, l4id_t closer, int fd);
int pager_update_stats(struct tcb *sender, unsigned long vnum,
unsigned long newsize);
int pager_notify_fork(struct tcb *sender, l4id_t parentid,
l4id_t childid, unsigned long utcb_address,
unsigned int flags);
int pager_notify_exit(struct tcb *sender, l4id_t tid);
#endif /* __FS0_SYSCALLS_H__ */

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2008 Bahadir Balban
*/
#ifndef __FS0_TASK_H__
#define __FS0_TASK_H__
#include <lib/idpool.h>
#include <l4/lib/list.h>
#include <l4/api/kip.h>
#define __TASKNAME__ __VFSNAME__
#define TCB_NO_SHARING 0
#define TCB_SHARED_VM (1 << 0)
#define TCB_SHARED_FILES (1 << 1)
#define TCB_SHARED_FS (1 << 2)
#define TASK_FILES_MAX 32
struct task_fd_head {
int fd[TASK_FILES_MAX];
struct id_pool *fdpool;
int tcb_refs;
};
struct task_fs_data {
struct vnode *curdir;
struct vnode *rootdir;
int tcb_refs;
};
/* Thread control block, fs0 portion */
struct tcb {
l4id_t tid;
struct link list;
unsigned long shpage_address;
struct task_fd_head *files;
struct task_fs_data *fs_data;
};
/* Structures used when receiving new task info from pager */
struct task_data {
unsigned long tid;
unsigned long shpage_address;
};
struct task_data_head {
unsigned long total;
struct task_data tdata[];
};
struct tcb *find_task(int tid);
int init_task_data(void);
#endif /* __FS0_TASK_H__ */

View File

@@ -0,0 +1,90 @@
#ifndef __VFS_H__
#define __VFS_H__
#include <fs.h>
#include <lib/malloc.h>
#include <l4/lib/list.h>
#include <memfs/memfs.h>
#include <l4/macros.h>
#include <stdio.h>
#include <task.h>
#include <path.h>
extern struct link vnode_cache;
extern struct link dentry_cache;
/*
* This is a temporary origacement for page cache support provided by mm0.
* Normally mm0 tracks all vnode pages, but this is used to track pages in
* directory vnodes, which are normally never mapped by tasks.
*/
static inline void *vfs_alloc_dirpage(struct vnode *v)
{
/*
* Urgh, we allocate from the block cache of memfs to store generic vfs directory
* pages. This is currently the quickest we can allocate page-aligned memory.
*/
return memfs_alloc_block(v->sb->fs_super);
}
static inline void vfs_free_dirpage(struct vnode *v, void *block)
{
memfs_free_block(v->sb->fs_super, block);
}
static inline struct dentry *vfs_alloc_dentry(void)
{
struct dentry *d = kzalloc(sizeof(struct dentry));
link_init(&d->child);
link_init(&d->children);
link_init(&d->vref);
link_init(&d->cache_list);
return d;
}
static inline void vfs_free_dentry(struct dentry *d)
{
return kfree(d);
}
static inline struct vnode *vfs_alloc_vnode(void)
{
struct vnode *v = kzalloc(sizeof(struct vnode));
link_init(&v->dentries);
link_init(&v->cache_list);
return v;
}
static inline void vfs_free_vnode(struct vnode *v)
{
BUG(); /* Are the dentries freed ??? */
list_remove(&v->cache_list);
kfree(v);
}
static inline struct superblock *vfs_alloc_superblock(void)
{
struct superblock *sb = kmalloc(sizeof(struct superblock));
link_init(&sb->list);
return sb;
}
struct vfs_mountpoint {
struct superblock *sb; /* The superblock of mounted filesystem */
struct vnode *pivot; /* The dentry upon which we mount */
};
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);
#endif /* __VFS_H__ */