12910a90cSMatthew Dillon /*
22910a90cSMatthew Dillon * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved.
32910a90cSMatthew Dillon *
42910a90cSMatthew Dillon * This code is derived from software contributed to The DragonFly Project
52910a90cSMatthew Dillon * by Matthew Dillon <dillon@dragonflybsd.org>
62910a90cSMatthew Dillon * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
72910a90cSMatthew Dillon *
82910a90cSMatthew Dillon * Redistribution and use in source and binary forms, with or without
92910a90cSMatthew Dillon * modification, are permitted provided that the following conditions
102910a90cSMatthew Dillon * are met:
112910a90cSMatthew Dillon *
122910a90cSMatthew Dillon * 1. Redistributions of source code must retain the above copyright
132910a90cSMatthew Dillon * notice, this list of conditions and the following disclaimer.
142910a90cSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
152910a90cSMatthew Dillon * notice, this list of conditions and the following disclaimer in
162910a90cSMatthew Dillon * the documentation and/or other materials provided with the
172910a90cSMatthew Dillon * distribution.
182910a90cSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
192910a90cSMatthew Dillon * contributors may be used to endorse or promote products derived
202910a90cSMatthew Dillon * from this software without specific, prior written permission.
212910a90cSMatthew Dillon *
222910a90cSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
232910a90cSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
242910a90cSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
252910a90cSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
262910a90cSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
272910a90cSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
282910a90cSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
292910a90cSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
302910a90cSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
312910a90cSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
322910a90cSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
332910a90cSMatthew Dillon * SUCH DAMAGE.
342910a90cSMatthew Dillon */
352910a90cSMatthew Dillon
36a8607002STomohiro Kusumi #include <sys/types.h>
372468135dSTomohiro Kusumi #include <sys/stat.h>
38a8607002STomohiro Kusumi #include <sys/time.h>
39a8607002STomohiro Kusumi #include <sys/ioctl.h>
4083d90983SMatthew Dillon #include <sys/mount.h>
4183d90983SMatthew Dillon #include <sys/statvfs.h>
420b738157STomohiro Kusumi #include <sys/diskslice.h>
43a8607002STomohiro Kusumi #include <unistd.h>
44a8607002STomohiro Kusumi #include <fcntl.h>
45a8607002STomohiro Kusumi #include <stdio.h>
46a8607002STomohiro Kusumi #include <stdlib.h>
4746eecc1eSTomohiro Kusumi #include <stdint.h>
48a8607002STomohiro Kusumi #include <string.h>
49a8607002STomohiro Kusumi #include <errno.h>
500b738157STomohiro Kusumi #include <err.h>
51a8607002STomohiro Kusumi #include <uuid.h>
52a8607002STomohiro Kusumi
53a8607002STomohiro Kusumi #include <vfs/hammer2/hammer2_disk.h>
54a8607002STomohiro Kusumi #include <vfs/hammer2/hammer2_ioctl.h>
55a8607002STomohiro Kusumi
56a8607002STomohiro Kusumi #include "hammer2_subs.h"
572910a90cSMatthew Dillon
582910a90cSMatthew Dillon /*
592910a90cSMatthew Dillon * Obtain a file descriptor that the caller can execute ioctl()'s on.
602910a90cSMatthew Dillon */
612910a90cSMatthew Dillon int
hammer2_ioctl_handle(const char * sel_path)622910a90cSMatthew Dillon hammer2_ioctl_handle(const char *sel_path)
632910a90cSMatthew Dillon {
642910a90cSMatthew Dillon struct hammer2_ioc_version info;
652910a90cSMatthew Dillon int fd;
662910a90cSMatthew Dillon
675ba65e34SMatthew Dillon if (sel_path == NULL)
685ba65e34SMatthew Dillon sel_path = ".";
695ba65e34SMatthew Dillon
702910a90cSMatthew Dillon fd = open(sel_path, O_RDONLY, 0);
712910a90cSMatthew Dillon if (fd < 0) {
722910a90cSMatthew Dillon fprintf(stderr, "hammer2: Unable to open %s: %s\n",
732910a90cSMatthew Dillon sel_path, strerror(errno));
742910a90cSMatthew Dillon return(-1);
752910a90cSMatthew Dillon }
76ae183399SMatthew Dillon if (ioctl(fd, HAMMER2IOC_VERSION_GET, &info) < 0) {
772910a90cSMatthew Dillon fprintf(stderr, "hammer2: '%s' is not a hammer2 filesystem\n",
782910a90cSMatthew Dillon sel_path);
792910a90cSMatthew Dillon close(fd);
802910a90cSMatthew Dillon return(-1);
812910a90cSMatthew Dillon }
822910a90cSMatthew Dillon return (fd);
832910a90cSMatthew Dillon }
845ba65e34SMatthew Dillon
85bd878fc9SMatthew Dillon const char *
hammer2_time64_to_str(uint64_t htime64,char ** strp)86bd878fc9SMatthew Dillon hammer2_time64_to_str(uint64_t htime64, char **strp)
87bd878fc9SMatthew Dillon {
88bd878fc9SMatthew Dillon struct tm *tp;
89bd878fc9SMatthew Dillon time_t t;
90bd878fc9SMatthew Dillon
91bd878fc9SMatthew Dillon if (*strp) {
92bd878fc9SMatthew Dillon free(*strp);
93bd878fc9SMatthew Dillon *strp = NULL;
94bd878fc9SMatthew Dillon }
95bd878fc9SMatthew Dillon *strp = malloc(64);
96bd878fc9SMatthew Dillon t = htime64 / 1000000;
97bd878fc9SMatthew Dillon tp = localtime(&t);
98bd878fc9SMatthew Dillon strftime(*strp, 64, "%d-%b-%Y %H:%M:%S", tp);
99bd878fc9SMatthew Dillon return (*strp);
100bd878fc9SMatthew Dillon }
101bd878fc9SMatthew Dillon
102bd878fc9SMatthew Dillon const char *
hammer2_uuid_to_str(const uuid_t * uuid,char ** strp)1034be3b20fSTomohiro Kusumi hammer2_uuid_to_str(const uuid_t *uuid, char **strp)
104bd878fc9SMatthew Dillon {
105bd878fc9SMatthew Dillon uint32_t status;
106bd878fc9SMatthew Dillon if (*strp) {
107bd878fc9SMatthew Dillon free(*strp);
108bd878fc9SMatthew Dillon *strp = NULL;
109bd878fc9SMatthew Dillon }
110bd878fc9SMatthew Dillon uuid_to_string(uuid, strp, &status);
111bd878fc9SMatthew Dillon return (*strp);
112bd878fc9SMatthew Dillon }
113bd878fc9SMatthew Dillon
114bd878fc9SMatthew Dillon const char *
hammer2_iptype_to_str(uint8_t type)115bd878fc9SMatthew Dillon hammer2_iptype_to_str(uint8_t type)
116bd878fc9SMatthew Dillon {
117bd878fc9SMatthew Dillon switch(type) {
118bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_UNKNOWN:
119bd878fc9SMatthew Dillon return("UNKNOWN");
120bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_DIRECTORY:
121bd878fc9SMatthew Dillon return("DIR");
122bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_REGFILE:
123bd878fc9SMatthew Dillon return("FILE");
124bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_FIFO:
125bd878fc9SMatthew Dillon return("FIFO");
126bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_CDEV:
127bd878fc9SMatthew Dillon return("CDEV");
128bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_BDEV:
129bd878fc9SMatthew Dillon return("BDEV");
130bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_SOFTLINK:
131bd878fc9SMatthew Dillon return("SOFTLINK");
132bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_SOCKET:
133bd878fc9SMatthew Dillon return("SOCKET");
134bd878fc9SMatthew Dillon case HAMMER2_OBJTYPE_WHITEOUT:
135bd878fc9SMatthew Dillon return("WHITEOUT");
136bd878fc9SMatthew Dillon default:
137bd878fc9SMatthew Dillon return("ILLEGAL");
138bd878fc9SMatthew Dillon }
139bd878fc9SMatthew Dillon }
140bd878fc9SMatthew Dillon
141bd878fc9SMatthew Dillon const char *
hammer2_pfstype_to_str(uint8_t type)142bd878fc9SMatthew Dillon hammer2_pfstype_to_str(uint8_t type)
143bd878fc9SMatthew Dillon {
144bd878fc9SMatthew Dillon switch(type) {
1457750fd72SMatthew Dillon case HAMMER2_PFSTYPE_NONE:
146bd878fc9SMatthew Dillon return("NONE");
147b93cc2e0SMatthew Dillon case HAMMER2_PFSTYPE_SUPROOT:
148b93cc2e0SMatthew Dillon return("SUPROOT");
149b93cc2e0SMatthew Dillon case HAMMER2_PFSTYPE_DUMMY:
150b93cc2e0SMatthew Dillon return("DUMMY");
151bd878fc9SMatthew Dillon case HAMMER2_PFSTYPE_CACHE:
152bd878fc9SMatthew Dillon return("CACHE");
153bd878fc9SMatthew Dillon case HAMMER2_PFSTYPE_SLAVE:
154bd878fc9SMatthew Dillon return("SLAVE");
155bd878fc9SMatthew Dillon case HAMMER2_PFSTYPE_SOFT_SLAVE:
156bd878fc9SMatthew Dillon return("SOFT_SLAVE");
157bd878fc9SMatthew Dillon case HAMMER2_PFSTYPE_SOFT_MASTER:
158bd878fc9SMatthew Dillon return("SOFT_MASTER");
159bd878fc9SMatthew Dillon case HAMMER2_PFSTYPE_MASTER:
160bd878fc9SMatthew Dillon return("MASTER");
161bd878fc9SMatthew Dillon default:
162bd878fc9SMatthew Dillon return("ILLEGAL");
163bd878fc9SMatthew Dillon }
164bd878fc9SMatthew Dillon }
165ad7cf8eaSMatthew Dillon
166ad7cf8eaSMatthew Dillon const char *
hammer2_pfssubtype_to_str(uint8_t subtype)167cac06d4eSTomohiro Kusumi hammer2_pfssubtype_to_str(uint8_t subtype)
168cac06d4eSTomohiro Kusumi {
169cac06d4eSTomohiro Kusumi switch(subtype) {
170cac06d4eSTomohiro Kusumi case HAMMER2_PFSSUBTYPE_NONE:
171856d0d8fSTomohiro Kusumi return("NONE");
172cac06d4eSTomohiro Kusumi case HAMMER2_PFSSUBTYPE_SNAPSHOT:
173cac06d4eSTomohiro Kusumi return("SNAPSHOT");
174cac06d4eSTomohiro Kusumi case HAMMER2_PFSSUBTYPE_AUTOSNAP:
175cac06d4eSTomohiro Kusumi return("AUTOSNAP");
176cac06d4eSTomohiro Kusumi default:
177cac06d4eSTomohiro Kusumi return("ILLEGAL");
178cac06d4eSTomohiro Kusumi }
179cac06d4eSTomohiro Kusumi }
180cac06d4eSTomohiro Kusumi
181cac06d4eSTomohiro Kusumi const char *
hammer2_breftype_to_str(uint8_t type)18294a97128STomohiro Kusumi hammer2_breftype_to_str(uint8_t type)
18394a97128STomohiro Kusumi {
18494a97128STomohiro Kusumi switch(type) {
18594a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_EMPTY:
18694a97128STomohiro Kusumi return("empty");
18794a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_INODE:
18894a97128STomohiro Kusumi return("inode");
18994a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_INDIRECT:
19094a97128STomohiro Kusumi return("indirect");
19194a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_DATA:
19294a97128STomohiro Kusumi return("data");
19394a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_DIRENT:
19494a97128STomohiro Kusumi return("dirent");
19594a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_FREEMAP_NODE:
19694a97128STomohiro Kusumi return("freemap_node");
19794a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_FREEMAP_LEAF:
19894a97128STomohiro Kusumi return("freemap_leaf");
1990b738157STomohiro Kusumi case HAMMER2_BREF_TYPE_INVALID:
2000b738157STomohiro Kusumi return("invalid");
20194a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_FREEMAP:
20294a97128STomohiro Kusumi return("freemap");
20394a97128STomohiro Kusumi case HAMMER2_BREF_TYPE_VOLUME:
20494a97128STomohiro Kusumi return("volume");
20594a97128STomohiro Kusumi default:
20694a97128STomohiro Kusumi return("unknown");
20794a97128STomohiro Kusumi }
20894a97128STomohiro Kusumi }
20994a97128STomohiro Kusumi
21094a97128STomohiro Kusumi const char *
hammer2_compmode_to_str(uint8_t comp_algo)211*2a98b0e0STomohiro Kusumi hammer2_compmode_to_str(uint8_t comp_algo)
212*2a98b0e0STomohiro Kusumi {
213*2a98b0e0STomohiro Kusumi static char buf[64];
214*2a98b0e0STomohiro Kusumi static const char *comps[] = HAMMER2_COMP_STRINGS;
215*2a98b0e0STomohiro Kusumi int comp = HAMMER2_DEC_ALGO(comp_algo);
216*2a98b0e0STomohiro Kusumi int level = HAMMER2_DEC_LEVEL(comp_algo);
217*2a98b0e0STomohiro Kusumi
218*2a98b0e0STomohiro Kusumi if (level) {
219*2a98b0e0STomohiro Kusumi if (comp >= 0 && comp < HAMMER2_COMP_STRINGS_COUNT)
220*2a98b0e0STomohiro Kusumi snprintf(buf, sizeof(buf), "%s:%d",
221*2a98b0e0STomohiro Kusumi comps[comp], level);
222*2a98b0e0STomohiro Kusumi else
223*2a98b0e0STomohiro Kusumi snprintf(buf, sizeof(buf), "unknown(%d):%d",
224*2a98b0e0STomohiro Kusumi comp, level);
225*2a98b0e0STomohiro Kusumi } else {
226*2a98b0e0STomohiro Kusumi if (comp >= 0 && comp < HAMMER2_COMP_STRINGS_COUNT)
227*2a98b0e0STomohiro Kusumi snprintf(buf, sizeof(buf), "%s:default",
228*2a98b0e0STomohiro Kusumi comps[comp]);
229*2a98b0e0STomohiro Kusumi else
230*2a98b0e0STomohiro Kusumi snprintf(buf, sizeof(buf), "unknown(%d):default",
231*2a98b0e0STomohiro Kusumi comp);
232*2a98b0e0STomohiro Kusumi }
233*2a98b0e0STomohiro Kusumi return (buf);
234*2a98b0e0STomohiro Kusumi }
235*2a98b0e0STomohiro Kusumi
236*2a98b0e0STomohiro Kusumi const char *
hammer2_checkmode_to_str(uint8_t check_algo)237*2a98b0e0STomohiro Kusumi hammer2_checkmode_to_str(uint8_t check_algo)
238*2a98b0e0STomohiro Kusumi {
239*2a98b0e0STomohiro Kusumi static char buf[64];
240*2a98b0e0STomohiro Kusumi static const char *checks[] = HAMMER2_CHECK_STRINGS;
241*2a98b0e0STomohiro Kusumi int check = HAMMER2_DEC_ALGO(check_algo);
242*2a98b0e0STomohiro Kusumi int level = HAMMER2_DEC_LEVEL(check_algo);
243*2a98b0e0STomohiro Kusumi
244*2a98b0e0STomohiro Kusumi /*
245*2a98b0e0STomohiro Kusumi * NOTE: Check algorithms normally do not encode any level.
246*2a98b0e0STomohiro Kusumi */
247*2a98b0e0STomohiro Kusumi if (level) {
248*2a98b0e0STomohiro Kusumi if (check >= 0 && check < HAMMER2_CHECK_STRINGS_COUNT)
249*2a98b0e0STomohiro Kusumi snprintf(buf, sizeof(buf), "%s:%d",
250*2a98b0e0STomohiro Kusumi checks[check], level);
251*2a98b0e0STomohiro Kusumi else
252*2a98b0e0STomohiro Kusumi snprintf(buf, sizeof(buf), "unknown(%d):%d",
253*2a98b0e0STomohiro Kusumi check, level);
254*2a98b0e0STomohiro Kusumi } else {
255*2a98b0e0STomohiro Kusumi if (check >= 0 && check < HAMMER2_CHECK_STRINGS_COUNT)
256*2a98b0e0STomohiro Kusumi snprintf(buf, sizeof(buf), "%s", checks[check]);
257*2a98b0e0STomohiro Kusumi else
258*2a98b0e0STomohiro Kusumi snprintf(buf, sizeof(buf), "unknown(%d)", check);
259*2a98b0e0STomohiro Kusumi }
260*2a98b0e0STomohiro Kusumi return (buf);
261*2a98b0e0STomohiro Kusumi }
262*2a98b0e0STomohiro Kusumi
263*2a98b0e0STomohiro Kusumi const char *
sizetostr(hammer2_off_t size)264ad7cf8eaSMatthew Dillon sizetostr(hammer2_off_t size)
265ad7cf8eaSMatthew Dillon {
266ad7cf8eaSMatthew Dillon static char buf[32];
267ad7cf8eaSMatthew Dillon
268ad7cf8eaSMatthew Dillon if (size < 1024 / 2) {
2691c90b351STomohiro Kusumi snprintf(buf, sizeof(buf), "%6.2fB", (double)size);
270ad7cf8eaSMatthew Dillon } else if (size < 1024 * 1024 / 2) {
271ad7cf8eaSMatthew Dillon snprintf(buf, sizeof(buf), "%6.2fKB",
272ad7cf8eaSMatthew Dillon (double)size / 1024);
273ad7cf8eaSMatthew Dillon } else if (size < 1024 * 1024 * 1024LL / 2) {
274ad7cf8eaSMatthew Dillon snprintf(buf, sizeof(buf), "%6.2fMB",
275ad7cf8eaSMatthew Dillon (double)size / (1024 * 1024));
276ad7cf8eaSMatthew Dillon } else if (size < 1024 * 1024 * 1024LL * 1024LL / 2) {
277ad7cf8eaSMatthew Dillon snprintf(buf, sizeof(buf), "%6.2fGB",
278ad7cf8eaSMatthew Dillon (double)size / (1024 * 1024 * 1024LL));
279ad7cf8eaSMatthew Dillon } else {
280ad7cf8eaSMatthew Dillon snprintf(buf, sizeof(buf), "%6.2fTB",
281ad7cf8eaSMatthew Dillon (double)size / (1024 * 1024 * 1024LL * 1024LL));
282ad7cf8eaSMatthew Dillon }
283ad7cf8eaSMatthew Dillon return(buf);
284ad7cf8eaSMatthew Dillon }
2858c280d5dSMatthew Dillon
2868b903fd1SMatthew Dillon const char *
counttostr(hammer2_off_t size)2878b903fd1SMatthew Dillon counttostr(hammer2_off_t size)
2888b903fd1SMatthew Dillon {
2898b903fd1SMatthew Dillon static char buf[32];
2908b903fd1SMatthew Dillon
2918b903fd1SMatthew Dillon if (size < 1024 / 2) {
2928b903fd1SMatthew Dillon snprintf(buf, sizeof(buf), "%jd",
2938b903fd1SMatthew Dillon (intmax_t)size);
2948b903fd1SMatthew Dillon } else if (size < 1024 * 1024 / 2) {
2958b903fd1SMatthew Dillon snprintf(buf, sizeof(buf), "%jd",
2968b903fd1SMatthew Dillon (intmax_t)size);
2978b903fd1SMatthew Dillon } else if (size < 1024 * 1024 * 1024LL / 2) {
2988b903fd1SMatthew Dillon snprintf(buf, sizeof(buf), "%6.2fM",
2998b903fd1SMatthew Dillon (double)size / (1024 * 1024));
3008b903fd1SMatthew Dillon } else if (size < 1024 * 1024 * 1024LL * 1024LL / 2) {
3018b903fd1SMatthew Dillon snprintf(buf, sizeof(buf), "%6.2fG",
3028b903fd1SMatthew Dillon (double)(size / (1024 * 1024 * 1024LL)));
3038b903fd1SMatthew Dillon } else {
3048b903fd1SMatthew Dillon snprintf(buf, sizeof(buf), "%6.2fT",
3058b903fd1SMatthew Dillon (double)(size / (1024 * 1024 * 1024LL * 1024LL)));
3068b903fd1SMatthew Dillon }
3078b903fd1SMatthew Dillon return(buf);
3088b903fd1SMatthew Dillon }
3098b903fd1SMatthew Dillon
3100b738157STomohiro Kusumi hammer2_off_t
check_volume(int fd)3110b738157STomohiro Kusumi check_volume(int fd)
3120b738157STomohiro Kusumi {
3130b738157STomohiro Kusumi struct partinfo pinfo;
3140b738157STomohiro Kusumi struct stat st;
3150b738157STomohiro Kusumi hammer2_off_t size;
3160b738157STomohiro Kusumi
3170b738157STomohiro Kusumi /*
3180b738157STomohiro Kusumi * Get basic information about the volume
3190b738157STomohiro Kusumi */
3200b738157STomohiro Kusumi if (ioctl(fd, DIOCGPART, &pinfo) < 0) {
3210b738157STomohiro Kusumi /*
3220b738157STomohiro Kusumi * Allow the formatting of regular files as HAMMER2 volumes
3230b738157STomohiro Kusumi */
3240b738157STomohiro Kusumi if (fstat(fd, &st) < 0)
3250b738157STomohiro Kusumi err(1, "Unable to stat fd %d", fd);
3260b738157STomohiro Kusumi if (!S_ISREG(st.st_mode))
3270b738157STomohiro Kusumi errx(1, "Unsupported file type for fd %d", fd);
3280b738157STomohiro Kusumi size = st.st_size;
3290b738157STomohiro Kusumi } else {
3300b738157STomohiro Kusumi /*
3310b738157STomohiro Kusumi * When formatting a block device as a HAMMER2 volume the
3320b738157STomohiro Kusumi * sector size must be compatible. HAMMER2 uses 64K
3330b738157STomohiro Kusumi * filesystem buffers but logical buffers for direct I/O
3340b738157STomohiro Kusumi * can be as small as HAMMER2_LOGSIZE (16KB).
3350b738157STomohiro Kusumi */
3360b738157STomohiro Kusumi if (pinfo.reserved_blocks) {
3370b738157STomohiro Kusumi errx(1, "HAMMER2 cannot be placed in a partition "
3380b738157STomohiro Kusumi "which overlaps the disklabel or MBR");
3390b738157STomohiro Kusumi }
3400b738157STomohiro Kusumi if (pinfo.media_blksize > HAMMER2_PBUFSIZE ||
3410b738157STomohiro Kusumi HAMMER2_PBUFSIZE % pinfo.media_blksize) {
3420b738157STomohiro Kusumi errx(1, "A media sector size of %d is not supported",
3430b738157STomohiro Kusumi pinfo.media_blksize);
3440b738157STomohiro Kusumi }
3450b738157STomohiro Kusumi size = pinfo.media_size;
3460b738157STomohiro Kusumi }
3470b738157STomohiro Kusumi return(size);
3480b738157STomohiro Kusumi }
3490b738157STomohiro Kusumi
3505914303aSTomohiro Kusumi /*
3515914303aSTomohiro Kusumi * Borrow HAMMER1's directory hash algorithm #1 with a few modifications.
3525914303aSTomohiro Kusumi * The filename is split into fields which are hashed separately and then
3535914303aSTomohiro Kusumi * added together.
3545914303aSTomohiro Kusumi *
3555914303aSTomohiro Kusumi * Differences include: bit 63 must be set to 1 for HAMMER2 (HAMMER1 sets
3565914303aSTomohiro Kusumi * it to 0), this is because bit63=0 is used for hidden hardlinked inodes.
3575914303aSTomohiro Kusumi * (This means we do not need to do a 0-check/or-with-0x100000000 either).
3585914303aSTomohiro Kusumi *
3595914303aSTomohiro Kusumi * Also, the iscsi crc code is used instead of the old crc32 code.
3605914303aSTomohiro Kusumi */
361775153c2SMatthew Dillon hammer2_key_t
dirhash(const char * aname,size_t len)3621d5238a4STomohiro Kusumi dirhash(const char *aname, size_t len)
363775153c2SMatthew Dillon {
364775153c2SMatthew Dillon uint32_t crcx;
365775153c2SMatthew Dillon uint64_t key;
366775153c2SMatthew Dillon size_t i;
367775153c2SMatthew Dillon size_t j;
368775153c2SMatthew Dillon
369775153c2SMatthew Dillon key = 0;
370775153c2SMatthew Dillon
371775153c2SMatthew Dillon /*
372775153c2SMatthew Dillon * m32
373775153c2SMatthew Dillon */
374775153c2SMatthew Dillon crcx = 0;
375775153c2SMatthew Dillon for (i = j = 0; i < len; ++i) {
376775153c2SMatthew Dillon if (aname[i] == '.' ||
377775153c2SMatthew Dillon aname[i] == '-' ||
378775153c2SMatthew Dillon aname[i] == '_' ||
379775153c2SMatthew Dillon aname[i] == '~') {
380775153c2SMatthew Dillon if (i != j)
381775153c2SMatthew Dillon crcx += hammer2_icrc32(aname + j, i - j);
382775153c2SMatthew Dillon j = i + 1;
383775153c2SMatthew Dillon }
384775153c2SMatthew Dillon }
385775153c2SMatthew Dillon if (i != j)
386775153c2SMatthew Dillon crcx += hammer2_icrc32(aname + j, i - j);
387775153c2SMatthew Dillon
388775153c2SMatthew Dillon /*
389775153c2SMatthew Dillon * The directory hash utilizes the top 32 bits of the 64-bit key.
390775153c2SMatthew Dillon * Bit 63 must be set to 1.
391775153c2SMatthew Dillon */
392775153c2SMatthew Dillon crcx |= 0x80000000U;
393775153c2SMatthew Dillon key |= (uint64_t)crcx << 32;
394775153c2SMatthew Dillon
395775153c2SMatthew Dillon /*
396775153c2SMatthew Dillon * l16 - crc of entire filename
397775153c2SMatthew Dillon *
398bc7ea12eSTomohiro Kusumi * This crc reduces degenerate hash collision conditions.
399775153c2SMatthew Dillon */
400775153c2SMatthew Dillon crcx = hammer2_icrc32(aname, len);
401775153c2SMatthew Dillon crcx = crcx ^ (crcx << 16);
402775153c2SMatthew Dillon key |= crcx & 0xFFFF0000U;
403775153c2SMatthew Dillon
404775153c2SMatthew Dillon /*
405775153c2SMatthew Dillon * Set bit 15. This allows readdir to strip bit 63 so a positive
406775153c2SMatthew Dillon * 64-bit cookie/offset can always be returned, and still guarantee
407775153c2SMatthew Dillon * that the values 0x0000-0x7FFF are available for artificial entries.
408775153c2SMatthew Dillon * ('.' and '..').
409775153c2SMatthew Dillon */
410775153c2SMatthew Dillon key |= 0x8000U;
411775153c2SMatthew Dillon
412775153c2SMatthew Dillon return (key);
413775153c2SMatthew Dillon }
41483d90983SMatthew Dillon
41583d90983SMatthew Dillon char **
get_hammer2_mounts(int * acp)41683d90983SMatthew Dillon get_hammer2_mounts(int *acp)
41783d90983SMatthew Dillon {
41883d90983SMatthew Dillon struct statfs *fs;
41983d90983SMatthew Dillon char **av;
42083d90983SMatthew Dillon int n;
42183d90983SMatthew Dillon int w;
42283d90983SMatthew Dillon int i;
42383d90983SMatthew Dillon
42483d90983SMatthew Dillon /*
42583d90983SMatthew Dillon * Get a stable list of mount points
42683d90983SMatthew Dillon */
42783d90983SMatthew Dillon again:
42883d90983SMatthew Dillon n = getfsstat(NULL, 0, MNT_NOWAIT);
4290966406fSTomohiro Kusumi av = calloc(n, sizeof(char *));
4309bd042a9STomohiro Kusumi fs = calloc(n, sizeof(struct statfs));
43183d90983SMatthew Dillon if (getfsstat(fs, sizeof(*fs) * n, MNT_NOWAIT) != n) {
43283d90983SMatthew Dillon free(av);
43383d90983SMatthew Dillon free(fs);
43483d90983SMatthew Dillon goto again;
43583d90983SMatthew Dillon }
43683d90983SMatthew Dillon
43783d90983SMatthew Dillon /*
43883d90983SMatthew Dillon * Pull out hammer2 filesystems only
43983d90983SMatthew Dillon */
44083d90983SMatthew Dillon for (i = w = 0; i < n; ++i) {
44183d90983SMatthew Dillon if (strcmp(fs[i].f_fstypename, "hammer2") != 0)
44283d90983SMatthew Dillon continue;
44383d90983SMatthew Dillon av[w++] = strdup(fs[i].f_mntonname);
44483d90983SMatthew Dillon }
44583d90983SMatthew Dillon *acp = w;
4460966406fSTomohiro Kusumi free(fs);
44783d90983SMatthew Dillon
44883d90983SMatthew Dillon return av;
44983d90983SMatthew Dillon }
45083d90983SMatthew Dillon
45183d90983SMatthew Dillon void
put_hammer2_mounts(int ac,char ** av)45283d90983SMatthew Dillon put_hammer2_mounts(int ac, char **av)
45383d90983SMatthew Dillon {
45483d90983SMatthew Dillon while (--ac >= 0)
45583d90983SMatthew Dillon free(av[ac]);
45683d90983SMatthew Dillon free(av);
45783d90983SMatthew Dillon }
458