/* This code is an adaptation of llapi_mds_getfileinfo() in liblustreapi. * It is unused for now, but could be useful when SOM will be implemented. */ int lustre_mds_stat(const char *fullpath, int parentfd, struct stat *inode) { /* this buffer must be large enough for handling filename */ char buffer[1024]; struct lov_user_mds_data *lmd = ( struct lov_user_mds_data * ) buffer; const char *filename; int rc; /* sanity checks */ if ((fullpath == NULL) || (inode == NULL)) return EINVAL; filename = rh_basename(fullpath); memset(lmd, 0, sizeof(buffer)); rh_strncpy(buffer, filename, strlen(filename) + 1); rc = ioctl(parentfd, IOC_MDC_GETFILEINFO, (void *)lmd); if ( rc ) { if ( errno == ENOTTY ) { /* ioctl is not supported, it is not a lustre fs. * Do the regular lstat(2) instead. */ rc = lstat( fullpath, inode ); if ( rc ) { DisplayLog( LVL_CRIT, TAG_MDSSTAT, "Error: %s: lstat failed for %s", __FUNCTION__, fullpath ); return rc; } } else if ( ( errno == ENOENT ) || ( errno == ESTALE ) ) { DisplayLog( LVL_MAJOR, TAG_MDSSTAT, "Warning: %s: %s does not exist", __FUNCTION__, fullpath ); return ENOENT; } else { DisplayLog(LVL_CRIT, TAG_MDSSTAT, "Error: %s: IOC_MDC_GETFILEINFO failed for %s: rc=%d, errno=%d", __FUNCTION__, fullpath, rc, errno); return rc; } } else *inode = lmd->lmd_st; return 0; }
/** * Main daemon routine */ int main(int argc, char **argv) { int c, option_index = 0; const char *bin; char config_file[MAX_OPT_LEN] = ""; bool do_start = false; bool do_reset = false; bool do_resume = false; bool do_complete = false; bool do_status = false; int list_state = -1; int local_flags = 0; int rc; char err_msg[4096]; robinhood_config_t config; struct sigaction act_sigterm; int chgd = 0; char badcfg[RBH_PATH_MAX]; bin = rh_basename(argv[0]); /* supports NULL argument */ /* parse command line options */ while ((c = getopt_long(argc, argv, SHORT_OPT_STRING, option_tab, &option_index)) != -1) { switch (c) { case 'S': do_start = true; break; case 's': do_status = true; break; case 'Z': do_reset = true; break; case 'c': do_complete = true; break; case 'r': do_resume = true; break; case 'L': if (!strcasecmp(optarg, "all")) list_state = RT_ALL; else if (!strcasecmp(optarg, "done")) list_state = RT_DONE; else if (!strcasecmp(optarg, "failed")) list_state = RT_FAILED; else if (!strcasecmp(optarg, "todo")) list_state = RT_TODO; else { fprintf(stderr, "Invalid parameter for option --list: all, done, failed or todo expected.\n"); exit(1); } break; case 'e': local_flags |= RETRY_ERRORS; break; case 'y': local_flags |= NO_CONFIRM; break; case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); break; case 'D': if (!optarg) { fprintf(stderr, "Missing mandatory argument <path> for --dir\n"); exit(1); } else { rh_strncpy(path_buff, optarg, MAX_OPT_LEN); path_filter = path_buff; } break; case 'o': if (!optarg) { fprintf(stderr, "Missing mandatory argument <ost_index> for --ost\n"); exit(1); } /* parse it as a set */ if (lmgr_range2list(optarg, DB_UINT, &ost_list)) { fprintf(stderr, "Invalid value '%s' for --ost option: integer or set expected (e.g. 2 or 3,5-8,10-12).\n", optarg); exit(1); } /* copy arg to display it */ rh_strncpy(ost_range_str, optarg, sizeof(ost_range_str)); break; case 'b': if (!optarg) { fprintf(stderr, "Missing mandatory argument <date_time> for --since\n"); exit(1); } since_time = str2date(optarg); if (since_time == (time_t)-1) { fprintf(stderr, "Invalid date format: yyyymmdd[HH[MM[SS]]] expected\n"); exit(1); } break; case 'l': { int log_level = str2debuglevel(optarg); if (log_level == -1) { fprintf(stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg); exit(1); } force_debug_level(log_level); break; } case 'h': display_help(bin); exit(0); break; case 'V': display_version(bin); exit(0); break; case ':': case '?': default: display_help(bin); exit(1); break; } } /* check there is no extra arguments */ if (optind != argc) { fprintf(stderr, "Error: unexpected argument on command line: %s\n", argv[optind]); exit(1); } rc = rbh_init_internals(); if (rc != 0) exit(rc); /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file); } /* only read ListMgr config */ if (ReadRobinhoodConfig(0, config_file, err_msg, &config, false)) { fprintf(stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg); exit(1); } /* XXX HOOK: Set logging to stderr */ strcpy(config.log_config.log_file, "stderr"); strcpy(config.log_config.report_file, "stderr"); strcpy(config.log_config.alert_file, "stderr"); /* Initialize logging */ rc = InitializeLogs(bin, &config.log_config); if (rc) { fprintf(stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror(errno)); exit(rc); } /* Initialize filesystem access */ rc = InitFS(); if (rc) exit(rc); /* Initialize status managers (XXX all or just the one used for * recovery?) */ rc = smi_init_all(options.flags); if (rc) exit(rc); /* Initialize list manager */ rc = ListMgr_Init(0); if (rc) { DisplayLog(LVL_CRIT, RECOV_TAG, "Error initializing list manager: %s (%d)", lmgr_err2str(rc), rc); exit(rc); } else DisplayLog(LVL_DEBUG, RECOV_TAG, "ListManager successfully initialized"); if (CheckLastFS() != 0) exit(1); /* Create database access */ rc = ListMgr_InitAccess(&lmgr); if (rc) { DisplayLog(LVL_CRIT, RECOV_TAG, "Error %d: cannot connect to database", rc); exit(rc); } #ifdef _HSM_LITE rc = Backend_Start(&config.backend_config, 0); if (rc) { DisplayLog(LVL_CRIT, RECOV_TAG, "Error initializing backend"); exit(1); } #endif /* create signal handlers */ memset(&act_sigterm, 0, sizeof(act_sigterm)); act_sigterm.sa_flags = 0; act_sigterm.sa_handler = terminate_handler; if (sigaction(SIGTERM, &act_sigterm, NULL) == -1 || sigaction(SIGINT, &act_sigterm, NULL) == -1) { DisplayLog(LVL_CRIT, RECOV_TAG, "Error while setting signal handlers for SIGTERM and SIGINT: %s", strerror(errno)); exit(1); } else DisplayLog(LVL_VERB, RECOV_TAG, "Signals SIGTERM and SIGINT (abort command) are ready to be used"); if (do_status) rc = recov_status(); else if (list_state != -1) rc = recov_list(list_state); else if (do_start) rc = recov_start(); else if (do_reset) rc = recov_reset(local_flags & NO_CONFIRM); else if (do_resume) rc = recov_resume(local_flags & RETRY_ERRORS); else if (do_complete) rc = recov_complete(); else { display_help(bin); rc = 1; } ListMgr_CloseAccess(&lmgr); return rc; }
/** * Main daemon routine */ int main(int argc, char **argv) { int c, option_index = 0; const char *bin; char config_file[MAX_OPT_LEN] = ""; int rc; char err_msg[4096]; robinhood_config_t config; int chgd = 0; char badcfg[RBH_PATH_MAX]; bin = rh_basename(argv[0]); /* parse command line options */ while ((c = getopt_long(argc, argv, SHORT_OPT_STRING, option_tab, &option_index)) != -1) { switch (c) { case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); break; case 'l': { int log_level = str2debuglevel(optarg); if (log_level == -1) { fprintf(stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg); exit(1); } force_debug_level(log_level); break; } case 'h': display_help(bin); exit(0); break; case 'V': display_version(bin); exit(0); break; case ':': case '?': default: display_help(bin); exit(1); break; } } /* 2 expected argument: old backend path, new path is FS */ if (optind > argc - 2) { fprintf(stderr, "Error: missing arguments on command line.\n"); display_help(bin); exit(1); } else if (optind < argc - 3) { fprintf(stderr, "Error: too many arguments on command line.\n"); display_help(bin); exit(1); } /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file); } rc = rbh_init_internals(); if (rc != 0) exit(rc); /* only read ListMgr config */ if (ReadRobinhoodConfig(0, config_file, err_msg, &config, false)) { fprintf(stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg); exit(1); } /* XXX HOOK: Set logging to stderr */ strcpy(config.log_config.log_file, "stderr"); strcpy(config.log_config.report_file, "stderr"); strcpy(config.log_config.alert_file, "stderr"); /* Initialize logging */ rc = InitializeLogs(bin, &config.log_config); if (rc) { fprintf(stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror(errno)); exit(rc); } /* Initialize Filesystem access */ rc = InitFS(); if (rc) exit(rc); /* Initialize status managers (XXX all or just the one used for rebind?) */ rc = smi_init_all(options.flags); if (rc) exit(rc); #ifdef _HSM_LITE rc = Backend_Start(&config.backend_config, 0); if (rc) { DisplayLog(LVL_CRIT, LOGTAG, "Error initializing backend"); exit(1); } #endif if (optind == argc - 2) rc = rebind_helper(argv[optind], argv[optind + 1], NULL); else if (optind == argc - 3) rc = rebind_helper(argv[optind], argv[optind + 1], argv[optind + 2]); return rc; }
static void usage(const char *argv0) { fprintf(stderr, "Usage: %s <ost_index> <ost_mount_point> <fid_remap_file>\n", rh_basename(argv0)); exit(1); }
/** * Main daemon routine */ int main(int argc, char **argv) { int c, option_index = 0; const char *bin; char config_file[MAX_OPT_LEN] = ""; int rc; char err_msg[4096]; bool chgd = false; char badcfg[RBH_PATH_MAX]; char sm_name[SM_NAME_MAX + 1] = ""; bin = rh_basename(argv[0]); /* parse command line options */ while ((c = getopt_long(argc, argv, SHORT_OPT_STRING, option_tab, &option_index)) != -1) { switch (c) { case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); break; case 'l': { int log_level = str2debuglevel(optarg); if (log_level == -1) { fprintf(stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg); exit(1); } force_debug_level(log_level); break; } case 's': if (!EMPTY_STRING(sm_name)) fprintf(stderr, "WARNING: only a single status manager is expected " "on command line. '%s' ignored.\n", optarg); else rh_strncpy(sm_name, optarg, sizeof(sm_name)); break; case 'h': display_help(bin); exit(EXIT_SUCCESS); break; case 'V': display_version(bin); exit(EXIT_SUCCESS); break; case ':': case '?': default: display_help(bin); exit(1); break; } } /* 2 expected argument: old backend path, new path is FS */ if (optind > argc - 3) { fprintf(stderr, "Error: missing arguments on command line.\n"); display_help(bin); exit(1); } else if (optind < argc - 4) { fprintf(stderr, "Error: too many arguments on command line.\n"); display_help(bin); exit(1); } rc = rbh_init_internals(); if (rc != 0) exit(EXIT_FAILURE); /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file); } /* only read common config (listmgr, ...) (mask=0) */ if (rbh_cfg_load(0, config_file, err_msg)) { fprintf(stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg); exit(1); } if (!log_config.force_debug_level) log_config.debug_level = LVL_MAJOR; /* no event message */ /* Set logging to stderr */ strcpy(log_config.log_file, "stderr"); strcpy(log_config.report_file, "stderr"); strcpy(log_config.alert_file, "stderr"); /* Initialize logging */ rc = InitializeLogs(bin); if (rc) { fprintf(stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror(errno)); exit(EXIT_FAILURE); } /* Initialize Filesystem access */ rc = InitFS(); if (rc) exit(EXIT_FAILURE); /* Initialize status managers (XXX all or just the one used for undelete?) */ rc = smi_init_all(0); if (rc) exit(EXIT_FAILURE); /* load the status manager */ if (!EMPTY_STRING(sm_name)) { rc = load_smi(sm_name, &smi); if (rc) exit(EXIT_FAILURE); } else { /* if there is a single smi that allows undelete, use it */ rc = load_single_smi(&smi); if (rc) exit(EXIT_FAILURE); } if (optind == argc - 3) rc = rebind_helper(argv[optind], argv[optind + 1], argv[optind + 2], NULL); else if (optind == argc - 4) rc = rebind_helper(argv[optind], argv[optind + 1], argv[optind + 2], argv[optind + 3]); exit(rc ? EXIT_FAILURE: EXIT_SUCCESS); }
/** * Main daemon routine */ int main(int argc, char **argv) { int c, i, option_index = 0; const char *bin; int rc; char err_msg[4096]; bool chgd = false; char badcfg[RBH_PATH_MAX]; char tag_name[256] = ""; bin = rh_basename(argv[0]); start_time = time(NULL); zero_options(&options); /* parse command line options */ while ((c = getopt_long(argc, argv, SHORT_OPT_STRING, option_tab, &option_index)) != -1) { switch (c) { case 's': options.partial_scan = 1; rh_strncpy(options.partial_scan_path, optarg, RBH_PATH_MAX); /* clean final slash */ if (FINAL_SLASH(options.partial_scan_path)) REMOVE_FINAL_SLASH(options.partial_scan_path); break; case 'd': if (parse_diff_mask(optarg, &options.diff_arg.diff_mask, err_msg)) { fprintf(stderr, "Invalid argument for --diff: %s\n", err_msg); exit(1); } break; case 'a': if (optarg) { if (!strcasecmp(optarg, "fs")) options.diff_arg.apply = APPLY_FS; else if (!strcasecmp(optarg, "db")) options.diff_arg.apply = APPLY_DB; else { fprintf(stderr, "Invalid argument for --apply: '%s' (fs or db expected)\n", optarg); exit(1); } } else options.diff_arg.apply = APPLY_DB; break; case 'D': options.flags |= RUNFLG_DRY_RUN; break; case 'f': rh_strncpy(options.config_file, optarg, MAX_OPT_LEN); break; #ifdef _HSM_LITE case 'b': options.diff_arg.recov_from_backend = 1; break; #endif #ifdef _HAVE_FID /* only for lustre 2.x */ case 'o': rh_strncpy(options.output_dir, optarg, MAX_OPT_LEN); break; #endif case 'l': { int log_level = str2debuglevel(optarg); if (log_level == -1) { fprintf(stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg); exit(1); } force_debug_level(log_level); break; } case 'h': display_help(bin); exit(0); break; case 'V': display_version(bin); exit(0); break; case ':': case '?': default: fprintf(stderr, "Run '%s --help' for more details.\n", bin); exit(1); break; } } /* check there is no extra arguments */ if (optind != argc) { fprintf(stderr, "Error: unexpected argument on command line: %s\n", argv[optind]); exit(1); } /* initialize internal resources (glib, llapi, internal resources...) */ rc = rbh_init_internals(); if (rc != 0) exit(rc); /* get default config file, if not specified */ if (SearchConfig(options.config_file, options.config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", options.config_file); } if (rbh_cfg_load(MODULE_MASK_FS_SCAN | MODULE_MASK_ENTRY_PROCESSOR, options.config_file, err_msg)) { fprintf(stderr, "Error reading configuration file '%s': %s\n", options.config_file, err_msg); exit(1); } if (!log_config.force_debug_level) log_config.debug_level = LVL_CRIT; /* least messages as possible */ /* Set logging to stderr */ strcpy(log_config.log_file, "stderr"); strcpy(log_config.report_file, "stderr"); strcpy(log_config.alert_file, "stderr"); /* Initialize logging */ rc = InitializeLogs(bin); if (rc) { fprintf(stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror(errno)); exit(rc); } /* Initialize filesystem access */ rc = InitFS(); if (rc) exit(rc); /* Initialize status managers */ rc = smi_init_all(options.flags); if (rc) exit(rc); /* Initialize list manager */ rc = ListMgr_Init(0); if (rc) { DisplayLog(LVL_CRIT, DIFF_TAG, "Error initializing list manager: %s (%d)", lmgr_err2str(rc), rc); exit(rc); } else DisplayLog(LVL_VERB, DIFF_TAG, "ListManager successfully initialized"); if (CheckLastFS() != 0) exit(1); if (attr_mask_is_null(options.diff_arg.diff_mask)) { /* parse "all" */ char tmpstr[] = "all"; rc = parse_diff_mask(tmpstr, &options.diff_arg.diff_mask, err_msg); if (rc) { DisplayLog(LVL_CRIT, DIFF_TAG, "unexpected error parsing diff mask: %s", err_msg); exit(1); } } options.diff_arg.diff_mask = translate_all_status_mask(options.diff_arg.diff_mask); #ifdef LUSTRE_DUMP_FILES if (options.diff_arg.apply == APPLY_FS && !(options.flags & RUNFLG_DRY_RUN)) { /* open the file to write LOV EA and FID remapping */ if (!EMPTY_STRING(options.output_dir)) { char fname[RBH_PATH_MAX]; if (mkdir(options.output_dir, 0700) && (errno != EEXIST)) { DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to create directory %s: %s", options.output_dir, strerror(errno)); exit(1); } snprintf(fname, RBH_PATH_MAX - 1, "%s/" LOVEA_FNAME, options.output_dir); options.diff_arg.lovea_file = fopen(fname, "w"); if (options.diff_arg.lovea_file == NULL) { DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to open %s for writing: %s", fname, strerror(errno)); exit(1); } snprintf(fname, RBH_PATH_MAX - 1, "%s/" FIDREMAP_FNAME, options.output_dir); options.diff_arg.fid_remap_file = fopen(fname, "w"); if (options.diff_arg.fid_remap_file == NULL) { DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to open %s for writing: %s", fname, strerror(errno)); exit(1); } } } #endif /* if no DB apply action is specified, can't use md_update field for * checking removed entries. So, create a special tag for that. */ if ((options.diff_arg.apply != APPLY_DB) || (options.flags & RUNFLG_DRY_RUN)) { fprintf(stderr, "Preparing diff table...\n"); /* create a connexion to the DB. this is safe to use the global lmgr var * as statistics thread is not running */ if (!ensure_db_access()) exit(1); /* create a tag to clear entries after the scan */ /* There could be several diff running in parallel, * so set a suffix to avoid conflicts */ sprintf(tag_name, "DIFF_%u", (unsigned int)getpid()); options.diff_arg.db_tag = tag_name; /* add filter for partial scan */ if (options.partial_scan) { lmgr_filter_t filter; filter_value_t val; lmgr_simple_filter_init(&filter); char tmp[RBH_PATH_MAX]; strcpy(tmp, options.partial_scan_path); strcat(tmp, "/*"); val.value.val_str = tmp; lmgr_simple_filter_add(&filter, ATTR_INDEX_fullpath, LIKE, val, 0); rc = ListMgr_CreateTag(&lmgr, tag_name, &filter, false); lmgr_simple_filter_free(&filter); } else rc = ListMgr_CreateTag(&lmgr, tag_name, NULL, false); if (rc) exit(rc); } /* Initialise Pipeline */ rc = EntryProcessor_Init(DIFF_PIPELINE, options.flags, &options.diff_arg); if (rc) { DisplayLog(LVL_CRIT, DIFF_TAG, "Error %d initializing EntryProcessor pipeline", rc); goto clean_tag; } else DisplayLog(LVL_VERB, DIFF_TAG, "EntryProcessor successfully initialized"); fprintf(stderr, "Starting scan\n"); /* print header to indicate the content of diff * #<diff cmd> * ---fs[=/subdir] * +++db */ for (i = 0; i < argc; i++) printf("%s%s", i == 0 ? "# " : " ", argv[i]); printf("\n"); if (options.diff_arg.apply == APPLY_FS) { if (options.partial_scan) printf("---fs=%s\n", options.partial_scan_path); else printf("---fs\n"); printf("+++db\n"); } else { printf("---db\n"); if (options.partial_scan) printf("+++fs=%s\n", options.partial_scan_path); else printf("+++fs\n"); } /* Start FS scan */ if (options.partial_scan) rc = FSScan_Start(options.flags, options.partial_scan_path); else rc = FSScan_Start(options.flags, NULL); if (rc) { DisplayLog(LVL_CRIT, DIFF_TAG, "Error %d initializing FS Scan module", rc); goto clean_tag; } else DisplayLog(LVL_VERB, DIFF_TAG, "FS Scan module successfully initialized"); /* Flush logs now, to have a trace in the logs */ FlushLogs(); /* both pipeline and scan are now running, can now trap events and * display stats */ /* create signal handling thread */ rc = pthread_create(&sig_thr, NULL, signal_handler_thr, NULL); if (rc) { DisplayLog(LVL_CRIT, DIFF_TAG, "Error starting signal handler thread: %s", strerror(errno)); goto clean_tag; } else DisplayLog(LVL_VERB, DIFF_TAG, "Signal handler thread started successfully"); pthread_create(&stat_thread, NULL, stats_thr, NULL); /* wait for FS scan to end */ FSScan_Wait(); DisplayLog(LVL_MAJOR, DIFF_TAG, "FS Scan finished"); /* Pipeline must be flushed */ EntryProcessor_Terminate(true); #ifdef LUSTRE_DUMP_FILES /* flush the lovea file */ if (options.diff_arg.lovea_file) { fprintf(stderr, " > LOV EA information written to %s/" LOVEA_FNAME "\n", options.output_dir); fclose(options.diff_arg.lovea_file); } if (options.diff_arg.fid_remap_file) { fprintf(stderr, " > FID remapping written to %s/" FIDREMAP_FNAME "\n", options.output_dir); fclose(options.diff_arg.fid_remap_file); } #endif fprintf(stderr, "End of scan\n"); DisplayLog(LVL_MAJOR, DIFF_TAG, "All tasks done! Exiting."); rc = 0; clean_tag: /* destroy the tag before exit */ if (options.diff_arg.db_tag != NULL && ensure_db_access()) { fprintf(stderr, "Cleaning diff table...\n"); ListMgr_DestroyTag(&lmgr, options.diff_arg.db_tag); } exit(rc); return rc; /* for compiler */ }