Re: [PATCH 1/1] scsi: storvsc: Avoid allocating memory for temp cpumasks
On Thu, 17 May 2018 14:07:40 -0700 Michael Kelleywrote: > Current code allocates 240 Kbytes (in typical configs) for > each synthetic SCSI controller to use as temp cpumask variables. > Recode to avoid needing the temp cpumask variables and remove the > memory allocation. > > Signed-off-by: Michael Kelley Acked-by: Stephen Hemminger
[PATCH 1/1] scsi: storvsc: Avoid allocating memory for temp cpumasks
Current code allocates 240 Kbytes (in typical configs) for each synthetic SCSI controller to use as temp cpumask variables. Recode to avoid needing the temp cpumask variables and remove the memory allocation. Signed-off-by: Michael Kelley--- This patch is for the 4.18/scsi-queue branch and improves on commit 2217a47de42f on April 20, 2018. --- drivers/scsi/storvsc_drv.c | 50 ++ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index d3897c4..a667119 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -474,13 +474,6 @@ struct storvsc_device { * Mask of CPUs bound to subchannels. */ struct cpumask alloced_cpus; - /* -* Pre-allocated struct cpumask for each hardware queue. -* struct cpumask is used by selecting out-going channels. It is a -* big structure, default to 1024k bytes when CONFIG_MAXSMP=y. -* Pre-allocate it to avoid allocation on the kernel stack. -*/ - struct cpumask *cpumask_chns; /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; @@ -885,13 +878,6 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) if (stor_device->stor_chns == NULL) return -ENOMEM; - stor_device->cpumask_chns = kcalloc(num_possible_cpus(), - sizeof(struct cpumask), GFP_KERNEL); - if (stor_device->cpumask_chns == NULL) { - kfree(stor_device->stor_chns); - return -ENOMEM; - } - stor_device->stor_chns[device->channel->target_cpu] = device->channel; cpumask_set_cpu(device->channel->target_cpu, _device->alloced_cpus); @@ -1252,7 +1238,6 @@ static int storvsc_dev_remove(struct hv_device *device) vmbus_close(device->channel); kfree(stor_device->stor_chns); - kfree(stor_device->cpumask_chns); kfree(stor_device); return 0; } @@ -1262,7 +1247,7 @@ static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device, { u16 slot = 0; u16 hash_qnum; - struct cpumask *alloced_mask = _device->cpumask_chns[q_num]; + const struct cpumask *node_mask; int num_channels, tgt_cpu; if (stor_device->num_sc == 0) @@ -1278,10 +1263,13 @@ static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device, * III. Mapping is persistent. */ - cpumask_and(alloced_mask, _device->alloced_cpus, - cpumask_of_node(cpu_to_node(q_num))); + node_mask = cpumask_of_node(cpu_to_node(q_num)); - num_channels = cpumask_weight(alloced_mask); + num_channels = 0; + for_each_cpu(tgt_cpu, _device->alloced_cpus) { + if (cpumask_test_cpu(tgt_cpu, node_mask)) + num_channels++; + } if (num_channels == 0) return stor_device->device->channel; @@ -1289,7 +1277,9 @@ static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device, while (hash_qnum >= num_channels) hash_qnum -= num_channels; - for_each_cpu(tgt_cpu, alloced_mask) { + for_each_cpu(tgt_cpu, _device->alloced_cpus) { + if (!cpumask_test_cpu(tgt_cpu, node_mask)) + continue; if (slot == hash_qnum) break; slot++; @@ -1308,7 +1298,7 @@ static int storvsc_do_io(struct hv_device *device, struct vstor_packet *vstor_packet; struct vmbus_channel *outgoing_channel, *channel; int ret = 0; - struct cpumask *alloced_mask; + const struct cpumask *node_mask; int tgt_cpu; vstor_packet = >vstor_packet; @@ -1329,11 +1319,11 @@ static int storvsc_do_io(struct hv_device *device, * Ideally, we want to pick a different channel if * available on the same NUMA node. */ - alloced_mask = _device->cpumask_chns[q_num]; - cpumask_and(alloced_mask, _device->alloced_cpus, - cpumask_of_node(cpu_to_node(q_num))); - - for_each_cpu_wrap(tgt_cpu, alloced_mask, q_num + 1) { + node_mask = cpumask_of_node(cpu_to_node(q_num)); + for_each_cpu_wrap(tgt_cpu, +_device->alloced_cpus, q_num + 1) { + if (!cpumask_test_cpu(tgt_cpu, node_mask)) + continue; if (tgt_cpu == q_num) continue; channel = stor_device->stor_chns[tgt_cpu]; @@
Re: [PATCH 11/40] ipv6/flowlabel: simplify pid namespace lookup
Christoph Hellwigwrites: > On Thu, May 17, 2018 at 12:28:01AM -0500, Eric W. Biederman wrote: >> > struct pid_namespace *proc_pid_namespace(struct inode *inode) >> > { >> >// maybe warn on for s_magic not on procfs?? >> >return inode->i_sb->s_fs_info; >> > } >> >> That should work. Ideally out of line for the proc_fs.h version. >> Basically it should be a cousin of PDE_DATA. > > The version in Al's tree is inline and without the warning as > I didn't want to drag in the magic.h include. Please look at it for > additional comments, I can send incremental fixups if needed. Sounds good. Eric
[PATCH 08/25] zfcp: decouple SCSI traces for scsi_eh / TMF from scsi_cmnd
The SCSI command pointer passed to scsi_eh callbacks is just one arbitrary command of potentially many that are in the eh queue to be processed. The command is only used to indirectly pass the TMF scope in terms of SCSI ID/target and SCSI LUN for LUN reset. Hence, zfcp had filled in SCSI trace record fields which do not really belong to the TMF. This was confusing. Therefore, refactor the TMF tracing to work without SCSI command. Since the FCP channel always requires a valid LUN handle, we use SCSI device as common context for any TMF (even target reset). To make it even clearer, we set all bits to 1 for the fields, which do not belong to the TMF, to indicate that these fields are invalid. The old zfcp_dbf_scsi() became zfcp_dbf_scsi_common() to now handle both SCSI commands and TMFs. The old argument scsi_cmnd is now optional and can be NULL with TMFs. The new argument scsi_device is mandatory to carry context, as well as SCSI ID/target and SCSI LUN in case of TMFs. New example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : SCSI Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag: [lt]r_ Request ID : 0x ID of FSF FCP request with TM flag For cases without FSF request: 0x0 for none (invalid) SCSI ID: 0xSCSI ID/target denoting scope SCSI LUN : 0x SCSI LUN denoting scope SCSI LUN high : 0x SCSI LUN denoting scope SCSI result: 0x none (invalid) SCSI retries : 0xff none (invalid) SCSI allowed : 0xff none (invalid) SCSI scribble : 0x none (invalid) SCSI opcode: none (invalid) FCP rsp inf cod: 0x00 FCP_RSP info code of TMF FCP rsp IU : 0100 ext FCP_RSP IU 0008 ext FCP_RSP IU FCP rsp IU len : 32 FCP_RSP IU length Payload time : ... FCP rsp IU all : 0100 full FCP_RSP IU 0008 full FCP_RSP IU Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- Notes: Changes since RFC: For consistency, renamed from "zfcp: drop unsuitable scsi_cmnd usage from SCSI traces for scsi_eh / TMF". Since the FCP channel always requires a valid LUN handle, we use SCSI device as common context for any TMF (even target reset) instead of explicit SCSI ID and SCSI LUN values. Added example trace record to commit description. drivers/s390/scsi/zfcp_dbf.c | 48 --- drivers/s390/scsi/zfcp_dbf.h | 21 --- drivers/s390/scsi/zfcp_ext.h | 5 +++-- drivers/s390/scsi/zfcp_scsi.c | 15 +++--- 4 files changed, 56 insertions(+), 33 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 1e5ea5e4992b..bb3373260169 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -578,16 +578,18 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) } /** - * zfcp_dbf_scsi - trace event for scsi commands - * @tag: identifier for event - * @sc: pointer to struct scsi_cmnd - * @fsf: pointer to struct zfcp_fsf_req + * zfcp_dbf_scsi_common() - Common trace event helper for scsi. + * @tag: Identifier for event. + * @level: trace level of event. + * @sdev: Pointer to SCSI device as context for this event. + * @sc: Pointer to SCSI command, or NULL with task management function (TMF). + * @fsf: Pointer to FSF request, or NULL. */ -void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, - struct zfcp_fsf_req *fsf) +void zfcp_dbf_scsi_common(char *tag, int level, struct scsi_device *sdev, + struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) { struct zfcp_adapter *adapter = - (struct zfcp_adapter *) sc->device->host->hostdata[0]; + (struct zfcp_adapter *) sdev->host->hostdata[0]; struct zfcp_dbf *dbf = adapter->dbf; struct zfcp_dbf_scsi *rec = >scsi_buf; struct fcp_resp_with_ext *fcp_rsp; @@ -599,16 +601,28 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); rec->id = ZFCP_DBF_SCSI_CMND; - rec->scsi_result = sc->result; - rec->scsi_retries = sc->retries; - rec->scsi_allowed = sc->allowed; - rec->scsi_id = sc->device->id; - rec->scsi_lun = (u32)sc->device->lun; - rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32); - rec->host_scribble = (unsigned long)sc->host_scribble; - - memcpy(rec->scsi_opcode, sc->cmnd, -
[PATCH 25/25] zfcp: enhance comments on fc_link_speed and supported_speed
From: Jens RemusThe comment on fsf_qtcb_bottom_port.supported_speed did read as if the field can only assume one of two possible values (i.e. 0x1 for 1 GBit/s or 0x2 for 2 GBit/s). This is not true for two reasons: first it is a flag field and can thus assume any combination and second there are meanwhile more speeds. Clarify comment on fsf_qtcb_bottom_port.supported_speed and add a comment to fsf_qtcb_bottom_config.fc_link_speed. Signed-off-by: Jens Remus Reviewed-by: Steffen Maier Reviewed-by: Fedor Loshakov Acked-by: Benjamin Block Acked-by: Hendrik Brueckner Signed-off-by: Steffen Maier --- drivers/s390/scsi/zfcp_fsf.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 4baca67aba6d..535628b92f0a 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -4,7 +4,7 @@ * * Interface to the FSF support functions. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #ifndef FSF_H @@ -356,7 +356,7 @@ struct fsf_qtcb_bottom_config { u32 adapter_features; u32 connection_features; u32 fc_topology; - u32 fc_link_speed; + u32 fc_link_speed; /* one of ZFCP_FSF_PORTSPEED_* */ u32 adapter_type; u8 res0; u8 peer_d_id[3]; @@ -382,7 +382,7 @@ struct fsf_qtcb_bottom_port { u32 class_of_service; /* should be 0x0006 for class 2 and 3 */ u8 supported_fc4_types[32]; /* should be 0x0100 for scsi fcp */ u8 active_fc4_types[32]; - u32 supported_speed;/* 0x0001 for 1 GBit/s or 0x0002 for 2 GBit/s */ + u32 supported_speed;/* any combination of ZFCP_FSF_PORTSPEED_* */ u32 maximum_frame_size; /* fixed value of 2112 */ u64 seconds_since_last_reset; u64 tx_frames; -- 2.16.3
[PATCH 23/25] zfcp: assert that the ERP lock is held when tracing a recovery trigger
From: Jens RemusOtherwise iterating with list_for_each() over the adapter->erp_ready_head and adapter->erp_running_head lists can lead to an infinite loop. See commit "zfcp: fix infinite iteration on erp_ready_head list". The run-time check is only performed for debug kernels which have the kernel lock validator enabled. Following is an example of the warning that is reported, if the ERP lock is not held when calling zfcp_dbf_rec_trig(): WARNING: CPU: 0 PID: 604 at drivers/s390/scsi/zfcp_dbf.c:288 zfcp_dbf_rec_trig+0x172/0x188 Modules linked in: ... CPU: 0 PID: 604 Comm: kworker/u128:3 Not tainted 4.16.0-... #1 Hardware name: IBM 2964 N96 702 (z/VM 6.4.0) Workqueue: zfcp_q_0.0.1906 zfcp_scsi_rport_work Krnl PSW : 330fdbf9 367e9728 (zfcp_dbf_rec_trig+0x172/0x188) R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:3 PM:0 RI:0 EA:3 Krnl GPRS: c57a5d99 32882000 6cc82740 009d09d6 00ff 00e1b5fe 6de01d38 76130958 6cc82548 6de01a98 009d09d6 6a6d3c80 Krnl Code: 009d0ad2: eb7ff0b80004lmg%r7,%r15,184(%r15) 009d0ad8: c0f4000d7dd0brcl 15,b80678 #009d0ade: a7f40001brc15,9d0ae0 >009d0ae2: a7f4ff7dbrc15,9d09dc 009d0ae6: e340f0f4lg %r4,240(%r15) 009d0aec: eb7ff0b80004lmg%r7,%r15,184(%r15) 009d0af2: 07f4bcr15,%r4 009d0af4: 0707bcr0,%r7 Call Trace: ([<009d09d6>] zfcp_dbf_rec_trig+0x66/0x188) [<009dd740>] zfcp_scsi_rport_work+0x98/0x190 [<00169b34>] process_one_work+0x3d4/0x6f8 [<0016a08a>] worker_thread+0x232/0x418 [<0017219e>] kthread+0x166/0x178 [<00b815ea>] kernel_thread_starter+0x6/0xc [<00b815e4>] kernel_thread_starter+0x0/0xc 2 locks held by kworker/u128:3/604: #0: ((wq_completion)name){+.+.}, at: [<82af1024>] process_one_work+0x1dc/0x6f8 #1: ((work_completion)(>rport_work)){+.+.}, at: [<82af1024>] process_one_work+0x1dc/0x6f8 Last Breaking-Event-Address: [<009d0ade>] zfcp_dbf_rec_trig+0x16e/0x188 ---[ end trace b2f4020572e2c124 ]--- Suggested-by: Steffen Maier Signed-off-by: Jens Remus Reviewed-by: Benjamin Block Reviewed-by: Steffen Maier Signed-off-by: Steffen Maier --- drivers/s390/scsi/zfcp_dbf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index bb3373260169..781141bf2c28 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -285,6 +285,8 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, struct list_head *entry; unsigned long flags; + lockdep_assert_held(>erp_lock); + if (unlikely(!debug_level_enabled(dbf->rec, level))) return; -- 2.16.3
[PATCH 22/25] zfcp: cleanup indentation for posting FC events
I just happened to see the function header indentation of zfcp_fc_enqueue_event() and I picked some more from checkpatch: $ checkpatch.pl --strict -f drivers/s390/scsi/zfcp_fc.c ... CHECK: Alignment should match open parenthesis #113: FILE: drivers/s390/scsi/zfcp_fc.c:113: + fc_host_post_event(adapter->scsi_host, fc_get_event_number(), + event->code, event->data); CHECK: Blank lines aren't necessary before a close brace '}' #118: FILE: drivers/s390/scsi/zfcp_fc.c:118: + +} ... The change complements v2.6.36 commit 2d1e547f7523 ("[SCSI] zfcp: Post events through FC transport class"). Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_fc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 54186943896b..f6c415d6ef48 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -111,11 +111,10 @@ void zfcp_fc_post_event(struct work_struct *work) list_for_each_entry_safe(event, tmp, _lh, list) { fc_host_post_event(adapter->scsi_host, fc_get_event_number(), - event->code, event->data); + event->code, event->data); list_del(>list); kfree(event); } - } /** @@ -126,7 +125,7 @@ void zfcp_fc_post_event(struct work_struct *work) * @event_data: The event data (e.g. n_port page in case of els) */ void zfcp_fc_enqueue_event(struct zfcp_adapter *adapter, - enum fc_host_event_code event_code, u32 event_data) + enum fc_host_event_code event_code, u32 event_data) { struct zfcp_fc_event *event; -- 2.16.3
[PATCH 21/25] zfcp: support SCSI_ADAPTER_RESET via scsi_host sysfs attribute host_reset
Make use of feature introduced with v3.2 commit 294436914454 ("[SCSI] scsi: Added support for adapter and firmware reset"). The common code interface was introduced for commit 95d31262b3c1 ("[SCSI] qla4xxx: Added support for adapter and firmware reset"). $ echo adapter > /sys/class/scsi_host/host/host_reset Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 ZFCP_DBF_REC_TRIG Tag: scshr_ySCSI sysfs host_reset yes LUN: 0x none (invalid) WWPN : 0x none (invalid) D_ID : 0x none (invalid) Adapter status : 0x4500050b Port status: 0x none (invalid) LUN status : 0x none (invalid) Ready count: 0x0001 Running count : 0x ERP want : 0x04 ZFCP_ERP_ACTION_REOPEN_ADAPTER ERP need : 0x04 ZFCP_ERP_ACTION_REOPEN_ADAPTER This is the common code equivalent to the zfcp-specific _attr_adapter_failed.attr in zfcp_sysfs_adapter_attrs.attrs[]: $ echo 0 > /sys/bus/ccw/drivers/zfcp//failed The unsupported case returns EOPNOTSUPP: $ echo firmware > /sys/class/scsi_host/host/host_reset -bash: echo: write error: Operation not supported Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : SCSI Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag: scshr_nSCSI sysfs host_reset no Request ID : 0x none (invalid) SCSI ID: 0x none (invalid) SCSI LUN : 0x none (invalid) SCSI LUN high : 0x none (invalid) SCSI result: 0xffa1 -EOPNOTSUPP==-95 SCSI retries : 0xff none (invalid) SCSI allowed : 0xff none (invalid) SCSI scribble : 0x none (invalid) SCSI opcode: none (invalid) FCP rsp inf cod: 0xff none (invalid) FCP rsp IU : none (invalid) For any other invalid value, common code returns EINVAL without invoking our callback: $ echo foo > /sys/class/scsi_host/host/host_reset -bash: echo: write error: Invalid argument Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 11 +++ drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_scsi.c | 26 ++ drivers/s390/scsi/zfcp_sysfs.c | 5 + 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 2968d2f57788..e7e6b63905e2 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -1691,3 +1691,14 @@ void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask) atomic_set(_sdev->erp_counter, 0); } +/** + * zfcp_erp_adapter_reset_sync() - Really reopen adapter and wait. + * @adapter: Pointer to zfcp_adapter to reopen. + * @id: Trace tag string of length %ZFCP_DBF_TAG_LEN. + */ +void zfcp_erp_adapter_reset_sync(struct zfcp_adapter *adapter, char *id) +{ + zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); + zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, id); + zfcp_erp_wait(adapter); +} diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index ad7c28ffd49f..f3b55cce748a 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -76,6 +76,7 @@ extern void zfcp_erp_thread_kill(struct zfcp_adapter *); extern void zfcp_erp_wait(struct zfcp_adapter *); extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long); extern void zfcp_erp_timeout_handler(struct timer_list *t); +extern void zfcp_erp_adapter_reset_sync(struct zfcp_adapter *adapter, char *id); /* zfcp_fc.c */ extern struct kmem_cache *zfcp_fc_req_cache; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index f69ef78ea930..9a01f583e562 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -372,6 +372,31 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) return ret; } +/** + * zfcp_scsi_sysfs_host_reset() - Support scsi_host sysfs attribute host_reset. + * @shost: Pointer to Scsi_Host to perform action on. + *
[PATCH 24/25] zfcp: add port speed capabilities
From: Jens RemusAdd port speed capabilities as defined in FC-LS RPSC ELS that have a counterpart FC_PORTSPEED_* defined in scsi/scsi_transport_fc.h. Suggested-by: Steffen Maier Signed-off-by: Jens Remus Reviewed-by: Steffen Maier Reviewed-by: Fedor Loshakov Acked-by: Hendrik Brueckner Acked-by: Benjamin Block Signed-off-by: Steffen Maier --- drivers/s390/scsi/zfcp_fsf.c | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 049fdd968130..3c86e27f094d 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4,7 +4,7 @@ * * Implementation of FSF commands. * - * Copyright IBM Corp. 2002, 2017 + * Copyright IBM Corp. 2002, 2018 */ #define KMSG_COMPONENT "zfcp" @@ -437,6 +437,9 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) #define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3) #define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4) #define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5) +#define ZFCP_FSF_PORTSPEED_32GBIT (1 << 6) +#define ZFCP_FSF_PORTSPEED_64GBIT (1 << 7) +#define ZFCP_FSF_PORTSPEED_128GBIT (1 << 8) #define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15) static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) @@ -454,6 +457,12 @@ static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) fdmi_speed |= FC_PORTSPEED_8GBIT; if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT) fdmi_speed |= FC_PORTSPEED_16GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_32GBIT) + fdmi_speed |= FC_PORTSPEED_32GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_64GBIT) + fdmi_speed |= FC_PORTSPEED_64GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_128GBIT) + fdmi_speed |= FC_PORTSPEED_128GBIT; if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED) fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED; return fdmi_speed; -- 2.16.3
[PATCH 18/25] zfcp: zfcp_erp_action_exists() does only check for running
Simplify its signature to return boolean and rename it to zfcp_erp_action_is_running() to indicate its actual unmodified semantics. It has always been used like this since v2.6.0 history commit ea127f975424 ("[PATCH] s390 (7/7): zfcp host adapter."). Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 14 +- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index b5ca484d5d5f..245621769c26 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -57,10 +57,6 @@ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_FAILED = 0xe0, }; -enum zfcp_erp_act_state { - ZFCP_ERP_ACTION_RUNNING = 1, -}; - enum zfcp_erp_act_result { ZFCP_ERP_SUCCEEDED = 0, ZFCP_ERP_FAILED= 1, @@ -76,14 +72,14 @@ static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask) ZFCP_STATUS_COMMON_UNBLOCKED | mask); } -static int zfcp_erp_action_exists(struct zfcp_erp_action *act) +static bool zfcp_erp_action_is_running(struct zfcp_erp_action *act) { struct zfcp_erp_action *curr_act; list_for_each_entry(curr_act, >adapter->erp_running_head, list) if (act == curr_act) - return ZFCP_ERP_ACTION_RUNNING; - return 0; + return true; + return false; } static void zfcp_erp_action_ready(struct zfcp_erp_action *act) @@ -99,7 +95,7 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act) static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) { act->status |= ZFCP_STATUS_ERP_DISMISSED; - if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING) + if (zfcp_erp_action_is_running(act)) zfcp_erp_action_ready(act); } @@ -622,7 +618,7 @@ void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask) unsigned long flags; write_lock_irqsave(>erp_lock, flags); - if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { + if (zfcp_erp_action_is_running(erp_action)) { erp_action->status |= set_mask; zfcp_erp_action_ready(erp_action); } -- 2.16.3
[PATCH 09/25] zfcp: decouple TMF response handler from scsi_cmnd
Originally, I planned for TMF handling to have different context data in fsf_req->data depending on the TMF scope in fcp_cmnd->fc_tm_flags: * scsi_device if FCP_TMF_LUN_RESET, * zfcp_port if FCP_TMF_TGT_RESET. However, the FCP channel requires a valid LUN handle so we now use scsi_device as context data with any TMF for the time being. Regular SCSI I/O FCP requests continue using scsi_cmnd as req->data. Hence, the callers of zfcp_fsf_fcp_handler_common() must resolve req->data and pass scsi_device as common context. While at it, remove the detour zfcp_sdev->port->adapter and use the more direct req->adapter as elsewhere in this function already. Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- Notes: Changes since RFC: Since the FCP channel always requires a valid LUN handle, we now use scsi_device as context data with any TMF instead of either scsi_device for FCP_TMF_LUN_RESET or zfcp_port for FCP_TMF_TGT_RESET. This also fixes a kernel panic due to a wrongly assigned req->data in the previous patch version. Added missing description on replacing zfcp_sdev->port->adapter with req->adapter which was already in the previous patch content. This is now the only change left in zfcp_fsf_fcp_handler_common(). drivers/s390/scsi/zfcp_fsf.c | 25 ++--- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b12cb81ad8a2..a95070c7cad8 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2036,10 +2036,14 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) sizeof(blktrc)); } -static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) +/** + * zfcp_fsf_fcp_handler_common() - FCP response handler common to I/O and TMF. + * @req: Pointer to FSF request. + * @sdev: Pointer to SCSI device as request context. + */ +static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req, + struct scsi_device *sdev) { - struct scsi_cmnd *scmnd = req->data; - struct scsi_device *sdev = scmnd->device; struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header = >qtcb->header; @@ -2051,7 +2055,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_HANDLE_MISMATCH: case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1"); + zfcp_erp_adapter_reopen(req->adapter, 0, "fssfch1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_FCPLUN_NOT_VALID: @@ -2069,8 +2073,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) req->qtcb->bottom.io.data_direction, (unsigned long long)zfcp_scsi_dev_lun(sdev), (unsigned long long)zfcp_sdev->port->wwpn); - zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, - "fssfch3"); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fssfch3"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_CMND_LENGTH_NOT_VALID: @@ -2080,8 +2083,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) req->qtcb->bottom.io.fcp_cmnd_length, (unsigned long long)zfcp_scsi_dev_lun(sdev), (unsigned long long)zfcp_sdev->port->wwpn); - zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, - "fssfch4"); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fssfch4"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PORT_BOXED: @@ -2120,7 +2122,7 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req) return; } - zfcp_fsf_fcp_handler_common(req); + zfcp_fsf_fcp_handler_common(req, scpnt->device); if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED); @@ -2297,10 +2299,11 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req) { + struct scsi_device *sdev = req->data; struct fcp_resp_with_ext *fcp_rsp; struct fcp_resp_rsp_info *rsp_info; - zfcp_fsf_fcp_handler_common(req); + zfcp_fsf_fcp_handler_common(req, sdev); fcp_rsp = >qtcb->bottom.io.fcp_rsp.iu; rsp_info = (struct fcp_resp_rsp_info *) _rsp[1]; @@ -2341,7 +2344,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, goto out; } -
[PATCH 16/25] zfcp: consistently use function name space prefix
I've been mixing up zfcp_task_mgmt_function() [SCSI] and zfcp_fsf_fcp_task_mgmt() [FSF] so often lately that I wanted to fix this. SCSI changes complement v2.6.27 commit f76af7d7e363 ("[SCSI] zfcp: Cleanup of code in zfcp_scsi.c"). While at it, also fixup the other inconsistencies elsewhere. ERP changes complement v2.6.27 commit 287ac01acf22 ("[SCSI] zfcp: Cleanup code in zfcp_erp.c") which introduced status_change_set(). FC changes complement v2.6.32 commit 6f53a2d2ecae ("[SCSI] zfcp: Apply common naming conventions to zfcp_fc"). by renaming a leftover introduced with v2.6.27 commit cc8c282963bd ("[SCSI] zfcp: Automatically attach remote ports"). FSF changes fixup v2.6.32 commit a4623c467ff7 ("[SCSI] zfcp: Improve request allocation through mempools"). which replaced zfcp_fsf_alloc_qtcb() introduced with v2.6.27 commit c41f8cbddd4e ("[SCSI] zfcp: zfcp_fsf cleanup."). SCSI fc_host statistics were introduced with v2.6.16 commit f6cd94b126aa ("[SCSI] zfcp: transport class adaptations"). SCSI fc_host port_state was introduced with v2.6.27 commit 85a82392fe6f ("[SCSI] zfcp: Add port_state attribute to sysfs"). SCSI rport setter for dev_loss_tmo was introduced with v2.6.18 commit 338151e06608 ("[SCSI] zfcp: make use of fc_remote_port_delete when target port is unavailable"). Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 11 +++ drivers/s390/scsi/zfcp_fc.c | 4 ++-- drivers/s390/scsi/zfcp_fsf.c | 7 --- drivers/s390/scsi/zfcp_scsi.c | 46 ++- 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 69dfb328dba4..9be629607dc0 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -551,21 +551,23 @@ void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id) zfcp_erp_wait(adapter); } -static int status_change_set(unsigned long mask, atomic_t *status) +static int zfcp_erp_status_change_set(unsigned long mask, atomic_t *status) { return (atomic_read(status) ^ mask) & mask; } static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) { - if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, >status)) + if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, + >status)) zfcp_dbf_rec_run("eraubl1", >erp_action); atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, >status); } static void zfcp_erp_port_unblock(struct zfcp_port *port) { - if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, >status)) + if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, + >status)) zfcp_dbf_rec_run("erpubl1", >erp_action); atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, >status); } @@ -574,7 +576,8 @@ static void zfcp_erp_lun_unblock(struct scsi_device *sdev) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); - if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, _sdev->status)) + if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, + _sdev->status)) zfcp_dbf_rec_run("erlubl1", _to_zfcp(sdev)->erp_action); atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, _sdev->status); } diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 2ad80c43f674..54186943896b 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -598,7 +598,7 @@ void zfcp_fc_test_link(struct zfcp_port *port) put_device(>dev); } -static struct zfcp_fc_req *zfcp_alloc_sg_env(int buf_num) +static struct zfcp_fc_req *zfcp_fc_alloc_sg_env(int buf_num) { struct zfcp_fc_req *fc_req; @@ -750,7 +750,7 @@ void zfcp_fc_scan_ports(struct work_struct *work) if (zfcp_fc_wka_port_get(>gs->ds)) return; - fc_req = zfcp_alloc_sg_env(buf_num); + fc_req = zfcp_fc_alloc_sg_env(buf_num); if (!fc_req) goto out; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index d86c3bf71664..049fdd968130 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -662,7 +662,7 @@ static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool) return req; } -static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool) +static struct fsf_qtcb *zfcp_fsf_qtcb_alloc(mempool_t *pool) { struct fsf_qtcb *qtcb; @@ -701,9 +701,10 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) { if (likely(pool)) - req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool); + req->qtcb = zfcp_fsf_qtcb_alloc( + adapter->pool.qtcb_pool);
[PATCH 05/25] zfcp: fix missing REC trigger trace on terminate_rport_io for ERP_FAILED
For problem determination we always want to see when we were invoked on the terminate_rport_io callback whether we perform something or not. Temporal event sequence of interest with a long fast_io_fail_tmo of 27 sec: loose remote port t workqueue [s] zfcp_q_ IRQ zfcperp === == === 0recv RSCN q p.test_link_work block rport start fast_io_fail_tmo send ADISC ELS 4recv ADISC fail block zfcp_port port forced reopen send open port 12recv open port fail q p.gid_pn_work zfcp_erp_wakeup (zfcp_erp_wait would return) GID_PN fail Before this point, we got a SCSI trace with tag "sctrpi1" on fast_io_fail, e.g. with the typical 5 sec setting. port.status |= ERP_FAILED If fast_io_fail_tmo triggers after this point, we missed a SCSI trace. workqueue fc_dl_ == 27 fc_timeout_fail_rport_io fc_terminate_rport_io zfcp_scsi_terminate_rport_io zfcp_erp_port_forced_reopen _zfcp_erp_port_forced_reopen if (port.status & ERP_FAILED) return; Therefore, write a trace before above early return. Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 ZFCP_DBF_REC_TRIG Tag: sctrpi1SCSI terminate rport I/O LUN: 0x none (invalid) WWPN : 0x D_ID : 0x Adapter status : 0x... Port status: 0x... LUN status : 0x none (invalid) Ready count: 0x... Running count : 0x... ERP want : 0x03 ZFCP_ERP_ACTION_REOPEN_PORT_FORCED ERP need : 0xe0 ZFCP_ERP_ACTION_FAILED Signed-off-by: Steffen MaierCc: #2.6.38+ Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 3489b1bc9121..5c368cdfc455 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -42,9 +42,13 @@ enum zfcp_erp_steps { * @ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: Forced port recovery. * @ZFCP_ERP_ACTION_REOPEN_ADAPTER: Adapter recovery. * @ZFCP_ERP_ACTION_NONE: Eyecatcher pseudo flag to bitwise or-combine with - * either of the other enum values. + * either of the first four enum values. * Used to indicate that an ERP action could not be * set up despite a detected need for some recovery. + * @ZFCP_ERP_ACTION_FAILED: Eyecatcher pseudo flag to bitwise or-combine with + * either of the first four enum values. + * Used to indicate that ERP not needed because + * the object has ZFCP_STATUS_COMMON_ERP_FAILED. */ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_REOPEN_LUN = 1, @@ -52,6 +56,7 @@ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, ZFCP_ERP_ACTION_NONE = 0xc0, + ZFCP_ERP_ACTION_FAILED = 0xe0, }; enum zfcp_erp_act_state { @@ -379,8 +384,12 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); - if (atomic_read(>status) & ZFCP_STATUS_COMMON_ERP_FAILED) + if (atomic_read(>status) & ZFCP_STATUS_COMMON_ERP_FAILED) { + zfcp_dbf_rec_trig(id, port->adapter, port, NULL, + ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, + ZFCP_ERP_ACTION_FAILED); return; + } zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, port->adapter, port, NULL, id, 0); -- 2.16.3
[PATCH 14/25] zfcp: decouple our scsi_eh callbacks from scsi_cmnd
Note: zfcp_scsi_eh_host_reset_handler() will be converted in a later patch. zfcp_scsi_eh_device_reset_handler() now only depends on scsi_device. zfcp_scsi_eh_target_reset_handler() now only depends on scsi_target. All derive other objects from these intended callback arguments. zfcp_scsi_eh_target_reset_handler() is special: The FCP channel requires a valid LUN handle so we try to find ourselves a stand-in scsi_device as suggested by Hannes Reinecke. If it cannot find a stand-in scsi device, trace a record like the following (formatted with zfcpdbf from s390-tools): Timestamp : ... Area : SCSI Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag: tr_nosdtarget reset, no SCSI device Request ID : 0x none (invalid) SCSI ID: 0x SCSI ID/target denoting scope SCSI LUN : 0x none (invalid) SCSI LUN high : 0x none (invalid) SCSI result: 0x2003 field re-used for midlayer value: FAILED SCSI retries : 0xff none (invalid) SCSI allowed : 0xff none (invalid) SCSI scribble : 0x none (invalid) SCSI opcode: none (invalid) FCP rsp inf cod: 0xff none (invalid) FCP rsp IU : none (invalid) Actually change the signature of zfcp_task_mgmt_function() used by zfcp_scsi_eh_device_reset_handler() & zfcp_scsi_eh_target_reset_handler(). Since it was prepared in a previous patch, we only need to delete a local auto variable which is now the intended argument. Suggested-by: Hannes ReineckeSigned-off-by: Steffen Maier Reviewed-by: Benjamin Block --- Notes: Changes since RFC: Since the FCP channel always requires a valid LUN handle, we now use scsi_device as context data with any TMF instead of zfcp_port for FCP_TMF_TGT_RESET and an optional scsi_device for FCP_TMF_LUN_RESET. zfcp_scsi_eh_target_reset_handler() became more involved as it needs to find a stand-in scsi_device within the target scope as suggested by Hannes. Trace if we could not find a stand-in scsi_device along with an example trace in the commit description. Put the refcount from shost_for_each_device for the stand-in scsi_device. NB: zfcp_scsi_eh_host_reset_handler() will be converted in a later patch. I need more time to resolve the proper sync with all fc_rports states with support for FAST_IO_FAIL. drivers/s390/scsi/zfcp_scsi.c | 41 + 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e0c5735cf3db..fcc832b73960 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -265,9 +265,14 @@ static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags) write_unlock_irqrestore(>abort_lock, flags); } -static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) +/** + * zfcp_task_mgmt_function() - Synchronously send a task management function. + * @sdev: Pointer to SCSI device to send the task management command to. + * @tm_flags: Task management flags, + * here we only handle %FCP_TMF_TGT_RESET or %FCP_TMF_LUN_RESET. + */ +static int zfcp_task_mgmt_function(struct scsi_device *sdev, u8 tm_flags) { - struct scsi_device *sdev = scpnt->device; struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); @@ -315,12 +320,40 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { - return zfcp_task_mgmt_function(scpnt, FCP_TMF_LUN_RESET); + struct scsi_device *sdev = scpnt->device; + + return zfcp_task_mgmt_function(sdev, FCP_TMF_LUN_RESET); } static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) { - return zfcp_task_mgmt_function(scpnt, FCP_TMF_TGT_RESET); + struct scsi_target *starget = scsi_target(scpnt->device); + struct fc_rport *rport = starget_to_rport(starget); + struct Scsi_Host *shost = rport_to_shost(rport); + struct scsi_device *sdev = NULL, *tmp_sdev; + struct zfcp_adapter *adapter = + (struct zfcp_adapter *)shost->hostdata[0]; + int ret; + + shost_for_each_device(tmp_sdev, shost) { + if (tmp_sdev->id == starget->id) { + sdev = tmp_sdev; +
[PATCH 17/25] zfcp: remove unused ERP enum values
All constant defines were introduced with v2.6.0 history commit ea127f975424 ("[PATCH] s390 (7/7): zfcp host adapter.") and refactored into enums with commit 287ac01acf22 ("[SCSI] zfcp: Cleanup code in zfcp_erp.c"). ZFCP_STATUS_ERP_DISMISSING and ZFCP_ERP_STEP_FSF_XCONFIG were never used. v2.6.27 commit 287ac01acf22 ("[SCSI] zfcp: Cleanup code in zfcp_erp.c") removed the use of ZFCP_ERP_ACTION_READY on refactoring zfcp_erp_action_exists() to now only check adapter->erp_running_head but no longer adapter->erp_ready_head. The same commit could have changed the function return type from int to "enum zfcp_erp_act_state". ZFCP_ERP_ACTION_READY was never used outside of zfcp_erp_action_exists(). Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 9be629607dc0..b5ca484d5d5f 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -19,7 +19,6 @@ enum zfcp_erp_act_flags { ZFCP_STATUS_ERP_TIMEDOUT= 0x1000, ZFCP_STATUS_ERP_CLOSE_ONLY = 0x0100, - ZFCP_STATUS_ERP_DISMISSING = 0x0010, ZFCP_STATUS_ERP_DISMISSED = 0x0020, ZFCP_STATUS_ERP_LOWMEM = 0x0040, ZFCP_STATUS_ERP_NO_REF = 0x0080, @@ -27,7 +26,6 @@ enum zfcp_erp_act_flags { enum zfcp_erp_steps { ZFCP_ERP_STEP_UNINITIALIZED = 0x, - ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, ZFCP_ERP_STEP_PORT_OPENING = 0x0800, @@ -61,7 +59,6 @@ enum zfcp_erp_act_type { enum zfcp_erp_act_state { ZFCP_ERP_ACTION_RUNNING = 1, - ZFCP_ERP_ACTION_READY = 2, }; enum zfcp_erp_act_result { -- 2.16.3
[PATCH 19/25] zfcp: remove unused return values of ERP trigger functions
Since v2.6.27 commit 553448f6c483 ("[SCSI] zfcp: Message cleanup"), none of the callers has been interested any more. Values were not returned consistently in all ERP trigger functions. Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 34 +- drivers/s390/scsi/zfcp_ext.h | 2 +- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 245621769c26..2968d2f57788 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -294,12 +294,12 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, return erp_action; } -static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, - struct zfcp_port *port, - struct scsi_device *sdev, - char *id, u32 act_status) +static void zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, + struct zfcp_port *port, + struct scsi_device *sdev, + char *id, u32 act_status) { - int retval = 1, need; + int need; struct zfcp_erp_action *act; need = zfcp_erp_handle_failed(want, adapter, port, sdev); @@ -310,7 +310,6 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, if (!adapter->erp_thread) { need = ZFCP_ERP_ACTION_NONE; /* marker for trace */ - retval = -EIO; goto out; } @@ -327,10 +326,8 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, ++adapter->erp_total_count; list_add_tail(>list, >erp_ready_head); wake_up(>erp_ready_wq); - retval = 0; out: zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need); - return retval; } void zfcp_erp_port_forced_no_port_dbf(char *id, struct zfcp_adapter *adapter, @@ -353,14 +350,14 @@ void zfcp_erp_port_forced_no_port_dbf(char *id, struct zfcp_adapter *adapter, write_unlock_irqrestore(>erp_lock, flags); } -static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, +static void _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask, char *id) { zfcp_erp_adapter_block(adapter, clear_mask); zfcp_scsi_schedule_rports_block(adapter); - return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, - adapter, NULL, NULL, id, 0); + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, + adapter, NULL, NULL, id, 0); } /** @@ -439,13 +436,13 @@ void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id) write_unlock_irqrestore(>erp_lock, flags); } -static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) +static void _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); - return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, - port->adapter, port, NULL, id, 0); + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, + port->adapter, port, NULL, id, 0); } /** @@ -453,20 +450,15 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) * @port: port to recover * @clear_mask: flags in port status to be cleared * @id: Id for debug trace event. - * - * Returns 0 if recovery has been triggered, < 0 if not. */ -int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) +void zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { - int retval; unsigned long flags; struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(>erp_lock, flags); - retval = _zfcp_erp_port_reopen(port, clear, id); + _zfcp_erp_port_reopen(port, clear, id); write_unlock_irqrestore(>erp_lock, flags); - - return retval; } static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask) diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index e317c4b513c9..ad7c28ffd49f 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -63,7 +63,7 @@ extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *); extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *); extern void zfcp_erp_set_port_status(struct zfcp_port *, u32); extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32); -extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *); +extern void zfcp_erp_port_reopen(struct zfcp_port *port, int
[PATCH 20/25] zfcp: explicitly support initiator in scsi_host_template
While the default did already correctly print "Initiator" let's make it explicit and convert zfcp to the feature. $ cat /sys/class/scsi_host/host0/supported_mode Initiator $ cat /sys/class/scsi_host/host0/active_mode Initiator The default worked, because not setting the field has it initialized to zero == MODE_UNKNOWN. scsi_host_alloc() sets shost->active_mode = MODE_INITIATOR in this case. The sysfs accessor function show_shost_supported_mode() assumes MODE_INITIATOR in this case. This default behavior was introduced with v2.6.24 commit 7a39ac3f25be ("[SCSI] make supported_mode default to initiator."). The feature flag was introduced with v2.6.24 commit 5dc2b89e1242 ("[SCSI] add supported_mode and active_mode attributes to the host"). So there was no release where zfcp would have shown "unknown". Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_scsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index b4e1f1b82503..f69ef78ea930 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -401,6 +401,7 @@ static struct scsi_host_template zfcp_scsi_host_template = { .shost_attrs = zfcp_sysfs_shost_attrs, .sdev_attrs = zfcp_sysfs_sdev_attrs, .track_queue_depth = 1, + .supported_mode = MODE_INITIATOR, }; /** -- 2.16.3
[PATCH 06/25] zfcp: fix missing REC trigger trace for all objects in ERP_FAILED
That other commit introduced an inconsistency because it would trace on ERP_FAILED for all callers of port forced reopen triggers (not just terminate_rport_io), but it would not trace on ERP_FAILED for all callers of other ERP triggers such as adapter, port regular, LUN. Therefore, generalize that other commit. zfcp_erp_action_enqueue() already had two early outs which re-used the one zfcp_dbf_rec_trig() call. All ERP trigger functions finally run through zfcp_erp_action_enqueue(). So move the special handling for ZFCP_STATUS_COMMON_ERP_FAILED into zfcp_erp_action_enqueue() and add another early out with new trace marker for pseudo ERP need in this case. This removes all early returns from all ERP trigger functions so we always end up at zfcp_dbf_rec_trig(). Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 ZFCP_DBF_REC_TRIG Tag: ... LUN: 0x... WWPN : 0x... D_ID : 0x... Adapter status : 0x... Port status: 0x... LUN status : 0x... Ready count: 0x... Running count : 0x... ERP want : 0x0. ZFCP_ERP_ACTION_REOPEN_... ERP need : 0xe0 ZFCP_ERP_ACTION_FAILED Signed-off-by: Steffen MaierCc: #2.6.38+ Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 79 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 5c368cdfc455..20fe59300d0e 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -143,6 +143,49 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) } } +static int zfcp_erp_handle_failed(int want, struct zfcp_adapter *adapter, + struct zfcp_port *port, + struct scsi_device *sdev) +{ + int need = want; + struct zfcp_scsi_dev *zsdev; + + switch (want) { + case ZFCP_ERP_ACTION_REOPEN_LUN: + zsdev = sdev_to_zfcp(sdev); + if (atomic_read(>status) & ZFCP_STATUS_COMMON_ERP_FAILED) + need = 0; + break; + case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: + if (atomic_read(>status) & ZFCP_STATUS_COMMON_ERP_FAILED) + need = 0; + break; + case ZFCP_ERP_ACTION_REOPEN_PORT: + if (atomic_read(>status) & + ZFCP_STATUS_COMMON_ERP_FAILED) { + need = 0; + /* ensure propagation of failed status to new devices */ + zfcp_erp_set_port_status( + port, ZFCP_STATUS_COMMON_ERP_FAILED); + } + break; + case ZFCP_ERP_ACTION_REOPEN_ADAPTER: + if (atomic_read(>status) & + ZFCP_STATUS_COMMON_ERP_FAILED) { + need = 0; + /* ensure propagation of failed status to new devices */ + zfcp_erp_set_adapter_status( + adapter, ZFCP_STATUS_COMMON_ERP_FAILED); + } + break; + default: + need = 0; + break; + } + + return need; +} + static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, struct zfcp_port *port, struct scsi_device *sdev) @@ -266,6 +309,12 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, int retval = 1, need; struct zfcp_erp_action *act; + need = zfcp_erp_handle_failed(want, adapter, port, sdev); + if (!need) { + need = ZFCP_ERP_ACTION_FAILED; /* marker for trace */ + goto out; + } + if (!adapter->erp_thread) return -EIO; @@ -314,12 +363,6 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, zfcp_erp_adapter_block(adapter, clear_mask); zfcp_scsi_schedule_rports_block(adapter); - /* ensure propagation of failed status to new devices */ - if (atomic_read(>status) & ZFCP_STATUS_COMMON_ERP_FAILED) { - zfcp_erp_set_adapter_status(adapter, - ZFCP_STATUS_COMMON_ERP_FAILED); - return -EIO; - } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, NULL, NULL, id, 0); } @@ -338,12 +381,8 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id) zfcp_scsi_schedule_rports_block(adapter);
[PATCH 03/25] zfcp: fix misleading REC trigger trace where erp_action setup failed
If a SCSI device is deleted during scsi_eh host reset, we cannot get a reference to the SCSI device anymore since scsi_device_get returns !=0 by design. Assuming the recovery of adapter and port(s) was successful, zfcp_erp_strategy_followup_success() attempts to trigger a LUN reset for the half-gone SCSI device. Unfortunately, it causes the following confusing trace record which states that zfcp will do a LUN recovery as "ERP need" is ZFCP_ERP_ACTION_REOPEN_LUN == 1 and equals "ERP want". Old example trace record formatted with zfcpdbf from s390-tools: Tag: : ersfs_3 ERP, trigger, unit reopen, port reopen succeeded LUN: 0x WWPN : 0x D_ID : 0x Adapter status : 0x5400050b Port status: 0x5401 LUN status : 0x4000 ZFCP_STATUS_COMMON_RUNNING but not ZFCP_STATUS_COMMON_UNBLOCKED as it was closed on close part of adapter reopen ERP want : 0x01 ERP need : 0x01 misleading However, zfcp_erp_setup_act() returns NULL as it cannot get the reference. Hence, zfcp_erp_action_enqueue() takes an early goto out and _NO_ recovery actually happens. We always do want the recovery trigger trace record even if no erp_action could be enqueued as in this case. For other cases where we did not enqueue an erp_action, 'need' has always been zero to indicate this. In order to indicate above goto out, introduce an eyecatcher "flag" to mark the "ERP need" as 'not needed' but still keep the information which erp_action type, that zfcp_erp_required_act() had decided upon, is needed. 0xc_ is chosen to be visibly different from 0x0_ in "ERP want". New example trace record formatted with zfcpdbf from s390-tools: Tag: : ersfs_3 ERP, trigger, unit reopen, port reopen succeeded LUN: 0x WWPN : 0x D_ID : 0x Adapter status : 0x5400050b Port status: 0x5401 LUN status : 0x4000 ERP want : 0x01 ERP need : 0xc1 would need LUN ERP, but no action set up ^ Before v2.6.38 commit ae0904f60fab ("[SCSI] zfcp: Redesign of the debug tracing for recovery actions.") we could detect this case because the "erp_action" field in the trace was NULL. The rework removed erp_action as argument and field from the trace. This patch here is for tracing. A fix to allow LUN recovery in the case at hand is a topic for a separate patch. See also commit fdbd1c5e27da ("[SCSI] zfcp: Allow running unit/LUN shutdown without acquiring reference") for a similar case and background info. Signed-off-by: Steffen MaierFixes: ae0904f60fab ("[SCSI] zfcp: Redesign of the debug tracing for recovery actions.") Cc: #2.6.38+ Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 1d91a32db08e..d9cd25b56cfa 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -35,11 +35,23 @@ enum zfcp_erp_steps { ZFCP_ERP_STEP_LUN_OPENING = 0x2000, }; +/** + * enum zfcp_erp_act_type - Type of ERP action object. + * @ZFCP_ERP_ACTION_REOPEN_LUN: LUN recovery. + * @ZFCP_ERP_ACTION_REOPEN_PORT: Port recovery. + * @ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: Forced port recovery. + * @ZFCP_ERP_ACTION_REOPEN_ADAPTER: Adapter recovery. + * @ZFCP_ERP_ACTION_NONE: Eyecatcher pseudo flag to bitwise or-combine with + * either of the other enum values. + * Used to indicate that an ERP action could not be + * set up despite a detected need for some recovery. + */ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_REOPEN_LUN = 1, ZFCP_ERP_ACTION_REOPEN_PORT= 2, ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, + ZFCP_ERP_ACTION_NONE = 0xc0, }; enum zfcp_erp_act_state { @@ -257,8 +269,10 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, goto out; act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev); - if (!act) + if (!act) { + need |= ZFCP_ERP_ACTION_NONE; /* marker for trace */ goto out; + } atomic_or(ZFCP_STATUS_ADAPTER_ERP_PENDING, >status); ++adapter->erp_total_count; list_add_tail(>list, >erp_ready_head); -- 2.16.3
[PATCH 07/25] zfcp: fix missing REC trigger trace on enqueue without ERP thread
Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 ZFCP_DBF_REC_TRIG Tag: ... LUN: 0x... WWPN : 0x... D_ID : 0x... Adapter status : 0x... Port status: 0x... LUN status : 0x... Ready count: 0x... Running count : 0x... ERP want : 0x0. ZFCP_ERP_ACTION_REOPEN_... ERP need : 0xc0 ZFCP_ERP_ACTION_NONE Signed-off-by: Steffen MaierCc: #2.6.38+ Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 20fe59300d0e..69dfb328dba4 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -315,8 +315,11 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, goto out; } - if (!adapter->erp_thread) - return -EIO; + if (!adapter->erp_thread) { + need = ZFCP_ERP_ACTION_NONE; /* marker for trace */ + retval = -EIO; + goto out; + } need = zfcp_erp_required_act(want, adapter, port, sdev); if (!need) -- 2.16.3
[PATCH 15/25] workqueue,zfcp: set description for port work items with their WWPN as context
As a prerequisite, complement commit 3d1cb2059d93 ("workqueue: include workqueue info when printing debug dump of a worker task") to be usable with kernel modules by exporting the symbol set_worker_desc(). Current built-in user was introduced with commit ef3b101925f2 ("writeback: set worker desc to identify writeback workers in task dumps"). Can help distinguishing work items which do not have adapter scope. Description is printed out with task dump for debugging on WARN, BUG, panic, or magic-sysrq [show-task-states(t)]. Example: $ echo 0 >| /sys/bus/ccw/drivers/zfcp/0.0.1880/0x50050763031bd327/failed & $ echo 't' >| /proc/sysrq-trigger $ dmesg sysrq: SysRq : Show State taskPC stack pid father ... zfcp_q_0.0.1880 S14640 2165 2 0x0200 Call Trace: ([<009df464>] __schedule+0xbf4/0xc78) [<009df57c>] schedule+0x94/0xc0 [<00168654>] rescuer_thread+0x33c/0x3a0 [<0016f8be>] kthread+0x166/0x178 [<009e71f2>] kernel_thread_starter+0x6/0xc [<009e71ec>] kernel_thread_starter+0x0/0xc no locks held by zfcp_q_0.0.1880/2165. ... kworker/u512:2 D11280 2193 2 0x0200 Workqueue: zfcp_q_0.0.1880 zfcp_scsi_rport_work [zfcp] (zrpd-50050763031bd327) ^ Call Trace: ([<009df464>] __schedule+0xbf4/0xc78) [<009df57c>] schedule+0x94/0xc0 [<009e50c0>] schedule_timeout+0x488/0x4d0 [<001e425c>] msleep+0x5c/0x78 >>test code only<< [<03ff8008a21e>] zfcp_scsi_rport_work+0xbe/0x100 [zfcp] [<00167154>] process_one_work+0x3b4/0x718 [<0016771c>] worker_thread+0x264/0x408 [<0016f8be>] kthread+0x166/0x178 [<009e71f2>] kernel_thread_starter+0x6/0xc [<009e71ec>] kernel_thread_starter+0x0/0xc 2 locks held by kworker/u512:2/2193: #0: (name){.+}, at: [<00166f4e>] process_one_work+0x1ae/0x718 #1: ((&(>rport_work)->work)){+.+.+.}, at: [<00166f4e>] process_one_work+0x1ae/0x718 ... = Showing busy workqueues and worker pools: workqueue zfcp_q_0.0.1880: flags=0x2000a pwq 512: cpus=0-255 flags=0x4 nice=0 active=1/1 in-flight: 2193:zfcp_scsi_rport_work [zfcp] pool 512: cpus=0-255 flags=0x4 nice=0 hung=0s workers=4 idle: 5 2354 2311 Work items with adapter scope are already identified by the workqueue name "zfcp_q_" and the work item function name. Signed-off-by: Steffen MaierCc: Tejun Heo Cc: Lai Jiangshan Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_fc.c | 2 ++ drivers/s390/scsi/zfcp_scsi.c | 3 +++ kernel/workqueue.c| 1 + 3 files changed, 6 insertions(+) diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 6162cf57a20a..2ad80c43f674 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -425,6 +425,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work) struct zfcp_port *port = container_of(work, struct zfcp_port, gid_pn_work); + set_worker_desc("zgidpn%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */ ret = zfcp_fc_ns_gid_pn(port); if (ret) { /* could not issue gid_pn for some reason */ @@ -559,6 +560,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) container_of(work, struct zfcp_port, test_link_work); int retval; + set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */ get_device(>dev); port->rport_task = RPORT_DEL; zfcp_scsi_rport_work(>rport_work); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index fcc832b73960..0f7830ffd40a 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -730,6 +730,9 @@ void zfcp_scsi_rport_work(struct work_struct *work) struct zfcp_port *port = container_of(work, struct zfcp_port, rport_work); + set_worker_desc("zrp%c-%16llx", + (port->rport_task == RPORT_ADD) ? 'a' : 'd', + port->wwpn); /* < WORKER_DESC_LEN=24 */ while (port->rport_task) { if (port->rport_task == RPORT_ADD) { port->rport_task = RPORT_NONE; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index ca7959be8aaa..4e6fa755ebdc 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -4350,6 +4350,7 @@ void set_worker_desc(const char *fmt, ...) worker->desc_valid = true; } } +EXPORT_SYMBOL_GPL(set_worker_desc); /** * print_worker_info - print out worker information and description -- 2.16.3
[PATCH 13/25] zfcp: decouple TMFs from scsi_cmnd by using fc_block_rport
Intentionally retrieve the rport by walking SCSI common code objects rather than zfcp_sdev->port->rport. The latter is used for pairing the calls to fc_remote_port_add() and fc_remote_port_delete(). [see v2.6.31 commit 379d6bf6573e ("[SCSI] zfcp: Add port only once to FC transport class")] zfcp_scsi_rport_register() sets zfcp_port.rport to what fc_remote_port_add() returned. zfcp_scsi_rport_block() sets zfcp_port.rport = NULL after having called fc_remote_port_delete(). Hence, while an rport is blocked (or in any subsequent state due to scsi_transport_fc timeouts such as fast_io_fail_tmo or dev_loss_tmo), zfcp_port.rport is NULL and cannot serve as argument to fc_block_rport(). During zfcp recovery, a just recovered zfcp_port can have the UNBLOCKED status flag, but an async rport unblocking has only started via zfcp_scsi_schedule_rport_register() in zfcp_erp_try_rport_unblock() [see v4.10 commit 6f2ce1c6af37 ("scsi: zfcp: fix rport unblock race with LUN recovery")] in zfcp_erp_action_cleanup(). Now zfcp_erp_wait() can return. This would be sufficient to successfully send a TMF. But the rport can still be blocked and zfcp_port.rport can still be NULL until zfcp_port.rport_work was scheduled and has actually called fc_remote_port_add() and assigned its return value to zfcp_port.rport. We need an unblocked rport for a successful scsi_eh TUR. Similarly, for a zfcp_port which has just lost its UNBLOCKED status flag, the return of zfcp_erp_wait() can race with zfcp_port.rport_work queued by zfcp_scsi_schedule_rport_block(). Therefore we cannot reliably access zfcp_port.rport. However, we'd like to get fc_rport_block()'s opinion on when fast_io_fail_tmo triggered. While we might use flush_work(>rport_work) to sync with the work item, we can simply use the other way to get an rport pointer. Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- Notes: Changes since RFC: For consistency renamed from "zfcp: use fc_block_rport for TMFs and host reset to decouple from scsi_cmnd". zfcp_scsi_eh_host_reset_handler() will be converted in a later patch. Therefore, this patch here does not touch the host reset case any more. Since the previous "[RFC 6/9] scsi: fc: start decoupling fc_block_scsi_eh from scsi_cmnd" was queued for 4.14 already, I dropped it from this new patch set version and simply depend on it. Intentionally retrieve the rport by walking SCSI common code objects rather than zfcp_sdev->port->rport. This also fixes the problem that we could not synchronize if port->rport is NULL but still continued as if the TMF was successful as Hannes correctly pointed out. drivers/s390/scsi/zfcp_scsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e77e43a0630a..e0c5735cf3db 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -270,6 +270,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) struct scsi_device *sdev = scpnt->device; struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); struct zfcp_fsf_req *fsf_req = NULL; int retval = SUCCESS, ret; int retry = 3; @@ -281,7 +282,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) zfcp_dbf_scsi_devreset("wait", sdev, tm_flags, NULL); zfcp_erp_wait(adapter); - ret = fc_block_scsi_eh(scpnt); + ret = fc_block_rport(rport); if (ret) { zfcp_dbf_scsi_devreset("fiof", sdev, tm_flags, NULL); return ret; -- 2.16.3
[PATCH 12/25] zfcp: decouple SCSI setup of TMF from scsi_cmnd
Actually change the signature of zfcp_fsf_fcp_task_mgmt(). Since it was prepared in the previous patch, we only need to delete a local auto variable which is now the intended argument. Prepare zfcp_fsf_fcp_task_mgmt's caller zfcp_task_mgmt_function() to have its function body only depend on a scsi_device and derived objects. Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- Notes: Changes since RFC: Since the FCP channel always requires a valid LUN handle, we now use scsi_device as context data with any TMF instead of zfcp_port for FCP_TMF_TGT_RESET and an optional scsi_device for FCP_TMF_LUN_RESET. Thus, zfcp_scsi_forget_cmnds() does not need a change anymore and zfcp_task_mgmt_function() needs less changes because the tracing with a mandatory scsi_device is simpler. drivers/s390/scsi/zfcp_ext.h | 3 ++- drivers/s390/scsi/zfcp_fsf.c | 12 ++-- drivers/s390/scsi/zfcp_scsi.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 78bcd80d0509..e317c4b513c9 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -123,7 +123,8 @@ extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32, struct zfcp_fsf_ct_els *, unsigned int); extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *); extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); -extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *, u8); +extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev, + u8 tm_flags); extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *); extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5bc84eaa6948..d86c3bf71664 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2314,17 +2314,17 @@ static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req) } /** - * zfcp_fsf_fcp_task_mgmt - send SCSI task management command - * @scmnd: SCSI command to send the task management command for - * @tm_flags: unsigned byte for task management flags - * Returns: on success pointer to struct fsf_req, NULL otherwise + * zfcp_fsf_fcp_task_mgmt() - Send SCSI task management command (TMF). + * @sdev: Pointer to SCSI device to send the task management command to. + * @tm_flags: Unsigned byte for task management flags. + * + * Return: On success pointer to struct zfcp_fsf_req, %NULL otherwise. */ -struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, +struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev, u8 tm_flags) { struct zfcp_fsf_req *req = NULL; struct fcp_cmnd *fcp_cmnd; - struct scsi_device *sdev = scmnd->device; struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 0afc546b71df..e77e43a0630a 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -275,7 +275,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) int retry = 3; while (retry--) { - fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags); + fsf_req = zfcp_fsf_fcp_task_mgmt(sdev, tm_flags); if (fsf_req) break; -- 2.16.3
[PATCH 11/25] zfcp: decouple FSF request setup of TMF from scsi_cmnd
In zfcp_fsf_fcp_task_mgmt() resolve the still old argument scsi_cmnd into scsi_device very early and only depend on scsi_device and derived objects in the function body. This prepares to later change the function signature replacing the scsi_cmnd argument with scsi_device. Signed-off-by: Steffen MaierReviewed-by: Benjamin Block --- Notes: Changes since RFC: Since the FCP channel always requires a valid LUN handle, we now use scsi_device as context data with any TMF instead of either scsi_device for FCP_TMF_LUN_RESET or zfcp_port for FCP_TMF_TGT_RESET. Thus, zfcp_fc_fcp_tm() no longer needs a change. This also fixes a kernel panic due to the unconditional dereference with sdev_to_zfcp(sdev) where sdev could have been NULL later in the patch set. drivers/s390/scsi/zfcp_fsf.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 8bc768a01ef5..5bc84eaa6948 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2324,7 +2324,8 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, { struct zfcp_fsf_req *req = NULL; struct fcp_cmnd *fcp_cmnd; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device); + struct scsi_device *sdev = scmnd->device; + struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; if (unlikely(!(atomic_read(_sdev->status) & @@ -2344,7 +2345,8 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, goto out; } - req->data = scmnd->device; + req->data = sdev; + req->handler = zfcp_fsf_fcp_task_mgmt_handler; req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; req->qtcb->header.port_handle = zfcp_sdev->port->handle; @@ -2355,7 +2357,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, zfcp_qdio_set_sbale_last(qdio, >qdio_req); fcp_cmnd = >qtcb->bottom.io.fcp_cmnd.iu; - zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags); + zfcp_fc_fcp_tm(fcp_cmnd, sdev, tm_flags); zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); if (!zfcp_fsf_req_send(req)) -- 2.16.3
[PATCH 10/25] zfcp: split FCP_CMND IU setup between SCSI I/O and TMF again
This reverts commit 2443c8b23aea ("[SCSI] zfcp: Merge FCP task management setup with regular FCP command setup"), because this introduced a dependency on the unsuitable SCSI command for scsi_eh / TMF. Signed-off-by: Steffen MaierReviewed-by: Hannes Reinecke Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_fc.h | 22 ++ drivers/s390/scsi/zfcp_fsf.c | 4 ++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h index 6a397ddaadf0..3cd74729cfb9 100644 --- a/drivers/s390/scsi/zfcp_fc.h +++ b/drivers/s390/scsi/zfcp_fc.h @@ -207,21 +207,14 @@ struct zfcp_fc_wka_ports { * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd * @fcp: fcp_cmnd to setup * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB - * @tm: task management flags to setup task management command */ static inline -void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi, -u8 tm_flags) +void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi) { u32 datalen; int_to_scsilun(scsi->device->lun, (struct scsi_lun *) >fc_lun); - if (unlikely(tm_flags)) { - fcp->fc_tm_flags = tm_flags; - return; - } - fcp->fc_pri_ta = FCP_PTA_SIMPLE; if (scsi->sc_data_direction == DMA_FROM_DEVICE) @@ -240,6 +233,19 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi, } } +/** + * zfcp_fc_fcp_tm() - Setup FCP command as task management command. + * @fcp: Pointer to FCP_CMND IU to set up. + * @dev: Pointer to SCSI_device where to send the task management command. + * @tm_flags: Task management flags to setup tm command. + */ +static inline +void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags) +{ + int_to_scsilun(dev->lun, (struct scsi_lun *) >fc_lun); + fcp->fc_tm_flags = tm_flags; +} + /** * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly * @fcp_rsp: FCP RSP IU to evaluate diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index a95070c7cad8..8bc768a01ef5 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2260,7 +2260,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) BUILD_BUG_ON(sizeof(struct fcp_cmnd) > FSF_FCP_CMND_SIZE); fcp_cmnd = >qtcb->bottom.io.fcp_cmnd.iu; - zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0); + zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd); if ((scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) && scsi_prot_sg_count(scsi_cmnd)) { @@ -2355,7 +2355,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd, zfcp_qdio_set_sbale_last(qdio, >qdio_req); fcp_cmnd = >qtcb->bottom.io.fcp_cmnd.iu; - zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags); + zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags); zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT); if (!zfcp_fsf_req_send(req)) -- 2.16.3
[PATCH 02/25] zfcp: fix missing SCSI trace for retry of abort / scsi_eh TMF
We already have a SCSI trace for the end of abort and scsi_eh TMF. Due to zfcp_erp_wait() and fc_block_scsi_eh() time can pass between the start of our eh callback and an actual send/recv of an abort / TMF request. In order to see the temporal sequence including any abort / TMF send retries, add a trace before the above two blocking functions. This supports problem determination with scsi_eh and parallel zfcp ERP. No need to explicitly trace the beginning of our eh callback, since we typically can send an abort / TMF and see its HBA response (in the worst case, it's a pseudo response on dismiss all of adapter recovery, e.g. due to an FSF request timeout [fsrth_1] of the abort / TMF). If we cannot send, we now get a trace record for the first "abrt_wt" or "[lt]r_wait" which denotes almost the beginning of the callback. No need to explicitly trace the wakeup after the above two blocking functions because the next retry loop causes another trace in any case and that is sufficient. Example trace records formatted with zfcpdbf from s390-tools: Timestamp : ... Area : SCSI Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag: abrt_wtabort, before zfcp_erp_wait() Request ID : 0x none (invalid) SCSI ID: 0x SCSI LUN : 0x SCSI LUN high : 0x SCSI result: 0x SCSI retries : 0x SCSI allowed : 0x SCSI scribble : 0x SCSI opcode: FCP rsp inf cod: 0x.. none (invalid) FCP rsp IU : ...none (invalid) Timestamp : ... Area : SCSI Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag: lr_waitLUN reset, before zfcp_erp_wait() Request ID : 0x none (invalid) SCSI ID: 0x SCSI LUN : 0x SCSI LUN high : 0x SCSI result: 0x... unrelated SCSI retries : 0x.. unrelated SCSI allowed : 0x.. unrelated SCSI scribble : 0x... unrelated SCSI opcode: ...unrelated FCP rsp inf cod: 0x.. none (invalid) FCP rsp IU : ...none (invalid) Signed-off-by: Steffen MaierFixes: 63caf367e1c9 ("[SCSI] zfcp: Improve reliability of SCSI eh handlers in zfcp") Fixes: af4de36d911a ("[SCSI] zfcp: Block scsi_eh thread for rport state BLOCKED") Cc: #2.6.38+ Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_scsi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index a62357f5e8b4..4fdb1665b0e6 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -181,6 +181,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) if (abrt_req) break; + zfcp_dbf_scsi_abort("abrt_wt", scpnt, NULL); zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); if (ret) { @@ -277,6 +278,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) if (fsf_req) break; + zfcp_dbf_scsi_devreset("wait", scpnt, tm_flags, NULL); zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); if (ret) { -- 2.16.3
[PATCH 04/25] zfcp: fix missing REC trigger trace on terminate_rport_io early return
get_device() and its internally used kobject_get() only return NULL if they get passed NULL as argument. zfcp_get_port_by_wwpn() loops over adapter->port_list so the iteration variable port is always non-NULL. Struct device is embedded in struct zfcp_port so >dev is always non-NULL. This is the argument to get_device(). However, if we get an fc_rport in terminate_rport_io() for which we cannot find a match within zfcp_get_port_by_wwpn(), the latter can return NULL. v2.6.30 commit 70932935b61e ("[SCSI] zfcp: Fix oops when port disappears") introduced an early return without adding a trace record for this case. Even if we don't need recovery in this case, for debugging we should still see that our callback was invoked originally by scsi_transport_fc. Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : REC Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag: sctrpinSCSI terminate rport I/O, no zfcp port LUN: 0x none (invalid) WWPN : 0x WWPN D_ID : 0x N_Port-ID Adapter status : 0x... Port status: 0x unknown (-1) LUN status : 0x none (invalid) Ready count: 0x... Running count : 0x... ERP want : 0x03 ZFCP_ERP_ACTION_REOPEN_PORT_FORCED ERP need : 0xc0 ZFCP_ERP_ACTION_NONE Signed-off-by: Steffen MaierFixes: 70932935b61e ("[SCSI] zfcp: Fix oops when port disappears") Cc: #2.6.38+ Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_erp.c | 20 drivers/s390/scsi/zfcp_ext.h | 3 +++ drivers/s390/scsi/zfcp_scsi.c | 5 + 3 files changed, 28 insertions(+) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index d9cd25b56cfa..3489b1bc9121 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -283,6 +283,26 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, return retval; } +void zfcp_erp_port_forced_no_port_dbf(char *id, struct zfcp_adapter *adapter, + u64 port_name, u32 port_id) +{ + unsigned long flags; + static /* don't waste stack */ struct zfcp_port tmpport; + + write_lock_irqsave(>erp_lock, flags); + /* Stand-in zfcp port with fields just good enough for +* zfcp_dbf_rec_trig() and zfcp_dbf_set_common(). +* Under lock because tmpport is static. +*/ + atomic_set(, -1); /* unknown */ + tmpport.wwpn = port_name; + tmpport.d_id = port_id; + zfcp_dbf_rec_trig(id, adapter, , NULL, + ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, + ZFCP_ERP_ACTION_NONE); + write_unlock_irqrestore(>erp_lock, flags); +} + static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask, char *id) { diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index e55f42ce1168..3299bd345076 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -55,6 +55,9 @@ extern void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, /* zfcp_erp.c */ extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32); +extern void zfcp_erp_port_forced_no_port_dbf(char *id, +struct zfcp_adapter *adapter, +u64 port_name, u32 port_id); extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *); extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *); extern void zfcp_erp_set_port_status(struct zfcp_port *, u32); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 4fdb1665b0e6..478e7ef9ea2f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -605,6 +605,11 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) if (port) { zfcp_erp_port_forced_reopen(port, 0, "sctrpi1"); put_device(>dev); + } else { + zfcp_erp_port_forced_no_port_dbf( + "sctrpin", adapter, + rport->port_name /* zfcp_scsi_rport_register */, + rport->port_id /* zfcp_scsi_rport_register */); } } -- 2.16.3
[PATCH 01/25] zfcp: fix missing SCSI trace for result of eh_host_reset_handler
For problem determination we need to see whether and why we were successful or not. This allows deduction of scsi_eh escalation. Example trace record formatted with zfcpdbf from s390-tools: Timestamp : ... Area : SCSI Subarea: 00 Level : 1 Exception : - CPU ID : .. Caller : 0x... Record ID : 1 Tag: schrh_rSCSI host reset handler result Request ID : 0x none (invalid) SCSI ID: 0x none (invalid) SCSI LUN : 0x none (invalid) SCSI LUN high : 0x none (invalid) SCSI result: 0x2002 field re-used for midlayer value: SUCCESS or in other cases: 0x2009 == FAST_IO_FAIL SCSI retries : 0xff none (invalid) SCSI allowed : 0xff none (invalid) SCSI scribble : 0x none (invalid) SCSI opcode: none (invalid) FCP rsp inf cod: 0xff none (invalid) FCP rsp IU : none (invalid) v2.6.35 commit a1dbfddd02d2 ("[SCSI] zfcp: Pass return code from fc_block_scsi_eh to scsi eh") introduced the first return with something other than the previously hardcoded single SUCCESS return path. Signed-off-by: Steffen MaierFixes: a1dbfddd02d2 ("[SCSI] zfcp: Pass return code from fc_block_scsi_eh to scsi eh") Cc: #2.6.38+ Reviewed-by: Jens Remus Reviewed-by: Benjamin Block --- drivers/s390/scsi/zfcp_dbf.c | 40 drivers/s390/scsi/zfcp_ext.h | 2 ++ drivers/s390/scsi/zfcp_scsi.c | 11 ++- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a8b831000b2d..1e5ea5e4992b 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -643,6 +643,46 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, spin_unlock_irqrestore(>scsi_lock, flags); } +/** + * zfcp_dbf_scsi_eh() - Trace event for special cases of scsi_eh callbacks. + * @tag: Identifier for event. + * @adapter: Pointer to zfcp adapter as context for this event. + * @scsi_id: SCSI ID/target to indicate scope of task management function (TMF). + * @ret: Return value of calling function. + * + * This SCSI trace variant does not depend on any of: + * scsi_cmnd, zfcp_fsf_req, scsi_device. + */ +void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, + unsigned int scsi_id, int ret) +{ + struct zfcp_dbf *dbf = adapter->dbf; + struct zfcp_dbf_scsi *rec = >scsi_buf; + unsigned long flags; + static int const level = 1; + + if (unlikely(!debug_level_enabled(adapter->dbf->scsi, level))) + return; + + spin_lock_irqsave(>scsi_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_SCSI_CMND; + rec->scsi_result = ret; /* re-use field, int is 4 bytes and fits */ + rec->scsi_retries = ~0; + rec->scsi_allowed = ~0; + rec->fcp_rsp_info = ~0; + rec->scsi_id = scsi_id; + rec->scsi_lun = (u32)ZFCP_DBF_INVALID_LUN; + rec->scsi_lun_64_hi = (u32)(ZFCP_DBF_INVALID_LUN >> 32); + rec->host_scribble = ~0; + memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE); + + debug_event(dbf->scsi, level, rec, sizeof(*rec)); + spin_unlock_irqrestore(>scsi_lock, flags); +} + static debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size) { struct debug_info *d; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index bf8ea4df2bb8..e55f42ce1168 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -49,6 +49,8 @@ extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_scsi(char *, int, struct scsi_cmnd *, struct zfcp_fsf_req *); +extern void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, +unsigned int scsi_id, int ret); /* zfcp_erp.c */ extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 4d2ba5682493..a62357f5e8b4 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -323,15 +323,16 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); struct zfcp_adapter *adapter =
[PATCH 00/25] zfcp: updates for v4.18
James, Martin, this is the zfcp patch set for the v4.18 merge window. The patches apply to Martin's 4.18/scsi-queue. The patches eventually go on top of the bug fix commit fa89adba1941e4f3b213399b81732a5c12fd9131 ("scsi: zfcp: fix infinite iteration on ERP ready list") in Martin's 4.17/scsi-fixes or James' scsi-fixes [https://www.spinics.net/lists/linux-scsi/msg120124.html]. There should be no merge conflicts between the fix and this patch set. Patches 1-7 are debugging/tracing fixes found during function test of 8-14. Patches 8-14 are the result of an earlier RFC to prepare for changing scsi_eh callback function arguments to decouple from scsi_cmnd. [http://www.spinics.net/lists/linux-scsi/msg92.html / https://marc.info/?l=linux-scsi=150099208822680=2] The only difference is that I have to defer the conversion of host_reset(). Patches 15-25 are small cleanups / updates. Jens Remus (3): zfcp: assert that the ERP lock is held when tracing a recovery trigger zfcp: add port speed capabilities zfcp: enhance comments on fc_link_speed and supported_speed Steffen Maier (22): zfcp: fix missing SCSI trace for result of eh_host_reset_handler zfcp: fix missing SCSI trace for retry of abort / scsi_eh TMF zfcp: fix misleading REC trigger trace where erp_action setup failed zfcp: fix missing REC trigger trace on terminate_rport_io early return zfcp: fix missing REC trigger trace on terminate_rport_io for ERP_FAILED zfcp: fix missing REC trigger trace for all objects in ERP_FAILED zfcp: fix missing REC trigger trace on enqueue without ERP thread zfcp: decouple SCSI traces for scsi_eh / TMF from scsi_cmnd zfcp: decouple TMF response handler from scsi_cmnd zfcp: split FCP_CMND IU setup between SCSI I/O and TMF again zfcp: decouple FSF request setup of TMF from scsi_cmnd zfcp: decouple SCSI setup of TMF from scsi_cmnd zfcp: decouple TMFs from scsi_cmnd by using fc_block_rport zfcp: decouple our scsi_eh callbacks from scsi_cmnd workqueue,zfcp: set description for port work items with their WWPN as context zfcp: consistently use function name space prefix zfcp: remove unused ERP enum values zfcp: zfcp_erp_action_exists() does only check for running zfcp: remove unused return values of ERP trigger functions zfcp: explicitly support initiator in scsi_host_template zfcp: support SCSI_ADAPTER_RESET via scsi_host sysfs attribute host_reset zfcp: cleanup indentation for posting FC events drivers/s390/scsi/zfcp_dbf.c | 90 +++ drivers/s390/scsi/zfcp_dbf.h | 21 +++-- drivers/s390/scsi/zfcp_erp.c | 194 - drivers/s390/scsi/zfcp_ext.h | 16 +++- drivers/s390/scsi/zfcp_fc.c| 11 +-- drivers/s390/scsi/zfcp_fc.h| 22 +++-- drivers/s390/scsi/zfcp_fsf.c | 61 - drivers/s390/scsi/zfcp_fsf.h | 6 +- drivers/s390/scsi/zfcp_scsi.c | 141 +++--- drivers/s390/scsi/zfcp_sysfs.c | 5 +- kernel/workqueue.c | 1 + 11 files changed, 401 insertions(+), 167 deletions(-) -- 2.16.3
[PATCH] scsi: snic: fix a couple of spelling mistakes: "COMPLETE"
From: Colin Ian KingTrivial fix to spelling mistakes/typos: "SNIC_IOREQ_ABTS_COMPELTE" -> "SNIC_IOREQ_ABTS_COMPLETE" "SNIC_IOREQ_LR_COMPELTE" -> "SNIC_IOREQ_LR_COMPLETE" "SNIC_IOREQ_CMD_COMPELTE" -> "SNIC_IOREQ_CMD_COMPLETE" Signed-off-by: Colin Ian King --- drivers/scsi/snic/snic_scsi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c index d8a376b7882d..d9b2e46424aa 100644 --- a/drivers/scsi/snic/snic_scsi.c +++ b/drivers/scsi/snic/snic_scsi.c @@ -47,10 +47,10 @@ static const char * const snic_req_state_str[] = { [SNIC_IOREQ_NOT_INITED] = "SNIC_IOREQ_NOT_INITED", [SNIC_IOREQ_PENDING]= "SNIC_IOREQ_PENDING", [SNIC_IOREQ_ABTS_PENDING] = "SNIC_IOREQ_ABTS_PENDING", - [SNIC_IOREQ_ABTS_COMPLETE] = "SNIC_IOREQ_ABTS_COMPELTE", + [SNIC_IOREQ_ABTS_COMPLETE] = "SNIC_IOREQ_ABTS_COMPLETE", [SNIC_IOREQ_LR_PENDING] = "SNIC_IOREQ_LR_PENDING", - [SNIC_IOREQ_LR_COMPLETE] = "SNIC_IOREQ_LR_COMPELTE", - [SNIC_IOREQ_COMPLETE] = "SNIC_IOREQ_CMD_COMPELTE", + [SNIC_IOREQ_LR_COMPLETE] = "SNIC_IOREQ_LR_COMPLETE", + [SNIC_IOREQ_COMPLETE] = "SNIC_IOREQ_CMD_COMPLETE", }; /* snic cmd status strings */ -- 2.17.0
Re: [PATCH 1/1] qla2xxx: Allow SCSI-MQ to be enabled selectively
On Wed, May 16, 2018 at 08:54:11PM -0700, Himanshu Madhani wrote: > when ql2xmqsupport=1, use that value to selectively > enable SCSI-MQ NAK. This is not something that we should grow driver parameters for. Btw, should we look into enabling blk-mq by default again now that all the performance fixes went in and srttled down?
Re: [PATCH 11/40] ipv6/flowlabel: simplify pid namespace lookup
On Thu, May 17, 2018 at 12:28:01AM -0500, Eric W. Biederman wrote: > > struct pid_namespace *proc_pid_namespace(struct inode *inode) > > { > > // maybe warn on for s_magic not on procfs?? > > return inode->i_sb->s_fs_info; > > } > > That should work. Ideally out of line for the proc_fs.h version. > Basically it should be a cousin of PDE_DATA. The version in Al's tree is inline and without the warning as I didn't want to drag in the magic.h include. Please look at it for additional comments, I can send incremental fixups if needed.