/* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

// don't change the include order
#include "adapter.h"
#include "pd.h"
#include "sml_errcodes.h"
#include "ld.h"

#ifdef ITEST_ENABLED
#include "ibmc_itest_sml.h"
#endif

/*
 * Description: 检查Array Ref是否在该RAID控制器的Array列表中
 * History: 1.2016年11月8日,  ()
 *          新生成函数
 */
static gint32 check_array_ref(guint16 array_ref, SML_ARRAY_LIST_S *array_lists, guint8 *array_index)
{
    guint16 idx = 0;
    gint32 result = RET_OK;

    if (array_lists == NULL) {
        return SML_ERR_NULL_DATA;
    }

    for (idx = 0; idx < array_lists->array_count; idx++) {
        if (array_ref == array_lists->array_refs[idx]) {
            *array_index = idx;
            break;
        }
    }

    if (idx == array_lists->array_count) {
        result = RET_ERR;
    }

    return result;
}

/*
 * Description: 获取LD的基本信息
 * History: 1.2016年11月8日, ()
 *          新生成函数
 */
gint32 smlib_get_array_info(guint8 ctrl_index, guint16 array_ref, SML_ARRAY_INFO_S *array)
{
    gint32 retval = SML_SUCCESS;
    guint8 array_index = 0;
    guint32 current_timestamp = 0;
    guint32 last_udate_timestamp = 0;
    guint8 updated = FALSE;
    SML_ARRAY_INFO_S new_array_info = { 0 };
    guint8 refresh_polciy = 0;
    gint32 data_validity = 0;
    gint32 locked = FALSE;
    SML_CTRL_S* sml_ctrl = NULL;

    if (SML_SUCCESS != (retval = check_input_parameters(ctrl_index, array))) {
        return retval;
    }
    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_array_ref(array_ref, &sml_ctrl->controller.arraylist, &array_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_ARRAY_INVALID_ARRAY_REF;
    }

#ifdef ITEST_ENABLED
    current_timestamp = iTest_get_cur_time_stamp();
#else
    current_timestamp = (guint32)time(0);
#endif

    g_mutex_lock(&sml_ctrl->ctrl_mutex);
    last_udate_timestamp = sml_ctrl->controller.array[array_index].last_update_timestamp;
    refresh_polciy = sml_ctrl->controller.array_refresh_ctrl[array_ref & 0xff];
    g_mutex_unlock(&sml_ctrl->ctrl_mutex);

    // 上次更新数据的时间是0或者距离上次更新数据已经超过数据更新时间间隔，并且当前控制器没有在执行任何操作，否则直接取缓存数据
    data_validity = check_cache_data_is_expired(refresh_polciy, current_timestamp, last_udate_timestamp,
        3 * SMLIB_UPDATE_CACHE_DATA_INTREVAL);
    // 超时刷新，试探获取操作锁；如果是无效数据或者强制刷新，必须等待获取操作锁
    if (CACHE_DATA_INVALID_TIMEOUT == data_validity) {
        if (g_mutex_trylock(&sml_ctrl->op_mutex)) {
            locked = TRUE;
        } else {
            debug_log(DLOG_DEBUG, "smlib_get_array_info: op_mutex locked, skip operation\n");
        }
    } else if ((CACHE_DATA_INVALID_NO_DATA == data_validity) || (CACHE_DATA_INVALID_FORCED == data_validity)) {
        g_mutex_lock(&sml_ctrl->op_mutex);
        locked = TRUE;
    }

    if (locked) {
        if (NULL != sml_ctrl->pfn_get_array_info) {
            // 调用适配层接口获取数据，成功则将数据更新至全局缓存数据区
            retval = sml_ctrl->pfn_get_array_info(sml_ctrl->controller_id, array_ref,
                &new_array_info);
            if (SML_SUCCESS == retval) {
                updated = TRUE;
            } else {
                /* BEGIN: Modified for PN:CSEC on 2018/12/7 */
                debug_log(DLOG_DEBUG,
                    "smlib: Get RAID controller [Ctrl index %d, Ctrl ID %d] Array info failed, return 0x%04x\n",
                    ctrl_index, SML_CTRL_ID_VALID_BIT(sml_ctrl->controller_id), retval);
            }
        } else {
            retval = SML_ERR_NULL_INFTERFACE;
        }

        g_mutex_unlock(&sml_ctrl->op_mutex);
    }

    // 实际从RAID卡更新数据会耗费几百毫秒到几秒的时间，这里再次获取当前系统时间记录更准确
#ifdef ITEST_ENABLED
    current_timestamp = iTest_get_cur_time_stamp();
#else
    current_timestamp = (guint32)time(0);
#endif

    // 集中更新缓存数据，拷贝需要返回的数据
    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    // 从RAID卡实际执行结果更新数据到全局缓存
    if (TRUE == updated) {
        memcpy_s(&sml_ctrl->controller.array[array_index], sizeof(SML_ARRAY_INFO_S), &new_array_info,
            sizeof(SML_ARRAY_INFO_S));
        sml_ctrl->controller.array[array_index].last_update_timestamp = current_timestamp;
        sml_ctrl->controller.array_refresh_ctrl[array_ref & 0xff] = update_refresh_policy(refresh_polciy);
    } else {
        // 如果强制从缓存读取数据，则需要刷新最后更新的时间
        if ((RAID_REFRESH_INTERNAL_CACHE == (refresh_polciy & 0x0f)) && (refresh_polciy & 0xf0)) {
            sml_ctrl->controller.array[array_index].last_update_timestamp = current_timestamp;
            sml_ctrl->controller.array_refresh_ctrl[array_ref & 0xff] =
                update_refresh_policy(refresh_polciy);
        }
    }

    /* END:   Modified for PN:CSEC on 2018/12/7 */
    memcpy_s(array, sizeof(SML_ARRAY_INFO_S), &sml_ctrl->controller.array[array_index],
        sizeof(SML_ARRAY_INFO_S));

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return retval;
}
/* END:   Added on 2016/11/8 */

/*
 * Description: 获取LD的基本信息
 * History: 1.2016年3月10日
 *          新生成函数
 */
