xref: /xv6-public/mkfs.c (revision 7894fcd2)
111a9947fSrtm #include <stdio.h>
211a9947fSrtm #include <unistd.h>
311a9947fSrtm #include <stdlib.h>
411a9947fSrtm #include <string.h>
511a9947fSrtm #include <fcntl.h>
6c59361f1Srtm #include <assert.h>
724067960SRuss Cox 
824067960SRuss Cox #define stat xv6_stat  // avoid clash with host struct stat
911a9947fSrtm #include "types.h"
1011a9947fSrtm #include "fs.h"
110c7f4838Srsc #include "stat.h"
1213a96baeSFrans Kaashoek #include "param.h"
1311a9947fSrtm 
14*4f2d3814SAyan Shafqat #ifndef static_assert
15c440b5cdSFrans Kaashoek #define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
16*4f2d3814SAyan Shafqat #endif
17cf57e525SFrans Kaashoek 
18c24ac5d7SFrans Kaashoek #define NINODES 200
19c24ac5d7SFrans Kaashoek 
20c24ac5d7SFrans Kaashoek // Disk layout:
218320d61bSFrans Kaashoek // [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
22c24ac5d7SFrans Kaashoek 
23895af77fSFrans Kaashoek int nbitmap = FSSIZE/(BSIZE*8) + 1;
24c24ac5d7SFrans Kaashoek int ninodeblocks = NINODES / IPB + 1;
2513a96baeSFrans Kaashoek int nlog = LOGSIZE;
268320d61bSFrans Kaashoek int nmeta;    // Number of meta blocks (boot, sb, nlog, inode, bitmap)
27c24ac5d7SFrans Kaashoek int nblocks;  // Number of data blocks
2811a9947fSrtm 
29c59361f1Srtm int fsfd;
3011a9947fSrtm struct superblock sb;
31c24ac5d7SFrans Kaashoek char zeroes[BSIZE];
32c59361f1Srtm uint freeinode = 1;
33c24ac5d7SFrans Kaashoek uint freeblock;
34c24ac5d7SFrans Kaashoek 
3511a9947fSrtm 
3624111398Skaashoek void balloc(int);
3711a9947fSrtm void wsect(uint, void*);
3811a9947fSrtm void winode(uint, struct dinode*);
39bdb66433Skaashoek void rinode(uint inum, struct dinode *ip);
4011a9947fSrtm void rsect(uint sec, void *buf);
41c59361f1Srtm uint ialloc(ushort type);
42c59361f1Srtm void iappend(uint inum, void *p, int n);
4311a9947fSrtm 
4411a9947fSrtm // convert to intel byte order
4511a9947fSrtm ushort
xshort(ushort x)4611a9947fSrtm xshort(ushort x)
4711a9947fSrtm {
4811a9947fSrtm   ushort y;
499d3fb671Srtm   uchar *a = (uchar*)&y;
5011a9947fSrtm   a[0] = x;
5111a9947fSrtm   a[1] = x >> 8;
5211a9947fSrtm   return y;
5311a9947fSrtm }
5411a9947fSrtm 
5511a9947fSrtm uint
xint(uint x)5611a9947fSrtm xint(uint x)
5711a9947fSrtm {
5811a9947fSrtm   uint y;
599d3fb671Srtm   uchar *a = (uchar*)&y;
6011a9947fSrtm   a[0] = x;
6111a9947fSrtm   a[1] = x >> 8;
6211a9947fSrtm   a[2] = x >> 16;
6311a9947fSrtm   a[3] = x >> 24;
6411a9947fSrtm   return y;
6511a9947fSrtm }
6611a9947fSrtm 
6794d7e259Srsc int
main(int argc,char * argv[])6811a9947fSrtm main(int argc, char *argv[])
6911a9947fSrtm {
70c59361f1Srtm   int i, cc, fd;
71558ab49fSrsc   uint rootino, inum, off;
72c59361f1Srtm   struct dirent de;
73c24ac5d7SFrans Kaashoek   char buf[BSIZE];
74bdb66433Skaashoek   struct dinode din;
7511a9947fSrtm 
76c440b5cdSFrans Kaashoek 
77c440b5cdSFrans Kaashoek   static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
78c440b5cdSFrans Kaashoek 
79c59361f1Srtm   if(argc < 2){
80c59361f1Srtm     fprintf(stderr, "Usage: mkfs fs.img files...\n");
8111a9947fSrtm     exit(1);
8211a9947fSrtm   }
8311a9947fSrtm 
84c24ac5d7SFrans Kaashoek   assert((BSIZE % sizeof(struct dinode)) == 0);
85c24ac5d7SFrans Kaashoek   assert((BSIZE % sizeof(struct dirent)) == 0);
8611a9947fSrtm 
87c59361f1Srtm   fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
88c59361f1Srtm   if(fsfd < 0){
8911a9947fSrtm     perror(argv[1]);
9011a9947fSrtm     exit(1);
9111a9947fSrtm   }
9211a9947fSrtm 
938320d61bSFrans Kaashoek   // 1 fs block = 1 disk sector
948320d61bSFrans Kaashoek   nmeta = 2 + nlog + ninodeblocks + nbitmap;
958320d61bSFrans Kaashoek   nblocks = FSSIZE - nmeta;
96c24ac5d7SFrans Kaashoek 
97895af77fSFrans Kaashoek   sb.size = xint(FSSIZE);
988320d61bSFrans Kaashoek   sb.nblocks = xint(nblocks);
99c24ac5d7SFrans Kaashoek   sb.ninodes = xint(NINODES);
10013a96baeSFrans Kaashoek   sb.nlog = xint(nlog);
1018320d61bSFrans Kaashoek   sb.logstart = xint(2);
1028320d61bSFrans Kaashoek   sb.inodestart = xint(2+nlog);
1038320d61bSFrans Kaashoek   sb.bmapstart = xint(2+nlog+ninodeblocks);
10411a9947fSrtm 
1058320d61bSFrans Kaashoek   printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
1068320d61bSFrans Kaashoek          nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);
10711a9947fSrtm 
108c24ac5d7SFrans Kaashoek   freeblock = nmeta;     // the first free block that we can allocate
10924111398Skaashoek 
110895af77fSFrans Kaashoek   for(i = 0; i < FSSIZE; i++)
11111a9947fSrtm     wsect(i, zeroes);
11211a9947fSrtm 
113e92fd614SRuss Cox   memset(buf, 0, sizeof(buf));
114e92fd614SRuss Cox   memmove(buf, &sb, sizeof(sb));
115e92fd614SRuss Cox   wsect(1, buf);
11611a9947fSrtm 
117c59361f1Srtm   rootino = ialloc(T_DIR);
1182ce40d70Srtm   assert(rootino == ROOTINO);
11911a9947fSrtm 
120c59361f1Srtm   bzero(&de, sizeof(de));
121c59361f1Srtm   de.inum = xshort(rootino);
122c59361f1Srtm   strcpy(de.name, ".");
123c59361f1Srtm   iappend(rootino, &de, sizeof(de));
124c59361f1Srtm 
125c59361f1Srtm   bzero(&de, sizeof(de));
126c59361f1Srtm   de.inum = xshort(rootino);
127c59361f1Srtm   strcpy(de.name, "..");
128c59361f1Srtm   iappend(rootino, &de, sizeof(de));
129c59361f1Srtm 
130c59361f1Srtm   for(i = 2; i < argc; i++){
131c59361f1Srtm     assert(index(argv[i], '/') == 0);
132ea2909b6Skaashoek 
133c59361f1Srtm     if((fd = open(argv[i], 0)) < 0){
134c59361f1Srtm       perror(argv[i]);
135c59361f1Srtm       exit(1);
136c59361f1Srtm     }
137c59361f1Srtm 
13894d7e259Srsc     // Skip leading _ in name when writing to file system.
13994d7e259Srsc     // The binaries are named _rm, _cat, etc. to keep the
14094d7e259Srsc     // build operating system from trying to execute them
14194d7e259Srsc     // in place of system binaries like rm and cat.
14294d7e259Srsc     if(argv[i][0] == '_')
14394d7e259Srsc       ++argv[i];
14494d7e259Srsc 
145c59361f1Srtm     inum = ialloc(T_FILE);
146c59361f1Srtm 
147c59361f1Srtm     bzero(&de, sizeof(de));
148c59361f1Srtm     de.inum = xshort(inum);
149c59361f1Srtm     strncpy(de.name, argv[i], DIRSIZ);
150c59361f1Srtm     iappend(rootino, &de, sizeof(de));
151c59361f1Srtm 
152c59361f1Srtm     while((cc = read(fd, buf, sizeof(buf))) > 0)
153c59361f1Srtm       iappend(inum, buf, cc);
154c59361f1Srtm 
155c59361f1Srtm     close(fd);
156c59361f1Srtm   }
15711a9947fSrtm 
158bdb66433Skaashoek   // fix size of root inode dir
159bdb66433Skaashoek   rinode(rootino, &din);
160bdb66433Skaashoek   off = xint(din.size);
161bdb66433Skaashoek   off = ((off/BSIZE) + 1) * BSIZE;
162bdb66433Skaashoek   din.size = xint(off);
163bdb66433Skaashoek   winode(rootino, &din);
164bdb66433Skaashoek 
165c24ac5d7SFrans Kaashoek   balloc(freeblock);
16624111398Skaashoek 
16711a9947fSrtm   exit(0);
16811a9947fSrtm }
16911a9947fSrtm 
17011a9947fSrtm void
wsect(uint sec,void * buf)17111a9947fSrtm wsect(uint sec, void *buf)
17211a9947fSrtm {
173c24ac5d7SFrans Kaashoek   if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
17411a9947fSrtm     perror("lseek");
17511a9947fSrtm     exit(1);
17611a9947fSrtm   }
177c24ac5d7SFrans Kaashoek   if(write(fsfd, buf, BSIZE) != BSIZE){
17811a9947fSrtm     perror("write");
17911a9947fSrtm     exit(1);
18011a9947fSrtm   }
18111a9947fSrtm }
18211a9947fSrtm 
18311a9947fSrtm void
winode(uint inum,struct dinode * ip)18411a9947fSrtm winode(uint inum, struct dinode *ip)
18511a9947fSrtm {
186c24ac5d7SFrans Kaashoek   char buf[BSIZE];
18711a9947fSrtm   uint bn;
18811a9947fSrtm   struct dinode *dip;
18911a9947fSrtm 
1908320d61bSFrans Kaashoek   bn = IBLOCK(inum, sb);
19111a9947fSrtm   rsect(bn, buf);
19211a9947fSrtm   dip = ((struct dinode*)buf) + (inum % IPB);
19311a9947fSrtm   *dip = *ip;
19411a9947fSrtm   wsect(bn, buf);
195c59361f1Srtm }
196c59361f1Srtm 
197c59361f1Srtm void
rinode(uint inum,struct dinode * ip)198c59361f1Srtm rinode(uint inum, struct dinode *ip)
199c59361f1Srtm {
200c24ac5d7SFrans Kaashoek   char buf[BSIZE];
201c59361f1Srtm   uint bn;
202c59361f1Srtm   struct dinode *dip;
203c59361f1Srtm 
2048320d61bSFrans Kaashoek   bn = IBLOCK(inum, sb);
205c59361f1Srtm   rsect(bn, buf);
206c59361f1Srtm   dip = ((struct dinode*)buf) + (inum % IPB);
207c59361f1Srtm   *ip = *dip;
20811a9947fSrtm }
20911a9947fSrtm 
21011a9947fSrtm void
rsect(uint sec,void * buf)21111a9947fSrtm rsect(uint sec, void *buf)
21211a9947fSrtm {
213c24ac5d7SFrans Kaashoek   if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
21411a9947fSrtm     perror("lseek");
21511a9947fSrtm     exit(1);
21611a9947fSrtm   }
217c24ac5d7SFrans Kaashoek   if(read(fsfd, buf, BSIZE) != BSIZE){
21811a9947fSrtm     perror("read");
21911a9947fSrtm     exit(1);
22011a9947fSrtm   }
22111a9947fSrtm }
222c59361f1Srtm 
223c59361f1Srtm uint
ialloc(ushort type)224c59361f1Srtm ialloc(ushort type)
225c59361f1Srtm {
226c59361f1Srtm   uint inum = freeinode++;
227c59361f1Srtm   struct dinode din;
228c59361f1Srtm 
229c59361f1Srtm   bzero(&din, sizeof(din));
230c59361f1Srtm   din.type = xshort(type);
231c59361f1Srtm   din.nlink = xshort(1);
232c59361f1Srtm   din.size = xint(0);
233c59361f1Srtm   winode(inum, &din);
234c59361f1Srtm   return inum;
235c59361f1Srtm }
236c59361f1Srtm 
23724111398Skaashoek void
balloc(int used)23824111398Skaashoek balloc(int used)
23924111398Skaashoek {
240c24ac5d7SFrans Kaashoek   uchar buf[BSIZE];
24124111398Skaashoek   int i;
24224111398Skaashoek 
24324111398Skaashoek   printf("balloc: first %d blocks have been allocated\n", used);
244c24ac5d7SFrans Kaashoek   assert(used < BSIZE*8);
245c24ac5d7SFrans Kaashoek   bzero(buf, BSIZE);
24624111398Skaashoek   for(i = 0; i < used; i++){
24724111398Skaashoek     buf[i/8] = buf[i/8] | (0x1 << (i%8));
24824111398Skaashoek   }
2498320d61bSFrans Kaashoek   printf("balloc: write bitmap block at sector %d\n", sb.bmapstart);
2508320d61bSFrans Kaashoek   wsect(sb.bmapstart, buf);
25124111398Skaashoek }
25224111398Skaashoek 
253c59361f1Srtm #define min(a, b) ((a) < (b) ? (a) : (b))
254c59361f1Srtm 
255c59361f1Srtm void
iappend(uint inum,void * xp,int n)256c59361f1Srtm iappend(uint inum, void *xp, int n)
257c59361f1Srtm {
258c59361f1Srtm   char *p = (char*)xp;
259c59361f1Srtm   uint fbn, off, n1;
260c59361f1Srtm   struct dinode din;
261c24ac5d7SFrans Kaashoek   char buf[BSIZE];
262ea2909b6Skaashoek   uint indirect[NINDIRECT];
263ea2909b6Skaashoek   uint x;
264c59361f1Srtm 
265c59361f1Srtm   rinode(inum, &din);
266c59361f1Srtm   off = xint(din.size);
2678320d61bSFrans Kaashoek   // printf("append inum %d at off %d sz %d\n", inum, off, n);
268c59361f1Srtm   while(n > 0){
269c24ac5d7SFrans Kaashoek     fbn = off / BSIZE;
270ea2909b6Skaashoek     assert(fbn < MAXFILE);
271ea2909b6Skaashoek     if(fbn < NDIRECT){
272ea2909b6Skaashoek       if(xint(din.addrs[fbn]) == 0){
273c59361f1Srtm         din.addrs[fbn] = xint(freeblock++);
27424111398Skaashoek       }
275ea2909b6Skaashoek       x = xint(din.addrs[fbn]);
276ea2909b6Skaashoek     } else {
277ba6cd8a6Srsc       if(xint(din.addrs[NDIRECT]) == 0){
278ba6cd8a6Srsc         din.addrs[NDIRECT] = xint(freeblock++);
279ea2909b6Skaashoek       }
280ba6cd8a6Srsc       rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
281ea2909b6Skaashoek       if(indirect[fbn - NDIRECT] == 0){
282ea2909b6Skaashoek         indirect[fbn - NDIRECT] = xint(freeblock++);
283ba6cd8a6Srsc         wsect(xint(din.addrs[NDIRECT]), (char*)indirect);
284ea2909b6Skaashoek       }
285ea2909b6Skaashoek       x = xint(indirect[fbn-NDIRECT]);
286ea2909b6Skaashoek     }
287c24ac5d7SFrans Kaashoek     n1 = min(n, (fbn + 1) * BSIZE - off);
288ea2909b6Skaashoek     rsect(x, buf);
289c24ac5d7SFrans Kaashoek     bcopy(p, buf + off - (fbn * BSIZE), n1);
290ea2909b6Skaashoek     wsect(x, buf);
291c59361f1Srtm     n -= n1;
292c59361f1Srtm     off += n1;
293c59361f1Srtm     p += n1;
294c59361f1Srtm   }
295c59361f1Srtm   din.size = xint(off);
296c59361f1Srtm   winode(inum, &din);
297c59361f1Srtm }
298