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
36 #include <sys/types.h>
38 #include <sys/ioctl.h>
39 #include <sys/mount.h>
40 #include <sys/statvfs.h>
49 #include <vfs/hammer2/hammer2_disk.h>
50 #include <vfs/hammer2/hammer2_ioctl.h>
52 #include "hammer2_subs.h"
55 * Obtain a file descriptor that the caller can execute ioctl()'s on.
58 hammer2_ioctl_handle(const char *sel_path
)
60 struct hammer2_ioc_version info
;
66 fd
= open(sel_path
, O_RDONLY
, 0);
68 fprintf(stderr
, "hammer2: Unable to open %s: %s\n",
69 sel_path
, strerror(errno
));
72 if (ioctl(fd
, HAMMER2IOC_VERSION_GET
, &info
) < 0) {
73 fprintf(stderr
, "hammer2: '%s' is not a hammer2 filesystem\n",
82 hammer2_time64_to_str(uint64_t htime64
, char **strp
)
92 t
= htime64
/ 1000000;
94 strftime(*strp
, 64, "%d-%b-%Y %H:%M:%S", tp
);
99 hammer2_uuid_to_str(uuid_t
*uuid
, char **strp
)
106 uuid_to_string(uuid
, strp
, &status
);
111 hammer2_iptype_to_str(uint8_t type
)
114 case HAMMER2_OBJTYPE_UNKNOWN
:
116 case HAMMER2_OBJTYPE_DIRECTORY
:
118 case HAMMER2_OBJTYPE_REGFILE
:
120 case HAMMER2_OBJTYPE_FIFO
:
122 case HAMMER2_OBJTYPE_CDEV
:
124 case HAMMER2_OBJTYPE_BDEV
:
126 case HAMMER2_OBJTYPE_SOFTLINK
:
128 case HAMMER2_OBJTYPE_SOCKET
:
130 case HAMMER2_OBJTYPE_WHITEOUT
:
138 hammer2_pfstype_to_str(uint8_t type
)
141 case HAMMER2_PFSTYPE_NONE
:
143 case HAMMER2_PFSTYPE_SUPROOT
:
145 case HAMMER2_PFSTYPE_DUMMY
:
147 case HAMMER2_PFSTYPE_CACHE
:
149 case HAMMER2_PFSTYPE_SLAVE
:
151 case HAMMER2_PFSTYPE_SOFT_SLAVE
:
152 return("SOFT_SLAVE");
153 case HAMMER2_PFSTYPE_SOFT_MASTER
:
154 return("SOFT_MASTER");
155 case HAMMER2_PFSTYPE_MASTER
:
163 hammer2_breftype_to_str(uint8_t type
)
166 case HAMMER2_BREF_TYPE_EMPTY
:
168 case HAMMER2_BREF_TYPE_INODE
:
170 case HAMMER2_BREF_TYPE_INDIRECT
:
172 case HAMMER2_BREF_TYPE_DATA
:
174 case HAMMER2_BREF_TYPE_DIRENT
:
176 case HAMMER2_BREF_TYPE_FREEMAP_NODE
:
177 return("freemap_node");
178 case HAMMER2_BREF_TYPE_FREEMAP_LEAF
:
179 return("freemap_leaf");
180 case HAMMER2_BREF_TYPE_FREEMAP
:
182 case HAMMER2_BREF_TYPE_VOLUME
:
190 sizetostr(hammer2_off_t size
)
194 if (size
< 1024 / 2) {
195 snprintf(buf
, sizeof(buf
), "%6.2fB", (double)size
);
196 } else if (size
< 1024 * 1024 / 2) {
197 snprintf(buf
, sizeof(buf
), "%6.2fKB",
198 (double)size
/ 1024);
199 } else if (size
< 1024 * 1024 * 1024LL / 2) {
200 snprintf(buf
, sizeof(buf
), "%6.2fMB",
201 (double)size
/ (1024 * 1024));
202 } else if (size
< 1024 * 1024 * 1024LL * 1024LL / 2) {
203 snprintf(buf
, sizeof(buf
), "%6.2fGB",
204 (double)size
/ (1024 * 1024 * 1024LL));
206 snprintf(buf
, sizeof(buf
), "%6.2fTB",
207 (double)size
/ (1024 * 1024 * 1024LL * 1024LL));
213 counttostr(hammer2_off_t size
)
217 if (size
< 1024 / 2) {
218 snprintf(buf
, sizeof(buf
), "%jd",
220 } else if (size
< 1024 * 1024 / 2) {
221 snprintf(buf
, sizeof(buf
), "%jd",
223 } else if (size
< 1024 * 1024 * 1024LL / 2) {
224 snprintf(buf
, sizeof(buf
), "%6.2fM",
225 (double)size
/ (1024 * 1024));
226 } else if (size
< 1024 * 1024 * 1024LL * 1024LL / 2) {
227 snprintf(buf
, sizeof(buf
), "%6.2fG",
228 (double)(size
/ (1024 * 1024 * 1024LL)));
230 snprintf(buf
, sizeof(buf
), "%6.2fT",
231 (double)(size
/ (1024 * 1024 * 1024LL * 1024LL)));
237 * Borrow HAMMER1's directory hash algorithm #1 with a few modifications.
238 * The filename is split into fields which are hashed separately and then
241 * Differences include: bit 63 must be set to 1 for HAMMER2 (HAMMER1 sets
242 * it to 0), this is because bit63=0 is used for hidden hardlinked inodes.
243 * (This means we do not need to do a 0-check/or-with-0x100000000 either).
245 * Also, the iscsi crc code is used instead of the old crc32 code.
248 dirhash(const unsigned char *name
, size_t len
)
250 const unsigned char *aname
= name
;
257 * Filesystem version 6 or better will create directories
258 * using the ALG1 dirhash. This hash breaks the filename
259 * up into domains separated by special characters and
260 * hashes each domain independently.
262 * We also do a simple sub-sort using the first character
263 * of the filename in the top 5-bits.
271 for (i
= j
= 0; i
< len
; ++i
) {
272 if (aname
[i
] == '.' ||
277 crcx
+= hammer2_icrc32(aname
+ j
, i
- j
);
282 crcx
+= hammer2_icrc32(aname
+ j
, i
- j
);
285 * The directory hash utilizes the top 32 bits of the 64-bit key.
286 * Bit 63 must be set to 1.
289 key
|= (uint64_t)crcx
<< 32;
292 * l16 - crc of entire filename
294 * This crc reduces degenerate hash collision conditions
296 crcx
= hammer2_icrc32(aname
, len
);
297 crcx
= crcx
^ (crcx
<< 16);
298 key
|= crcx
& 0xFFFF0000U
;
301 * Set bit 15. This allows readdir to strip bit 63 so a positive
302 * 64-bit cookie/offset can always be returned, and still guarantee
303 * that the values 0x0000-0x7FFF are available for artificial entries.
312 get_hammer2_mounts(int *acp
)
321 * Get a stable list of mount points
324 n
= getfsstat(NULL
, 0, MNT_NOWAIT
);
325 av
= malloc(sizeof(char *) * n
);
326 fs
= malloc(sizeof(struct statfs
*) * n
);
327 if (getfsstat(fs
, sizeof(*fs
) * n
, MNT_NOWAIT
) != n
) {
334 * Pull out hammer2 filesystems only
336 for (i
= w
= 0; i
< n
; ++i
) {
337 if (strcmp(fs
[i
].f_fstypename
, "hammer2") != 0)
339 av
[w
++] = strdup(fs
[i
].f_mntonname
);
347 put_hammer2_mounts(int ac
, char **av
)