gint32 smlib_get_ld_info(guint8 ctrl_index, guint16 ld_target_id, SML_LD_BASIC_INFO_S *ld)
{
    gint32 retval = SML_SUCCESS;
    guint8 ld_index = 0;
    guint32 current_timestamp = 0;
    guint32 last_udate_timestamp = 0;
    guint8 updated = FALSE;
    SML_LD_BASIC_INFO_S new_ld_info = { 0 };
    guint8 refresh_polciy = 0;
    gint32 data_validity = 0;
    gint32 locked = FALSE;

    guint8 try_count = 0;
    SML_CTRL_S* sml_ctrl = NULL;

    if (SML_SUCCESS != (retval = check_input_parameters(ctrl_index, ld))) {
        return retval;
    }
    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(ld_target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }

#ifdef ITEST_ENABLED
    current_timestamp = iTest_get_cur_time_stamp();
#else
    current_timestamp = (guint32)time(0);
#endif

    g_mutex_lock(&sml_ctrl->ctrl_mutex);
    last_udate_timestamp = sml_ctrl->controller.ld[ld_index].ldinfo.last_update_timestamp;
    refresh_polciy = sml_ctrl->controller.ld_refresh_ctrl[ld_target_id];
    g_mutex_unlock(&sml_ctrl->ctrl_mutex);

    // 上次更新数据的时间是0或者距离上次更新数据已经超过数据更新时间间隔，并且当前控制器没有在执行任何操作，否则直接取缓存数据
    data_validity = check_cache_data_is_expired(refresh_polciy, current_timestamp, last_udate_timestamp,
        3 * SMLIB_UPDATE_CACHE_DATA_INTREVAL);
    // 超时刷新，试探获取操作锁；如果是无效数据或者强制刷新，必须等待获取操作锁
    if (CACHE_DATA_INVALID_TIMEOUT == data_validity) {
        if (g_mutex_trylock(&sml_ctrl->op_mutex)) {
            locked = TRUE;
        } else {
            debug_log(DLOG_DEBUG, "smlib_get_ld_info: op_mutex locked, skip operation\n");
        }
    } else if ((CACHE_DATA_INVALID_NO_DATA == data_validity) || (CACHE_DATA_INVALID_FORCED == data_validity)) {
        g_mutex_lock(&sml_ctrl->op_mutex);
        locked = TRUE;
    }

    if (locked) {
        if (NULL != sml_ctrl->pfn_get_ld_info) {
            do {
                (void)memset_s(&new_ld_info, sizeof(SML_LD_BASIC_INFO_S), 0, sizeof(SML_LD_BASIC_INFO_S));
                new_ld_info.ld_warnig_info_reported =
                    sml_ctrl->controller.ld[ld_index].ldinfo.ld_warnig_info_reported;
                // 调用适配层接口获取数据，成功则将数据更新至全局缓存数据区
                retval = sml_ctrl->pfn_get_ld_info(sml_ctrl->controller_id, ld_target_id,
                    &new_ld_info);

                // 从RAID卡读取数据成功的就可以更新数据
                updated = (SML_SUCCESS == retval) ? TRUE : FALSE;

                if (SML_SUCCESS == retval) {
                    // 逻辑盘状态告警
                    if (new_ld_info.drive_state == LD_STATE_OFFLINE) {
                        // 已经上报的告警，直接标记信息确认次数为最大
                        if (new_ld_info.ld_warnig_info_reported) {
                            break;
                        }
                        // 防抖
                        g_mutex_unlock(&sml_ctrl->op_mutex);
                        unlock_ctrl_list_mutex(ctrl_index);
                        vos_task_delay(RAID_INFO_DEBOUNCE_DELAY);
                        try_count++;
                        lock_ctrl_list_mutex(ctrl_index);
                        if (sml_ctrl == NULL) {
                            unlock_ctrl_list_mutex(ctrl_index);
                            return SML_ERR_CTRL_NOT_REGISTERED;
                        }
                        g_mutex_lock(&sml_ctrl->op_mutex);
                    } else {
                        new_ld_info.ld_warnig_info_reported = 0;
                        break;
                    }
                } else {
                    debug_log(DLOG_DEBUG,
                        "smlib: Get RAID controller [Ctrl index %d, Ctrl ID %d] LD info failed, return 0x%04x\n",
                        ctrl_index, SML_CTRL_ID_VALID_BIT(sml_ctrl->controller_id), retval);
                    break;
                }
            } while (try_count < MAX_WARNNING_INFO_DEBOUNCE_COUNT);
        } else {
            retval = SML_ERR_NULL_INFTERFACE;
        }

        g_mutex_unlock(&sml_ctrl->op_mutex);
    }
    // 连续三次获取为0则告警
    if (try_count == MAX_WARNNING_INFO_DEBOUNCE_COUNT) {
        new_ld_info.ld_warnig_info_reported = 1;
    }

    // 实际从RAID卡更新数据会耗费几百毫秒到几秒的时间，这里再次获取当前系统时间记录更准确
#ifdef ITEST_ENABLED
    current_timestamp = iTest_get_cur_time_stamp();
#else
    current_timestamp = (guint32)time(0);
#endif

    // 集中更新缓存数据，拷贝需要返回的数据
    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    // 从RAID卡实际执行结果更新数据到全局缓存
    if (updated) {
        memcpy_s(&sml_ctrl->controller.ld[ld_index].ldinfo, sizeof(SML_LD_BASIC_INFO_S), &new_ld_info,
            sizeof(SML_LD_BASIC_INFO_S));
        sml_ctrl->controller.ld[ld_index].ldinfo.last_update_timestamp = current_timestamp;
        sml_ctrl->controller.ld_refresh_ctrl[ld_target_id] = update_refresh_policy(refresh_polciy);
    } else {
        // 如果强制从缓存读取数据，则需要刷新最后更新的时间
        if ((RAID_REFRESH_INTERNAL_CACHE == (refresh_polciy & 0x0f)) && (refresh_polciy & 0xf0)) {
            sml_ctrl->controller.ld[ld_index].ldinfo.last_update_timestamp = current_timestamp;
            sml_ctrl->controller.ld_refresh_ctrl[ld_target_id] = update_refresh_policy(refresh_polciy);
        }
    }

    memcpy_s(ld, sizeof(SML_LD_BASIC_INFO_S), &sml_ctrl->controller.ld[ld_index].ldinfo,
        sizeof(SML_LD_BASIC_INFO_S));

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return retval;
}
/*
 * Description: 获取LD的成员盘列表（PD）
 * History: 1.2016年3月10日
 *          新生成函数
 */
