2 * mkfs.lafs - Create an empty LAFS filesystem
4 * Copyright (C) 2010 NeilBrown <neil@brown.name>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Email: <neil@brown.name>
25 #include <sys/types.h>
30 #include <lafs/lafs.h>
36 * A new filesystem must contain:
37 * inode 0 - TypeInodeFile with all the files listed here
38 * inode 1 - TypeInodeMap - empty
39 * inode 2 - TypeDir - empty
40 * inode 8 - TypeOrphanList - empty
41 * inode 16 - TypeSegmentMap - youth block and usage block for first segment
43 * These can all be in one checkpoint and could be in a single
44 * write-cluster, though that could be a bit awkward.
46 * As well as the write-clusters we need device-blocks and state-blocks.
48 * Configurable values are:
49 * - block size, 512 to 4096 -b or --block-size
50 * - segment size - up to 64k, but multiple of width --segment-size
51 * - width - spindles across which device is striped --width
52 * - stride - chunk-size when device is striped --stride
64 char short_options[] = "-b:Vvh";
65 struct option long_options[] = {
66 {"block-size", 1, 0, 'b'},
67 {"segment-size", 1, 0, opt_segsize},
68 {"width", 1, 0, opt_width},
69 {"stride", 1, 0, opt_stride},
70 {"version", 0, 0, 'V'},
71 {"verbose", 0, 0, 'v'},
73 {"no-atime-file",0, 0, opt_noatime},
74 {"regular-file", 0, 0, opt_regular},
78 char version_text[] = "mkfs.lafs - unreleased\n";
81 "mkfs.lafs: create a lafs filesystem\n"
85 "Usage: mkfs.lafs [options] device-name\n"
87 " --block-size (-b) size of basic block, up to 4096 (e.g. 2K)\n"
88 " --segment-size size of segments, up to 65536 blocks (e.g. 32M)\n"
89 " --width number of members of a striped device (e.g. 3)\n"
90 " --stride chunk size of a striped device (e.g. 64K)\n"
91 " --help (-h) This help message\n"
92 " --version (-V) Report version information\n"
93 " --verbose (-v) Be more verbose\n"
96 static void get_size(long *valp, char *arg, char *name)
103 fprintf(stderr, "mkfs.lafs: %s has already been given, value \"%s\" not permitted.\n",
108 val = strtol(arg, &endp, 0);
111 fprintf(stderr, "mkfs.lafs: Unrecognised size \"%s\" for %s\n", arg, name);
124 scale = 1024*1024*1024;
130 fprintf(stderr, "mkfs.lafs: unrecognised modifier \"%s\" for %s\n", endp, name);
134 fprintf(stderr, "mkfs.lafs: 0 is not a valid number for %s\n", name);
141 void get_num(int *valp, char *arg, char *name)
147 fprintf(stderr, "mkfs.lafs: %s has already been given, value \"%s\" not permitted.\n",
152 val = strtol(arg, &endp, 0);
153 if (endp == arg || *endp) {
154 fprintf(stderr, "mkfs.lafs: Unrecognised number \"%s\" for %s\n", arg, name);
158 fprintf(stderr, "mkfs.lafs: 0 is not a valid number for %s\n", name);
164 int main(int argc, char *argv[])
167 long block_bytes = 0;
168 long segment_bytes = 0;
170 long stride_bytes = 0;
171 long long device_bytes;
172 char *devname = NULL;
173 int create_atime = 1;
174 int regular_file = 0;
179 struct lafs_device *dev;
180 struct lafs_ino *ifile, *imfile, *rootdir, *orphans, *segmap;
181 struct lafs_ino *atimefile = NULL;
183 while ((opt = getopt_long(argc, argv,
184 short_options, long_options,
188 fputs(help_text, stdout);
189 fputs(usage_text, stdout);
192 fputs(version_text, stdout);
198 get_size(&block_bytes, optarg, "block size");
201 get_size(&segment_bytes, optarg, "segment size");
204 get_size(&stride_bytes, optarg, "stride size");
207 get_num(&width, optarg, "device width");
217 if (devname == NULL) {
221 fprintf(stderr, "mkfs.lafs: multiple device names not supported: %s and %s\n",
227 fputs(usage_text, stderr);
232 if (devname == NULL) {
233 fputs("mkfs.lafs: no device name given\n", stderr);
234 fputs(usage_text, stderr);
238 /* Validate device */
239 dev_fd = open_device(devname, &device_bytes, regular_file, &error);
241 fprintf(stderr, "mkfs.lafs: %s\n", error);
246 /* Validate parameters */
247 error = lafs_validate_geometry(&block_bytes, &segment_bytes,
248 &stride_bytes, &width,
251 fprintf(stderr, "mkfs.lafs: %s\n", error);
256 /* Create filesystem handle */
259 /* Initialise filesystem */
260 lafs_new(lafs, block_bytes);
263 dev = lafs_add_device(lafs, devname, dev_fd,
264 segment_bytes / block_bytes,
265 stride_bytes / block_bytes,
269 /* Write device blocks */
273 ifile = lafs_get_itable(lafs);
274 imfile = lafs_add_inode(ifile, 1, TypeInodeMap);
275 rootdir = lafs_add_inode(ifile, 2, TypeDir);
277 atimefile = lafs_add_inode(ifile, 3, TypeAccessTime);
278 rootdir->md.file.linkcount = 2;
279 rootdir->md.file.mode = 0755;
280 rootdir->md.file.parent = 2;
281 lafs_dirty_inode(rootdir);
282 orphans = lafs_add_inode(ifile, 8, TypeOrphanList);
283 segmap = lafs_add_inode(ifile, 16, TypeSegmentMap);
284 lafs->devs->segsum = segmap;
285 segmap->md.segmentusage.table_size = lafs->devs->tablesize * 16;
286 lafs->devs->tablesize = segmap->md.segmentusage.table_size;
287 lafs_dirty_inode(segmap);
289 lafs_imap_set(imfile, 1);
290 lafs_imap_set(imfile, 2);
291 lafs_imap_set(imfile, 8);
292 lafs_imap_set(imfile, 16);
294 lafs_cluster_init(lafs, 0, 0, 0, 1);
295 lafs_add_free_seg(lafs, dev->devnum, 0);
296 /* Write checkpoint and state blocks */
297 lafs_checkpoint(lafs);
298 /* Write state blocks a second time, so all 4 copies are written */
299 lafs_write_state(lafs);
301 printf("Filesystem created with %llu segments of %llu %dK blocks\n",
302 (unsigned long long)dev->segment_count,
303 (unsigned long long)dev->segment_size,
304 lafs->blocksize/1024);