Bug #2759 ยป cmd_dedup01.diff
| sbin/hammer/cmd_dedup.c | ||
|---|---|---|
|
#define DEDUP_PASS2 0x0001 /* process_btree_elm() mode */
|
||
|
static int SigInfoFlag;
|
||
|
static int SigAlrmFlag;
|
||
|
static int64_t DedupDataReads;
|
||
|
static int64_t DedupCurrentRecords;
|
||
|
static int64_t DedupTotalRecords;
|
||
| ... | ... | |
|
struct dedup_entry *de;
|
||
|
struct sha_dedup_entry *sha_de;
|
||
|
struct pass2_dedup_entry *pass2_de;
|
||
|
char *tmp;
|
||
|
char buf[8];
|
||
|
int needfree = 0;
|
||
|
if (TimeoutOpt > 0)
|
||
|
alarm(TimeoutOpt);
|
||
| ... | ... | |
|
glob_fd = getpfs(&glob_pfs, av[0]);
|
||
|
/*
|
||
|
* A cycle file is _required_ for resuming dedup after the timeout
|
||
|
* specified with -t has expired. If no -c option, then place a
|
||
|
* .dedup.cycle file either in the PFS snapshots directory or in
|
||
|
* the default snapshots directory.
|
||
|
*/
|
||
|
if (!CyclePath) {
|
||
|
if (glob_pfs.ondisk->snapshots[0] != '/')
|
||
|
asprintf(&tmp, "%s/%s/.dedup.cycle",
|
||
|
SNAPSHOTS_BASE, av[0]);
|
||
|
else
|
||
|
asprintf(&tmp, "%s/.dedup.cycle",
|
||
|
glob_pfs.ondisk->snapshots);
|
||
|
CyclePath = tmp;
|
||
|
needfree = 1;
|
||
|
}
|
||
|
/*
|
||
|
* Pre-pass to cache the btree
|
||
|
*/
|
||
|
scan_pfs(av[0], count_btree_elm, "pre-pass ");
|
||
| ... | ... | |
|
relpfs(glob_fd, &glob_pfs);
|
||
|
humanize_unsigned(buf, sizeof(buf), dedup_ref_size, "B", 1024);
|
||
|
printf("Dedup ratio = %.2f\n"
|
||
|
printf("Dedup ratio = %.2f (in this run)\n"
|
||
|
" %8s referenced\n",
|
||
|
((dedup_alloc_size != 0) ?
|
||
|
(double)dedup_ref_size / dedup_alloc_size : 0),
|
||
| ... | ... | |
|
(intmax_t)dedup_successes_count,
|
||
|
(intmax_t)dedup_successes_bytes
|
||
|
);
|
||
|
/* Once completed remove cycle file */
|
||
|
hammer_reset_cycle();
|
||
|
/* We don't want to mess up with other directives */
|
||
|
if (needfree) {
|
||
|
free(tmp);
|
||
|
CyclePath = NULL;
|
||
|
}
|
||
|
}
|
||
|
static int
|
||
| ... | ... | |
|
}
|
||
|
static void
|
||
|
sigAlrm(int signo __unused)
|
||
|
{
|
||
|
SigAlrmFlag = 1;
|
||
|
}
|
||
|
static void
|
||
|
sigInfo(int signo __unused)
|
||
|
{
|
||
|
SigInfoFlag = 1;
|
||
| ... | ... | |
|
DedupDataReads = 0;
|
||
|
DedupCurrentRecords = 0;
|
||
|
signal(SIGINFO, sigInfo);
|
||
|
signal(SIGALRM, sigAlrm);
|
||
|
/*
|
||
|
* Deduplication happens per element so hammer(8) is in full
|
||
|
* control of the ioctl()s to actually perform it. SIGALRM
|
||
|
* needs to be handled within hammer(8) but a checkpoint
|
||
|
* is needed for resuming. Use cycle file for that.
|
||
|
*
|
||
|
* Try to obtain the previous obj_id from the cycle file and
|
||
|
* if not available just start from the beginning.
|
||
|
*/
|
||
|
bzero(&mirror, sizeof(mirror));
|
||
|
hammer_key_beg_init(&mirror.key_beg);
|
||
|
hammer_get_cycle(&mirror.key_beg, &mirror.tid_beg);
|
||
|
if (mirror.key_beg.obj_id != (int64_t)HAMMER_MIN_OBJID) {
|
||
|
if (VerboseOpt)
|
||
|
fprintf(stderr, "%s: mirror-read: Resuming at object %016jx\n",
|
||
|
id, (uintmax_t)mirror.key_beg.obj_id);
|
||
|
}
|
||
|
hammer_key_end_init(&mirror.key_end);
|
||
|
mirror.tid_beg = glob_pfs.ondisk->sync_beg_tid;
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
mirror.key_beg = mirror.key_cur;
|
||
|
if (DidInterrupt) {
|
||
|
fprintf(stderr, "Interrupted\n");
|
||
|
if (DidInterrupt || SigAlrmFlag) {
|
||
|
if (VerboseOpt)
|
||
|
fprintf(stderr, "%s\n",
|
||
|
(DidInterrupt ? "Interrupted" : "Timeout"));
|
||
|
hammer_set_cycle(&mirror.key_cur, mirror.tid_beg);
|
||
|
if (VerboseOpt)
|
||
|
fprintf(stderr, "Cyclefile %s updated for "
|
||
|
"continuation\n", CyclePath);
|
||
|
exit(1);
|
||
|
}
|
||
|
if (SigInfoFlag) {
|
||
| ... | ... | |
|
} while (mirror.count != 0);
|
||
|
signal(SIGINFO, SIG_IGN);
|
||
|
signal(SIGALRM, SIG_IGN);
|
||
|
free(buf);
|
||
|
}
|
||