kfs_open()
[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         /* need to do something to link this inode/file to the actual "blocks" on
116          * "disk". */
117
118         /* TODO: what does it mean to ask for an inode->i_ino that doesn't exist?
119          *      possibly a bug, since these inos come from directories */
120         if (inode->i_ino == 1) {
121                 inode->i_mode = 0x777;                  /* TODO: use something appropriate */
122                 inode->i_nlink = 1;                             /* assuming only one hardlink */
123                 inode->i_uid = 0;
124                 inode->i_gid = 0;
125                 inode->i_rdev = 0;
126                 inode->i_size = 0;                              /* make sense for KFS? */
127                 inode->i_atime.tv_sec = 0;
128                 inode->i_atime.tv_nsec = 0;
129                 inode->i_mtime.tv_sec = 0;
130                 inode->i_mtime.tv_nsec = 0;
131                 inode->i_ctime.tv_sec = 0;
132                 inode->i_ctime.tv_nsec = 0;
133                 inode->i_blksize = 0;
134                 inode->i_blocks = 0;
135                 inode->i_bdev = 0;                              /* assuming blockdev? */
136                 inode->dirtied_when = 0;
137                 inode->i_flags = 0;
138                 inode->i_socket = FALSE;
139         } else {
140                 panic("Not implemented");
141         }
142         /* TODO: unused: inode->i_hash add to hash (saves on disc reading)
143          * i_mapping, i_data, when they mean something */
144 }
145
146 /* called when an inode in memory is modified (journalling FS's care) */
147 void kfs_dirty_inode(struct inode *inode)
148 {       // KFS doesn't care
149 }
150
151 /* write the inode to disk (specifically, to inode inode->i_ino), synchronously
152  * if we're asked to wait */
153 void kfs_write_inode(struct inode *inode, bool wait)
154 {       // KFS doesn't care
155 }
156
157 /* called when an inode is decref'd, to do any FS specific work */
158 void kfs_put_inode(struct inode *inode)
159 {       // KFS doesn't care
160 }
161
162 /* called when an inode is about to be destroyed.  the generic version ought to
163  * remove every reference to the inode from the VFS, and if the inode isn't in
164  * any directory, calls delete_inode */
165 void kfs_drop_inode(struct inode *inode)
166 { // TODO: should call a generic one instead.  or at least do something...
167         // remove from lists
168 }
169
170 /* delete the inode from disk (all data) and deallocs the in memory inode */
171 void kfs_delete_inode(struct inode *inode)
172 {
173         // would remove from "disk" here
174         kfs_destroy_inode(inode);
175 }
176
177 /* unmount and release the super block */
178 void kfs_put_super(struct super_block *sb)
179 {
180         panic("Shazbot! KFS can't be unmounted yet!");
181 }
182
183 /* updates the on-disk SB with the in-memory SB */
184 void kfs_write_super(struct super_block *sb)
185 {       // KFS doesn't care
186 }
187
188 /* syncs FS metadata with the disc, synchronously if we're waiting.  this info
189  * also includes anything pointed to by s_fs_info. */
190 int kfs_sync_fs(struct super_block *sb, bool wait)
191 {
192         return 0;
193 }
194
195 /* remount the FS with the new flags */
196 int kfs_remount_fs(struct super_block *sb, int flags, char *data)
197 {
198         warn("KFS will not remount.");
199         return -1; // can't remount
200 }
201
202 /* interrupts a mount operation - used by NFS and friends */
203 void kfs_umount_begin(struct super_block *sb)
204 {
205         panic("Cannot abort a KFS mount, and why would you?");
206 }
207
208 /* inode_operations */
209
210 /* Create a new disk inode in dir associated with dentry, with the given mode.
211  * called when creating or opening a regular file  (TODO probably not open) */
212 int kfs_create(struct inode *dir, struct dentry *dentry, int mode,
213                struct nameidata *nd)
214 {
215         // TODO: how exactly does this work when we open a file?  and what about
216         // when we need an inode to fill in a dentry structure?
217         // seems like we can use this to fill it in, instead of having the inode
218         // filled in at dentry creation
219         //      - diff between dentry creation for an existing path and a new one (open
220         //      vs create)
221         //      - this might just be for a brand new one (find a free inode, give it to
222         //      me, etc)
223         //
224         //      note it is the i_ino that uniquely identifies a file in the system.
225         //              there's a diff between creating an inode (even for an in-use ino)
226         //              and then filling it in, and vs creating a brand new one
227         //
228         //dentry with d_inode == NULL -> ENOENT (negative entry?)
229         //      linux now has a nameidata for this
230         //
231         //presence of a lookup op (in linux) shows it is a directory... np
232         //same with symlink
233         //their link depth is tied to the task_struct (for max, not for one path)
234         return -1;
235 }
236
237 /* Searches the directory for the filename in the dentry, filling in the dentry
238  * with the FS specific info of this file */
239 struct dentry *kfs_lookup(struct inode *dir, struct dentry *dentry,
240                           struct nameidata *nd)
241 {
242         // TODO: does this mean the inode too?
243         // what the hell are we returning?  the passed in dentry?  an error code?
244         // this will have to read the directory, then find the ino, then creates a
245         // dentry for it
246         //
247         // linux now has a nameidata for this
248         return 0;
249 }
250
251 /* Hard link to old_dentry in directory dir with a name specified by new_dentry.
252  * TODO: should this also make the dentry linkage, or just discard everything?*/
253 int kfs_link(struct dentry *old_dentry, struct inode *dir,
254              struct dentry *new_dentry)
255 {
256         return -1;
257 }
258
259 /* Removes the link from the dentry in the directory */
260 int kfs_unlink(struct inode *dir, struct dentry *dentry)
261 {
262         return -1;
263 }
264
265 /* Creates a new inode for a symlink named symname in dir, and links to dentry.
266  * */
267 int kfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
268 {
269         return -1;
270 }
271
272 /* Creates a new inode for a directory associated with dentry in dir with the
273  * given mode */
274 int kfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
275 {
276         return -1;
277 }
278
279 /* Removes from dir the directory specified by the name in dentry. */
280 // TODO: note this isn't necessarily the same dentry, just using it for the
281 // naming (which seems to be a common way of doing things, like in lookup() -
282 // can work either way.
283 int kfs_rmdir(struct inode *dir, struct dentry *dentry)
284 {
285         return -1;
286 }
287
288 /* Used to make a generic file, based on the type and the major/minor numbers
289  * (in rdev), with the given mode.  As with others, this creates a new disk
290  * inode for the file */
291 int kfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
292 {
293         return -1;
294 }
295
296 /* Moves old_dentry from old_dir to new_dentry in new_dir */
297 int kfs_rename(struct inode *old_dir, struct dentry *old_dentry,
298                struct inode *new_dir, struct dentry *new_dentry)
299 {
300         return -1;
301 }
302
303 /* Copies to the userspace buffer the file pathname corresponding to the symlink
304  * specified by dentry. */
305 int kfs_readlink(struct dentry *dentry, char *buffer, size_t buflen)
306 {
307         return -1;
308 }
309
310 /* Translates the symlink specified by sym and puts the result in nd. */
311 int kfs_follow_link(struct dentry *sym, struct nameidata *nd)
312 {
313         return -1;
314 }
315
316 /* Cleans up after follow_link (decrefs the nameidata business) */
317 int kfs_put_link(struct dentry *sym, struct nameidata *nd)
318 {
319         return -1;
320 }
321
322 /* Modifies the size of the file of inode to whatever its i_size is set to */
323 void kfs_truncate(struct inode *inode)
324 {
325 }
326
327 /* Checks whether the the access mode is allowed for the file belonging to the
328  * inode.  Implies that the permissions are on the file, and not the hardlink */
329 int kfs_permission(struct inode *inode, int mode, struct nameidata *nd)
330 {
331         return -1;
332 }
333
334
335 /* dentry_operations */
336 /* Determines if the dentry is still valid before using it to translate a path.
337  * Network FS's need to deal with this. */
338 int kfs_d_revalidate(struct dentry *dir, struct nameidata *nd)
339 { // default, nothing
340         return -1;
341 }
342
343 /* Produces the hash to lookup this dentry from the dcache */
344 int kfs_d_hash(struct dentry *dentry, struct qstr *name)
345 {
346         return -1;
347 }
348
349 /* Compares name1 and name2.  name1 should be a member of dir. */
350 int kfs_d_compare(struct dentry *dir, struct qstr *name1, struct qstr *name2)
351 { // default, string comp (case sensitive)
352         return -1;
353 }
354
355 /* Called when the last ref is deleted (refcnt == 0) */
356 int kfs_d_delete(struct dentry *dentry)
357 { // default, nothin
358         return -1;
359 }
360
361 /* Called when it's about to be slab-freed */
362 int kfs_d_release(struct dentry *dentry)
363 { // default, nothin
364         return -1;
365 }
366
367 /* Called when the dentry loses it's inode (becomes "negative") */
368 void kfs_d_iput(struct dentry *dentry, struct inode *inode)
369 { // default, call i_put to release the inode object
370 }
371
372
373 /* file_operations */
374
375 /* Updates the file pointer */
376 off_t kfs_llseek(struct file *file, off_t offset, int whence)
377 {
378         return -1;
379 }
380
381 /* Read cound bytes from the file into buf, starting at *offset, which is increased
382  * accordingly */
383 ssize_t kfs_read(struct file *file, char *buf, size_t count, off_t *offset)
384 {
385         return -1;
386 }
387
388 /* Writes count bytes from buf to the file, starting at *offset, which is
389  * increased accordingly */
390 ssize_t kfs_write(struct file *file, const char *buf, size_t count,
391                   off_t *offset)
392 {
393         return -1;
394 }
395
396 /* Fills in the next directory entry (dirent), starting with d_off */
397 int kfs_readdir(struct file *dir, struct dirent *dirent)
398 {
399         return -1;
400 }
401
402 /* Memory maps the file into the virtual memory area */
403 int kfs_mmap(struct file *file, struct vm_area_struct *vma)
404 {
405         return -1;
406 }
407
408 /* Opens the file specified by the inode, creating and filling in the file */
409 /* TODO: fill out the other // entries, sort vmnt refcnting */
410 int kfs_open(struct inode *inode, struct file *file)
411 {
412         /* This is mostly FS-agnostic, consider a helper */
413         file = kmem_cache_alloc(file_kcache, 0);
414         /* Add to the list of all files of this SB */
415         TAILQ_INSERT_TAIL(&inode->i_sb->s_files, file, f_list);
416         file->f_inode = inode;
417         atomic_inc(&inode->i_refcnt);
418         file->f_vfsmnt = inode->i_sb->s_mount;          /* saving a ref to the vmnt...*/
419         file->f_op = &kfs_f_op;
420         atomic_set(&file->f_refcnt, 1);                         /* ref passed out */
421         file->f_flags = inode->i_flags;                         /* just taking the inode vals */
422         file->f_mode = inode->i_mode;
423         file->f_pos = 0;
424         file->f_uid = inode->i_uid;
425         file->f_gid = inode->i_gid;
426         file->f_error = 0;
427 //      struct event_poll_tailq         f_ep_links;
428         spinlock_init(&file->f_ep_lock);
429         file->f_fs_info = 0;
430 //      struct address_space            *f_mapping;             /* page cache mapping */
431         return 0;
432 }
433
434 /* Called when a file descriptor is closed. */
435 int kfs_flush(struct file *file)
436 {
437         kmem_cache_free(file_kcache, file);
438         return -1;
439 }
440
441 /* Called when the file refcnt == 0 */
442 int kfs_release(struct inode *inode, struct file *file)
443 {
444         return -1;
445 }
446
447 /* Flushes the file's dirty contents to disc */
448 int kfs_fsync(struct file *file, struct dentry *dentry, int datasync)
449 {
450         return -1;
451 }
452
453 /* Traditionally, sleeps until there is file activity.  We probably won't
454  * support this, or we'll handle it differently. */
455 unsigned int kfs_poll(struct file *file, struct poll_table_struct *poll_table)
456 {
457         return -1;
458 }
459
460 /* Reads count bytes from a file, starting from (and modifiying) offset, and
461  * putting the bytes into buffers described by vector */
462 ssize_t kfs_readv(struct file *file, const struct iovec *vector,
463                   unsigned long count, off_t *offset)
464 {
465         return -1;
466 }
467
468 /* Writes count bytes to a file, starting from (and modifiying) offset, and
469  * taking the bytes from buffers described by vector */
470 ssize_t kfs_writev(struct file *file, const struct iovec *vector,
471                   unsigned long count, off_t *offset)
472 {
473         return -1;
474 }
475
476 /* Write the contents of file to the page.  Will sort the params later */
477 ssize_t kfs_sendpage(struct file *file, struct page *page, int offset,
478                      size_t size, off_t pos, int more)
479 {
480         return -1;
481 }
482
483 /* Checks random FS flags.  Used by NFS. */
484 int kfs_check_flags(int flags)
485 { // default, nothing
486         return -1;
487 }
488
489 /* Redeclaration and initialization of the FS ops structures */
490 struct super_operations kfs_s_op = {
491         kfs_alloc_inode,
492         kfs_destroy_inode,
493         kfs_read_inode,
494         kfs_dirty_inode,
495         kfs_write_inode,
496         kfs_put_inode,
497         kfs_drop_inode,
498         kfs_delete_inode,
499         kfs_put_super,
500         kfs_write_super,
501         kfs_sync_fs,
502         kfs_remount_fs,
503         kfs_umount_begin,
504 };
505
506 struct inode_operations kfs_i_op = {
507         kfs_create,
508         kfs_lookup,
509         kfs_link,
510         kfs_unlink,
511         kfs_symlink,
512         kfs_mkdir,
513         kfs_rmdir,
514         kfs_mknod,
515         kfs_rename,
516         kfs_readlink,
517         kfs_follow_link,
518         kfs_put_link,
519         kfs_truncate,
520         kfs_permission,
521 };
522
523 struct dentry_operations kfs_d_op = {
524         kfs_d_revalidate,
525         kfs_d_hash,
526         kfs_d_compare,
527         kfs_d_delete,
528         kfs_d_release,
529         kfs_d_iput,
530 };
531
532 struct file_operations kfs_f_op = {
533         kfs_llseek,
534         kfs_read,
535         kfs_write,
536         kfs_readdir,
537         kfs_mmap,
538         kfs_open,
539         kfs_flush,
540         kfs_release,
541         kfs_fsync,
542         kfs_poll,
543         kfs_readv,
544         kfs_writev,
545         kfs_sendpage,
546         kfs_check_flags,
547 };
548
549 /* KFS Specific Internal Functions */
550
551 /* For obj files compiled with the kernel */
552 #define DECL_PROG(x) \
553     extern uint8_t (COUNT(sizeof(size_t)) _binary_obj_tests_##x##_size)[],\
554         (COUNT(_binary_obj_user_apps_##x##_size)_binary_obj_tests_##x##_start)[];
555
556 #define KFS_PENTRY(x) {#x, _binary_obj_tests_##x##_start, (size_t) _binary_obj_tests_##x##_size},
557
558 /* For generic files in kern/kfs */
559 #define DECL_FILE(x) \
560     extern uint8_t (COUNT(sizeof(size_t)) _binary_kern_kfs_##x##_size)[],\
561         (COUNT(_binary_kern_kfs_##x##_size)_binary_kern_kfs_##x##_start)[];
562
563 #define KFS_FENTRY(x) {#x, _binary_kern_kfs_##x##_start, (size_t) _binary_kern_kfs_##x##_size},
564
565 /*
566  * Hardcode the files included in the KFS.  PROGs need to be in sync with the
567  * userapps in kern/src/Makefrag.  Files need to be in kern/kfs/
568  * Make sure to declare it, and add an entry.  Keep MAX_KFS_FILES big enough too
569  * Note that files with a . in their name will have an _ instead.
570  */
571 #ifdef __CONFIG_KFS__
572 DECL_PROG(tlstest);
573 DECL_PROG(fp_test);
574 DECL_PROG(mproctests);
575 DECL_PROG(hello);
576 DECL_PROG(mhello);
577 DECL_PROG(pthread_test);
578 DECL_PROG(pthread_barrier_test);
579 DECL_PROG(idle);
580 DECL_PROG(tsc_spitter);
581 DECL_PROG(msr_get_cores);
582 DECL_PROG(msr_get_singlecore);
583 DECL_PROG(msr_dumb_while);
584 DECL_PROG(msr_nice_while);
585 DECL_PROG(msr_single_while);
586 DECL_PROG(msr_cycling_vcores);
587 DECL_FILE(kfs_test_txt);
588 DECL_FILE(hello_txt);
589 #endif
590
591 struct kfs_entry kfs[MAX_KFS_FILES] = {
592 #ifdef __CONFIG_KFS__
593         KFS_PENTRY(tlstest)
594         KFS_PENTRY(fp_test)
595         KFS_PENTRY(mproctests)
596         KFS_PENTRY(hello)
597         KFS_PENTRY(mhello)
598         KFS_PENTRY(pthread_test)
599         KFS_PENTRY(pthread_barrier_test)
600         KFS_PENTRY(idle)
601         KFS_PENTRY(tsc_spitter)
602         KFS_PENTRY(msr_get_cores)
603         KFS_PENTRY(msr_get_singlecore)
604         KFS_PENTRY(msr_dumb_while)
605         KFS_PENTRY(msr_nice_while)
606         KFS_PENTRY(msr_single_while)
607         KFS_PENTRY(msr_cycling_vcores)
608         KFS_FENTRY(kfs_test_txt)
609         KFS_FENTRY(hello_txt)
610 #endif
611 };
612
613 ssize_t kfs_lookup_path(char* path)
614 {
615         for (int i = 0; i < MAX_KFS_FILES; i++)
616                 // need to think about how to copy-in something of unknown length
617                 if (!strncmp(kfs[i].name, path, strlen(path)))
618                         return i;
619         return -EINVAL;
620 }
621
622 /*
623  * Creates a process from the file pointed to by the KFS inode (index)
624  * This should take a real inode or something to point to the real location,
625  * and proc_create shouldn't assume everything is contiguous
626  */
627 struct proc *kfs_proc_create(int kfs_inode)
628 {
629         if (kfs_inode < 0 || kfs_inode >= MAX_KFS_FILES)
630                 panic("Invalid kfs_inode.  Check you error codes!");
631         return proc_create(kfs[kfs_inode].start, kfs[kfs_inode].size);
632 }
633
634 /* Dumps the contents of the KFS file to the console.  Not meant to be taken
635  * too seriously - just dumps each char. */
636 void kfs_cat(int kfs_inode)
637 {
638         if (kfs_inode < 0 || kfs_inode >= MAX_KFS_FILES)
639                 panic("Invalid kfs_inode.  Check you error codes!");
640         uint8_t *end = kfs[kfs_inode].start + kfs[kfs_inode].size;
641         for (uint8_t *ptr = kfs[kfs_inode].start; ptr < end; ptr++)
642                 cputchar(*ptr);
643 }