Ejemplo n.º 1
0
static int _sysfs_read_file(char *err_msg, const char *sys_fs_path,
                            uint8_t *buff, ssize_t *size, size_t max_size)
{
    int fd = -1;

    *size = 0;
    memset(buff, 0, max_size);

    fd = open(sys_fs_path, O_RDONLY);
    if (fd < 0) {
        if (errno == ENOENT)
            return LSM_ERR_NO_SUPPORT;

        _lsm_err_msg_set(err_msg, "_sysfs_read_file(): Failed to open %s, "
                         "error: %d, %s", sys_fs_path, errno, strerror(errno));
        return LSM_ERR_LIB_BUG;
    }
    *size = read(fd, buff, max_size);
    close(fd);

    if (*size < 0) {
        _lsm_err_msg_set(err_msg, "Failed to read %s, error: %d, %s",
                         sys_fs_path, errno, strerror(errno));
        return LSM_ERR_LIB_BUG;
    }
    return LSM_ERR_OK;
}
Ejemplo n.º 2
0
static int _fs_create_internal(char *err_msg, sqlite3 *db, const char *name,
                               uint64_t size, uint64_t sim_pool_id)
{
    int rc = LSM_ERR_OK;
    char size_str[_BUFF_SIZE];
    lsm_hash *sim_pool = NULL;
    char sim_pool_id_str[_BUFF_SIZE];
    uint64_t element_type = 0;

    assert(db != NULL);
    assert(name != NULL);

    size = _db_blk_size_rounding(size);
    if (_pool_has_enough_free_size(db, sim_pool_id, 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, size_str, "%" PRIu64, size);
    _snprintf_buff(err_msg, rc, out, sim_pool_id_str, "%" PRIu64, sim_pool_id);
    _good(_db_sim_pool_of_sim_id(err_msg, db, sim_pool_id, &sim_pool),
          rc, out);
    /* Check whether pool support creating fs. */
    _good(_str_to_uint64(err_msg, lsm_hash_string_get(sim_pool, "element_type"),
                         &element_type),
          rc, out);
    if (! (element_type & LSM_POOL_ELEMENT_TYPE_FS)) {
        rc = LSM_ERR_NO_SUPPORT;
        _lsm_err_msg_set(err_msg, "Specified pool does not support fs "
                         "creation");
        goto out;
    }
    rc = _db_data_add(err_msg, db, _DB_TABLE_FSS,
                      "name", name,
                      "total_space", size_str,
                      "consumed_size", size_str,
                      "free_space", size_str,
                      "pool_id", sim_pool_id_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 name '%s' in use", name);
        }
        goto out;
    }

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

    return rc;
}
Ejemplo n.º 3
0
static int _sysfs_get_all_sd_names(char *err_msg,
                                   lsm_string_list **sd_name_list)
{
    DIR *dir = NULL;
    struct dirent *dp = NULL;
    int rc = LSM_ERR_OK;

    *sd_name_list = lsm_string_list_alloc(0 /* no pre-allocation */);
    if (*sd_name_list == NULL) {
        return LSM_ERR_NO_MEMORY;
    }

    dir = opendir(_SYS_BLOCK_PATH);
    if (dir == NULL) {
        _lsm_err_msg_set(err_msg, "Cannot open %s: error (%d)%s",
                         _SYS_BLOCK_PATH, errno, strerror(errno));
        rc = LSM_ERR_LIB_BUG;
        goto out;
    }

    do {
        if ((dp = readdir(dir)) != NULL) {
            if (strncmp(dp->d_name, "sd", strlen("sd")) != 0)
                continue;
            if (strlen(dp->d_name) >= _MAX_SD_NAME_STR_LEN) {
                _lsm_err_msg_set(err_msg, "BUG: Got a SCSI disk name exceeded "
                                 "the maximum string length %d, current %zd",
                                 _MAX_SD_PATH_STR_LEN, strlen(dp->d_name));
                rc = LSM_ERR_LIB_BUG;
                goto out;
            }
            if (lsm_string_list_append(*sd_name_list, dp->d_name) != 0) {
                rc = LSM_ERR_NO_MEMORY;
                goto out;
            }
        }
    } while(dp != NULL);

 out:
    if (dir != NULL) {
        if (closedir(dir) != 0) {
            _lsm_err_msg_set(err_msg, "Failed to close dir %s: error (%d)%s",
                             _SYS_BLOCK_PATH, errno, strerror(errno));
            rc = LSM_ERR_LIB_BUG;
        }
    }

    if (rc != LSM_ERR_OK) {
        lsm_string_list_free(*sd_name_list);
        *sd_name_list = NULL;
    }
    return rc;
}
Ejemplo n.º 4
0
lsm_fs *_sim_fs_to_lsm(char *err_msg, lsm_hash *sim_fs)
{
    const char *plugin_data = NULL;
    uint64_t total_space = 0;
    uint64_t free_space = 0;
    lsm_fs *lsm_fs_obj = NULL;

    assert(sim_fs != NULL);

    if ((_str_to_uint64(err_msg, lsm_hash_string_get(sim_fs, "free_space"),
                        &free_space) != LSM_ERR_OK) ||
        (_str_to_uint64(err_msg, lsm_hash_string_get(sim_fs, "total_space"),
                        &total_space) != LSM_ERR_OK))
        return NULL;

    lsm_fs_obj = lsm_fs_record_alloc
        (lsm_hash_string_get(sim_fs, "lsm_fs_id"),
         lsm_hash_string_get(sim_fs, "name"),
         total_space, free_space, lsm_hash_string_get(sim_fs, "lsm_pool_id"),
         _SYS_ID, plugin_data);

    if (lsm_fs_obj == NULL)
        _lsm_err_msg_set(err_msg, "No memory");

    return lsm_fs_obj;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/*
 * Assume input path is not NULL or empty string.
 * Try to open provided path file or folder, return true if file could be open,
 * or false.
 */
static bool _file_is_exist(char *err_msg, const char *path)
{
    int fd = 0;

    fd = open(path, O_RDONLY);
    if (fd == -1) {
        _lsm_err_msg_set(err_msg, "Failed to open %s, error: %d, %s",
                         path, errno, strerror(errno));
        return false;
    }
    close(fd);
    return true;
}
Ejemplo n.º 7
0
/*
 * Try to parse /sys/block/sda/device/vpd_pg83 for VPD83 NAA ID first.
 * This sysfs file is missing in some older kernel(like RHEL6), we use udev
 * ID_WWN_WITH_EXTENSION property instead, even through ID_WWN_WITH_EXTENSION
 * does not mean VPD83 NAA ID, this is the only workaround I could found for
 * old system without root privilege.
 * Input *vpd83 should be char[_MAX_VPD83_NAA_ID_LEN], assuming caller did
 * the check.
 * The maximum *sd_name strlen is (_MAX_SD_NAME_STR_LEN - 1), assuming caller
 * did the check.
 */
static int _udev_vpd83_of_sd_name(char *err_msg, const char *sd_name,
                                  char *vpd83)
{
    struct udev *udev = NULL;
    struct udev_device *sd_udev = NULL;
    int rc = LSM_ERR_OK;
    const char *wwn = NULL;
    char sys_path[_MAX_SYSFS_BLK_PATH_STR_LEN];

    memset(vpd83, 0, _MAX_VPD83_NAA_ID_LEN);
    snprintf(sys_path, _MAX_SYSFS_BLK_PATH_STR_LEN, _SYSFS_BLK_PATH_FORMAT,
             sd_name);

    udev = udev_new();
    if (udev == NULL) {
        rc = LSM_ERR_NO_MEMORY;
        goto out;
    }

    sd_udev = udev_device_new_from_syspath(udev, sys_path);
    if (sd_udev == NULL) {
        _lsm_err_msg_set(err_msg, "Provided disk not found");
        rc = LSM_ERR_NOT_FOUND_DISK;
        goto out;
    }
    wwn = udev_device_get_property_value(sd_udev, "ID_WWN_WITH_EXTENSION");
    if (wwn == NULL)
        goto out;

    if (strncmp(wwn, "0x", strlen("0x")) == 0)
        wwn += strlen("0x");

    snprintf(vpd83, _MAX_VPD83_NAA_ID_LEN, wwn);

 out:
    if (udev != NULL)
        udev_unref(udev);

    if (sd_udev != NULL)
        udev_device_unref(sd_udev);

    return rc;
}
Ejemplo n.º 8
0
lsm_fs_ss *_sim_fs_snap_to_lsm(char *err_msg, lsm_hash *sim_fs_snap)
{
    const char *plugin_data = NULL;
    uint64_t timestamp = 0;
    lsm_fs_ss *lsm_fs_snap = NULL;

    assert(sim_fs_snap != NULL);

    if (_str_to_uint64(err_msg, lsm_hash_string_get(sim_fs_snap, "timestamp"),
                       &timestamp) != LSM_ERR_OK)
        return NULL;

    lsm_fs_snap = lsm_fs_ss_record_alloc
        (lsm_hash_string_get(sim_fs_snap, "lsm_fs_snap_id"),
         lsm_hash_string_get(sim_fs_snap, "name"),
         timestamp, plugin_data);

    if (lsm_fs_snap == NULL)
        _lsm_err_msg_set(err_msg, "No memory");

    return lsm_fs_snap;
}
Ejemplo n.º 9
0
/*
 * Check whether input pointer is NULL.
 * If found NULL pointer, set error message and return LSM_ERR_INVALID_ARGUMENT.
 * Return LSM_ERR_OK if no NULL pointer.
 */
static int _check_null_ptr(char *err_msg, int arg_count, ...)
{
    int rc = LSM_ERR_OK;
    va_list arg;
    int i = 0;
    void *ptr = NULL;

    va_start(arg, arg_count);

    for (; i < arg_count; ++i) {
        ptr = va_arg(arg, void*);
        if (ptr == NULL) {
            _lsm_err_msg_set(err_msg, "Got NULL pointer in arguments");
            rc = LSM_ERR_INVALID_ARGUMENT;
            goto out;
        }
    }

 out:
    va_end(arg);
    return rc;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
/*
 * Parse _SYSFS_VPD83_PATH_FORMAT file for VPD83 NAA ID.
 * When no such sysfs file found, return LSM_ERR_NO_SUPPORT.
 * When VPD83 page does not have NAA ID, return LSM_ERR_OK and vpd83 as empty
 * string.
 *
 * Input *vpd83 should be char[_MAX_VPD83_NAA_ID_LEN], assuming caller did
 * the check.
 * The maximum *sd_name strlen is (_MAX_SD_NAME_STR_LEN - 1), assuming caller
 * did the check.
 * Return LSM_ERR_NO_MEMORY or LSM_ERR_NO_SUPPORT or LSM_ERR_LIB_BUG or
 *        LSM_ERR_NOT_FOUND_DISK
 */
static int _sysfs_vpd83_naa_of_sd_name(char *err_msg, const char *sd_name,
                                       char *vpd83)
{
    ssize_t read_size = 0;
    uint8_t *end_p = NULL;
    uint8_t *p = NULL;
    struct t10_vpd83_header *vpd83_header = NULL;
    uint32_t vpd83_len = 0;
    struct t10_vpd83_id_header *id_header = NULL;
    struct t10_vpd83_naa_header *naa_header = NULL;
    int rc = LSM_ERR_OK;
    uint8_t buff[_MAX_VPD83_PAGE_LEN];
    char sysfs_path[_MAX_SYSFS_VPD83_PATH_STR_LEN];
    char sysfs_blk_path[_MAX_SYSFS_BLK_PATH_STR_LEN];

    memset(vpd83, 0, _MAX_VPD83_NAA_ID_LEN);

    if (sd_name == NULL) {
        _lsm_err_msg_set(err_msg, "_sysfs_vpd83_naa_of_sd_name(): "
                         "Input sd_name argument is NULL");
        rc = LSM_ERR_LIB_BUG;
        goto out;
    }

    /*
     * Check the existence of disk vis /sys/block/sdX folder.
     */
    snprintf(sysfs_blk_path, _MAX_SYSFS_BLK_PATH_STR_LEN,
             _SYSFS_BLK_PATH_FORMAT, sd_name);
    if (_file_is_exist(err_msg, sysfs_blk_path) == false) {
        rc = LSM_ERR_NOT_FOUND_DISK;
        goto out;
    }

    snprintf(sysfs_path, _MAX_SYSFS_VPD83_PATH_STR_LEN,
             _SYSFS_VPD83_PATH_FORMAT, sd_name);

    rc = _sysfs_read_file(err_msg, sysfs_path, buff, &read_size,
                          _MAX_VPD83_PAGE_LEN);

    if (rc != LSM_ERR_OK)
        goto out;

    /* Return NULL and LSM_ERR_OK when got invalid sysfs file */
    /* Read size is smaller than VPD83 header */
    if (read_size < sizeof(struct t10_vpd83_header))
        goto out;

    vpd83_header = (struct t10_vpd83_header*) buff;

    /* Incorrect page code */
    if (vpd83_header->page_code != _T10_VPD83_PAGE_CODE)
        goto out;

    vpd83_len = (((uint32_t) vpd83_header->page_len_msb) << 8) +
        vpd83_header->page_len_lsb + sizeof(struct t10_vpd83_header);

    end_p = buff + vpd83_len - 1;
    p = buff + sizeof(struct t10_vpd83_header);


    while(p <= end_p) {
        /* Corrupted data: facing data end */
        if (p + sizeof(struct t10_vpd83_id_header) > end_p)
            goto out;

        id_header = (struct t10_vpd83_id_header *) p;
        /* Skip non-NAA ID */
        if (id_header->designator_type != _T10_VPD83_DESIGNATOR_TYPE_NAA)
            goto next_one;

        naa_header = (struct t10_vpd83_naa_header *)
            ((uint8_t *)id_header + sizeof(struct t10_vpd83_id_header));

        switch(naa_header->naa_type) {
        case _T10_VPD83_NAA_TYPE_2:
        case _T10_VPD83_NAA_TYPE_3:
        case _T10_VPD83_NAA_TYPE_5:
            _be_raw_to_hex((uint8_t *) naa_header, _T10_VPD83_NAA_235_ID_LEN,
                           vpd83);
            break;
        case _T10_VPD83_NAA_TYPE_6:
            _be_raw_to_hex((uint8_t *) naa_header, _T10_VPD83_NAA_6_ID_LEN,
                           vpd83);
            break;
        default:
            /* Skip for Unknown NAA ID type */
            goto next_one;
        }
        /* Quit when found first NAA ID */
        if (vpd83[0] != 0)
            break;

     next_one:
        p = (uint8_t *) id_header + id_header->len +
            sizeof(struct t10_vpd83_id_header);
        continue;
    }

 out:
    return rc;
}