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)
102 fprintf(stderr, "mkfs.lafs: %s has already been given,"
103 " value \"%s\" not permitted.\n",
108 val = parse_size(arg, &error);
110 fprintf(stderr, "mkfs.lafs: %s: \"%s\" for %s\n",
117 void get_num(int *valp, char *arg, char *name)
123 fprintf(stderr, "mkfs.lafs: %s has already been given,"
124 " value \"%s\" not permitted.\n",
129 val = strtol(arg, &endp, 0);
130 if (endp == arg || *endp) {
131 fprintf(stderr, "mkfs.lafs: Unrecognised number \"%s\""
132 " for %s\n", arg, name);
136 fprintf(stderr, "mkfs.lafs: 0 is not a valid number for %s\n", name);
142 int main(int argc, char *argv[])
145 long block_bytes = 0;
146 long segment_bytes = 0;
148 long stride_bytes = 0;
149 long long device_bytes;
150 char *devname = NULL;
151 int create_atime = 1;
152 int regular_file = 0;
157 struct lafs_device *dev;
158 struct lafs_ino *ifile, *imfile, *rootdir, *orphans, *segmap;
159 struct lafs_ino *atimefile = NULL;
161 while ((opt = getopt_long(argc, argv,
162 short_options, long_options,
166 fputs(help_text, stdout);
167 fputs(usage_text, stdout);
170 fputs(version_text, stdout);
176 get_size(&block_bytes, optarg, "block size");
179 get_size(&segment_bytes, optarg, "segment size");
182 get_size(&stride_bytes, optarg, "stride size");
185 get_num(&width, optarg, "device width");
195 if (devname == NULL) {
199 fprintf(stderr, "mkfs.lafs: multiple device names not supported: %s and %s\n",
205 fputs(usage_text, stderr);
210 if (devname == NULL) {
211 fputs("mkfs.lafs: no device name given\n", stderr);
212 fputs(usage_text, stderr);
216 /* Validate device */
217 dev_fd = open_device(devname, &device_bytes, regular_file, &error);
219 fprintf(stderr, "mkfs.lafs: %s\n", error);
224 /* Validate parameters */
225 error = lafs_validate_geometry(&block_bytes, &segment_bytes,
226 &stride_bytes, &width,
229 fprintf(stderr, "mkfs.lafs: %s\n", error);
234 /* Create filesystem handle */
237 /* Initialise filesystem */
238 lafs_new(lafs, block_bytes);
241 dev = lafs_add_device(lafs, devname, dev_fd,
242 segment_bytes / block_bytes,
243 stride_bytes / block_bytes,
247 /* Write device blocks */
251 ifile = lafs_get_itable(lafs);
252 imfile = lafs_add_inode(ifile, 1, TypeInodeMap);
253 rootdir = lafs_add_inode(ifile, 2, TypeDir);
255 atimefile = lafs_add_inode(ifile, 3, TypeAccessTime);
256 rootdir->md.file.linkcount = 2;
257 rootdir->md.file.mode = 0755;
258 rootdir->md.file.parent = 2;
259 lafs_dirty_inode(rootdir);
260 orphans = lafs_add_inode(ifile, 8, TypeOrphanList);
261 segmap = lafs_add_inode(ifile, 16, TypeSegmentMap);
262 lafs->devs->segsum = segmap;
263 segmap->md.segmentusage.table_size = lafs->devs->tablesize * 16;
264 lafs->devs->tablesize = segmap->md.segmentusage.table_size;
265 lafs_dirty_inode(segmap);
267 lafs_imap_set(imfile, 1);
268 lafs_imap_set(imfile, 2);
269 lafs_imap_set(imfile, 8);
270 lafs_imap_set(imfile, 16);
272 lafs_cluster_init(lafs, 0, 0, 0, 1);
273 /* Write checkpoint and state blocks */
274 lafs_checkpoint(lafs);
275 /* Write state blocks a second time, so all 4 copies are written */
276 lafs_write_state(lafs);
278 printf("Filesystem created with %llu segments of %llu %dK blocks\n",
279 (unsigned long long)dev->segment_count,
280 (unsigned long long)dev->segment_size,
281 lafs->blocksize/1024);