xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

mkfs.c (5815B)


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