kernel: Fix stop_cpus()/restart_cpus() usages when panicing.
[dragonfly.git] / sbin / newfs_hammer / newfs_hammer.c
blobb8c4e57faf0524fd256f7614865fc627eeaf12ad
1 /*
2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 #include <sys/sysctl.h>
36 #include <sys/ioctl_compat.h>
38 #include "hammer_util.h"
40 static int64_t getsize(const char *str, int pw);
41 static int trim_volume(struct volume_info *vol);
42 static void format_volume(struct volume_info *vol, int nvols,const char *label);
43 static hammer_off_t format_root_directory(const char *label);
44 static uint64_t nowtime(void);
45 static void print_volume(const struct volume_info *vol);
46 static void usage(int exit_code);
47 static void test_header_junk_size(int64_t size);
48 static void test_boot_area_size(int64_t size);
49 static void test_memory_log_size(int64_t size);
50 static void test_undo_buffer_size(int64_t size);
52 static int ForceOpt;
53 static int64_t HeaderJunkSize = -1;
54 static int64_t BootAreaSize = -1;
55 static int64_t MemoryLogSize = -1;
56 static int64_t UndoBufferSize;
57 static int HammerVersion = -1;
59 #define GIG (1024LL*1024*1024)
61 int
62 main(int ac, char **av)
64 uint32_t status;
65 off_t total;
66 off_t avg_vol_size;
67 int ch;
68 int i;
69 int nvols;
70 int eflag = 0;
71 const char *label = NULL;
72 struct volume_info *vol;
75 * Sanity check basic filesystem structures. No cookies for us
76 * if it gets broken!
78 assert(sizeof(struct hammer_volume_ondisk) <= HAMMER_BUFSIZE);
79 assert(sizeof(struct hammer_volume_ondisk) <= HAMMER_MIN_VOL_JUNK);
80 assert(sizeof(struct hammer_blockmap_layer1) == 32);
81 assert(sizeof(struct hammer_blockmap_layer2) == 16);
84 * Parse arguments
86 while ((ch = getopt(ac, av, "dfEL:j:b:m:u:hC:V:")) != -1) {
87 switch(ch) {
88 case 'd':
89 ++DebugOpt;
90 break;
91 case 'f':
92 ForceOpt = 1;
93 break;
94 case 'E':
95 eflag = 1;
96 break;
97 case 'L':
98 label = optarg;
99 break;
100 case 'j': /* Not mentioned in newfs_hammer(8) */
101 HeaderJunkSize = getsize(optarg, 2);
102 test_header_junk_size(HeaderJunkSize);
103 break;
104 case 'b':
105 BootAreaSize = getsize(optarg, 2);
106 test_boot_area_size(BootAreaSize);
107 break;
108 case 'm':
109 MemoryLogSize = getsize(optarg, 2);
110 test_memory_log_size(MemoryLogSize);
111 break;
112 case 'u':
113 UndoBufferSize = getsize(optarg, 2);
114 test_undo_buffer_size(UndoBufferSize);
115 break;
116 case 'h':
117 usage(0);
118 break;
119 case 'C':
120 if (hammer_parse_cache_size(optarg) == -1)
121 usage(1);
122 break;
123 case 'V':
124 HammerVersion = strtol(optarg, NULL, 0);
125 if (HammerVersion < HAMMER_VOL_VERSION_MIN ||
126 HammerVersion >= HAMMER_VOL_VERSION_WIP) {
127 errx(1,
128 "I don't understand how to format "
129 "HAMMER version %d",
130 HammerVersion);
132 break;
133 default:
134 usage(1);
135 break;
138 ac -= optind;
139 av += optind;
140 nvols = ac;
142 if (label == NULL) {
143 fprintf(stderr,
144 "newfs_hammer: A filesystem label must be specified\n");
145 usage(1);
148 if (HammerVersion < 0) {
149 size_t olen = sizeof(HammerVersion);
150 HammerVersion = HAMMER_VOL_VERSION_DEFAULT;
151 if (sysctlbyname("vfs.hammer.supported_version",
152 &HammerVersion, &olen, NULL, 0) == 0) {
153 if (HammerVersion >= HAMMER_VOL_VERSION_WIP) {
154 HammerVersion = HAMMER_VOL_VERSION_WIP - 1;
155 fprintf(stderr,
156 "newfs_hammer: WARNING: HAMMER VFS "
157 "supports higher version than I "
158 "understand,\n"
159 "using version %d\n",
160 HammerVersion);
162 } else {
163 fprintf(stderr,
164 "newfs_hammer: WARNING: HAMMER VFS not "
165 "loaded, cannot get version info.\n"
166 "Using version %d\n",
167 HAMMER_VOL_VERSION_DEFAULT);
171 if (nvols == 0) {
172 fprintf(stderr,
173 "newfs_hammer: You must specify at least one "
174 "special file (volume)\n");
175 exit(1);
178 if (nvols > HAMMER_MAX_VOLUMES) {
179 fprintf(stderr,
180 "newfs_hammer: The maximum number of volumes is %d\n",
181 HAMMER_MAX_VOLUMES);
182 exit(1);
186 * Generate a filesystem id and lookup the filesystem type
188 uuidgen(&Hammer_FSId, 1);
189 uuid_name_lookup(&Hammer_FSType, HAMMER_FSTYPE_STRING, &status);
190 if (status != uuid_s_ok) {
191 errx(1, "uuids file does not have the DragonFly "
192 "HAMMER filesystem type");
195 total = 0;
196 for (i = 0; i < nvols; ++i) {
197 vol = init_volume(av[i], O_RDWR, i);
198 printf("Volume %d %s %-15s size %s\n",
199 vol->vol_no, vol->type, vol->name,
200 sizetostr(vol->size));
202 if (eflag) {
203 int res = trim_volume(vol);
204 if (res == -1 || (res == 1 && ForceOpt == 0))
205 exit(1);
207 total += vol->size;
211 * Reserve space for (future) header junk, setup our poor-man's
212 * big-block allocator. Note that the header junk space includes
213 * volume header which is 1928 bytes.
215 if (HeaderJunkSize == -1)
216 HeaderJunkSize = HAMMER_VOL_JUNK_SIZE;
217 else if (HeaderJunkSize < (int64_t)sizeof(struct hammer_volume_ondisk))
218 HeaderJunkSize = sizeof(struct hammer_volume_ondisk);
219 HeaderJunkSize = HAMMER_BUFSIZE_DOALIGN(HeaderJunkSize);
222 * Calculate defaults for the boot area and memory log sizes,
223 * only if not specified by -b or -m option.
225 avg_vol_size = total / nvols;
226 if (BootAreaSize == -1)
227 BootAreaSize = init_boot_area_size(BootAreaSize, avg_vol_size);
228 if (MemoryLogSize == -1)
229 MemoryLogSize = init_memory_log_size(MemoryLogSize, avg_vol_size);
232 * Format the volumes. Format the root volume first so we can
233 * bootstrap the freemap.
235 format_volume(get_root_volume(), nvols, label);
236 for (i = 0; i < nvols; ++i) {
237 if (i != HAMMER_ROOT_VOLNO)
238 format_volume(get_volume(i), nvols, label);
241 print_volume(get_root_volume());
243 flush_all_volumes();
244 return(0);
247 static
248 void
249 print_volume(const struct volume_info *vol)
251 hammer_volume_ondisk_t ondisk;
252 hammer_blockmap_t blockmap;
253 hammer_off_t total = 0;
254 int i, nvols;
255 uint32_t status;
256 const char *name = NULL;
257 char *fsidstr;
259 ondisk = vol->ondisk;
260 blockmap = &ondisk->vol0_blockmap[HAMMER_ZONE_UNDO_INDEX];
262 nvols = ondisk->vol_count;
263 for (i = 0; i < nvols; ++i) {
264 struct volume_info *p = get_volume(i);
265 total += p->size;
266 if (p->vol_no == HAMMER_ROOT_VOLNO) {
267 assert(name == NULL);
268 name = p->name;
272 uuid_to_string(&Hammer_FSId, &fsidstr, &status);
274 printf("---------------------------------------------\n");
275 printf("HAMMER version %d\n", HammerVersion);
276 printf("%d volume%s total size %s\n",
277 nvols, (nvols == 1 ? "" : "s"), sizetostr(total));
278 printf("root-volume: %s\n", name);
279 if (DebugOpt)
280 printf("header-junk-size: %s\n",
281 sizetostr(ondisk->vol_bot_beg));
282 printf("boot-area-size: %s\n",
283 sizetostr(ondisk->vol_mem_beg - ondisk->vol_bot_beg));
284 printf("memory-log-size: %s\n",
285 sizetostr(ondisk->vol_buf_beg - ondisk->vol_mem_beg));
286 printf("undo-buffer-size: %s\n",
287 sizetostr(HAMMER_OFF_LONG_ENCODE(blockmap->alloc_offset)));
288 printf("total-pre-allocated: %s\n",
289 sizetostr(HAMMER_OFF_SHORT_ENCODE(vol->vol_free_off)));
290 printf("fsid: %s\n", fsidstr);
291 printf("\n");
292 printf("NOTE: Please remember that you may have to manually set up a\n"
293 "cron(8) job to prune and reblock the filesystem regularly.\n"
294 "By default, the system automatically runs 'hammer cleanup'\n"
295 "on a nightly basis. The periodic.conf(5) variable\n"
296 "'daily_clean_hammer_enable' can be unset to disable this.\n"
297 "Also see 'man hammer' and 'man HAMMER' for more information.\n");
298 if (total < 10*GIG) {
299 printf("\nWARNING: The minimum UNDO/REDO FIFO is %s, "
300 "you really should not\n"
301 "try to format a HAMMER filesystem this small.\n",
302 sizetostr(HAMMER_BIGBLOCK_SIZE *
303 HAMMER_MIN_UNDO_BIGBLOCKS));
305 if (total < 50*GIG) {
306 printf("\nWARNING: HAMMER filesystems less than 50GB are "
307 "not recommended!\n"
308 "You may have to run 'hammer prune-everything' and "
309 "'hammer reblock'\n"
310 "quite often, even if using a nohistory mount.\n");
314 static
315 void
316 usage(int exit_code)
318 fprintf(stderr,
319 "usage: newfs_hammer -L label [-Efh] [-b bootsize] [-m savesize] [-u undosize]\n"
320 " [-C cachesize[:readahead]] [-V version] special ...\n"
322 exit(exit_code);
325 static void
326 test_header_junk_size(int64_t size)
328 if (size < HAMMER_MIN_VOL_JUNK) {
329 if (ForceOpt == 0) {
330 errx(1, "The minimum header junk size is %s",
331 sizetostr(HAMMER_MIN_VOL_JUNK));
332 } else {
333 fprintf(stderr,
334 "WARNING: you have specified "
335 "header junk size less than %s.\n",
336 sizetostr(HAMMER_MIN_VOL_JUNK));
338 } else if (size > HAMMER_MAX_VOL_JUNK) {
339 errx(1, "The maximum header junk size is %s",
340 sizetostr(HAMMER_MAX_VOL_JUNK));
344 static void
345 test_boot_area_size(int64_t size)
347 if (size < HAMMER_BOOT_MINBYTES) {
348 if (ForceOpt == 0) {
349 errx(1, "The minimum boot area size is %s",
350 sizetostr(HAMMER_BOOT_MINBYTES));
351 } else {
352 fprintf(stderr,
353 "WARNING: you have specified "
354 "boot area size less than %s.\n",
355 sizetostr(HAMMER_BOOT_MINBYTES));
357 } else if (size > HAMMER_BOOT_MAXBYTES) {
358 errx(1, "The maximum boot area size is %s",
359 sizetostr(HAMMER_BOOT_MAXBYTES));
363 static void
364 test_memory_log_size(int64_t size)
366 if (size < HAMMER_MEM_MINBYTES) {
367 if (ForceOpt == 0) {
368 errx(1, "The minimum memory log size is %s",
369 sizetostr(HAMMER_MEM_MINBYTES));
370 } else {
371 fprintf(stderr,
372 "WARNING: you have specified "
373 "memory log size less than %s.\n",
374 sizetostr(HAMMER_MEM_MINBYTES));
376 } else if (size > HAMMER_MEM_MAXBYTES) {
377 errx(1, "The maximum memory log size is %s",
378 sizetostr(HAMMER_MEM_MAXBYTES));
382 static void
383 test_undo_buffer_size(int64_t size)
385 int64_t minbuf, maxbuf;
387 minbuf = HAMMER_BIGBLOCK_SIZE * HAMMER_MIN_UNDO_BIGBLOCKS;
388 maxbuf = HAMMER_BIGBLOCK_SIZE * HAMMER_MAX_UNDO_BIGBLOCKS;
390 if (size < minbuf) {
391 if (ForceOpt == 0) {
392 errx(1, "The minimum UNDO/REDO FIFO size is %s",
393 sizetostr(minbuf));
394 } else {
395 fprintf(stderr,
396 "WARNING: you have specified an "
397 "UNDO/REDO FIFO size less than %s,\n"
398 "which may lead to VFS panics.\n",
399 sizetostr(minbuf));
401 } else if (size > maxbuf) {
402 errx(1, "The maximum UNDO/REDO FIFO size is %s",
403 sizetostr(maxbuf));
408 * Convert a string to a 64 bit signed integer with various requirements.
410 static int64_t
411 getsize(const char *str, int powerof2)
413 int64_t val;
414 char *ptr;
416 val = strtoll(str, &ptr, 0);
417 switch(*ptr) {
418 case 't':
419 case 'T':
420 val *= 1024;
421 /* fall through */
422 case 'g':
423 case 'G':
424 val *= 1024;
425 /* fall through */
426 case 'm':
427 case 'M':
428 val *= 1024;
429 /* fall through */
430 case 'k':
431 case 'K':
432 val *= 1024;
433 break;
434 default:
435 errx(1, "Unknown suffix in number '%s'", str);
436 /* not reached */
439 if (ptr[1]) {
440 errx(1, "Unknown suffix in number '%s'", str);
441 /* not reached */
443 if ((powerof2 & 1) && (val ^ (val - 1)) != ((val << 1) - 1)) {
444 errx(1, "Value not power of 2: %s", str);
445 /* not reached */
447 if ((powerof2 & 2) && (val & HAMMER_BUFMASK)) {
448 errx(1, "Value not an integral multiple of %dK: %s",
449 HAMMER_BUFSIZE / 1024, str);
450 /* not reached */
452 return(val);
456 * Generate a transaction id. Transaction ids are no longer time-based.
457 * Put the nail in the coffin by not making the first one time-based.
459 * We could start at 1 here but start at 2^32 to reserve a small domain for
460 * possible future use.
462 static hammer_tid_t
463 createtid(void)
465 static hammer_tid_t lasttid;
467 if (lasttid == 0)
468 lasttid = 0x0000000100000000ULL;
469 return(lasttid++);
472 static uint64_t
473 nowtime(void)
475 struct timeval tv;
476 uint64_t xtime;
478 gettimeofday(&tv, NULL);
479 xtime = tv.tv_sec * 1000000LL + tv.tv_usec;
480 return(xtime);
484 * TRIM the volume, but only if the backing store is a DEVICE
486 static
488 trim_volume(struct volume_info *vol)
490 size_t olen;
491 char *dev_name, *p;
492 char sysctl_name[64];
493 int trim_enabled;
494 off_t ioarg[2];
496 if (strcmp(vol->type, "DEVICE")) {
497 fprintf(stderr, "Cannot TRIM regular file %s\n", vol->name);
498 return(1);
500 if (strncmp(vol->name, "/dev/da", 7)) {
501 fprintf(stderr, "%s does not support the TRIM command\n",
502 vol->name);
503 return(1);
506 /* Extract a number from /dev/da?s? */
507 dev_name = strdup(vol->name);
508 p = strtok(dev_name + strlen("/dev/da"), "s");
509 sprintf(sysctl_name, "kern.cam.da.%s.trim_enabled", p);
510 free(dev_name);
512 trim_enabled = 0;
513 olen = sizeof(trim_enabled);
515 if (sysctlbyname(sysctl_name, &trim_enabled, &olen, NULL, 0) == -1) {
516 fprintf(stderr, "%s (%s) does not support the TRIM command\n",
517 vol->name, sysctl_name);
518 return(1);
520 if (!trim_enabled) {
521 fprintf(stderr, "Erase device option selected, but sysctl (%s) "
522 "is not enabled\n", sysctl_name);
523 return(1);
526 ioarg[0] = vol->device_offset;
527 ioarg[1] = vol->size;
529 printf("Trimming %s %s, sectors %llu-%llu\n",
530 vol->type, vol->name,
531 (unsigned long long)ioarg[0] / 512,
532 (unsigned long long)ioarg[1] / 512);
534 if (ioctl(vol->fd, IOCTLTRIM, ioarg) == -1) {
535 fprintf(stderr, "Device trim failed\n");
536 return(-1);
539 return(0);
543 * Format a HAMMER volume.
545 static
546 void
547 format_volume(struct volume_info *vol, int nvols, const char *label)
549 struct volume_info *root_vol;
550 hammer_volume_ondisk_t ondisk;
551 int64_t freeblks;
552 int64_t freebytes;
553 int64_t vol_buf_size;
554 hammer_off_t vol_alloc;
555 int i;
558 * Initialize basic information in the on-disk volume structure.
560 ondisk = vol->ondisk;
562 ondisk->vol_fsid = Hammer_FSId;
563 ondisk->vol_fstype = Hammer_FSType;
564 snprintf(ondisk->vol_label, sizeof(ondisk->vol_label), "%s", label);
565 ondisk->vol_no = vol->vol_no;
566 ondisk->vol_count = nvols;
567 ondisk->vol_version = HammerVersion;
569 vol_alloc = HeaderJunkSize;
570 ondisk->vol_bot_beg = vol_alloc;
571 vol_alloc += BootAreaSize;
572 ondisk->vol_mem_beg = vol_alloc;
573 vol_alloc += MemoryLogSize;
576 * The remaining area is the zone 2 buffer allocation area.
578 ondisk->vol_buf_beg = vol_alloc;
579 ondisk->vol_buf_end = vol->size & ~(int64_t)HAMMER_BUFMASK;
580 vol_buf_size = HAMMER_VOL_BUF_SIZE(ondisk);
582 if (vol_buf_size < 0) {
583 errx(1, "volume %d %s is too small to hold the volume header",
584 vol->vol_no, vol->name);
587 if ((vol_buf_size & ~HAMMER_OFF_SHORT_MASK) != 0) {
588 errx(1, "volume %d %s is too large", vol->vol_no, vol->name);
591 ondisk->vol_rootvol = HAMMER_ROOT_VOLNO;
592 ondisk->vol_signature = HAMMER_FSBUF_VOLUME;
594 vol->vol_free_off = HAMMER_ENCODE_RAW_BUFFER(vol->vol_no, 0);
595 vol->vol_free_end = HAMMER_ENCODE_RAW_BUFFER(vol->vol_no,
596 vol_buf_size & ~HAMMER_BIGBLOCK_MASK64);
599 * Format the root volume.
601 if (vol->vol_no == HAMMER_ROOT_VOLNO) {
603 * Check freemap counts before formatting
605 freeblks = count_freemap(vol);
606 freebytes = freeblks * HAMMER_BIGBLOCK_SIZE64;
607 if (freebytes < 10*GIG && ForceOpt == 0) {
608 errx(1, "Cannot create a HAMMER filesystem less than 10GB "
609 "unless you use -f\n(for the size of Volume %d). "
610 "HAMMER filesystems less than 50GB are not "
611 "recommended.", HAMMER_ROOT_VOLNO);
615 * Starting TID
617 ondisk->vol0_next_tid = createtid();
620 * Format freemap. vol0_stat_freebigblocks is
621 * the number of big-blocks available for anything
622 * other than freemap zone at this point.
624 format_freemap(vol);
625 assert(ondisk->vol0_stat_freebigblocks == 0);
626 ondisk->vol0_stat_freebigblocks = initialize_freemap(vol);
629 * Format zones that are mapped to zone-2.
631 for (i = 0; i < HAMMER_MAX_ZONES; ++i) {
632 if (hammer_is_zone2_mapped_index(i))
633 format_blockmap(vol, i, 0);
637 * Format undo zone. Formatting decrements
638 * vol0_stat_freebigblocks whenever a new big-block
639 * is allocated for undo zone.
641 format_undomap(vol, &UndoBufferSize);
642 assert(ondisk->vol0_stat_bigblocks == 0);
643 ondisk->vol0_stat_bigblocks = ondisk->vol0_stat_freebigblocks;
646 * Format the root directory. Formatting decrements
647 * vol0_stat_freebigblocks whenever a new big-block
648 * is allocated for required zones.
650 ondisk->vol0_btree_root = format_root_directory(label);
651 ++ondisk->vol0_stat_inodes; /* root inode */
652 } else {
653 freeblks = initialize_freemap(vol);
654 root_vol = get_root_volume();
655 root_vol->ondisk->vol0_stat_freebigblocks += freeblks;
656 root_vol->ondisk->vol0_stat_bigblocks += freeblks;
661 * Format the root directory.
663 static
664 hammer_off_t
665 format_root_directory(const char *label)
667 hammer_off_t btree_off;
668 hammer_off_t idata_off;
669 hammer_off_t pfsd_off;
670 hammer_tid_t create_tid;
671 hammer_node_ondisk_t bnode;
672 hammer_inode_data_t idata;
673 hammer_pseudofs_data_t pfsd;
674 struct buffer_info *data_buffer0 = NULL;
675 struct buffer_info *data_buffer1 = NULL;
676 struct buffer_info *data_buffer2 = NULL;
677 hammer_btree_elm_t elm;
678 uint64_t xtime;
681 * Allocate zero-filled root btree node, inode and pfs
683 bnode = alloc_btree_node(&btree_off, &data_buffer0);
684 idata = alloc_meta_element(&idata_off, sizeof(*idata), &data_buffer1);
685 pfsd = alloc_meta_element(&pfsd_off, sizeof(*pfsd), &data_buffer2);
686 create_tid = createtid();
687 xtime = nowtime();
690 * Populate the inode data and inode record for the root directory.
692 idata->version = HAMMER_INODE_DATA_VERSION;
693 idata->mode = 0755;
694 idata->ctime = xtime;
695 idata->mtime = xtime;
696 idata->atime = xtime;
697 idata->obj_type = HAMMER_OBJTYPE_DIRECTORY;
698 idata->size = 0;
699 idata->nlinks = 1;
700 if (HammerVersion >= HAMMER_VOL_VERSION_TWO)
701 idata->cap_flags |= HAMMER_INODE_CAP_DIR_LOCAL_INO;
702 if (HammerVersion >= HAMMER_VOL_VERSION_SIX)
703 idata->cap_flags |= HAMMER_INODE_CAP_DIRHASH_ALG1;
706 * Populate the PFS data for the root PFS.
708 pfsd->sync_low_tid = 1;
709 pfsd->sync_beg_tid = 0;
710 pfsd->sync_end_tid = 0; /* overriden by vol0_next_tid on pfs0 */
711 pfsd->shared_uuid = Hammer_FSId;
712 pfsd->unique_uuid = Hammer_FSId;
713 pfsd->mirror_flags = 0;
714 snprintf(pfsd->label, sizeof(pfsd->label), "%s", label);
717 * Create the root of the B-Tree. The root is a leaf node so we
718 * do not have to worry about boundary elements.
720 bnode->parent = 0; /* no parent */
721 bnode->count = 2;
722 bnode->type = HAMMER_BTREE_TYPE_LEAF;
723 bnode->mirror_tid = 0;
726 * Create the first node element for the inode.
728 elm = &bnode->elms[0];
729 elm->leaf.base.btype = HAMMER_BTREE_TYPE_RECORD;
730 elm->leaf.base.localization = HAMMER_DEF_LOCALIZATION |
731 HAMMER_LOCALIZE_INODE;
732 elm->leaf.base.obj_id = HAMMER_OBJID_ROOT;
733 elm->leaf.base.key = 0;
734 elm->leaf.base.create_tid = create_tid;
735 elm->leaf.base.delete_tid = 0;
736 elm->leaf.base.rec_type = HAMMER_RECTYPE_INODE;
737 elm->leaf.base.obj_type = HAMMER_OBJTYPE_DIRECTORY;
738 elm->leaf.create_ts = (uint32_t)time(NULL);
740 elm->leaf.data_offset = idata_off;
741 elm->leaf.data_len = sizeof(*idata);
742 hammer_crc_set_leaf(idata, &elm->leaf);
745 * Create the second node element for the PFS data.
746 * This is supposed to be a record part of the root ip (inode),
747 * so it should have the same obj_type value as above.
749 elm = &bnode->elms[1];
750 elm->leaf.base.btype = HAMMER_BTREE_TYPE_RECORD;
751 elm->leaf.base.localization = HAMMER_DEF_LOCALIZATION |
752 HAMMER_LOCALIZE_MISC;
753 elm->leaf.base.obj_id = HAMMER_OBJID_ROOT;
754 elm->leaf.base.key = 0;
755 elm->leaf.base.create_tid = create_tid;
756 elm->leaf.base.delete_tid = 0;
757 elm->leaf.base.rec_type = HAMMER_RECTYPE_PFS;
758 elm->leaf.base.obj_type = HAMMER_OBJTYPE_DIRECTORY;
759 elm->leaf.create_ts = (uint32_t)time(NULL);
761 elm->leaf.data_offset = pfsd_off;
762 elm->leaf.data_len = sizeof(*pfsd);
763 hammer_crc_set_leaf(pfsd, &elm->leaf);
765 hammer_crc_set_btree(bnode);
767 rel_buffer(data_buffer0);
768 rel_buffer(data_buffer1);
769 rel_buffer(data_buffer2);
771 return(btree_off);