gint32 smlib_get_ld_pd_list(guint8 ctrl_index, guint16 ld_target_id, SML_PD_LIST_S *ld)
{
    gint32 retval = SML_SUCCESS;
    guint8 ld_index = 0;
    guint32 current_timestamp = 0;
    guint32 last_udate_timestamp = 0;
    /* BEGIN: Modified for PN:CSEC on 2018/12/7 */
    guint8 update = FALSE;
    SML_PD_LIST_S new_pd_list = { 0 };
    guint8 refresh_polciy = 0;
    gint32 data_validity = 0;
    gint32 locked = FALSE;
    SML_CTRL_S* sml_ctrl = NULL;

    if (SML_SUCCESS != (retval = check_input_parameters(ctrl_index, ld))) {
        return retval;
    }
    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(ld_target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }

#ifdef ITEST_ENABLED
    current_timestamp = iTest_get_cur_time_stamp();
#else
    current_timestamp = (guint32)time(0);
#endif

    g_mutex_lock(&sml_ctrl->ctrl_mutex);
    last_udate_timestamp = sml_ctrl->controller.ld[ld_index].pd_in_ld.last_update_timestamp;
    refresh_polciy = sml_ctrl->controller.pd_in_ld_refresh_ctrl[ld_target_id];
    g_mutex_unlock(&sml_ctrl->ctrl_mutex);

    // 上次更新数据的时间是0或者距离上次更新数据已经超过数据更新时间间隔，并且当前控制器没有在执行任何操作，否则直接取缓存数据
    data_validity = check_cache_data_is_expired(refresh_polciy, current_timestamp, last_udate_timestamp,
        3 * SMLIB_UPDATE_CACHE_DATA_INTREVAL);
    // 超时刷新，试探获取操作锁；如果是无效数据或者强制刷新，必须等待获取操作锁
    if (CACHE_DATA_INVALID_TIMEOUT == data_validity) {
        if (g_mutex_trylock(&sml_ctrl->op_mutex)) {
            locked = TRUE;
        } else {
            debug_log(DLOG_DEBUG, "smlib_get_ld_pd_list: op_mutex locked, skip operation\n");
        }
    } else if ((CACHE_DATA_INVALID_NO_DATA == data_validity) || (CACHE_DATA_INVALID_FORCED == data_validity)) {
        g_mutex_lock(&sml_ctrl->op_mutex);
        locked = TRUE;
    }

    if (locked) {
        if (NULL != sml_ctrl->pfn_get_ld_pd_list) {
            // 调用适配层接口获取数据，成功则将数据更新至全局缓存数据区
            retval = sml_ctrl->pfn_get_ld_pd_list(sml_ctrl->controller_id, ld_target_id,
                &new_pd_list);
            if (SML_SUCCESS == retval) {
                update = TRUE;
            } else {
                debug_log(DLOG_DEBUG,
                    "smlib: Get RAID controller [Ctrl index %d, Ctrl ID %d] LD info failed, return 0x%04x\n",
                    ctrl_index, SML_CTRL_ID_VALID_BIT(sml_ctrl->controller_id), retval);
            }
        } else {
            retval = SML_ERR_NULL_INFTERFACE;
        }

        g_mutex_unlock(&sml_ctrl->op_mutex);
    }

    // 实际从RAID卡更新数据会耗费几百毫秒到几秒的时间，这里再次获取当前系统时间记录更准确
#ifdef ITEST_ENABLED
    current_timestamp = iTest_get_cur_time_stamp();
#else
    current_timestamp = (guint32)time(0);
#endif

    // 集中更新缓存数据，拷贝需要返回的数据
    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    // 从RAID卡实际执行结果更新数据到全局缓存
    if (TRUE == update) {
        memcpy_s(&sml_ctrl->controller.ld[ld_index].pd_in_ld, sizeof(SML_PD_LIST_S), &new_pd_list,
            sizeof(SML_PD_LIST_S));
        sml_ctrl->controller.ld[ld_index].pd_in_ld.last_update_timestamp = current_timestamp;
        sml_ctrl->controller.pd_in_ld_refresh_ctrl[ld_target_id] = update_refresh_policy(refresh_polciy);
    } else {
        // 如果强制从缓存读取数据，则需要刷新最后更新的时间
        if ((RAID_REFRESH_INTERNAL_CACHE == (refresh_polciy & 0x0f)) && (refresh_polciy & 0xf0)) {
            sml_ctrl->controller.ld[ld_index].pd_in_ld.last_update_timestamp = current_timestamp;
            sml_ctrl->controller.pd_in_ld_refresh_ctrl[ld_target_id] =
                update_refresh_policy(refresh_polciy);
        }
    }

    /* END:   Modified for PN:CSEC on 2018/12/7 */
    memcpy_s(ld, sizeof(SML_PD_LIST_S), &sml_ctrl->controller.ld[ld_index].pd_in_ld, sizeof(SML_PD_LIST_S));

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return retval;
}
/*
 * Description: 检查指定的逻辑盘中是否有SSD物理盘存在
 * History: 1.2016年11月14日, ()
 *          新生成函数
 */
