renamed and cleaned up export header files to match linux convention
[lunaix-os.git] / lunaix-os / kernel / process / taskfs.c
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>
7
8 #include <klibc/strfmt.h>
9 #include <klibc/string.h>
10
11 #include <usr/lunaix/dirent.h>
12
13 #define COUNTER_MASK ((1 << 16) - 1)
14
15 static struct hbucket* attr_export_table;
16 static DEFINE_LLIST(attributes);
17 static volatile int ino_cnt = 1;
18
19 int
20 taskfs_next_counter()
21 {
22     return (ino_cnt = ((ino_cnt + 1) & COUNTER_MASK) + 1);
23 }
24
25 inode_t
26 taskfs_inode_id(pid_t pid, int sub_counter)
27 {
28     return ((pid & (MAX_PROCESS - 1)) << 16) | (sub_counter & COUNTER_MASK);
29 }
30
31 int
32 taskfs_mknod(struct v_dnode* dnode, pid_t pid, int sub_counter, int itype)
33 {
34     inode_t ino = taskfs_inode_id(pid, sub_counter);
35
36     struct v_superblock* vsb = dnode->super_block;
37     struct v_inode* inode = vfs_i_find(vsb, ino);
38     if (!inode) {
39         if (!(inode = vfs_i_alloc(vsb))) {
40             return ENOMEM;
41         }
42         inode->id = ino;
43         inode->itype = itype;
44         vfs_i_addhash(inode);
45     }
46
47     vfs_assign_inode(dnode, inode);
48     return 0;
49 }
50
51 int
52 taskfs_readdir(struct v_file* file, struct dir_context* dctx)
53 {
54     struct v_inode* inode = file->inode;
55     pid_t pid = inode->id >> 16;
56     unsigned int counter = 0;
57
58     if ((inode->id & COUNTER_MASK)) {
59         return ENOTDIR;
60     }
61
62     if (fsapi_handle_pseudo_dirent(file, dctx)) {
63         return 1;
64     }
65
66     if (pid) {
67         struct task_attribute *pos, *n;
68         llist_for_each(pos, n, &attributes, siblings)
69         {
70             if (counter == file->f_pos) {
71                 dctx->read_complete_callback(
72                   dctx, pos->key_val, VFS_NAME_MAXLEN, DT_FILE);
73                 return 1;
74             }
75             counter++;
76         }
77         return 0;
78     }
79
80     char name[VFS_NAME_MAXLEN];
81     struct proc_info *root = get_process(pid), *pos, *n;
82     llist_for_each(pos, n, &root->tasks, tasks)
83     {
84         if (counter == file->f_pos) {
85             ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid);
86             dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR);
87             return 1;
88         }
89         counter++;
90     }
91     return 0;
92 }
93
94 // ascii to pid
95 pid_t
96 taskfs_atop(const char* str)
97 {
98     pid_t t = 0;
99     int i = 0;
100     char c;
101     while ((c = str[i++])) {
102         if ('0' > c || c > '9') {
103             return -1;
104         }
105         t = t * 10 + (c - '0');
106     }
107     return t;
108 }
109
110 int
111 taskfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
112 {
113     pid_t pid = this->id >> 16;
114     struct proc_info* proc;
115
116     if (pid) {
117         struct task_attribute* tattr = taskfs_get_attr(&dnode->name);
118         if (!tattr || !(proc = get_process(pid)))
119             return ENOENT;
120
121         int errno =
122           taskfs_mknod(dnode, pid, taskfs_next_counter(), VFS_IFSEQDEV);
123         if (!errno) {
124             tattr->map_file->data = proc;
125             dnode->inode->data = tattr->map_file;
126             dnode->inode->default_fops = &twimap_file_ops;
127         }
128         return errno;
129     }
130
131     pid = taskfs_atop(dnode->name.value);
132
133     if (pid <= 0 || !(proc = get_process(pid))) {
134         return ENOENT;
135     }
136
137     return taskfs_mknod(dnode, pid, 0, F_DIR);
138 }
139
140 static struct v_file_ops taskfs_file_ops = { .close = default_file_close,
141                                              .read = default_file_read,
142                                              .read_page =
143                                                default_file_read_page,
144                                              .write = default_file_write,
145                                              .write_page =
146                                                default_file_write_page,
147                                              .readdir = taskfs_readdir,
148                                              .seek = default_file_seek };
149 static struct v_inode_ops taskfs_inode_ops = { .dir_lookup = taskfs_dirlookup,
150                                                .open = default_inode_open,
151                                                .mkdir = default_inode_mkdir,
152                                                .rmdir = default_inode_rmdir,
153                                                .rename = default_inode_rename };
154
155 void
156 taskfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
157 {
158     inode->default_fops = &taskfs_file_ops;
159     inode->ops = &taskfs_inode_ops;
160 }
161
162 static volatile struct v_superblock* taskfs_sb;
163
164 int
165 taskfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
166 {
167     taskfs_sb = vsb;
168     vsb->ops.init_inode = taskfs_init_inode;
169
170     return taskfs_mknod(mount_point, 0, 0, VFS_IFDIR);
171 }
172
173 int
174 taskfs_unmount(struct v_superblock* vsb)
175 {
176     return 0;
177 }
178
179 void
180 taskfs_invalidate(pid_t pid)
181 {
182     struct v_dnode *pos, *n;
183     struct v_inode* inode = vfs_i_find(taskfs_sb, taskfs_inode_id(pid, 0));
184
185     if (!inode)
186         return;
187
188     llist_for_each(pos, n, &inode->aka_dnodes, aka_list)
189     {
190         if (pos->ref_count > 1) {
191             continue;
192         }
193         vfs_d_free(pos);
194     }
195 }
196
197 #define ATTR_TABLE_LEN 16
198
199 void
200 taskfs_export_attr(const char* key, struct twimap* attr_map_file)
201 {
202     struct task_attribute* tattr = valloc(sizeof(*tattr));
203
204     tattr->map_file = attr_map_file;
205     tattr->key = HSTR(tattr->key_val, 0);
206     strncpy(tattr->key_val, key, 32);
207     hstr_rehash(&tattr->key, HSTR_FULL_HASH);
208
209     struct hbucket* slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN];
210     hlist_add(&slot->head, &tattr->attrs);
211     llist_append(&attributes, &tattr->siblings);
212 }
213
214 struct task_attribute*
215 taskfs_get_attr(struct hstr* key)
216 {
217     struct hbucket* slot = &attr_export_table[key->hash % ATTR_TABLE_LEN];
218     struct task_attribute *pos, *n;
219     hashtable_bucket_foreach(slot, pos, n, attrs)
220     {
221         if (HSTR_EQ(&pos->key, key)) {
222             return pos;
223         }
224     }
225     return NULL;
226 }
227
228 extern void
229 export_task_attr();
230
231 void
232 taskfs_init()
233 {
234     struct filesystem* fs;
235     fs = fsapi_fs_declare("taskfs", FSTYPE_PSEUDO);
236     
237     fsapi_fs_set_mntops(fs, taskfs_mount, taskfs_unmount);
238     fsapi_fs_finalise(fs);
239
240     attr_export_table = vcalloc(ATTR_TABLE_LEN, sizeof(struct hbucket));
241
242     export_task_attr();
243 }
244 EXPORT_FILE_SYSTEM(taskfs, taskfs_init);