iterator->fs = NULL;
}
+static inline bool
+fsm_check_pseudo_fs(struct filesystem* fs)
+{
+ return !!(fs->types & FSTYPE_PSEUDO);
+}
+
void
vfs_init();
fsm_register(fs);
}
+static inline bool
+fsapi_check_readdir_pos_pseduo(struct v_file* file)
+{
+ return file->f_pos < 2;
+}
+
+static inline bool
+fsapi_readdir_pos_entries_at(struct v_file* file, unsigned int pos)
+{
+ return file->f_pos == pos + 2;
+}
+
#endif /* __LUNAIX_FSAPI_H */
#include <lunaix/fs/api.h>
#include <lunaix/fs/twimap.h>
+#include <lunaix/ds/list.h>
struct task_attribute
{
- struct llist_header siblings;
+ struct list_node siblings;
struct hlist_node attrs;
struct hstr key;
- struct twimap* map_file;
- char key_val[32];
+ struct twimap_ops ops;
};
+#define taskfs_export_attr(name) \
+ ({ \
+ taskfs_export_attr_mapping(stringify(name), \
+ (struct twimap_ops) { \
+ __task_read_##name, \
+ __twimap_default_gonext, __twimap_default_reset \
+ }); \
+ })
+
+#define taskfs_export_list_attr(name) \
+ ({ \
+ taskfs_export_attr_mapping(stringify(name), \
+ (struct twimap_ops) { \
+ __task_read_##name, \
+ __task_gonext_##name, __task_reset_##name \
+ }); \
+ })
+
void
taskfs_init();
void
-taskfs_export_attr(const char* key, struct twimap* attr_map_file);
+taskfs_export_attr_mapping(const char* key, struct twimap_ops ops);
struct task_attribute*
taskfs_get_attr(struct hstr* key);
extern struct v_file_ops twimap_file_ops;
+struct twimap;
+struct twimap_ops
+{
+ void (*read)(struct twimap* mapping);
+ int (*go_next)(struct twimap* mapping);
+ void (*reset)(struct twimap* mapping);
+};
+
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);
+
+ union {
+ struct {
+ void (*read)(struct twimap* mapping);
+ int (*go_next)(struct twimap* mapping);
+ void (*reset)(struct twimap* mapping);
+ };
+ struct twimap_ops ops;
+ };
};
+void
+__twimap_default_reset(struct twimap* map);
+
+int
+__twimap_default_gonext(struct twimap* map);
+
int
twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos);
size_t acc_size = MIN(len, map->size_acc - (pos - fpos)), rdlen = acc_size;
memcpy(buffer, map->buffer + (pos - fpos), acc_size);
- while (acc_size < len && map->go_next(map)) {
+ while (acc_size < len) {
map->size_acc = 0;
map->read(map);
rdlen = MIN(len - acc_size, map->size_acc);
memcpy(buffer + acc_size, map->buffer, rdlen);
acc_size += rdlen;
+
+ if (!map->go_next(map)) {
+ break;
+ }
}
if (acc_size <= len - 1) {
void
vfs_i_free(struct v_inode* inode)
{
+ assert(inode->link_count == 0);
+
if (inode->pg_cache) {
pcache_release(inode->pg_cache);
vfree(inode->pg_cache);
const int dtype)
{
struct lx_dirent* dent = (struct lx_dirent*)dctx->cb_data;
- strncpy(dent->d_name, name, MIN(len, DIRENT_NAME_MAX_LEN));
- dent->d_nlen = len;
+ int len_ = MIN(len, DIRENT_NAME_MAX_LEN - 1);
+
+ strncpy(dent->d_name, name, len_);
+ dent->d_name[len_] = 0;
+
+ dent->d_nlen = len_;
dent->d_type = dtype;
}
return DO_STATUS_OR_RETURN(errno);
}
+static inline bool
+check_pcache_eligibility(struct v_fd* fd_s)
+{
+ struct v_inode* inode;
+
+ inode = fd_s->file->inode;
+ return !check_seqdev_node(inode) \
+ && !fsm_check_pseudo_fs(inode->sb->fs) \
+ && !(fd_s->flags & FO_DIRECT);
+}
+
__DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count)
{
int errno = 0;
file->inode->atime = clock_unixtime();
- if (check_seqdev_node(file->inode) || (fd_s->flags & FO_DIRECT)) {
+ if (!check_pcache_eligibility(fd_s)) {
errno = file->ops->read(file->inode, buf, count, file->f_pos);
} else {
errno = pcache_read(file->inode, buf, count, file->f_pos);
file->f_pos = inode->fsize;
}
- if (check_seqdev_node(inode) || (fd_s->flags & FO_DIRECT)) {
+ if (!check_pcache_eligibility(fd_s)) {
errno = file->ops->write(inode, buf, count, file->f_pos);
} else {
errno = pcache_write(inode, buf, count, file->f_pos);
size_t cpy_size = MIN(dnode->name.len, size - len);
strncpy(buf + len, dnode->name.value, cpy_size);
+ buf[len + cpy_size] = 0;
+
len += cpy_size;
return len;
vfs_ref_dnode(dnode);
proc->cwd = dnode;
+done:
unlock_dnode(dnode);
-done:
return errno;
}
assert(!proc_terminated(process->parent));
}
- if (sched_ctx.proc_list) {
+ if (likely(sched_ctx.proc_list)) {
llist_append(sched_ctx.proc_list, &process->tasks);
} else {
sched_ctx.proc_list = &process->tasks;
#include <lunaix/fs/taskfs.h>
#include <lunaix/process.h>
+#define proc(map) (twimap_data(map, struct proc_info*))
+
void
-__read_parent(struct twimap* map)
+__task_read_parent(struct twimap* map)
{
- struct proc_info* proc = twimap_data(map, struct proc_info*);
- twimap_printf(map, "%d", proc->parent->pid);
+ twimap_printf(map, "%d", proc(map)->parent->pid);
}
void
-__read_ctimestamp(struct twimap* map)
+__task_read_created(struct twimap* map)
{
- struct proc_info* proc = twimap_data(map, struct proc_info*);
- twimap_printf(map, "%d", proc->created);
+ twimap_printf(map, "%d", proc(map)->created);
}
void
-__read_pgid(struct twimap* map)
+__task_read_pgid(struct twimap* map)
{
- struct proc_info* proc = twimap_data(map, struct proc_info*);
- twimap_printf(map, "%d", proc->pgid);
+ twimap_printf(map, "%d", proc(map)->pgid);
}
void
-__read_children(struct twimap* map)
+__task_read_cmdline(struct twimap* map)
{
- struct llist_header* proc_list = twimap_index(map, struct llist_header*);
- struct proc_info* proc =
- container_of(proc_list, struct proc_info, siblings);
- if (!proc)
- return;
- twimap_printf(map, "%d ", proc->pid);
+ twimap_printf(map, "%s", proc(map)->cmd);
+}
+
+static inline void
+__get_protection(struct mm_region* vmr, char* prot_buf)
+{
+ prot_buf[0] = (vmr->attr & REGION_READ) ? 'r' : '-';
+ prot_buf[1] = (vmr->attr & REGION_WRITE) ? 'w' : '-';
+ prot_buf[2] = (vmr->attr & REGION_EXEC) ? 'x' : '-';
+ prot_buf[3] = shared_writable_region(vmr) ? 's' : 'p';
+ prot_buf[4] = 0;
+}
+
+static inline void
+__get_vmr_name(struct mm_region* vmr, char* buf, unsigned int size)
+{
+ int region_type;
+
+ region_type = (vmr->attr >> 16) & 0xf;
+
+ if (region_type == REGION_TYPE_STACK) {
+ strcpy(buf, "[stack]");
+ }
+
+ else if (region_type == REGION_TYPE_HEAP) {
+ strcpy(buf, "[heap]");
+ }
+
+ else if (vmr->mfile) {
+ vfs_get_path(vmr->mfile->dnode, buf, size, 0);
+ }
+
+ else {
+ buf[0] = 0;
+ }
+}
+
+void
+__task_read_maps(struct twimap* map)
+{
+ struct llist_header* vmr_;
+ struct mm_region* vmr;
+ unsigned int size;
+
+ vmr_ = twimap_index(map, struct llist_header*);
+ vmr = container_of(vmr_, struct mm_region, head);
+
+ assert(vmr_);
+
+ char prot[5], name[256];
+
+ __get_protection(vmr, prot);
+ __get_vmr_name(vmr, name, 256);
+
+ size = vmr->end - vmr->start;
+
+ twimap_printf(map, "%012lx-%012lx %x %s %s\n",
+ vmr->start, vmr->end, size, prot, name);
}
int
-__next_children(struct twimap* map)
+__task_gonext_maps(struct twimap* map)
{
- struct llist_header* proc = twimap_index(map, struct llist_header*);
- struct proc_info* current = twimap_data(map, struct proc_info*);
- if (!proc)
+ struct proc_mm* mm;
+ struct llist_header* vmr;
+
+ vmr = twimap_index(map, struct llist_header*);
+ mm = vmspace(proc(map));
+
+ if (!vmr)
return 0;
- map->index = proc->next;
- if (map->index == ¤t->children) {
+
+ map->index = vmr->next;
+ if (map->index == &mm->regions) {
return 0;
}
+
return 1;
}
void
-__reset_children(struct twimap* map)
+__task_reset_maps(struct twimap* map)
{
- struct proc_info* proc = twimap_data(map, struct proc_info*);
- if (llist_empty(&proc->children)) {
+ struct proc_mm* mm;
+
+ mm = vmspace(proc(map));
+ if (llist_empty(&mm->regions)) {
map->index = 0;
return;
}
- map->index = proc->children.next;
+
+ map->index = mm->regions.next;
}
void
export_task_attr()
{
- struct twimap* map;
-
- // FIXME goes to thread specific location
- // 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);
+ taskfs_export_attr(parent);
+ taskfs_export_attr(created);
+ taskfs_export_attr(pgid);
+ taskfs_export_attr(cmdline);
+ taskfs_export_list_attr(maps);
}
\ No newline at end of file
#define COUNTER_MASK ((1 << 16) - 1)
static struct hbucket* attr_export_table;
-static DEFINE_LLIST(attributes);
+static DEFINE_LIST(attributes);
static volatile int ino_cnt = 1;
-int
+extern struct scheduler sched_ctx;
+
+static void
+__destruct_inode(struct v_inode* inode)
+{
+ vfree_safe(inode->data);
+}
+
+static int
taskfs_next_counter()
{
return (ino_cnt = ((ino_cnt + 1) & COUNTER_MASK) + 1);
}
-inode_t
+static inode_t
taskfs_inode_id(pid_t pid, int sub_counter)
{
return ((pid & (MAX_PROCESS - 1)) << 16) | (sub_counter & COUNTER_MASK);
if (!(inode = vfs_i_alloc(vsb))) {
return ENOMEM;
}
+
inode->id = ino;
inode->itype = itype;
+ inode->destruct = __destruct_inode;
vfs_i_addhash(inode);
}
return 0;
}
+static inline int
+__report_task_entries(struct v_file* file, struct dir_context* dctx)
+{
+ unsigned int counter = 0;
+ char name[VFS_NAME_MAXLEN];
+ struct proc_info *pos, *n;
+
+ llist_for_each(pos, n, sched_ctx.proc_list, tasks)
+ {
+ if (!fsapi_readdir_pos_entries_at(file, counter)) {
+ counter++;
+ continue;
+ }
+
+ ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid);
+ dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR);
+ return 1;
+ }
+
+ return 0;
+}
+
+static inline int
+__report_task_attributes(struct v_file* file, struct dir_context* dctx)
+{
+ unsigned int counter = 0;
+ struct task_attribute *pos, *n;
+
+ list_for_each(pos, n, attributes.first, siblings)
+ {
+ if (fsapi_readdir_pos_entries_at(file, counter)) {
+ dctx->read_complete_callback(
+ dctx, HSTR_VAL(pos->key), VFS_NAME_MAXLEN, DT_FILE);
+ return 1;
+ }
+ counter++;
+ }
+
+ return 0;
+}
+
int
taskfs_readdir(struct v_file* file, struct dir_context* dctx)
{
}
if (pid) {
- struct task_attribute *pos, *n;
- llist_for_each(pos, n, &attributes, siblings)
- {
- if (counter == file->f_pos) {
- dctx->read_complete_callback(
- dctx, pos->key_val, VFS_NAME_MAXLEN, DT_FILE);
- return 1;
- }
- counter++;
- }
- return 0;
+ return __report_task_attributes(file, dctx);
}
- char name[VFS_NAME_MAXLEN];
- struct proc_info *root = get_process(pid), *pos, *n;
- llist_for_each(pos, n, &root->tasks, tasks)
- {
- if (counter == file->f_pos) {
- ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid);
- dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR);
- return 1;
- }
- counter++;
- }
- return 0;
+ return __report_task_entries(file, dctx);
}
// ascii to pid
-pid_t
+static inline pid_t
taskfs_atop(const char* str)
{
pid_t t = 0;
return t;
}
+static inline int
+__init_task_inode(pid_t pid, struct v_dnode* dnode)
+{
+ struct twimap* map;
+ struct proc_info* proc;
+ struct task_attribute* tattr;
+
+ tattr = taskfs_get_attr(&dnode->name);
+ if (!tattr || !(proc = get_process(pid)))
+ return ENOENT;
+
+ map = twimap_create(proc);
+ map->ops = tattr->ops;
+
+ dnode->inode->data = map;
+ dnode->inode->default_fops = &twimap_file_ops;
+
+ return 0;
+}
+
+static int
+__lookup_attribute(pid_t pid, struct v_dnode* dnode)
+{
+ int errno;
+
+ errno = taskfs_mknod(dnode, pid, taskfs_next_counter(), VFS_IFFILE);
+ if (errno) {
+ return errno;
+ }
+
+ return __init_task_inode(pid, dnode);
+}
+
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_IFSEQDEV);
- if (!errno) {
- tattr->map_file->data = proc;
- dnode->inode->data = tattr->map_file;
- dnode->inode->default_fops = &twimap_file_ops;
- }
- return errno;
+ return __lookup_attribute(pid, dnode);
}
pid = taskfs_atop(dnode->name.value);
- if (pid <= 0 || !(proc = get_process(pid))) {
+ if (pid <= 0) {
return ENOENT;
}
- return taskfs_mknod(dnode, pid, 0, F_DIR);
+ return taskfs_mknod(dnode, pid, 0, VFS_IFDIR);
}
-static struct v_file_ops taskfs_file_ops = { .close = default_file_close,
- .read = default_file_read,
- .read_page =
- default_file_read_page,
- .write = default_file_write,
- .write_page =
- default_file_write_page,
- .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 };
+static struct v_file_ops taskfs_file_ops = {
+ .close = default_file_close,
+ .read = default_file_read,
+ .read_page = default_file_read_page,
+ .write = default_file_write,
+ .write_page = default_file_write_page,
+ .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
+};
+
+static volatile struct v_superblock* taskfs_sb;
void
taskfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
inode->ops = &taskfs_inode_ops;
}
-static volatile struct v_superblock* taskfs_sb;
-
int
taskfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
{
taskfs_invalidate(pid_t pid)
{
struct v_dnode *pos, *n;
- struct v_inode* inode = vfs_i_find(taskfs_sb, taskfs_inode_id(pid, 0));
+ struct v_inode* inode;
+ inode = vfs_i_find(taskfs_sb, taskfs_inode_id(pid, 0));
if (!inode)
return;
}
vfs_d_free(pos);
}
+
+ if (!inode->link_count) {
+ vfs_i_free(inode);
+ }
}
#define ATTR_TABLE_LEN 16
+#define ATTR_KEY_LEN 32
void
-taskfs_export_attr(const char* key, struct twimap* attr_map_file)
+taskfs_export_attr_mapping(const char* key, struct twimap_ops ops)
{
- struct task_attribute* tattr = valloc(sizeof(*tattr));
+ char* key_val;
+ struct hbucket* slot;
+ struct task_attribute* tattr;
+
+ tattr = valloc(sizeof(*tattr));
+ key_val = valloc(ATTR_KEY_LEN);
- tattr->map_file = attr_map_file;
- tattr->key = HSTR(tattr->key_val, 0);
- strncpy(tattr->key_val, key, 32);
+ tattr->ops = ops;
+ tattr->key = HSTR(key_val, 0);
+ strncpy(key_val, key, ATTR_KEY_LEN);
hstr_rehash(&tattr->key, HSTR_FULL_HASH);
- struct hbucket* slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN];
+ slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN];
hlist_add(&slot->head, &tattr->attrs);
- llist_append(&attributes, &tattr->siblings);
+ list_add(&attributes, &tattr->siblings);
}
struct task_attribute*
char* _weak
strncpy(char* dest, const char* src, unsigned long n)
{
- char c;
+ char c = '\0';
unsigned int i = 0;
- while (i <= n && (c = src[i]))
+ while (i < n && (c = src[i]))
dest[i++] = c;
- if (!(n < i && src[i - 1])) {
- while (i <= n)
- dest[i++] = 0;
- }
- else {
- dest[i - 1] = 0;
- }
+ while (i < n)
+ dest[i++] = 0;
return dest;
}
\ No newline at end of file