gint32 smlib_is_ssd_in_ld(guint8 ctrl_index, guint16 ld_target_id)
{
    gint32 retval = SML_SUCCESS;
    guint8 ld_index = 0;
    guint32 pd_count = 0;
    guint32 idx = 0;
    guint16 pd_id = 0;
    guint16 pd_index = 0;
    gint32 result = FALSE;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, (gpointer)1);
    if (SML_SUCCESS != retval) {
        return FALSE;
    }

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(ld_target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return FALSE;
    }

    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    pd_count = sml_ctrl->controller.ld[ld_index].pd_in_ld.pd_count;

    for (idx = 0; idx < pd_count; idx++) {
        pd_id = sml_ctrl->controller.ld[ld_index].pd_in_ld.device_ids[idx];
        retval = check_pd_device_id(pd_id, &sml_ctrl->controller.pdlist, &pd_index);
        if (RET_OK != retval) {
            continue;
        }

        if (PD_MEDIA_TYPE_SSD == sml_ctrl->controller.pd[pd_index].pdinfo.media_type) {
            result = TRUE;
            break;
        }
    }

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return result;
}

/*
 * Description: 列出指定控制器下的所有CacheCade逻辑盘列表
 * History: 1.2016年11月17日, ()
 *          新生成函数
 */
gint32 smlib_get_sscd_list(guint8 ctrl_index, guint16 *target_ids, guint8 *sscd_count)
{
    gint32 retval = SML_SUCCESS;
    guint16 ld_count = 0;
    guint16 idx = 0;
    guint16 cnt = 0;
    guint16 ld_id = 0;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, (gpointer)target_ids);
    if (SML_SUCCESS != retval) {
        return retval;
    }
    if (NULL == sscd_count) {
        return SML_ERR_NULL_DATA;
    }

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    *sscd_count = 0;
    ld_count = sml_ctrl->controller.ldlist.ld_count;

    // 找出所有cachecade 逻辑盘，记录下id，并统计个数
    for (idx = 0; idx < ld_count; idx++) {
        ld_id = sml_ctrl->controller.ldlist.target_ids[idx];

        if (sml_ctrl->controller.ld[idx].ldinfo.is_sscd == 1) {
            target_ids[cnt] = ld_id;
            cnt++;
        }
    }

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    *sscd_count = cnt;

    return SML_SUCCESS;
}

/*
 * Description: 获取指定的普通ld是否有关联的cachecade ld
 * History: 1.2016年11月18日, ()
 *          新生成函数
 */
gint32 smlib_get_ld_sscd_caching_enable(guint8 ctrl_index, guint16 target_id, guint8 *enable)
{
    gint32 retval = SML_SUCCESS;
    guint16 ld_count = 0;
    guint16 idx = 0;
    guint16 i = 0;
    guint8 ld_index = 0;
    SML_LD_BASIC_INFO_S *pLdInfo = NULL;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, (gpointer)enable);
    if (SML_SUCCESS != retval) {
        return retval;
    }

    *enable = FALSE;

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }
    if (0 != sml_ctrl->controller.ld[ld_index].ldinfo.is_sscd) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }

    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    // 找出所有cachecade 逻辑盘
    ld_count = sml_ctrl->controller.ldlist.ld_count;

    for (idx = 0; idx < ld_count; idx++) {
        if (sml_ctrl->controller.ld[idx].ldinfo.is_sscd == 1) {
            pLdInfo = &sml_ctrl->controller.ld[idx].ldinfo;

            // 判断指定的普通逻辑盘ID是否在CacheCade逻辑盘关联列表中
            for (i = 0; i < pLdInfo->sscd_ld_count; i++) {
                // 如果在关联id中匹配到了指定的逻辑盘id，则认为该逻辑盘的ssd caching功能已经打开
                if (target_id == pLdInfo->sscd_ld_list[i]) {
                    *enable = TRUE;
                    break;
                }
            }
        }

        if (TRUE == *enable) {
            break;
        }
    }

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return SML_SUCCESS;
}

/*
 * Description: 从控制器的pd list中获取pd slot来填充逻辑盘的热备盘槽位号
 * History: 1.2016年11月23日, ()
 *          新生成函数
 */
gint32 smlib_update_ld_spare_pd_slots(guint8 ctrl_index, guint16 target_id)
{
    gint32 retval = SML_SUCCESS;
    guint16 spare_count = 0;
    guint16 idx = 0;
    guint8 ld_index = 0;
    SML_LD_BASIC_INFO_S *pLdInfo = NULL;
    guint16 pd_device_id = 0;
    guint16 pd_index = 0;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, (gpointer)1);
    if (SML_SUCCESS != retval) {
        return retval;
    }
    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }

    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    pLdInfo = &sml_ctrl->controller.ld[ld_index].ldinfo;
    spare_count = pLdInfo->spare_count;

    for (idx = 0; idx < spare_count; idx++) {
        pd_device_id = pLdInfo->spare_pd_ids[idx];

        if (RET_OK != check_pd_device_id(pd_device_id, &sml_ctrl->controller.pdlist, &pd_index)) {
            retval = SML_ERR_PD_INVALID_DEVICE_ID;
            break;
        }

        pLdInfo->spare_pd_slots[idx] = sml_ctrl->controller.pdlist.slot_num[pd_index];
        pLdInfo->spare_pd_enclosure_ids[idx] = sml_ctrl->controller.pdlist.enclosure_ids[pd_index];
    }

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return retval;
}

/*
 * Description: 从控制器的全局缓存数据获取创建逻辑盘需要的物理盘信息
 * History:2016-12-08 杨仕贵  新生成函数
 *         2020-12-22  修改从底层获取最新的硬盘信息作为参数创建
 */
gint32 smlib_get_pds_info_for_ld_creation(guint8 ctrl_index, guint16 *pd_ids, guint8 pd_count,
    SML_CREATE_LD_PD_INFO_S *pd_infos)
{
    gint32 retval = SML_SUCCESS;
    guint16 idx = 0;
    guint16 pd_device_id = 0;
    SML_PD_BASIC_INFO_S pd_info;

    retval = check_input_parameters(ctrl_index, pd_ids);
    if (SML_SUCCESS != retval) {
        return retval;
    }
    if (NULL == pd_infos) {
        return SML_ERR_NULL_DATA;
    }

    for (idx = 0; idx < pd_count; idx++) {
        pd_device_id = pd_ids[idx];

        // 获取最新的硬盘信息作为参数创建
        (void)memset_s(&pd_info, sizeof(pd_info), 0, sizeof(pd_info));
        retval = smlib_get_pd_info(ctrl_index, pd_device_id, &pd_info);
        if (retval != SML_SUCCESS) {
            break;
        }

        // 提取创建需要的那部分物理盘信息数据
        pd_infos[idx].device_id = pd_device_id;
        pd_infos[idx].seq_num = pd_info.sequence_num;
        pd_infos[idx].scsi_dev_type = pd_info.scsi_dev_type;
        pd_infos[idx].media_type = pd_info.media_type;
        pd_infos[idx].interface_type = pd_info.interface_type;
        pd_infos[idx].fw_state = pd_info.fw_state_raw;
        pd_infos[idx].not_supported = pd_info.dev_not_supported;
        pd_infos[idx].is_foreign = pd_info.is_foreign;
        pd_infos[idx].coerced_size_blk = pd_info.coerced_size_blk;
        pd_infos[idx].block_size = pd_info.block_size;
    }

    return retval;
}

