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