xref: /dragonfly/sbin/hammer2/subs.c (revision 2a98b0e0)
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