Mounts ext2
[akaros.git] / kern / src / blockdev.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  * Block devices and generic blockdev infrastructure */
6
7 #include <devfs.h>
8 #include <blockdev.h>
9 #include <kmalloc.h>
10 #include <slab.h>
11
12 struct file_operations block_f_op;
13 struct kmem_cache *breq_kcache;
14
15 void block_init(void)
16 {
17         breq_kcache = kmem_cache_create("block_reqs", sizeof(struct block_request),
18                                         __alignof__(struct block_request), 0, 0, 0);
19
20         #ifdef __CONFIG_EXT2FS__
21         /* Now probe for and init the block device for the ext2 ram disk */
22         extern uint8_t _binary_mnt_ext2fs_img_size[];
23         extern uint8_t _binary_mnt_ext2fs_img_start[];
24         /* Build and init the block device */
25         struct block_device *ram_bd = kmalloc(sizeof(struct block_device), 0);
26         memset(ram_bd, 0, sizeof(struct block_device));
27         ram_bd->b_id = 31337;
28         ram_bd->b_sector_size = 512;
29         ram_bd->b_num_sectors = (unsigned int)_binary_mnt_ext2fs_img_size / 512;
30         kref_init(&ram_bd->b_kref, fake_release, 1);
31         ram_bd->b_data = _binary_mnt_ext2fs_img_start;
32         strncpy(ram_bd->b_name, "RAMDISK", BDEV_INLINE_NAME);
33         ram_bd->b_name[BDEV_INLINE_NAME - 1] = '\0';
34         /* Connect it to the file system */
35         struct file *ram_bf = make_device("/dev/ramdisk", S_IRUSR | S_IWUSR,
36                                           __S_IFBLK, &block_f_op);
37         ram_bf->f_dentry->d_inode->i_bdev = ram_bd;     /* this holds the bd kref */
38         kref_put(&ram_bf->f_kref);
39         #endif /* __CONFIG_EXT2FS__ */
40 }
41
42 /* Generic helper, returns a kref'd reference out of principle. */
43 struct block_device *get_bdev(char *path)
44 {
45         struct block_device *bdev;
46         struct file *block_f;
47         block_f = do_file_open(path, O_RDWR, 0);
48         assert(block_f);
49         bdev = block_f->f_dentry->d_inode->i_bdev;
50         kref_get(&bdev->b_kref, 1);
51         kref_put(&block_f->f_kref);
52         return bdev;
53 }
54
55 /* This ultimately will handle the actual request processing, all the way down
56  * to the driver, and will deal with blocking.  For now, we just fulfill the
57  * request right away. */
58 int make_request(struct block_device *bdev, struct block_request *req)
59 {
60         void *src, *dst;
61         /* Sectors are indexed starting with 0, for now. */
62         if (req->first_sector + req->amount > bdev->b_num_sectors)
63                 return -1;
64         if (req->flags & BREQ_READ) {
65                 dst = req->buffer;
66                 src = bdev->b_data + (req->first_sector << SECTOR_SZ_LOG);
67         } else if (req->flags & BREQ_WRITE) {
68                 dst = bdev->b_data + (req->first_sector << SECTOR_SZ_LOG);
69                 src = req->buffer;
70         } else {
71                 panic("Need a request type!\n");
72         }
73         memcpy(dst, src, req->amount << SECTOR_SZ_LOG);
74         return 0;
75 }
76
77 /* Block device file ops: for now, we don't let you do much of anything */
78 struct file_operations block_f_op = {
79         dev_c_llseek,
80         0,
81         0,
82         kfs_readdir,    /* this will fail gracefully */
83         dev_mmap,
84         kfs_open,
85         kfs_flush,
86         kfs_release,
87         0,      /* fsync - makes no sense */
88         kfs_poll,
89         0,      /* readv */
90         0,      /* writev */
91         kfs_sendpage,
92         kfs_check_flags,
93 };