Path: blob/master/filesystems-distributed-ufs/mkfs.c
909 views
#include <assert.h>1#include <fcntl.h>2#include <stdio.h>3#include <stdlib.h>4#include <string.h>5#include <unistd.h>67#include "ufs.h"89void usage() {10fprintf(stderr, "usage: mkfs -f <image_file> [-d <num_data_blocks] [-i <num_inodes>]\n");11exit(1);12}1314int main(int argc, char *argv[]) {15int ch;16char *image_file = NULL;17int num_inodes = 32;18int num_data = 32;19int visual = 0;2021while ((ch = getopt(argc, argv, "i:d:f:v")) != -1) {22switch (ch) {23case 'i':24num_inodes = atoi(optarg);25break;26case 'd':27num_data = atoi(optarg);28break;29case 'f':30image_file = optarg;31break;32case 'v':33visual = 1;34break;35default:36usage();37}38}39argc -= optind;40argv += optind;4142if (image_file == NULL)43usage();4445unsigned char *empty_buffer;46empty_buffer = calloc(UFS_BLOCK_SIZE, 1);47if (empty_buffer == NULL) {48perror("calloc");49exit(1);50}5152int fd = open(image_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);53if (fd < 0) {54perror("open");55exit(1);56}5758assert(num_inodes >= 32);59assert(num_data >= 32);6061// presumed: block 0 is the super block62super_t s;6364// totals65s.num_inodes = num_inodes;66s.num_data = num_data;6768// inode bitmap69int bits_per_block = (8 * UFS_BLOCK_SIZE); // remember, there are 8 bits per byte7071s.inode_bitmap_addr = 1;72s.inode_bitmap_len = num_inodes / bits_per_block;73if (num_inodes % bits_per_block != 0)74s.inode_bitmap_len++;7576// data bitmap77s.data_bitmap_addr = s.inode_bitmap_addr + s.inode_bitmap_len;78s.data_bitmap_len = num_data / bits_per_block;79if (num_data % bits_per_block != 0)80s.data_bitmap_len++;8182// inode table83s.inode_region_addr = s.data_bitmap_addr + s.data_bitmap_len;84int total_inode_bytes = num_inodes * sizeof(inode_t);85s.inode_region_len = total_inode_bytes / UFS_BLOCK_SIZE;86if (total_inode_bytes % UFS_BLOCK_SIZE != 0)87s.inode_region_len++;8889// data blocks90s.data_region_addr = s.inode_region_addr + s.inode_region_len;91s.data_region_len = num_data;9293int total_blocks = 1 + s.inode_bitmap_len + s.data_bitmap_len + s.inode_region_len + s.data_region_len;9495// super block is the first block96int rc = pwrite(fd, &s, sizeof(super_t), 0);97if (rc != sizeof(super_t)) {98perror("write");99exit(1);100}101102printf("total blocks %d\n", total_blocks);103printf(" inodes %d [size of each: %lu]\n", num_inodes, sizeof(inode_t));104printf(" data blocks %d\n", num_data);105printf("layout details\n");106printf(" inode bitmap address/len %d [%d]\n", s.inode_bitmap_addr, s.inode_bitmap_len);107printf(" data bitmap address/len %d [%d]\n", s.data_bitmap_addr, s.data_bitmap_len);108109// first, zero out all the blocks110int i;111for (i = 1; i < total_blocks; i++) {112rc = pwrite(fd, empty_buffer, UFS_BLOCK_SIZE, i * UFS_BLOCK_SIZE);113if (rc != UFS_BLOCK_SIZE) {114perror("write");115exit(1);116}117}118119//120// need to allocate first inode in inode bitmap121//122typedef struct {123unsigned int bits[UFS_BLOCK_SIZE / sizeof(unsigned int)];124} bitmap_t;125assert(sizeof(bitmap_t) == UFS_BLOCK_SIZE);126127bitmap_t b;128for (i = 0; i < 1024; i++)129b.bits[i] = 0;130b.bits[0] = 0x1 << 31; // first entry is allocated131132rc = pwrite(fd, &b, UFS_BLOCK_SIZE, s.inode_bitmap_addr * UFS_BLOCK_SIZE);133assert(rc == UFS_BLOCK_SIZE);134135//136// need to allocate first data block in data bitmap137// (can just reuse this to write out data bitmap too)138//139rc = pwrite(fd, &b, UFS_BLOCK_SIZE, s.data_bitmap_addr * UFS_BLOCK_SIZE);140assert(rc == UFS_BLOCK_SIZE);141142//143// need to write out inode144//145typedef struct {146inode_t inodes[UFS_BLOCK_SIZE / sizeof(inode_t)];147} inode_block;148149inode_block itable;150itable.inodes[0].type = UFS_DIRECTORY;151itable.inodes[0].size = 2 * sizeof(dir_ent_t); // in bytes152itable.inodes[0].direct[0] = s.data_region_addr;153for (i = 1; i < DIRECT_PTRS; i++)154itable.inodes[0].direct[i] = -1;155156rc = pwrite(fd, &itable, UFS_BLOCK_SIZE, s.inode_region_addr * UFS_BLOCK_SIZE);157assert(rc == UFS_BLOCK_SIZE);158159//160// need to write out root directory contents to first data block161// create a root directory, with nothing in it162//163typedef struct {164dir_ent_t entries[128];165} dir_block_t;166// xxx assumes 4096 block, 32 byte entries167assert(sizeof(dir_ent_t) * 128 == UFS_BLOCK_SIZE);168169dir_block_t parent;170strcpy(parent.entries[0].name, ".");171parent.entries[0].inum = 0;172173strcpy(parent.entries[1].name, "..");174parent.entries[1].inum = 0;175176for (i = 2; i < 128; i++)177parent.entries[i].inum = -1;178179rc = pwrite(fd, &parent, UFS_BLOCK_SIZE, s.data_region_addr * UFS_BLOCK_SIZE);180assert(rc == UFS_BLOCK_SIZE);181182if (visual) {183int i;184printf("\nVisualization of layout\n\n");185printf("S");186for (i = 0; i < s.inode_bitmap_len; i++)187printf("i");188for (i = 0; i < s.data_bitmap_len; i++)189printf("d");190for (i = 0; i < s.inode_region_len; i++)191printf("I");192for (i = 0; i < s.data_region_len; i++)193printf("D");194printf("\n\n");195}196197(void) fsync(fd);198(void) close(fd);199200return 0;201}202203204205