// #define KHEAP_START (KERNEL_MM_BASE + KCODE_MAX_SIZE)
// #define KHEAP_SIZE_MB 256
-#define PROC_TABLE_SIZE_MB 4
-#define PROC_START (KERNEL_MM_BASE + KCODE_MAX_SIZE)
-
#define VGA_FRAMEBUFFER 0xB8000
#define KCODE_SEG 0x08
#define DIRENT_NAME_MAX_LEN 256
+#define DT_FILE 0x0
+#define DT_DIR 0x1
+#define DT_SYMLINK 0x2
+#define DT_PIPE 0x2
+
struct dirent
{
unsigned int d_type;
int flags;
};
+// FIXME how do we invalidate corresponding v_dnodes given the v_inode?
+/*
+ Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
+ info of every process being accessible via file system. Each process's
+ creation will result a creation of a directory under the root of task fs
+ with it's pid as name. But that dir must delete when process is killed, and
+ such deletion does not mediated by vfs itself, so there is a need of cache
+ syncing.
+ And this is also the case of all ramfs where argumentation to file tree is
+ performed by third party.
+*/
+
struct v_inode
{
inode_t id;
int
vfs_getfd(int fd, struct v_fd** fd_s);
+int
+vfs_get_dtype(int itype);
+
void
pcache_init(struct pcache* pcache);
--- /dev/null
+#ifndef __LUNAIX_TASKFS_H
+#define __LUNAIX_TASKFS_H
+
+#include <lunaix/fs.h>
+#include <lunaix/fs/twimap.h>
+
+struct task_attribute
+{
+ struct llist_header siblings;
+ struct hlist_node attrs;
+ struct hstr key;
+ struct twimap* map_file;
+ char key_val[32];
+};
+
+void
+taskfs_init();
+
+void
+taskfs_export_attr(const char* key, struct twimap* attr_map_file);
+
+struct task_attribute*
+taskfs_get_attr(struct hstr* key);
+
+#endif /* __LUNAIX_TASKFS_H */
#define __LUNAIX_TWIFS_H
#include <lunaix/fs.h>
+#include <lunaix/fs/twimap.h>
#include <lunaix/spike.h>
struct twifs_node
} ops;
};
-struct twimap
-{
- void* index;
- void* buffer;
- void* data;
- size_t size_acc;
- void (*read)(struct twimap* mapping);
- int (*go_next)(struct twimap* mapping);
- void (*reset)(struct twimap* mapping);
-};
-
#define twinode_getdata(inode, type) \
({ \
struct twifs_node* twinode = (struct twifs_node*)(inode)->data; \
int
twifs_rm_node(struct twifs_node* node);
-#define twimap_index(twimap, type) ((type)((twimap)->index))
-#define twimap_data(twimap, type) ((type)((twimap)->data))
-
struct twimap*
twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...);
-void
-twimap_printf(struct twimap* mapping, const char* fmt, ...);
-
-int
-twimap_memcpy(struct twimap* mapping, const void* src, const size_t len);
-
-int
-twimap_memappend(struct twimap* mapping, const void* src, const size_t len);
-
#endif /* __LUNAIX_TWIFS_H */
--- /dev/null
+#ifndef __LUNAIX_TWIMAP_H
+#define __LUNAIX_TWIMAP_H
+
+#include <lunaix/types.h>
+
+#define twimap_index(twimap, type) ((type)((twimap)->index))
+#define twimap_data(twimap, type) ((type)((twimap)->data))
+
+extern struct v_file_ops twimap_file_ops;
+
+struct twimap
+{
+ void* index;
+ void* buffer;
+ void* data;
+ size_t size_acc;
+ void (*read)(struct twimap* mapping);
+ int (*go_next)(struct twimap* mapping);
+ void (*reset)(struct twimap* mapping);
+};
+
+int
+twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos);
+
+void
+twimap_printf(struct twimap* mapping, const char* fmt, ...);
+
+int
+twimap_memcpy(struct twimap* mapping, const void* src, const size_t len);
+
+int
+twimap_memappend(struct twimap* mapping, const void* src, const size_t len);
+
+struct twimap*
+twimap_create(void* data);
+
+#endif /* __LUNAIX_TWIMAP_H */
/* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */
#define PG_MOUNT_RANGE(l1_index) (701 <= l1_index && l1_index <= 703)
-#define PD_MOUNT_1 (PROC_START + MEM_4MB)
+#define PD_MOUNT_1 (KERNEL_MM_BASE + MEM_4MB)
#define PG_MOUNT_BASE (PD_MOUNT_1 + MEM_4MB)
#define PG_MOUNT_1 (PG_MOUNT_BASE)
#define PG_MOUNT_2 (PG_MOUNT_BASE + 0x1000)
/* ---- critical section end ---- */
+ struct llist_header tasks;
struct llist_header siblings;
struct llist_header children;
struct llist_header grp_member;
#define SCHED_TIME_SLICE 300
+#define PROC_TABLE_SIZE 8192
+#define MAX_PROCESS (PROC_TABLE_SIZE / sizeof(uintptr_t))
+
struct scheduler
{
struct proc_info** _procs;
struct dirent ent = { .d_offset = 0 };
int status;
while ((status = readdir(fd, &ent)) == 1) {
- printf(" %s\n", ent.d_name);
+ if (ent.d_type == DT_DIR) {
+ printf(" \033[3m%s\033[39;49m\n", ent.d_name);
+ } else {
+ printf(" %s\n", ent.d_name);
+ }
}
if (status < 0)
sh_printerr();
} else {
int sz;
- while ((sz = read(fd, cat_buf, 1024)) == 1024) {
- write(stdout, cat_buf, 1024);
+ while ((sz = read(fd, cat_buf, 1024)) > 0) {
+ write(stdout, cat_buf, sz);
}
if (sz < 0) {
sh_printerr();
- } else {
- write(stdout, cat_buf, sz);
}
close(fd);
printf("\n");
#include <lunaix/device.h>
+#include <lunaix/dirent.h>
#include <lunaix/fs.h>
#include <lunaix/fs/devfs.h>
#include <lunaix/spike.h>
return itype;
}
+int
+devfs_get_dtype(struct device* dev)
+{
+ switch (dev->dev_type & DEV_MSKIF) {
+ case DEV_IFCAT:
+ return DT_DIR;
+
+ default:
+ return DT_FILE;
+ }
+}
+
int
devfs_mknod(struct v_dnode* dnode, struct device* dev)
{
return 0;
}
dctx->read_complete_callback(
- dctx, dev->name.value, dev->name.len, devfs_get_itype(dev));
+ dctx, dev->name.value, dev->name.len, devfs_get_dtype(dev));
return 1;
}
#include <lunaix/fs.h>
#include <lunaix/fs/devfs.h>
#include <lunaix/fs/ramfs.h>
+#include <lunaix/fs/taskfs.h>
#include <lunaix/fs/twifs.h>
void
ramfs_init();
twifs_init();
devfs_init();
+ taskfs_init();
// ... more fs implementation
}
\ No newline at end of file
}
struct v_mount* parent_mnt = mnt_point->mnt;
- struct v_superblock* sb = vfs_sb_alloc();
+ struct v_superblock *sb = vfs_sb_alloc(), *old_sb = mnt_point->super_block;
sb->dev = device;
+ mnt_point->super_block = sb;
int errno = 0;
if (!(errno = fs->mount(sb, mnt_point))) {
- mnt_point->super_block = sb;
sb->fs = fs;
sb->root = mnt_point;
return errno;
cleanup:
+ mnt_point->super_block = old_sb;
vfs_sb_free(sb);
return errno;
}
llist_for_each(pos, n, &file->dnode->children, siblings)
{
if (i++ >= dctx->index) {
- dctx->read_complete_callback(
- dctx, pos->name.value, pos->name.len, 0);
+ dctx->read_complete_callback(dctx,
+ pos->name.value,
+ pos->name.len,
+ vfs_get_dtype(pos->inode->itype));
return 1;
}
}
#include <lunaix/clock.h>
#include <lunaix/fs.h>
#include <lunaix/fs/twifs.h>
+#include <lunaix/fs/twimap.h>
#include <lunaix/mm/cake.h>
#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
if (counter++ >= dctx->index) {
dctx->index = counter;
dctx->read_complete_callback(
- dctx, pos->name.value, pos->name.len, pos->itype);
+ dctx, pos->name.value, pos->name.len, vfs_get_dtype(pos->itype));
return 1;
}
}
fs_root = twifs_dir_node(NULL, NULL, 0, 0);
}
+int
+__twifs_twimap_file_read(struct v_inode* inode,
+ void* buf,
+ size_t len,
+ size_t fpos)
+{
+ struct twimap* map = twinode_getdata(inode, struct twimap*);
+ return twimap_read(map, buf, len, fpos);
+}
+
+struct twimap*
+twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ struct twimap* map = twimap_create(data);
+ struct twifs_node* node = twifs_file_node_vargs(parent, fmt, args);
+ node->ops.read = __twifs_twimap_file_read;
+ node->data = map;
+
+ return map;
+}
+
const struct v_file_ops twifs_file_ops = { .close = default_file_close,
.read = __twifs_fread,
.write = __twifs_fwrite,
-#include <lunaix/fs/twifs.h>
+#include <lunaix/fs.h>
+#include <lunaix/fs/twimap.h>
#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
#include <klibc/stdio.h>
#include <klibc/string.h>
}
int
-__twimap_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+__twimap_file_read(struct v_inode* inode, void* buf, size_t len, size_t fpos)
+{
+ struct twimap* map = (struct twimap*)(inode->data);
+ return twimap_read(map, buf, len, fpos);
+}
+
+int
+twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos)
{
- struct twimap* map = twinode_getdata(inode, struct twimap*);
map->buffer = valloc(TWIMAP_BUFFER_SIZE);
map->reset(map);
return acc_size;
}
-struct twimap*
-twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- struct twimap* map = vzalloc(sizeof(struct twimap));
- struct twifs_node* node = twifs_file_node_vargs(parent, fmt, args);
- node->ops.read = __twimap_read;
- node->data = map;
-
- map->reset = __twimap_default_reset;
- map->go_next = __twimap_default_gonext;
- map->data = data;
-
- return map;
-}
-
void
twimap_printf(struct twimap* mapping, const char* fmt, ...)
{
mapping->size_acc += cpy_len;
return cpy_len;
-}
\ No newline at end of file
+}
+
+struct twimap*
+twimap_create(void* data)
+{
+ struct twimap* map = vzalloc(sizeof(struct twimap));
+ map->reset = __twimap_default_reset;
+ map->go_next = __twimap_default_gonext;
+ map->data = data;
+
+ return map;
+}
+
+struct v_file_ops twimap_file_ops = { .close = default_file_close,
+ .read = __twimap_file_read,
+ .readdir = default_file_readdir,
+ .seek = default_file_seek,
+ .write = default_file_write };
\ No newline at end of file
__vfs_readdir_callback };
errno = 1;
if (dent->d_offset == 0) {
- __vfs_readdir_callback(&dctx, vfs_dot.value, vfs_dot.len, 0);
+ __vfs_readdir_callback(&dctx, vfs_dot.value, vfs_dot.len, DT_DIR);
} else if (dent->d_offset == 1) {
- __vfs_readdir_callback(&dctx, vfs_ddot.value, vfs_ddot.len, 0);
+ __vfs_readdir_callback(&dctx, vfs_ddot.value, vfs_ddot.len, DT_DIR);
} else {
dctx.index -= 2;
if ((errno = fd_s->file->ops->readdir(fd_s->file, &dctx)) != 1) {
return 0;
}
+int
+vfs_get_dtype(int itype)
+{
+ switch (itype) {
+ case VFS_IFDIR:
+ return DT_DIR;
+ case VFS_IFSYMLINK:
+ return DT_SYMLINK;
+ default:
+ return DT_PIPE;
+ }
+}
+
__DEFINE_LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size)
{
int errno;
vfs_mount("/dev", "devfs", NULL, 0);
vfs_mount("/sys", "twifs", NULL, MNT_RO);
+ vfs_mount("/task", "taskfs", NULL, MNT_RO);
lxconsole_init();
#include <lunaix/syscall.h>
#include <lunaix/syslog.h>
-#define PROC_TABLE_SIZE 8192
-#define MAX_PROCESS (PROC_TABLE_SIZE / sizeof(uintptr_t))
-
volatile struct proc_info* __current;
struct proc_info dummy;
proc->fdtable = vzalloc(sizeof(struct v_fdtable));
llist_init_head(&proc->mm.regions.head);
+ llist_init_head(&proc->tasks);
llist_init_head(&proc->children);
llist_init_head(&proc->grp_member);
llist_init_head(&proc->sleep.sleepers);
}
llist_append(&process->parent->children, &process->siblings);
+ llist_append(&sched_ctx._procs[0]->tasks, &process->tasks);
process->state = PS_READY;
}
--- /dev/null
+#include <lunaix/fs/taskfs.h>
+
+void
+__read_pending_sig(struct twimap* map)
+{
+ struct proc_info* proc = twimap_data(map, struct proc_info*);
+ twimap_printf(map, "%bb", proc->sig_pending);
+}
+
+void
+__read_masked_sig(struct twimap* map)
+{
+ struct proc_info* proc = twimap_data(map, struct proc_info*);
+ twimap_printf(map, "%bb", proc->sig_mask);
+}
+
+void
+__read_parent(struct twimap* map)
+{
+ struct proc_info* proc = twimap_data(map, struct proc_info*);
+ twimap_printf(map, "%d", proc->parent->pid);
+}
+
+void
+__read_ctimestamp(struct twimap* map)
+{
+ struct proc_info* proc = twimap_data(map, struct proc_info*);
+ twimap_printf(map, "%d", proc->created);
+}
+
+void
+__read_pgid(struct twimap* map)
+{
+ struct proc_info* proc = twimap_data(map, struct proc_info*);
+ twimap_printf(map, "%d", proc->pgid);
+}
+
+void
+__read_children(struct twimap* map)
+{
+ struct proc_info* proc = twimap_index(map, struct proc_info*);
+ if (!proc)
+ return;
+ twimap_printf(map, "%d ", proc->pid);
+}
+
+int
+__next_children(struct twimap* map)
+{
+ struct proc_info* proc = twimap_index(map, struct proc_info*);
+ if (!proc)
+ return 0;
+ map->index = container_of(proc->siblings.next, struct proc_info, siblings);
+ if (map->index == proc) {
+ return 0;
+ }
+ return 1;
+}
+
+void
+__reset_children(struct twimap* map)
+{
+ struct proc_info* proc = twimap_data(map, struct proc_info*);
+ if (llist_empty(&proc->children)) {
+ map->index = 0;
+ return;
+ }
+ map->index = container_of(proc->children.next, struct proc_info, siblings);
+}
+
+void
+export_task_attr()
+{
+ struct twimap* map;
+ map = twimap_create(NULL);
+ map->read = __read_pending_sig;
+ taskfs_export_attr("sig_pending", map);
+
+ map = twimap_create(NULL);
+ map->read = __read_masked_sig;
+ taskfs_export_attr("sig_masked", map);
+
+ map = twimap_create(NULL);
+ map->read = __read_parent;
+ taskfs_export_attr("parent", map);
+
+ map = twimap_create(NULL);
+ map->read = __read_ctimestamp;
+ taskfs_export_attr("created", map);
+
+ map = twimap_create(NULL);
+ map->read = __read_pgid;
+ taskfs_export_attr("pgid", map);
+
+ map = twimap_create(NULL);
+ map->read = __read_children;
+ map->go_next = __next_children;
+ map->reset = __reset_children;
+ taskfs_export_attr("children", map);
+}
\ No newline at end of file
--- /dev/null
+#include <lunaix/dirent.h>
+#include <lunaix/fs/taskfs.h>
+#include <lunaix/fs/twimap.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
+
+#include <klibc/stdio.h>
+#include <klibc/string.h>
+
+#define COUNTER_MASK ((1 << 16) - 1)
+
+static struct hbucket* attr_export_table;
+static DEFINE_LLIST(attributes);
+static volatile int ino_cnt = 1;
+
+int
+taskfs_next_counter()
+{
+ return (ino_cnt = ((ino_cnt + 1) & COUNTER_MASK) + 1);
+}
+
+inode_t
+taskfs_inode_id(pid_t pid, int sub_counter)
+{
+ return ((pid & (MAX_PROCESS - 1)) << 16) | (sub_counter & COUNTER_MASK);
+}
+
+int
+taskfs_mknod(struct v_dnode* dnode, pid_t pid, int sub_counter, int itype)
+{
+ inode_t ino = taskfs_inode_id(pid, sub_counter);
+
+ struct v_superblock* vsb = dnode->super_block;
+ struct v_inode* inode = vfs_i_find(vsb, ino);
+ if (!inode) {
+ if (!(inode = vfs_i_alloc(vsb))) {
+ return ENOMEM;
+ }
+ inode->id = ino;
+ inode->itype = itype;
+ vfs_i_addhash(inode);
+ }
+
+ vfs_assign_inode(dnode, inode);
+ return 0;
+}
+
+int
+taskfs_readdir(struct v_file* file, struct dir_context* dctx)
+{
+ struct v_inode* inode = file->inode;
+ pid_t pid = inode->id >> 16;
+ int counter = 0;
+
+ if ((inode->id & COUNTER_MASK)) {
+ return ENOTDIR;
+ }
+
+ if (pid) {
+ struct task_attribute *pos, *n;
+ llist_for_each(pos, n, &attributes, siblings)
+ {
+ if (counter == dctx->index) {
+ dctx->read_complete_callback(
+ dctx, pos->key_val, VFS_NAME_MAXLEN, DT_FILE);
+ return 1;
+ }
+ counter++;
+ }
+ return 0;
+ }
+
+ char name[VFS_NAME_MAXLEN];
+ struct proc_info *root = get_process(pid), *pos, *n;
+ llist_for_each(pos, n, &root->tasks, tasks)
+ {
+ if (counter == dctx->index) {
+ ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid);
+ dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR);
+ return 1;
+ }
+ counter++;
+ }
+ return 0;
+}
+
+pid_t
+taskfs_atop(const char* str)
+{
+ pid_t t = 0;
+ int i = 0;
+ char c;
+ while ((c = str[i++])) {
+ if ('0' > c || c > '9') {
+ return -1;
+ }
+ t = t * 10 + (c - '0');
+ }
+ return t;
+}
+
+int
+taskfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
+{
+ pid_t pid = this->id >> 16;
+ struct proc_info* proc;
+
+ if (pid) {
+ struct task_attribute* tattr = taskfs_get_attr(&dnode->name);
+ if (!tattr || !(proc = get_process(pid)))
+ return ENOENT;
+
+ int errno = taskfs_mknod(dnode, pid, taskfs_next_counter(), VFS_IFFILE);
+ if (!errno) {
+ tattr->map_file->data = proc;
+ dnode->inode->data = tattr->map_file;
+ dnode->inode->default_fops = &twimap_file_ops;
+ }
+ return errno;
+ }
+
+ pid = taskfs_atop(dnode->name.value);
+
+ if (pid <= 0 || !(proc = get_process(pid))) {
+ return ENOENT;
+ }
+
+ return taskfs_mknod(dnode, pid, 0, VFS_IFDIR);
+}
+
+static struct v_file_ops taskfs_file_ops = { .close = default_file_close,
+ .read = default_file_read,
+ .write = default_file_write,
+ .readdir = taskfs_readdir,
+ .seek = default_file_seek };
+static struct v_inode_ops taskfs_inode_ops = { .dir_lookup = taskfs_dirlookup,
+ .open = default_inode_open,
+ .mkdir = default_inode_mkdir,
+ .rmdir = default_inode_rmdir,
+ .rename = default_inode_rename };
+
+void
+taskfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
+{
+ inode->default_fops = &taskfs_file_ops;
+ inode->ops = &taskfs_inode_ops;
+}
+
+int
+taskfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
+{
+ vsb->ops.init_inode = taskfs_init_inode;
+
+ return taskfs_mknod(mount_point, 0, 0, VFS_IFDIR);
+}
+
+#define ATTR_TABLE_LEN 16
+
+void
+taskfs_export_attr(const char* key, struct twimap* attr_map_file)
+{
+ struct task_attribute* tattr = valloc(sizeof(*tattr));
+
+ tattr->map_file = attr_map_file;
+ tattr->key = HSTR(tattr->key_val, 0);
+ strncpy(tattr->key_val, key, 32);
+ hstr_rehash(&tattr->key, HSTR_FULL_HASH);
+
+ struct hbucket* slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN];
+ hlist_add(&slot->head, &tattr->attrs);
+ llist_append(&attributes, &tattr->siblings);
+}
+
+struct task_attribute*
+taskfs_get_attr(struct hstr* key)
+{
+ struct hbucket* slot = &attr_export_table[key->hash % ATTR_TABLE_LEN];
+ struct task_attribute *pos, *n;
+ hashtable_bucket_foreach(slot, pos, n, attrs)
+ {
+ if (HSTR_EQ(&pos->key, key)) {
+ return pos;
+ }
+ }
+ return NULL;
+}
+
+extern void
+export_task_attr();
+
+void
+taskfs_init()
+{
+ struct filesystem* taskfs = fsm_new_fs("taskfs", 5);
+ taskfs->mount = taskfs_mount;
+
+ fsm_register(taskfs);
+
+ attr_export_table = vcalloc(ATTR_TABLE_LEN, sizeof(struct hbucket));
+
+ export_task_attr();
+}
\ No newline at end of file
: va_arg(vargs, unsigned);
flags |= FLAG_NUMERIC;
break;
+ case 'b':
+ base = 2;
+ goto format_unsigned;
case 'x':
base = 16;
goto format_unsigned;