1 #include <lunaix/fs/taskfs.h>
2 #include <lunaix/fs/twimap.h>
3 #include <lunaix/fs/api.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/process.h>
6 #include <lunaix/sched.h>
8 #include <klibc/strfmt.h>
9 #include <klibc/string.h>
11 #include <usr/lunaix/dirent_defs.h>
13 #define COUNTER_MASK ((1 << 16) - 1)
15 static struct hbucket* attr_export_table;
16 static DEFINE_LIST(attributes);
17 static volatile int ino_cnt = 1;
19 extern struct scheduler sched_ctx;
22 __destruct_inode(struct v_inode* inode)
24 vfree_safe(inode->data);
30 return (ino_cnt = ((ino_cnt + 1) & COUNTER_MASK) + 1);
34 taskfs_inode_id(pid_t pid, int sub_counter)
36 return ((pid & (MAX_PROCESS - 1)) << 16) | (sub_counter & COUNTER_MASK);
40 taskfs_mknod(struct v_dnode* dnode, pid_t pid, int sub_counter, int itype)
42 inode_t ino = taskfs_inode_id(pid, sub_counter);
44 struct v_superblock* vsb = dnode->super_block;
45 struct v_inode* inode = vfs_i_find(vsb, ino);
47 if (!(inode = vfs_i_alloc(vsb))) {
53 inode->destruct = __destruct_inode;
57 vfs_assign_inode(dnode, inode);
62 __report_task_entries(struct v_file* file, struct dir_context* dctx)
64 unsigned int counter = 0;
65 char name[VFS_NAME_MAXLEN];
66 struct proc_info *pos, *n;
68 llist_for_each(pos, n, sched_ctx.proc_list, tasks)
70 if (!fsapi_readdir_pos_entries_at(file, counter)) {
75 ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid);
76 dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR);
84 __report_task_attributes(struct v_file* file, struct dir_context* dctx)
86 unsigned int counter = 0;
87 struct task_attribute *pos, *n;
89 list_for_each(pos, n, attributes.first, siblings)
91 if (fsapi_readdir_pos_entries_at(file, counter)) {
92 dctx->read_complete_callback(
93 dctx, HSTR_VAL(pos->key), VFS_NAME_MAXLEN, DT_FILE);
103 taskfs_readdir(struct v_file* file, struct dir_context* dctx)
105 struct v_inode* inode = file->inode;
106 pid_t pid = inode->id >> 16;
107 unsigned int counter = 0;
109 if ((inode->id & COUNTER_MASK)) {
113 if (fsapi_handle_pseudo_dirent(file, dctx)) {
118 return __report_task_attributes(file, dctx);
121 return __report_task_entries(file, dctx);
126 taskfs_atop(const char* str)
131 while ((c = str[i++])) {
132 if ('0' > c || c > '9') {
135 t = t * 10 + (c - '0');
141 __init_task_inode(pid_t pid, struct v_dnode* dnode)
144 struct proc_info* proc;
145 struct task_attribute* tattr;
147 tattr = taskfs_get_attr(&dnode->name);
148 if (!tattr || !(proc = get_process(pid)))
151 map = twimap_create(proc);
152 map->ops = tattr->ops;
154 dnode->inode->data = map;
155 dnode->inode->default_fops = &twimap_file_ops;
161 __lookup_attribute(pid_t pid, struct v_dnode* dnode)
165 errno = taskfs_mknod(dnode, pid, taskfs_next_counter(), VFS_IFFILE);
170 return __init_task_inode(pid, dnode);
174 taskfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
176 pid_t pid = this->id >> 16;
179 return __lookup_attribute(pid, dnode);
182 pid = taskfs_atop(dnode->name.value);
188 return taskfs_mknod(dnode, pid, 0, VFS_IFDIR);
191 static struct v_file_ops taskfs_file_ops = {
192 .close = default_file_close,
193 .read = default_file_read,
194 .read_page = default_file_read_page,
195 .write = default_file_write,
196 .write_page = default_file_write_page,
197 .readdir = taskfs_readdir,
198 .seek = default_file_seek
201 static struct v_inode_ops taskfs_inode_ops = {
202 .dir_lookup = taskfs_dirlookup,
203 .open = default_inode_open,
204 .mkdir = default_inode_mkdir,
205 .rmdir = default_inode_rmdir,
206 .rename = default_inode_rename
209 static volatile struct v_superblock* taskfs_sb;
212 taskfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
214 inode->default_fops = &taskfs_file_ops;
215 inode->ops = &taskfs_inode_ops;
219 taskfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
222 vsb->ops.init_inode = taskfs_init_inode;
224 return taskfs_mknod(mount_point, 0, 0, VFS_IFDIR);
228 taskfs_unmount(struct v_superblock* vsb)
234 taskfs_invalidate(pid_t pid)
236 struct v_dnode *pos, *n;
237 struct v_inode* inode;
239 inode = vfs_i_find(taskfs_sb, taskfs_inode_id(pid, 0));
243 llist_for_each(pos, n, &inode->aka_dnodes, aka_list)
245 if (pos->ref_count > 1) {
251 if (!inode->link_count) {
256 #define ATTR_TABLE_LEN 16
257 #define ATTR_KEY_LEN 32
260 taskfs_export_attr_mapping(const char* key, struct twimap_ops ops)
263 struct hbucket* slot;
264 struct task_attribute* tattr;
266 tattr = valloc(sizeof(*tattr));
267 key_val = valloc(ATTR_KEY_LEN);
270 tattr->key = HSTR(key_val, 0);
271 strncpy(key_val, key, ATTR_KEY_LEN);
272 hstr_rehash(&tattr->key, HSTR_FULL_HASH);
274 slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN];
275 hlist_add(&slot->head, &tattr->attrs);
276 list_add(&attributes, &tattr->siblings);
279 struct task_attribute*
280 taskfs_get_attr(struct hstr* key)
282 struct hbucket* slot = &attr_export_table[key->hash % ATTR_TABLE_LEN];
283 struct task_attribute *pos, *n;
284 hashtable_bucket_foreach(slot, pos, n, attrs)
286 if (HSTR_EQ(&pos->key, key)) {
299 struct filesystem* fs;
300 fs = fsapi_fs_declare("taskfs", FSTYPE_PSEUDO);
302 fsapi_fs_set_mntops(fs, taskfs_mount, taskfs_unmount);
303 fsapi_fs_finalise(fs);
305 attr_export_table = vcalloc(ATTR_TABLE_LEN, sizeof(struct hbucket));
309 EXPORT_FILE_SYSTEM(taskfs, taskfs_init);