示例#1
0
int fs_create(lsm_plugin_ptr c, lsm_pool *pool, const char *name,
              uint64_t size_bytes, lsm_fs **fs, char **job, lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    sqlite3 *db = NULL;
    char err_msg[_LSM_ERR_MSG_LEN];

    _lsm_err_msg_clear(err_msg);
    _good(_check_null_ptr(err_msg, 4 /* argument count */, pool, name, fs, job),
          rc, out);
    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);
    _good(_db_sql_trans_begin(err_msg, db), rc, out);
    _good(_fs_create_internal(err_msg, db, name, size_bytes,
                              _db_lsm_id_to_sim_id(lsm_pool_id_get(pool))),
          rc, out);
    _good(_job_create(err_msg, db, LSM_DATA_TYPE_FS, _db_last_rowid(db),
                      job),
          rc, out);
    _good(_db_sql_trans_commit(err_msg, db), rc, out);

 out:
    if (fs != NULL)
        *fs = NULL;
    if (rc != LSM_ERR_OK) {
        _db_sql_trans_rollback(db);
        if (job != NULL)
            *job = NULL;
        lsm_log_error_basic(c, rc, err_msg);
    }
    if (rc == LSM_ERR_OK)
        rc = LSM_ERR_JOB_STARTED;
    return rc;
}
示例#2
0
int fs_child_dependency_rm(lsm_plugin_ptr c, lsm_fs *fs,
                           lsm_string_list *files, char **job, lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    uint8_t yes = 0;
    char err_msg[_LSM_ERR_MSG_LEN];
    uint64_t sim_fs_id = 0;
    char condition[_BUFF_SIZE];
    sqlite3 *db = NULL;

    _lsm_err_msg_clear(err_msg);

    _good(_check_null_ptr(err_msg, 2 /* argument count */, fs, job), rc, out);

    _good(fs_child_dependency(c, fs, files, &yes), rc, out);
    if (yes == 0) {
        rc = LSM_ERR_NO_STATE_CHANGE;
        _lsm_err_msg_set(err_msg, "Specified file system does not have child "
                         "dependency");
        goto out;
    }

    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);
    _good(_db_sql_trans_begin(err_msg, db), rc, out);

    /*
     * Assuming API definition is break all clone relationship and remove
     * all snapshot of this source file system.
     */

    /* Previous fs_child_dependency() call already checked the fs existence */
    sim_fs_id = _db_lsm_id_to_sim_id(lsm_fs_id_get(fs));

    _snprintf_buff(err_msg, rc, out, condition, "src_fs_id = %" PRIu64,
                   sim_fs_id);
    _good(_db_data_delete_condition(err_msg, db, _DB_TABLE_FS_CLONES,
                                    condition),
          rc, out);

    _snprintf_buff(err_msg, rc, out, condition, "fs_id = %" PRIu64,
                   sim_fs_id);
    _good(_db_data_delete_condition(err_msg, db, _DB_TABLE_FS_SNAPS,
                                    condition),
          rc, out);

    _good(_job_create(err_msg, db, LSM_DATA_TYPE_NONE, _DB_SIM_ID_NONE, job),
          rc, out);
    _good(_db_sql_trans_commit(err_msg, db), rc, out);

 out:
    _db_sql_trans_rollback(db);
    if (rc != LSM_ERR_OK) {
        lsm_log_error_basic(c, rc, err_msg);
    } else {
        rc = LSM_ERR_JOB_STARTED;
    }
    return rc;
}
示例#3
0
int fs_child_dependency(lsm_plugin_ptr c, lsm_fs *fs, lsm_string_list *files,
                        uint8_t *yes)
{
    int rc = LSM_ERR_OK;
    sqlite3 *db = NULL;
    char err_msg[_LSM_ERR_MSG_LEN];
    lsm_hash *sim_fs = NULL;
    uint64_t sim_fs_id = 0;
    char sql_cmd[_BUFF_SIZE];
    struct _vector *vec = NULL;

    _lsm_err_msg_clear(err_msg);

    _good(_check_null_ptr(err_msg, 2 /* argument count */, fs, yes), rc, out);

    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);

    _good(_db_sql_trans_begin(err_msg, db), rc, out);

    sim_fs_id = _db_lsm_id_to_sim_id(lsm_fs_id_get(fs));

    _good(_db_sim_fs_of_sim_id(err_msg, db, sim_fs_id, &sim_fs), rc, out);

    /* Check fs snapshot status */
    _snprintf_buff(err_msg, rc, out, sql_cmd,
                   "SELECT * FROM " _DB_TABLE_FS_SNAPS_VIEW " WHERE fs_id=%"
                   PRIu64 ";", sim_fs_id);

    _good(_db_sql_exec(err_msg, db, sql_cmd, &vec), rc, out);
    if (_vector_size(vec) != 0) {
        *yes = 1;
        goto out;
    }
    _db_sql_exec_vec_free(vec);
    vec = NULL;
    /* Check fs clone(clone here means read and writeable snapshot) */
    _snprintf_buff(err_msg, rc, out, sql_cmd,
                   "SELECT * FROM " _DB_TABLE_FS_CLONES " WHERE src_fs_id = %"
                   PRIu64 ";", sim_fs_id);

    _good(_db_sql_exec(err_msg, db, sql_cmd, &vec), rc, out);
    if (_vector_size(vec) != 0)
        *yes = 1;

 out:
    _db_sql_exec_vec_free(vec);
    if (sim_fs != NULL)
        lsm_hash_free(sim_fs);
    _db_sql_trans_rollback(db);
    if (rc != LSM_ERR_OK) {
        if (yes != NULL)
            *yes = 0;
        lsm_log_error_basic(c, rc, err_msg);
    }
    return rc;
}
示例#4
0
int fs_snapshot_list(lsm_plugin_ptr c, lsm_fs *fs, lsm_fs_ss **ss[],
                     uint32_t *ss_count, lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    struct _vector *vec = NULL;
    sqlite3 *db = NULL;
    char err_msg[_LSM_ERR_MSG_LEN];
    char sql_cmd[_BUFF_SIZE];
    lsm_hash *sim_fs = NULL;
    uint64_t sim_fs_id = 0;

    _lsm_err_msg_clear(err_msg);
    _good(_check_null_ptr(err_msg, 2 /* argument count */, ss, ss_count),
          rc, out);

    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);
    _good(_db_sql_trans_begin(err_msg, db), rc, out);
    /* Check fs existence */
    sim_fs_id = _db_lsm_id_to_sim_id(lsm_fs_id_get(fs));
    _good(_db_sim_fs_of_sim_id(err_msg, db, sim_fs_id, &sim_fs), rc, out);

    _snprintf_buff(err_msg, rc, out, sql_cmd,
                   "SELECT * from " _DB_TABLE_FS_SNAPS_VIEW
                   " WHERE fs_id=%" PRIu64 ";", sim_fs_id);

    _good(_db_sql_exec(err_msg, db, sql_cmd, &vec), rc, out);
    if (_vector_size(vec) == 0) {
        *ss = NULL;
        *ss_count = 0;
        goto out;
    }
    _vec_to_lsm_xxx_array(err_msg, vec, lsm_fs_ss, _sim_fs_snap_to_lsm, ss,
                          ss_count, rc, out);
 out:
    _db_sql_trans_rollback(db);
    _db_sql_exec_vec_free(vec);

    if (sim_fs != NULL)
        lsm_hash_free(sim_fs);

    if (rc != LSM_ERR_OK) {
        if ((ss != NULL) && (ss_count != NULL)) {
            if (*ss != NULL)
                lsm_fs_ss_record_array_free(*ss , *ss_count);
        }
        if (ss != NULL)
            *ss = NULL;
        if (ss_count != NULL)
            *ss_count = 0;
        lsm_log_error_basic(c, rc, err_msg);
    }
    return rc;
}
示例#5
0
int fs_file_clone(lsm_plugin_ptr c, lsm_fs *fs, const char *src_file_name,
                  const char *dest_file_name, lsm_fs_ss *snapshot, char **job,
                  lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    sqlite3 *db = NULL;
    char err_msg[_LSM_ERR_MSG_LEN];
    lsm_hash *sim_fs = NULL;
    lsm_hash *sim_fs_snap = NULL;

    _lsm_err_msg_clear(err_msg);
    _good(_check_null_ptr(err_msg, 4 /* argument count */, fs, src_file_name,
                          dest_file_name, job),
          rc, out);

    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);
    _good(_db_sql_trans_begin(err_msg, db), rc, out);
    /* Check fs existence */
    _good(_db_sim_fs_of_sim_id(err_msg, db,
                               _db_lsm_id_to_sim_id(lsm_fs_id_get(fs)),
                               &sim_fs),
          rc, out);
    if (snapshot != NULL)
        _good(_db_sim_fs_snap_of_sim_id(err_msg, db,
                                        _db_lsm_id_to_sim_id
                                        (lsm_fs_ss_id_get(snapshot)),
                                        &sim_fs_snap),
              rc, out);
    /* We don't have API to query file level clone. So do nothing here */

    _good(_job_create(err_msg, db, LSM_DATA_TYPE_NONE, _DB_SIM_ID_NONE, job),
          rc, out);
    _good(_db_sql_trans_commit(err_msg, db), rc, out);

 out:
    if (sim_fs != NULL)
        lsm_hash_free(sim_fs);
    if (sim_fs_snap != NULL)
        lsm_hash_free(sim_fs_snap);
    if (rc != LSM_ERR_OK) {
        _db_sql_trans_rollback(db);
        if (job != NULL)
            *job = NULL;
        lsm_log_error_basic(c, rc, err_msg);
    } else {
        rc = LSM_ERR_JOB_STARTED;
    }
    return rc;
}
示例#6
0
int fs_snapshot_delete(lsm_plugin_ptr c, lsm_fs *fs, lsm_fs_ss *ss, char **job,
                       lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    sqlite3 *db = NULL;
    char err_msg[_LSM_ERR_MSG_LEN];
    lsm_hash *sim_fs_snap = NULL;
    uint64_t sim_fs_snap_id = 0;

    _lsm_err_msg_clear(err_msg);
    _good(_check_null_ptr(err_msg, 3 /* argument count */, fs, ss, job),
          rc, out);
    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);

    _good(_db_sql_trans_begin(err_msg, db), rc, out);
    sim_fs_snap_id = _db_lsm_id_to_sim_id(lsm_fs_ss_id_get(ss));
    /* The existence of fs snapshot indicate the fs is exist due to the sqlite
     * REFERENCES and PRAGMA foreign_keys = ON
     */
    _good(_db_sim_fs_snap_of_sim_id(err_msg, db, sim_fs_snap_id, &sim_fs_snap),
          rc, out);
    _good(_db_data_delete(err_msg, db, _DB_TABLE_FS_SNAPS, sim_fs_snap_id),
          rc, out);
    _good(_job_create(err_msg, db, LSM_DATA_TYPE_NONE, _DB_SIM_ID_NONE, job),
          rc, out);
    _good(_db_sql_trans_commit(err_msg, db), rc, out);

 out:
    if (sim_fs_snap != NULL)
        lsm_hash_free(sim_fs_snap);

    if (rc != LSM_ERR_OK) {
        _db_sql_trans_rollback(db);
        lsm_log_error_basic(c, rc, err_msg);
        if (job != NULL)
            *job = NULL;
    } else {
        rc = LSM_ERR_JOB_STARTED;
    }
    return rc;
}
示例#7
0
int fs_snapshot_create(lsm_plugin_ptr c, lsm_fs *fs, const char *name,
                       lsm_fs_ss **snapshot, char **job, lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    struct _vector *vec = NULL;
    sqlite3 *db = NULL;
    char err_msg[_LSM_ERR_MSG_LEN];
    lsm_hash *sim_fs = NULL;
    uint64_t sim_fs_id = 0;
    char ts_str[_BUFF_SIZE];
    struct timespec ts;

    _lsm_err_msg_clear(err_msg);
    _good(_check_null_ptr(err_msg, 4 /* argument count */, fs, name, snapshot,
                          job),
          rc, out);

    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);
    _good(_db_sql_trans_begin(err_msg, db), rc, out);
    /* Check fs existence */
    sim_fs_id = _db_lsm_id_to_sim_id(lsm_fs_id_get(fs));
    _good(_db_sim_fs_of_sim_id(err_msg, db, sim_fs_id, &sim_fs), rc, out);

    if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
        rc = LSM_ERR_PLUGIN_BUG;
        _lsm_err_msg_set(err_msg, "BUG: clock_gettime(CLOCK_REALTIME, &ts) "
                         "failed");
        goto out;
    }
    _snprintf_buff(err_msg, rc, out, ts_str, "%" PRIu64,
                   (uint64_t) difftime(ts.tv_sec, 0));

    rc = _db_data_add(err_msg, db, _DB_TABLE_FS_SNAPS,
                      "name", name,
                      "fs_id", _db_lsm_id_to_sim_id_str(lsm_fs_id_get(fs)),
                      "timestamp", ts_str,
                      NULL);

    if (rc != LSM_ERR_OK) {
        if (sqlite3_errcode(db) == SQLITE_CONSTRAINT) {
            rc = LSM_ERR_NAME_CONFLICT;
            _lsm_err_msg_set(err_msg, "FS snapshot name '%s' in use", name);
        }
        goto out;
    }
    _good(_job_create(err_msg, db, LSM_DATA_TYPE_SS, _db_last_rowid(db), job),
          rc, out);
    _good(_db_sql_trans_commit(err_msg, db), rc, out);

 out:
    _db_sql_exec_vec_free(vec);
    if (snapshot != NULL)
        *snapshot = NULL;

    if (sim_fs != NULL)
        lsm_hash_free(sim_fs);

    if (rc != LSM_ERR_OK) {
        lsm_log_error_basic(c, rc, err_msg);
    } else {
        rc = LSM_ERR_JOB_STARTED;
    }
    return rc;
}
示例#8
0
int fs_resize(lsm_plugin_ptr c, lsm_fs *fs, uint64_t new_size,
              lsm_fs ** rfs, char **job, lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    char err_msg[_LSM_ERR_MSG_LEN];
    uint64_t sim_fs_id = 0;
    lsm_hash *sim_fs = NULL;
    uint64_t increment_size = 0;
    uint64_t cur_size = 0;
    uint64_t sim_pool_id = 0;
    char new_size_str[_BUFF_SIZE];
    sqlite3 *db = NULL;

    _lsm_err_msg_clear(err_msg);
    _good(_check_null_ptr(err_msg, 3 /* argument count */, fs,
                          rfs, job),
          rc, out);
    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);
    _good(_db_sql_trans_begin(err_msg, db), rc, out);

    sim_fs_id = _db_lsm_id_to_sim_id(lsm_fs_id_get(fs));
    _good(_db_sim_fs_of_sim_id(err_msg, db, sim_fs_id, &sim_fs), rc, out);
    _good(_str_to_uint64(err_msg, lsm_hash_string_get(sim_fs, "total_space"),
                         &cur_size),
          rc, out);
    new_size = _db_blk_size_rounding(new_size);
    if (cur_size == new_size) {
        rc = LSM_ERR_NO_STATE_CHANGE;
        _lsm_err_msg_set(err_msg, "Specified new size is identical to "
                         "current fs size");
        goto out;
    }
    if (new_size > cur_size) {
        increment_size = new_size - cur_size;
        sim_pool_id = _db_lsm_id_to_sim_id(lsm_fs_pool_id_get(fs));

        if (_pool_has_enough_free_size(db, sim_pool_id, increment_size)
            == false) {
            rc = LSM_ERR_NOT_ENOUGH_SPACE;
            _lsm_err_msg_set(err_msg, "Insufficient space in pool");
            goto out;
        }
    }
    _snprintf_buff(err_msg, rc, out, new_size_str, "%" PRIu64,
                   new_size);
    _good(_db_data_update(err_msg, db, _DB_TABLE_FSS, sim_fs_id,
                          "total_space", new_size_str),
          rc, out);
    _good(_db_data_update(err_msg, db, _DB_TABLE_FSS, sim_fs_id,
                          "consumed_size", new_size_str),
          rc, out);
    _good(_db_data_update(err_msg, db, _DB_TABLE_FSS, sim_fs_id,
                          "free_space", new_size_str),
          rc, out);

    _good(_job_create(err_msg, db, LSM_DATA_TYPE_FS, sim_fs_id, job),
          rc, out);
    _good(_db_sql_trans_commit(err_msg, db), rc, out);

 out:
    if (rfs != NULL)
        *rfs = NULL;
    if (sim_fs != NULL)
        lsm_hash_free(sim_fs);

    if (rc != LSM_ERR_OK) {
        _db_sql_trans_rollback(db);
        if (job != NULL)
            *job = NULL;
        lsm_log_error_basic(c, rc, err_msg);
    } else {
        rc = LSM_ERR_JOB_STARTED;
    }
    return rc;
}
示例#9
0
int fs_clone(lsm_plugin_ptr c, lsm_fs *src_fs, const char *dest_fs_name,
             lsm_fs **cloned_fs, lsm_fs_ss *optional_snapshot, char **job,
             lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    sqlite3 *db = NULL;
    char err_msg[_LSM_ERR_MSG_LEN];
    lsm_hash *sim_fs = NULL;
    lsm_hash *sim_fs_snap = NULL;
    uint64_t sim_fs_id = 0;
    uint64_t dst_sim_fs_id = 0;
    char dst_sim_fs_id_str[_BUFF_SIZE];
    uint64_t sim_fs_snap_id = 0;

    _lsm_err_msg_clear(err_msg);
    _good(_check_null_ptr(err_msg, 4 /* argument count */, src_fs,
                          dest_fs_name, cloned_fs, job),
          rc, out);
    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);

    _good(_db_sql_trans_begin(err_msg, db), rc, out);
    sim_fs_id = _db_lsm_id_to_sim_id(lsm_fs_id_get(src_fs));
    /* Check fs existence */
    _good(_db_sim_fs_of_sim_id(err_msg, db, sim_fs_id, &sim_fs), rc, out);

    if (optional_snapshot != NULL) {
        sim_fs_snap_id = _db_lsm_id_to_sim_id
            (lsm_fs_ss_id_get(optional_snapshot));
        /* No need to trace state of snap id here due to lack of query method.
         * We just check snapshot existence
         */
        _good(_db_sim_fs_snap_of_sim_id(err_msg, db, sim_fs_snap_id,
                                        &sim_fs_snap),
              rc, out);
        lsm_hash_free(sim_fs_snap);
    }

    _good(_fs_create_internal(err_msg, db, dest_fs_name,
                              lsm_fs_total_space_get(src_fs),
                              _db_lsm_id_to_sim_id(lsm_fs_pool_id_get(src_fs))),
          rc, out);

    dst_sim_fs_id = _db_last_rowid(db);

    _snprintf_buff(err_msg, rc, out, dst_sim_fs_id_str, "%" PRIu64,
                   dst_sim_fs_id);

    _good(_db_data_add(err_msg, db, _DB_TABLE_FS_CLONES,
                       "src_fs_id",
                       _db_lsm_id_to_sim_id_str(lsm_fs_id_get(src_fs)),
                       "dst_fs_id", dst_sim_fs_id_str,
                       NULL),
          rc, out);

    _good(_job_create(err_msg, db, LSM_DATA_TYPE_FS, dst_sim_fs_id, job),
          rc, out);
    _good(_db_sql_trans_commit(err_msg, db), rc, out);

 out:
    if (sim_fs != NULL)
        lsm_hash_free(sim_fs);
    if (cloned_fs != NULL)
        *cloned_fs = NULL;
    if (rc != LSM_ERR_OK) {
        _db_sql_trans_rollback(db);
        if (job != NULL)
            *job = NULL;
        lsm_log_error_basic(c, rc, err_msg);
    } else {
        rc = LSM_ERR_JOB_STARTED;
    }
    return rc;
}
示例#10
0
int fs_delete(lsm_plugin_ptr c, lsm_fs *fs, char **job, lsm_flag flags)
{
    int rc = LSM_ERR_OK;
    sqlite3 *db = NULL;
    char err_msg[_LSM_ERR_MSG_LEN];
    lsm_hash *sim_fs = NULL;
    uint64_t sim_fs_id = 0;
    char sql_cmd[_BUFF_SIZE];
    struct _vector *vec = NULL;

    _lsm_err_msg_clear(err_msg);
    _good(_check_null_ptr(err_msg, 2 /* argument count */, fs, job), rc, out);
    _good(_get_db_from_plugin_ptr(err_msg, c, &db), rc, out);

    _good(_db_sql_trans_begin(err_msg, db), rc, out);
    sim_fs_id = _db_lsm_id_to_sim_id(lsm_fs_id_get(fs));
    /* Check fs existence */
    _good(_db_sim_fs_of_sim_id(err_msg, db, sim_fs_id, &sim_fs), rc, out);
    /* Check fs snapshot status */
    _snprintf_buff(err_msg, rc, out, sql_cmd,
                   "SELECT * FROM " _DB_TABLE_FS_SNAPS_VIEW " WHERE fs_id=%"
                   PRIu64 ";", sim_fs_id);

    _good(_db_sql_exec(err_msg, db, sql_cmd, &vec), rc, out);
    if (_vector_size(vec) != 0) {
        rc = LSM_ERR_PLUGIN_BUG;
        /* TODO(Gris Ge): API does not have dedicate error for this scenario.*/
        _lsm_err_msg_set(err_msg, "Specified filesystem has snapshot");
        goto out;
    }
    _db_sql_exec_vec_free(vec);
    vec = NULL;
    /* Check fs clone(clone here means read and writeable snapshot) */
    _snprintf_buff(err_msg, rc, out, sql_cmd,
                   "SELECT * FROM " _DB_TABLE_FS_CLONES " WHERE src_fs_id = %"
                   PRIu64 ";", sim_fs_id);

    _good(_db_sql_exec(err_msg, db, sql_cmd, &vec), rc, out);
    if (_vector_size(vec) != 0) {
        rc = LSM_ERR_PLUGIN_BUG;
        /* We don't have error number for this yet */
        _lsm_err_msg_set(err_msg, "Specified fs is a clone source");
        goto out;
    }

    _good(_db_data_delete(err_msg, db, _DB_TABLE_FSS, sim_fs_id), rc, out);
    _good(_job_create(err_msg, db, LSM_DATA_TYPE_NONE, _DB_SIM_ID_NONE, job),
          rc, out);
    _good(_db_sql_trans_commit(err_msg, db), rc, out);

 out:
    _db_sql_exec_vec_free(vec);
    if (sim_fs != NULL)
        lsm_hash_free(sim_fs);

    if (rc != LSM_ERR_OK) {
        _db_sql_trans_rollback(db);
        lsm_log_error_basic(c, rc, err_msg);
        if (job != NULL)
            *job = NULL;
    } else {
        rc = LSM_ERR_JOB_STARTED;
    }
    return rc;
}
int lsm_scsi_vpd83_of_disk_path(const char *sd_path, const char **vpd83,
                                lsm_error **lsm_err)
{
    char tmp_vpd83[_MAX_VPD83_NAA_ID_LEN];
    const char *sd_name = NULL;
    int rc = LSM_ERR_OK;
    char err_msg[_LSM_ERR_MSG_LEN];

    _lsm_err_msg_clear(err_msg);

    rc = _check_null_ptr(err_msg, 3 /* arg_count */, sd_path, vpd83, lsm_err);

    if (rc != LSM_ERR_OK) {
        if (vpd83 != NULL)
            *vpd83 = NULL;

        goto out;
    }

    if ((strlen(sd_path) <= strlen("/dev/")) ||
        (strncmp(sd_path, "/dev/", strlen("/dev/")) != 0)) {

        _lsm_err_msg_set(err_msg, "Invalid sd_path, should start with /dev/");
        rc = LSM_ERR_INVALID_ARGUMENT;
        goto out;
    }

    sd_name = sd_path + strlen("/dev/");
    if (strlen(sd_name) > _MAX_SD_NAME_STR_LEN) {
        rc = LSM_ERR_INVALID_ARGUMENT;
        _lsm_err_msg_set(err_msg, "Illegal sd_path string, the SCSI disk name "
                         "part(sdX) exceeded the max length %d, current %d",
                         _MAX_SD_NAME_STR_LEN - 1, strlen(sd_name));
        goto out;
    }

    *vpd83 = NULL;
    *lsm_err = NULL;

    rc = _sysfs_vpd83_naa_of_sd_name(err_msg, sd_name, tmp_vpd83);
    if (rc == LSM_ERR_NO_SUPPORT)
        /* Try udev if kernel does not expose vpd83 */
        rc = _udev_vpd83_of_sd_name(err_msg, sd_name, tmp_vpd83);

    if (rc != LSM_ERR_OK)
        goto out;

    if (tmp_vpd83[0] != '\0') {
        *vpd83 = strdup(tmp_vpd83);
        if (*vpd83 == NULL)
            rc = LSM_ERR_NO_MEMORY;
    }

 out:
    if (rc != LSM_ERR_OK) {
        if (lsm_err != NULL)
            *lsm_err = LSM_ERROR_CREATE_PLUGIN_MSG(rc, err_msg);

        if (vpd83 != NULL) {
            free((char *) *vpd83);
            *vpd83= NULL;
        }
    }

    return rc;
}
int lsm_scsi_disk_paths_of_vpd83(const char *vpd83,
                                 lsm_string_list **sd_path_list,
                                 lsm_error **lsm_err)
{
    int rc = LSM_ERR_OK;
    lsm_string_list *sd_name_list = NULL;
    uint32_t i = 0;
    const char *sd_name = NULL;
    char tmp_vpd83[_MAX_VPD83_NAA_ID_LEN];
    char sd_path[_MAX_SD_PATH_STR_LEN];
    bool sysfs_support = true;
    char err_msg[_LSM_ERR_MSG_LEN];

    _lsm_err_msg_clear(err_msg);

    rc = _check_null_ptr(err_msg, 3 /* argument count */, vpd83, sd_path_list,
                         lsm_err);

    if (rc != LSM_ERR_OK) {
        /* set output pointers to NULL if possible when facing error in case
         * application use output memory.
         */
        if (sd_path_list != NULL)
            *sd_path_list = NULL;

        goto out;
    }

    if (strlen(vpd83) >= _MAX_VPD83_NAA_ID_LEN) {
        _lsm_err_msg_set(err_msg, "Provided vpd83 string exceeded the maximum "
                         "string length for SCSI VPD83 NAA ID %d, current %zd",
                         _MAX_VPD83_NAA_ID_LEN - 1, strlen(vpd83));
        rc = LSM_ERR_INVALID_ARGUMENT;
        goto out;
    }


    *lsm_err = NULL;
    *sd_path_list = lsm_string_list_alloc(0 /* no pre-allocation */);
    if (*sd_path_list == NULL) {
        rc = LSM_ERR_NO_MEMORY;
        goto out;
    }

    rc = _sysfs_get_all_sd_names(err_msg, &sd_name_list);
    if (rc != LSM_ERR_OK)
        goto out;

    _lsm_string_list_foreach(sd_name_list, i, sd_name) {
        if (sd_name == NULL)
            continue;
        if (sysfs_support == true) {
            rc = _sysfs_vpd83_naa_of_sd_name(err_msg, sd_name, tmp_vpd83);
            if (rc == LSM_ERR_NO_SUPPORT) {
                sysfs_support = false;
            } else if (rc == LSM_ERR_NOT_FOUND_DISK) {
                /* In case disk got removed after _sysfs_get_all_sd_names() */
                continue;
            }
            else if (rc != LSM_ERR_OK)
                break;
        }
        /* Try udev way if got NO_SUPPORT from sysfs way. */
        if (sysfs_support == false) {
            rc = _udev_vpd83_of_sd_name(err_msg, sd_name, tmp_vpd83);
            if (rc == LSM_ERR_NOT_FOUND_DISK)
                /* In case disk got removed after _sysfs_get_all_sd_names() */
                continue;
            else if (rc != LSM_ERR_OK)
                break;
        }
        if (strncmp(vpd83, tmp_vpd83, _MAX_VPD83_NAA_ID_LEN) == 0) {
            snprintf(sd_path, _MAX_SD_PATH_STR_LEN, _SD_PATH_FORMAT, sd_name);

            if (lsm_string_list_append(*sd_path_list, sd_path) != 0) {
                rc = LSM_ERR_NO_MEMORY;
                goto out;
            }
        }
    }

 out:
    if (sd_name_list != NULL)
        lsm_string_list_free(sd_name_list);

    if (rc == LSM_ERR_OK) {
        /* clean sd_path_list if nothing found */
        if (lsm_string_list_size(*sd_path_list) == 0) {
            lsm_string_list_free(*sd_path_list);
            *sd_path_list = NULL;
        }
    } else {
        /* Error found, clean up */

        if (lsm_err != NULL)
            *lsm_err = LSM_ERROR_CREATE_PLUGIN_MSG(rc, err_msg);

        if ((sd_path_list != NULL) && (*sd_path_list != NULL)) {
            lsm_string_list_free(*sd_path_list);
            *sd_path_list = NULL;
        }
    }

    return rc;
}