Mounts ext2
[akaros.git] / kern / src / ext2fs.c
1 /* Copyright (c) 2010 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * For now, just a lot of debugging / bootstrapping functions for ext2.
6  */
7
8 #include <vfs.h>
9 #include <ext2fs.h>
10 #include <blockdev.h>
11 #include <kmalloc.h>
12 #include <assert.h>
13 #include <kref.h>
14 #include <endian.h>
15
16 /* These structs are declared again and initialized farther down */
17 struct page_map_operations ext2_pm_op;
18 struct super_operations ext2_s_op;
19 struct inode_operations ext2_i_op;
20 struct dentry_operations ext2_d_op;
21 struct file_operations ext2_f_op_file;
22 struct file_operations ext2_f_op_dir;
23 struct file_operations ext2_f_op_sym;
24
25 /* EXT2 Internal Functions */
26 /* Free whatever is returned with kfree(), pending proper buffer management.
27  * Ext2's superblock is always in the same spot, starting at byte 1024 and is
28  * 1024 bytes long. */
29 struct ext2_sb *ext2_read_sb(struct block_device *bdev)
30 {
31         struct ext2_sb *e2sb;
32         struct block_request *breq;
33         int retval;
34
35         e2sb = kmalloc(sizeof(struct ext2_sb), 0);
36         assert(e2sb);
37         breq = kmem_cache_alloc(breq_kcache, 0);
38         assert(breq);
39         breq->flags = BREQ_READ;
40         breq->buffer = e2sb;
41         breq->first_sector = 1024 >> SECTOR_SZ_LOG;
42         breq->amount = 1024 >> SECTOR_SZ_LOG;
43         retval = make_request(bdev, breq);
44         assert(!retval);
45         kmem_cache_free(breq_kcache, breq);
46         return e2sb;
47 }
48         
49 /* One-time init for all ext2 instances */
50 void ext2_init(void)
51 {
52 }
53
54 /* Helper op to read one ext2 block, 0-indexing the block numbers.  Kfree your
55  * answer.
56  *
57  * TODO: consider taking a buffer_head, or having a generic block_dev function
58  * for this.  Also, eventually we can track a lot of this with the VFS SB. */
59 //int ext2_read_block(struct super_block *sb, unsigned int block_num) (TODO)
60 void *ext2_read_block(struct block_device *bdev, int block_num, int blocksize)
61 {
62         int retval;
63         void *buffer = kmalloc(blocksize, 0);
64         struct block_request *breq = kmem_cache_alloc(breq_kcache, 0);
65         breq->flags = BREQ_READ;
66         breq->buffer = buffer;
67         breq->first_sector = block_num * (blocksize >> SECTOR_SZ_LOG);
68         breq->amount = blocksize >> SECTOR_SZ_LOG;
69         retval = make_request(bdev, breq);
70         assert(!retval);
71         kmem_cache_free(breq_kcache, breq);
72         return buffer;
73 }
74
75 /* This checks an ext2 disc SB for consistency, optionally printing out its
76  * stats.  It also will also read in a copy of the block group descriptor table
77  * from its first location (right after the primary SB copy) */
78 void ext2_check_sb(struct ext2_sb *e2sb, struct block_device *bdev, bool print)
79 {
80         int retval;
81         unsigned int blksize, blks_per_group, num_blk_group, num_blks;
82         struct ext2_block_group *bg;
83         unsigned int inodes_per_grp, blks_per_grp, inode_size;
84         unsigned int sum_blks = 0, sum_inodes = 0;
85
86         assert(le16_to_cpu(e2sb->s_magic) == EXT2_SUPER_MAGIC);
87         num_blks = le32_to_cpu(e2sb->s_free_blocks_cnt);
88         blksize = 1024 << le32_to_cpu(e2sb->s_log_block_size);
89         blks_per_group = le32_to_cpu(e2sb->s_blocks_per_group);
90         num_blk_group = num_blks / blks_per_group + (num_blks % blks_per_group ? 1 : 0);
91         
92         if (print) {
93                 printk("EXT2 info:\n-------------------------\n");
94                 printk("Total Inodes:     %8d\n", le32_to_cpu(e2sb->s_inodes_cnt));
95                 printk("Total Blocks:     %8d\n", le32_to_cpu(e2sb->s_blocks_cnt));
96                 printk("Num R-Blocks:     %8d\n", le32_to_cpu(e2sb->s_rblocks_cnt));
97                 printk("Num Free Blocks:  %8d\n", le32_to_cpu(e2sb->s_free_blocks_cnt));
98                 printk("Num Free Inodes:  %8d\n", le32_to_cpu(e2sb->s_free_inodes_cnt));
99                 printk("First Data Block: %8d\n",
100                        le32_to_cpu(e2sb->s_first_data_block));
101                 printk("Block Size:       %8d\n",
102                        1024 << le32_to_cpu(e2sb->s_log_block_size));
103                 printk("Fragment Size:    %8d\n",
104                        1024 << le32_to_cpu(e2sb->s_log_frag_size));
105                 printk("Blocks per group: %8d\n",
106                        le32_to_cpu(e2sb->s_blocks_per_group));
107                 printk("Inodes per group: %8d\n",
108                        le32_to_cpu(e2sb->s_inodes_per_group));
109                 printk("Block groups:     %8d\n", num_blk_group);
110                 printk("Mount state:      %8d\n", le16_to_cpu(e2sb->s_state));
111                 printk("Rev Level:        %8d\n", le32_to_cpu(e2sb->s_minor_rev_level));
112                 printk("Minor Rev Level:  %8d\n", le16_to_cpu(e2sb->s_minor_rev_level));
113                 printk("Creator OS:       %8d\n", le32_to_cpu(e2sb->s_creator_os));
114                 printk("First Inode:      %8d\n", le32_to_cpu(e2sb->s_first_ino));
115                 printk("Inode size:       %8d\n", le16_to_cpu(e2sb->s_inode_size));
116                 printk("This block group: %8d\n", le16_to_cpu(e2sb->s_block_group_nr));
117                 printk("BG ID of 1st meta:%8d\n", le16_to_cpu(e2sb->s_first_meta_bg));
118                 printk("Volume name:      %s\n", e2sb->s_volume_name);
119                 printk("\nBlock Group Info:\n----------------------\n");
120         }
121         
122         /* which block the BG table is on depends on the blocksize */
123         bg = ext2_read_block(bdev, blksize == 1024 ? 2 : 1, blksize);
124         assert(bg);
125         for (int i = 0; i < num_blk_group; i++) {
126                 sum_blks += le16_to_cpu(bg[i].bg_free_blocks_cnt);
127                 sum_inodes += le16_to_cpu(bg[i].bg_free_inodes_cnt);
128                 if (print) {
129                         printk("*** BG %d at %08p\n", i, bg[i]);
130                         printk("Block bitmap:%8d\n", le32_to_cpu(bg[i].bg_block_bitmap));
131                         printk("Inode bitmap:%8d\n", le32_to_cpu(bg[i].bg_inode_bitmap));
132                         printk("Inode table: %8d\n", le32_to_cpu(bg[i].bg_inode_table));
133                         printk("Free blocks: %8d\n", le16_to_cpu(bg[i].bg_free_blocks_cnt));
134                         printk("Free inodes: %8d\n", le16_to_cpu(bg[i].bg_free_inodes_cnt));
135                         printk("Used Dirs:   %8d\n", le16_to_cpu(bg[i].bg_used_dirs_cnt));
136                 }
137         }
138         
139         /* Sanity Assertions.  A good ext2 will always pass these. */
140         inodes_per_grp = le32_to_cpu(e2sb->s_inodes_per_group);
141         blks_per_group = le32_to_cpu(e2sb->s_blocks_per_group);
142         inode_size = le32_to_cpu(e2sb->s_inode_size);
143         assert(le32_to_cpu(e2sb->s_inodes_cnt) <= inodes_per_grp * num_blk_group);
144         assert(le32_to_cpu(e2sb->s_free_inodes_cnt) == sum_inodes);
145         assert(le32_to_cpu(e2sb->s_blocks_cnt) <= blks_per_group * num_blk_group);
146         assert(le32_to_cpu(e2sb->s_free_blocks_cnt) == sum_blks);
147         if (blksize == 1024)
148                 assert(le32_to_cpu(e2sb->s_first_data_block) == 1);
149         else
150                 assert(le32_to_cpu(e2sb->s_first_data_block) == 0);
151         assert(inode_size <= blksize);
152         assert(inode_size == 1 << LOG2_UP(inode_size));
153         assert(blksize * 8 >= inodes_per_grp);
154         assert(inodes_per_grp % (blksize / inode_size) == 0);
155         
156         /* Free the buffer used during the IO request */
157         kfree(bg);
158         if (print)
159                 printk("Passed EXT2 Checks\n");
160 }
161
162 /* VFS required Misc Functions */
163
164 /* Creates the SB.  Like with Ext2's, we should consider pulling out the
165  * FS-independent stuff, if possible. */
166 struct super_block *ext2_get_sb(struct fs_type *fs, int flags,
167                                char *dev_name, struct vfsmount *vmnt)
168 {
169         struct block_device *bdev;
170         struct ext2_sb *e2sb;
171
172         static bool ran_once = FALSE;
173         if (!ran_once) {
174                 ran_once = TRUE;
175                 ext2_init();
176         }
177         bdev = get_bdev(dev_name);
178         assert(bdev);
179         e2sb = ext2_read_sb(bdev);
180         if (!(le16_to_cpu(e2sb->s_magic) == EXT2_SUPER_MAGIC)) {
181                 warn("EXT2 Not detected when it was expected!");
182                 return 0;
183         }
184         ext2_check_sb(e2sb, bdev, FALSE);
185
186         /* Now we build and init the VFS SB */
187         struct super_block *sb = get_sb();
188         sb->s_dev = 0;                  /* what do we really want here? */
189         sb->s_blocksize = 1024 << le32_to_cpu(e2sb->s_log_block_size);
190         /* max file size for a 1024 blocksize FS.  good enough for now (TODO) */
191         sb->s_maxbytes = 17247252480;
192         sb->s_type = &ext2_fs_type;
193         sb->s_op = &ext2_s_op;
194         sb->s_flags = flags;    /* from the disc too?  which flags are these? */
195         sb->s_magic = EXT2_SUPER_MAGIC;
196         sb->s_mount = vmnt;     /* Kref?  also in KFS */
197         sb->s_syncing = FALSE;
198         kref_get(&bdev->b_kref, 1);
199         sb->s_bdev = bdev;
200         strlcpy(sb->s_name, "EXT2", 32);
201         sb->s_fs_info = e2sb;   /* store the in-memory copy of the disk SB */
202
203         /* Final stages of initializing the sb, mostly FS-independent */
204         init_sb(sb, vmnt, &ext2_d_op, EXT2_ROOT_INO, 0);
205
206         printk("EXT2 superblock loaded\n");
207         kref_put(&bdev->b_kref);
208         return sb;
209 }
210
211 void ext2_kill_sb(struct super_block *sb)
212 {
213         kfree(sb->s_fs_info);   /* this is the e2sb we received from a disk read */
214         panic("Killing an EXT2 SB is not supported!");
215 }
216
217 /* Every FS must have a static FS Type, with which the VFS code can bootstrap */
218 struct fs_type ext2_fs_type = {"EXT2", 0, ext2_get_sb, ext2_kill_sb, {0, 0},
219                                TAILQ_HEAD_INITIALIZER(ext2_fs_type.fs_supers)};
220
221 /* Page Map Operations */
222
223 /* Fills page with its contents from its backing store file.  Note that we do
224  * the zero padding here, instead of higher in the VFS.  Might change in the
225  * future. */
226 int ext2_readpage(struct file *file, struct page *page)
227 {
228         I_AM_HERE;
229         #if 0
230         size_t pg_idx_byte = page->pg_index * PGSIZE;
231         struct ext2_i_info *k_i_info = (struct ext2_i_info*)
232                                       file->f_dentry->d_inode->i_fs_info;
233         uintptr_t begin = (size_t)k_i_info->filestart + pg_idx_byte;
234         /* If we're beyond the initial start point, we just need a zero page.  This
235          * is for a hole or for extending a file (even though it won't be saved).
236          * Otherwise, we want the data from Ext2, being careful to not copy from
237          * beyond the original EOF (and zero padding anything extra). */
238         if (pg_idx_byte >= k_i_info->init_size) {
239                 memset(page2kva(page), 0, PGSIZE);
240         } else {
241                 size_t copy_amt = MIN(PGSIZE, k_i_info->init_size - pg_idx_byte);
242                 memcpy(page2kva(page), (void*)begin, copy_amt);
243                 memset(page2kva(page) + copy_amt, 0, PGSIZE - copy_amt);
244         }
245         /* This is supposed to be done in the IO system when the operation is
246          * complete.  Since we aren't doing a real IO request, and it is already
247          * done, we can do it here. */
248         page->pg_flags |= PG_UPTODATE;
249         unlock_page(page);
250         #endif
251         return 0;
252 }
253
254 /* Super Operations */
255
256 /* creates and initializes a new inode.  generic fields are filled in.  specific
257  * fields are filled in in read_inode() based on what's on the disk for a given
258  * i_no.  i_no and i_fop are set by the caller.  Note that this means this inode
259  * can be for an inode that is already on disk, or it can be used when creating.
260  * The i_fop depends on the type of file (file, directory, symlink, etc). */
261 struct inode *ext2_alloc_inode(struct super_block *sb)
262 {
263 I_AM_HERE;
264         struct inode *inode = kmem_cache_alloc(inode_kcache, 0);
265         memset(inode, 0, sizeof(struct inode));
266         inode->i_op = &ext2_i_op;
267         inode->i_pm.pm_op = &ext2_pm_op;
268         #if 0
269         inode->i_fs_info = kmem_cache_alloc(ext2_i_kcache, 0);
270         TAILQ_INIT(&((struct ext2_i_info*)inode->i_fs_info)->children);
271         ((struct ext2_i_info*)inode->i_fs_info)->filestart = 0;
272         #endif
273         return inode;
274 }
275
276 /* deallocs and cleans up after an inode. */
277 void ext2_dealloc_inode(struct inode *inode)
278 {
279 I_AM_HERE;
280         #if 0
281         /* If we're a symlink, give up our storage for the symname */
282         if (S_ISLNK(inode->i_mode))
283                 kfree(((struct ext2_i_info*)inode->i_fs_info)->filestart);
284         kmem_cache_free(ext2_i_kcache, inode->i_fs_info);
285         #endif
286 }
287
288 /* reads the inode data on disk specified by inode->i_ino into the inode.
289  * basically, it's a "make this inode the one for i_ino (i number)" */
290 void ext2_read_inode(struct inode *inode)
291 {
292 I_AM_HERE;
293         /* need to do something to link this inode/file to the actual "blocks" on
294          * "disk". */
295
296 #if 0
297
298         if (inode->i_ino == 1) {
299                 inode->i_mode = S_IRWXU | S_IRWXG | S_IRWXO;
300                 SET_FTYPE(inode->i_mode, __S_IFDIR);
301                 inode->i_fop = &ext2_f_op_dir;
302                 inode->i_nlink = 1;                             /* assuming only one hardlink */
303                 inode->i_uid = 0;
304                 inode->i_gid = 0;
305                 inode->i_rdev = 0;
306                 inode->i_size = 0;                              /* make sense for Ext2? */
307                 inode->i_atime.tv_sec = 0;
308                 inode->i_atime.tv_nsec = 0;
309                 inode->i_mtime.tv_sec = 0;
310                 inode->i_mtime.tv_nsec = 0;
311                 inode->i_ctime.tv_sec = 0;
312                 inode->i_ctime.tv_nsec = 0;
313                 inode->i_blocks = 0;
314                 inode->i_bdev = 0;                              /* assuming blockdev? */
315                 inode->i_flags = 0;
316                 inode->i_socket = FALSE;
317         } else {
318                 panic("Not implemented");
319         }
320         /* TODO: unused: inode->i_hash add to hash (saves on disc reading) */
321 #endif
322 }
323
324 /* called when an inode in memory is modified (journalling FS's care) */
325 void ext2_dirty_inode(struct inode *inode)
326 {
327 }
328
329 /* write the inode to disk (specifically, to inode inode->i_ino), synchronously
330  * if we're asked to wait */
331 void ext2_write_inode(struct inode *inode, bool wait)
332 {
333 I_AM_HERE;
334 }
335
336 /* called when an inode is decref'd, to do any FS specific work */
337 void ext2_put_inode(struct inode *inode)
338 {
339 I_AM_HERE;
340 }
341
342 /* called when an inode is about to be destroyed.  the generic version ought to
343  * remove every reference to the inode from the VFS, and if the inode isn't in
344  * any directory, calls delete_inode */
345 void ext2_drop_inode(struct inode *inode)
346 { // TODO: should call a generic one instead.  or at least do something...
347         // remove from lists
348 I_AM_HERE;
349 }
350
351 /* delete the inode from disk (all data) and deallocs the in memory inode */
352 void ext2_delete_inode(struct inode *inode)
353 {
354 I_AM_HERE;
355         // would remove from "disk" here
356         ext2_dealloc_inode(inode);
357         /* TODO: give up our i_ino */
358 }
359
360 /* unmount and release the super block */
361 void ext2_put_super(struct super_block *sb)
362 {
363         panic("Shazbot! Ext2 can't be unmounted yet!");
364 }
365
366 /* updates the on-disk SB with the in-memory SB */
367 void ext2_write_super(struct super_block *sb)
368 {
369 I_AM_HERE;
370 }
371
372 /* syncs FS metadata with the disc, synchronously if we're waiting.  this info
373  * also includes anything pointed to by s_fs_info. */
374 int ext2_sync_fs(struct super_block *sb, bool wait)
375 {
376 I_AM_HERE;
377         return 0;
378 }
379
380 /* remount the FS with the new flags */
381 int ext2_remount_fs(struct super_block *sb, int flags, char *data)
382 {
383         warn("Ext2 will not remount.");
384         return -1; // can't remount
385 }
386
387 /* interrupts a mount operation - used by NFS and friends */
388 void ext2_umount_begin(struct super_block *sb)
389 {
390         panic("Cannot abort a Ext2 mount, and why would you?");
391 }
392
393 /* inode_operations */
394
395 /* Little helper, used for initializing new inodes for file-like objects (files,
396  * symlinks, etc).  We pass the dentry, since we need to up it. */
397 static void ext2_init_inode(struct inode *dir, struct dentry *dentry)
398 {
399 #if 0
400         struct inode *inode = dentry->d_inode;
401         inode->i_ino = ext2_get_free_ino();
402 #endif
403 }
404
405 /* Called when creating a new disk inode in dir associated with dentry.  We need
406  * to fill out the i_ino, set the type, and do whatever else we need */
407 int ext2_create(struct inode *dir, struct dentry *dentry, int mode,
408                struct nameidata *nd)
409 {
410 I_AM_HERE;
411         #if 0
412         struct inode *inode = dentry->d_inode;
413         ext2_init_inode(dir, dentry);
414         SET_FTYPE(inode->i_mode, __S_IFREG);
415         inode->i_fop = &ext2_f_op_file;
416         /* fs_info->filestart is set by the caller, or else when first written (for
417          * new files.  it was set to 0 in alloc_inode(). */
418         #endif
419         return 0;
420 }
421
422 /* Searches the directory for the filename in the dentry, filling in the dentry
423  * with the FS specific info of this file.  If it succeeds, it will pass back
424  * the *dentry you should use.  If this fails, it will return 0 and will take
425  * the ref to the dentry for you.  Either way, you shouldn't use the ref you
426  * passed in anymore.  Still, there are issues with refcnting with this.
427  *
428  * Callers, make sure you alloc and fill out the name parts of the dentry, and
429  * an initialized nameidata. TODO: not sure why we need an ND.  Don't use it in
430  * a fs_lookup for now!
431  *
432  * Because of the way Ext2 currently works, if there is ever a dentry, it's
433  * already in memory, along with its inode (all path's pinned).  So we just find
434  * it and return it, freeing the one that came in. */
435 struct dentry *ext2_lookup(struct inode *dir, struct dentry *dentry,
436                           struct nameidata *nd)
437 {
438         I_AM_HERE;
439         return 0;
440 }
441
442 /* Hard link to old_dentry in directory dir with a name specified by new_dentry.
443  * At the very least, set the new_dentry's FS-specific fields. */
444 int ext2_link(struct dentry *old_dentry, struct inode *dir,
445              struct dentry *new_dentry)
446 {
447 I_AM_HERE;
448         assert(new_dentry->d_op = &ext2_d_op);
449         return 0;
450 }
451
452 /* Removes the link from the dentry in the directory */
453 int ext2_unlink(struct inode *dir, struct dentry *dentry)
454 {
455 I_AM_HERE;
456         return 0;
457 }
458
459 /* Creates a new inode for a symlink dir, linking to / containing the name
460  * symname.  dentry is the controlling dentry of the inode. */
461 int ext2_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
462 {
463 I_AM_HERE;
464         #if 0
465         struct inode *inode = dentry->d_inode;
466         SET_FTYPE(inode->i_mode, __S_IFLNK);
467         inode->i_fop = &ext2_f_op_sym;
468         strncpy(string, symname, len);
469         string[len] = '\0';             /* symname should be \0d anyway, but just in case */
470         #endif
471         return 0;
472 }
473
474 /* Called when creating a new inode for a directory associated with dentry in
475  * dir with the given mode.  Note, we might (later) need to track subdirs within
476  * the parent inode, like we do with regular files.  I'd rather not, so we'll
477  * see if we need it. */
478 int ext2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
479 {
480 I_AM_HERE;
481         #if 0
482         struct inode *inode = dentry->d_inode;
483         inode->i_ino = ext2_get_free_ino();
484         SET_FTYPE(inode->i_mode, __S_IFDIR);
485         inode->i_fop = &ext2_f_op_dir;
486         #endif
487         return 0;
488 }
489
490 /* Removes from dir the directory 'dentry.'  Ext2 doesn't store anything in the
491  * inode for which children it has.  It probably should, but since everything is
492  * pinned, it just relies on the dentry connections. */
493 int ext2_rmdir(struct inode *dir, struct dentry *dentry)
494 {
495 I_AM_HERE;
496         return 0;
497 }
498
499 /* Used to make a generic file, based on the type and the major/minor numbers
500  * (in rdev), with the given mode.  As with others, this creates a new disk
501  * inode for the file */
502 int ext2_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
503 {
504 I_AM_HERE;
505         return -1;
506 }
507
508 /* Moves old_dentry from old_dir to new_dentry in new_dir */
509 int ext2_rename(struct inode *old_dir, struct dentry *old_dentry,
510                struct inode *new_dir, struct dentry *new_dentry)
511 {
512 I_AM_HERE;
513         return -1;
514 }
515
516 /* Returns the char* for the symname for the given dentry.  The VFS code that
517  * calls this for real FS's might assume it's already read in, so if the char *
518  * isn't already in memory, we'd need to read it in here.  Regarding the char*
519  * storage, the char* only will last as long as the dentry and inode are in
520  * memory. */
521 char *ext2_readlink(struct dentry *dentry)
522 {
523 I_AM_HERE;
524         struct inode *inode = dentry->d_inode;
525         if (!S_ISLNK(inode->i_mode))
526                 return 0;
527         return 0;
528 }
529
530 /* Modifies the size of the file of inode to whatever its i_size is set to */
531 void ext2_truncate(struct inode *inode)
532 {
533 }
534
535 /* Checks whether the the access mode is allowed for the file belonging to the
536  * inode.  Implies that the permissions are on the file, and not the hardlink */
537 int ext2_permission(struct inode *inode, int mode, struct nameidata *nd)
538 {
539         return -1;
540 }
541
542
543 /* dentry_operations */
544 /* Determines if the dentry is still valid before using it to translate a path.
545  * Network FS's need to deal with this. */
546 int ext2_d_revalidate(struct dentry *dir, struct nameidata *nd)
547 { // default, nothing
548         return -1;
549 }
550
551 /* Produces the hash to lookup this dentry from the dcache */
552 int ext2_d_hash(struct dentry *dentry, struct qstr *name)
553 {
554         return -1;
555 }
556
557 /* Compares name1 and name2.  name1 should be a member of dir. */
558 int ext2_d_compare(struct dentry *dir, struct qstr *name1, struct qstr *name2)
559 { // default, string comp (case sensitive)
560         return -1;
561 }
562
563 /* Called when the last ref is deleted (refcnt == 0) */
564 int ext2_d_delete(struct dentry *dentry)
565 { // default, nothin
566         return -1;
567 }
568
569 /* Called when it's about to be slab-freed */
570 int ext2_d_release(struct dentry *dentry)
571 {
572         return -1;
573 }
574
575 /* Called when the dentry loses it's inode (becomes "negative") */
576 void ext2_d_iput(struct dentry *dentry, struct inode *inode)
577 { // default, call i_put to release the inode object
578 }
579
580
581 /* file_operations */
582
583 /* Updates the file pointer.  Ext2 doesn't let you go past the end of a file
584  * yet, so it won't let you seek past either.  TODO: think about locking. */
585 off_t ext2_llseek(struct file *file, off_t offset, int whence)
586 {
587 I_AM_HERE;
588         off_t temp_off = 0;
589         #if 0
590         switch (whence) {
591                 case SEEK_SET:
592                         temp_off = offset;
593                         break;
594                 case SEEK_CUR:
595                         temp_off = file->f_pos + offset;
596                         break;
597                 case SEEK_END:
598                         temp_off = file->f_dentry->d_inode->i_size + offset;
599                         break;
600                 default:
601                         set_errno(EINVAL);
602                         warn("Unknown 'whence' in llseek()!\n");
603                         return -1;
604         }
605         /* make sure the f_pos isn't outside the limits of the existing file.
606          * techincally, if they go too far, we should return EINVAL */
607         temp_off = MAX(MIN(temp_off, file->f_dentry->d_inode->i_size), 0);
608         file->f_pos = temp_off;
609         #endif
610         return temp_off;
611 }
612
613 /* Fills in the next directory entry (dirent), starting with d_off.  Like with
614  * read and write, there will be issues with userspace and the *dirent buf.
615  * TODO: we don't really do anything with userspace concerns here, in part
616  * because memcpy_to doesn't work well.  When we fix how we want to handle the
617  * userbuffers, we can write this accordingly. (UMEM)  */
618 int ext2_readdir(struct file *dir, struct dirent *dirent)
619 {
620         I_AM_HERE;
621         #if 0
622         int count = 0;
623         /* some of this error handling can be done by the VFS.  The syscall should
624          * handle EBADF, EFAULT, and EINVAL (TODO, memory related). */
625         if (!S_ISDIR(dir_d->d_inode->i_mode)) {
626                 set_errno(ENOTDIR);
627                 return -1;
628         }
629
630
631         if (!found) {
632                 set_errno(ENOENT);
633                 return -1;
634         }
635         if (count - 1 == dirent->d_off)         /* found the last dir in the list */
636                 return 0;
637         #endif
638         return 1;                                                       /* normal success for readdir */
639 }
640
641 /* This is called when a VMR is mapping a particular file.  The FS needs to do
642  * whatever it needs so that faults can be handled by read_page(), and handle all
643  * of the cases of MAP_SHARED, MAP_PRIVATE, whatever.  It also needs to ensure
644  * the file is not being mmaped in a way that conflicts with the manner in which
645  * the file was opened or the file type. */
646 int ext2_mmap(struct file *file, struct vm_region *vmr)
647 {
648         if (S_ISREG(file->f_dentry->d_inode->i_mode))
649                 return 0;
650         return -1;
651 }
652
653 /* Called by the VFS while opening the file, which corresponds to inode,  for
654  * the FS to do whatever it needs. */
655 int ext2_open(struct inode *inode, struct file *file)
656 {
657         I_AM_HERE;
658         return 0;
659 }
660
661 /* Called when a file descriptor is closed. */
662 int ext2_flush(struct file *file)
663 {
664 I_AM_HERE;
665         return -1;
666 }
667
668 /* Called when the file is about to be closed (file obj freed) */
669 int ext2_release(struct inode *inode, struct file *file)
670 {
671         return 0;
672 }
673
674 /* Flushes the file's dirty contents to disc */
675 int ext2_fsync(struct file *file, struct dentry *dentry, int datasync)
676 {
677         return -1;
678 }
679
680 /* Traditionally, sleeps until there is file activity.  We probably won't
681  * support this, or we'll handle it differently. */
682 unsigned int ext2_poll(struct file *file, struct poll_table_struct *poll_table)
683 {
684         return -1;
685 }
686
687 /* Reads count bytes from a file, starting from (and modifiying) offset, and
688  * putting the bytes into buffers described by vector */
689 ssize_t ext2_readv(struct file *file, const struct iovec *vector,
690                   unsigned long count, off_t *offset)
691 {
692         return -1;
693 }
694
695 /* Writes count bytes to a file, starting from (and modifiying) offset, and
696  * taking the bytes from buffers described by vector */
697 ssize_t ext2_writev(struct file *file, const struct iovec *vector,
698                   unsigned long count, off_t *offset)
699 {
700         return -1;
701 }
702
703 /* Write the contents of file to the page.  Will sort the params later */
704 ssize_t ext2_sendpage(struct file *file, struct page *page, int offset,
705                      size_t size, off_t pos, int more)
706 {
707         return -1;
708 }
709
710 /* Checks random FS flags.  Used by NFS. */
711 int ext2_check_flags(int flags)
712 { // default, nothing
713         return -1;
714 }
715
716 /* Redeclaration and initialization of the FS ops structures */
717 struct page_map_operations ext2_pm_op = {
718         ext2_readpage,
719 };
720
721 struct super_operations ext2_s_op = {
722         ext2_alloc_inode,
723         ext2_dealloc_inode,
724         ext2_read_inode,
725         ext2_dirty_inode,
726         ext2_write_inode,
727         ext2_put_inode,
728         ext2_drop_inode,
729         ext2_delete_inode,
730         ext2_put_super,
731         ext2_write_super,
732         ext2_sync_fs,
733         ext2_remount_fs,
734         ext2_umount_begin,
735 };
736
737 struct inode_operations ext2_i_op = {
738         ext2_create,
739         ext2_lookup,
740         ext2_link,
741         ext2_unlink,
742         ext2_symlink,
743         ext2_mkdir,
744         ext2_rmdir,
745         ext2_mknod,
746         ext2_rename,
747         ext2_readlink,
748         ext2_truncate,
749         ext2_permission,
750 };
751
752 struct dentry_operations ext2_d_op = {
753         ext2_d_revalidate,
754         ext2_d_hash,
755         ext2_d_compare,
756         ext2_d_delete,
757         ext2_d_release,
758         ext2_d_iput,
759 };
760
761 struct file_operations ext2_f_op_file = {
762         ext2_llseek,
763         generic_file_read,
764         generic_file_write,
765         ext2_readdir,
766         ext2_mmap,
767         ext2_open,
768         ext2_flush,
769         ext2_release,
770         ext2_fsync,
771         ext2_poll,
772         ext2_readv,
773         ext2_writev,
774         ext2_sendpage,
775         ext2_check_flags,
776 };
777
778 struct file_operations ext2_f_op_dir = {
779         ext2_llseek,
780         generic_dir_read,
781         0,
782         ext2_readdir,
783         ext2_mmap,
784         ext2_open,
785         ext2_flush,
786         ext2_release,
787         ext2_fsync,
788         ext2_poll,
789         ext2_readv,
790         ext2_writev,
791         ext2_sendpage,
792         ext2_check_flags,
793 };
794
795 struct file_operations ext2_f_op_sym = {
796         ext2_llseek,
797         generic_file_read,
798         generic_file_write,
799         ext2_readdir,
800         ext2_mmap,
801         ext2_open,
802         ext2_flush,
803         ext2_release,
804         ext2_fsync,
805         ext2_poll,
806         ext2_readv,
807         ext2_writev,
808         ext2_sendpage,
809         ext2_check_flags,
810 };