/*
 * Description: 从控制器的全局缓存数据获取创建逻辑盘需要的控制器信息
 * History: 1.2016年12月08日, ()
 *          新生成函数
 */
gint32 smlib_get_ctrl_info_for_ld_creation(guint8 ctrl_index, SML_CREATE_LD_CTRL_INFO_S *ctrl_info)
{
    gint32 retval = SML_SUCCESS;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, ctrl_info);
    if (SML_SUCCESS != retval) {
        return retval;
    }

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    ctrl_info->max_lds_per_array = sml_ctrl->controller.ctrl.max_lds_per_array;
    ctrl_info->max_lds = sml_ctrl->controller.ctrl.max_lds;
    ctrl_info->allow_mix_ssd_hdd = sml_ctrl->controller.ctrl.allow_mix_ssd_hdd;
    ctrl_info->allow_ssd_mix = sml_ctrl->controller.ctrl.allow_ssd_mix;

    ctrl_info->raid0_supported = sml_ctrl->controller.ctrl.raid0_supported;
    ctrl_info->raid1_supported = sml_ctrl->controller.ctrl.raid1_supported;
    ctrl_info->raid5_supported = sml_ctrl->controller.ctrl.raid5_supported;
    ctrl_info->raid6_supported = sml_ctrl->controller.ctrl.raid6_supported;
    ctrl_info->raid10_supported = sml_ctrl->controller.ctrl.raid10_supported;
    ctrl_info->raid50_supported = sml_ctrl->controller.ctrl.raid50_supported;
    ctrl_info->raid60_supported = sml_ctrl->controller.ctrl.raid60_supported;

    ctrl_info->ssc_raid0_unsupported = sml_ctrl->controller.ctrl.ssc_raid0_unsupported;
    ctrl_info->ssc_raid1_supported = sml_ctrl->controller.ctrl.ssc_raid1_supported;
    ctrl_info->ssc_raid5_supported = sml_ctrl->controller.ctrl.ssc_raid5_supported;

    ctrl_info->min_pd_raid0 = sml_ctrl->controller.ctrl.min_pd_raid0;
    ctrl_info->min_pd_raid1 = sml_ctrl->controller.ctrl.min_pd_raid1;
    ctrl_info->min_pd_raid5 = sml_ctrl->controller.ctrl.min_pd_raid5;
    ctrl_info->min_pd_raid6 = sml_ctrl->controller.ctrl.min_pd_raid6;
    ctrl_info->min_pd_raid10 = sml_ctrl->controller.ctrl.min_pd_raid10;
    ctrl_info->min_pd_raid50 = sml_ctrl->controller.ctrl.min_pd_raid50;
    ctrl_info->min_pd_raid60 = sml_ctrl->controller.ctrl.min_pd_raid60;

    ctrl_info->max_pd_raid0 = sml_ctrl->controller.ctrl.max_pd_raid0;
    ctrl_info->max_pd_raid1 = sml_ctrl->controller.ctrl.max_pd_raid1;
    ctrl_info->max_pd_raid5 = sml_ctrl->controller.ctrl.max_pd_raid5;
    ctrl_info->max_pd_raid6 = sml_ctrl->controller.ctrl.max_pd_raid6;
    ctrl_info->max_pd_raid10 = sml_ctrl->controller.ctrl.max_pd_raid10;
    ctrl_info->max_pd_raid50 = sml_ctrl->controller.ctrl.max_pd_raid50;
    ctrl_info->max_pd_raid60 = sml_ctrl->controller.ctrl.max_pd_raid60;

    ctrl_info->min_strip = sml_ctrl->controller.ctrl.min_strip;
    ctrl_info->max_strip = sml_ctrl->controller.ctrl.max_strip;

    ctrl_info->support_epd = sml_ctrl->controller.ctrl.operations.ctrl_operations.support_epd;

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return retval;
}

/*
 * Description: 从控制器的全局缓存数据获取指定逻辑盘的array id列表
 * History: 1.2016年12月28日, ()
 *          新生成函数
 */
gint32 smlib_get_ld_ref_array(guint8 ctrl_index, guint16 target_id, guint16 *ref_array, guint8 *array_count)
{
    gint32 retval = SML_SUCCESS;
    guint8 ld_index = 0;
    guint8 idx = 0;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, ref_array);
    if (SML_SUCCESS != retval) {
        return retval;
    }
    if (NULL == array_count) {
        return SML_ERR_NULL_DATA;
    }

    *array_count = 0;

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }

    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    *array_count = MIN(sml_ctrl->controller.ld[ld_index].ldinfo.array_count, SML_MAX_SPAN_DEPTH);
    for (idx = 0; idx < *array_count; idx++) {
        ref_array[idx] = sml_ctrl->controller.ld[ld_index].ldinfo.ref_array[idx];
    }

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return retval;
}

/*
 * Description: 利用控制器的全局缓存数据判断指定的逻辑盘是否是Array上最后一个逻辑盘
 * History: 1.2016年12月28日, ()
 *          新生成函数
 */
