2e340af7dedd3e09150fa461471cfb1696538158
[akaros.git] / kern / src / kfs.c
1 /* Copyright (c) 2009, 2010 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Implementation of the KFS file system.  It is a RAM based, read-only FS
6  * consisting of files that are added to the kernel binary image.  Might turn
7  * this into a read/write FS with directories someday. */
8
9 #ifdef __SHARC__
10 #pragma nosharc
11 #endif
12
13 #ifdef __DEPUTY__
14 #pragma nodeputy
15 #endif
16
17 #include <vfs.h>
18 #include <kfs.h>
19 #include <slab.h>
20 #include <kmalloc.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <assert.h>
24 #include <error.h>
25
26 #define KFS_MAX_FILE_SIZE 1024*1024*128
27 #define KFS_MAGIC 0xdead0001
28
29 /* VFS required Functions */
30 /* These structs are declared again and initialized farther down */
31 struct super_operations kfs_s_op;
32 struct inode_operations kfs_i_op;
33 struct dentry_operations kfs_d_op;
34 struct file_operations kfs_f_op;
35
36 /* Creates the SB (normally would read in from disc and create).  Ups the refcnt
37  * for whoever consumes this.  Returns 0 on failure.
38  * TODO: consider pulling out more of the FS-independent stuff, if possible.
39  * There are only two things, but the pain in the ass is that you'd need to read
40  * the disc to get that first inode, and it's a FS-specific thing. */
41 struct super_block *kfs_get_sb(struct fs_type *fs, int flags,
42                                char *dev_name, struct vfsmount *vmnt)
43 {
44         /* Ought to check that dev_name has our FS on it.  in this case, it's
45          * irrelevant. */
46         //if (something_bad)
47         //      return 0;
48
49         /* Build and init the SB.  No need to read off disc. */
50         struct super_block *sb = get_sb();
51         sb->s_dev = 0;
52         sb->s_blocksize = 4096; /* or 512.  haven't thought this through */
53         sb->s_maxbytes = KFS_MAX_FILE_SIZE;
54         sb->s_type = &kfs_fs_type;
55         sb->s_op = &kfs_s_op;
56         sb->s_flags = flags;
57         sb->s_magic = KFS_MAGIC;
58         sb->s_mount = vmnt;
59         sb->s_syncing = FALSE;
60         sb->s_bdev = 0;
61         strlcpy(sb->s_name, "KFS", 32);
62         //sb->s_fs_info = 0; /* nothing to override with for KFS */
63         /* Final stages of initializing the sb, mostly FS-independent */
64         init_sb(sb, vmnt, &kfs_d_op, 1); /* 1 is the KFS root ino (inode number) */
65         printk("KFS superblock loaded\n");
66         return sb;
67 }
68
69 void kfs_kill_sb(struct super_block *sb)
70 {
71         panic("Killing KFS is not supported!");
72 }
73
74 /* Every FS must have a static FS Type, with which the VFS code can bootstrap */
75 struct fs_type kfs_fs_type = {"KFS", 0, kfs_get_sb, kfs_kill_sb, {0, 0},
76                TAILQ_HEAD_INITIALIZER(kfs_fs_type.fs_supers)};
77
78 /* Super Operations */
79
80 /* creates and initializes a new inode.  generic fields are filled in.  specific
81  * fields are filled in in read_inode() based on what's on the disk for a given
82  * i_no.  i_no is set by the caller. */
83 struct inode *kfs_alloc_inode(struct super_block *sb)
84 {
85         /* arguably, we can avoid some of this init by using the slab/cache */
86         struct inode *inode = kmem_cache_alloc(inode_kcache, 0);
87         memset(inode, 0, sizeof(struct inode));
88         TAILQ_INSERT_HEAD(&sb->s_inodes, inode, i_sb_list);
89         TAILQ_INIT(&inode->i_dentry);
90         inode->i_ino = 0;                                       /* set by caller later */
91         atomic_set(&inode->i_refcnt, 1);
92         inode->i_blksize = 4096;                        /* keep in sync with get_sb() */
93         spinlock_init(&inode->i_lock);
94         inode->i_op = &kfs_i_op;
95         inode->i_fop = &kfs_f_op;
96         inode->i_sb = sb;
97         inode->i_state = 0;                                     /* need real states, want I_NEW */
98         inode->dirtied_when = 0;
99         atomic_set(&inode->i_writecount, 0);
100         inode->i_fs_info = 0;
101         return inode;
102         /* caller sets i_ino, i_list set when applicable */
103 }
104
105 /* deallocs and cleans up after an inode. */
106 void kfs_destroy_inode(struct inode *inode)
107 {
108         kmem_cache_free(inode_kcache, inode);
109 }
110
111 /* reads the inode data on disk specified by inode->i_ino into the inode.
112  * basically, it's a "make this inode the one for i_ino (i number)" */
113 void kfs_read_inode(struct inode *inode)
114 {
115         /* TODO: what does it mean to ask for an inode->i_ino that doesn't exist?
116          *      possibly a bug, since these inos come from directories */
117         if (inode->i_ino == 1) {
118                 inode->i_mode = 0x777;                  /* TODO: use something appropriate */
119                 inode->i_nlink = 1;                             /* assuming only one hardlink */
120                 inode->i_uid = 0;
121                 inode->i_gid = 0;
122                 inode->i_rdev = 0;
123                 inode->i_size = 0;                              /* make sense for KFS? */
124                 inode->i_atime.tv_sec = 0;
125                 inode->i_atime.tv_nsec = 0;
126                 inode->i_mtime.tv_sec = 0;
127                 inode->i_mtime.tv_nsec = 0;
128                 inode->i_ctime.tv_sec = 0;
129                 inode->i_ctime.tv_nsec = 0;
130                 inode->i_blksize = 0;
131                 inode->i_blocks = 0;
132                 inode->i_bdev = 0;                              /* assuming blockdev? */
133                 inode->dirtied_when = 0;
134                 inode->i_flags = 0;
135                 inode->i_socket = FALSE;
136         } else {
137                 panic("Not implemented");
138         }
139         /* TODO: unused: inode->i_hash add to hash (saves on disc reading)
140          * i_mapping, i_data, when they mean something */
141 }
142
143 /* called when an inode in memory is modified (journalling FS's care) */
144 void kfs_dirty_inode(struct inode *inode)
145 {       // KFS doesn't care
146 }
147
148 /* write the inode to disk (specifically, to inode inode->i_ino), synchronously
149  * if we're asked to wait */
150 void kfs_write_inode(struct inode *inode, bool wait)
151 {       // KFS doesn't care
152 }
153
154 /* called when an inode is decref'd, to do any FS specific work */
155 void kfs_put_inode(struct inode *inode)
156 {       // KFS doesn't care
157 }
158
159 /* called when an inode is about to be destroyed.  the generic version ought to
160  * remove every reference to the inode from the VFS, and if the inode isn't in
161  * any directory, calls delete_inode */
162 void kfs_drop_inode(struct inode *inode)
163 { // TODO: should call a generic one instead.  or at least do something...
164         // remove from lists
165 }
166
167 /* delete the inode from disk (all data) and deallocs the in memory inode */
168 void kfs_delete_inode(struct inode *inode)
169 {
170         // would remove from "disk" here
171         kfs_destroy_inode(inode);
172 }
173
174 /* unmount and release the super block */
175 void kfs_put_super(struct super_block *sb)
176 {
177         panic("Shazbot! KFS can't be unmounted yet!");
178 }
179
180 /* updates the on-disk SB with the in-memory SB */
181 void kfs_write_super(struct super_block *sb)
182 {       // KFS doesn't care
183 }
184
185 /* syncs FS metadata with the disc, synchronously if we're waiting.  this info
186  * also includes anything pointed to by s_fs_info. */
187 int kfs_sync_fs(struct super_block *sb, bool wait)
188 {
189         return 0;
190 }
191
192 /* remount the FS with the new flags */
193 int kfs_remount_fs(struct super_block *sb, int flags, char *data)
194 {
195         warn("KFS will not remount.");
196         return -1; // can't remount
197 }
198
199 /* interrupts a mount operation - used by NFS and friends */
200 void kfs_umount_begin(struct super_block *sb)
201 {
202         panic("Cannot abort a KFS mount, and why would you?");
203 }
204
205 /* inode_operations */
206
207 /* Create a new disk inode in dir associated with dentry, with the given mode.
208  * called when creating or opening a regular file  (TODO probably not open) */
209 int kfs_create(struct inode *dir, struct dentry *dentry, int mode,
210                struct nameidata *nd)
211 {
212         // TODO: how exactly does this work when we open a file?  and what about
213         // when we need an inode to fill in a dentry structure?
214         // seems like we can use this to fill it in, instead of having the inode
215         // filled in at dentry creation
216         //      - diff between dentry creation for an existing path and a new one (open
217         //      vs create)
218         //      - this might just be for a brand new one (find a free inode, give it to
219         //      me, etc)
220         //
221         //      note it is the i_ino that uniquely identifies a file in the system.
222         //              there's a diff between creating an inode (even for an in-use ino)
223         //              and then filling it in, and vs creating a brand new one
224         //
225         //dentry with d_inode == NULL -> ENOENT (negative entry?)
226         //      linux now has a nameidata for this
227         //
228         //presence of a lookup op (in linux) shows it is a directory... np
229         //same with symlink
230         //their link depth is tied to the task_struct (for max, not for one path)
231         return -1;
232 }
233
234 /* Searches the directory for the filename in the dentry, filling in the dentry
235  * with the FS specific info of this file */
236 struct dentry *kfs_lookup(struct inode *dir, struct dentry *dentry,
237                           struct nameidata *nd)
238 {
239         // TODO: does this mean the inode too?
240         // what the hell are we returning?  the passed in dentry?  an error code?
241         // this will have to read the directory, then find the ino, then creates a
242         // dentry for it
243         //
244         // linux now has a nameidata for this
245         return 0;
246 }
247
248 /* Hard link to old_dentry in directory dir with a name specified by new_dentry.
249  * TODO: should this also make the dentry linkage, or just discard everything?*/
250 int kfs_link(struct dentry *old_dentry, struct inode *dir,
251              struct dentry *new_dentry)
252 {
253         return -1;
254 }
255
256 /* Removes the link from the dentry in the directory */
257 int kfs_unlink(struct inode *dir, struct dentry *dentry)
258 {
259         return -1;
260 }
261
262 /* Creates a new inode for a symlink named symname in dir, and links to dentry.
263  * */
264 int kfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
265 {
266         return -1;
267 }
268
269 /* Creates a new inode for a directory associated with dentry in dir with the
270  * given mode */
271 int kfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
272 {
273         return -1;
274 }
275
276 /* Removes from dir the directory specified by the name in dentry. */
277 // TODO: note this isn't necessarily the same dentry, just using it for the
278 // naming (which seems to be a common way of doing things, like in lookup() -
279 // can work either way.
280 int kfs_rmdir(struct inode *dir, struct dentry *dentry)
281 {
282         return -1;
283 }
284
285 /* Used to make a generic file, based on the type and the major/minor numbers
286  * (in rdev), with the given mode.  As with others, this creates a new disk
287  * inode for the file */
288 int kfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
289 {
290         return -1;
291 }
292
293 /* Moves old_dentry from old_dir to new_dentry in new_dir */
294 int kfs_rename(struct inode *old_dir, struct dentry *old_dentry,
295                struct inode *new_dir, struct dentry *new_dentry)
296 {
297         return -1;
298 }
299
300 /* Copies to the userspace buffer the file pathname corresponding to the symlink
301  * specified by dentry. */
302 int kfs_readlink(struct dentry *dentry, char *buffer, size_t buflen)
303 {
304         return -1;
305 }
306
307 /* Translates the symlink specified by sym and puts the result in nd. */
308 int kfs_follow_link(struct dentry *sym, struct nameidata *nd)
309 {
310         return -1;
311 }
312
313 /* Cleans up after follow_link (decrefs the nameidata business) */
314 int kfs_put_link(struct dentry *sym, struct nameidata *nd)
315 {
316         return -1;
317 }
318
319 /* Modifies the size of the file of inode to whatever its i_size is set to */
320 void kfs_truncate(struct inode *inode)
321 {
322 }
323
324 /* Checks whether the the access mode is allowed for the file belonging to the
325  * inode.  Implies that the permissions are on the file, and not the hardlink */
326 int kfs_permission(struct inode *inode, int mode, struct nameidata *nd)
327 {
328         return -1;
329 }
330
331
332 /* dentry_operations */
333 /* Determines if the dentry is still valid before using it to translate a path.
334  * Network FS's need to deal with this. */
335 int kfs_d_revalidate(struct dentry *dir, struct nameidata *nd)
336 { // default, nothing
337         return -1;
338 }
339
340 /* Produces the hash to lookup this dentry from the dcache */
341 int kfs_d_hash(struct dentry *dentry, struct qstr *name)
342 {
343         return -1;
344 }
345
346 /* Compares name1 and name2.  name1 should be a member of dir. */
347 int kfs_d_compare(struct dentry *dir, struct qstr *name1, struct qstr *name2)
348 { // default, string comp (case sensitive)
349         return -1;
350 }
351
352 /* Called when the last ref is deleted (refcnt == 0) */
353 int kfs_d_delete(struct dentry *dentry)
354 { // default, nothin
355         return -1;
356 }
357
358 /* Called when it's about to be slab-freed */
359 int kfs_d_release(struct dentry *dentry)
360 { // default, nothin
361         return -1;
362 }
363
364 /* Called when the dentry loses it's inode (becomes "negative") */
365 void kfs_d_iput(struct dentry *dentry, struct inode *inode)
366 { // default, call i_put to release the inode object
367 }
368
369
370 /* file_operations */
371
372 /* Updates the file pointer */
373 off_t kfs_llseek(struct file *file, off_t offset, int whence)
374 {
375         return -1;
376 }
377
378 /* Read cound bytes from the file into buf, starting at *offset, which is increased
379  * accordingly */
380 ssize_t kfs_read(struct file *file, char *buf, size_t count, off_t *offset)
381 {
382         return -1;
383 }
384
385 /* Writes count bytes from buf to the file, starting at *offset, which is
386  * increased accordingly */
387 ssize_t kfs_write(struct file *file, const char *buf, size_t count,
388                   off_t *offset)
389 {
390         return -1;
391 }
392
393 /* Fills in the next directory entry (dirent), starting with d_off */
394 int kfs_readdir(struct file *dir, struct dirent *dirent)
395 {
396         return -1;
397 }
398
399 /* Memory maps the file into the virtual memory area */
400 int kfs_mmap(struct file *file, struct vm_area_struct *vma)
401 {
402         return -1;
403 }
404
405 /* Opens the file specified by the inode, linking it with file */
406 int kfs_open(struct inode *inode, struct file *file)
407 {
408         return -1;
409 }
410
411 /* Called when a file descriptor is closed. */
412 int kfs_flush(struct file *file)
413 {
414         return -1;
415 }
416
417 /* Called when the file refcnt == 0 */
418 int kfs_release(struct inode *inode, struct file *file)
419 {
420         return -1;
421 }
422
423 /* Flushes the file's dirty contents to disc */
424 int kfs_fsync(struct file *file, struct dentry *dentry, int datasync)
425 {
426         return -1;
427 }
428
429 /* Traditionally, sleeps until there is file activity.  We probably won't
430  * support this, or we'll handle it differently. */
431 unsigned int kfs_poll(struct file *file, struct poll_table_struct *poll_table)
432 {
433         return -1;
434 }
435
436 /* Reads count bytes from a file, starting from (and modifiying) offset, and
437  * putting the bytes into buffers described by vector */
438 ssize_t kfs_readv(struct file *file, const struct iovec *vector,
439                   unsigned long count, off_t *offset)
440 {
441         return -1;
442 }
443
444 /* Writes count bytes to a file, starting from (and modifiying) offset, and
445  * taking the bytes from buffers described by vector */
446 ssize_t kfs_writev(struct file *file, const struct iovec *vector,
447                   unsigned long count, off_t *offset)
448 {
449         return -1;
450 }
451
452 /* Write the contents of file to the page.  Will sort the params later */
453 ssize_t kfs_sendpage(struct file *file, struct page *page, int offset,
454                      size_t size, off_t pos, int more)
455 {
456         return -1;
457 }
458
459 /* Checks random FS flags.  Used by NFS. */
460 int kfs_check_flags(int flags)
461 { // default, nothing
462         return -1;
463 }
464
465 /* Redeclaration and initialization of the FS ops structures */
466 struct super_operations kfs_s_op = {
467         kfs_alloc_inode,
468         kfs_destroy_inode,
469         kfs_read_inode,
470         kfs_dirty_inode,
471         kfs_write_inode,
472         kfs_put_inode,
473         kfs_drop_inode,
474         kfs_delete_inode,
475         kfs_put_super,
476         kfs_write_super,
477         kfs_sync_fs,
478         kfs_remount_fs,
479         kfs_umount_begin,
480 };
481
482 struct inode_operations kfs_i_op = {
483         kfs_create,
484         kfs_lookup,
485         kfs_link,
486         kfs_unlink,
487         kfs_symlink,
488         kfs_mkdir,
489         kfs_rmdir,
490         kfs_mknod,
491         kfs_rename,
492         kfs_readlink,
493         kfs_follow_link,
494         kfs_put_link,
495         kfs_truncate,
496         kfs_permission,
497 };
498
499 struct dentry_operations kfs_d_op = {
500         kfs_d_revalidate,
501         kfs_d_hash,
502         kfs_d_compare,
503         kfs_d_delete,
504         kfs_d_release,
505         kfs_d_iput,
506 };
507
508 struct file_operations kfs_f_op = {
509         kfs_llseek,
510         kfs_read,
511         kfs_write,
512         kfs_readdir,
513         kfs_mmap,
514         kfs_open,
515         kfs_flush,
516         kfs_release,
517         kfs_fsync,
518         kfs_poll,
519         kfs_readv,
520         kfs_writev,
521         kfs_sendpage,
522         kfs_check_flags,
523 };
524
525 /* KFS Specific Internal Functions */
526
527 /* For obj files compiled with the kernel */
528 #define DECL_PROG(x) \
529     extern uint8_t (COUNT(sizeof(size_t)) _binary_obj_tests_##x##_size)[],\
530         (COUNT(_binary_obj_user_apps_##x##_size)_binary_obj_tests_##x##_start)[];
531
532 #define KFS_PENTRY(x) {#x, _binary_obj_tests_##x##_start, (size_t) _binary_obj_tests_##x##_size},
533
534 /* For generic files in kern/kfs */
535 #define DECL_FILE(x) \
536     extern uint8_t (COUNT(sizeof(size_t)) _binary_kern_kfs_##x##_size)[],\
537         (COUNT(_binary_kern_kfs_##x##_size)_binary_kern_kfs_##x##_start)[];
538
539 #define KFS_FENTRY(x) {#x, _binary_kern_kfs_##x##_start, (size_t) _binary_kern_kfs_##x##_size},
540
541 /*
542  * Hardcode the files included in the KFS.  PROGs need to be in sync with the
543  * userapps in kern/src/Makefrag.  Files need to be in kern/kfs/
544  * Make sure to declare it, and add an entry.  Keep MAX_KFS_FILES big enough too
545  * Note that files with a . in their name will have an _ instead.
546  */
547 #ifdef __CONFIG_KFS__
548 DECL_PROG(tlstest);
549 DECL_PROG(fp_test);
550 DECL_PROG(mproctests);
551 DECL_PROG(hello);
552 DECL_PROG(mhello);
553 DECL_PROG(pthread_test);
554 DECL_PROG(pthread_barrier_test);
555 DECL_PROG(idle);
556 DECL_PROG(tsc_spitter);
557 DECL_PROG(msr_get_cores);
558 DECL_PROG(msr_get_singlecore);
559 DECL_PROG(msr_dumb_while);
560 DECL_PROG(msr_nice_while);
561 DECL_PROG(msr_single_while);
562 DECL_PROG(msr_cycling_vcores);
563 DECL_FILE(kfs_test_txt);
564 DECL_FILE(hello_txt);
565 #endif
566
567 struct kfs_entry kfs[MAX_KFS_FILES] = {
568 #ifdef __CONFIG_KFS__
569         KFS_PENTRY(tlstest)
570         KFS_PENTRY(fp_test)
571         KFS_PENTRY(mproctests)
572         KFS_PENTRY(hello)
573         KFS_PENTRY(mhello)
574         KFS_PENTRY(pthread_test)
575         KFS_PENTRY(pthread_barrier_test)
576         KFS_PENTRY(idle)
577         KFS_PENTRY(tsc_spitter)
578         KFS_PENTRY(msr_get_cores)
579         KFS_PENTRY(msr_get_singlecore)
580         KFS_PENTRY(msr_dumb_while)
581         KFS_PENTRY(msr_nice_while)
582         KFS_PENTRY(msr_single_while)
583         KFS_PENTRY(msr_cycling_vcores)
584         KFS_FENTRY(kfs_test_txt)
585         KFS_FENTRY(hello_txt)
586 #endif
587 };
588
589 ssize_t kfs_lookup_path(char* path)
590 {
591         for (int i = 0; i < MAX_KFS_FILES; i++)
592                 // need to think about how to copy-in something of unknown length
593                 if (!strncmp(kfs[i].name, path, strlen(path)))
594                         return i;
595         return -EINVAL;
596 }
597
598 /*
599  * Creates a process from the file pointed to by the KFS inode (index)
600  * This should take a real inode or something to point to the real location,
601  * and proc_create shouldn't assume everything is contiguous
602  */
603 struct proc *kfs_proc_create(int kfs_inode)
604 {
605         if (kfs_inode < 0 || kfs_inode >= MAX_KFS_FILES)
606                 panic("Invalid kfs_inode.  Check you error codes!");
607         return proc_create(kfs[kfs_inode].start, kfs[kfs_inode].size);
608 }
609
610 /* Dumps the contents of the KFS file to the console.  Not meant to be taken
611  * too seriously - just dumps each char. */
612 void kfs_cat(int kfs_inode)
613 {
614         if (kfs_inode < 0 || kfs_inode >= MAX_KFS_FILES)
615                 panic("Invalid kfs_inode.  Check you error codes!");
616         uint8_t *end = kfs[kfs_inode].start + kfs[kfs_inode].size;
617         for (uint8_t *ptr = kfs[kfs_inode].start; ptr < end; ptr++)
618                 cputchar(*ptr);
619 }