kern

annotate src/fs.c @ 95:ec62cbe00b55

whatever
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 11 Dec 2011 21:15:35 +0200
parents b3351d018ac6
children 07fe6a614185
rev   line source
nuclear@90 1 /* This code is used by the kernel AND by userspace filesystem-related tools.
nuclear@90 2 * The kernel-specific parts are conditionally compiled in #ifdef KERNEL blocks
nuclear@90 3 * the rest of the code should be independent.
nuclear@90 4 */
nuclear@88 5 #include <stdio.h>
nuclear@89 6 #include <stdlib.h>
nuclear@94 7 #include <string.h>
nuclear@90 8 #include <errno.h>
nuclear@94 9 #include <assert.h>
nuclear@88 10 #include "fs.h"
nuclear@93 11 #include "bdev.h"
nuclear@90 12
nuclear@95 13 #define BM_IDX(x) ((x) / 32)
nuclear@95 14 #define BM_BIT(x) ((x) & 0x1f)
nuclear@95 15
nuclear@95 16 #define BM_ISFREE(bm, x) (((bm)[BM_IDX(x)] & (1 << BM_BIT(x))) == 0)
nuclear@95 17 #define BM_SET(bm, x) ((bm)[BM_IDX(x)] |= (1 << BM_BIT(x)))
nuclear@95 18 #define BM_CLR(bm, x) ((bm)[BM_IDX(x)] &= ~(1 << BM_BIT(x)))
nuclear@95 19
nuclear@89 20
nuclear@93 21 int openfs(struct filesys *fs, dev_t dev);
nuclear@94 22 static int read_superblock(struct filesys *fs);
nuclear@94 23 static int write_superblock(struct filesys *fs);
nuclear@94 24 static int get_inode(struct filesys *fs, int ino, struct inode *inode);
nuclear@94 25 static int put_inode(struct filesys *fs, struct inode *inode);
nuclear@90 26
nuclear@93 27 int openfs(struct filesys *fs, dev_t dev)
nuclear@93 28 {
nuclear@93 29 int res;
nuclear@93 30 struct block_device *bdev;
nuclear@94 31
nuclear@94 32 assert(BLKSZ % sizeof(struct inode) == 0);
nuclear@89 33
nuclear@93 34 if(!(bdev = blk_open(dev))) {
nuclear@93 35 return -ENOENT;
nuclear@90 36 }
nuclear@94 37 fs->bdev = bdev;
nuclear@90 38
nuclear@93 39 /* read the superblock */
nuclear@94 40 if(!(fs->sb = malloc(BLKSZ))) {
nuclear@93 41 res = -ENOMEM;
nuclear@93 42 goto done;
nuclear@93 43 }
nuclear@94 44 if((res = read_superblock(fs)) != 0) {
nuclear@93 45 goto done;
nuclear@93 46 }
nuclear@90 47
nuclear@93 48
nuclear@93 49 done:
nuclear@93 50 blk_close(bdev);
nuclear@93 51 return res;
nuclear@90 52 }
nuclear@88 53
nuclear@94 54 static int read_superblock(struct filesys *fs)
nuclear@88 55 {
nuclear@94 56 struct superblock *sb = fs->sb;
nuclear@94 57
nuclear@93 58 /* read superblock and verify */
nuclear@94 59 if(blk_read(fs->bdev, 1, 1, sb) == -1) {
nuclear@93 60 printf("failed to read superblock\n");
nuclear@93 61 return -EIO;
nuclear@93 62 }
nuclear@93 63 if(sb->magic != MAGIC) {
nuclear@93 64 printf("invalid magic\n");
nuclear@93 65 return -EINVAL;
nuclear@93 66 }
nuclear@93 67 if(sb->ver > FS_VER) {
nuclear@93 68 printf("invalid version: %d\n", sb->ver);
nuclear@93 69 return -EINVAL;
nuclear@93 70 }
nuclear@93 71 if(sb->blksize != BLKSZ) {
nuclear@93 72 printf("invalid block size: %d\n", sb->blksize);
nuclear@93 73 return -EINVAL;
nuclear@93 74 }
nuclear@89 75
nuclear@93 76 /* allocate and populate in-memory bitmaps */
nuclear@93 77 if(!(sb->ibm = malloc(sb->ibm_count * sb->blksize))) {
nuclear@93 78 return -ENOMEM;
nuclear@88 79 }
nuclear@94 80 if(blk_read(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) {
nuclear@93 81 printf("failed to read inode bitmap\n");
nuclear@93 82 free(sb->ibm);
nuclear@93 83 return -EIO;
nuclear@93 84 }
nuclear@93 85 if(!(sb->bm = malloc(sb->bm_count * sb->blksize))) {
nuclear@93 86 free(sb->ibm);
nuclear@93 87 return -ENOMEM;
nuclear@93 88 }
nuclear@94 89 if(blk_read(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) {
nuclear@93 90 printf("failed to read block bitmap\n");
nuclear@93 91 free(sb->ibm);
nuclear@93 92 free(sb->bm);
nuclear@93 93 return -EIO;
nuclear@93 94 }
nuclear@93 95
nuclear@94 96 /* read the root inode */
nuclear@94 97 if(!(sb->root = malloc(sizeof *sb->root))) {
nuclear@94 98 free(sb->ibm);
nuclear@94 99 free(sb->bm);
nuclear@94 100 return -ENOMEM;
nuclear@94 101 }
nuclear@94 102 if(get_inode(fs, sb->root_ino, sb->root) == -1) {
nuclear@94 103 printf("failed to read root inode\n");
nuclear@94 104 return -1;
nuclear@94 105 }
nuclear@94 106
nuclear@93 107 return 0;
nuclear@88 108 }
nuclear@94 109
nuclear@94 110 static int write_superblock(struct filesys *fs)
nuclear@94 111 {
nuclear@94 112 struct superblock *sb = fs->sb;
nuclear@94 113
nuclear@94 114 /* write back any changes in the root inode */
nuclear@94 115 if(put_inode(fs, sb->root) == -1) {
nuclear@94 116 return -1;
nuclear@94 117 }
nuclear@94 118 /* write back the block bitmap */
nuclear@94 119 if(blk_write(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) {
nuclear@94 120 return -1;
nuclear@94 121 }
nuclear@94 122 /* write back the inode bitmap */
nuclear@94 123 if(blk_write(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) {
nuclear@94 124 return -1;
nuclear@94 125 }
nuclear@94 126 return 0;
nuclear@94 127 }
nuclear@94 128
nuclear@94 129 /* number of inodes in a block */
nuclear@94 130 #define BLK_INODES (BLKSZ / sizeof(struct inode))
nuclear@94 131
nuclear@94 132 /* copy the requested inode from the disk, into the buffer passed in the last arg */
nuclear@94 133 static int get_inode(struct filesys *fs, int ino, struct inode *inode)
nuclear@94 134 {
nuclear@94 135 struct inode *buf = malloc(BLKSZ);
nuclear@94 136 assert(buf);
nuclear@94 137
nuclear@94 138 if(blk_read(fs->bdev, fs->sb->itbl_start + ino / BLK_INODES, 1, buf) == -1) {
nuclear@94 139 free(buf);
nuclear@94 140 return -1;
nuclear@94 141 }
nuclear@94 142 memcpy(inode, buf + ino % BLK_INODES, sizeof *inode);
nuclear@94 143 free(buf);
nuclear@94 144 return 0;
nuclear@94 145 }
nuclear@94 146
nuclear@94 147 /* write the inode to the disk */
nuclear@94 148 static int put_inode(struct filesys *fs, struct inode *inode)
nuclear@94 149 {
nuclear@94 150 struct inode *buf = malloc(BLKSZ);
nuclear@94 151 assert(buf);
nuclear@94 152
nuclear@94 153 if(blk_read(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) {
nuclear@94 154 free(buf);
nuclear@94 155 return -1;
nuclear@94 156 }
nuclear@94 157 memcpy(buf + inode->ino % BLK_INODES, inode, sizeof *inode);
nuclear@94 158
nuclear@94 159 if(blk_write(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) {
nuclear@94 160 free(buf);
nuclear@94 161 return -1;
nuclear@94 162 }
nuclear@94 163 free(buf);
nuclear@94 164 return 0;
nuclear@94 165 }
nuclear@95 166
nuclear@95 167 static int find_free(uint32_t *bm, int sz)
nuclear@95 168 {
nuclear@95 169 int i;
nuclear@95 170 uint32_t ent;
nuclear@95 171
nuclear@95 172 for(i=0; i<=sz/32; i++) {
nuclear@95 173 if(bm[i] != 0xffffffff) {
nuclear@95 174 ent = i * 32;
nuclear@95 175 for(j=0; j<32; j++) {
nuclear@95 176 if(BM_ISFREE(bm, ent)) {
nuclear@95 177 return ent;
nuclear@95 178 }
nuclear@95 179 }
nuclear@95 180
nuclear@95 181 panic("shouldn't happen (in find_free:fs.c)");
nuclear@95 182 }
nuclear@95 183 }
nuclear@95 184
nuclear@95 185 return -1;
nuclear@95 186 }
nuclear@95 187
nuclear@95 188 static int alloc_inode(struct filesys *fs)
nuclear@95 189 {
nuclear@95 190 int ino;
nuclear@95 191
nuclear@95 192 if((ino = find_free(fs->ibm, fs->ibm_count)) == -1) {
nuclear@95 193 return -1;
nuclear@95 194 }
nuclear@95 195 BM_SET(fs->ibm, ino);
nuclear@95 196 return 0;
nuclear@95 197 }