gint32 smlib_is_last_ld_on_array(guint8 ctrl_index, guint16 target_id)
{
    gint32 retval = SML_SUCCESS;
    guint8 ld_index = 0;
    guint8 array_count = 0;
    guint16 ref_array = 0;
    gint32 is_last = FALSE;
    guint8 array_index = 0;
    SML_ARRAY_INFO_S *pArray = NULL;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, (gpointer)1);
    if (SML_SUCCESS != retval) {
        return FALSE;
    }

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return FALSE;
    }

    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    array_count = sml_ctrl->controller.ld[ld_index].ldinfo.array_count;
    if ((array_count < 1) || (array_count > SML_MAX_SPAN_DEPTH)) {
        is_last = FALSE;
        debug_log(DLOG_ERROR, "%s: array_count = %d", __FUNCTION__, array_count);
        goto unlock_and_exit;
    }

    // 只需要检查其中一个array的信息，因为相关联的array逻辑盘信息是一致的
    ref_array = sml_ctrl->controller.ld[ld_index].ldinfo.ref_array[0];
    retval = check_array_ref(ref_array, &sml_ctrl->controller.arraylist, &array_index);
    if (RET_OK != retval) {
        is_last = FALSE;
        debug_log(DLOG_ERROR, "%s: check_array_ref failed", __FUNCTION__);
        goto unlock_and_exit;
    }

    // 获取Array信息，判断逻辑盘列表是否只有唯一一个id并且等于指定的id
    pArray = &sml_ctrl->controller.array[array_index];
    if ((1 == pArray->ld_count) && (target_id == pArray->ld_ids[0])) {
        is_last = TRUE;
    }

unlock_and_exit:
    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return is_last;
}

/*
 * Description: 在array info列表中给定的array id的列表项，后面的列表项依次前移
 *              array有删除时，控制器的array id由控制器动态调整，任何时候，array id从0开始，依次顺序加1
 * History: 1.2016年12月29日, ()
 *          新生成函数
 */
static gint32 resort_array_infos(guint16 *array_refs, guint8 array_count, SML_ARRAY_INFO_S *array_info,
    SML_ARRAY_LIST_S *array_lists)
{
    SML_ARRAY_INFO_S *temp_info = NULL;
    guint16 i = 0;
    guint16 j = 0;
    guint8 array_idx = 0;
    guint8 not_found = 1;
    guint8 new_array_count = 0;

    if ((array_refs == NULL) || (array_lists == NULL) || (array_info == NULL)) {
        return SML_ERR_NULL_DATA;
    }

    if (SML_MAX_ARRAY < MAX(array_lists->array_count, array_count)) {
        return SML_ERR_EXCEED_LIMIT;
    }

    temp_info = (SML_ARRAY_INFO_S *)g_malloc(array_lists->array_count * sizeof(SML_ARRAY_INFO_S));
    if (temp_info == NULL) {
        return SML_ERR_CANNOT_ALLOC_MEM;
    }

    // 将原来的Array信息备份
    errno_t securec_rv = memcpy_s(temp_info, array_lists->array_count * sizeof(SML_ARRAY_INFO_S), array_info,
        array_lists->array_count * sizeof(SML_ARRAY_INFO_S));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }

    // 把不在ref_array中的id对应的列表信息复制到array_info中, 在ref_array中id对应的信息丢弃
    new_array_count = 0;
    for (i = 0; i < array_lists->array_count; i++) {
        for (j = 0; j < array_count; j++) {
            not_found = 1;
            if (array_lists->array_refs[i] == array_refs[j]) {
                not_found = 0;
                break;
            }
        }

        if (not_found) {
            if (check_array_ref(array_lists->array_refs[i], array_lists, &array_idx) == RET_OK) {
                memcpy_s(&array_info[new_array_count], sizeof(SML_ARRAY_INFO_S), &temp_info[array_idx],
                    sizeof(SML_ARRAY_INFO_S));
                new_array_count++;
            }
        }
    }

    array_lists->array_count = new_array_count;

    g_free(temp_info);

    return SML_SUCCESS;
}

/*
 * Description: 在array info列表中给定的array id的列表项，后面的列表项依次前移
 *              array有删除时，控制器的array id由控制器动态调整，任何时候，array id从0开始，依次顺序加1
 * History: 1.2016年12月29日, ()
 *          新生成函数
 */
gint32 smlib_resort_array_infos(guint8 ctrl_index, guint16 *array_refs, guint8 array_count)
{
    gint32 retval = SML_SUCCESS;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, array_refs);
    if (SML_SUCCESS != retval) {
        return retval;
    }
    if (array_count > SML_MAX_ARRAY) {
        return SML_ERR_EXCEED_LIMIT;
    }

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    g_mutex_lock(&sml_ctrl->ctrl_mutex);
    retval = resort_array_infos(array_refs, array_count, &sml_ctrl->controller.array[0],
        &sml_ctrl->controller.arraylist);
    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return retval;
}

/*
 * Description: 从控制器的全局缓存数据获取指定逻辑盘的物理成员盘device id列表
 * History: 1.2017年1月3日, ()
 *          新生成函数
 */
gint32 smlib_get_pd_ids_in_ld(guint8 ctrl_index, guint16 target_id, guint16 *pd_ids, guint8 *pd_count)
{
    gint32 retval = SML_SUCCESS;
    guint8 ld_index = 0;
    guint8 idx = 0;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, pd_ids);
    if (SML_SUCCESS != retval) {
        return retval;
    }
    if (NULL == pd_count) {
        return SML_ERR_NULL_DATA;
    }

    *pd_count = 0;

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }

    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    *pd_count = sml_ctrl->controller.ld[ld_index].pd_in_ld.pd_count;
    for (idx = 0; idx < *pd_count; idx++) {
        pd_ids[idx] = sml_ctrl->controller.ld[ld_index].pd_in_ld.device_ids[idx];
    }

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return retval;
}

/*
 * Description: 标记逻辑盘删除后需要刷新的信息
 * History: 1.2017年1月3日, ()
 *          新生成函数
 */
