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 }
|