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