void smlib_refresh_infos_after_ld_delete(guint8 ctrl_index, guint16 ld_target_id)
{
    gint32 retval = SML_SUCCESS;
    guint16 array_refs[SML_MAX_SPAN_DEPTH] = { 0 };
    guint8 array_count = 0;
    gint32 is_last_ld = FALSE;
    guint16 pd_ids[SML_MAX_PHYSICAL_DRIVES] = { 0 };
    guint8 pd_count = 0;

    retval = check_input_parameters(ctrl_index, (gpointer)1);
    if (SML_SUCCESS != retval) {
        return;
    }

    // 刷新逻辑盘列表和array列表显示
    smlib_invalid_ctrl_cached_info(ctrl_index, (CTRL_INFO_TYPE_LDLIST | CTRL_INFO_TYPE_ARRAYLIST));
    // 所有逻辑盘信息从缓存刷新
    smlib_refresh_all_lds_from_cache_next(ctrl_index, 1);

    // 只刷新逻辑盘关联的array的信息
    retval = smlib_get_ld_ref_array(ctrl_index, ld_target_id, array_refs, &array_count);
    if (SML_SUCCESS != retval) {
        return;
    }

    is_last_ld = smlib_is_last_ld_on_array(ctrl_index, ld_target_id);
    // 删除的是array上的最后一个逻辑盘
    if (is_last_ld) {
        // 从缓存丢弃逻辑盘相关的array信息，其余array信息从缓存刷新
        (void)smlib_resort_array_infos(ctrl_index, array_refs, array_count);
        smlib_refresh_all_arrays_from_cache_next(ctrl_index, 1);

        // 从控制器刷新逻辑盘的成员盘信息 - 固件状态
        retval = smlib_get_pd_ids_in_ld(ctrl_index, ld_target_id, pd_ids, &pd_count);
        if (SML_SUCCESS != retval) {
            return;
        }
        smlib_refresh_specfied_pds_from_hw_next(ctrl_index, pd_ids, pd_count, 1);
    } else {
        // 刷新逻辑盘所在的array信息 - array的空间占用状况
        smlib_refresh_specfied_arrays_from_hw_next(ctrl_index, array_refs, array_count, 1);

        // 物理盘信息没有变化，直接从缓存刷新
        smlib_refresh_all_pds_from_cache_next(ctrl_index, 1);
    }

    // 其余控制器的信息强制从缓存刷新
    smlib_refresh_all_other_from_cache_next(ctrl_index, 1);
}

/*
 * Description: 获取array中第一个物理盘的block size
 * History: 1.2017年1月13日, ()
 *          新生成函数
 */
guint16 smlib_get_pd_block_size_in_array(guint8 ctrl_index, guint16 array_ref)
{
    guint8 array_index = 0;
    guint16 pd_id = 0;
    guint16 pd_index = 0;
    guint16 block_size = PD_BLOCK_SIZE_512;
    gint32 ret = RET_OK;
    SML_CTRL_S* sml_ctrl = NULL;

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    g_mutex_lock(&sml_ctrl->ctrl_mutex);
    ret = check_array_ref(array_ref, &sml_ctrl->controller.arraylist, &array_index);
    if (RET_OK != ret) {
        goto unlock_and_return;
    }

    pd_id = sml_ctrl->controller.array[array_index].pd_ids[0];

    ret = check_pd_device_id(pd_id, &sml_ctrl->controller.pdlist, &pd_index);
    if (RET_OK != ret) {
        goto unlock_and_return;
    }

    block_size = sml_ctrl->controller.pd[pd_index].pdinfo.block_size;
    if (0 == block_size) {
        block_size = PD_BLOCK_SIZE_512;
    }

unlock_and_return:
    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    return block_size;
}
/* END:   Added on 2017/1/11 */

/*
 * Description: 执行创建逻辑盘的操作
 * History: 1.2016年11月4日, ()
 *          新生成函数
 */
gint32 smlib_exec_config_operation(guint8 ctrl_index, guint8 operation, gpointer param, guint32 param_length)
{
    gint32 retval = SML_SUCCESS;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, param);
    if (SML_SUCCESS != retval) {
        return retval;
    }

    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    g_mutex_lock(&sml_ctrl->op_mutex);

    if (NULL != sml_ctrl->pfn_config_operation) {
        // 调用适配层接口执行操作
        retval = sml_ctrl->pfn_config_operation(sml_ctrl->controller_id, operation, param,
            param_length);
        if (SML_SUCCESS != retval) {
            debug_log(DLOG_DEBUG,
                "smlib: RAID controller [Ctrl index %d, Ctrl ID %d] exec Config operation %d failed, return 0x%04x\n",
                ctrl_index, SML_CTRL_ID_VALID_BIT(sml_ctrl->controller_id), operation, retval);
        }
    } else {
        retval = SML_ERR_NULL_INFTERFACE;
    }

    g_mutex_unlock(&sml_ctrl->op_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    if (SML_SUCCESS == retval) {
        smlib_invalid_ctrl_cached_info(ctrl_index, CTRL_INFO_TYPE_LDLIST | CTRL_INFO_TYPE_ARRAYLIST);
    }

    return retval;
}

/*
 * Description: 更新LD缓存数据中的启动优先级
 */
static void smlib_refresh_ld_boot_priority(SML_CTRL_S* sml_ctrl, guint16 ld_target_id, gpointer param)
{
    guint8 ld_index = 0;
    if (check_ld_target_id(ld_target_id, &sml_ctrl->controller.ldlist, &ld_index) != RET_OK) {
        return;
    }
    if (param == NULL) {
        return;
    }
    g_mutex_lock(&sml_ctrl->ctrl_mutex);
    guint8 boot_priority = *(guint8 *)param;
    /* 先清除再设置 */
    smlib_clear_boot_priority_from_cache(sml_ctrl, boot_priority);
    sml_ctrl->controller.ld[ld_index].ldinfo.boot_priority = boot_priority;
    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    return;
}

/*
 * Description: 对指定逻辑盘进行操作后刷新缓存区数据
 */
