#include "hammer_util.h"
void
hammer_key_beg_init(hammer_base_elm_t base)
{
bzero(base, sizeof(*base));
base->localization = HAMMER_MIN_LOCALIZATION;
base->obj_id = HAMMER_MIN_OBJID;
base->key = HAMMER_MIN_KEY;
base->create_tid = 1;
base->rec_type = HAMMER_MIN_RECTYPE;
base->obj_type = 0;
}
void
hammer_key_end_init(hammer_base_elm_t base)
{
bzero(base, sizeof(*base));
base->localization = HAMMER_MAX_LOCALIZATION;
base->obj_id = HAMMER_MAX_OBJID;
base->key = HAMMER_MAX_KEY;
base->create_tid = HAMMER_MAX_TID;
base->rec_type = HAMMER_MAX_RECTYPE;
base->obj_type = 0;
}
int
getyn(void)
{
char buf[256];
int len;
if (fgets(buf, sizeof(buf), stdin) == NULL)
return(0);
len = strlen(buf);
while (len && (buf[len-1] == '\n' || buf[len-1] == '\r'))
--len;
buf[len] = 0;
if (strcmp(buf, "y") == 0 ||
strcmp(buf, "yes") == 0 ||
strcmp(buf, "Y") == 0 ||
strcmp(buf, "YES") == 0) {
return(1);
}
return(0);
}
const char *
sizetostr(off_t size)
{
static char buf[32];
if (size < 1024 / 2) {
snprintf(buf, sizeof(buf), "%6.2fB", (double)size);
} else if (size < 1024 * 1024 / 2) {
snprintf(buf, sizeof(buf), "%6.2fKB", (double)size / 1024);
} else if (size < 1024 * 1024 * 1024LL / 2) {
snprintf(buf, sizeof(buf), "%6.2fMB",
(double)size / (1024 * 1024));
} else if (size < 1024 * 1024 * 1024LL * 1024LL / 2) {
snprintf(buf, sizeof(buf), "%6.2fGB",
(double)size / (1024 * 1024 * 1024LL));
} else {
snprintf(buf, sizeof(buf), "%6.2fTB",
(double)size / (1024 * 1024 * 1024LL * 1024LL));
}
return(buf);
}
int
hammer_fs_to_vol(const char *fs, struct hammer_ioc_volume_list *p)
{
struct hammer_ioc_volume_list ioc;
int fd;
fd = open(fs, O_RDONLY);
if (fd < 0) {
perror("open");
return(-1);
}
bzero(&ioc, sizeof(ioc));
ioc.nvols = HAMMER_MAX_VOLUMES;
ioc.vols = malloc(ioc.nvols * sizeof(*ioc.vols));
if (ioc.vols == NULL) {
perror("malloc");
close(fd);
return(-1);
}
if (ioctl(fd, HAMMERIOC_LIST_VOLUMES, &ioc) < 0) {
perror("ioctl");
close(fd);
free(ioc.vols);
return(-1);
}
bcopy(&ioc, p, sizeof(ioc));
close(fd);
return(0);
}
int
hammer_fs_to_rootvol(const char *fs, char *buf, int len)
{
struct hammer_ioc_volume_list ioc;
int i;
if (hammer_fs_to_vol(fs, &ioc) == -1)
return(-1);
for (i = 0; i < ioc.nvols; i++) {
if (ioc.vols[i].vol_no == HAMMER_ROOT_VOLNO) {
buf[len - 1] = '\0';
strncpy(buf, ioc.vols[i].device_name, len - 1);
break;
}
}
assert(i != ioc.nvols);
free(ioc.vols);
return(0);
}
#define HAMMER_LAYER1_UINT64 8192
#define HAMMER_LAYER1_BYTES (HAMMER_LAYER1_UINT64 * sizeof(uint64_t))
static int *l1_max = NULL;
static uint64_t **l1_bits = NULL;
static __inline
int
hammer_set_layer_bits(uint64_t *bits, int i)
{
int q, r;
q = i >> 6;
r = i & ((1 << 6) - 1);
bits += q;
if (!((*bits) & ((uint64_t)1 << r))) {
(*bits) |= ((uint64_t)1 << r);
return(1);
}
return(0);
}
static
void
hammer_extend_layer1_bits(int vol, int newsiz, int oldsiz)
{
uint64_t *p;
assert(newsiz > oldsiz);
assert(newsiz > 0 && oldsiz >= 0);
p = l1_bits[vol];
if (p == NULL)
p = malloc(HAMMER_LAYER1_BYTES * newsiz);
else
p = realloc(p, HAMMER_LAYER1_BYTES * newsiz);
if (p == NULL) {
err(1, "alloc");
}
l1_bits[vol] = p;
p += HAMMER_LAYER1_UINT64 * oldsiz;
bzero(p, HAMMER_LAYER1_BYTES * (newsiz - oldsiz));
}
zone_stat_t
hammer_init_zone_stat(void)
{
return(calloc(HAMMER_MAX_ZONES, sizeof(struct zone_stat)));
}
zone_stat_t
hammer_init_zone_stat_bits(void)
{
int i;
l1_max = calloc(HAMMER_MAX_VOLUMES, sizeof(int));
if (l1_max == NULL) {
err(1, "calloc");
}
l1_bits = calloc(HAMMER_MAX_VOLUMES, sizeof(uint64_t*));
if (l1_bits == NULL) {
err(1, "calloc");
}
for (i = 0; i < HAMMER_MAX_VOLUMES; i++) {
l1_max[i] = -1;
l1_bits[i] = NULL;
}
return(hammer_init_zone_stat());
}
void
hammer_cleanup_zone_stat(zone_stat_t stats)
{
int i;
if (l1_bits) {
for (i = 0; i < HAMMER_MAX_VOLUMES; i++) {
free(l1_bits[i]);
l1_bits[i] = NULL;
}
}
free(l1_bits);
l1_bits = NULL;
free(l1_max);
l1_max = NULL;
free(stats);
}
static
void
_hammer_add_zone_stat(zone_stat_t stats, int zone, int bytes,
int new_block, int new_item)
{
zone_stat_t sp = stats + zone;
if (new_block)
sp->blocks++;
if (new_item)
sp->items++;
sp->used += bytes;
}
void
hammer_add_zone_stat(zone_stat_t stats, hammer_off_t offset, int bytes)
{
int zone, vol, i, j, new_block;
uint64_t *p;
offset &= ~HAMMER_BIGBLOCK_MASK64;
zone = HAMMER_ZONE_DECODE(offset);
vol = HAMMER_VOL_DECODE(offset);
offset = HAMMER_OFF_SHORT_ENCODE(offset);
i = HAMMER_BLOCKMAP_LAYER1_INDEX(offset);
j = HAMMER_BLOCKMAP_LAYER2_INDEX(offset);
if (i > l1_max[vol]) {
assert(i < (HAMMER_BLOCKMAP_RADIX1 / HAMMER_MAX_VOLUMES));
hammer_extend_layer1_bits(vol, i + 1, l1_max[vol] + 1);
l1_max[vol] = i;
}
p = l1_bits[vol] + i * HAMMER_LAYER1_UINT64;
new_block = hammer_set_layer_bits(p, j);
_hammer_add_zone_stat(stats, zone, bytes, new_block, 1);
}
void
hammer_add_zone_stat_layer2(zone_stat_t stats,
hammer_blockmap_layer2_t layer2)
{
_hammer_add_zone_stat(stats, layer2->zone,
HAMMER_BIGBLOCK_SIZE - layer2->bytes_free, 1, 0);
}
static __inline
double
_calc_used_percentage(int64_t blocks, int64_t used)
{
double res;
if (blocks)
res = ((double)(used * 100)) / (blocks << HAMMER_BIGBLOCK_BITS);
else
res = 0;
return(res);
}
void
hammer_print_zone_stat(zone_stat_t stats)
{
int i;
int64_t total_blocks = 0;
int64_t total_items = 0;
int64_t total_used = 0;
zone_stat_t p = stats;
#define INDENT ""
printf("HAMMER zone statistics\n");
printf(INDENT"zone # "
"blocks items used[B] used[%%]\n");
for (i = 0; i < HAMMER_MAX_ZONES; i++) {
printf(INDENT"zone %-2d %-10s %-12ju %-18ju %-19ju %g\n",
i, zone_labels[i], p->blocks, p->items, p->used,
_calc_used_percentage(p->blocks, p->used));
total_blocks += p->blocks;
total_items += p->items;
total_used += p->used;
p++;
}
printf(INDENT"--------------------------------------------------------------------------------\n");
printf(INDENT"total %-12ju %-18ju %-19ju %g\n",
(uintmax_t)total_blocks,
(uintmax_t)total_items,
(uintmax_t)total_used,
_calc_used_percentage(total_blocks, total_used));
}