コード例 #1
0
ファイル: lustre_tools.c プロジェクト: seagate-ssg/robinhood
/* 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;

}
コード例 #2
0
ファイル: rbh_recov.c プロジェクト: cea-hpc/robinhood
/**
 * 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;
}
コード例 #3
0
/**
 * 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;
}
コード例 #4
0
ファイル: ost_fids_remap.c プロジェクト: martinetd/robinhood
static void usage(const char *argv0)
{
    fprintf(stderr, "Usage: %s <ost_index> <ost_mount_point> <fid_remap_file>\n",
            rh_basename(argv0));
    exit(1);
}
コード例 #5
0
ファイル: rbh_rebind.c プロジェクト: cea-hpc/robinhood
/**
 * 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);
}
コード例 #6
0
ファイル: rbh_diff.c プロジェクト: cea-hpc/robinhood
/**
 * 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 */
}