rev |
line source |
nuclear@96
|
1 /* This code is used by the kernel AND by userspace filesystem-related tools. */
|
nuclear@88
|
2 #include <stdio.h>
|
nuclear@89
|
3 #include <stdlib.h>
|
nuclear@94
|
4 #include <string.h>
|
nuclear@90
|
5 #include <errno.h>
|
nuclear@94
|
6 #include <assert.h>
|
nuclear@88
|
7 #include "fs.h"
|
nuclear@93
|
8 #include "bdev.h"
|
nuclear@96
|
9 #include "kdef.h"
|
nuclear@96
|
10
|
nuclear@96
|
11 /* number of inodes in a block */
|
nuclear@96
|
12 #define BLK_INODES (BLKSZ / sizeof(struct inode))
|
nuclear@96
|
13 /* number of directory entries in a block */
|
nuclear@96
|
14 #define BLK_DIRENT (BLKSZ / sizeof(struct dir_entry))
|
nuclear@96
|
15
|
nuclear@96
|
16 #define BLKBITS (BLKSZ * 8)
|
nuclear@90
|
17
|
nuclear@95
|
18 #define BM_IDX(x) ((x) / 32)
|
nuclear@95
|
19 #define BM_BIT(x) ((x) & 0x1f)
|
nuclear@95
|
20
|
nuclear@95
|
21 #define BM_ISFREE(bm, x) (((bm)[BM_IDX(x)] & (1 << BM_BIT(x))) == 0)
|
nuclear@95
|
22 #define BM_SET(bm, x) ((bm)[BM_IDX(x)] |= (1 << BM_BIT(x)))
|
nuclear@95
|
23 #define BM_CLR(bm, x) ((bm)[BM_IDX(x)] &= ~(1 << BM_BIT(x)))
|
nuclear@95
|
24
|
nuclear@89
|
25
|
nuclear@96
|
26 static struct inode *newdir(struct filesys *fs, struct inode *parent);
|
nuclear@96
|
27 static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name);
|
nuclear@94
|
28 static int read_superblock(struct filesys *fs);
|
nuclear@94
|
29 static int write_superblock(struct filesys *fs);
|
nuclear@94
|
30 static int get_inode(struct filesys *fs, int ino, struct inode *inode);
|
nuclear@94
|
31 static int put_inode(struct filesys *fs, struct inode *inode);
|
nuclear@96
|
32 static int find_free(uint32_t *bm, int sz);
|
nuclear@96
|
33 static int alloc_inode(struct filesys *fs);
|
nuclear@96
|
34 static void free_inode(struct filesys *fs, int ino);
|
nuclear@96
|
35 static int alloc_block(struct filesys *fs);
|
nuclear@96
|
36 static void free_block(struct filesys *fs, int ino);
|
nuclear@96
|
37 static int file_block(struct filesys *fs, struct inode *node, int boffs);
|
nuclear@90
|
38
|
nuclear@93
|
39 int openfs(struct filesys *fs, dev_t dev)
|
nuclear@93
|
40 {
|
nuclear@93
|
41 int res;
|
nuclear@93
|
42 struct block_device *bdev;
|
nuclear@94
|
43
|
nuclear@94
|
44 assert(BLKSZ % sizeof(struct inode) == 0);
|
nuclear@89
|
45
|
nuclear@93
|
46 if(!(bdev = blk_open(dev))) {
|
nuclear@93
|
47 return -ENOENT;
|
nuclear@90
|
48 }
|
nuclear@94
|
49 fs->bdev = bdev;
|
nuclear@90
|
50
|
nuclear@93
|
51 /* read the superblock */
|
nuclear@94
|
52 if(!(fs->sb = malloc(BLKSZ))) {
|
nuclear@96
|
53 blk_close(bdev);
|
nuclear@96
|
54 return -ENOMEM;
|
nuclear@93
|
55 }
|
nuclear@94
|
56 if((res = read_superblock(fs)) != 0) {
|
nuclear@96
|
57 blk_close(bdev);
|
nuclear@96
|
58 return res;
|
nuclear@93
|
59 }
|
nuclear@90
|
60
|
nuclear@96
|
61 return 0;
|
nuclear@96
|
62 }
|
nuclear@93
|
63
|
nuclear@96
|
64 int mkfs(struct filesys *fs, dev_t dev)
|
nuclear@96
|
65 {
|
nuclear@96
|
66 struct filesys *fs;
|
nuclear@96
|
67 struct superblock *sb;
|
nuclear@96
|
68 struct block_device *bdev;
|
nuclear@96
|
69 int i, bcount;
|
nuclear@96
|
70
|
nuclear@96
|
71 if(!(bdev = blk_open(dev))) {
|
nuclear@96
|
72 return -1;
|
nuclear@96
|
73 }
|
nuclear@96
|
74 fs->bdev = bdev;
|
nuclear@96
|
75
|
nuclear@96
|
76 if(!(sb = malloc(BLKSZ))) {
|
nuclear@96
|
77 blk_close(bdev);
|
nuclear@96
|
78 return -1;
|
nuclear@96
|
79 }
|
nuclear@96
|
80 fs->sb = sb;
|
nuclear@96
|
81
|
nuclear@96
|
82 /* populate the superblock */
|
nuclear@96
|
83 sb->magic = MAGIC;
|
nuclear@96
|
84 sb->ver = FS_VER;
|
nuclear@96
|
85 sb->blksize = BLKSZ;
|
nuclear@96
|
86
|
nuclear@96
|
87 sb->num_blocks = bdev->size;
|
nuclear@96
|
88 sb->num_inodes = sb->num_blocks / 4;
|
nuclear@96
|
89
|
nuclear@96
|
90 /* inode bitmap just after the superblock */
|
nuclear@96
|
91 sb->ibm_start = 2;
|
nuclear@96
|
92 sb->ibm_count = (sb->num_inodes + BLKBITS - 1) / BLKBITS;
|
nuclear@96
|
93 /* also allocate and initialize in-memory inode bitmap */
|
nuclear@96
|
94 sb->ibm = malloc(sb->ibm_count * BLKSZ);
|
nuclear@96
|
95 assert(sb->ibm);
|
nuclear@96
|
96 memset(sb->ibm, 0, sb->ibm_count * BLKSZ);
|
nuclear@96
|
97
|
nuclear@96
|
98 /* XXX mark inode 0 as used always */
|
nuclear@96
|
99 BM_SET(sb->ibm, 0);
|
nuclear@96
|
100
|
nuclear@96
|
101 /* block bitmap just after the inode bitmap */
|
nuclear@96
|
102 sb->bm_start = sb->ibm_start + sb->ibm_count;
|
nuclear@96
|
103 sb->bm_count = (sb->num_blocks + BLKBITS - 1) / BLKBITS;
|
nuclear@96
|
104 /* also allocate and initialize in-memory block bitmap */
|
nuclear@96
|
105 sb->bm = malloc(sb->bm_count * BLKSZ);
|
nuclear@96
|
106 assert(sb->bm);
|
nuclear@96
|
107 memset(sb->bm, 0, sb->bm_count * BLKSZ);
|
nuclear@96
|
108
|
nuclear@96
|
109 /* inode table, just after the block bitmap */
|
nuclear@96
|
110 sb->itbl_start = sb->bm_start + sb->bm_count;
|
nuclear@96
|
111 sb->itbl_count = (sb->num_inodes * sizeof(struct inode) + BLKSZ - 1) / BLKSZ;
|
nuclear@96
|
112
|
nuclear@96
|
113 /* mark all used blocks as used */
|
nuclear@96
|
114 bcount = sb->itbl_start + sb->itbl_count;
|
nuclear@96
|
115 memset(sb->bm, 0xff, bcount / 8);
|
nuclear@96
|
116 for(i=0; i<bcount % 8; i++) {
|
nuclear@96
|
117 int bit = bcount / 8 + i;
|
nuclear@96
|
118 BM_SET(sb->bm, bit);
|
nuclear@96
|
119 }
|
nuclear@96
|
120
|
nuclear@96
|
121 /* create the root directory */
|
nuclear@96
|
122 sb->root = newdir(fs, 0);
|
nuclear@96
|
123 sb->root_ino = sb->root->ino;
|
nuclear@90
|
124 }
|
nuclear@88
|
125
|
nuclear@96
|
126 static struct inode *newdir(struct filesys *fs, struct inode *parent)
|
nuclear@96
|
127 {
|
nuclear@96
|
128 struct inode *dirnode;
|
nuclear@96
|
129
|
nuclear@96
|
130 /* allocate and initialize inode */
|
nuclear@96
|
131 if(!(dirnode = malloc(sizeof *dirnode))) {
|
nuclear@96
|
132 return 0;
|
nuclear@96
|
133 }
|
nuclear@96
|
134 memset(dirnode, 0, sizeof *dirnode);
|
nuclear@96
|
135
|
nuclear@96
|
136 if((dirnode->ino = alloc_inode(fs)) == -1) {
|
nuclear@96
|
137 printf("failed to allocate inode for a new directory\n");
|
nuclear@96
|
138 free(dirnode);
|
nuclear@96
|
139 return 0;
|
nuclear@96
|
140 }
|
nuclear@96
|
141 dirnode->mode = S_IFDIR;
|
nuclear@96
|
142
|
nuclear@96
|
143 /* add . and .. links */
|
nuclear@96
|
144 addlink(fs, dirnode, dirnode, ".");
|
nuclear@96
|
145 addlink(fs, dirnode, parent ? parent : dirnode, "..");
|
nuclear@96
|
146
|
nuclear@96
|
147 /* and write the inode to disk */
|
nuclear@96
|
148 put_inode(fs, dirnode);
|
nuclear@96
|
149 return dirnode;
|
nuclear@96
|
150 }
|
nuclear@96
|
151
|
nuclear@96
|
152 static int addlink(struct filesys *fs, struct inode *target, struct inode *node, const char *name)
|
nuclear@96
|
153 {
|
nuclear@96
|
154 struct dir_entry ent, *data;
|
nuclear@96
|
155 int boffs, bidx, len;
|
nuclear@96
|
156
|
nuclear@96
|
157 if(!(target->mode & S_IFDIR)) {
|
nuclear@96
|
158 return -ENOTDIR;
|
nuclear@96
|
159 }
|
nuclear@96
|
160 if(node->mode & S_IFDIR) {
|
nuclear@96
|
161 return -EPERM;
|
nuclear@96
|
162 }
|
nuclear@96
|
163 /* TODO check that the link does not already exist (EEXIST) */
|
nuclear@96
|
164
|
nuclear@96
|
165 if((len = strlen(name)) > MAX_FNAME) {
|
nuclear@96
|
166 return -ENAMETOOLONG;
|
nuclear@96
|
167 }
|
nuclear@96
|
168 ent->ino = node->ino;
|
nuclear@96
|
169 memcpy(newent->name, name, len + 1);
|
nuclear@96
|
170
|
nuclear@96
|
171 /* find a place to put it */
|
nuclear@96
|
172 if(!(data = malloc(BLKSZ))) {
|
nuclear@96
|
173 return -ENOMEM;
|
nuclear@96
|
174 }
|
nuclear@96
|
175
|
nuclear@96
|
176 boffs = 0;
|
nuclear@96
|
177 while((bidx = file_block(fs, target, boffs)) > 0) {
|
nuclear@96
|
178 /* read the block, and search for an empty entry */
|
nuclear@96
|
179 blk_read(fs->bdev, bidx, 1, data);
|
nuclear@96
|
180
|
nuclear@96
|
181 /* for all directory entries in this block... */
|
nuclear@96
|
182 for(i=0; i<BLK_DIRENT; i++) {
|
nuclear@96
|
183 if(data[i].ino == 0) {
|
nuclear@96
|
184 /* found empty */
|
nuclear@96
|
185 memcpy(data + i, &ent, sizeof ent);
|
nuclear@96
|
186 goto success;
|
nuclear@96
|
187 }
|
nuclear@96
|
188 }
|
nuclear@96
|
189 boffs++;
|
nuclear@96
|
190 }
|
nuclear@96
|
191
|
nuclear@96
|
192 /* didn't find any free entries amongst our blocks, allocate a new one */
|
nuclear@96
|
193 if(!(bidx = alloc_file_block(fs, target, boffs))) {
|
nuclear@96
|
194 free(data);
|
nuclear@96
|
195 return -ENOSPC;
|
nuclear@96
|
196 }
|
nuclear@96
|
197 /* zero-fill the new block and add the first entry */
|
nuclear@96
|
198 memset(data, 0, BLKSZ);
|
nuclear@96
|
199 *data = ent;
|
nuclear@96
|
200
|
nuclear@96
|
201 success:
|
nuclear@96
|
202 /* write to disk */
|
nuclear@96
|
203 blk_write(fs->bdev, bidx, 1, data);
|
nuclear@96
|
204 node->nlink++; /* increase reference count */
|
nuclear@96
|
205
|
nuclear@96
|
206 free(data);
|
nuclear@96
|
207 return 0;
|
nuclear@96
|
208 }
|
nuclear@96
|
209
|
nuclear@96
|
210
|
nuclear@94
|
211 static int read_superblock(struct filesys *fs)
|
nuclear@88
|
212 {
|
nuclear@94
|
213 struct superblock *sb = fs->sb;
|
nuclear@94
|
214
|
nuclear@93
|
215 /* read superblock and verify */
|
nuclear@94
|
216 if(blk_read(fs->bdev, 1, 1, sb) == -1) {
|
nuclear@93
|
217 printf("failed to read superblock\n");
|
nuclear@93
|
218 return -EIO;
|
nuclear@93
|
219 }
|
nuclear@93
|
220 if(sb->magic != MAGIC) {
|
nuclear@93
|
221 printf("invalid magic\n");
|
nuclear@93
|
222 return -EINVAL;
|
nuclear@93
|
223 }
|
nuclear@93
|
224 if(sb->ver > FS_VER) {
|
nuclear@93
|
225 printf("invalid version: %d\n", sb->ver);
|
nuclear@93
|
226 return -EINVAL;
|
nuclear@93
|
227 }
|
nuclear@93
|
228 if(sb->blksize != BLKSZ) {
|
nuclear@93
|
229 printf("invalid block size: %d\n", sb->blksize);
|
nuclear@93
|
230 return -EINVAL;
|
nuclear@93
|
231 }
|
nuclear@89
|
232
|
nuclear@93
|
233 /* allocate and populate in-memory bitmaps */
|
nuclear@93
|
234 if(!(sb->ibm = malloc(sb->ibm_count * sb->blksize))) {
|
nuclear@93
|
235 return -ENOMEM;
|
nuclear@88
|
236 }
|
nuclear@94
|
237 if(blk_read(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) {
|
nuclear@93
|
238 printf("failed to read inode bitmap\n");
|
nuclear@93
|
239 free(sb->ibm);
|
nuclear@93
|
240 return -EIO;
|
nuclear@93
|
241 }
|
nuclear@93
|
242 if(!(sb->bm = malloc(sb->bm_count * sb->blksize))) {
|
nuclear@93
|
243 free(sb->ibm);
|
nuclear@93
|
244 return -ENOMEM;
|
nuclear@93
|
245 }
|
nuclear@94
|
246 if(blk_read(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) {
|
nuclear@93
|
247 printf("failed to read block bitmap\n");
|
nuclear@93
|
248 free(sb->ibm);
|
nuclear@93
|
249 free(sb->bm);
|
nuclear@93
|
250 return -EIO;
|
nuclear@93
|
251 }
|
nuclear@93
|
252
|
nuclear@94
|
253 /* read the root inode */
|
nuclear@94
|
254 if(!(sb->root = malloc(sizeof *sb->root))) {
|
nuclear@94
|
255 free(sb->ibm);
|
nuclear@94
|
256 free(sb->bm);
|
nuclear@94
|
257 return -ENOMEM;
|
nuclear@94
|
258 }
|
nuclear@94
|
259 if(get_inode(fs, sb->root_ino, sb->root) == -1) {
|
nuclear@94
|
260 printf("failed to read root inode\n");
|
nuclear@94
|
261 return -1;
|
nuclear@94
|
262 }
|
nuclear@94
|
263
|
nuclear@93
|
264 return 0;
|
nuclear@88
|
265 }
|
nuclear@94
|
266
|
nuclear@94
|
267 static int write_superblock(struct filesys *fs)
|
nuclear@94
|
268 {
|
nuclear@94
|
269 struct superblock *sb = fs->sb;
|
nuclear@94
|
270
|
nuclear@94
|
271 /* write back any changes in the root inode */
|
nuclear@94
|
272 if(put_inode(fs, sb->root) == -1) {
|
nuclear@94
|
273 return -1;
|
nuclear@94
|
274 }
|
nuclear@94
|
275 /* write back the block bitmap */
|
nuclear@94
|
276 if(blk_write(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) {
|
nuclear@94
|
277 return -1;
|
nuclear@94
|
278 }
|
nuclear@94
|
279 /* write back the inode bitmap */
|
nuclear@94
|
280 if(blk_write(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) {
|
nuclear@94
|
281 return -1;
|
nuclear@94
|
282 }
|
nuclear@96
|
283 /* write the superblock itself */
|
nuclear@96
|
284 if(blk_write(fs->bdev, 1, 1, sb) == -1) {
|
nuclear@96
|
285 return -1;
|
nuclear@96
|
286 }
|
nuclear@94
|
287 return 0;
|
nuclear@94
|
288 }
|
nuclear@94
|
289
|
nuclear@94
|
290 /* copy the requested inode from the disk, into the buffer passed in the last arg */
|
nuclear@94
|
291 static int get_inode(struct filesys *fs, int ino, struct inode *inode)
|
nuclear@94
|
292 {
|
nuclear@94
|
293 struct inode *buf = malloc(BLKSZ);
|
nuclear@94
|
294 assert(buf);
|
nuclear@94
|
295
|
nuclear@94
|
296 if(blk_read(fs->bdev, fs->sb->itbl_start + ino / BLK_INODES, 1, buf) == -1) {
|
nuclear@94
|
297 free(buf);
|
nuclear@94
|
298 return -1;
|
nuclear@94
|
299 }
|
nuclear@94
|
300 memcpy(inode, buf + ino % BLK_INODES, sizeof *inode);
|
nuclear@94
|
301 free(buf);
|
nuclear@94
|
302 return 0;
|
nuclear@94
|
303 }
|
nuclear@94
|
304
|
nuclear@94
|
305 /* write the inode to the disk */
|
nuclear@94
|
306 static int put_inode(struct filesys *fs, struct inode *inode)
|
nuclear@94
|
307 {
|
nuclear@94
|
308 struct inode *buf = malloc(BLKSZ);
|
nuclear@94
|
309 assert(buf);
|
nuclear@94
|
310
|
nuclear@94
|
311 if(blk_read(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) {
|
nuclear@94
|
312 free(buf);
|
nuclear@94
|
313 return -1;
|
nuclear@94
|
314 }
|
nuclear@94
|
315 memcpy(buf + inode->ino % BLK_INODES, inode, sizeof *inode);
|
nuclear@94
|
316
|
nuclear@94
|
317 if(blk_write(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) {
|
nuclear@94
|
318 free(buf);
|
nuclear@94
|
319 return -1;
|
nuclear@94
|
320 }
|
nuclear@94
|
321 free(buf);
|
nuclear@94
|
322 return 0;
|
nuclear@94
|
323 }
|
nuclear@95
|
324
|
nuclear@96
|
325 /* find a free element in the bitmap and return its number */
|
nuclear@96
|
326 static int find_free(uint32_t *bm, int nbits)
|
nuclear@95
|
327 {
|
nuclear@96
|
328 int i, j, nwords = nbits / 32;
|
nuclear@96
|
329 uint32_t ent = 0;
|
nuclear@95
|
330
|
nuclear@96
|
331 for(i=0; i<=nwords; i++) {
|
nuclear@95
|
332 if(bm[i] != 0xffffffff) {
|
nuclear@95
|
333 for(j=0; j<32; j++) {
|
nuclear@95
|
334 if(BM_ISFREE(bm, ent)) {
|
nuclear@95
|
335 return ent;
|
nuclear@95
|
336 }
|
nuclear@96
|
337 ent++;
|
nuclear@95
|
338 }
|
nuclear@95
|
339
|
nuclear@95
|
340 panic("shouldn't happen (in find_free:fs.c)");
|
nuclear@96
|
341 } else {
|
nuclear@96
|
342 ent += 32;
|
nuclear@95
|
343 }
|
nuclear@95
|
344 }
|
nuclear@95
|
345
|
nuclear@95
|
346 return -1;
|
nuclear@95
|
347 }
|
nuclear@95
|
348
|
nuclear@95
|
349 static int alloc_inode(struct filesys *fs)
|
nuclear@95
|
350 {
|
nuclear@95
|
351 int ino;
|
nuclear@95
|
352
|
nuclear@96
|
353 if((ino = find_free(fs->sb->ibm, fs->sb->num_inodes)) == -1) {
|
nuclear@95
|
354 return -1;
|
nuclear@95
|
355 }
|
nuclear@96
|
356 BM_SET(fs->sb->ibm, ino);
|
nuclear@95
|
357 return 0;
|
nuclear@95
|
358 }
|
nuclear@96
|
359
|
nuclear@96
|
360 static void free_inode(struct filesys *fs, int ino)
|
nuclear@96
|
361 {
|
nuclear@96
|
362 BM_CLR(fs->sb->ibm, ino);
|
nuclear@96
|
363 }
|
nuclear@96
|
364
|
nuclear@96
|
365 static int alloc_block(struct filesys *fs)
|
nuclear@96
|
366 {
|
nuclear@96
|
367 int ino;
|
nuclear@96
|
368
|
nuclear@96
|
369 if((ino = find_free(fs->sb->bm, fs->sb->num_blocks)) == -1) {
|
nuclear@96
|
370 return -1;
|
nuclear@96
|
371 }
|
nuclear@96
|
372 BM_SET(fs->sb->bm, ino);
|
nuclear@96
|
373 return 0;
|
nuclear@96
|
374 }
|
nuclear@96
|
375
|
nuclear@96
|
376 static void free_block(struct filesys *fs, int ino)
|
nuclear@96
|
377 {
|
nuclear@96
|
378 BM_CLR(fs->sb->bm, ino);
|
nuclear@96
|
379 }
|
nuclear@96
|
380
|
nuclear@96
|
381 #define BLK_BLKID (BLKSZ / sizeof(blkid))
|
nuclear@96
|
382 #define MAX_IND (NDIRBLK + BLK_BLKID)
|
nuclear@96
|
383 #define MAX_DIND (MAX_IND + BLK_BLKID * BLK_BLKID)
|
nuclear@96
|
384
|
nuclear@96
|
385 static int file_block(struct filesys *fs, struct inode *node, int boffs)
|
nuclear@96
|
386 {
|
nuclear@96
|
387 int res, idx;
|
nuclear@96
|
388 blkid *barr;
|
nuclear@96
|
389
|
nuclear@96
|
390 /* is it a direct block ? */
|
nuclear@96
|
391 if(boffs < NDIRBLK) {
|
nuclear@96
|
392 return node->blk[boffs];
|
nuclear@96
|
393 }
|
nuclear@96
|
394
|
nuclear@96
|
395 barr = malloc(BLKSZ);
|
nuclear@96
|
396 assert(barr);
|
nuclear@96
|
397
|
nuclear@96
|
398 /* is it an indirect block ? */
|
nuclear@96
|
399 if(boffs < MAX_IND) {
|
nuclear@96
|
400 if(!node->ind) {
|
nuclear@96
|
401 res = 0;
|
nuclear@96
|
402 goto end;
|
nuclear@96
|
403 }
|
nuclear@96
|
404 blk_read(fs->bdev, node->ind, 1, barr);
|
nuclear@96
|
405 res = barr[boffs - NDIRBLK];
|
nuclear@96
|
406 goto end;
|
nuclear@96
|
407 }
|
nuclear@96
|
408
|
nuclear@96
|
409 /* is it a double-indirect block ? */
|
nuclear@96
|
410 if(boffs < MAX_DIND) {
|
nuclear@96
|
411 /* first read the dind block and find the index of the ind block */
|
nuclear@96
|
412 if(!node->dind) {
|
nuclear@96
|
413 res = 0;
|
nuclear@96
|
414 goto end;
|
nuclear@96
|
415 }
|
nuclear@96
|
416 blk_read(fd->bdev, node->dind, 1, barr);
|
nuclear@96
|
417 idx = (boffs - MAX_IND) / BLK_BLKID;
|
nuclear@96
|
418
|
nuclear@96
|
419 /* then read the ind block and find the index of the block */
|
nuclear@96
|
420 if(!barr[idx]) {
|
nuclear@96
|
421 res = 0;
|
nuclear@96
|
422 goto end;
|
nuclear@96
|
423 }
|
nuclear@96
|
424 blk_read(fd->bdev, barr[idx], 1, barr);
|
nuclear@96
|
425 res = barr[(boffs - MAX_IND) % BLK_BLKID];
|
nuclear@96
|
426 }
|
nuclear@96
|
427
|
nuclear@96
|
428 end:
|
nuclear@96
|
429 free(barr);
|
nuclear@96
|
430 return res;
|
nuclear@96
|
431 }
|