root/mkfs/mkfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xshort
  2. xint
  3. main
  4. wsect
  5. winode
  6. rinode
  7. rsect
  8. ialloc
  9. balloc
  10. iappend
  11. die

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

/* [<][>][^][v][top][bottom][index][help] */