Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
remzi-arpacidusseau
GitHub Repository: remzi-arpacidusseau/ostep-projects
Path: blob/master/filesystems-distributed-ufs/mkfs.c
909 views
1
#include <assert.h>
2
#include <fcntl.h>
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <unistd.h>
7
8
#include "ufs.h"
9
10
void usage() {
11
fprintf(stderr, "usage: mkfs -f <image_file> [-d <num_data_blocks] [-i <num_inodes>]\n");
12
exit(1);
13
}
14
15
int main(int argc, char *argv[]) {
16
int ch;
17
char *image_file = NULL;
18
int num_inodes = 32;
19
int num_data = 32;
20
int visual = 0;
21
22
while ((ch = getopt(argc, argv, "i:d:f:v")) != -1) {
23
switch (ch) {
24
case 'i':
25
num_inodes = atoi(optarg);
26
break;
27
case 'd':
28
num_data = atoi(optarg);
29
break;
30
case 'f':
31
image_file = optarg;
32
break;
33
case 'v':
34
visual = 1;
35
break;
36
default:
37
usage();
38
}
39
}
40
argc -= optind;
41
argv += optind;
42
43
if (image_file == NULL)
44
usage();
45
46
unsigned char *empty_buffer;
47
empty_buffer = calloc(UFS_BLOCK_SIZE, 1);
48
if (empty_buffer == NULL) {
49
perror("calloc");
50
exit(1);
51
}
52
53
int fd = open(image_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
54
if (fd < 0) {
55
perror("open");
56
exit(1);
57
}
58
59
assert(num_inodes >= 32);
60
assert(num_data >= 32);
61
62
// presumed: block 0 is the super block
63
super_t s;
64
65
// totals
66
s.num_inodes = num_inodes;
67
s.num_data = num_data;
68
69
// inode bitmap
70
int bits_per_block = (8 * UFS_BLOCK_SIZE); // remember, there are 8 bits per byte
71
72
s.inode_bitmap_addr = 1;
73
s.inode_bitmap_len = num_inodes / bits_per_block;
74
if (num_inodes % bits_per_block != 0)
75
s.inode_bitmap_len++;
76
77
// data bitmap
78
s.data_bitmap_addr = s.inode_bitmap_addr + s.inode_bitmap_len;
79
s.data_bitmap_len = num_data / bits_per_block;
80
if (num_data % bits_per_block != 0)
81
s.data_bitmap_len++;
82
83
// inode table
84
s.inode_region_addr = s.data_bitmap_addr + s.data_bitmap_len;
85
int total_inode_bytes = num_inodes * sizeof(inode_t);
86
s.inode_region_len = total_inode_bytes / UFS_BLOCK_SIZE;
87
if (total_inode_bytes % UFS_BLOCK_SIZE != 0)
88
s.inode_region_len++;
89
90
// data blocks
91
s.data_region_addr = s.inode_region_addr + s.inode_region_len;
92
s.data_region_len = num_data;
93
94
int total_blocks = 1 + s.inode_bitmap_len + s.data_bitmap_len + s.inode_region_len + s.data_region_len;
95
96
// super block is the first block
97
int rc = pwrite(fd, &s, sizeof(super_t), 0);
98
if (rc != sizeof(super_t)) {
99
perror("write");
100
exit(1);
101
}
102
103
printf("total blocks %d\n", total_blocks);
104
printf(" inodes %d [size of each: %lu]\n", num_inodes, sizeof(inode_t));
105
printf(" data blocks %d\n", num_data);
106
printf("layout details\n");
107
printf(" inode bitmap address/len %d [%d]\n", s.inode_bitmap_addr, s.inode_bitmap_len);
108
printf(" data bitmap address/len %d [%d]\n", s.data_bitmap_addr, s.data_bitmap_len);
109
110
// first, zero out all the blocks
111
int i;
112
for (i = 1; i < total_blocks; i++) {
113
rc = pwrite(fd, empty_buffer, UFS_BLOCK_SIZE, i * UFS_BLOCK_SIZE);
114
if (rc != UFS_BLOCK_SIZE) {
115
perror("write");
116
exit(1);
117
}
118
}
119
120
//
121
// need to allocate first inode in inode bitmap
122
//
123
typedef struct {
124
unsigned int bits[UFS_BLOCK_SIZE / sizeof(unsigned int)];
125
} bitmap_t;
126
assert(sizeof(bitmap_t) == UFS_BLOCK_SIZE);
127
128
bitmap_t b;
129
for (i = 0; i < 1024; i++)
130
b.bits[i] = 0;
131
b.bits[0] = 0x1 << 31; // first entry is allocated
132
133
rc = pwrite(fd, &b, UFS_BLOCK_SIZE, s.inode_bitmap_addr * UFS_BLOCK_SIZE);
134
assert(rc == UFS_BLOCK_SIZE);
135
136
//
137
// need to allocate first data block in data bitmap
138
// (can just reuse this to write out data bitmap too)
139
//
140
rc = pwrite(fd, &b, UFS_BLOCK_SIZE, s.data_bitmap_addr * UFS_BLOCK_SIZE);
141
assert(rc == UFS_BLOCK_SIZE);
142
143
//
144
// need to write out inode
145
//
146
typedef struct {
147
inode_t inodes[UFS_BLOCK_SIZE / sizeof(inode_t)];
148
} inode_block;
149
150
inode_block itable;
151
itable.inodes[0].type = UFS_DIRECTORY;
152
itable.inodes[0].size = 2 * sizeof(dir_ent_t); // in bytes
153
itable.inodes[0].direct[0] = s.data_region_addr;
154
for (i = 1; i < DIRECT_PTRS; i++)
155
itable.inodes[0].direct[i] = -1;
156
157
rc = pwrite(fd, &itable, UFS_BLOCK_SIZE, s.inode_region_addr * UFS_BLOCK_SIZE);
158
assert(rc == UFS_BLOCK_SIZE);
159
160
//
161
// need to write out root directory contents to first data block
162
// create a root directory, with nothing in it
163
//
164
typedef struct {
165
dir_ent_t entries[128];
166
} dir_block_t;
167
// xxx assumes 4096 block, 32 byte entries
168
assert(sizeof(dir_ent_t) * 128 == UFS_BLOCK_SIZE);
169
170
dir_block_t parent;
171
strcpy(parent.entries[0].name, ".");
172
parent.entries[0].inum = 0;
173
174
strcpy(parent.entries[1].name, "..");
175
parent.entries[1].inum = 0;
176
177
for (i = 2; i < 128; i++)
178
parent.entries[i].inum = -1;
179
180
rc = pwrite(fd, &parent, UFS_BLOCK_SIZE, s.data_region_addr * UFS_BLOCK_SIZE);
181
assert(rc == UFS_BLOCK_SIZE);
182
183
if (visual) {
184
int i;
185
printf("\nVisualization of layout\n\n");
186
printf("S");
187
for (i = 0; i < s.inode_bitmap_len; i++)
188
printf("i");
189
for (i = 0; i < s.data_bitmap_len; i++)
190
printf("d");
191
for (i = 0; i < s.inode_region_len; i++)
192
printf("I");
193
for (i = 0; i < s.data_region_len; i++)
194
printf("D");
195
printf("\n\n");
196
}
197
198
(void) fsync(fd);
199
(void) close(fd);
200
201
return 0;
202
}
203
204
205