2 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sbin/hammer/misc.c,v 1.5 2008/06/26 04:07:57 dillon Exp $
37 #include "hammer_util.h"
40 hammer_key_beg_init(hammer_base_elm_t base)
42 bzero(base, sizeof(*base));
44 base->localization = HAMMER_MIN_LOCALIZATION;
45 base->obj_id = HAMMER_MIN_OBJID;
46 base->key = HAMMER_MIN_KEY;
48 base->rec_type = HAMMER_MIN_RECTYPE;
52 hammer_key_end_init(hammer_base_elm_t base)
54 bzero(base, sizeof(*base));
56 base->localization = HAMMER_MAX_LOCALIZATION;
57 base->obj_id = HAMMER_MAX_OBJID;
58 base->key = HAMMER_MAX_KEY;
59 base->create_tid = HAMMER_MAX_TID;
60 base->rec_type = HAMMER_MAX_RECTYPE;
69 if (fgets(buf, sizeof(buf), stdin) == NULL)
72 while (len && (buf[len-1] == '\n' || buf[len-1] == '\r'))
75 if (strcmp(buf, "y") == 0 ||
76 strcmp(buf, "yes") == 0 ||
77 strcmp(buf, "Y") == 0 ||
78 strcmp(buf, "YES") == 0) {
89 if (size < 1024 / 2) {
90 snprintf(buf, sizeof(buf), "%6.2fB", (double)size);
91 } else if (size < 1024 * 1024 / 2) {
92 snprintf(buf, sizeof(buf), "%6.2fKB",
94 } else if (size < 1024 * 1024 * 1024LL / 2) {
95 snprintf(buf, sizeof(buf), "%6.2fMB",
96 (double)size / (1024 * 1024));
97 } else if (size < 1024 * 1024 * 1024LL * 1024LL / 2) {
98 snprintf(buf, sizeof(buf), "%6.2fGB",
99 (double)size / (1024 * 1024 * 1024LL));
101 snprintf(buf, sizeof(buf), "%6.2fTB",
102 (double)size / (1024 * 1024 * 1024LL * 1024LL));
108 hammer_fs_to_vol(const char *fs, struct hammer_ioc_volume_list *p)
110 struct hammer_ioc_volume_list ioc;
113 fd = open(fs, O_RDONLY);
119 bzero(&ioc, sizeof(ioc));
120 ioc.nvols = HAMMER_MAX_VOLUMES;
121 ioc.vols = malloc(ioc.nvols * sizeof(*ioc.vols));
122 if (ioc.vols == NULL) {
128 if (ioctl(fd, HAMMERIOC_LIST_VOLUMES, &ioc) < 0) {
135 bcopy(&ioc, p, sizeof(ioc));
142 hammer_fs_to_rootvol(const char *fs, char *buf, int len)
144 struct hammer_ioc_volume_list ioc;
147 if (hammer_fs_to_vol(fs, &ioc) == -1)
150 for (i = 0; i < ioc.nvols; i++) {
151 if (ioc.vols[i].vol_no == HAMMER_ROOT_VOLNO) {
152 strlcpy(buf, ioc.vols[i].device_name, len);
156 assert(i != ioc.nvols); /* root volume must exist */
163 * Functions and data structure for zone statistics
166 * Each layer1 needs ((2^19) / 64) = 8192 uint64_t.
168 #define HAMMER_LAYER1_UINT64 8192
169 #define HAMMER_LAYER1_BYTES (HAMMER_LAYER1_UINT64 * sizeof(uint64_t))
171 static int *l1_max = NULL;
172 static uint64_t **l1_bits = NULL;
176 hammer_set_layer_bits(uint64_t *bits, int i)
181 r = i & ((1 << 6) - 1);
184 if (!((*bits) & ((uint64_t)1 << r))) {
185 (*bits) |= ((uint64_t)1 << r);
188 return(0); /* already seen this block */
193 hammer_extend_layer1_bits(int vol, int newsiz, int oldsiz)
197 assert(newsiz > oldsiz);
198 assert(newsiz > 0 && oldsiz >= 0);
202 p = malloc(HAMMER_LAYER1_BYTES * newsiz);
204 p = realloc(p, HAMMER_LAYER1_BYTES * newsiz);
209 p += HAMMER_LAYER1_UINT64 * oldsiz;
210 bzero(p, HAMMER_LAYER1_BYTES * (newsiz - oldsiz));
214 hammer_init_zone_stat(void)
216 return(calloc(HAMMER_MAX_ZONES, sizeof(struct zone_stat)));
220 hammer_init_zone_stat_bits(void)
224 l1_max = calloc(HAMMER_MAX_VOLUMES, sizeof(int));
228 l1_bits = calloc(HAMMER_MAX_VOLUMES, sizeof(uint64_t*));
232 for (i = 0; i < HAMMER_MAX_VOLUMES; i++) {
233 l1_max[i] = -1; /* +1 needs to be 0 */
236 return(hammer_init_zone_stat());
240 hammer_cleanup_zone_stat(struct zone_stat *stats)
245 for (i = 0; i < HAMMER_MAX_VOLUMES; i++) {
262 _hammer_add_zone_stat(struct zone_stat *stats, int zone, int bytes,
263 int new_block, int new_item)
265 struct zone_stat *sp = stats + zone;
275 hammer_add_zone_stat(struct zone_stat *stats, hammer_off_t offset, int bytes)
277 int zone, vol, i, j, new_block;
280 offset &= ~HAMMER_BIGBLOCK_MASK64;
281 zone = HAMMER_ZONE_DECODE(offset);
282 vol = HAMMER_VOL_DECODE(offset);
284 offset &= HAMMER_OFF_SHORT_MASK; /* cut off volume bits from layer1 */
285 i = HAMMER_BLOCKMAP_LAYER1_INDEX(offset);
286 j = HAMMER_BLOCKMAP_LAYER2_INDEX(offset);
288 if (i > l1_max[vol]) {
289 assert(i < (HAMMER_BLOCKMAP_RADIX1 / HAMMER_MAX_VOLUMES));
290 hammer_extend_layer1_bits(vol, i + 1, l1_max[vol] + 1);
294 p = l1_bits[vol] + i * HAMMER_LAYER1_UINT64;
295 new_block = hammer_set_layer_bits(p, j);
296 _hammer_add_zone_stat(stats, zone, bytes, new_block, 1);
300 * If the same layer2 is used more than once the result will be wrong.
303 hammer_add_zone_stat_layer2(struct zone_stat *stats,
304 hammer_blockmap_layer2_t layer2)
306 _hammer_add_zone_stat(stats, layer2->zone,
307 HAMMER_BIGBLOCK_SIZE - layer2->bytes_free, 1, 0);
312 _calc_used_percentage(int64_t blocks, int64_t used)
317 res = ((double)(used * 100)) / (blocks << HAMMER_BIGBLOCK_BITS);
324 hammer_print_zone_stat(const struct zone_stat *stats)
327 int64_t total_blocks = 0;
328 int64_t total_items = 0;
329 int64_t total_used = 0;
330 const struct zone_stat *p = stats;
333 printf("HAMMER zone statistics\n");
334 printf(INDENT"zone # "
335 "blocks items used[B] used[%%]\n");
336 for (i = 0; i < HAMMER_MAX_ZONES; i++) {
337 printf(INDENT"zone %-2d %-10s %-12ju %-18ju %-19ju %g\n",
338 i, zone_labels[i], p->blocks, p->items, p->used,
339 _calc_used_percentage(p->blocks, p->used));
340 total_blocks += p->blocks;
341 total_items += p->items;
342 total_used += p->used;
347 * Remember that zone0 is always 0% used and zone15 is
350 printf(INDENT"--------------------------------------------------------------------------------\n");
351 printf(INDENT"total %-12ju %-18ju %-19ju %g\n",
352 (uintmax_t)total_blocks,
353 (uintmax_t)total_items,
354 (uintmax_t)total_used,
355 _calc_used_percentage(total_blocks, total_used));