/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- xshort
- xint
- main
- wsect
- winode
- rinode
- rsect
- ialloc
- balloc
- iappend
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <assert.h>
7
8 #define stat xv6_stat // avoid clash with host struct stat
9 #include "types.h"
10 #include "fs.h"
11 #include "stat.h"
12 #include "param.h"
13
14 #ifndef static_assert
15 #define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
16 #endif
17
18 #define NINODES 200
19
20 // Disk layout:
21 // [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
22
23 int nbitmap = FSSIZE/(BSIZE*8) + 1;
24 int ninodeblocks = NINODES / IPB + 1;
25 int nlog = LOGSIZE;
26 int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap)
27 int nblocks; // Number of data blocks
28
29 int fsfd;
30 struct superblock sb;
31 char zeroes[BSIZE];
32 uint freeinode = 1;
33 uint freeblock;
34
35
36 void balloc(int);
37 void wsect(uint, void*);
38 void winode(uint, struct dinode*);
39 void rinode(uint inum, struct dinode *ip);
40 void rsect(uint sec, void *buf);
41 uint ialloc(ushort type);
42 void iappend(uint inum, void *p, int n);
43
44 // convert to intel byte order
45 ushort
46 xshort(ushort x)
47 {
48 ushort y;
49 uchar *a = (uchar*)&y;
50 a[0] = x;
51 a[1] = x >> 8;
52 return y;
53 }
54
55 uint
56 xint(uint x)
57 {
58 uint y;
59 uchar *a = (uchar*)&y;
60 a[0] = x;
61 a[1] = x >> 8;
62 a[2] = x >> 16;
63 a[3] = x >> 24;
64 return y;
65 }
66
67 int
68 main(int argc, char *argv[])
69 {
70 int i, cc, fd;
71 uint rootino, inum, off;
72 struct dirent de;
73 char buf[BSIZE];
74 struct dinode din;
75
76
77 static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
78
79 if(argc < 2){
80 fprintf(stderr, "Usage: mkfs fs.img files...\n");
81 exit(1);
82 }
83
84 assert((BSIZE % sizeof(struct dinode)) == 0);
85 assert((BSIZE % sizeof(struct dirent)) == 0);
86
87 fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
88 if(fsfd < 0){
89 perror(argv[1]);
90 exit(1);
91 }
92
93 // 1 fs block = 1 disk sector
94 nmeta = 2 + nlog + ninodeblocks + nbitmap;
95 nblocks = FSSIZE - nmeta;
96
97 sb.size = xint(FSSIZE);
98 sb.nblocks = xint(nblocks);
99 sb.ninodes = xint(NINODES);
100 sb.nlog = xint(nlog);
101 sb.logstart = xint(2);
102 sb.inodestart = xint(2+nlog);
103 sb.bmapstart = xint(2+nlog+ninodeblocks);
104
105 printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
106 nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);
107
108 freeblock = nmeta; // the first free block that we can allocate
109
110 for(i = 0; i < FSSIZE; i++)
111 wsect(i, zeroes);
112
113 memset(buf, 0, sizeof(buf));
114 memmove(buf, &sb, sizeof(sb));
115 wsect(1, buf);
116
117 rootino = ialloc(T_DIR);
118 assert(rootino == ROOTINO);
119
120 bzero(&de, sizeof(de));
121 de.inum = xshort(rootino);
122 strcpy(de.name, ".");
123 iappend(rootino, &de, sizeof(de));
124
125 bzero(&de, sizeof(de));
126 de.inum = xshort(rootino);
127 strcpy(de.name, "..");
128 iappend(rootino, &de, sizeof(de));
129
130 for(i = 2; i < argc; i++){
131 assert(index(argv[i], '/') == 0);
132
133 if((fd = open(argv[i], 0)) < 0){
134 perror(argv[i]);
135 exit(1);
136 }
137
138 // Skip leading _ in name when writing to file system.
139 // The binaries are named _rm, _cat, etc. to keep the
140 // build operating system from trying to execute them
141 // in place of system binaries like rm and cat.
142 if(argv[i][0] == '_')
143 ++argv[i];
144
145 inum = ialloc(T_FILE);
146
147 bzero(&de, sizeof(de));
148 de.inum = xshort(inum);
149 strncpy(de.name, argv[i], DIRSIZ);
150 iappend(rootino, &de, sizeof(de));
151
152 while((cc = read(fd, buf, sizeof(buf))) > 0)
153 iappend(inum, buf, cc);
154
155 close(fd);
156 }
157
158 // fix size of root inode dir
159 rinode(rootino, &din);
160 off = xint(din.size);
161 off = ((off/BSIZE) + 1) * BSIZE;
162 din.size = xint(off);
163 winode(rootino, &din);
164
165 balloc(freeblock);
166
167 exit(0);
168 }
169
170 void
171 wsect(uint sec, void *buf)
172 {
173 if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
174 perror("lseek");
175 exit(1);
176 }
177 if(write(fsfd, buf, BSIZE) != BSIZE){
178 perror("write");
179 exit(1);
180 }
181 }
182
183 void
184 winode(uint inum, struct dinode *ip)
185 {
186 char buf[BSIZE];
187 uint bn;
188 struct dinode *dip;
189
190 bn = IBLOCK(inum, sb);
191 rsect(bn, buf);
192 dip = ((struct dinode*)buf) + (inum % IPB);
193 *dip = *ip;
194 wsect(bn, buf);
195 }
196
197 void
198 rinode(uint inum, struct dinode *ip)
199 {
200 char buf[BSIZE];
201 uint bn;
202 struct dinode *dip;
203
204 bn = IBLOCK(inum, sb);
205 rsect(bn, buf);
206 dip = ((struct dinode*)buf) + (inum % IPB);
207 *ip = *dip;
208 }
209
210 void
211 rsect(uint sec, void *buf)
212 {
213 if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
214 perror("lseek");
215 exit(1);
216 }
217 if(read(fsfd, buf, BSIZE) != BSIZE){
218 perror("read");
219 exit(1);
220 }
221 }
222
223 uint
224 ialloc(ushort type)
225 {
226 uint inum = freeinode++;
227 struct dinode din;
228
229 bzero(&din, sizeof(din));
230 din.type = xshort(type);
231 din.nlink = xshort(1);
232 din.size = xint(0);
233 winode(inum, &din);
234 return inum;
235 }
236
237 void
238 balloc(int used)
239 {
240 uchar buf[BSIZE];
241 int i;
242
243 printf("balloc: first %d blocks have been allocated\n", used);
244 assert(used < BSIZE*8);
245 bzero(buf, BSIZE);
246 for(i = 0; i < used; i++){
247 buf[i/8] = buf[i/8] | (0x1 << (i%8));
248 }
249 printf("balloc: write bitmap block at sector %d\n", sb.bmapstart);
250 wsect(sb.bmapstart, buf);
251 }
252
253 #define min(a, b) ((a) < (b) ? (a) : (b))
254
255 void
256 iappend(uint inum, void *xp, int n)
257 {
258 char *p = (char*)xp;
259 uint fbn, off, n1;
260 struct dinode din;
261 char buf[BSIZE];
262 uint indirect[NINDIRECT];
263 uint x;
264
265 rinode(inum, &din);
266 off = xint(din.size);
267 // printf("append inum %d at off %d sz %d\n", inum, off, n);
268 while(n > 0){
269 fbn = off / BSIZE;
270 assert(fbn < MAXFILE);
271 if(fbn < NDIRECT){
272 if(xint(din.addrs[fbn]) == 0){
273 din.addrs[fbn] = xint(freeblock++);
274 }
275 x = xint(din.addrs[fbn]);
276 } else {
277 if(xint(din.addrs[NDIRECT]) == 0){
278 din.addrs[NDIRECT] = xint(freeblock++);
279 }
280 rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
281 if(indirect[fbn - NDIRECT] == 0){
282 indirect[fbn - NDIRECT] = xint(freeblock++);
283 wsect(xint(din.addrs[NDIRECT]), (char*)indirect);
284 }
285 x = xint(indirect[fbn-NDIRECT]);
286 }
287 n1 = min(n, (fbn + 1) * BSIZE - off);
288 rsect(x, buf);
289 bcopy(p, buf + off - (fbn * BSIZE), n1);
290 wsect(x, buf);
291 n -= n1;
292 off += n1;
293 p += n1;
294 }
295 din.size = xint(off);
296 winode(inum, &din);
297 }