2 * Copyright (c) 2011-2014 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/types.h>
41 #include <sys/dirent.h>
49 hammer2_dev_exlock(hammer2_dev_t
*hmp
)
51 hammer2_mtx_ex(&hmp
->vchain
.lock
);
55 hammer2_dev_shlock(hammer2_dev_t
*hmp
)
57 hammer2_mtx_sh(&hmp
->vchain
.lock
);
61 hammer2_dev_unlock(hammer2_dev_t
*hmp
)
63 hammer2_mtx_unlock(&hmp
->vchain
.lock
);
67 * Return the directory entry type for an inode.
69 * ip must be locked sh/ex.
72 hammer2_get_dtype(const hammer2_inode_data_t
*ipdata
)
76 if ((type
= ipdata
->meta
.type
) == HAMMER2_OBJTYPE_HARDLINK
)
77 type
= ipdata
->meta
.target_type
;
80 case HAMMER2_OBJTYPE_UNKNOWN
:
82 case HAMMER2_OBJTYPE_DIRECTORY
:
84 case HAMMER2_OBJTYPE_REGFILE
:
86 case HAMMER2_OBJTYPE_FIFO
:
88 case HAMMER2_OBJTYPE_CDEV
: /* not supported */
90 case HAMMER2_OBJTYPE_BDEV
: /* not supported */
92 case HAMMER2_OBJTYPE_SOFTLINK
:
94 case HAMMER2_OBJTYPE_HARDLINK
: /* (never directly associated w/vp) */
96 case HAMMER2_OBJTYPE_SOCKET
:
98 case HAMMER2_OBJTYPE_WHITEOUT
: /* not supported */
107 * Return the directory entry type for an inode
110 hammer2_get_vtype(uint8_t type
)
113 case HAMMER2_OBJTYPE_UNKNOWN
:
115 case HAMMER2_OBJTYPE_DIRECTORY
:
117 case HAMMER2_OBJTYPE_REGFILE
:
119 case HAMMER2_OBJTYPE_FIFO
:
121 case HAMMER2_OBJTYPE_CDEV
: /* not supported */
123 case HAMMER2_OBJTYPE_BDEV
: /* not supported */
125 case HAMMER2_OBJTYPE_SOFTLINK
:
127 case HAMMER2_OBJTYPE_HARDLINK
: /* XXX */
129 case HAMMER2_OBJTYPE_SOCKET
:
131 case HAMMER2_OBJTYPE_WHITEOUT
: /* not supported */
140 hammer2_get_obj_type(enum vtype vtype
)
144 return(HAMMER2_OBJTYPE_DIRECTORY
);
146 return(HAMMER2_OBJTYPE_REGFILE
);
148 return(HAMMER2_OBJTYPE_FIFO
);
150 return(HAMMER2_OBJTYPE_SOCKET
);
152 return(HAMMER2_OBJTYPE_CDEV
);
154 return(HAMMER2_OBJTYPE_BDEV
);
156 return(HAMMER2_OBJTYPE_SOFTLINK
);
158 return(HAMMER2_OBJTYPE_UNKNOWN
);
164 * Convert a hammer2 64-bit time to a timespec.
167 hammer2_time_to_timespec(uint64_t xtime
, struct timespec
*ts
)
169 ts
->tv_sec
= (unsigned long)(xtime
/ 1000000);
170 ts
->tv_nsec
= (unsigned int)(xtime
% 1000000) * 1000L;
174 hammer2_timespec_to_time(const struct timespec
*ts
)
178 xtime
= (unsigned)(ts
->tv_nsec
/ 1000) +
179 (unsigned long)ts
->tv_sec
* 1000000ULL;
184 * Convert a uuid to a unix uid or gid
187 hammer2_to_unix_xid(const uuid_t
*uuid
)
189 return(*(const uint32_t *)&uuid
->node
[2]);
193 hammer2_guid_to_uuid(uuid_t
*uuid
, uint32_t guid
)
195 bzero(uuid
, sizeof(*uuid
));
196 *(uint32_t *)&uuid
->node
[2] = guid
;
200 * Borrow HAMMER1's directory hash algorithm #1 with a few modifications.
201 * The filename is split into fields which are hashed separately and then
204 * Differences include: bit 63 must be set to 1 for HAMMER2 (HAMMER1 sets
205 * it to 0), this is because bit63=0 is used for hidden hardlinked inodes.
206 * (This means we do not need to do a 0-check/or-with-0x100000000 either).
208 * Also, the iscsi crc code is used instead of the old crc32 code.
211 hammer2_dirhash(const unsigned char *name
, size_t len
)
213 const unsigned char *aname
= name
;
225 for (i
= j
= 0; i
< len
; ++i
) {
226 if (aname
[i
] == '.' ||
231 crcx
+= hammer2_icrc32(aname
+ j
, i
- j
);
236 crcx
+= hammer2_icrc32(aname
+ j
, i
- j
);
239 * The directory hash utilizes the top 32 bits of the 64-bit key.
240 * Bit 63 must be set to 1.
243 key
|= (uint64_t)crcx
<< 32;
246 * l16 - crc of entire filename
248 * This crc reduces degenerate hash collision conditions
250 crcx
= hammer2_icrc32(aname
, len
);
251 crcx
= crcx
^ (crcx
<< 16);
252 key
|= crcx
& 0xFFFF0000U
;
255 * Set bit 15. This allows readdir to strip bit 63 so a positive
256 * 64-bit cookie/offset can always be returned, and still guarantee
257 * that the values 0x0000-0x7FFF are available for artificial entries.
267 * Return the power-of-2 radix greater or equal to
268 * the specified number of bytes.
270 * Always returns at least the minimum media allocation
271 * size radix, HAMMER2_RADIX_MIN (10), which is 1KB.
274 hammer2_allocsize(size_t bytes
)
278 if (bytes
< HAMMER2_ALLOC_MIN
)
279 bytes
= HAMMER2_ALLOC_MIN
;
280 if (bytes
== HAMMER2_PBUFSIZE
)
281 radix
= HAMMER2_PBUFRADIX
;
282 else if (bytes
>= 16384)
284 else if (bytes
>= 1024)
287 radix
= HAMMER2_RADIX_MIN
;
289 while (((size_t)1 << radix
) < bytes
)
297 * Convert bytes to radix with no limitations
300 hammer2_getradix(size_t bytes
)
304 if (bytes
== HAMMER2_PBUFSIZE
)
305 radix
= HAMMER2_PBUFRADIX
;
306 else if (bytes
>= HAMMER2_LBUFSIZE
)
307 radix
= HAMMER2_LBUFRADIX
;
308 else if (bytes
>= HAMMER2_ALLOC_MIN
) /* clamp */
309 radix
= HAMMER2_RADIX_MIN
;
313 while (((size_t)1 << radix
) < bytes
)
319 * The logical block size is currently always PBUFSIZE.
322 hammer2_calc_logical(hammer2_inode_t
*ip
, hammer2_off_t uoff
,
323 hammer2_key_t
*lbasep
, hammer2_key_t
*leofp
)
325 KKASSERT(ip
->flags
& HAMMER2_INODE_METAGOOD
);
327 *lbasep
= uoff
& ~HAMMER2_PBUFMASK64
;
329 *leofp
= (ip
->meta
.size
+ HAMMER2_PBUFMASK64
) &
332 return (HAMMER2_PBUFSIZE
);
336 * Calculate the physical block size. pblksize <= lblksize. Primarily
337 * used to calculate a smaller physical block for the logical block
338 * containing the file EOF.
340 * Returns 0 if the requested base offset is beyond the file EOF.
343 hammer2_calc_physical(hammer2_inode_t
*ip
, hammer2_key_t lbase
)
349 KKASSERT(ip
->flags
& HAMMER2_INODE_METAGOOD
);
350 lblksize
= hammer2_calc_logical(ip
, lbase
, NULL
, NULL
);
351 if (lbase
+ lblksize
<= ip
->meta
.size
)
353 if (lbase
>= ip
->meta
.size
)
355 eofbytes
= (int)(ip
->meta
.size
- lbase
);
357 while (pblksize
>= eofbytes
&& pblksize
>= HAMMER2_ALLOC_MIN
)
365 hammer2_update_time(uint64_t *timep
)
370 *timep
= (unsigned long)tv
.tv_sec
* 1000000 + tv
.tv_usec
;
374 hammer2_adjreadcounter(hammer2_blockref_t
*bref
, size_t bytes
)
379 case HAMMER2_BREF_TYPE_DATA
:
380 counterp
= &hammer2_iod_file_read
;
382 case HAMMER2_BREF_TYPE_INODE
:
383 counterp
= &hammer2_iod_meta_read
;
385 case HAMMER2_BREF_TYPE_INDIRECT
:
386 counterp
= &hammer2_iod_indr_read
;
388 case HAMMER2_BREF_TYPE_FREEMAP_NODE
:
389 case HAMMER2_BREF_TYPE_FREEMAP_LEAF
:
390 counterp
= &hammer2_iod_fmap_read
;
393 counterp
= &hammer2_iod_volu_read
;
400 hammer2_signal_check(time_t *timep
)
405 if (*timep
!= time_second
) {
406 *timep
= time_second
;
407 if (CURSIG_NOBLOCK(curthread
->td_lwp
) != 0)
414 hammer2_error_str(int error
)
419 case HAMMER2_ERROR_NONE
:
422 case HAMMER2_ERROR_IO
:
425 case HAMMER2_ERROR_CHECK
:
428 case HAMMER2_ERROR_INCOMPLETE
:
429 str
= "incomplete-node";