static void smlib_ld_refresh_cache(SML_CTRL_S *sml_ctrl, guint8 ctrl_index, guint8 ld_target_id, guint8 operation,
    gpointer param)
{
    switch (operation) {
        case LD_OPERATION_DELETE:
            smlib_refresh_infos_after_ld_delete(ctrl_index, ld_target_id);
            break;

        case LD_OPERATION_SET_BOOTABLE:
            // bootable是互斥的，更新所有逻辑盘信息
            smlib_invalid_ctrl_cached_info(ctrl_index, CTRL_INFO_TYPE_LD);
            // 其余信息从缓存读取
            smlib_refresh_all_arrays_from_cache_next(ctrl_index, 1);
            smlib_refresh_all_pds_from_cache_next(ctrl_index, 1);
            smlib_refresh_all_other_from_cache_next(ctrl_index, 1);
            smlib_refresh_ld_boot_priority(sml_ctrl, ld_target_id, param);
            break;

        case LD_OPERATION_SET_PROPERTIES:
            // 强制从控制器刷新该逻辑盘的信息
            smlib_refresh_specfied_ld_from_hw_next(ctrl_index, ld_target_id, 1);
            // 其余信息从缓存读取
            smlib_refresh_all_arrays_from_cache_next(ctrl_index, 1);
            smlib_refresh_all_pds_from_cache_next(ctrl_index, 1);
            smlib_refresh_all_other_from_cache_next(ctrl_index, 1);
            break;

        case LD_OPERATION_SET_SSCD_CACHING_ENABLE:
            // cachecade关联涉及到其他的cachcade逻辑盘，更新所有逻辑盘信息
            smlib_invalid_ctrl_cached_info(ctrl_index, CTRL_INFO_TYPE_LD);
            // 其余信息从缓存读取
            smlib_refresh_all_arrays_from_cache_next(ctrl_index, 1);
            smlib_refresh_all_pds_from_cache_next(ctrl_index, 1);
            smlib_refresh_all_other_from_cache_next(ctrl_index, 1);
            break;

        case LD_OPERATION_START_FGI:
            g_mutex_lock(&sml_ctrl->ctrl_mutex);
            sml_ctrl->controller.ld[ld_target_id].ldinfo.progress_info.current_fgi_state = 1;
            g_mutex_unlock(&sml_ctrl->ctrl_mutex);
            break;

        default:
            break;
    }
}
/*
 * Description: 对指定逻辑盘进行操作
 * History: 1.2016年11月4日, ()
 *          新生成函数
 */
gint32 smlib_exec_ld_operation(guint8 ctrl_index, guint16 ld_target_id, guint8 operation, gpointer param,
    guint32 param_length)
{
    gint32 retval = SML_SUCCESS;
    guint8 ld_index = 0;
    SML_CTRL_S* sml_ctrl = NULL;

    retval = check_input_parameters(ctrl_index, param);
    if (SML_SUCCESS != retval && SML_ERR_NULL_DATA != retval) {
        return retval;
    }
    // 有的操作不需要参数，param可能为空
    lock_ctrl_list_mutex(ctrl_index);
    sml_ctrl = get_ctrl_by_index(ctrl_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (RET_OK != check_ld_target_id(ld_target_id, &sml_ctrl->controller.ldlist, &ld_index)) {
        unlock_ctrl_list_mutex(ctrl_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }

    g_mutex_lock(&sml_ctrl->op_mutex);

    if (NULL != sml_ctrl->pfn_ld_operation) {
        // 调用适配层接口执行操作
        retval = sml_ctrl->pfn_ld_operation(sml_ctrl->controller_id, ld_target_id, operation,
            param, param_length);
        if (retval != SML_SUCCESS && retval != SML_ERR_REBOOT_REQUIRED) {
            debug_log(DLOG_DEBUG,
                "smlib: RAID controller [Ctrl index %d, Ctrl ID %d] exec LD[%d] operation %d failed, return 0x%04x\n",
                ctrl_index, SML_CTRL_ID_VALID_BIT(sml_ctrl->controller_id), ld_target_id, operation,
                retval);
        }
    } else {
        retval = SML_ERR_NULL_INFTERFACE;
    }

    g_mutex_unlock(&sml_ctrl->op_mutex);
    unlock_ctrl_list_mutex(ctrl_index);

    if (SML_SUCCESS == retval) {
        smlib_ld_refresh_cache(sml_ctrl, ctrl_index, ld_target_id, operation, param);
    }

    return retval;
}

gint32 smlib_get_ld_associated_sscd_list(SML_LD_ASSOCIATED_SSCD_LIST_S* ld)
{
    guint8 ld_index = 0;

    lock_ctrl_list_mutex(ld->i_controller_index);
    SML_CTRL_S* sml_ctrl = get_ctrl_by_index(ld->i_controller_index);
    if (sml_ctrl == NULL) {
        unlock_ctrl_list_mutex(ld->i_controller_index);
        return SML_ERR_CTRL_NOT_REGISTERED;
    }
    if (check_ld_target_id(ld->i_ld_id, &sml_ctrl->controller.ldlist, &ld_index) != RET_OK) {
        unlock_ctrl_list_mutex(ld->i_controller_index);
        return SML_ERR_LD_INVALID_TARGET_ID;
    }

    g_mutex_lock(&sml_ctrl->ctrl_mutex);

    guint8 count = 0;
    for (guint16 i = 0; i < sml_ctrl->controller.ldlist.ld_count; i++) {
        SML_LD_BASIC_INFO_S *ld_info = &sml_ctrl->controller.ld[i].ldinfo;
        if (ld_info->is_sscd == 0) {
            continue;
        }

        /* 在CacheCade盘关联的普通逻辑盘列表中找目标id */
        gboolean found = FALSE;
        for (guint16 j = 0; j < ld_info->sscd_ld_count; j++) {
            if (ld->i_ld_id == ld_info->sscd_ld_list[j]) {
                found = TRUE;
                break;
            }
        }

        /* 如果在列表里面，把当前遍历到的CacheCade盘id记录下来 */
        if (found == TRUE && count < G_N_ELEMENTS(ld->o_sscd_ids)) {
            ld->o_sscd_ids[count++] = ld_info->target_id;
        }
    }

    ld->o_sscd_count = count;

    g_mutex_unlock(&sml_ctrl->ctrl_mutex);
    unlock_ctrl_list_mutex(ld->i_controller_index);

    return SML_SUCCESS;
}