CPIO parsing, kfs building, vfs tweaks
[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 #include <cpio.h>
26
27 #define KFS_MAX_FILE_SIZE 1024*1024*128
28 #define KFS_MAGIC 0xdead0001
29
30 /* VFS required Functions */
31 /* These structs are declared again and initialized farther down */
32 struct super_operations kfs_s_op;
33 struct inode_operations kfs_i_op;
34 struct dentry_operations kfs_d_op;
35 struct file_operations kfs_f_op;
36
37 /* TODO: something more better.  Prob something like the vmem cache, for this,
38  * pids, etc.  Good enough for now.  This also means we can only have one
39  * KFS instance, and we also aren't synchronizing access. */
40 static unsigned long kfs_get_free_ino(void)
41 {
42         static unsigned long last_ino = 1;       /* 1 is reserved for the root */
43         last_ino++;
44         if (!last_ino)
45                 panic("Out of inos in KFS!");
46         return last_ino;
47 }
48
49 /* Slabs for KFS specific info chunks */
50 struct kmem_cache *kfs_i_kcache;
51
52 static void kfs_init(void)
53 {
54         kfs_i_kcache = kmem_cache_create("kfs_ino_info", sizeof(struct kfs_i_info),
55                                          __alignof__(struct kfs_i_info), 0, 0, 0);
56 }
57
58 /* Creates the SB (normally would read in from disc and create).  Ups the refcnt
59  * for whoever consumes this.  Returns 0 on failure.
60  * TODO: consider pulling out more of the FS-independent stuff, if possible.
61  * There are only two things, but the pain in the ass is that you'd need to read
62  * the disc to get that first inode, and it's a FS-specific thing. */
63 struct super_block *kfs_get_sb(struct fs_type *fs, int flags,
64                                char *dev_name, struct vfsmount *vmnt)
65 {
66         /* Ought to check that dev_name has our FS on it.  in this case, it's
67          * irrelevant. */
68         //if (something_bad)
69         //      return 0;
70         static bool ran_once = FALSE;
71         if (!ran_once) {
72                 ran_once = TRUE;
73                 kfs_init();
74         }
75
76         /* Build and init the SB.  No need to read off disc. */
77         struct super_block *sb = get_sb();
78         sb->s_dev = 0;
79         sb->s_blocksize = 1;
80         sb->s_maxbytes = KFS_MAX_FILE_SIZE;
81         sb->s_type = &kfs_fs_type;
82         sb->s_op = &kfs_s_op;
83         sb->s_flags = flags;
84         sb->s_magic = KFS_MAGIC;
85         sb->s_mount = vmnt;
86         sb->s_syncing = FALSE;
87         sb->s_bdev = 0;
88         strlcpy(sb->s_name, "KFS", 32);
89         /* store the location of the CPIO archive.  make this more generic later. */
90         extern uint8_t _binary_obj_kern_initramfs_cpio_size[];
91         extern uint8_t _binary_obj_kern_initramfs_cpio_start[];
92         sb->s_fs_info = (void*)_binary_obj_kern_initramfs_cpio_start;
93
94         /* Final stages of initializing the sb, mostly FS-independent */
95         /* 1 is the KFS root ino (inode number) */
96         init_sb(sb, vmnt, &kfs_d_op, 1, 0);
97         /* Parses the CPIO entries and builds the in-memory KFS tree. */
98         parse_cpio_entries(sb, sb->s_fs_info);
99         printk("KFS superblock loaded\n");
100         return sb;
101 }
102
103 void kfs_kill_sb(struct super_block *sb)
104 {
105         panic("Killing KFS is not supported!");
106 }
107
108 /* Every FS must have a static FS Type, with which the VFS code can bootstrap */
109 struct fs_type kfs_fs_type = {"KFS", 0, kfs_get_sb, kfs_kill_sb, {0, 0},
110                TAILQ_HEAD_INITIALIZER(kfs_fs_type.fs_supers)};
111
112 /* Super Operations */
113
114 /* creates and initializes a new inode.  generic fields are filled in.  specific
115  * fields are filled in in read_inode() based on what's on the disk for a given
116  * i_no.  i_no is set by the caller. */
117 struct inode *kfs_alloc_inode(struct super_block *sb)
118 {
119         /* arguably, we can avoid some of this init by using the slab/cache */
120         struct inode *inode = kmem_cache_alloc(inode_kcache, 0);
121         memset(inode, 0, sizeof(struct inode));
122         TAILQ_INSERT_HEAD(&sb->s_inodes, inode, i_sb_list);
123         TAILQ_INIT(&inode->i_dentry);
124         inode->i_ino = 0;                                       /* set by caller later */
125         atomic_set(&inode->i_refcnt, 1);
126         inode->i_blksize = 1;                           /* keep in sync with get_sb() */
127         spinlock_init(&inode->i_lock);
128         inode->i_op = &kfs_i_op;
129         inode->i_fop = &kfs_f_op;
130         inode->i_sb = sb;
131         inode->i_state = 0;                                     /* need real states, want I_NEW */
132         inode->dirtied_when = 0;
133         atomic_set(&inode->i_writecount, 0);
134         inode->i_fs_info = kmem_cache_alloc(kfs_i_kcache, 0);
135         TAILQ_INIT(&((struct kfs_i_info*)inode->i_fs_info)->children);
136         ((struct kfs_i_info*)inode->i_fs_info)->filestart = 0;
137         return inode;
138         /* caller sets i_ino, i_list set when applicable */
139 }
140
141 /* deallocs and cleans up after an inode. */
142 void kfs_destroy_inode(struct inode *inode)
143 {
144         kmem_cache_free(kfs_i_kcache, inode->i_fs_info);
145         kmem_cache_free(inode_kcache, inode);
146 }
147
148 /* reads the inode data on disk specified by inode->i_ino into the inode.
149  * basically, it's a "make this inode the one for i_ino (i number)" */
150 void kfs_read_inode(struct inode *inode)
151 {
152         /* need to do something to link this inode/file to the actual "blocks" on
153          * "disk". */
154
155         /* TODO: what does it mean to ask for an inode->i_ino that doesn't exist?
156          *      possibly a bug, since these inos come from directories */
157         if (inode->i_ino == 1) {
158                 inode->i_mode = 0x777;                  /* TODO: use something appropriate */
159                 inode->i_nlink = 1;                             /* assuming only one hardlink */
160                 inode->i_uid = 0;
161                 inode->i_gid = 0;
162                 inode->i_rdev = 0;
163                 inode->i_size = 0;                              /* make sense for KFS? */
164                 inode->i_atime.tv_sec = 0;
165                 inode->i_atime.tv_nsec = 0;
166                 inode->i_mtime.tv_sec = 0;
167                 inode->i_mtime.tv_nsec = 0;
168                 inode->i_ctime.tv_sec = 0;
169                 inode->i_ctime.tv_nsec = 0;
170                 inode->i_blocks = 0;
171                 inode->i_bdev = 0;                              /* assuming blockdev? */
172                 inode->i_flags = FS_I_DIR;
173                 inode->i_socket = FALSE;
174         } else {
175                 panic("Not implemented");
176         }
177         /* TODO: unused: inode->i_hash add to hash (saves on disc reading)
178          * i_mapping, i_data, when they mean something */
179 }
180
181 /* called when an inode in memory is modified (journalling FS's care) */
182 void kfs_dirty_inode(struct inode *inode)
183 {       // KFS doesn't care
184 }
185
186 /* write the inode to disk (specifically, to inode inode->i_ino), synchronously
187  * if we're asked to wait */
188 void kfs_write_inode(struct inode *inode, bool wait)
189 {       // KFS doesn't care
190 }
191
192 /* called when an inode is decref'd, to do any FS specific work */
193 void kfs_put_inode(struct inode *inode)
194 {       // KFS doesn't care
195 }
196
197 /* called when an inode is about to be destroyed.  the generic version ought to
198  * remove every reference to the inode from the VFS, and if the inode isn't in
199  * any directory, calls delete_inode */
200 void kfs_drop_inode(struct inode *inode)
201 { // TODO: should call a generic one instead.  or at least do something...
202         // remove from lists
203 }
204
205 /* delete the inode from disk (all data) and deallocs the in memory inode */
206 void kfs_delete_inode(struct inode *inode)
207 {
208         // would remove from "disk" here
209         kfs_destroy_inode(inode);
210 }
211
212 /* unmount and release the super block */
213 void kfs_put_super(struct super_block *sb)
214 {
215         panic("Shazbot! KFS can't be unmounted yet!");
216 }
217
218 /* updates the on-disk SB with the in-memory SB */
219 void kfs_write_super(struct super_block *sb)
220 {       // KFS doesn't care
221 }
222
223 /* syncs FS metadata with the disc, synchronously if we're waiting.  this info
224  * also includes anything pointed to by s_fs_info. */
225 int kfs_sync_fs(struct super_block *sb, bool wait)
226 {
227         return 0;
228 }
229
230 /* remount the FS with the new flags */
231 int kfs_remount_fs(struct super_block *sb, int flags, char *data)
232 {
233         warn("KFS will not remount.");
234         return -1; // can't remount
235 }
236
237 /* interrupts a mount operation - used by NFS and friends */
238 void kfs_umount_begin(struct super_block *sb)
239 {
240         panic("Cannot abort a KFS mount, and why would you?");
241 }
242
243 /* inode_operations */
244
245 /* Helper op, used when creating regular files (kfs_create()) and when making
246  * directories (kfs_mkdir()).  References are a bit ugly.  We're passing out a
247  * ref that is already stored/accounted for.  Might change that...  Also, this
248  * needs to handle having nd == 0. */
249 struct inode *kfs_create_generic(struct inode *dir, struct dentry *dentry,
250                                  int mode, struct nameidata *nd)
251 {
252         /* note it is the i_ino that uniquely identifies a file in the system.
253          * there's a diff between creating an inode (even for an in-use ino) and
254          * then filling it in, and vs creating a brand new one */
255         struct inode *inode = kfs_alloc_inode(dentry->d_sb);
256         dentry->d_inode = inode;                /* inode ref stored here */
257         TAILQ_INSERT_TAIL(&inode->i_dentry, dentry, d_alias); /* stored dentry ref*/
258         inode->i_mode = mode;
259         inode->i_ino = kfs_get_free_ino();
260         inode->i_nlink = 1;
261         inode->i_atime.tv_sec = 0;              /* TODO: now! */
262         inode->i_ctime.tv_sec = 0;              /* TODO: now! */
263         inode->i_mtime.tv_sec = 0;              /* TODO: now! */
264         inode->i_atime.tv_nsec = 0;             /* are these supposed to be the extra ns? */
265         inode->i_ctime.tv_nsec = 0;
266         inode->i_mtime.tv_nsec = 0;
267         return inode;
268 }
269
270 /* Create a new disk inode in dir associated with dentry, with the given mode.
271  * called when creating a regular file.  dir is the directory/parent.  dentry is
272  * the dentry of the inode we are creating. */
273 int kfs_create(struct inode *dir, struct dentry *dentry, int mode,
274                struct nameidata *nd)
275 {
276         struct inode *inode = kfs_create_generic(dir, dentry, mode, nd);        
277         if (!inode)
278                 return -1;
279         inode->i_flags = FS_I_FILE;
280         /* our parent dentry's inode tracks our dentry info.  We do this
281          * since it's all in memory and we aren't using the dcache yet.
282          * We're reusing the subdirs link, which is used by the VFS when
283          * we're a directory.  But since we're a file, it's okay to reuse
284          * it. */
285         TAILQ_INSERT_TAIL(&((struct kfs_i_info*)dir->i_fs_info)->children,
286                           dentry, d_subdirs_link);
287         /* fs_info->filestart is set by the caller, or else when first written (for
288          * new files.  it was set to 0 in alloc_inode(). */
289         return 0;
290 }
291
292 /* Searches the directory for the filename in the dentry, filling in the dentry
293  * with the FS specific info of this file */
294 struct dentry *kfs_lookup(struct inode *dir, struct dentry *dentry,
295                           struct nameidata *nd)
296 {
297         // TODO: does this mean the inode too?
298         // what the hell are we returning?  the passed in dentry?  an error code?
299         // this will have to read the directory, then find the ino, then creates a
300         // dentry for it
301         //
302         // linux now has a nameidata for this
303         return 0;
304 }
305
306 /* Hard link to old_dentry in directory dir with a name specified by new_dentry.
307  * TODO: should this also make the dentry linkage, or just discard everything?*/
308 int kfs_link(struct dentry *old_dentry, struct inode *dir,
309              struct dentry *new_dentry)
310 {
311         return -1;
312 }
313
314 /* Removes the link from the dentry in the directory */
315 int kfs_unlink(struct inode *dir, struct dentry *dentry)
316 {
317         return -1;
318 }
319
320 /* Creates a new inode for a symlink named symname in dir, and links to dentry.
321  * */
322 int kfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
323 {
324         return -1;
325 }
326
327 /* Creates a new inode for a directory associated with dentry in dir with the
328  * given mode.  Note, we might (later) need to track subdirs within the parent
329  * inode, like we do with regular files.  I'd rather not, so we'll see if we
330  * need it. */
331 int kfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
332 {
333         struct inode *inode = kfs_create_generic(dir, dentry, mode, 0); 
334         if (!inode)
335                 return -1;
336         struct dentry *parent = TAILQ_FIRST(&dir->i_dentry);
337         assert(parent && parent == TAILQ_LAST(&dir->i_dentry, dentry_tailq));
338         inode->i_flags = FS_I_DIR;
339         /* parent dentry tracks dentry as a subdir */
340         TAILQ_INSERT_TAIL(&parent->d_subdirs, dentry, d_subdirs_link);
341         atomic_inc(&dentry->d_refcnt);
342         /* get ready to have our own kids */
343         TAILQ_INIT(&((struct kfs_i_info*)inode->i_fs_info)->children);
344         ((struct kfs_i_info*)inode->i_fs_info)->filestart = 0;
345         return 0;
346 }
347
348 /* Removes from dir the directory specified by the name in dentry. */
349 // TODO: note this isn't necessarily the same dentry, just using it for the
350 // naming (which seems to be a common way of doing things, like in lookup() -
351 // can work either way.
352 int kfs_rmdir(struct inode *dir, struct dentry *dentry)
353 {
354         return -1;
355 }
356
357 /* Used to make a generic file, based on the type and the major/minor numbers
358  * (in rdev), with the given mode.  As with others, this creates a new disk
359  * inode for the file */
360 int kfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
361 {
362         return -1;
363 }
364
365 /* Moves old_dentry from old_dir to new_dentry in new_dir */
366 int kfs_rename(struct inode *old_dir, struct dentry *old_dentry,
367                struct inode *new_dir, struct dentry *new_dentry)
368 {
369         return -1;
370 }
371
372 /* Copies to the userspace buffer the file pathname corresponding to the symlink
373  * specified by dentry. */
374 int kfs_readlink(struct dentry *dentry, char *buffer, size_t buflen)
375 {
376         return -1;
377 }
378
379 /* Translates the symlink specified by sym and puts the result in nd. */
380 int kfs_follow_link(struct dentry *sym, struct nameidata *nd)
381 {
382         return -1;
383 }
384
385 /* Cleans up after follow_link (decrefs the nameidata business) */
386 int kfs_put_link(struct dentry *sym, struct nameidata *nd)
387 {
388         return -1;
389 }
390
391 /* Modifies the size of the file of inode to whatever its i_size is set to */
392 void kfs_truncate(struct inode *inode)
393 {
394 }
395
396 /* Checks whether the the access mode is allowed for the file belonging to the
397  * inode.  Implies that the permissions are on the file, and not the hardlink */
398 int kfs_permission(struct inode *inode, int mode, struct nameidata *nd)
399 {
400         return -1;
401 }
402
403
404 /* dentry_operations */
405 /* Determines if the dentry is still valid before using it to translate a path.
406  * Network FS's need to deal with this. */
407 int kfs_d_revalidate(struct dentry *dir, struct nameidata *nd)
408 { // default, nothing
409         return -1;
410 }
411
412 /* Produces the hash to lookup this dentry from the dcache */
413 int kfs_d_hash(struct dentry *dentry, struct qstr *name)
414 {
415         return -1;
416 }
417
418 /* Compares name1 and name2.  name1 should be a member of dir. */
419 int kfs_d_compare(struct dentry *dir, struct qstr *name1, struct qstr *name2)
420 { // default, string comp (case sensitive)
421         return -1;
422 }
423
424 /* Called when the last ref is deleted (refcnt == 0) */
425 int kfs_d_delete(struct dentry *dentry)
426 { // default, nothin
427         return -1;
428 }
429
430 /* Called when it's about to be slab-freed */
431 int kfs_d_release(struct dentry *dentry)
432 { // default, nothin
433         return -1;
434 }
435
436 /* Called when the dentry loses it's inode (becomes "negative") */
437 void kfs_d_iput(struct dentry *dentry, struct inode *inode)
438 { // default, call i_put to release the inode object
439 }
440
441
442 /* file_operations */
443
444 /* Updates the file pointer */
445 off_t kfs_llseek(struct file *file, off_t offset, int whence)
446 {
447         return -1;
448 }
449
450 /* Read cound bytes from the file into buf, starting at *offset, which is increased
451  * accordingly */
452 ssize_t kfs_read(struct file *file, char *buf, size_t count, off_t *offset)
453 {
454         return -1;
455 }
456
457 /* Writes count bytes from buf to the file, starting at *offset, which is
458  * increased accordingly */
459 ssize_t kfs_write(struct file *file, const char *buf, size_t count,
460                   off_t *offset)
461 {
462         return -1;
463 }
464
465 /* Fills in the next directory entry (dirent), starting with d_off */
466 int kfs_readdir(struct file *dir, struct dirent *dirent)
467 {
468         return -1;
469 }
470
471 /* Memory maps the file into the virtual memory area */
472 int kfs_mmap(struct file *file, struct vm_area_struct *vma)
473 {
474         return -1;
475 }
476
477 /* Opens the file specified by the inode, creating and filling in the file */
478 /* TODO: fill out the other // entries, sort vmnt refcnting */
479 int kfs_open(struct inode *inode, struct file *file)
480 {
481         /* This is mostly FS-agnostic, consider a helper */
482         file = kmem_cache_alloc(file_kcache, 0);
483         /* Add to the list of all files of this SB */
484         TAILQ_INSERT_TAIL(&inode->i_sb->s_files, file, f_list);
485         file->f_inode = inode;
486         atomic_inc(&inode->i_refcnt);
487         file->f_vfsmnt = inode->i_sb->s_mount;          /* saving a ref to the vmnt...*/
488         file->f_op = &kfs_f_op;
489         atomic_set(&file->f_refcnt, 1);                         /* ref passed out */
490         file->f_flags = inode->i_flags;                         /* just taking the inode vals */
491         file->f_mode = inode->i_mode;
492         file->f_pos = 0;
493         file->f_uid = inode->i_uid;
494         file->f_gid = inode->i_gid;
495         file->f_error = 0;
496 //      struct event_poll_tailq         f_ep_links;
497         spinlock_init(&file->f_ep_lock);
498         file->f_fs_info = 0;
499 //      struct address_space            *f_mapping;             /* page cache mapping */
500         return 0;
501 }
502
503 /* Called when a file descriptor is closed. */
504 int kfs_flush(struct file *file)
505 {
506         kmem_cache_free(file_kcache, file);
507         return -1;
508 }
509
510 /* Called when the file refcnt == 0 */
511 int kfs_release(struct inode *inode, struct file *file)
512 {
513         return -1;
514 }
515
516 /* Flushes the file's dirty contents to disc */
517 int kfs_fsync(struct file *file, struct dentry *dentry, int datasync)
518 {
519         return -1;
520 }
521
522 /* Traditionally, sleeps until there is file activity.  We probably won't
523  * support this, or we'll handle it differently. */
524 unsigned int kfs_poll(struct file *file, struct poll_table_struct *poll_table)
525 {
526         return -1;
527 }
528
529 /* Reads count bytes from a file, starting from (and modifiying) offset, and
530  * putting the bytes into buffers described by vector */
531 ssize_t kfs_readv(struct file *file, const struct iovec *vector,
532                   unsigned long count, off_t *offset)
533 {
534         return -1;
535 }
536
537 /* Writes count bytes to a file, starting from (and modifiying) offset, and
538  * taking the bytes from buffers described by vector */
539 ssize_t kfs_writev(struct file *file, const struct iovec *vector,
540                   unsigned long count, off_t *offset)
541 {
542         return -1;
543 }
544
545 /* Write the contents of file to the page.  Will sort the params later */
546 ssize_t kfs_sendpage(struct file *file, struct page *page, int offset,
547                      size_t size, off_t pos, int more)
548 {
549         return -1;
550 }
551
552 /* Checks random FS flags.  Used by NFS. */
553 int kfs_check_flags(int flags)
554 { // default, nothing
555         return -1;
556 }
557
558 /* Redeclaration and initialization of the FS ops structures */
559 struct super_operations kfs_s_op = {
560         kfs_alloc_inode,
561         kfs_destroy_inode,
562         kfs_read_inode,
563         kfs_dirty_inode,
564         kfs_write_inode,
565         kfs_put_inode,
566         kfs_drop_inode,
567         kfs_delete_inode,
568         kfs_put_super,
569         kfs_write_super,
570         kfs_sync_fs,
571         kfs_remount_fs,
572         kfs_umount_begin,
573 };
574
575 struct inode_operations kfs_i_op = {
576         kfs_create,
577         kfs_lookup,
578         kfs_link,
579         kfs_unlink,
580         kfs_symlink,
581         kfs_mkdir,
582         kfs_rmdir,
583         kfs_mknod,
584         kfs_rename,
585         kfs_readlink,
586         kfs_follow_link,
587         kfs_put_link,
588         kfs_truncate,
589         kfs_permission,
590 };
591
592 struct dentry_operations kfs_d_op = {
593         kfs_d_revalidate,
594         kfs_d_hash,
595         kfs_d_compare,
596         kfs_d_delete,
597         kfs_d_release,
598         kfs_d_iput,
599 };
600
601 struct file_operations kfs_f_op = {
602         kfs_llseek,
603         kfs_read,
604         kfs_write,
605         kfs_readdir,
606         kfs_mmap,
607         kfs_open,
608         kfs_flush,
609         kfs_release,
610         kfs_fsync,
611         kfs_poll,
612         kfs_readv,
613         kfs_writev,
614         kfs_sendpage,
615         kfs_check_flags,
616 };
617
618 /* KFS Specific Internal Functions */
619
620 /* For obj files compiled with the kernel */
621 #define DECL_PROG(x) \
622     extern uint8_t (COUNT(sizeof(size_t)) _binary_obj_tests_##x##_size)[],\
623         (COUNT(_binary_obj_user_apps_##x##_size)_binary_obj_tests_##x##_start)[];
624
625 #define KFS_PENTRY(x) {#x, _binary_obj_tests_##x##_start, (size_t) _binary_obj_tests_##x##_size},
626
627 /*
628  * Hardcode the files included in the KFS.  PROGs need to be in sync with the
629  * userapps in kern/src/Makefrag.  Files need to be in kern/kfs/
630  * Make sure to declare it, and add an entry.  Keep MAX_KFS_FILES big enough too
631  * Note that files with a . in their name will have an _ instead.
632  */
633 #ifdef __CONFIG_KFS__
634 DECL_PROG(tlstest);
635 DECL_PROG(fp_test);
636 DECL_PROG(mproctests);
637 DECL_PROG(hello);
638 DECL_PROG(mhello);
639 DECL_PROG(pthread_test);
640 DECL_PROG(pthread_barrier_test);
641 DECL_PROG(idle);
642 DECL_PROG(tsc_spitter);
643 DECL_PROG(msr_get_cores);
644 DECL_PROG(msr_get_singlecore);
645 DECL_PROG(msr_dumb_while);
646 DECL_PROG(msr_nice_while);
647 DECL_PROG(msr_single_while);
648 DECL_PROG(msr_cycling_vcores);
649 #endif
650
651 struct kfs_entry kfs[MAX_KFS_FILES] = {
652 #ifdef __CONFIG_KFS__
653         KFS_PENTRY(tlstest)
654         KFS_PENTRY(fp_test)
655         KFS_PENTRY(mproctests)
656         KFS_PENTRY(hello)
657         KFS_PENTRY(mhello)
658         KFS_PENTRY(pthread_test)
659         KFS_PENTRY(pthread_barrier_test)
660         KFS_PENTRY(idle)
661         KFS_PENTRY(tsc_spitter)
662         KFS_PENTRY(msr_get_cores)
663         KFS_PENTRY(msr_get_singlecore)
664         KFS_PENTRY(msr_dumb_while)
665         KFS_PENTRY(msr_nice_while)
666         KFS_PENTRY(msr_single_while)
667         KFS_PENTRY(msr_cycling_vcores)
668 #endif
669 };
670
671 ssize_t kfs_lookup_path(char* path)
672 {
673         for (int i = 0; i < MAX_KFS_FILES; i++)
674                 // need to think about how to copy-in something of unknown length
675                 if (!strncmp(kfs[i].name, path, strlen(path)))
676                         return i;
677         return -EINVAL;
678 }
679
680 /*
681  * Creates a process from the file pointed to by the KFS inode (index)
682  * This should take a real inode or something to point to the real location,
683  * and proc_create shouldn't assume everything is contiguous
684  */
685 struct proc *kfs_proc_create(int kfs_inode)
686 {
687         if (kfs_inode < 0 || kfs_inode >= MAX_KFS_FILES)
688                 panic("Invalid kfs_inode.  Check you error codes!");
689         return proc_create(kfs[kfs_inode].start, kfs[kfs_inode].size);
690 }
691
692 /* Dumps the contents of the KFS file to the console.  Not meant to be taken
693  * too seriously - just dumps each char. */
694 void kfs_cat(int kfs_inode)
695 {
696         if (kfs_inode < 0 || kfs_inode >= MAX_KFS_FILES)
697                 panic("Invalid kfs_inode.  Check you error codes!");
698         uint8_t *end = kfs[kfs_inode].start + kfs[kfs_inode].size;
699         for (uint8_t *ptr = kfs[kfs_inode].start; ptr < end; ptr++)
700                 cputchar(*ptr);
701 }
702
703 /* Need to pass path separately, since we'll recurse on it */
704 static int __add_kfs_entry(struct dentry *parent, char *path,
705                            struct cpio_bin_hdr *c_bhdr)
706 {
707         char *first_slash = strchr(path, '/');  
708         char dir[MAX_FILENAME_SZ + 1];  /* room for the \0 */
709         size_t dirname_sz;                              /* not counting the \0 */
710         struct dentry *dentry;
711         struct inode *inode;
712
713         if (first_slash) {
714                 /* get the first part, find that dentry, pass in the second part,
715                  * recurse.  this isn't being smart about extra slashes, dots, or
716                  * anything like that. */
717                 dirname_sz = first_slash - path;
718                 assert(dirname_sz <= MAX_FILENAME_SZ);
719                 strncpy(dir, path, dirname_sz);
720                 dir[dirname_sz] = '\0';
721                 printk("Finding DIR %s in dentry %s (start: %p, size %d)\n", dir,
722                        parent->d_name.name, c_bhdr->c_filestart, c_bhdr->c_filesize);
723                 // send to the real dentry
724                 __add_kfs_entry(parent, first_slash + 1, c_bhdr);
725
726         } else {
727                 /* no directories left in the path.  add the 'file' to the dentry */
728                 printk("Adding file/dir %s to dentry %s (start: %p, size %d)\n", path,
729                        parent->d_name.name, c_bhdr->c_filestart, c_bhdr->c_filesize);
730
731                 /* Init the dentry for this path */
732                 dentry = get_dentry(parent->d_sb, parent, path);
733                 dentry->d_op = &kfs_d_op;
734                 dcache_put(dentry);                     /* TODO: should set a d_flag too */
735                 /* build the inode */
736                 if (!c_bhdr->c_filesize) {
737                         /* we are a directory.  Note that fifos might look like dirs... */
738                         kfs_mkdir(parent->d_inode, dentry, c_bhdr->c_mode);
739                         inode = dentry->d_inode;
740                 } else {
741                         /* we are a file */
742                         kfs_create(parent->d_inode, dentry, c_bhdr->c_mode, 0);
743                         inode = dentry->d_inode;
744                         ((struct kfs_i_info*)inode->i_fs_info)->filestart =
745                                                                 c_bhdr->c_filestart;
746                 }
747                 /* Set other info from the CPIO entry */
748                 inode->i_uid = c_bhdr->c_uid;
749                 inode->i_gid = c_bhdr->c_gid;
750                 inode->i_atime.tv_sec = c_bhdr->c_mtime;
751                 inode->i_ctime.tv_sec = c_bhdr->c_mtime;
752                 inode->i_mtime.tv_sec = c_bhdr->c_mtime;
753                 inode->i_size = c_bhdr->c_filesize;
754                 //inode->i_XXX = c_bhdr->c_dev;                 /* and friends */
755                 inode->i_bdev = 0;                                              /* assuming blockdev? */
756                 inode->i_socket = FALSE;
757                 inode->i_blocks = c_bhdr->c_filesize;   /* blocksize == 1 */
758         }
759         return 0;
760 }
761
762 /* Adds an entry (from a CPIO archive) to KFS.  This will put all the FS
763  * metadata in memory, instead of having to reparse the entire archive each time
764  * we need to traverse.
765  *
766  * The other option is to just maintain a LL of {FN, FS}, and O(n) scan it.
767  *
768  * The path is a complete path, interpreted from the root of the mount point.
769  * Directories have a size of 0.  so do symlinks, but we don't handle those yet.
770  *
771  * If a directory does not exist for a file, this will return an error.  Don't
772  * use the -depth flag to find when building the CPIO archive, and this won't be
773  * a problem.  (Maybe) */
774 static int add_kfs_entry(struct super_block *sb, struct cpio_bin_hdr *c_bhdr)
775 {
776         char *path = c_bhdr->c_filename;
777         /* Root of the FS, already part of KFS */
778         if (!strcmp(path, "."))
779                 return 0;
780         return __add_kfs_entry(sb->s_mount->mnt_root, path, c_bhdr);
781 }
782
783 void parse_cpio_entries(struct super_block *sb, void *cpio_b)
784 {
785         struct cpio_newc_header *c_hdr = (struct cpio_newc_header*)cpio_b;
786
787         char buf[9] = {0};      /* temp space for strol conversions */
788         size_t namesize = 0;
789         int offset = 0;         /* offset in the cpio archive */
790         struct cpio_bin_hdr *c_bhdr = kmalloc(sizeof(*c_bhdr), 0);
791         memset(c_bhdr, 0, sizeof(*c_bhdr));
792
793         /* read all files and paths */
794         for (; ; c_hdr = (struct cpio_newc_header*)(cpio_b + offset)) {
795                 offset += sizeof(*c_hdr);
796                 if (strncmp(c_hdr->c_magic, "070701", 6)) {
797                         printk("Invalid magic number in CPIO header, aborting.\n");
798                         return;
799                 }
800                 c_bhdr->c_filename = (char*)c_hdr + sizeof(*c_hdr);
801                 namesize = cpio_strntol(buf, c_hdr->c_namesize, 8);
802                 printd("Namesize: %d\n", size);
803                 if (!strcmp(c_bhdr->c_filename, "TRAILER!!!"))
804                         break;
805                 c_bhdr->c_ino = cpio_strntol(buf, c_hdr->c_ino, 8);
806                 c_bhdr->c_mode = (int)cpio_strntol(buf, c_hdr->c_mode, 8);
807                 c_bhdr->c_uid = cpio_strntol(buf, c_hdr->c_uid, 8);
808                 c_bhdr->c_gid = cpio_strntol(buf, c_hdr->c_gid, 8);
809                 c_bhdr->c_nlink = (unsigned int)cpio_strntol(buf, c_hdr->c_nlink, 8);
810                 c_bhdr->c_mtime = cpio_strntol(buf, c_hdr->c_mtime, 8);
811                 c_bhdr->c_filesize = cpio_strntol(buf, c_hdr->c_filesize, 8);
812                 c_bhdr->c_dev_maj = cpio_strntol(buf, c_hdr->c_dev_maj, 8);
813                 c_bhdr->c_dev_min = cpio_strntol(buf, c_hdr->c_dev_min, 8);
814                 c_bhdr->c_rdev_maj = cpio_strntol(buf, c_hdr->c_rdev_maj, 8);
815                 c_bhdr->c_rdev_min = cpio_strntol(buf, c_hdr->c_rdev_min, 8);
816                 printk("File: %s: %d Bytes\n", c_bhdr->c_filename, c_bhdr->c_filesize);
817                 offset += namesize;
818                 /* header + name will be padded out to 4-byte alignment */
819                 offset = ROUNDUP(offset, 4);
820                 /* make this a function pointer or something */
821                 if (add_kfs_entry(sb, c_bhdr)) {
822                         printk("Failed to add an entry to KFS!\n");
823                         break;
824                 }
825                 offset += c_bhdr->c_filesize;
826                 offset = ROUNDUP(offset, 4);
827                 //printk("offset is %d bytes\n", offset);
828                 c_hdr = (struct cpio_newc_header*)(cpio_b + offset);
829         }
830         kfree(c_bhdr);
831 }
832
833 /* Debugging */
834 void print_dir_tree(struct dentry *dentry, int depth)
835 {
836         struct inode *inode = dentry->d_inode;
837         struct kfs_i_info *k_i_info = (struct kfs_i_info*)inode->i_fs_info;
838         struct dentry *d_i;
839         assert(dentry && inode && inode->i_flags & FS_I_DIR);
840         char buf[32] = {0};
841
842         for (int i = 0; i < depth; i++)
843                 buf[i] = '\t';
844
845         TAILQ_FOREACH(d_i, &dentry->d_subdirs, d_subdirs_link) {
846                 printk("%sDir %s has child dir: %s\n", buf, dentry->d_name.name,
847                        d_i->d_name.name);
848                 print_dir_tree(d_i, depth + 1);
849         }
850         TAILQ_FOREACH(d_i, &k_i_info->children, d_subdirs_link)
851                 printk("%sDir %s has child file: %s\n", buf, dentry->d_name.name,
852                        d_i->d_name.name);
853 }