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