2 * Copyright (c) 2011-2012 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
39 * Obtain a file descriptor that the caller can execute ioctl()'s on.
42 hammer2_ioctl_handle(const char *sel_path
)
44 struct hammer2_ioc_version info
;
50 fd
= open(sel_path
, O_RDONLY
, 0);
52 fprintf(stderr
, "hammer2: Unable to open %s: %s\n",
53 sel_path
, strerror(errno
));
56 if (ioctl(fd
, HAMMER2IOC_VERSION_GET
, &info
) < 0) {
57 fprintf(stderr
, "hammer2: '%s' is not a hammer2 filesystem\n",
66 * Execute the specified function as a detached independent process/daemon,
67 * unless we are in debug mode. If we are in debug mode the function is
68 * executed as a pthread in the current process.
71 hammer2_demon(void *(*func
)(void *), void *arg
)
73 pthread_t thread
= NULL
;
78 * Do not disconnect in debug mode
81 pthread_create(&thread
, NULL
, func
, arg
);
87 * Otherwise disconnect us. Double-fork to get rid of the ppid
88 * association and disconnect the TTY.
90 if ((pid
= fork()) < 0) {
91 fprintf(stderr
, "hammer2: fork(): %s\n", strerror(errno
));
95 while (waitpid(pid
, NULL
, 0) != pid
)
97 return; /* parent returns */
101 * Get rid of the TTY/session before double-forking to finish off
104 ttyfd
= open("/dev/null", O_RDWR
);
116 ttyfd
= open("/dev/tty", O_RDWR
);
118 ioctl(ttyfd
, TIOCNOTTY
, 0);
124 * Second fork to disconnect ppid (the original parent waits for
127 if ((pid
= fork()) < 0) {
137 pthread_create(&thread
, NULL
, func
, arg
);
139 _exit(2); /* NOT REACHED */
143 hammer2_time64_to_str(uint64_t htime64
, char **strp
)
153 t
= htime64
/ 1000000;
155 strftime(*strp
, 64, "%d-%b-%Y %H:%M:%S", tp
);
160 hammer2_uuid_to_str(uuid_t
*uuid
, char **strp
)
167 uuid_to_string(uuid
, strp
, &status
);
172 hammer2_iptype_to_str(uint8_t type
)
175 case HAMMER2_OBJTYPE_UNKNOWN
:
177 case HAMMER2_OBJTYPE_DIRECTORY
:
179 case HAMMER2_OBJTYPE_REGFILE
:
181 case HAMMER2_OBJTYPE_FIFO
:
183 case HAMMER2_OBJTYPE_CDEV
:
185 case HAMMER2_OBJTYPE_BDEV
:
187 case HAMMER2_OBJTYPE_SOFTLINK
:
189 case HAMMER2_OBJTYPE_HARDLINK
:
191 case HAMMER2_OBJTYPE_SOCKET
:
193 case HAMMER2_OBJTYPE_WHITEOUT
:
201 hammer2_pfstype_to_str(uint8_t type
)
204 case HAMMER2_PFSTYPE_NONE
:
206 case HAMMER2_PFSTYPE_SUPROOT
:
208 case HAMMER2_PFSTYPE_DUMMY
:
210 case HAMMER2_PFSTYPE_CACHE
:
212 case HAMMER2_PFSTYPE_SLAVE
:
214 case HAMMER2_PFSTYPE_SOFT_SLAVE
:
215 return("SOFT_SLAVE");
216 case HAMMER2_PFSTYPE_SOFT_MASTER
:
217 return("SOFT_MASTER");
218 case HAMMER2_PFSTYPE_MASTER
:
226 sizetostr(hammer2_off_t size
)
230 if (size
< 1024 / 2) {
231 snprintf(buf
, sizeof(buf
), "%6.2f", (double)size
);
232 } else if (size
< 1024 * 1024 / 2) {
233 snprintf(buf
, sizeof(buf
), "%6.2fKB",
234 (double)size
/ 1024);
235 } else if (size
< 1024 * 1024 * 1024LL / 2) {
236 snprintf(buf
, sizeof(buf
), "%6.2fMB",
237 (double)size
/ (1024 * 1024));
238 } else if (size
< 1024 * 1024 * 1024LL * 1024LL / 2) {
239 snprintf(buf
, sizeof(buf
), "%6.2fGB",
240 (double)size
/ (1024 * 1024 * 1024LL));
242 snprintf(buf
, sizeof(buf
), "%6.2fTB",
243 (double)size
/ (1024 * 1024 * 1024LL * 1024LL));
249 counttostr(hammer2_off_t size
)
253 if (size
< 1024 / 2) {
254 snprintf(buf
, sizeof(buf
), "%jd",
256 } else if (size
< 1024 * 1024 / 2) {
257 snprintf(buf
, sizeof(buf
), "%jd",
259 } else if (size
< 1024 * 1024 * 1024LL / 2) {
260 snprintf(buf
, sizeof(buf
), "%6.2fM",
261 (double)size
/ (1024 * 1024));
262 } else if (size
< 1024 * 1024 * 1024LL * 1024LL / 2) {
263 snprintf(buf
, sizeof(buf
), "%6.2fG",
264 (double)(size
/ (1024 * 1024 * 1024LL)));
266 snprintf(buf
, sizeof(buf
), "%6.2fT",
267 (double)(size
/ (1024 * 1024 * 1024LL * 1024LL)));
274 * Allocation wrappers give us shims for possible future use
277 hammer2_alloc(size_t bytes
)
288 hammer2_free(void *ptr
)
296 dirhash(const unsigned char *name
, size_t len
)
298 const unsigned char *aname
= name
;
305 * Filesystem version 6 or better will create directories
306 * using the ALG1 dirhash. This hash breaks the filename
307 * up into domains separated by special characters and
308 * hashes each domain independently.
310 * We also do a simple sub-sort using the first character
311 * of the filename in the top 5-bits.
319 for (i
= j
= 0; i
< len
; ++i
) {
320 if (aname
[i
] == '.' ||
325 crcx
+= hammer2_icrc32(aname
+ j
, i
- j
);
330 crcx
+= hammer2_icrc32(aname
+ j
, i
- j
);
333 * The directory hash utilizes the top 32 bits of the 64-bit key.
334 * Bit 63 must be set to 1.
337 key
|= (uint64_t)crcx
<< 32;
340 * l16 - crc of entire filename
342 * This crc reduces degenerate hash collision conditions
344 crcx
= hammer2_icrc32(aname
, len
);
345 crcx
= crcx
^ (crcx
<< 16);
346 key
|= crcx
& 0xFFFF0000U
;
349 * Set bit 15. This allows readdir to strip bit 63 so a positive
350 * 64-bit cookie/offset can always be returned, and still guarantee
351 * that the values 0x0000-0x7FFF are available for artificial entries.