diff --git a/dbfile.c b/dbfile.c index c8447a38a15d..df857e3edb65 100644 --- a/dbfile.c +++ b/dbfile.c @@ -50,6 +50,13 @@ static int __dbfile_get_config(sqlite3 *db, unsigned int *block_size, int *major, int *minor, char *db_hash_type, unsigned int *db_dedupe_seq); +static void dbfile_config_defaults(struct dbfile_config *cfg) +{ + memset(cfg, 0, sizeof(*cfg)); + cfg->blocksize = blocksize; + strncpy(cfg->hash_type, hash_type, 8); +} + #if 0 static int debug_print_cb(void *priv, int argc, char **argv, char **column) { @@ -146,7 +153,7 @@ static int dbfile_set_modes(sqlite3 *db) return ret; } -int dbfile_create(char *filename, int *dbfile_is_new) +int dbfile_create(char *filename, int *dbfile_is_new, struct dbfile_config *cfg) { int ret, inmem = 0, newfile = 0; sqlite3 *db = NULL; @@ -181,7 +188,12 @@ int dbfile_create(char *filename, int *dbfile_is_new) sqlite3_close(db); return ret; } + /* Config is not written yet, but we can load some defaults. */ + dbfile_config_defaults(cfg); + cfg->major = DB_FILE_MAJOR; + cfg->minor = DB_FILE_MINOR; } else { + /* Get only version numbers initially */ ret = __dbfile_get_config(db, NULL, NULL, NULL, NULL, NULL, &vmajor, &vminor, NULL, NULL); if (ret && ret != SQLITE_CORRUPT) { @@ -218,6 +230,8 @@ int dbfile_create(char *filename, int *dbfile_is_new) sqlite3_close(db); return -EIO; } + + ret = dbfile_get_config(cfg); } ret = dbfile_set_modes(db); @@ -232,7 +246,7 @@ int dbfile_create(char *filename, int *dbfile_is_new) return 0; } -int dbfile_open(char *filename) +int dbfile_open(char *filename, struct dbfile_config *cfg) { int ret; sqlite3 *db; @@ -251,6 +265,14 @@ int dbfile_open(char *filename) return ret; } + dbfile_config_defaults(cfg); + ret = dbfile_get_config(cfg); + if (ret) { + perror_sqlite(ret, "loading config"); + sqlite3_close(db); + return ret; + } + gdb = db; return 0; } @@ -343,8 +365,7 @@ static int sync_config_int64(sqlite3_stmt *stmt, const char *key, uint64_t val) return ret; } -int __dbfile_sync_config(sqlite3 *db, unsigned int block_size, dev_t onefs_dev, - uint64_t onefs_fsid, unsigned int seq) +int __dbfile_sync_config(sqlite3 *db, struct dbfile_config *cfg) { int ret; sqlite3_stmt *stmt = NULL; @@ -358,33 +379,33 @@ int __dbfile_sync_config(sqlite3 *db, unsigned int block_size, dev_t onefs_dev, return ret; } - ret = sync_config_text(stmt, "hash_type", hash_type, 8); + ret = sync_config_text(stmt, "hash_type", cfg->hash_type, 8); if (ret) goto out; - ret = sync_config_int(stmt, "block_size", block_size); + ret = sync_config_int(stmt, "block_size", cfg->blocksize); if (ret) goto out; - onefs_major = major(onefs_dev); + onefs_major = major(cfg->onefs_dev); ret = sync_config_int(stmt, "onefs_dev_major", onefs_major); if (ret) goto out; - onefs_minor = minor(onefs_dev); + onefs_minor = minor(cfg->onefs_dev); ret = sync_config_int(stmt, "onefs_dev_minor", onefs_minor); if (ret) goto out; - ret = sync_config_int64(stmt, "onefs_fsid", onefs_fsid); + ret = sync_config_int64(stmt, "onefs_fsid", cfg->onefs_fsid); if (ret) goto out; - ret = sync_config_int(stmt, "dedupe_sequence", seq); + ret = sync_config_int(stmt, "dedupe_sequence", cfg->dedupe_seq); if (ret) goto out; - ret = sync_config_int(stmt, "version_minor", DB_FILE_MINOR); + ret = sync_config_int(stmt, "version_minor", cfg->minor); if (ret) goto out; @@ -392,7 +413,7 @@ int __dbfile_sync_config(sqlite3 *db, unsigned int block_size, dev_t onefs_dev, * Always write version_major last so we have an easy check * whether the config table was fully written. */ - ret = sync_config_int(stmt, "version_major", DB_FILE_MAJOR); + ret = sync_config_int(stmt, "version_major", cfg->major); if (ret) goto out; @@ -407,8 +428,7 @@ int __dbfile_sync_config(sqlite3 *db, unsigned int block_size, dev_t onefs_dev, return ret; } -int dbfile_sync_config(unsigned int block_size, dev_t onefs_dev, - uint64_t onefs_fsid, unsigned int seq) +int dbfile_sync_config(struct dbfile_config *cfg) { sqlite3 *db; int ret; @@ -417,7 +437,7 @@ int dbfile_sync_config(unsigned int block_size, dev_t onefs_dev, if (!db) return ENOENT; - ret = __dbfile_sync_config(db, block_size, onefs_dev, onefs_fsid, seq); + ret = __dbfile_sync_config(db, cfg); return ret; } @@ -640,16 +660,15 @@ static int __dbfile_get_config(sqlite3 *db, unsigned int *block_size, return ret; } -int dbfile_get_config(unsigned int *block_size, uint64_t *num_hashes, - uint64_t *num_files, dev_t *onefs_dev, - uint64_t *onefs_fsid, int *ver_major, int *ver_minor, - char *db_hash_type, unsigned int *db_dedupe_seq) +int dbfile_get_config(struct dbfile_config *cfg) { int ret; - ret = __dbfile_get_config(gdb, block_size, num_hashes, num_files, - onefs_dev, onefs_fsid, ver_major, ver_minor, - db_hash_type, db_dedupe_seq); + ret = __dbfile_get_config(gdb, &cfg->blocksize, &cfg->num_hashes, + &cfg->num_files, &cfg->onefs_dev, + &cfg->onefs_fsid, &cfg->major, + &cfg->minor, cfg->hash_type, + &cfg->dedupe_seq); return ret; } diff --git a/dbfile.h b/dbfile.h index 3f43645f7392..cbcd4ba60167 100644 --- a/dbfile.h +++ b/dbfile.h @@ -6,18 +6,25 @@ struct filerec; struct block_csum; struct extent_csum; struct results_tree; +struct dbfile_config; -int dbfile_create(char *filename, int *dbfile_is_new); -int dbfile_open(char *filename); +int dbfile_create(char *filename, int *dbfile_is_new, struct dbfile_config *cfg); +int dbfile_open(char *filename, struct dbfile_config *cfg); void dbfile_close(void); -/* TODO: Clean up this ridiculous prototype. */ -int dbfile_get_config(unsigned int *block_size, uint64_t *num_hashes, - uint64_t *num_files, dev_t *onefs_dev, - uint64_t *onefs_fsid, int *major, int *minor, - char *db_hash_type, unsigned int *db_dedupe_seq); -int dbfile_sync_config(unsigned int block_size, dev_t onefs_dev, - uint64_t onefs_fsid, unsigned int seq); +struct dbfile_config { + unsigned int blocksize; + uint64_t num_hashes; + uint64_t num_files; + dev_t onefs_dev; + uint64_t onefs_fsid; + int major; + int minor; + char hash_type[8]; + unsigned int dedupe_seq; +}; +int dbfile_get_config(struct dbfile_config *cfg); +int dbfile_sync_config(struct dbfile_config *cfg); struct hash_tree; struct hash_file_header; diff --git a/duperemove.c b/duperemove.c index 3f4a6670c1d3..62307baf15d8 100644 --- a/duperemove.c +++ b/duperemove.c @@ -67,6 +67,7 @@ static int fdupes_mode = 0; static int stdin_filelist = 0; static unsigned int list_only_opt = 0; static unsigned int rm_only_opt = 0; +static struct dbfile_config dbfile_cfg; static enum { H_READ, @@ -99,7 +100,7 @@ static int list_db_files(char *filename) { int ret; - ret = dbfile_open(filename); + ret = dbfile_open(filename, &dbfile_cfg); if (ret) { fprintf(stderr, "Error: Could not open \"%s\"\n", filename); return ret; @@ -166,7 +167,7 @@ static int rm_db_files(char *dbfilename) int ret, err = 0; struct rm_file *rm, *tmp; - ret = dbfile_open(dbfilename); + ret = dbfile_open(dbfilename, &dbfile_cfg); if (ret) { fprintf(stderr, "Error: Could not open \"%s\"\n", dbfilename); return ret; @@ -573,45 +574,44 @@ static void print_header(void) printf("Gathering file list...\n"); } +static int update_config_from_dbfile(void) +{ + dedupe_seq = dbfile_cfg.dedupe_seq; + + if (strncasecmp(dbfile_cfg.hash_type, hash_type, 8)) { + fprintf(stderr, + "Error: Hashfile %s uses %.*s. for checksums " + "but we are using %.*s.\nTry running with " + "--hash=%.*s\n", serialize_fname, 8, + dbfile_cfg.hash_type, 8, hash_type, + 8, dbfile_cfg.hash_type); + return EINVAL; + } + + if (dbfile_cfg.blocksize != blocksize) { + vprintf("Using blocksize %uK from hashfile (%uK " + "blocksize requested).\n", dbfile_cfg.blocksize/1024, + blocksize/1024); + blocksize = dbfile_cfg.blocksize; + } + + return 0; +} + static int create_update_hashfile(int argc, char **argv, int filelist_idx) { int ret; int dbfile_is_new = 0; - ret = dbfile_create(serialize_fname, &dbfile_is_new); + ret = dbfile_create(serialize_fname, &dbfile_is_new, &dbfile_cfg); if (ret) goto out; if (!dbfile_is_new) { - dev_t dev; - uint64_t fsid; - unsigned db_blocksize; - char db_hash_type[8]; - - ret = dbfile_get_config(&db_blocksize, NULL, NULL, &dev, &fsid, - NULL, NULL, db_hash_type, &dedupe_seq); + ret = update_config_from_dbfile(); if (ret) goto out; - - if (strncasecmp(db_hash_type, hash_type, 8)) { - fprintf(stderr, - "Error: Hashfile %s uses %.*s. for checksums " - "but we are using %.*s.\nTry running with " - "--hash=%.*s\n", serialize_fname, 8, - db_hash_type, 8, hash_type, - 8, db_hash_type); - ret = EINVAL; - goto out; - } - - if (db_blocksize != blocksize) { - vprintf("Using blocksize %uK from hashfile (%uK " - "blocksize requested).\n", db_blocksize/1024, - blocksize/1024); - blocksize = db_blocksize; - } - - fs_set_onefs(dev, fsid); + fs_set_onefs(dbfile_cfg.onefs_dev, dbfile_cfg.onefs_fsid); } print_header(); @@ -625,8 +625,11 @@ static int create_update_hashfile(int argc, char **argv, int filelist_idx) goto out; if (dbfile_is_new) { - ret = dbfile_sync_config(blocksize, fs_onefs_dev(), - fs_onefs_id(), dedupe_seq); + dbfile_cfg.blocksize = blocksize; + dbfile_cfg.onefs_dev = fs_onefs_dev(); + dbfile_cfg.onefs_fsid = fs_onefs_id(); + dbfile_cfg.dedupe_seq = dedupe_seq; + ret = dbfile_sync_config(&dbfile_cfg); if (ret) goto out; } else { @@ -733,7 +736,7 @@ int main(int argc, char **argv) } break; case H_READ: - ret = dbfile_open(serialize_fname); + ret = dbfile_open(serialize_fname, &dbfile_cfg); if (ret) { fprintf(stderr, "Error: Could not open dbfile %s.\n", serialize_fname); @@ -744,12 +747,11 @@ int main(int argc, char **argv) * Skips the file scan, used to isolate the * extent-find and dedupe stages */ - ret = dbfile_get_config(&blocksize, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, &dedupe_seq); - if (ret) { - fprintf(stderr, "Error: initializing dbfile config\n"); + blocksize = dbfile_cfg.blocksize; + ret = update_config_from_dbfile(); + if (ret) goto out; - } + print_header(); break; default: @@ -791,8 +793,11 @@ int main(int argc, char **argv) dedupe_seq++; /* Sync to get new dedupe_seq written. */ - ret = dbfile_sync_config(blocksize, fs_onefs_dev(), - fs_onefs_id(), dedupe_seq); + dbfile_cfg.dedupe_seq = dedupe_seq; + dbfile_cfg.blocksize = blocksize; + dbfile_cfg.onefs_dev = fs_onefs_dev(); + dbfile_cfg.onefs_fsid = fs_onefs_id(); + ret = dbfile_sync_config(&dbfile_cfg); if (ret) goto out; } else { diff --git a/hashstats.c b/hashstats.c index efd0909dccf8..068c706c328f 100644 --- a/hashstats.c +++ b/hashstats.c @@ -42,7 +42,7 @@ static int print_blocks = 0; static int num_to_print = 10; static int print_file_list = 0; static char *serialize_fname = NULL; -static uint64_t disk_files, disk_hashes; +static struct dbfile_config dbfile_cfg; static sqlite3_stmt *top_hashes_stmt = NULL; static sqlite3_stmt *files_count_stmt = NULL; @@ -235,7 +235,7 @@ static void print_filerecs(void) "select ino, subvol, blocks, size, filename from files;" printf("Showing %"PRIu64" files.\nInode\tSubvol ID\tBlocks Stored\tSize\tFilename\n", - disk_files); + dbfile_cfg.num_files); ret = sqlite3_exec(gdb, LIST_FILES, print_files_cb, gdb, &errorstr); if (ret) { @@ -245,16 +245,13 @@ static void print_filerecs(void) } } -static unsigned int disk_blocksize; -static int major, minor; - static void print_file_info(void) { printf("Raw header info for \"%s\":\n", serialize_fname); - printf(" version: %d.%d\tblock_size: %u\n", major, minor, - disk_blocksize); + printf(" version: %d.%d\tblock_size: %u\n", dbfile_cfg.major, + dbfile_cfg.minor, dbfile_cfg.blocksize); printf(" num_files: %"PRIu64"\tnum_hashes: %"PRIu64"\n", - disk_files, disk_hashes); + dbfile_cfg.num_files, dbfile_cfg.num_hashes); } static void usage(const char *prog) @@ -345,16 +342,11 @@ int main(int argc, char **argv) if (init_csum_module(DEFAULT_HASH_STR)) return ENOMEM; - ret = dbfile_open(serialize_fname); - if (ret) - return ret; - - ret = dbfile_get_config(&disk_blocksize, &disk_hashes, &disk_files, - NULL, NULL, &major, &minor, NULL, NULL); + ret = dbfile_open(serialize_fname, &dbfile_cfg); if (ret) return ret; - blocksize = disk_blocksize; + blocksize = dbfile_cfg.blocksize; ret = prepare_statements(); if (ret)