Created
January 6, 2015 00:11
-
-
Save tuxillo/5ab6255d50d7e8e72496 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/sbin/hammer/cmd_dedup.c b/sbin/hammer/cmd_dedup.c | |
index 5b4d43d..e307e58 100644 | |
--- a/sbin/hammer/cmd_dedup.c | |
+++ b/sbin/hammer/cmd_dedup.c | |
@@ -101,6 +101,7 @@ struct pass2_dedup_entry { | |
#define DEDUP_PASS2 0x0001 /* process_btree_elm() mode */ | |
static int SigInfoFlag; | |
+static int SigAlarmFlag; | |
static int64_t DedupDataReads; | |
static int64_t DedupCurrentRecords; | |
static int64_t DedupTotalRecords; | |
@@ -111,6 +112,7 @@ static u_int64_t MemoryUse; | |
/* PFS global ids - we deal with just one PFS at a run */ | |
int glob_fd; | |
struct hammer_ioc_pseudofs_rw glob_pfs; | |
+char *snpath; | |
/* | |
* Global accounting variables | |
@@ -133,7 +135,7 @@ static int rb_dedup_entry_compare(struct dedup_entry *de1, | |
static int rb_sha_dedup_entry_compare(struct sha_dedup_entry *sha_de1, | |
struct sha_dedup_entry *sha_de2); | |
typedef int (*scan_pfs_cb_t)(hammer_btree_leaf_elm_t scan_leaf, int flags); | |
-static void scan_pfs(char *filesystem, scan_pfs_cb_t func, const char *id); | |
+static void scan_pfs(char *filesystem, scan_pfs_cb_t func, const char *id, int64_t); | |
static int collect_btree_elm(hammer_btree_leaf_elm_t scan_leaf, int flags); | |
static int count_btree_elm(hammer_btree_leaf_elm_t scan_leaf, int flags); | |
static int process_btree_elm(hammer_btree_leaf_elm_t scan_leaf, int flags); | |
@@ -141,6 +143,7 @@ static int upgrade_chksum(hammer_btree_leaf_elm_t leaf, u_int8_t *sha_hash); | |
static void dump_simulated_dedup(void); | |
static void dump_real_dedup(void); | |
static void dedup_usage(int code); | |
+static void sigAlarm(int signo); | |
RB_GENERATE2(sim_dedup_entry_rb_tree, sim_dedup_entry, rb_entry, | |
rb_sim_dedup_entry_compare, hammer_crc_t, crc); | |
@@ -149,6 +152,61 @@ RB_GENERATE2(dedup_entry_rb_tree, dedup_entry, rb_entry, | |
RB_GENERATE(sha_dedup_entry_rb_tree, sha_dedup_entry, fict_entry, | |
rb_sha_dedup_entry_compare); | |
+/* | |
+ * Retrieve last key | |
+ */ | |
+static int | |
+get_lastkey(int64_t *key) | |
+{ | |
+ FILE *fp; | |
+ char *path; | |
+ char buf[128]; | |
+ | |
+ /* | |
+ * Retrieve the start time of the last successful operation. | |
+ */ | |
+ asprintf(&path, "%s/.dedup.key", snpath); | |
+ fp = fopen(path, "r"); | |
+ free(path); | |
+ if (fp == NULL) | |
+ return(1); | |
+ if (fgets(buf, sizeof(buf), fp) == NULL) { | |
+ fclose(fp); | |
+ return(1); | |
+ } | |
+ fclose(fp); | |
+ | |
+ *key = strtol(buf, NULL, 0); | |
+ | |
+ return 0; | |
+} | |
+ | |
+/* | |
+ * Store current key | |
+ */ | |
+static void | |
+save_curkey(int64_t key) | |
+{ | |
+ FILE *fp; | |
+ char *opath; | |
+ char *npath; | |
+ | |
+ asprintf(&opath, "%s/.dedup.key", snpath); | |
+ asprintf(&npath, "%s/.dedup.key.new", snpath); | |
+ fp = fopen(npath, "w"); | |
+ if (fp) { | |
+ fprintf(fp, "0x%016jx\n", (intmax_t)key); | |
+ if (fclose(fp) == 0) | |
+ rename(npath, opath); | |
+ remove(npath); | |
+ } else { | |
+ fprintf(stderr, "hammer: Unable to create keyfile-file %s: %s\n", | |
+ npath, strerror(errno)); | |
+ } | |
+ free(npath); | |
+ free(opath); | |
+} | |
+ | |
static int | |
rb_sim_dedup_entry_compare(struct sim_dedup_entry *sim_de1, | |
struct sim_dedup_entry *sim_de2) | |
@@ -217,7 +275,7 @@ hammer_cmd_dedup_simulate(char **av, int ac) | |
DedupCrcStart); | |
fflush(stdout); | |
} | |
- scan_pfs(av[0], collect_btree_elm, "simu-pass"); | |
+ scan_pfs(av[0], collect_btree_elm, "simu-pass", 0); | |
if (VerboseOpt >= 2) | |
dump_simulated_dedup(); | |
@@ -254,6 +312,7 @@ hammer_cmd_dedup(char **av, int ac) | |
struct dedup_entry *de; | |
struct sha_dedup_entry *sha_de; | |
struct pass2_dedup_entry *pass2_de; | |
+ int64_t lastkey; | |
char buf[8]; | |
if (TimeoutOpt > 0) | |
@@ -266,10 +325,31 @@ hammer_cmd_dedup(char **av, int ac) | |
glob_fd = getpfs(&glob_pfs, av[0]); | |
+ signal(SIGALRM, sigAlarm); | |
+ | |
+ /* | |
+ * Get snapshots path from the metadata since dedup is only supported | |
+ * in HAMMER versions 5 or higher. | |
+ * It must be an absolute-path or we set the default. | |
+ */ | |
+ if (glob_pfs.ondisk->snapshots[0] != '/') | |
+ asprintf(&snpath, "%s/%s", SNAPSHOTS_BASE, av[0]); | |
+ else | |
+ snpath = strdup(glob_pfs.ondisk->snapshots); | |
+ | |
+ /* | |
+ * Obtain last key processed, if available. | |
+ */ | |
+ if(get_lastkey(&lastkey)) | |
+ lastkey = 0; | |
+ | |
+ if (VerboseOpt) | |
+ printf("Got last obj_id=%016jx\n", lastkey); | |
+ | |
/* | |
* Pre-pass to cache the btree | |
*/ | |
- scan_pfs(av[0], count_btree_elm, "pre-pass "); | |
+ scan_pfs(av[0], count_btree_elm, "pre-pass ", lastkey); | |
DedupTotalRecords = DedupCurrentRecords; | |
/* | |
@@ -286,7 +366,7 @@ hammer_cmd_dedup(char **av, int ac) | |
DedupCrcStart); | |
fflush(stdout); | |
} | |
- scan_pfs(av[0], process_btree_elm, "main-pass"); | |
+ scan_pfs(av[0], process_btree_elm, "main-pass", lastkey); | |
while ((pass2_de = STAILQ_FIRST(&pass2_dedup_queue)) != NULL) { | |
if (process_btree_elm(&pass2_de->leaf, DEDUP_PASS2)) | |
@@ -328,6 +408,7 @@ hammer_cmd_dedup(char **av, int ac) | |
if (DedupCrcEnd && VerboseOpt == 0) | |
printf("."); | |
} while (DedupCrcEnd); | |
+ free(snpath); | |
printf("Dedup %s succeeded\n", av[0]); | |
relpfs(glob_fd, &glob_pfs); | |
@@ -820,7 +901,13 @@ sigInfo(int signo __unused) | |
} | |
static void | |
-scan_pfs(char *filesystem, scan_pfs_cb_t func, const char *id) | |
+sigAlarm(int signo __unused) | |
+{ | |
+ SigAlarmFlag = 1; | |
+} | |
+ | |
+static void | |
+scan_pfs(char *filesystem, scan_pfs_cb_t func, const char *id, int64_t lastkey) | |
{ | |
struct hammer_ioc_mirror_rw mirror; | |
hammer_ioc_mrecord_any_t mrec; | |
@@ -846,6 +933,7 @@ scan_pfs(char *filesystem, scan_pfs_cb_t func, const char *id) | |
mirror.size = DEDUP_BUF; | |
mirror.pfs_id = glob_pfs.pfs_id; | |
mirror.shared_uuid = glob_pfs.ondisk->shared_uuid; | |
+ mirror.key_cur.obj_id = lastkey; | |
if (VerboseOpt && DedupCrcStart == 0) { | |
printf("%s %s: objspace %016jx:%04x %016jx:%04x\n", | |
@@ -905,6 +993,11 @@ scan_pfs(char *filesystem, scan_pfs_cb_t func, const char *id) | |
} | |
} | |
mirror.key_beg = mirror.key_cur; | |
+ if (SigAlarmFlag) { | |
+ save_curkey(mirror.key_cur.obj_id); | |
+ fprintf(stderr, "Time is up!\n"); | |
+ exit(1); | |
+ } | |
if (DidInterrupt) { | |
fprintf(stderr, "Interrupted\n"); | |
exit(1); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment