Skip to content

Instantly share code, notes, and snippets.

@tuxillo
Created January 6, 2015 00:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tuxillo/5ab6255d50d7e8e72496 to your computer and use it in GitHub Desktop.
Save tuxillo/5ab6255d50d7e8e72496 to your computer and use it in GitHub Desktop.
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