xref: /dragonfly/sys/vfs/hammer2/hammer2_subr.c (revision a552887f)
1e118c14fSMatthew Dillon /*
268b321c1SMatthew Dillon  * Copyright (c) 2011-2018 The DragonFly Project.  All rights reserved.
3e118c14fSMatthew Dillon  *
4e118c14fSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5e118c14fSMatthew Dillon  * by Matthew Dillon <dillon@dragonflybsd.org>
6e118c14fSMatthew Dillon  * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7e118c14fSMatthew Dillon  *
8e118c14fSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
9e118c14fSMatthew Dillon  * modification, are permitted provided that the following conditions
10e118c14fSMatthew Dillon  * are met:
11e118c14fSMatthew Dillon  *
12e118c14fSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
13e118c14fSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
14e118c14fSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
15e118c14fSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
16e118c14fSMatthew Dillon  *    the documentation and/or other materials provided with the
17e118c14fSMatthew Dillon  *    distribution.
18e118c14fSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
19e118c14fSMatthew Dillon  *    contributors may be used to endorse or promote products derived
20e118c14fSMatthew Dillon  *    from this software without specific, prior written permission.
21e118c14fSMatthew Dillon  *
22e118c14fSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23e118c14fSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24e118c14fSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25e118c14fSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
26e118c14fSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27e118c14fSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28e118c14fSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29e118c14fSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30e118c14fSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31e118c14fSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32e118c14fSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33e118c14fSMatthew Dillon  * SUCH DAMAGE.
34e118c14fSMatthew Dillon  */
35703720e4SMatthew Dillon #include <sys/cdefs.h>
36703720e4SMatthew Dillon #include <sys/param.h>
37703720e4SMatthew Dillon #include <sys/systm.h>
38703720e4SMatthew Dillon #include <sys/types.h>
39703720e4SMatthew Dillon #include <sys/lock.h>
40703720e4SMatthew Dillon #include <sys/uuid.h>
41e028fa74SMatthew Dillon #include <sys/dirent.h>
42703720e4SMatthew Dillon 
43703720e4SMatthew Dillon #include "hammer2.h"
44703720e4SMatthew Dillon 
45703720e4SMatthew Dillon /*
46703720e4SMatthew Dillon  * Mount-wide locks
47703720e4SMatthew Dillon  */
48703720e4SMatthew Dillon void
49506bd6d1SMatthew Dillon hammer2_dev_exlock(hammer2_dev_t *hmp)
50703720e4SMatthew Dillon {
51f1c7c224SMatthew Dillon 	hammer2_mtx_ex(&hmp->vchain.lock);
52703720e4SMatthew Dillon }
53703720e4SMatthew Dillon 
54703720e4SMatthew Dillon void
55506bd6d1SMatthew Dillon hammer2_dev_shlock(hammer2_dev_t *hmp)
56703720e4SMatthew Dillon {
57f1c7c224SMatthew Dillon 	hammer2_mtx_sh(&hmp->vchain.lock);
58703720e4SMatthew Dillon }
59703720e4SMatthew Dillon 
60703720e4SMatthew Dillon void
61506bd6d1SMatthew Dillon hammer2_dev_unlock(hammer2_dev_t *hmp)
62703720e4SMatthew Dillon {
63f1c7c224SMatthew Dillon 	hammer2_mtx_unlock(&hmp->vchain.lock);
64703720e4SMatthew Dillon }
65703720e4SMatthew Dillon 
66703720e4SMatthew Dillon /*
67476d2aadSMatthew Dillon  * Return the directory entry type for an inode.
68476d2aadSMatthew Dillon  *
69476d2aadSMatthew Dillon  * ip must be locked sh/ex.
70e028fa74SMatthew Dillon  */
71e028fa74SMatthew Dillon int
72da0cdd33SMatthew Dillon hammer2_get_dtype(uint8_t type)
73e028fa74SMatthew Dillon {
7499535653SMatthew Dillon 	switch(type) {
75e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_UNKNOWN:
76e028fa74SMatthew Dillon 		return (DT_UNKNOWN);
77e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_DIRECTORY:
78e028fa74SMatthew Dillon 		return (DT_DIR);
79e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_REGFILE:
80e028fa74SMatthew Dillon 		return (DT_REG);
81e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_FIFO:
82e028fa74SMatthew Dillon 		return (DT_FIFO);
83e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_CDEV:	/* not supported */
84e028fa74SMatthew Dillon 		return (DT_CHR);
85e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_BDEV:	/* not supported */
86e028fa74SMatthew Dillon 		return (DT_BLK);
87e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_SOFTLINK:
88e028fa74SMatthew Dillon 		return (DT_LNK);
89e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_SOCKET:
90e028fa74SMatthew Dillon 		return (DT_SOCK);
91e028fa74SMatthew Dillon 	case HAMMER2_OBJTYPE_WHITEOUT:	/* not supported */
92e028fa74SMatthew Dillon 		return (DT_UNKNOWN);
93e028fa74SMatthew Dillon 	default:
94e028fa74SMatthew Dillon 		return (DT_UNKNOWN);
95e028fa74SMatthew Dillon 	}
96e028fa74SMatthew Dillon 	/* not reached */
97e028fa74SMatthew Dillon }
98e028fa74SMatthew Dillon 
99cd4b3d92SMatthew Dillon /*
100cd4b3d92SMatthew Dillon  * Return the directory entry type for an inode
101cd4b3d92SMatthew Dillon  */
102cd4b3d92SMatthew Dillon int
103159c3ca2SMatthew Dillon hammer2_get_vtype(uint8_t type)
104cd4b3d92SMatthew Dillon {
105159c3ca2SMatthew Dillon 	switch(type) {
106cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_UNKNOWN:
107cd4b3d92SMatthew Dillon 		return (VBAD);
108cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_DIRECTORY:
109cd4b3d92SMatthew Dillon 		return (VDIR);
110cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_REGFILE:
111cd4b3d92SMatthew Dillon 		return (VREG);
112cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_FIFO:
113cd4b3d92SMatthew Dillon 		return (VFIFO);
114cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_CDEV:	/* not supported */
115cd4b3d92SMatthew Dillon 		return (VCHR);
116cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_BDEV:	/* not supported */
117cd4b3d92SMatthew Dillon 		return (VBLK);
118cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_SOFTLINK:
119cd4b3d92SMatthew Dillon 		return (VLNK);
120cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_SOCKET:
121cd4b3d92SMatthew Dillon 		return (VSOCK);
122cd4b3d92SMatthew Dillon 	case HAMMER2_OBJTYPE_WHITEOUT:	/* not supported */
123cd4b3d92SMatthew Dillon 		return (DT_UNKNOWN);
124cd4b3d92SMatthew Dillon 	default:
125cd4b3d92SMatthew Dillon 		return (DT_UNKNOWN);
126cd4b3d92SMatthew Dillon 	}
127cd4b3d92SMatthew Dillon 	/* not reached */
128cd4b3d92SMatthew Dillon }
129cd4b3d92SMatthew Dillon 
1302f70512bSTomohiro Kusumi uint8_t
13137494cabSMatthew Dillon hammer2_get_obj_type(enum vtype vtype)
13237494cabSMatthew Dillon {
13337494cabSMatthew Dillon 	switch(vtype) {
13437494cabSMatthew Dillon 	case VDIR:
13537494cabSMatthew Dillon 		return(HAMMER2_OBJTYPE_DIRECTORY);
13637494cabSMatthew Dillon 	case VREG:
13737494cabSMatthew Dillon 		return(HAMMER2_OBJTYPE_REGFILE);
13837494cabSMatthew Dillon 	case VFIFO:
13937494cabSMatthew Dillon 		return(HAMMER2_OBJTYPE_FIFO);
14037494cabSMatthew Dillon 	case VSOCK:
14137494cabSMatthew Dillon 		return(HAMMER2_OBJTYPE_SOCKET);
14237494cabSMatthew Dillon 	case VCHR:
14337494cabSMatthew Dillon 		return(HAMMER2_OBJTYPE_CDEV);
14437494cabSMatthew Dillon 	case VBLK:
14537494cabSMatthew Dillon 		return(HAMMER2_OBJTYPE_BDEV);
14637494cabSMatthew Dillon 	case VLNK:
14737494cabSMatthew Dillon 		return(HAMMER2_OBJTYPE_SOFTLINK);
14837494cabSMatthew Dillon 	default:
14937494cabSMatthew Dillon 		return(HAMMER2_OBJTYPE_UNKNOWN);
15037494cabSMatthew Dillon 	}
15137494cabSMatthew Dillon 	/* not reached */
15237494cabSMatthew Dillon }
15337494cabSMatthew Dillon 
154cd4b3d92SMatthew Dillon /*
155cd4b3d92SMatthew Dillon  * Convert a hammer2 64-bit time to a timespec.
156cd4b3d92SMatthew Dillon  */
157cd4b3d92SMatthew Dillon void
1582f70512bSTomohiro Kusumi hammer2_time_to_timespec(uint64_t xtime, struct timespec *ts)
159cd4b3d92SMatthew Dillon {
160cd4b3d92SMatthew Dillon 	ts->tv_sec = (unsigned long)(xtime / 1000000);
161cd4b3d92SMatthew Dillon 	ts->tv_nsec = (unsigned int)(xtime % 1000000) * 1000L;
162cd4b3d92SMatthew Dillon }
163cd4b3d92SMatthew Dillon 
1642f70512bSTomohiro Kusumi uint64_t
1656a5f4fe6SMatthew Dillon hammer2_timespec_to_time(const struct timespec *ts)
166b2b78aaaSMatthew Dillon {
1672f70512bSTomohiro Kusumi 	uint64_t xtime;
168b2b78aaaSMatthew Dillon 
169b2b78aaaSMatthew Dillon 	xtime = (unsigned)(ts->tv_nsec / 1000) +
170b2b78aaaSMatthew Dillon 		(unsigned long)ts->tv_sec * 1000000ULL;
171b2b78aaaSMatthew Dillon 	return(xtime);
172b2b78aaaSMatthew Dillon }
173b2b78aaaSMatthew Dillon 
17437494cabSMatthew Dillon /*
17537494cabSMatthew Dillon  * Convert a uuid to a unix uid or gid
17637494cabSMatthew Dillon  */
1772f70512bSTomohiro Kusumi uint32_t
1786a5f4fe6SMatthew Dillon hammer2_to_unix_xid(const uuid_t *uuid)
17937494cabSMatthew Dillon {
1802f70512bSTomohiro Kusumi 	return(*(const uint32_t *)&uuid->node[2]);
18137494cabSMatthew Dillon }
182e028fa74SMatthew Dillon 
183b2b78aaaSMatthew Dillon void
1842f70512bSTomohiro Kusumi hammer2_guid_to_uuid(uuid_t *uuid, uint32_t guid)
185b2b78aaaSMatthew Dillon {
186b2b78aaaSMatthew Dillon 	bzero(uuid, sizeof(*uuid));
1872f70512bSTomohiro Kusumi 	*(uint32_t *)&uuid->node[2] = guid;
188b2b78aaaSMatthew Dillon }
189b2b78aaaSMatthew Dillon 
190e028fa74SMatthew Dillon /*
19150e4f8f4SMatthew Dillon  * Borrow HAMMER1's directory hash algorithm #1 with a few modifications.
19250e4f8f4SMatthew Dillon  * The filename is split into fields which are hashed separately and then
19350e4f8f4SMatthew Dillon  * added together.
19450e4f8f4SMatthew Dillon  *
19550e4f8f4SMatthew Dillon  * Differences include: bit 63 must be set to 1 for HAMMER2 (HAMMER1 sets
19650e4f8f4SMatthew Dillon  * it to 0), this is because bit63=0 is used for hidden hardlinked inodes.
19750e4f8f4SMatthew Dillon  * (This means we do not need to do a 0-check/or-with-0x100000000 either).
19850e4f8f4SMatthew Dillon  *
19950e4f8f4SMatthew Dillon  * Also, the iscsi crc code is used instead of the old crc32 code.
20050e4f8f4SMatthew Dillon  */
20150e4f8f4SMatthew Dillon hammer2_key_t
20250e4f8f4SMatthew Dillon hammer2_dirhash(const unsigned char *name, size_t len)
20350e4f8f4SMatthew Dillon {
20450e4f8f4SMatthew Dillon 	const unsigned char *aname = name;
20550e4f8f4SMatthew Dillon 	uint32_t crcx;
20650e4f8f4SMatthew Dillon 	uint64_t key;
20750e4f8f4SMatthew Dillon 	size_t i;
20850e4f8f4SMatthew Dillon 	size_t j;
20950e4f8f4SMatthew Dillon 
21050e4f8f4SMatthew Dillon 	key = 0;
21150e4f8f4SMatthew Dillon 
21250e4f8f4SMatthew Dillon 	/*
21350e4f8f4SMatthew Dillon 	 * m32
21450e4f8f4SMatthew Dillon 	 */
21550e4f8f4SMatthew Dillon 	crcx = 0;
21650e4f8f4SMatthew Dillon 	for (i = j = 0; i < len; ++i) {
21750e4f8f4SMatthew Dillon 		if (aname[i] == '.' ||
21850e4f8f4SMatthew Dillon 		    aname[i] == '-' ||
21950e4f8f4SMatthew Dillon 		    aname[i] == '_' ||
22050e4f8f4SMatthew Dillon 		    aname[i] == '~') {
22150e4f8f4SMatthew Dillon 			if (i != j)
22250e4f8f4SMatthew Dillon 				crcx += hammer2_icrc32(aname + j, i - j);
22350e4f8f4SMatthew Dillon 			j = i + 1;
22450e4f8f4SMatthew Dillon 		}
22550e4f8f4SMatthew Dillon 	}
22650e4f8f4SMatthew Dillon 	if (i != j)
22750e4f8f4SMatthew Dillon 		crcx += hammer2_icrc32(aname + j, i - j);
22850e4f8f4SMatthew Dillon 
22950e4f8f4SMatthew Dillon 	/*
23050e4f8f4SMatthew Dillon 	 * The directory hash utilizes the top 32 bits of the 64-bit key.
23150e4f8f4SMatthew Dillon 	 * Bit 63 must be set to 1.
23250e4f8f4SMatthew Dillon 	 */
23350e4f8f4SMatthew Dillon 	crcx |= 0x80000000U;
23450e4f8f4SMatthew Dillon 	key |= (uint64_t)crcx << 32;
23550e4f8f4SMatthew Dillon 
23650e4f8f4SMatthew Dillon 	/*
23750e4f8f4SMatthew Dillon 	 * l16 - crc of entire filename
23850e4f8f4SMatthew Dillon 	 *
23950e4f8f4SMatthew Dillon 	 * This crc reduces degenerate hash collision conditions
24050e4f8f4SMatthew Dillon 	 */
24150e4f8f4SMatthew Dillon 	crcx = hammer2_icrc32(aname, len);
24250e4f8f4SMatthew Dillon 	crcx = crcx ^ (crcx << 16);
24350e4f8f4SMatthew Dillon 	key |= crcx & 0xFFFF0000U;
24450e4f8f4SMatthew Dillon 
245e028fa74SMatthew Dillon 	/*
246e028fa74SMatthew Dillon 	 * Set bit 15.  This allows readdir to strip bit 63 so a positive
247e028fa74SMatthew Dillon 	 * 64-bit cookie/offset can always be returned, and still guarantee
248e028fa74SMatthew Dillon 	 * that the values 0x0000-0x7FFF are available for artificial entries.
249e028fa74SMatthew Dillon 	 * ('.' and '..').
250e028fa74SMatthew Dillon 	 */
251e028fa74SMatthew Dillon 	key |= 0x8000U;
252e028fa74SMatthew Dillon 
25350e4f8f4SMatthew Dillon 	return (key);
25450e4f8f4SMatthew Dillon }
2556ba3b984SMatthew Dillon 
2561a7cfe5aSMatthew Dillon /*
257da0cdd33SMatthew Dillon  * Convert bytes to radix with no limitations.
258da0cdd33SMatthew Dillon  *
259da0cdd33SMatthew Dillon  * 0 bytes is special-cased to a radix of zero (which would normally
260da0cdd33SMatthew Dillon  * translate to (1 << 0) == 1).
2611a7cfe5aSMatthew Dillon  */
2621a7cfe5aSMatthew Dillon int
2631a7cfe5aSMatthew Dillon hammer2_getradix(size_t bytes)
2641a7cfe5aSMatthew Dillon {
2651a7cfe5aSMatthew Dillon 	int radix;
2661a7cfe5aSMatthew Dillon 
267da0cdd33SMatthew Dillon 	/*
268da0cdd33SMatthew Dillon 	 * Optimize the iteration by pre-checking commonly used radii.
269da0cdd33SMatthew Dillon 	 */
2701a7cfe5aSMatthew Dillon 	if (bytes == HAMMER2_PBUFSIZE)
2711a7cfe5aSMatthew Dillon 		radix = HAMMER2_PBUFRADIX;
27293f3933aSMatthew Dillon 	else if (bytes >= HAMMER2_LBUFSIZE)
27393f3933aSMatthew Dillon 		radix = HAMMER2_LBUFRADIX;
27450456506SMatthew Dillon 	else if (bytes >= HAMMER2_ALLOC_MIN)	/* clamp */
27550456506SMatthew Dillon 		radix = HAMMER2_RADIX_MIN;
2761a7cfe5aSMatthew Dillon 	else
2771a7cfe5aSMatthew Dillon 		radix = 0;
2781a7cfe5aSMatthew Dillon 
279da0cdd33SMatthew Dillon 	/*
280da0cdd33SMatthew Dillon 	 * Iterate as needed.  Note that bytes == 0 is expected to return
281da0cdd33SMatthew Dillon 	 * a radix of 0 as a special case.
282da0cdd33SMatthew Dillon 	 */
2831a7cfe5aSMatthew Dillon 	while (((size_t)1 << radix) < bytes)
2841a7cfe5aSMatthew Dillon 		++radix;
2851a7cfe5aSMatthew Dillon 	return (radix);
2861a7cfe5aSMatthew Dillon }
2871a7cfe5aSMatthew Dillon 
288476d2aadSMatthew Dillon /*
2897a9b14a0SMatthew Dillon  * The logical block size is currently always PBUFSIZE.
290476d2aadSMatthew Dillon  */
2918cce658dSMatthew Dillon int
2928cce658dSMatthew Dillon hammer2_calc_logical(hammer2_inode_t *ip, hammer2_off_t uoff,
2938cce658dSMatthew Dillon 		     hammer2_key_t *lbasep, hammer2_key_t *leofp)
2948cce658dSMatthew Dillon {
2957a9b14a0SMatthew Dillon 	KKASSERT(ip->flags & HAMMER2_INODE_METAGOOD);
296355d67fcSMatthew Dillon 	if (lbasep)
297355d67fcSMatthew Dillon 		*lbasep = uoff & ~HAMMER2_PBUFMASK64;
298355d67fcSMatthew Dillon 	if (leofp) {
2997a9b14a0SMatthew Dillon 		*leofp = (ip->meta.size + HAMMER2_PBUFMASK64) &
300355d67fcSMatthew Dillon 			 ~HAMMER2_PBUFMASK64;
301355d67fcSMatthew Dillon 	}
302355d67fcSMatthew Dillon 	return (HAMMER2_PBUFSIZE);
303355d67fcSMatthew Dillon }
304355d67fcSMatthew Dillon 
305355d67fcSMatthew Dillon /*
306355d67fcSMatthew Dillon  * Calculate the physical block size.  pblksize <= lblksize.  Primarily
307355d67fcSMatthew Dillon  * used to calculate a smaller physical block for the logical block
308355d67fcSMatthew Dillon  * containing the file EOF.
309355d67fcSMatthew Dillon  *
310355d67fcSMatthew Dillon  * Returns 0 if the requested base offset is beyond the file EOF.
311355d67fcSMatthew Dillon  */
312355d67fcSMatthew Dillon int
3137a9b14a0SMatthew Dillon hammer2_calc_physical(hammer2_inode_t *ip, hammer2_key_t lbase)
314355d67fcSMatthew Dillon {
315355d67fcSMatthew Dillon 	int lblksize;
316355d67fcSMatthew Dillon 	int pblksize;
317355d67fcSMatthew Dillon 	int eofbytes;
318355d67fcSMatthew Dillon 
3197a9b14a0SMatthew Dillon 	KKASSERT(ip->flags & HAMMER2_INODE_METAGOOD);
320355d67fcSMatthew Dillon 	lblksize = hammer2_calc_logical(ip, lbase, NULL, NULL);
3217a9b14a0SMatthew Dillon 	if (lbase + lblksize <= ip->meta.size)
322355d67fcSMatthew Dillon 		return (lblksize);
3237a9b14a0SMatthew Dillon 	if (lbase >= ip->meta.size)
324355d67fcSMatthew Dillon 		return (0);
3257a9b14a0SMatthew Dillon 	eofbytes = (int)(ip->meta.size - lbase);
326355d67fcSMatthew Dillon 	pblksize = lblksize;
32750456506SMatthew Dillon 	while (pblksize >= eofbytes && pblksize >= HAMMER2_ALLOC_MIN)
328355d67fcSMatthew Dillon 		pblksize >>= 1;
329355d67fcSMatthew Dillon 	pblksize <<= 1;
330355d67fcSMatthew Dillon 
331355d67fcSMatthew Dillon 	return (pblksize);
3328cce658dSMatthew Dillon }
333b2b78aaaSMatthew Dillon 
334b2b78aaaSMatthew Dillon void
335b2b78aaaSMatthew Dillon hammer2_update_time(uint64_t *timep)
336b2b78aaaSMatthew Dillon {
337d489a79aSMatthew Dillon 	struct timespec ts;
338b2b78aaaSMatthew Dillon 
339d489a79aSMatthew Dillon 	vfs_timestamp(&ts);
340d489a79aSMatthew Dillon 	*timep = (unsigned long)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
341b2b78aaaSMatthew Dillon }
342278ab2b2SMatthew Dillon 
343278ab2b2SMatthew Dillon void
344*a552887fSTomohiro Kusumi hammer2_adjreadcounter(int btype, size_t bytes)
345278ab2b2SMatthew Dillon {
346278ab2b2SMatthew Dillon 	long *counterp;
347278ab2b2SMatthew Dillon 
348*a552887fSTomohiro Kusumi 	switch(btype) {
349278ab2b2SMatthew Dillon 	case HAMMER2_BREF_TYPE_DATA:
350278ab2b2SMatthew Dillon 		counterp = &hammer2_iod_file_read;
351278ab2b2SMatthew Dillon 		break;
352da0cdd33SMatthew Dillon 	case HAMMER2_BREF_TYPE_DIRENT:
353278ab2b2SMatthew Dillon 	case HAMMER2_BREF_TYPE_INODE:
354278ab2b2SMatthew Dillon 		counterp = &hammer2_iod_meta_read;
355278ab2b2SMatthew Dillon 		break;
356278ab2b2SMatthew Dillon 	case HAMMER2_BREF_TYPE_INDIRECT:
357278ab2b2SMatthew Dillon 		counterp = &hammer2_iod_indr_read;
358278ab2b2SMatthew Dillon 		break;
359278ab2b2SMatthew Dillon 	case HAMMER2_BREF_TYPE_FREEMAP_NODE:
360278ab2b2SMatthew Dillon 	case HAMMER2_BREF_TYPE_FREEMAP_LEAF:
361278ab2b2SMatthew Dillon 		counterp = &hammer2_iod_fmap_read;
362278ab2b2SMatthew Dillon 		break;
3631de4fc15STomohiro Kusumi 	case HAMMER2_BREF_TYPE_FREEMAP:
3641de4fc15STomohiro Kusumi 	case HAMMER2_BREF_TYPE_VOLUME:
365278ab2b2SMatthew Dillon 		counterp = &hammer2_iod_volu_read;
366278ab2b2SMatthew Dillon 		break;
3671de4fc15STomohiro Kusumi 	case HAMMER2_BREF_TYPE_EMPTY:
3681de4fc15STomohiro Kusumi 	default:
3691de4fc15STomohiro Kusumi 		return;
370278ab2b2SMatthew Dillon 	}
371278ab2b2SMatthew Dillon 	*counterp += bytes;
372278ab2b2SMatthew Dillon }
373d662271eSMatthew Dillon 
374*a552887fSTomohiro Kusumi void
375*a552887fSTomohiro Kusumi hammer2_adjwritecounter(int btype, size_t bytes)
376*a552887fSTomohiro Kusumi {
377*a552887fSTomohiro Kusumi 	long *counterp;
378*a552887fSTomohiro Kusumi 
379*a552887fSTomohiro Kusumi 	switch(btype) {
380*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_DATA:
381*a552887fSTomohiro Kusumi 		counterp = &hammer2_iod_file_write;
382*a552887fSTomohiro Kusumi 		break;
383*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_DIRENT:
384*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_INODE:
385*a552887fSTomohiro Kusumi 		counterp = &hammer2_iod_meta_write;
386*a552887fSTomohiro Kusumi 		break;
387*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_INDIRECT:
388*a552887fSTomohiro Kusumi 		counterp = &hammer2_iod_indr_write;
389*a552887fSTomohiro Kusumi 		break;
390*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_FREEMAP_NODE:
391*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_FREEMAP_LEAF:
392*a552887fSTomohiro Kusumi 		counterp = &hammer2_iod_fmap_write;
393*a552887fSTomohiro Kusumi 		break;
394*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_FREEMAP:
395*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_VOLUME:
396*a552887fSTomohiro Kusumi 		counterp = &hammer2_iod_volu_write;
397*a552887fSTomohiro Kusumi 		break;
398*a552887fSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_EMPTY:
399*a552887fSTomohiro Kusumi 	default:
400*a552887fSTomohiro Kusumi 		return;
401*a552887fSTomohiro Kusumi 	}
402*a552887fSTomohiro Kusumi 	*counterp += bytes;
403*a552887fSTomohiro Kusumi }
404*a552887fSTomohiro Kusumi 
4059dca9515SMatthew Dillon /*
4069dca9515SMatthew Dillon  * Check for pending signal to allow interruption.  This function will
4079dca9515SMatthew Dillon  * return immediately if the calling thread is a kernel thread and not
4089dca9515SMatthew Dillon  * a user thread.
4099dca9515SMatthew Dillon  */
410d662271eSMatthew Dillon int
411d662271eSMatthew Dillon hammer2_signal_check(time_t *timep)
412d662271eSMatthew Dillon {
4139dca9515SMatthew Dillon 	thread_t td = curthread;
414d662271eSMatthew Dillon 	int error = 0;
415d662271eSMatthew Dillon 
4169dca9515SMatthew Dillon 	if (td->td_lwp) {
417d662271eSMatthew Dillon 		lwkt_user_yield();
418d662271eSMatthew Dillon 		if (*timep != time_second) {
419d662271eSMatthew Dillon 			*timep = time_second;
4202d7e662fSMatthew Dillon 			if (CURSIG_NOBLOCK(curthread->td_lwp) != 0)
4211e2c8208SMatthew Dillon 				error = HAMMER2_ERROR_ABORTED;
422d662271eSMatthew Dillon 		}
4234ff0b408SMatthew Dillon 	} else {
4244ff0b408SMatthew Dillon 		lwkt_yield();
4259dca9515SMatthew Dillon 	}
426d662271eSMatthew Dillon 	return error;
427d662271eSMatthew Dillon }
428b93cc2e0SMatthew Dillon 
429b93cc2e0SMatthew Dillon const char *
430b93cc2e0SMatthew Dillon hammer2_error_str(int error)
431b93cc2e0SMatthew Dillon {
43265cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_EIO)
43365cacacfSMatthew Dillon 		return("I/O Error");
43465cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_CHECK)
43565cacacfSMatthew Dillon 		return("Check Error");
43665cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_INCOMPLETE)
43765cacacfSMatthew Dillon 		return("Cluster Quorum Error");
43865cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_DEPTH)
43965cacacfSMatthew Dillon 		return("Chain Depth Error");
44065cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_BADBREF)
44165cacacfSMatthew Dillon 		return("Bad Blockref Error");
44265cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_ENOSPC)
44365cacacfSMatthew Dillon 		return("No Space on Device");
44465cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_ENOENT)
44565cacacfSMatthew Dillon 		return("Entry Not Found");
44665cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_ENOTEMPTY)
44765cacacfSMatthew Dillon 		return("Directory Not Empty");
44865cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_EAGAIN)
44965cacacfSMatthew Dillon 		return("EAGAIN");
45065cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_ENOTDIR)
45165cacacfSMatthew Dillon 		return("Not a Directory");
45265cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_EISDIR)
45365cacacfSMatthew Dillon 		return("Is a Directory");
45465cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_EINPROGRESS)
45565cacacfSMatthew Dillon 		return("Operation in Progress");
45665cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_ABORTED)
45765cacacfSMatthew Dillon 		return("Operation Aborted");
45865cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_EOF)
45965cacacfSMatthew Dillon 		return("Operation Complete");
46065cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_EINVAL)
46165cacacfSMatthew Dillon 		return("Invalid Operation");
46265cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_EEXIST)
46365cacacfSMatthew Dillon 		return("Object Exists");
46465cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_EDEADLK)
46565cacacfSMatthew Dillon 		return("Deadlock Detected");
46665cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_ESRCH)
46765cacacfSMatthew Dillon 		return("Object Not Found");
46865cacacfSMatthew Dillon 	if (error & HAMMER2_ERROR_ETIMEDOUT)
46965cacacfSMatthew Dillon 		return("Timeout");
47065cacacfSMatthew Dillon 	return("Unknown Error");
471b93cc2e0SMatthew Dillon }
4727ac04587SMatthew Dillon 
4737ac04587SMatthew Dillon const char *
4747ac04587SMatthew Dillon hammer2_bref_type_str(hammer2_blockref_t *bref)
4757ac04587SMatthew Dillon {
4767ac04587SMatthew Dillon 	switch(bref->type) {
4777ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_EMPTY:
4787ac04587SMatthew Dillon 		return("Unknown-zero'd field");
4797ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_INODE:
4807ac04587SMatthew Dillon 		return("Inode");
4817ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_INDIRECT:
4827ac04587SMatthew Dillon 		return("Indirect-Block");
4837ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_DATA:
4847ac04587SMatthew Dillon 		return("Data-Block");
4857ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_DIRENT:
4867ac04587SMatthew Dillon 		return("Directory-Entry");
4877ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_FREEMAP_NODE:
4887ac04587SMatthew Dillon 		return("Freemap-Node");
4897ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_FREEMAP_LEAF:
4907ac04587SMatthew Dillon 		return("Freemap-Leaf");
4917ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_FREEMAP:
4927ac04587SMatthew Dillon 		return("Freemap-Header");
4937ac04587SMatthew Dillon 	case HAMMER2_BREF_TYPE_VOLUME:
4947ac04587SMatthew Dillon 		return("Volume-Header");
4957ac04587SMatthew Dillon 	default:
4967ac04587SMatthew Dillon 		break;
4977ac04587SMatthew Dillon 	}
4987ac04587SMatthew Dillon 	return("Unknown");
4997ac04587SMatthew Dillon }
500