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; }
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; }
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; }
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; }
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; }
/* * 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; }
/* * 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; }
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"), ×tamp) != 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; }
/* * 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; }
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; }
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; }
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; }
/* * 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; }