📄 qla_cfg.c
字号:
if ((lq = qla2x00_lun_alloc( vis_host->ha, t, lun)) != NULL) { lq->fclun = fclun; } } } } }}/* * qla2x00_is_ww_name_zero * * Input: * ww_name = Pointer to WW name to check * * Returns: * TRUE if name is 0 else FALSE * * Context: * Kernel context. */static BOOLqla2x00_is_ww_name_zero(uint8_t *nn){ int cnt; /* Check for zero node name */ for (cnt = 0; cnt < WWN_SIZE ; cnt++, nn++) { if (*nn != 0) break; } /* if zero return TRUE */ if (cnt == WWN_SIZE) return TRUE; else return FALSE;}/* * qla2x00_add_path * Add a path to the pathlist * * Input: * pathlist -- path list of paths * path -- path to be added to list * * Returns: * None * * Context: * Kernel context. */static voidqla2x00_add_path( mp_path_list_t *pathlist, mp_path_t *path ){ mp_path_t *last = pathlist->last; ENTER("qla2x00_add_path"); DEBUG3(printk("add_path: pathlist =%p, path =%p, cnt = %d\n", pathlist, path, pathlist->path_cnt);) if (last == NULL) { last = path; } else { path->next = last->next; } last->next = path; pathlist->last = path; pathlist->path_cnt++; LEAVE("qla2x00_add_path");}/* * qla2x00_is_portname_in_device * Search for the specified "portname" in the device list. * * Input: * dp = device pointer * portname = portname to searched for in device * * Returns: * qla2x00 local function return status code. * * Context: * Kernel context. */static BOOLqla2x00_is_portname_in_device(mp_device_t *dp, uint8_t *portname){ int idx; for (idx = 0; idx < MAX_PATHS_PER_DEVICE; idx++) { if (memcmp(&dp->portnames[idx][0], portname, WWN_SIZE) == 0) return TRUE; } return FALSE;}/* * qla2x00_set_lun_data_from_bitmask * Set or clear the LUN_DATA_ENABLED bits in the LUN_DATA from * a LUN bitmask provided from the miniport driver. * * Inputs: * lun_data = Extended LUN_DATA buffer to set. * lun_mask = Pointer to lun bit mask union. * * Return Value: none. */voidqla2x00_set_lun_data_from_bitmask(mp_lun_data_t *lun_data, lun_bit_mask_t *lun_mask){ int16_t lun; ENTER("qla2x00_set_lun_data_from_bitmask"); for (lun = 0; lun < MAX_LUNS; lun++) { /* our bit mask is inverted */ if (!(EXT_IS_LUN_BIT_SET(lun_mask,lun))) lun_data->data[lun] |= LUN_DATA_ENABLED; else lun_data->data[lun] &= ~LUN_DATA_ENABLED; DEBUG5(printk("set_lun_data_from_bitmask: " "lun data[%d] = 0x%x\n", lun, lun_data->data[lun]);) } LEAVE("qla2x00_set_lun_data_from_bitmask"); return;}static voidqla2x00_failback_single_lun(mp_device_t *dp, uint8_t lun, uint8_t new){ mp_path_list_t *pathlist; mp_path_t *new_path, *old_path; uint8_t old; mp_host_t *host; os_lun_t *lq; mp_path_t *vis_path; mp_host_t *vis_host; /* Failback and update statistics. */ if ((pathlist = dp->path_list) == NULL) return; old = pathlist->current_path[lun]; pathlist->current_path[lun] = new; if ((new_path = qla2x00_find_path_by_id(dp, new)) == NULL) return; if ((old_path = qla2x00_find_path_by_id(dp, old)) == NULL) return; /* An fclun should exist for the failbacked lun */ if (qla2x00_find_matching_lun(lun, new_path) == NULL) return; if (qla2x00_find_matching_lun(lun, old_path) == NULL) return; /* Log to console and to event log. */ printk(KERN_INFO "qla2x00: FAILBACK device %d -> " "%02x%02x%02x%02x%02x%02x%02x%02x LUN %02x\n", dp->dev_id, dp->nodename[0], dp->nodename[1], dp->nodename[2], dp->nodename[3], dp->nodename[4], dp->nodename[5], dp->nodename[6], dp->nodename[7], lun); printk(KERN_INFO "qla2x00: FROM HBA %d to HBA %d \n", old_path->host->instance, new_path->host->instance); /* Send a failover notification. */#if 0 qla2x00_send_failover_notify(dp, lun, new_path, old_path);#endif host = new_path->host; /* remap the lun */ qla2x00_map_a_oslun(host, dp, dp->dev_id, lun); /* 7/16 * Reset counts on the visible path */ if ((vis_path = qla2x00_get_visible_path(dp)) == NULL) { printk(KERN_INFO "qla2x00(%d): No visible path for " "target %d, dp = %p\n", host->instance, dp->dev_id, dp); return; } vis_host = vis_path->host; if ((lq = qla2x00_lun_alloc(vis_host->ha, dp->dev_id, lun)) != NULL) { qla2x00_suspend_lun(vis_host->ha, lq, recoveryTime, 1); qla2x00_flush_failover_q(vis_host->ha, lq); qla2x00_reset_lun_fo_counts(vis_host->ha, lq); }}/** qla2x00_failback_luns* This routine looks through the devices on an adapter, and* for each device that has this adapter as the visible path,* it forces that path to be the current path. This allows us* to keep some semblance of static load balancing even after* an adapter goes away and comes back.** Arguments:* host Adapter that has just come back online.** Return:* None.*/static voidqla2x00_failback_luns( mp_host_t *host){ uint16_t dev_no; uint8_t l; uint16_t lun; int i; mp_device_t *dp; mp_path_list_t *path_list; mp_path_t *path; ENTER("qla2x00_failback_luns"); for (dev_no = 0; dev_no < MAX_MP_DEVICES; dev_no++) { dp = host->mp_devs[dev_no]; if (dp == NULL) continue; path_list = dp->path_list; for (path = path_list->last, i= 0; i < path_list->path_cnt; i++, path = path->next) { if (path->host != host ) continue; /* * Failback all the paths for this host, * the luns could be preferred across all paths */ DEBUG2(printk("qla2x00_failback_luns(%d): " "Lun Data for device %p, " "id=%d, path id=%d\n", host->instance, dp, dp->dev_id, path->id);) DEBUG4(qla2x00_dump_buffer( (char *)&path->lun_data.data[0], 64);) DEBUG4(printk("qla2x00_failback_luns(%d): " "Perferrred Path data:\n", host->instance);) DEBUG4(qla2x00_dump_buffer( (char *)&path_list->current_path[0], 64);) for (lun = 0; lun < MAX_LUNS_PER_DEVICE; lun++) { l = (uint8_t)(lun & 0xFF); /* * if this is the preferred lun and not * the current path then failback lun. */ DEBUG4(printk("failback_luns: " "target= %d, cur path id =%d, " "lun data[%d] = %d)\n", dp->dev_id, path->id, lun, path->lun_data.data[lun]);) if ((path->lun_data.data[l] & LUN_DATA_PREFERRED_PATH) && /* !path->relogin && */ path_list->current_path[l] != path->id ) { qla2x00_failback_single_lun( dp, l, path->id); } } } } LEAVE("qla2x00_failback_luns"); return;}/* * qla2x00_setup_new_path * Checks the path against the existing paths to see if there * are any incompatibilities. It then checks and sets up the * current path indices. * * Inputs: * dp = pointer to device * path = new path * * Returns: * None */static voidqla2x00_setup_new_path( mp_device_t *dp, mp_path_t *path){ mp_path_list_t *path_list = dp->path_list; mp_path_t *tmp_path, *first_path; mp_host_t *first_host; mp_host_t *tmp_host; uint16_t lun; uint8_t l; int i; ENTER("qla2x00_setup_new_path"); /* If this is a visible path, and there is not already a * visible path, save it as the visible path. If there * is already a visible path, log an error and make this * path invisible. */ if (!(path->mp_byte & (MP_MASK_HIDDEN | MP_MASK_UNCONFIGURED))) { /* No known visible path */ if (path_list->visible == PATH_INDEX_INVALID) { DEBUG3(printk("setup_new_path: No know " "visible path - make this path " "visible\n");) path_list->visible = path->id; path->mp_byte &= ~MP_MASK_HIDDEN; } else { DEBUG3(printk("setup_new_path: Second " "visible path - make this " "one hidden\n");) DEBUG3(printk("qla2x00_setup_new_path: " "Second visible path found.\n");) path->mp_byte |= MP_MASK_HIDDEN; } } /* * If this is not the first path added, and the setting for * MaxLunsPerTarget does not match that of the first path * then disable qla_cfg for all adapters. */ first_path = qla2x00_find_path_by_id(dp, 0); if (first_path != NULL) { first_host = first_path->host; if ((path->id != 0) && (first_host->MaxLunsPerTarget != path->host->MaxLunsPerTarget)) { for (tmp_path = path_list->last, i = 0; (tmp_path) && i <= path->id; i++) { tmp_host = tmp_path->host; if (!(tmp_host->flags & MP_HOST_FLAG_DISABLE)) { DEBUG4(printk( "qla2x00_setup_new_path: " "2nd visible path (%p)\n", tmp_host);) tmp_host->flags |= MP_HOST_FLAG_DISABLE; } } } } /* * For each LUN, evaluate whether the new path that is added * is better than the existing path. If it is, make it the * current path for the LUN. */ for (lun = 0; lun < MAX_LUNS_PER_DEVICE; lun++) { l = (uint8_t)(lun & 0xFF); /* If this is the first path added, it is the only * available path, so make it the current path. */ DEBUG4(printk("qla2x00_setup_new_path: " "lun_data 0x%x, LUN %d\n", path->lun_data.data[l], lun);) if (first_path == path) { path_list->current_path[l] = 0; path->lun_data.data[l] |= LUN_DATA_PREFERRED_PATH; } else if (path->lun_data.data[l] & LUN_DATA_PREFERRED_PATH) { /* * If this is not the first path added, if this is * the preferred path, make it the current path. */ path_list->current_path[l] = path->id; } } LEAVE("qla2x00_setup_new_path"); return;}/* * qla2x00_cfg_mem_free * Free all configuration structures. * * Input: * ha = adapter state pointer. * * Context: * Kernel context. */voidqla2x00_cfg_mem_free(scsi_qla_host_t *ha){ mp_device_t *dp; mp_path_list_t *path_list; mp_path_t *tmp_path, *path; mp_host_t *host, *temp; int id, cnt; if ((host = qla2x00_cfg_find_host(ha)) != NULL) { if( mp_num_hosts == 0 ) return; for (id= 0; id < MAX_MP_DEVICES; id++) { if ((dp = host->mp_devs[id]) == NULL) continue; if ((path_list = dp->path_list) == NULL) continue; if ((tmp_path = path_list->last) == NULL) continue; for (cnt = 0; cnt < path_list->path_cnt; cnt++) { path = tmp_path; tmp_path = tmp_path->next; DEBUG(printk(KERN_INFO "host%d - Removing path[%d] " "= %p\n", host->instance, cnt, path);) KMEM_FREE(path,sizeof(mp_path_t)); } KMEM_FREE(path_list, sizeof(mp_path_list_t)); host->mp_devs[id] = NULL; /* remove dp from other hosts */ for (temp = mp_hosts_base; (temp); temp = temp->next) { if (temp->mp_devs[id] == dp) { DEBUG(printk(KERN_INFO "host%d - Removing host[%d] = " "%p\n", host->instance, temp->instance,temp);) temp->mp_devs[id] = NULL; } } KMEM_FREE(dp, sizeof(mp_device_t)); } /* remove this host from host list */ temp = mp_hosts_base; if (temp != NULL) { /* Remove from top of queue */ if (temp == host) { mp_hosts_base = host->next; } else { /* * Remove from middle of queue * or bottom of queue */ for (temp = mp_hosts_base; temp != NULL; temp = temp->next) { if (temp->next == host) { temp->next = host->next; break; } } } } KMEM_FREE(host, sizeof(mp_host_t)); mp_num_hosts--; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -