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@89
|
13
|
nuclear@93
|
14 int openfs(struct filesys *fs, dev_t dev);
|
nuclear@94
|
15 static int read_superblock(struct filesys *fs);
|
nuclear@94
|
16 static int write_superblock(struct filesys *fs);
|
nuclear@94
|
17 static int get_inode(struct filesys *fs, int ino, struct inode *inode);
|
nuclear@94
|
18 static int put_inode(struct filesys *fs, struct inode *inode);
|
nuclear@90
|
19
|
nuclear@93
|
20 int openfs(struct filesys *fs, dev_t dev)
|
nuclear@93
|
21 {
|
nuclear@93
|
22 int res;
|
nuclear@93
|
23 struct block_device *bdev;
|
nuclear@94
|
24
|
nuclear@94
|
25 assert(BLKSZ % sizeof(struct inode) == 0);
|
nuclear@89
|
26
|
nuclear@93
|
27 if(!(bdev = blk_open(dev))) {
|
nuclear@93
|
28 return -ENOENT;
|
nuclear@90
|
29 }
|
nuclear@94
|
30 fs->bdev = bdev;
|
nuclear@90
|
31
|
nuclear@93
|
32 /* read the superblock */
|
nuclear@94
|
33 if(!(fs->sb = malloc(BLKSZ))) {
|
nuclear@93
|
34 res = -ENOMEM;
|
nuclear@93
|
35 goto done;
|
nuclear@93
|
36 }
|
nuclear@94
|
37 if((res = read_superblock(fs)) != 0) {
|
nuclear@93
|
38 goto done;
|
nuclear@93
|
39 }
|
nuclear@90
|
40
|
nuclear@93
|
41
|
nuclear@93
|
42 done:
|
nuclear@93
|
43 blk_close(bdev);
|
nuclear@93
|
44 return res;
|
nuclear@90
|
45 }
|
nuclear@88
|
46
|
nuclear@94
|
47 static int read_superblock(struct filesys *fs)
|
nuclear@88
|
48 {
|
nuclear@94
|
49 struct superblock *sb = fs->sb;
|
nuclear@94
|
50
|
nuclear@93
|
51 /* read superblock and verify */
|
nuclear@94
|
52 if(blk_read(fs->bdev, 1, 1, sb) == -1) {
|
nuclear@93
|
53 printf("failed to read superblock\n");
|
nuclear@93
|
54 return -EIO;
|
nuclear@93
|
55 }
|
nuclear@93
|
56 if(sb->magic != MAGIC) {
|
nuclear@93
|
57 printf("invalid magic\n");
|
nuclear@93
|
58 return -EINVAL;
|
nuclear@93
|
59 }
|
nuclear@93
|
60 if(sb->ver > FS_VER) {
|
nuclear@93
|
61 printf("invalid version: %d\n", sb->ver);
|
nuclear@93
|
62 return -EINVAL;
|
nuclear@93
|
63 }
|
nuclear@93
|
64 if(sb->blksize != BLKSZ) {
|
nuclear@93
|
65 printf("invalid block size: %d\n", sb->blksize);
|
nuclear@93
|
66 return -EINVAL;
|
nuclear@93
|
67 }
|
nuclear@89
|
68
|
nuclear@93
|
69 /* allocate and populate in-memory bitmaps */
|
nuclear@93
|
70 if(!(sb->ibm = malloc(sb->ibm_count * sb->blksize))) {
|
nuclear@93
|
71 return -ENOMEM;
|
nuclear@88
|
72 }
|
nuclear@94
|
73 if(blk_read(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) {
|
nuclear@93
|
74 printf("failed to read inode bitmap\n");
|
nuclear@93
|
75 free(sb->ibm);
|
nuclear@93
|
76 return -EIO;
|
nuclear@93
|
77 }
|
nuclear@93
|
78 if(!(sb->bm = malloc(sb->bm_count * sb->blksize))) {
|
nuclear@93
|
79 free(sb->ibm);
|
nuclear@93
|
80 return -ENOMEM;
|
nuclear@93
|
81 }
|
nuclear@94
|
82 if(blk_read(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) {
|
nuclear@93
|
83 printf("failed to read block bitmap\n");
|
nuclear@93
|
84 free(sb->ibm);
|
nuclear@93
|
85 free(sb->bm);
|
nuclear@93
|
86 return -EIO;
|
nuclear@93
|
87 }
|
nuclear@93
|
88
|
nuclear@94
|
89 /* read the root inode */
|
nuclear@94
|
90 if(!(sb->root = malloc(sizeof *sb->root))) {
|
nuclear@94
|
91 free(sb->ibm);
|
nuclear@94
|
92 free(sb->bm);
|
nuclear@94
|
93 return -ENOMEM;
|
nuclear@94
|
94 }
|
nuclear@94
|
95 if(get_inode(fs, sb->root_ino, sb->root) == -1) {
|
nuclear@94
|
96 printf("failed to read root inode\n");
|
nuclear@94
|
97 return -1;
|
nuclear@94
|
98 }
|
nuclear@94
|
99
|
nuclear@93
|
100 return 0;
|
nuclear@88
|
101 }
|
nuclear@94
|
102
|
nuclear@94
|
103 static int write_superblock(struct filesys *fs)
|
nuclear@94
|
104 {
|
nuclear@94
|
105 struct superblock *sb = fs->sb;
|
nuclear@94
|
106
|
nuclear@94
|
107 /* write back any changes in the root inode */
|
nuclear@94
|
108 if(put_inode(fs, sb->root) == -1) {
|
nuclear@94
|
109 return -1;
|
nuclear@94
|
110 }
|
nuclear@94
|
111 /* write back the block bitmap */
|
nuclear@94
|
112 if(blk_write(fs->bdev, sb->bm_start, sb->bm_count, sb->bm) == -1) {
|
nuclear@94
|
113 return -1;
|
nuclear@94
|
114 }
|
nuclear@94
|
115 /* write back the inode bitmap */
|
nuclear@94
|
116 if(blk_write(fs->bdev, sb->ibm_start, sb->ibm_count, sb->ibm) == -1) {
|
nuclear@94
|
117 return -1;
|
nuclear@94
|
118 }
|
nuclear@94
|
119 return 0;
|
nuclear@94
|
120 }
|
nuclear@94
|
121
|
nuclear@94
|
122 /* number of inodes in a block */
|
nuclear@94
|
123 #define BLK_INODES (BLKSZ / sizeof(struct inode))
|
nuclear@94
|
124
|
nuclear@94
|
125 /* copy the requested inode from the disk, into the buffer passed in the last arg */
|
nuclear@94
|
126 static int get_inode(struct filesys *fs, int ino, struct inode *inode)
|
nuclear@94
|
127 {
|
nuclear@94
|
128 struct inode *buf = malloc(BLKSZ);
|
nuclear@94
|
129 assert(buf);
|
nuclear@94
|
130
|
nuclear@94
|
131 if(blk_read(fs->bdev, fs->sb->itbl_start + ino / BLK_INODES, 1, buf) == -1) {
|
nuclear@94
|
132 free(buf);
|
nuclear@94
|
133 return -1;
|
nuclear@94
|
134 }
|
nuclear@94
|
135 memcpy(inode, buf + ino % BLK_INODES, sizeof *inode);
|
nuclear@94
|
136 free(buf);
|
nuclear@94
|
137 return 0;
|
nuclear@94
|
138 }
|
nuclear@94
|
139
|
nuclear@94
|
140 /* write the inode to the disk */
|
nuclear@94
|
141 static int put_inode(struct filesys *fs, struct inode *inode)
|
nuclear@94
|
142 {
|
nuclear@94
|
143 struct inode *buf = malloc(BLKSZ);
|
nuclear@94
|
144 assert(buf);
|
nuclear@94
|
145
|
nuclear@94
|
146 if(blk_read(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) {
|
nuclear@94
|
147 free(buf);
|
nuclear@94
|
148 return -1;
|
nuclear@94
|
149 }
|
nuclear@94
|
150 memcpy(buf + inode->ino % BLK_INODES, inode, sizeof *inode);
|
nuclear@94
|
151
|
nuclear@94
|
152 if(blk_write(fs->bdev, fs->sb->itbl_start + inode->ino / BLK_INODES, 1, buf) == -1) {
|
nuclear@94
|
153 free(buf);
|
nuclear@94
|
154 return -1;
|
nuclear@94
|
155 }
|
nuclear@94
|
156 free(buf);
|
nuclear@94
|
157 return 0;
|
nuclear@94
|
158 }
|