📄 qla_fo.c
字号:
EXT_CLR_LUN_BIT(&(fcport->lun_mask), lun); } else { EXT_SET_LUN_BIT(&(fcport->lun_mask), lun); } } /* Go to next entry */ continue; } /* * Failover is enabled. Go through the mp_devs list and set lun * data in configured path. */ for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { dp = host->mp_devs[dev_no]; if (dp == NULL) continue; /* Lookup entry name */ if (!qla2x00_is_portname_in_device(dp, entry->PortName)) continue; if ((pathlist = dp->path_list) == NULL) continue; path = pathlist->last; for (path_id = 0; path_id < pathlist->path_cnt; path_id++, path = path->next) { if (path->host != host) continue; if (!qla2x00_is_portname_equal(path->portname, entry->PortName)) continue; for (lun = 0; lun < MAX_LUNS; lun++) { path->lun_data.data[lun] = entry->Data[lun]; DEBUG4(printk("cfg_set_lun_data: lun " "data[%d] = 0x%x \n", lun, path->lun_data.data[lun]);) } break; } break; } } KMEM_FREE(list, FO_LUN_DATA_LIST); return ret;}/* * qla2x00_fo_get_target_data * Get the target control byte for all devices attached to a HBA. * * Input: * bp = pointer to buffer * * Return; * 0 on success or errno. * * Context: * Kernel context. */static intqla2x00_fo_get_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode){ scsi_qla_host_t *ha; fc_port_t *fcport; int ret = 0; mp_host_t *host = NULL; mp_device_t *dp; mp_path_t *path; mp_path_list_t *pathlist; os_tgt_t *ostgt; uint8_t i, cnt; uint8_t path_id; uint16_t dev_no; FO_DEVICE_DATA *entry, *u_entry; ha = qla2x00_get_hba((int)bp->HbaInstance); DEBUG3(printk("qla_fo_get_target_data: hba %p, buff %p.\n", ha, bp);) if (ha->flags.failover_enabled) if ((host = qla2x00_cfg_find_host(ha)) == NULL) { DEBUG2(printk("qla2x00_get_target_data: no HOST for " "ha %p.\n", ha);) return 1; } if ((entry = (FO_DEVICE_DATA *)kmem_zalloc(sizeof(FO_DEVICE_DATA), GFP_ATOMIC,14)) == NULL) { DEBUG2_3(printk("qla_fo_get_target_data: failed to allocate " "memory of size (%d)\n", (int)sizeof(FO_DEVICE_DATA));) return 1; } u_entry = (FO_DEVICE_DATA *) pext->ResponseAdr; /* find the correct fcport list */ if (!ha->flags.failover_enabled) fcport = ha->fcport; else fcport = host->fcport; /* Check thru this adapter's fcport list */ for (i = 0; fcport && i < MAX_TARGETS; i++, fcport = fcport->next) { memcpy(entry->WorldWideName, fcport->node_name, EXT_DEF_WWN_NAME_SIZE); memcpy(entry->PortName, fcport->port_name, EXT_DEF_WWN_NAME_SIZE); if (!ha->flags.failover_enabled) { /* * Failover disabled. Just find the port and return * target info. */ for (cnt = 0; cnt < MAX_FIBRE_DEVICES; cnt++) { if (!(ostgt = ha->otgt[cnt])) { continue; } if (ostgt->vis_port == fcport) { entry->TargetId = cnt; break; } } if (cnt == MAX_FIBRE_DEVICES) { /* Not found? For now just go to next port. */#if defined(QL_DEBUG_LEVEL_2) uint8_t *tmp_name;#if USE_PORTNAME tmp_name = fcport->port_name;#else tmp_name = fcport->node_name;#endif printk("fo_get_target_data(%ld): ERROR " "port %02x%02x%02x%02x%02x%02x%02x%02x " "not configured.\n", ha->host_no, tmp_name[0], tmp_name[1], tmp_name[2], tmp_name[3], tmp_name[4], tmp_name[5], tmp_name[6], tmp_name[7]);#endif /* DEBUG */ continue; } entry->MultipathControl = 0; /* always configured */ copy_to_user(u_entry, entry, sizeof(FO_DEVICE_DATA)); u_entry++; continue; } /* * Failover is enabled. Go through the mp_devs list and * get target data in configured path. */ for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { dp = host->mp_devs[dev_no]; if (dp == NULL) continue; /* Lookup entry name */ if (!qla2x00_is_portname_in_device(dp, entry->PortName)) continue; if ((pathlist = dp->path_list) == NULL) continue; path = pathlist->last; for (path_id = 0; path_id < pathlist->path_cnt; path_id++, path= path->next) { if (path->host != host) continue; if (!qla2x00_is_portname_equal(path->portname, entry->PortName)) continue; entry->TargetId = dp->dev_id; entry->Dev_No = path->id; entry->MultipathControl = path->mp_byte; DEBUG3(printk("cfg_get_target_data: path->id " "= %d, target data = 0x%x \n", path->id, path->mp_byte);) copy_to_user(u_entry, entry, sizeof(FO_DEVICE_DATA)); u_entry++; /* Path found. Continue with next fcport */ break; } break; } } pext->ResponseLen = sizeof(FO_DEVICE_DATABASE); KMEM_FREE(entry, sizeof(FO_DEVICE_DATA)); return ret;}/* * qla2x00_fo_set_target_data * Set multipath control byte for all devices on the attached hba * * Input: * bp = pointer to buffer * * Return; * 0 on success or errno. * * Context: * Kernel context. */static intqla2x00_fo_set_target_data(EXT_IOCTL *pext, FO_TARGET_DATA_INPUT *bp, int mode){ scsi_qla_host_t *ha; int i; int ret = 0; mp_host_t *host; mp_device_t *dp; mp_path_t *path; mp_path_list_t *pathlist; uint16_t dev_no; uint8_t path_id; FO_DEVICE_DATA *entry, *u_entry; ha = qla2x00_get_hba((int)bp->HbaInstance); DEBUG3(printk("qla_fo_set_target_data: hba %p, buff %p.\n", ha, bp);) if (!ha->flags.failover_enabled) /* non-failover mode. nothing to be done. */ return 0; if ((host = qla2x00_cfg_find_host(ha)) == NULL) { DEBUG2(printk("qla2x00_fo_set_target_data: no HOST for " "ha %p.\n", ha);) return 1; } if ((entry = (FO_DEVICE_DATA *)kmem_zalloc(sizeof(FO_DEVICE_DATA), GFP_ATOMIC,15)) == NULL) { DEBUG2_3(printk("qla_fo_set_target_data: failed to allocate " "memory of size (%d)\n", (int)sizeof(FO_LUN_DATA_LIST));) return 1; } u_entry = (FO_DEVICE_DATA *)(pext->RequestAdr + sizeof(FO_TARGET_DATA_INPUT)); for (i = 0; i < MAX_TARGETS; i++, u_entry++) { copy_from_user(entry, u_entry, sizeof(FO_DEVICE_DATA)); for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { dp = host->mp_devs[dev_no]; if (dp == NULL) continue; /* Lookup entry name */ if (!qla2x00_is_portname_in_device(dp, entry->PortName)) continue; if ((pathlist = dp->path_list) == NULL) continue; path = pathlist->last; for (path_id = 0; path_id < pathlist->path_cnt; path_id++, path= path->next) { if (path->host != host) continue; if (!qla2x00_is_portname_equal(path->portname, entry->PortName)) continue; path->mp_byte = entry->MultipathControl; DEBUG3(printk("cfg_set_target_data: %d target " "data = 0x%x \n", path->id,path->mp_byte);) /* * If this is the visible path, then make it * available on next reboot. */ if (!((path->mp_byte & MP_MASK_HIDDEN) || (path->mp_byte & MP_MASK_UNCONFIGURED))) { pathlist->visible = path->id; } /* Found path. Go to next entry. */ break; } break; } } KMEM_FREE(entry, sizeof(FO_DEVICE_DATA)); return ret;}/* * qla2x00_fo_ioctl * Provides functions for failover ioctl() calls. * * Input: * ha = adapter state pointer. * ioctl_code = ioctl function to perform * arg = Address of application EXT_IOCTL cmd data * mode = flags * * Returns: * Return value is the ioctl rval_p return value. * 0 = success * * Context: * Kernel context. *//* ARGSUSED */intqla2x00_fo_ioctl(scsi_qla_host_t *ha, int ioctl_code, void *arg, int mode){ static EXT_IOCTL cmd_struct; int stat, rval = 0; /* EXT_IOCTL status values */ size_t in_size, out_size; static union { FO_PARAMS params; FO_GET_PATHS path; FO_SET_CURRENT_PATH set_path; /* FO_HBA_STAT_INPUT stat; */ FO_HBA_STAT stat; FO_LUN_DATA_INPUT lun_data; FO_TARGET_DATA_INPUT target_data; } buff; ENTER("qla2x00_fo_ioctl"); memcpy(&cmd_struct, arg, sizeof(cmd_struct)); DEBUG3(printk("qla2x00_fo_ioctl: arg (%p):\n", arg);) /* * default case for this switch not needed, * ioctl_code validated by caller. */ in_size = out_size = 0; switch (ioctl_code) { case FO_CC_GET_PARAMS: out_size = sizeof(FO_PARAMS); break; case FO_CC_SET_PARAMS: in_size = sizeof(FO_PARAMS); break; case FO_CC_GET_PATHS: in_size = sizeof(FO_GET_PATHS); break; case FO_CC_SET_CURRENT_PATH: in_size = sizeof(FO_SET_CURRENT_PATH); break; case FO_CC_GET_HBA_STAT: case FO_CC_RESET_HBA_STAT: in_size = sizeof(FO_HBA_STAT_INPUT); break; case FO_CC_GET_LUN_DATA: in_size = sizeof(FO_LUN_DATA_INPUT); break; case FO_CC_SET_LUN_DATA: in_size = sizeof(FO_LUN_DATA_INPUT); break; case FO_CC_GET_TARGET_DATA: in_size = sizeof(FO_TARGET_DATA_INPUT); break; case FO_CC_SET_TARGET_DATA: in_size = sizeof(FO_TARGET_DATA_INPUT); break; } if (in_size != 0) { if ((int)cmd_struct.RequestLen < in_size) { cmd_struct.Status = EXT_STATUS_INVALID_PARAM; cmd_struct.DetailStatus = EXT_DSTATUS_REQUEST_LEN; rval = EINVAL; } else { stat = copy_from_user(&buff, cmd_struct.RequestAdr, in_size); DEBUG4(printk("qla2x00_fo_ioctl: printing " "request buffer:\n")); if (stat) { cmd_struct.Status = EXT_STATUS_COPY_ERR; rval = EFAULT; } } } else if (out_size != 0 && (int)cmd_struct.ResponseLen < out_size) { cmd_struct.Status = EXT_STATUS_BUFFER_TOO_SMALL; cmd_struct.DetailStatus = out_size; rval = EINVAL; } if (rval == 0) cmd_struct.Status = EXT_STATUS_OK; cmd_struct.DetailStatus = EXT_STATUS_OK; switch (ioctl_code) { case FO_CC_GET_PARAMS: rval = qla2x00_fo_get_params(&buff.params); break; case FO_CC_SET_PARAMS: rval = qla2x00_fo_set_params(&buff.params); break; case FO_CC_GET_PATHS: rval = qla2x00_cfg_get_paths(&cmd_struct, &buff.path,mode); if (rval != 0) out_size = 0; break; case FO_CC_SET_CURRENT_PATH: rval = qla2x00_cfg_set_current_path(&cmd_struct, &buff.set_path,mode); break; case FO_CC_RESET_HBA_STAT: rval = qla2x00_fo_stats(&buff.stat, TRUE); break; case FO_CC_GET_HBA_STAT: rval = qla2x00_fo_stats(&buff.stat, FALSE); break; case FO_CC_GET_LUN_DATA: DEBUG4(printk("calling qla2x00_fo_get_lun_data\n");) DEBUG4(printk("((EXT_IOCTL*)arg)->RequestAdr (%p):\n", (((EXT_IOCTL*)arg)->RequestAdr));)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -