-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmkfs.chunkfs.c
190 lines (151 loc) · 5.06 KB
/
mkfs.chunkfs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*
* Create a chunkfs file system.
*
* (C) 2007-2008 Val Henson <[email protected]>
*/
#include <stdio.h>
#include <error.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <linux/byteorder/little_endian.h>
#include "chunkfs.h"
#include "chunkfs_pool.h"
#include "chunkfs_dev.h"
#include "chunkfs_chunk.h"
#include "chunkfs_i.h"
#define exit _exit
/* Compile time test that structures have not outgrown blocks. */
static char canary_buf1[CHUNKFS_BLK_SIZE -
sizeof(struct chunkfs_pool)] __attribute__((unused));
static char canary_buf2[CHUNKFS_BLK_SIZE -
sizeof(struct chunkfs_dev)] __attribute__((unused));
static char * cmd;
static void usage (void)
{
fprintf(stderr, "Usage: %s <device>\n", cmd);
exit(1);
}
static void write_block(void *metadata, int size, int fd, __u64 offset)
{
char buf[CHUNKFS_BLK_SIZE];
int buf_size = sizeof (buf);
struct chunkfs_chkmagic *x = (struct chunkfs_chkmagic *) buf;
bzero(buf, buf_size);
memcpy(buf, metadata, size);
write_chksum(buf, size);
printf("Writing magic %0x chksum %0x to offset %llu\n",
__le32_to_cpu(x->x_magic), __le32_to_cpu(x->x_chksum),
offset);
if (lseek(fd, offset, SEEK_SET) < 0)
error(1, errno, "Cannot seek");
if (write(fd, buf, buf_size) < buf_size)
error(1, errno, "Cannot write metadata at offset %llu",
(unsigned long long) offset);
}
/*
* Create and write a pool summary (superblock)
*/
static void create_pool_summary(char *dev_name, struct chunkfs_pool *pool)
{
struct chunkfs_dev_desc *dev_desc = &pool->p_root_desc;
/* Fill in device description. */
strcpy(dev_desc->d_hint, dev_name);
/* XXX need userland generated uuid */
dev_desc->d_uuid = __cpu_to_le64(0x001d001d);
bzero(pool, sizeof(*pool));
pool->p_magic = __cpu_to_le32(CHUNKFS_SUPER_MAGIC);
}
static void create_dev_summary(struct chunkfs_pool *pool,
struct chunkfs_dev *dev,
__u64 dev_begin,
__u64 dev_size)
{
struct chunkfs_dev_desc *dev_desc = &pool->p_root_desc;
bzero(dev, sizeof(*dev));
dev->d_uuid = dev_desc->d_uuid; /* Already swapped */
dev->d_begin = __cpu_to_le64(dev_begin);
dev->d_end = __cpu_to_le64(dev_begin + dev_size - 1); /* Starting counting from zero */
dev->d_innards_begin = __cpu_to_le64(dev_begin + CHUNKFS_BLK_SIZE);
dev->d_innards_end = dev->d_end; /* Already swapped */
dev->d_root_chunk = dev->d_innards_begin; /* Already swapped */
dev->d_magic = __cpu_to_le32(CHUNKFS_DEV_MAGIC);
}
static void create_chunk_summary(struct chunkfs_chunk *chunk,
__u64 chunk_start, __u64 chunk_size,
__u64 chunk_id)
{
bzero(chunk, sizeof(*chunk));
chunk->c_begin = __cpu_to_le64(chunk_start);
chunk->c_end = __cpu_to_le64(chunk_start + chunk_size - 1);
chunk->c_innards_begin = __cpu_to_le64(chunk_start + CHUNKFS_BLK_SIZE);
chunk->c_innards_end = chunk->c_end; /* Already swapped */
chunk->c_chunk_id = __cpu_to_le64(chunk_id);
chunk->c_magic = __cpu_to_le32(CHUNKFS_CHUNK_MAGIC);
}
static void write_chunk_summaries(struct chunkfs_dev *dev,
struct chunkfs_chunk *chunk,
int fd)
{
__u64 chunk_id = 1; /* 0 is not a valid chunk id */
__u64 chunk_start = __le64_to_cpu(dev->d_root_chunk);
__u64 chunk_size = CHUNKFS_CHUNK_SIZE;
__u64 dev_end = __le64_to_cpu(dev->d_end);
while ((chunk_start + chunk_size - 1) < dev_end) {
/* XXX Throwing away disk if not multiple of chunk size */
create_chunk_summary(chunk, chunk_start, chunk_size,
chunk_id);
if (chunk_id == 1)
chunk->c_flags |= __cpu_to_le64(CHUNKFS_ROOT);
/* Can we get another chunk in? Then point to it */
if ((__le64_to_cpu(chunk->c_end) + chunk_size - 1) < dev_end)
chunk->c_next_chunk = __cpu_to_le64(chunk->c_end + 1);
printf("Writing chunk %llu: start %llu end %llu)\n",
__le64_to_cpu(chunk->c_chunk_id),
__le64_to_cpu(chunk->c_begin),
__le64_to_cpu(chunk->c_end));
printf("clientfs: start %llu\n", __le64_to_cpu(chunk->c_innards_begin));
write_block(chunk, sizeof(*chunk), fd, chunk_start);
chunk_start += chunk_size;
chunk_id++;
}
}
int main (int argc, char * argv[])
{
int fd;
char * dev_name;
struct stat stat_buf;
off_t raw_dev_size;
struct chunkfs_pool pool = { 0 };
struct chunkfs_dev root_dev = { 0 };
struct chunkfs_chunk root_chunk = { 0 };
cmd = argv[0];
if (argc != 2)
usage();
dev_name = argv[1];
/*
* Get some info about the device.
*/
if ((fd = open(dev_name, O_RDWR)) < 0)
error(1, errno, "Cannot open device %s", dev_name);
if (fstat(fd, &stat_buf) != 0)
error(1, errno, "Cannot stat device %s", dev_name);
raw_dev_size = stat_buf.st_size;
/*
* XXX Sanity check size - big enough?
*/
/*
* Create structures and write them out
*/
create_pool_summary(dev_name, &pool);
write_block(&pool, sizeof(pool), fd, CHUNKFS_POOL_OFFSET);
/* XXX handle multiple devs */
create_dev_summary(&pool, &root_dev, CHUNKFS_DEV_OFFSET,
raw_dev_size - CHUNKFS_DEV_OFFSET - 1);
write_block(&root_dev, sizeof(root_dev), fd, CHUNKFS_DEV_OFFSET);
/* Now we get to the meaty bit: chunk summaries. */
write_chunk_summaries(&root_dev, &root_chunk, fd);
close(fd);
return 0;
}