X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=fsck.c;h=ee7f4ee260df9ada41fb06f072d41d8adca200cc;hp=7bca01637beddba149f7476bd994f1e2940618a0;hb=06372eab260c4d2cba43bfef0d668744aa6c1216;hpb=6c3da3d98f13377c20b6ade64480e7bb9f6f7320 diff --git a/fsck.c b/fsck.c index 7bca0163..ee7f4ee2 100644 --- a/fsck.c +++ b/fsck.c @@ -1,4 +1,17 @@ +/* + * Copyright (C) 1997-2008 Andre Noll + * + * Licensed under the GPL v2. For licencing details see COPYING. + */ + +/** \file fsck.c The program used to check an osl table. */ + + +#include +#include + #include "para.h" +#include "fd.h" #include "error.h" #include "osl_core.h" #include "fsck.cmdline.h" @@ -102,7 +115,7 @@ static int check_index_ranges(struct osl_table *t) { int i, j, ret; - PARA_NOTICE_LOG("checking for range violations in index\n"); + PARA_INFO_LOG("checking for range violations in index\n"); //PARA_DEBUG_LOG("%d rows. %d columns\n", t->num_rows, t->desc->num_columns); t->num_invalid_rows = 0; for (i = 0; i < t->num_rows; i++) { @@ -163,8 +176,8 @@ static int map_index(const struct osl_table_description *desc, struct osl_object char *filename = index_filename(desc); int ret; - ret = mmap_full_file(filename, O_RDWR, map); - PARA_INFO_LOG("mapping index %s: ret: %d, size: %zu\n", filename, ret, map->size); + ret = mmap_full_file(filename, O_RDWR, &map->data, &map->size, NULL); + PARA_DEBUG_LOG("mapping index %s: ret: %d, size: %zu\n", filename, ret, map->size); free(filename); return ret; } @@ -199,7 +212,7 @@ static int prune_invalid_rows_from_index(struct osl_table *t) break; } } - PARA_INFO_LOG("unmapping index\n"); + PARA_DEBUG_LOG("unmapping index\n"); para_munmap(t->index_map.data, t->index_map.size); filename = index_filename(t->desc); ret = para_truncate(filename, t->row_index_size @@ -220,7 +233,7 @@ static int check_for_invalid_objects(struct osl_table *t, uint32_t **lost_bytes) const struct osl_column_description *cd; uint32_t *loss = para_malloc(sizeof(uint32_t) * t->desc->num_columns); - PARA_NOTICE_LOG("looking for mapped objects not contained in index\n"); + PARA_INFO_LOG("looking for mapped objects not contained in index\n"); /* first count used bytes */ FOR_EACH_MAPPED_COLUMN(i, t, cd) { loss[i] = t->columns[i].data_map.size; @@ -421,7 +434,7 @@ static int check_disk_storage_presence(struct osl_table *t) if (!t->num_rows) return 1; hashes = para_malloc(t->num_rows * HASH_SIZE); - PARA_NOTICE_LOG("looking for missing disk storage objects\n"); + PARA_INFO_LOG("looking for missing disk storage objects\n"); for (i = 0; i < t->num_rows; i++) { if (row_is_invalid(t, i)) continue; @@ -461,7 +474,7 @@ static int dummy_compare(const struct osl_object *obj1, const struct osl_object static unsigned files_pruned; -int prune_disk_storage_file(const char *path, const void *private_data) +int prune_disk_storage_file(const char *path, void *private_data) { HASH_TYPE hash[HASH_SIZE]; unsigned flags = *(unsigned *)private_data; @@ -518,10 +531,11 @@ static int prune_disk_storage_files(struct osl_table *t) int i, ret = 1; const struct osl_column_description *cd; - PARA_NOTICE_LOG("looking for unreferenced disk storage files\n"); + PARA_INFO_LOG("looking for unreferenced disk storage files\n"); FOR_EACH_DISK_STORAGE_COLUMN(i, t, cd) { char *dirname = column_filename(t, i); - ret = for_each_file_in_dir(dirname, prune_disk_storage_file, &t->desc->flags); + ret = for_each_file_in_dir(dirname, prune_disk_storage_file, + (unsigned *)&t->desc->flags); free(dirname); } if (files_pruned) @@ -538,7 +552,7 @@ static int check_disk_storage_columns(struct osl_table *t) const struct osl_column_description *cd; if (!t->num_disk_storage_columns) { - PARA_NOTICE_LOG("no disk storage columns in table '%s', " + PARA_INFO_LOG("no disk storage columns in table '%s', " "skipping checks\n", t->desc->name); return 1; } @@ -547,7 +561,7 @@ static int check_disk_storage_columns(struct osl_table *t) ret = init_rbtrees(t); if (ret < 0) return ret; - PARA_NOTICE_LOG("creating rbtree for disk storage hash values\n"); + PARA_INFO_LOG("creating rbtree for disk storage hash values\n"); ret = osl_open_table(&hash_tree_table_desc, &hash_tree_table); if (ret < 0) goto out; @@ -558,6 +572,7 @@ static int check_disk_storage_columns(struct osl_table *t) out_close_hash_tree: osl_close_table(hash_tree_table, 0); free(hashes); + hashes = NULL; out: clear_rbtrees(t); /* TODO why are we doing that here? Seems odd */ return ret; @@ -592,7 +607,7 @@ static int fsck_init(struct osl_table_description *desc, struct osl_table **t) para_munmap(map.data, map.size); goto out; } - PARA_INFO_LOG("unmapping index\n"); + PARA_DEBUG_LOG("unmapping index\n"); para_munmap(map.data, map.size); if (conf.force_given) ret = map_table(*t, (MAP_TBL_FL_IGNORE_DIRTY)); @@ -607,6 +622,9 @@ out: static void fsck_cleanup(struct osl_table *t) { int i; + + if (!t) + return; if (t->desc->column_descriptions) { struct osl_column_description *cd; for (i = 0; i < t->desc->num_columns; i++) { @@ -615,10 +633,8 @@ static void fsck_cleanup(struct osl_table *t) } free(t->desc->column_descriptions); } - if (t) { - free(t->columns); - free(t); - } + free(t->columns); + free(t); } @@ -737,14 +753,14 @@ static int dump_row(struct osl_table *t, unsigned row_num, const char *row_dir) if (!t->num_disk_storage_columns) return 1; dsnc = t->disk_storage_name_column; - ret = get_mapped_object(t, dsnc, i, &obj); + ret = get_mapped_object(t, dsnc, row_num, &obj); if (ret < 0) return ret; hash_object(&obj, hash); ds_name = disk_storage_name_of_hash(t, hash); FOR_EACH_DISK_STORAGE_COLUMN(i, t, cd) { filename = disk_storage_path(t, i, ds_name); - ret = mmap_full_file(filename, O_RDONLY, &obj); + ret = mmap_full_file(filename, O_RDONLY, &obj.data, &obj.size, NULL); free(filename); if (ret < 0) goto out; @@ -775,12 +791,12 @@ static int dump_rows(char *dump_dir, struct osl_table *t) current_dir = make_message("%s/rows_%u-%u", dump_dir, i, i + 999); PARA_NOTICE_LOG("dumping rows %u - %u\n", i, i + 999); ret = para_mkdir(current_dir, 0777); - if (ret < 0) + if (ret < 0 && !is_errno(-ret, EEXIST)) goto out; } row_dir = make_message("%s/row_%03u", current_dir, i); ret = para_mkdir(row_dir, 0777); - if (ret < 0) { + if (ret < 0 && !is_errno(-ret, EEXIST)) { free(row_dir); goto out; } @@ -799,13 +815,18 @@ static int dump_table(char *dump_dir, struct osl_table_description *desc) struct osl_table *t = NULL; int fd, ret = fsck_init(desc, &t); char *desc_file; + char *table_dump_dir = NULL; if (ret < 0) goto out; ret = para_mkdir(dump_dir, 0777); - if (ret < 0) + if (ret < 0 && !is_errno(-ret, EEXIST)) goto out; - desc_file = make_message("%s/table_description.c", dump_dir); + table_dump_dir = make_message("%s/%s", dump_dir, desc->name); + ret = para_mkdir(table_dump_dir, 0777); + if (ret < 0 && !is_errno(-ret, EEXIST)) + goto out; + desc_file = make_message("%s/table_description.c", table_dump_dir); ret = para_open(desc_file, O_WRONLY | O_CREAT | O_EXCL, 0644); free(desc_file); if (ret < 0) @@ -815,8 +836,9 @@ static int dump_table(char *dump_dir, struct osl_table_description *desc) close(fd); if (ret < 0) goto out; - ret = dump_rows(dump_dir, t); + ret = dump_rows(table_dump_dir, t); out: + free(table_dump_dir); fsck_cleanup(t); return ret; } @@ -848,7 +870,6 @@ static int fsck(struct osl_table_description *desc) goto out_unmap; } free(lost_bytes); - PARA_INFO_LOG("success\n"); out_unmap: unmap_table(t, OSL_MARK_CLEAN); out: @@ -856,10 +877,68 @@ out: return ret; } -int main(__a_unused int argc, char **argv) +static int check_table(char *base_dir, char *table_name) +{ + struct osl_table_description desc = { + .column_descriptions = NULL, + .dir = base_dir, + .name = table_name + }; + int ret; + + PARA_INFO_LOG("checking table %s\n", table_name); + if (!conf.no_fsck_given) { + ret = fsck(&desc); + if (ret < 0) + goto out; + } + ret = 1; + if (!conf.dump_dir_given || !*conf.dump_dir_arg) + goto out; + ret = dump_table(conf.dump_dir_arg, &desc); +out: + if (ret < 0) + PARA_ERROR_LOG("failed to check table %s\n", table_name); + else + PARA_NOTICE_LOG("successfully checked table %s\n", table_name); + return ret; +} + +static int check_all_tables(char *base_dir) +{ + DIR *dir; + struct dirent *entry; + int cwd_fd, ret2, ret = para_opendir(base_dir, &dir, &cwd_fd); + + if (ret < 0) + return ret; + while ((entry = readdir(dir))) { + mode_t m; + struct stat s; + if (!strcmp(entry->d_name, ".")) + continue; + if (!strcmp(entry->d_name, "..")) + continue; + if (lstat(entry->d_name, &s) == -1) + continue; + m = s.st_mode; + if (!S_ISDIR(m)) + continue; + ret = check_table(base_dir, entry->d_name); + if (ret < 0) + break; + } + closedir(dir); + ret2 = para_fchdir(cwd_fd); + if (ret2 < 0 && ret >= 0) + ret = ret2; + close(cwd_fd); + return ret; +} + +int main(int argc, char **argv) { int i, ret; - struct osl_table_description desc = {.column_descriptions = NULL}; char *base_dir = NULL; ret = fsck_cmdline_parser(argc, argv, &conf); @@ -868,35 +947,35 @@ int main(__a_unused int argc, char **argv) goto out; } HANDLE_VERSION_FLAG("fsck", conf); - if (!conf.inputs_num) { - /* FIXME: Find all subdirs */ - ret = -E_FSCK_SYNTAX; - goto out; - } - desc.dir = conf.base_dir_arg; - if (!conf.base_dir_given) { + if (conf.base_dir_given) + base_dir = para_strdup(conf.base_dir_arg); + else { char *home = para_homedir(); base_dir = make_message("%s/.paraslash/afs_database", home); free(home); - desc.dir = base_dir; + } + if (!conf.inputs_num) { + ret = check_all_tables(base_dir); + goto out; } for (i = 0; i < conf.inputs_num; i++) { - desc.name = conf.inputs[i]; - if (!conf.no_fsck_given) { - ret = fsck(&desc); - if (ret < 0) - break; - } - if (conf.dump_dir_given && *conf.dump_dir_arg) { - ret = dump_table(conf.dump_dir_arg, &desc); - if (ret < 0) - break; - } + ret = check_table(base_dir, conf.inputs[i]); + if (ret < 0) + break; } - free(base_dir); - ret = 1; out: - if (ret < 0) - PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); + if (ret < 0) { + PARA_ERROR_LOG("%s%s: %s\n", + base_dir? "base_dir: " : "", + base_dir? base_dir : "", + para_strerror(-ret) + ); + if (conf.loglevel_arg > 1) + PARA_EMERG_LOG("re-run with \"--loglevel %d\" to increase verbosity\n", + conf.loglevel_arg - 1); + } else + PARA_NOTICE_LOG("success\n"); + if (base_dir) + free(base_dir); return ret < 0? EXIT_FAILURE : EXIT_SUCCESS; }