Merged revisions 5456-5485,5487-5508 via svnmerge from

svn+ssh://yanb123@svn.code.sf.net/p/scst/svn/trunk

........
  r5456 | bvassche | 2014-04-23 08:15:57 +0300 (Wed, 23 Apr 2014) | 1 line
  
  scst/README: Update implicit ALUA section
........
  r5457 | bvassche | 2014-04-23 11:57:17 +0300 (Wed, 23 Apr 2014) | 1 line
  
  ib_srpt: RHEL 5.9 build fix
........
  r5458 | bvassche | 2014-04-23 11:59:18 +0300 (Wed, 23 Apr 2014) | 1 line
  
  ib_srpt: Clean up the CM event handling code
........
  r5459 | bvassche | 2014-04-23 12:02:29 +0300 (Wed, 23 Apr 2014) | 1 line
  
  ib_srpt: Clean up the CM event handling code (part 2)
........
  r5460 | bvassche | 2014-04-23 12:04:15 +0300 (Wed, 23 Apr 2014) | 1 line
  
  ib_srpt, RDMA/CM: Avoid hanging sessions due to a cable pull
........
  r5461 | bvassche | 2014-04-23 12:20:52 +0300 (Wed, 23 Apr 2014) | 1 line
  
  ib_srpt: RHEL 5.9 build fix (part 2)
........
  r5462 | bvassche | 2014-04-23 16:38:54 +0300 (Wed, 23 Apr 2014) | 1 line
  
  ib_srpt: Clean up the CM event handling messages (part 3)
........
  r5463 | vlnb | 2014-04-24 03:07:22 +0300 (Thu, 24 Apr 2014) | 3 lines
  
  Cleanups
........
  r5464 | vlnb | 2014-04-24 05:30:52 +0300 (Thu, 24 Apr 2014) | 35 lines
  
  scst_lib: Avoid integer overflows
  
  This patch fixes the following kernel oops:
  
  [3696]: scst: scst_parse_cmd:826:Warning: expected transfer length 522240 for opcode 0x08 (handler vcdrom, target iscsi) doesn't match decoded value -2048
  [3696]: scst_parse_cmd:828:Suspicious CDB:
   (h)___0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F
     0: 08 1f ff ff ff 00   ......
  BUG: unable to handle kernel paging request at ffff88283597f0c8
  IP: [<ffffffff8135c3af>] sg_init_table+0x5f/0x90
  Call Trace:
   [<ffffffffa021eb48>] sgv_pool_alloc+0x3b8/0xbf0 [scst]
   [<ffffffffa0204c16>] scst_alloc_space+0xb6/0x290 [scst]
   [<ffffffffa01e2d28>] scst_prepare_space+0x3b8/0x6e0 [scst]
   [<ffffffffa01ef4a5>] scst_process_active_cmd+0x455/0x7e0 [scst]
   [<ffffffffa01efb22>] scst_cmd_init_done+0x2f2/0x5c0 [scst]
   [<ffffffffa0156ac2>] scst_cmd_init_stage1_done.constprop.37+0x12/0x20 [iscsi_scst]
   [<ffffffffa015d9fa>] scsi_cmnd_start+0x25a/0x550 [iscsi_scst]
   [<ffffffffa015e4b8>] cmnd_rx_start+0x148/0x1a0 [iscsi_scst]
   [<ffffffffa0161598>] process_read_io+0x3b8/0x800 [iscsi_scst]
   [<ffffffffa0161aa7>] scst_do_job_rd+0xc7/0x220 [iscsi_scst]
   [<ffffffffa016208d>] istrd+0x16d/0x2e0 [iscsi_scst]
   [<ffffffff81075bad>] kthread+0xed/0x110
   [<ffffffff816dd5bc>] ret_from_fork+0x7c/0xb0
  
  and causes the following message to be reported instead:
  
  [11269]: scst: scst_generic_parse:7402:***WARNING***: bufflen 16777215, data_len 16777215 or out_bufflen 0 too large for device disk12 (block size 2048)
  scst_generic_parse:CDB:
   (h)___0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F
     0: 08 1f ff ff ff 00   ......
  
  Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
  r5465 | vlnb | 2014-04-24 05:33:07 +0300 (Thu, 24 Apr 2014) | 5 lines
  
  scst_targ: Clarify a comment
  
  Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
  r5466 | vlnb | 2014-04-24 05:39:05 +0300 (Thu, 24 Apr 2014) | 12 lines
  
  scst: Avoid that smatch complains about dead code
  
  The panic() function that implements BUG() has been declared with attribute
  noreturn in some RHEL 5 kernel headers and also in the RHEL 6 kernel headers.
  Smatch warns about dead code if any code follows a function that has been
  declared with attribute noreturn. Hence add a few preprocessor statements to
  suppress the smatch warning when building against an upstream kernel or when
  building against RHEL 6 or later.
  
  Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
  r5467 | vlnb | 2014-04-24 06:15:12 +0300 (Thu, 24 Apr 2014) | 3 lines
  
  Fix queuing of UA for aborted by PREEMPT AND ABORT, if TAS is 0, + some clarifications
........
  r5468 | vlnb | 2014-04-24 07:03:51 +0300 (Thu, 24 Apr 2014) | 6 lines
  
  Fix for TARGET RESET race
  
  It can happen, when a device added after blocking, so unblocking then
  will make dev->block_count of the new device negative.
........
  r5469 | bvassche | 2014-04-24 11:41:15 +0300 (Thu, 24 Apr 2014) | 1 line
  
  scst/README: Update multipathd information in implicit ALUA section
........
  r5470 | bvassche | 2014-04-24 13:37:58 +0300 (Thu, 24 Apr 2014) | 1 line
  
  ib_srpt: OFED 3.12 build fix
........
  r5471 | bvassche | 2014-04-24 13:38:37 +0300 (Thu, 24 Apr 2014) | 1 line
  
  ib_srpt: Add support in the Makefile for MLNX OFED and for OFED 3.x
........
  r5472 | bvassche | 2014-04-24 14:11:26 +0300 (Thu, 24 Apr 2014) | 1 line
  
  ib_srpt: Make srpt_disconnect_ch() close sessions properly that have not yet reached the connected state
........
  r5473 | bvassche | 2014-04-24 15:27:00 +0300 (Thu, 24 Apr 2014) | 1 line
  
  ib_srpt, Makefile: Introduce the OFED_KERNEL_DIR variable
........
  r5474 | bvassche | 2014-04-24 21:43:41 +0300 (Thu, 24 Apr 2014) | 1 line
  
  ib_srpt: Unload properly with RDMA/CM disabled
........
  r5475 | bvassche | 2014-04-24 21:45:23 +0300 (Thu, 24 Apr 2014) | 1 line
  
  scstadmin, regression tests: Follow-up for r5409
........
  r5476 | bvassche | 2014-04-24 21:49:52 +0300 (Thu, 24 Apr 2014) | 16 lines
  
  scst: Avoid that reassigning a session triggers a kernel crash
  
  This patch fixes the following kernel bug:
  
  BUG: unable to handle kernel NULL pointer dereference at 0000000000000064
  IP: [<ffffffffa069e59c>] scst_alloc_add_tgt_dev+0x9c/0x540 [scst]
  Call Trace:
   [<ffffffffa06a1b57>] scst_check_reassign_sessions+0x367/0x3b0 [scst]
   [<ffffffffa06a1cb7>] scst_acg_add_acn+0x117/0x1a0 [scst]
   [<ffffffffa06a5e42>] scst_acg_ini_mgmt_store_work_fn+0x152/0x370 [scst]
   [<ffffffffa06a93a6>] sysfs_work_thread_fn+0xa6/0x2f0 [scst]
   [<ffffffff8108dd72>] kthread+0xd2/0xf0
   [<ffffffff816912bc>] ret_from_fork+0x7c/0xb0
  
  Reported-by: Zhen Xu <zhenxu.zj@gmail.com>
........
  r5477 | vlnb | 2014-04-25 02:07:58 +0300 (Fri, 25 Apr 2014) | 3 lines
  
  Minor logging cleanup
........
  r5478 | vlnb | 2014-04-25 02:44:25 +0300 (Fri, 25 Apr 2014) | 3 lines
  
  Cleanup
........
  r5479 | vlnb | 2014-04-25 05:03:04 +0300 (Fri, 25 Apr 2014) | 3 lines
  
  Saved mode pages added
........
  r5480 | vlnb | 2014-04-25 05:47:31 +0300 (Fri, 25 Apr 2014) | 3 lines
  
  Follow up for the previous commit
........
  r5481 | vlnb | 2014-04-26 04:56:36 +0300 (Sat, 26 Apr 2014) | 3 lines
  
  Processing of QErr and TMF_ONLY added
........
  r5482 | vlnb | 2014-04-26 05:12:17 +0300 (Sat, 26 Apr 2014) | 3 lines
  
  Cleanups
........
  r5483 | bvassche | 2014-04-26 09:32:32 +0300 (Sat, 26 Apr 2014) | 7 lines
  
  scst: Fix recently introduced checkpatch complaints about whitespace
  
  Fix two instances of the following checkpatch errors:
  
  ERROR: code indent should use tabs where possible
  ERROR: spaces required around that ':' (ctx:VxW)
........
  r5484 | bvassche | 2014-04-27 09:26:29 +0300 (Sun, 27 Apr 2014) | 6 lines
  
  scst_const.h: Fix a checkpatch complaint about whitespace
  
  Avoid that checkpatch reports the following warning message:
  
  WARNING: please, no space before tabs
........
  r5485 | bvassche | 2014-04-28 12:29:25 +0300 (Mon, 28 Apr 2014) | 5 lines
  
  scst: Export scst_path_put()
  
  This patch makes the code that was added via r5479 build against kernel
  version 2.6.38 and before.
........
  r5487 | vlnb | 2014-04-28 23:31:14 +0300 (Mon, 28 Apr 2014) | 3 lines
  
  Cleanups
........
  r5488 | vlnb | 2014-04-29 00:38:22 +0300 (Tue, 29 Apr 2014) | 3 lines
  
  Returned sense cleanups
........
  r5489 | vlnb | 2014-04-29 01:30:03 +0300 (Tue, 29 Apr 2014) | 3 lines
  
  Let REPORT SUPPORTED OPERATION CODES be handled by dev handler as well
........
  r5490 | vlnb | 2014-04-29 03:13:24 +0300 (Tue, 29 Apr 2014) | 6 lines
  
  It's wrong to clean reservation on failed RESERVE commands
  
  With multiple outstanding commands it can open a race window leading to
  loose of a valid reservation
........
  r5491 | vlnb | 2014-04-29 04:32:13 +0300 (Tue, 29 Apr 2014) | 3 lines
  
  SCSI logging improvements
........
  r5492 | vlnb | 2014-04-29 04:45:43 +0300 (Tue, 29 Apr 2014) | 3 lines
  
  Missed hunk in the previous commit
........
  r5493 | vlnb | 2014-04-29 05:09:29 +0300 (Tue, 29 Apr 2014) | 3 lines
  
  Minor logging improvement
........
  r5494 | bvassche | 2014-04-29 15:35:41 +0300 (Tue, 29 Apr 2014) | 1 line
  
  ib_srpt, README: Fix RDMA/CM login instructions
........
  r5495 | bvassche | 2014-04-29 15:39:50 +0300 (Tue, 29 Apr 2014) | 4 lines
  
  ib_srpt: Make LUN masking work again
  
  This patch fixes a regression that was introduced in r5425.
........
  r5496 | vlnb | 2014-04-30 04:04:27 +0300 (Wed, 30 Apr 2014) | 3 lines
  
  Extended INQUIRY page added
........
  r5497 | vlnb | 2014-04-30 04:07:41 +0300 (Wed, 30 Apr 2014) | 3 lines
  
  Cleanup
........
  r5498 | bvassche | 2014-04-30 08:30:45 +0300 (Wed, 30 Apr 2014) | 1 line
  
  ib_srpt: Fix two recently introduced checkpatch complaints about whitespace
........
  r5499 | bvassche | 2014-04-30 09:01:17 +0300 (Wed, 30 Apr 2014) | 1 line
  
  nightly build: Update kernel versions
........
  r5500 | vlnb | 2014-05-02 05:50:12 +0300 (Fri, 02 May 2014) | 3 lines
  
  Fix CDROM empty case
........
  r5501 | vlnb | 2014-05-02 05:50:34 +0300 (Fri, 02 May 2014) | 3 lines
  
  Cleanups
........
  r5502 | vlnb | 2014-05-02 05:56:19 +0300 (Fri, 02 May 2014) | 9 lines
  
  scst_sysfs: Save the value of the 'preferred' attribute only if it has been set
  
  The default value of the 'preferred' attribute is 0 (disabled). Hence
  it is only necessary that scstadmin saves the value of that attribute
  if it is not zero.
  
  Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
  r5503 | vlnb | 2014-05-07 02:22:32 +0300 (Wed, 07 May 2014) | 3 lines
  
  Cleanups and logging improvements
........
  r5504 | vlnb | 2014-05-07 05:13:11 +0300 (Wed, 07 May 2014) | 5 lines
  
  Fix COMMAND DATA LENGTH in All_commands parameter data of REPORT SUPPORTED OPERATION CODES
  
  Reported by Sebastian Herbszt <herbszt@gmx.de>
........
  r5505 | bvassche | 2014-05-07 11:38:47 +0300 (Wed, 07 May 2014) | 5 lines
  
  scst: Fix the procfs build
  
  Move the definition of scst_get_opcode_name() up such that it occurs
  outside #ifndef CONFIG_SCST_PROC / #endif. See also r5491.
........
  r5506 | bvassche | 2014-05-07 11:57:04 +0300 (Wed, 07 May 2014) | 4 lines
  
  scst_vdisk: Build fix for kernel versions < 2.6.37
      
  See also r5420 / r5479.
........
  r5507 | bvassche | 2014-05-07 16:42:56 +0300 (Wed, 07 May 2014) | 1 line
  
  nightly build: Update kernel versions
........
  r5508 | vlnb | 2014-05-08 05:28:49 +0300 (Thu, 08 May 2014) | 7 lines
  
  Avoid that the code for dumping the PR state triggers a race condition
  
  Callers of scst_pr_dump_prs() must hold dev_pr_mutex.
  
  Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........


git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/iser@5509 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Yan Burman
2014-05-08 08:32:01 +00:00
parent 23250756c2
commit 6a2d41b480
26 changed files with 2295 additions and 613 deletions
+3 -2
View File
@@ -1457,9 +1457,10 @@ static void cmnd_prepare_get_rejected_immed_data(struct iscsi_cmnd *cmnd)
TRACE_DBG_FLAG(iscsi_get_flow_ctrl_or_mgmt_dbg_log_flag(cmnd),
"Skipping (cmnd %p, ITT %x, op %x, cmd op %x, "
"datasize %u, scst_cmd %p, scst state %d)", cmnd,
"datasize %u, scst_cmd %p, scst state %d, status %d)", cmnd,
cmnd->pdu.bhs.itt, cmnd_opcode(cmnd), cmnd_hdr(cmnd)->scb[0],
cmnd->pdu.datasize, cmnd->scst_cmd, cmnd->scst_state);
cmnd->pdu.datasize, cmnd->scst_cmd, cmnd->scst_state,
cmnd->scst_cmd ? cmnd->scst_cmd->status : -1);
iscsi_extracheck_is_rd_thread(conn);
+3 -3
View File
@@ -3,17 +3,17 @@
ABT_DETAILS="x86_64"
ABT_JOBS=5
ABT_KERNELS=" \
3.14.1 \
3.14.3 \
3.13.10 \
3.12.17-nc \
3.11.10-nc \
3.10.37-nc \
3.10.39-nc \
3.9.11-nc \
3.8.14-nc \
3.7.10-nc \
3.6.11-nc \
3.5.7-nc \
3.4.87-nc \
3.4.89-nc \
3.3.8-nc \
3.2.57-nc \
3.1.10-nc \
+13 -13
View File
@@ -2623,16 +2623,16 @@ static int q2t_pre_xmit_response(struct q2t_cmd *cmd,
if (unlikely(scst_get_resid(scst_cmd, &prm->residual, NULL))) {
if (prm->residual > 0) {
TRACE_DBG("Residual underflow: %d (tag %lld, "
"op %x, bufflen %d, rq_result %x)",
"op %s, bufflen %d, rq_result %x)",
prm->residual, scst_cmd->tag,
scst_cmd->cdb[0], cmd->bufflen,
scst_get_opcode_name(scst_cmd), cmd->bufflen,
prm->rq_result);
prm->rq_result |= SS_RESIDUAL_UNDER;
} else if (prm->residual < 0) {
TRACE_DBG("Residual overflow: %d (tag %lld, "
"op %x, bufflen %d, rq_result %x)",
"op %s, bufflen %d, rq_result %x)",
prm->residual, scst_cmd->tag,
scst_cmd->cdb[0], cmd->bufflen,
scst_get_opcode_name(scst_cmd), cmd->bufflen,
prm->rq_result);
prm->rq_result |= SS_RESIDUAL_OVER;
prm->residual = -prm->residual;
@@ -3591,18 +3591,18 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
TRACE(TRACE_MINOR_AND_MGMT_DBG,
"qla2x00t(%ld): CTIO with "
"status %#x received, state %x, scst_cmd %p, "
"op %x (LIP_RESET=e, ABORTED=2, TARGET_RESET=17, "
"op %s (LIP_RESET=e, ABORTED=2, TARGET_RESET=17, "
"TIMEOUT=b, INVALID_RX_ID=8)", ha->instance,
status, cmd->state, scst_cmd, scst_cmd->cdb[0]);
status, cmd->state, scst_cmd, scst_get_opcode_name(scst_cmd));
break;
case CTIO_PORT_LOGGED_OUT:
case CTIO_PORT_UNAVAILABLE:
PRINT_INFO("qla2x00t(%ld): CTIO with PORT LOGGED "
"OUT (29) or PORT UNAVAILABLE (28) status %x "
"received (state %x, scst_cmd %p, op %x)",
"received (state %x, scst_cmd %p, op %s)",
ha->instance, status, cmd->state, scst_cmd,
scst_cmd->cdb[0]);
scst_get_opcode_name(scst_cmd));
break;
case CTIO_SRR_RECEIVED:
@@ -3613,9 +3613,9 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
default:
PRINT_ERROR("qla2x00t(%ld): CTIO with error status "
"0x%x received (state %x, scst_cmd %p, op %x)",
"0x%x received (state %x, scst_cmd %p, op %s)",
ha->instance, status, cmd->state, scst_cmd,
scst_cmd->cdb[0]);
scst_get_opcode_name(scst_cmd));
break;
}
@@ -4652,10 +4652,10 @@ restart:
cmd->sg = scst_cmd_get_sg(&cmd->scst_cmd);
cmd->sg_cnt = scst_cmd_get_sg_cnt(&cmd->scst_cmd);
TRACE_MGMT_DBG("SRR cmd %p (scst_cmd %p, tag %d, op %x), "
TRACE_MGMT_DBG("SRR cmd %p (scst_cmd %p, tag %d, op %s), "
"sg_cnt=%d, offset=%d", cmd, &cmd->scst_cmd,
cmd->tag, cmd->scst_cmd.cdb[0], cmd->sg_cnt,
cmd->offset);
cmd->tag, scst_get_opcode_name(&cmd->scst_cmd),
cmd->sg_cnt, cmd->offset);
if (IS_FWI2_CAPABLE(ha))
q24_handle_srr(ha, sctio, imm);
+108 -76
View File
@@ -949,6 +949,11 @@ cache. The following parameters possible for vdisk_fileio:
initiators can unmap blocks of storage, if they don't need them
anymore. Backend storage also must support this facility.
- tst - allows to specify TST control mode page field. It specifies
the type of task set in the device. Possible values are: 0 - the
device maintains one task set for all I_T nexuses and 1 - the device
maintains separate task sets for each I_T nexus. Default - 1.
- removable - with this flag set the device is reported to remote
initiators as removable.
@@ -965,16 +970,17 @@ storage HBAs and for applications that either do not need caching
between application and disk or need the large block throughput. See
below for more info.
The following parameters possible for vdisk_blockio: filename,
blocksize, nv_cache, read_only, removable, rotational, thin_provisioned.
See vdisk_fileio above for description of those parameters.
The following common with vdisk_fileio parameters are possible for
vdisk_blockio: filename, blocksize, nv_cache, write_through, read_only,
removable, rotational, thin_provisioned, tst. See vdisk_fileio above for
description of those parameters.
Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
this mode no real I/O is done, but success returned to initiators.
Intended to be used for performance measurements at the same way as
"*_perf" handlers. The following parameters possible for vdisk_nullio:
blocksize, read_only, removable. See vdisk_fileio above for description
of those parameters.
blocksize, read_only, removable, tst. See vdisk_fileio above for
description of those parameters.
vdisk_nullio also has extra attribute:
@@ -986,7 +992,7 @@ vdisk_nullio also has extra attribute:
"dummy" placeholder on LUN 0, if LUN 0 is not desired.
Handler vcdrom allows emulation of a virtual CDROM device using an ISO
file as backend. It doesn't have any parameters.
file as backend. It has only single parameter: tst.
For example:
@@ -1025,6 +1031,9 @@ Each vdisk_fileio's device has the following attributes in
SCST device belongs to (in SCSI terminology all SCST devices called
Logical Units). See SPC for more info.
- tst - contains TST field of SCSI Control mode page. See SPC-4 for
more details about this field.
- thin_provisioned - contains thin provisioning status of this virtual
device.
@@ -1087,6 +1096,7 @@ For example:
|-- thin_provisioned
|-- threads_num
|-- threads_pool_type
|-- tst
|-- type
|-- usn
`-- write_through
@@ -1094,17 +1104,17 @@ For example:
Each vdisk_blockio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: blocksize, filename, nv_cache,
read_only, removable, resync_size, rotational, size_mb, t10_dev_id,
thin_provisioned, threads_num, threads_pool_type, type, usn. See above
description of those parameters.
thin_provisioned, threads_num, threads_pool_type, tst, type, usn. See
above description of those parameters.
Each vdisk_nullio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: blocksize, read_only,
removable, size_mb, t10_dev_id, threads_num, threads_pool_type, type,
usn, dummy. See above description of those parameters.
tst, usn, dummy. See above description of those parameters.
Each vcdrom's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: filename, size_mb,
t10_dev_id, threads_num, threads_pool_type, type, usn. See above
t10_dev_id, threads_num, threads_pool_type, type, usn, tst. See above
description of those parameters. Exception is filename attribute. For
vcdrom it is writable. Writing to it allows to virtually insert or
change virtual CD media in the virtual CDROM device. For example:
@@ -1352,70 +1362,48 @@ The steps involved in configuring ALUA are:
As an example, in a H.A. setup with two systems each having one InfiniBand
HCA controlled by the ib_srpt driver and where each system exports two LUNs
could be configured as follows:
the following configuration can be used in scst.conf on both systems:
own_tgt_id=1
other_tgt_id=2
cd /sys/kernel/scst_tgt/device_groups
echo del dgroup1 >mgmt
echo del dgroup2 >mgmt
echo create dgroup1 >mgmt
echo add disk01 >dgroup1/devices/mgmt
echo create tgroup1 >dgroup1/target_groups/mgmt
echo ${own_tgt_id} >dgroup1/target_groups/tgroup1/group_id
echo add ib_srpt_0 >dgroup1/target_groups/tgroup1/mgmt
echo ${own_tgt_id} >dgroup1/target_groups/tgroup1/ib_srpt_0/rel_tgt_id
if [ ${own_tgt_id} = 1 ]; then
echo 1 >dgroup1/target_groups/tgroup1/preferred
fi
echo create tgroup2 >dgroup1/target_groups/mgmt
echo ${other_tgt_id} >dgroup1/target_groups/tgroup2/group_id
echo add ib_srpt_0-other >dgroup1/target_groups/tgroup2/mgmt
echo ${other_tgt_id} >dgroup1/target_groups/tgroup2/ib_srpt_0-other/rel_tgt_id
if [ ${other_tgt_id} = 1 ]; then
echo 1 >dgroup1/target_groups/tgroup2/preferred
fi
echo create dgroup2 >mgmt
echo add disk02 >dgroup2/devices/mgmt
echo create tgroup1 >dgroup2/target_groups/mgmt
echo ${own_tgt_id} >dgroup2/target_groups/tgroup1/group_id
echo add ib_srpt_0 >dgroup2/target_groups/tgroup1/mgmt
echo ${own_tgt_id} >dgroup2/target_groups/tgroup1/ib_srpt_0/rel_tgt_id
if [ ${own_tgt_id} = 2 ]; then
echo 1 >dgroup2/target_groups/tgroup1/preferred
fi
echo create tgroup2 >dgroup2/target_groups/mgmt
echo ${other_tgt_id} >dgroup2/target_groups/tgroup2/group_id
echo add ib_srpt_0-other >dgroup2/target_groups/tgroup2/mgmt
echo ${other_tgt_id} >dgroup2/target_groups/tgroup2/ib_srpt_0-other/rel_tgt_id
if [ ${other_tgt_id} = 2 ]; then
echo 1 >dgroup2/target_groups/tgroup2/preferred
fi
DEVICE_GROUP dgroup1 {
DEVICE disk01
The second system in the same H.A. setup can be configured with the same
commands but with the values of ${own_rel_tgt_id} and ${other_rel_tgt_id}
swapped.
TARGET_GROUP tgroup1 {
group_id 256
preferred 1
state active
TARGET fe80:0000:0000:0000:0002:c903:00fa:b7e1 {
rel_tgt_id 1
}
}
TARGET_GROUP tgroup2 {
group_id 257
state standby
TARGET fe80:0000:0000:0000:0002:c903:00fa:b7f2 {
rel_tgt_id 2
}
}
}
The result of the above commands is:
DEVICE_GROUP dgroup2 {
DEVICE disk02
TARGET_GROUP tgroup1 {
group_id 256
state standby
TARGET fe80:0000:0000:0000:0002:c903:00fa:b7e1 {
rel_tgt_id 1
}
}
TARGET_GROUP tgroup2 {
group_id 257
preferred 1
state active
TARGET fe80:0000:0000:0000:0002:c903:00fa:b7f2 {
rel_tgt_id 2
}
}
}
$ find -type f | grep -v '/mgmt$' | cut -c3- | sort | \
while read f; do echo $f = $(head -n 1 $f); done
dgroup1/target_groups/tgroup1/group_id = 1
dgroup1/target_groups/tgroup1/ib_srpt_0/rel_tgt_id = 1
dgroup1/target_groups/tgroup1/preferred = 1
dgroup1/target_groups/tgroup1/state = active
dgroup1/target_groups/tgroup2/group_id = 2
dgroup1/target_groups/tgroup2/ib_srpt_0-other/rel_tgt_id = 2
dgroup1/target_groups/tgroup2/preferred = 0
dgroup1/target_groups/tgroup2/state = active
dgroup2/target_groups/tgroup1/group_id = 1
dgroup2/target_groups/tgroup1/ib_srpt_0/rel_tgt_id = 1
dgroup2/target_groups/tgroup1/preferred = 1
dgroup2/target_groups/tgroup1/state = active
dgroup2/target_groups/tgroup2/group_id = 2
dgroup2/target_groups/tgroup2/ib_srpt_0-other/rel_tgt_id = 2
dgroup2/target_groups/tgroup2/preferred = 0
dgroup2/target_groups/tgroup2/state = active
Checking the Target Configuration
.................................
@@ -1446,7 +1434,7 @@ configured on the target:
# sg_rtpg /dev/sdb
Report target port groups:
target port group id : 0x1 , Pref=1
target port group id : 0x100 , Pref=1
target port group asymmetric access state : 0x00
T_SUP : 0, O_SUP : 0, LBD_SUP : 0, U_SUP : 1, S_SUP : 1, AN_SUP : 1, AO_SUP : 1
status code : 0x02
@@ -1454,7 +1442,7 @@ Report target port groups:
target port count : 01
Relative target port ids:
0x01
target port group id : 0x2 , Pref=0
target port group id : 0x101 , Pref=0
target port group asymmetric access state : 0x00
T_SUP : 0, O_SUP : 0, LBD_SUP : 0, U_SUP : 1, S_SUP : 1, AN_SUP : 1, AO_SUP : 1
status code : 0x02
@@ -1463,6 +1451,24 @@ Report target port groups:
Relative target port ids:
0x02
The relative target port ID and the target port group ID for a certain path
can be queried e.g. as follows:
# sg_vpd -p di /dev/sdb
Device Identification VPD page:
Addressed logical unit:
designator type: T10 vendor identification, code set: ASCII
vendor id: SCST_FIO
vendor specific: 27cddc71-disk01
designator type: EUI-64 based, code set: Binary
0x3237636464633731
Target port:
designator type: Relative target port, code set: Binary
Relative target port: 0x1
designator type: Target port group, code set: Binary
Target port group: 0x100
Initiator Support
.................
@@ -1472,14 +1478,40 @@ modify at least the following in /etc/multipath.conf to enable implicit ALUA:
* hardware_handler "1 alua"
* prio alua
* path_grouping_policy group_by_prio
* path_checker tur
Note: newer versions of multipathd support a parameter called
"detect_prio". It can be more convenient to enable this parameter instead of
setting the parameter "prio" to "alua" for only those LUNs that support ALUA.
Notes:
- Newer versions of multipathd support a parameter called
"detect_prio". It can be more convenient to enable this parameter instead of
setting the parameter "prio" to "alua" for only those LUNs that support ALUA.
- Older versions of multipathd (e.g. RHEL 5 and SLES 10 SP1) need
'prio_callout "/sbin/mpath_prio_alua /dev/%n"' instead of 'prio alua'.
# multipath -ll
23237636464633731 dm-3 SCST_FIO,disk01
size=1.0G features='3 queue_if_no_path pg_init_retries 50' hwhandler='1 alua' wp=rw
|-+- policy='service-time 0' prio=1 status=active
| `- 10:0:0:0 sdd 8:48 active ready running
`-+- policy='service-time 0' prio=130 status=enabled
`- 11:0:0:0 sde 8:64 active ready running
23133326137346538 dm-4 SCST_FIO,disk02
size=1.0G features='3 queue_if_no_path pg_init_retries 50' hwhandler='1 alua' wp=rw
|-+- policy='service-time 0' prio=130 status=active
| `- 10:0:0:2 sdn 8:208 active ready running
`-+- policy='service-time 0' prio=1 status=enabled
`- 11:0:0:2 sdp 8:240 active ready running
The following information can be derived from the above output:
* That the hardware handler (hw_handler) has been set to "1 alua".
* That multipathd created two priority groups - one with priority 1 and one
with priority 130.
* That the SRP path with SCSI host number 10 will be used for communication
with LUN "disk01" and that the SRP path with SCSI host number 11 will be used
for communication with LUN "disk02".
More information about how to configure the device mapper and the scsi_dh_alua
driver can be found in the manual of your Linux distribution ("man
multipath.conf").
multipath.conf", "man multipath" and "man multipathd").
Windows initiator systems support ALUA from Windows Server 2008 on. For more
information about ALUA support in Windows Server, see also:
+20 -10
View File
@@ -807,6 +807,11 @@ cache. The following parameters possible for vdisk_fileio:
initiators can unmap blocks of storage, if they don't need them
anymore. Backend storage also must support this facility.
- tst - allows to specify TST control mode page field. It specifies
the type of task set in the device. Possible values are: 0 - the
device maintains one task set for all I_T nexuses and 1 - the device
maintains separate task sets for each I_T nexus. Default - 1.
- removable - with this flag set the device is reported to remote
initiators as removable.
@@ -823,16 +828,17 @@ storage HBAs and for applications that either do not need caching
between application and disk or need the large block throughput. See
below for more info.
The following parameters possible for vdisk_blockio: filename,
blocksize, nv_cache, read_only, removable, rotational, thin_provisioned.
See vdisk_fileio above for description of those parameters.
The following common with vdisk_fileio parameters are possible for
vdisk_blockio: filename, blocksize, nv_cache, write_through, read_only,
removable, rotational, thin_provisioned, tst. See vdisk_fileio above for
description of those parameters.
Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
this mode no real I/O is done, but success returned to initiators.
Intended to be used for performance measurements at the same way as
"*_perf" handlers. The following parameters possible for vdisk_nullio:
blocksize, read_only, removable. See vdisk_fileio above for description
of those parameters.
blocksize, read_only, removable, tst. See vdisk_fileio above for
description of those parameters.
vdisk_nullio also has extra attribute:
@@ -844,7 +850,7 @@ vdisk_nullio also has extra attribute:
"dummy" placeholder on LUN 0, if LUN 0 is not desired.
Handler vcdrom allows emulation of a virtual CDROM device using an ISO
file as backend. It doesn't have any parameters.
file as backend. It has only single parameter: tst.
For example:
@@ -883,6 +889,9 @@ Each vdisk_fileio's device has the following attributes in
SCST device belongs to (in SCSI terminology all SCST devices called
Logical Units). See SPC for more info.
- tst - contains TST field of SCSI Control mode page. See SPC-4 for
more details about this field.
- thin_provisioned - contains thin provisioning status of this virtual
device.
@@ -939,6 +948,7 @@ For example:
|-- thin_provisioned
|-- threads_num
|-- threads_pool_type
|-- tst
|-- type
|-- usn
`-- write_through
@@ -946,17 +956,17 @@ For example:
Each vdisk_blockio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: blocksize, filename, nv_cache,
read_only, removable, resync_size, rotational, size_mb, t10_dev_id,
thin_provisioned, threads_num, threads_pool_type, type, usn. See above
description of those parameters.
thin_provisioned, threads_num, threads_pool_type, tst, type, usn. See
above description of those parameters.
Each vdisk_nullio's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: blocksize, read_only,
removable, size_mb, t10_dev_id, threads_num, threads_pool_type, type,
usn, dummy. See above description of those parameters.
tst, usn, dummy. See above description of those parameters.
Each vcdrom's device has the following attributes in
/sys/kernel/scst_tgt/devices/device_name: filename, size_mb,
t10_dev_id, threads_num, threads_pool_type, type, usn. See above
t10_dev_id, threads_num, threads_pool_type, type, usn, tst. See above
description of those parameters. Exception is filename attribute. For
vcdrom it is writable. Writing to it allows to virtually insert or
change virtual CD media in the virtual CDROM device. For example:
+83 -9
View File
@@ -225,6 +225,8 @@ static inline bool list_entry_in_list(const struct list_head *entry)
** !! as well!
*************************************************************/
enum {
/** Active states **/
/* Dev handler's parse() is going to be called */
SCST_CMD_STATE_PARSE = 0,
@@ -258,6 +260,12 @@ enum {
/* Checks before target driver's xmit_response() is called */
SCST_CMD_STATE_PRE_XMIT_RESP,
/* Checks 1 before target driver's xmit_response() is called */
SCST_CMD_STATE_PRE_XMIT_RESP1,
/* Checks 2 before target driver's xmit_response() is called */
SCST_CMD_STATE_PRE_XMIT_RESP2,
/* Target driver's xmit_response() is going to be called */
SCST_CMD_STATE_XMIT_RESP,
@@ -269,6 +277,8 @@ enum {
SCST_CMD_STATE_LAST_ACTIVE = (SCST_CMD_STATE_FINISHED_INTERNAL+100),
/** Passive states **/
/* A cmd is created, but scst_cmd_init_done() not called */
SCST_CMD_STATE_INIT_WAIT,
@@ -568,7 +578,11 @@ enum scst_exec_context {
/* Set if the cmd is aborted by other initiator */
#define SCST_CMD_ABORTED_OTHER 1
/* Set if no response should be sent to the target about this cmd */
/*
* Set if no response should be sent to the target about this cmd.
* Must be set together with SCST_CMD_ABORTED for better processing
* in scst_pre_xmit_response2().
*/
#define SCST_CMD_NO_RESP 2
/* Set if the cmd is dead and can be destroyed at any time */
@@ -2078,8 +2092,8 @@ struct scst_cmd {
unsigned long start_time;
/* List entry for tgt_dev's SN related lists */
struct list_head sn_cmd_list_entry;
/* List entry for tgt_dev's deferred (SN, etc.) lists */
struct list_head deferred_cmd_list_entry;
/* Cmd's serial number, used to execute cmd's in order of arrival */
unsigned int sn;
@@ -2243,6 +2257,10 @@ struct scst_cmd {
void *cmd_data_descriptors;
int cmd_data_descriptors_cnt;
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
char not_parsed_op_name[8];
#endif
#ifdef CONFIG_SCST_MEASURE_LATENCY
uint64_t start, curr_start, parse_time, alloc_buf_time;
uint64_t restart_waiting_time, rdy_to_xfer_time;
@@ -2311,6 +2329,7 @@ struct scst_mgmt_cmd {
unsigned int needs_unblocking:1;
unsigned int lun_set:1; /* set, if lun field is valid */
unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */
unsigned int scst_get_called:1; /* set, if scst_get() was called */
/* Set if dev handler's task_mgmt_fn_received was called */
unsigned int task_mgmt_fn_received_called:1;
unsigned int mcmd_dropped:1; /* set if mcmd was dropped */
@@ -2403,20 +2422,51 @@ struct scst_device {
/*************************************************************
** Dev's control mode page related values. Updates serialized
** by scst_block_dev(). Modified independently to the above
** fields, hence the alignment.
** by device blocking. Since device blocking protects only
** commands on the execution stage, in all other read cases
** use ACCESS_ONCE(), if necessary. Modified independently
** to the above fields, hence the alignment.
*************************************************************/
unsigned int queue_alg:4 __aligned(sizeof(long));
unsigned int tst:3;
unsigned int qerr:2;
unsigned int tmf_only:1;
unsigned int tas:1;
unsigned int swp:1;
unsigned int d_sense:1;
/**
** Saved and default versions of them, which supported. TST is not
** among them, because it's hard to switch curr_order_data on the
** fly. To ensure that no commands lost, we need to flush the previous
** curr_order_data at first and with one being active command (MODE
** SELECT), we don't have facility for that at the moment. Suspending
** activities will hang waiting for the active MODE SELECT. ToDo.
**/
unsigned int queue_alg_saved:4;
unsigned int queue_alg_default:4;
unsigned int tmf_only_saved:1;
unsigned int tmf_only_default:1;
unsigned int qerr_saved:2;
unsigned int qerr_default:2;
unsigned int tas_saved:1;
unsigned int tas_default:1;
unsigned int swp_saved:1;
unsigned int swp_default:1;
unsigned int d_sense_saved:1;
unsigned int d_sense_default:1;
/*
* Set if device implements own ordered commands management. If not set
* and queue_alg is SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER,
* expected_sn will be incremented only after commands finished.
* and queue_alg is SCST_QUEUE_ALG_0_RESTRICTED_REORDER, expected_sn
* will be incremented only after commands finished.
*/
unsigned int has_own_order_mgmt:1;
@@ -2884,7 +2934,6 @@ struct scst_tg_tgt {
uint16_t rel_tgt_id;
};
/*
* Used to store per-session UNIT ATTENTIONs
*/
@@ -4260,7 +4309,7 @@ static inline int scst_check_local_events(struct scst_cmd *cmd)
return __scst_check_local_events(cmd, true);
}
int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd);
int scst_get_cmd_abnormal_done_state(struct scst_cmd *cmd);
void scst_set_cmd_abnormal_done_state(struct scst_cmd *cmd);
struct scst_trace_log {
@@ -4559,6 +4608,15 @@ static inline void put_unaligned_be24(const uint32_t v, uint8_t *const p)
p[2] = v >> 0;
}
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
const char *scst_get_opcode_name(struct scst_cmd *cmd);
#else
static inline const char *scst_get_opcode_name(struct scst_cmd *cmd)
{
return cmd->op_name;
}
#endif
#ifndef CONFIG_SCST_PROC
/*
@@ -4593,6 +4651,7 @@ int scst_wait_info_completion(struct scst_sysfs_user_info *info,
unsigned int scst_get_setup_id(void);
/*
* Needed to avoid potential circular locking dependency between scst_mutex
* and internal sysfs locking (s_active). It could be since most sysfs entries
@@ -4694,4 +4753,19 @@ void scst_write_same(struct scst_cmd *cmd);
__be64 scst_pack_lun(const uint64_t lun, enum scst_lun_addr_method addr_method);
uint64_t scst_unpack_lun(const uint8_t *lun, int len);
int scst_save_global_mode_pages(const struct scst_device *dev,
uint8_t *buf, int size);
int scst_restore_global_mode_pages(struct scst_device *dev, char *params,
char **last_param);
int scst_read_file_transactional(const char *name, const char *name1,
const char *signature, int signature_len, uint8_t *buf, int size);
int scst_write_file_transactional(const char *name, const char *name1,
const char *signature, int signature_len, const uint8_t *buf, int size);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
void scst_path_put(struct nameidata *nd);
#endif
int scst_remove_file(const char *name);
#endif /* __SCST_H */
+14 -6
View File
@@ -495,20 +495,28 @@ enum {
/*************************************************************
** Values for the control mode page TST field
*************************************************************/
#define SCST_CONTR_MODE_ONE_TASK_SET 0
#define SCST_CONTR_MODE_SEP_TASK_SETS 1
#define SCST_TST_0_SINGLE_TASK_SET 0
#define SCST_TST_1_SEP_TASK_SETS 1
/*******************************************************************
** Values for the control mode page QUEUE ALGORITHM MODIFIER field
*******************************************************************/
#define SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER 0
#define SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER 1
#define SCST_QUEUE_ALG_0_RESTRICTED_REORDER 0
#define SCST_QUEUE_ALG_1_UNRESTRICTED_REORDER 1
/*************************************************************
** Values for the control mode page D_SENSE field
*************************************************************/
#define SCST_CONTR_MODE_FIXED_SENSE 0
#define SCST_CONTR_MODE_DESCR_SENSE 1
#define SCST_D_SENSE_0_FIXED_SENSE 0
#define SCST_D_SENSE_1_DESCR_SENSE 1
/*************************************************************
** Values for the control mode page QErr field
*************************************************************/
#define SCST_QERR_0_ALL_RESUME 0
#define SCST_QERR_1_ABORT_ALL 1
#define SCST_QERR_2_RESERVED 2
#define SCST_QERR_3_ABORT_THIS_NEXUS_ONLY 3
/*************************************************************
** TransportID protocol identifiers
+2
View File
@@ -88,7 +88,9 @@ struct scst_user_opt {
/* SCSI control mode page parameters, see SPC */
uint8_t tst;
uint8_t tmf_only;
uint8_t queue_alg;
uint8_t qerr;
uint8_t tas;
uint8_t swp;
uint8_t d_sense;
+1 -1
View File
@@ -116,7 +116,7 @@ endif
@echo "*!! target drivers, custom dev handlers and necessary user !!*"
@echo "*!! space applications. Otherwise, because of the versions !!*"
@echo "*!! mismatch, you could have many problems and crashes. !!*"
@echo "*!! See IMPORTANT note in the \"Installation\" section of !!*"
@echo "*!! See IMPORTANT note in the \"Installation\" section of !!*"
@echo "*!! SCST's README file for more info. !!*"
@echo "*!! !!*"
@echo "*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*"
+1
View File
@@ -71,6 +71,7 @@ all:
$(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd)
install: all
mkdir -p $(DESTDIR)/var/lib/scst/vdev_mode_pages
$(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd) \
modules_install
+3 -2
View File
@@ -406,8 +406,9 @@ static int disk_exec(struct scst_cmd *cmd)
if (unlikely((cmd->bufflen >> block_shift) > max_sectors)) {
if ((cmd->out_bufflen >> block_shift) > max_sectors) {
PRINT_ERROR("Too limited max_sectors %d for "
"bidirectional cmd %x (out_bufflen %d)",
max_sectors, cmd->cdb[0], cmd->out_bufflen);
"bidirectional cmd %p (op %s, out_bufflen %d)",
max_sectors, cmd, scst_get_opcode_name(cmd),
cmd->out_bufflen);
/* Let lower level handle it */
res = SCST_EXEC_NOT_COMPLETED;
goto out;
+46 -12
View File
@@ -62,7 +62,9 @@ struct scst_user_dev {
unsigned int blocking:1;
unsigned int cleanup_done:1;
unsigned int tst:3;
unsigned int tmf_only:1;
unsigned int queue_alg:4;
unsigned int qerr:2;
unsigned int tas:1;
unsigned int swp:1;
unsigned int d_sense:1;
@@ -1368,8 +1370,8 @@ out_process:
return res;
out_inval:
PRINT_ERROR("Invalid parse_reply parameters (LUN %lld, op %x, cmd %p)",
(long long unsigned int)cmd->lun, cmd->cdb[0], cmd);
PRINT_ERROR("Invalid parse_reply parameters (LUN %lld, op %s, cmd %p)",
(long long unsigned int)cmd->lun, scst_get_opcode_name(cmd), cmd);
PRINT_BUFFER("Invalid parse_reply", reply, sizeof(*reply));
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
res = -EINVAL;
@@ -1554,8 +1556,8 @@ out:
return res;
out_inval:
PRINT_ERROR("Invalid exec_reply parameters (LUN %lld, op %x, cmd %p)",
(long long unsigned int)cmd->lun, cmd->cdb[0], cmd);
PRINT_ERROR("Invalid exec_reply parameters (LUN %lld, op %s, cmd %p)",
(long long unsigned int)cmd->lun, scst_get_opcode_name(cmd), cmd);
PRINT_BUFFER("Invalid exec_reply", reply, sizeof(*reply));
out_hwerr:
@@ -2618,10 +2620,22 @@ static int dev_user_attach(struct scst_device *sdev)
sdev->dh_priv = dev;
sdev->tst = dev->tst;
sdev->tmf_only = dev->tmf_only;
sdev->tmf_only_saved = dev->tmf_only;
sdev->tmf_only_default = dev->tmf_only;
sdev->queue_alg = dev->queue_alg;
sdev->qerr = dev->qerr;
sdev->qerr_saved = dev->qerr;
sdev->qerr_default = dev->qerr;
sdev->swp = dev->swp;
sdev->swp_saved = dev->swp;
sdev->swp_default = dev->swp;
sdev->tas = dev->tas;
sdev->tas_saved = dev->tas;
sdev->tas_default = dev->tas;
sdev->d_sense = dev->d_sense;
sdev->d_sense_saved = dev->d_sense;
sdev->d_sense_default = dev->d_sense;
sdev->has_own_order_mgmt = dev->has_own_order_mgmt;
dev->sdev = sdev;
@@ -3350,20 +3364,34 @@ static int __dev_user_set_opt(struct scst_user_dev *dev,
goto out;
}
if (((opt->tst != SCST_CONTR_MODE_ONE_TASK_SET) &&
(opt->tst != SCST_CONTR_MODE_SEP_TASK_SETS)) ||
((opt->queue_alg != SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) &&
(opt->queue_alg != SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER)) ||
if (((opt->tst != SCST_TST_0_SINGLE_TASK_SET) &&
(opt->tst != SCST_TST_1_SEP_TASK_SETS)) ||
(opt->tmf_only > 1) ||
((opt->queue_alg != SCST_QUEUE_ALG_0_RESTRICTED_REORDER) &&
(opt->queue_alg != SCST_QUEUE_ALG_1_UNRESTRICTED_REORDER)) ||
((opt->qerr == SCST_QERR_2_RESERVED) ||
(opt->qerr > SCST_QERR_3_ABORT_THIS_NEXUS_ONLY)) ||
(opt->swp > 1) || (opt->tas > 1) || (opt->has_own_order_mgmt > 1) ||
(opt->d_sense > 1)) {
PRINT_ERROR("Invalid SCSI option (tst %x, queue_alg %x, swp %x,"
" tas %x, d_sense %d, has_own_order_mgmt %x)", opt->tst,
opt->queue_alg, opt->swp, opt->tas, opt->d_sense,
opt->has_own_order_mgmt);
PRINT_ERROR("Invalid SCSI option (tst %x, tmf_only %x, "
"queue_alg %x, qerr %x, swp %x, tas %x, d_sense %d, "
"has_own_order_mgmt %x)",
opt->tst, opt->tmf_only, opt->queue_alg, opt->qerr,
opt->swp, opt->tas, opt->d_sense, opt->has_own_order_mgmt);
res = -EINVAL;
goto out;
}
#if 1
if ((dev->tst != opt->tst) && (dev->sdev != NULL) &&
!list_empty(&dev->sdev->dev_tgt_dev_list)) {
PRINT_ERROR("On the fly setting of TST not supported. "
"See comment in struct scst_device.");
res = -EINVAL;
goto out;
}
#endif
dev->parse_type = opt->parse_type;
dev->on_free_cmd_type = opt->on_free_cmd_type;
dev->memory_reuse_type = opt->memory_reuse_type;
@@ -3371,14 +3399,18 @@ static int __dev_user_set_opt(struct scst_user_dev *dev,
dev->partial_len = opt->partial_len;
dev->tst = opt->tst;
dev->tmf_only = opt->tmf_only;
dev->queue_alg = opt->queue_alg;
dev->qerr = opt->qerr;
dev->swp = opt->swp;
dev->tas = opt->tas;
dev->d_sense = opt->d_sense;
dev->has_own_order_mgmt = opt->has_own_order_mgmt;
if (dev->sdev != NULL) {
dev->sdev->tst = opt->tst;
dev->sdev->tmf_only = opt->tmf_only;
dev->sdev->queue_alg = opt->queue_alg;
dev->sdev->qerr = opt->qerr;
dev->sdev->swp = opt->swp;
dev->sdev->tas = opt->tas;
dev->sdev->d_sense = opt->d_sense;
@@ -3449,7 +3481,9 @@ static int dev_user_get_opt(struct file *file, void __user *arg)
opt.partial_transfers_type = dev->partial_transfers_type;
opt.partial_len = dev->partial_len;
opt.tst = dev->tst;
opt.tmf_only = dev->tmf_only;
opt.queue_alg = dev->queue_alg;
opt.qerr = dev->qerr;
opt.tas = dev->tas;
opt.swp = dev->swp;
opt.d_sense = dev->d_sense;
File diff suppressed because it is too large Load Diff
+801 -79
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -960,8 +960,8 @@ int scst_suspend_activity(unsigned long timeout)
set_bit(SCST_FLAG_SUSPENDED, &scst_flags);
/*
* Assignment of SCST_FLAG_SUSPENDING and SCST_FLAG_SUSPENDED must be
* ordered with cpu_cmd_count in scst_get(). Otherwise lockless logic in
* scst_translate_lun() and scst_mgmt_translate_lun() won't work.
* ordered with cpu_cmd_count in scst_get(). Otherwise, lockless logic
* of scst_get() users won't work.
*/
smp_mb__after_set_bit();
+40 -19
View File
@@ -565,6 +565,27 @@ static void scst_pr_abort_reg(struct scst_device *dev,
*/
PRINT_ERROR("SCST_PR_ABORT_ALL failed %d (sess %p)",
rc, sess);
goto out;
}
if ((reg->tgt_dev != pr_cmd->tgt_dev) && !dev->tas) {
uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
int sl;
sl = scst_set_sense(sense_buffer, sizeof(sense_buffer),
dev->d_sense,
SCST_LOAD_SENSE(scst_sense_cleared_by_another_ini_UA));
/*
* Potentially, setting UA here, when the aborted commands are
* still running, can lead to a situation that one of them could
* take it, then that would be detected and the UA requeued.
* But, meanwhile, one or more subsequent, i.e. not aborted,
* commands can "leak" executed normally. So, as result, the
* UA would be delivered one or more commands "later". However,
* that should be OK, because, if multiple commands are being
* executed in parallel, you can't control exact order of UA
* delivery anyway.
*/
scst_check_set_UA(reg->tgt_dev, sense_buffer, sl, 0);
}
out:
@@ -1559,8 +1580,8 @@ void scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
}
if (spec_i_pt) {
TRACE_PR("%s", "spec_i_pt must be zero in this case");
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_parm_list(cmd, 20,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 3);
goto out;
}
if (action_key == 0) {
@@ -1700,8 +1721,7 @@ void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
if (tid_buffer_size < 24) {
TRACE_PR("%s", "Transport id buffer too small");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, 20, 0);
goto out;
}
@@ -1730,9 +1750,8 @@ void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
*/
if (!scst_pr_is_holder(dev, reg)) {
TRACE_PR("Registrant %s/%d (%p) is not a holder (tgt_dev %p)",
debug_transport_id_to_initiator_name(
reg->transport_id), reg->rel_tgt_id,
reg, tgt_dev);
debug_transport_id_to_initiator_name(reg->transport_id),
reg->rel_tgt_id, reg, tgt_dev);
scst_set_cmd_error_status(cmd, SAM_STAT_RESERVATION_CONFLICT);
goto out;
}
@@ -2267,8 +2286,9 @@ bool scst_pr_crh_case(struct scst_cmd *cmd)
TRACE_ENTRY();
TRACE_DBG("Test if there is a CRH case for command %s (0x%x) from "
"%s", cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
TRACE_DBG("Test if there is a CRH case for command %s (%s) from "
"%s", cmd->op_name, scst_get_opcode_name(cmd),
cmd->sess->initiator_name);
if (!dev->pr_is_set) {
TRACE_PR("%s", "PR not set");
@@ -2303,12 +2323,12 @@ bool scst_pr_crh_case(struct scst_cmd *cmd)
}
if (!allowed)
TRACE_PR("Command %s (0x%x) from %s rejected due to not CRH "
"reservation", cmd->op_name, cmd->cdb[0],
TRACE_PR("Command %s (%s) from %s rejected due to not CRH "
"reservation", cmd->op_name, scst_get_opcode_name(cmd),
cmd->sess->initiator_name);
else
TRACE_DBG("Command %s (0x%x) from %s is allowed to execute "
"due to CRH", cmd->op_name, cmd->cdb[0],
TRACE_DBG("Command %s (%s) from %s is allowed to execute "
"due to CRH", cmd->op_name, scst_get_opcode_name(cmd),
cmd->sess->initiator_name);
out:
@@ -2330,8 +2350,8 @@ bool scst_pr_is_cmd_allowed(struct scst_cmd *cmd)
scst_pr_read_lock(dev);
TRACE_DBG("Testing if command %s (0x%x) from %s allowed to execute",
cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
TRACE_DBG("Testing if command %s (%s) from %s allowed to execute",
cmd->op_name, scst_get_opcode_name(cmd), cmd->sess->initiator_name);
/* Recheck, because it can change while we were waiting for the lock */
if (unlikely(!dev->pr_is_set)) {
@@ -2380,12 +2400,13 @@ bool scst_pr_is_cmd_allowed(struct scst_cmd *cmd)
}
if (!allowed)
TRACE_PR("Command %s (0x%x) from %s rejected due "
"to PR", cmd->op_name, cmd->cdb[0],
TRACE_PR("Command %s (%s) from %s rejected due "
"to PR", cmd->op_name, scst_get_opcode_name(cmd),
cmd->sess->initiator_name);
else
TRACE_DBG("Command %s (0x%x) from %s is allowed to execute",
cmd->op_name, cmd->cdb[0], cmd->sess->initiator_name);
TRACE_DBG("Command %s (%s) from %s is allowed to execute",
cmd->op_name, scst_get_opcode_name(cmd),
cmd->sess->initiator_name);
out_unlock:
scst_pr_read_unlock(dev);
+2 -5
View File
@@ -375,6 +375,8 @@ int scst_set_cmd_error_sense(struct scst_cmd *cmd, uint8_t *sense,
unsigned int len);
void scst_store_sense(struct scst_cmd *cmd);
int scst_process_check_condition(struct scst_cmd *cmd);
int scst_assign_dev_handler(struct scst_device *dev,
struct scst_dev_type *handler);
@@ -770,16 +772,11 @@ void scst_vfs_unlink_and_put(struct nameidata *nd);
void scst_vfs_unlink_and_put(struct path *path);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
void scst_path_put(struct nameidata *nd);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
int scst_vfs_fsync(struct file *file, loff_t loff, loff_t len);
#endif
int scst_copy_file(const char *src, const char *dest);
int scst_remove_file(const char *name);
#ifdef CONFIG_SCST_DEBUG_TM
extern void tm_dbg_check_released_cmds(void);
+6 -1
View File
@@ -397,7 +397,12 @@ int scst_proc_log_entry_write(struct file *file, const char __user *buf,
list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
if (strcmp(dev->virt_name, p) == 0) {
scst_pr_dump_prs(dev, true);
if (mutex_lock_interruptible(&dev->dev_pr_mutex) == 0) {
scst_pr_dump_prs(dev, true);
mutex_unlock(&dev->dev_pr_mutex);
} else {
res = -EINTR;
}
goto out_up;
}
}
+12 -4
View File
@@ -2762,15 +2762,23 @@ static ssize_t scst_dev_sysfs_dump_prs(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
struct scst_device *dev;
int res;
TRACE_ENTRY();
dev = container_of(kobj, struct scst_device, dev_kobj);
res = mutex_lock_interruptible(&dev->dev_pr_mutex);
if (res != 0)
goto out;
scst_pr_dump_prs(dev, true);
mutex_unlock(&dev->dev_pr_mutex);
TRACE_EXIT_RES(count);
return count;
res = count;
out:
TRACE_EXIT_RES(res);
return res;
}
static struct kobj_attribute dev_dump_prs_attr =
@@ -5414,8 +5422,8 @@ static ssize_t scst_tg_preferred_show(struct kobject *kobj,
struct scst_target_group *tg;
tg = container_of(kobj, struct scst_target_group, kobj);
return scnprintf(buf, PAGE_SIZE, "%u\n%s",
tg->preferred, SCST_SYSFS_KEY_MARK "\n");
return scnprintf(buf, PAGE_SIZE, "%u\n%s", tg->preferred,
tg->preferred ? SCST_SYSFS_KEY_MARK "\n" : "");
}
static int scst_tg_preferred_store_work_fn(struct scst_sysfs_work_item *w)
+259 -174
View File
@@ -413,12 +413,12 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
scst_set_start_time(cmd);
TRACE_DBG("Preferred context: %d (cmd %p)", pref_context, cmd);
TRACE(TRACE_SCSI, "lun=%lld, initiator %s, target %s, CDB len=%d, "
"queue_type=%x, tag=%llu (cmd %p, sess %p)",
(long long unsigned int)cmd->lun, cmd->sess->initiator_name,
cmd->tgt->tgt_name, cmd->cdb_len, cmd->queue_type,
TRACE(TRACE_SCSI, "NEW CDB: len %d, lun %lld, initiator %s, "
"target %s, queue_type %x, tag %llu (cmd %p, sess %p)",
cmd->cdb_len, (long long unsigned int)cmd->lun,
cmd->sess->initiator_name, cmd->tgt->tgt_name, cmd->queue_type,
(long long unsigned int)cmd->tag, cmd, sess);
PRINT_BUFF_FLAG(TRACE_SCSI, "Receiving CDB", cmd->cdb, cmd->cdb_len);
PRINT_BUFF_FLAG(TRACE_SCSI, "CDB", cmd->cdb, cmd->cdb_len);
#ifdef CONFIG_SCST_EXTRACHECKS
if (unlikely((in_irq() || irqs_disabled())) &&
@@ -570,19 +570,19 @@ int scst_pre_parse(struct scst_cmd *cmd)
#else
cmd->inc_expected_sn_on_done = devt->exec_sync ||
(!dev->has_own_order_mgmt &&
(dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER ||
(dev->queue_alg == SCST_QUEUE_ALG_0_RESTRICTED_REORDER ||
cmd->queue_type == SCST_CMD_QUEUE_ORDERED));
#endif
TRACE_DBG("op_name <%s> (cmd %p), direction=%d "
"(expected %d, set %s), lba %lld, bufflen=%d, data_len %lld, "
"out_bufflen=%d (expected len %d, out expected len %d), "
"flags=0x%x", cmd->op_name, cmd, cmd->data_direction,
"flags=0x%x, naca %d", cmd->op_name, cmd, cmd->data_direction,
cmd->expected_data_direction,
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
(long long)cmd->lba, cmd->bufflen, (long long)cmd->data_len,
cmd->out_bufflen, cmd->expected_transfer_len,
cmd->expected_out_transfer_len, cmd->op_flags);
cmd->expected_out_transfer_len, cmd->op_flags, cmd->cmd_naca);
res = 0;
@@ -700,8 +700,8 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
if (unlikely(cmd->cdb_len == 0)) {
PRINT_ERROR("Unable to get CDB length for "
"opcode 0x%02x. Returning INVALID "
"OPCODE", cmd->cdb[0]);
"opcode %s. Returning INVALID "
"OPCODE", scst_get_opcode_name(cmd));
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_done;
@@ -726,8 +726,9 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
} else {
if (cmd->bufflen == 0) {
PRINT_ERROR("Unknown data transfer length for opcode "
"0x%x (handler %s, target %s)", cmd->cdb[0],
devt->name, cmd->tgtt->name);
"%s (handler %s, target %s)",
scst_get_opcode_name(cmd), devt->name,
cmd->tgtt->name);
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_message));
@@ -747,7 +748,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
if (unlikely(cmd->cmd_linked)) {
PRINT_ERROR("Linked commands are not supported "
"(opcode 0x%02x)", cmd->cdb[0]);
"(opcode %s)", scst_get_opcode_name(cmd));
scst_set_invalid_field_in_cdb(cmd, cmd->cdb_len-1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out_done;
@@ -768,9 +769,9 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
((cmd->sg == NULL) && (state > SCST_CMD_STATE_PREPARE_SPACE)))) {
PRINT_ERROR("Dev handler %s parse() returned "
"invalid cmd data_direction %d, bufflen %d, state %d "
"or sg %p (opcode 0x%x)", devt->name,
"or sg %p (opcode %s)", devt->name,
cmd->data_direction, cmd->bufflen, state, cmd->sg,
cmd->cdb[0]);
scst_get_opcode_name(cmd));
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
goto out_hw_error;
}
@@ -805,10 +806,10 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
(cmd->bufflen != 0)) &&
!scst_is_allowed_to_mismatch_cmd(cmd)) {
PRINT_ERROR("Expected data direction %d for "
"opcode 0x%02x (handler %s, target %s) "
"opcode %s (handler %s, target %s) "
"doesn't match decoded value %d",
cmd->expected_data_direction,
cmd->cdb[0], devt->name,
scst_get_opcode_name(cmd), devt->name,
cmd->tgtt->name, cmd->data_direction);
PRINT_BUFFER("Failed CDB", cmd->cdb,
cmd->cdb_len);
@@ -819,10 +820,10 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
}
if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) {
TRACE(TRACE_MINOR, "Warning: expected "
"transfer length %d for opcode 0x%02x "
"transfer length %d for opcode %s "
"(handler %s, target %s) doesn't match "
"decoded value %d",
cmd->expected_transfer_len, cmd->cdb[0],
cmd->expected_transfer_len, scst_get_opcode_name(cmd),
devt->name, cmd->tgtt->name, cmd->bufflen);
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
cmd->cdb, cmd->cdb_len);
@@ -832,12 +833,12 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
}
if (unlikely(cmd->out_bufflen != cmd->expected_out_transfer_len)) {
TRACE(TRACE_MINOR, "Warning: expected bidirectional OUT "
"transfer length %d for opcode 0x%02x "
"transfer length %d for opcode %s "
"(handler %s, target %s) doesn't match "
"decoded value %d",
cmd->expected_out_transfer_len, cmd->cdb[0],
devt->name, cmd->tgtt->name,
cmd->out_bufflen);
cmd->expected_out_transfer_len,
scst_get_opcode_name(cmd), devt->name,
cmd->tgtt->name, cmd->out_bufflen);
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
cmd->cdb, cmd->cdb_len);
cmd->resid_possible = 1;
@@ -846,16 +847,17 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
}
if (unlikely(cmd->data_direction == SCST_DATA_UNKNOWN)) {
PRINT_ERROR("Unknown data direction. Opcode 0x%x, handler %s, "
"target %s", cmd->cdb[0], devt->name,
PRINT_ERROR("Unknown data direction (opcode %s, handler %s, "
"target %s)", scst_get_opcode_name(cmd), devt->name,
cmd->tgtt->name);
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
goto out_hw_error;
}
if (unlikely(cmd->op_flags & SCST_UNKNOWN_LBA)) {
PRINT_ERROR("Unknown LBA (opcode 0x%x, handler %s, "
"target %s)", cmd->cdb[0], devt->name, cmd->tgtt->name);
PRINT_ERROR("Unknown LBA (opcode %s, handler %s, "
"target %s)", scst_get_opcode_name(cmd), devt->name,
cmd->tgtt->name);
PRINT_BUFFER("Failed CDB", cmd->cdb, cmd->cdb_len);
goto out_hw_error;
}
@@ -872,13 +874,13 @@ set_res:
TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
"(expected %d, set %s), lba=%lld, bufflen=%d, data len %lld, "
"out_bufflen=%d, (expected len %d, out expected len %d), "
"flags=0x%x, internal %d", cmd->op_name, cmd,
"flags=0x%x, internal %d, naca %d", cmd->op_name, cmd,
cmd->data_direction, cmd->expected_data_direction,
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
(unsigned long long)cmd->lba,
cmd->bufflen, (long long)cmd->data_len, cmd->out_bufflen,
cmd->expected_transfer_len, cmd->expected_out_transfer_len,
cmd->op_flags, cmd->internal);
cmd->op_flags, cmd->internal, cmd->cmd_naca);
#ifdef CONFIG_SCST_EXTRACHECKS
switch (state) {
@@ -893,7 +895,8 @@ set_res:
case SCST_CMD_STATE_REAL_EXEC:
case SCST_CMD_STATE_PRE_DEV_DONE:
case SCST_CMD_STATE_DEV_DONE:
case SCST_CMD_STATE_PRE_XMIT_RESP:
case SCST_CMD_STATE_PRE_XMIT_RESP1:
case SCST_CMD_STATE_PRE_XMIT_RESP2:
case SCST_CMD_STATE_XMIT_RESP:
case SCST_CMD_STATE_FINISHED:
case SCST_CMD_STATE_FINISHED_INTERNAL:
@@ -906,12 +909,12 @@ set_res:
default:
if (state >= 0) {
PRINT_ERROR("Dev handler %s parse() returned "
"invalid cmd state %d (opcode %d)",
devt->name, state, cmd->cdb[0]);
"invalid cmd state %d (opcode %s)",
devt->name, state, scst_get_opcode_name(cmd));
} else {
PRINT_ERROR("Dev handler %s parse() returned "
"error %d (opcode %d)", devt->name,
state, cmd->cdb[0]);
"error %d (opcode %s)", devt->name,
state, scst_get_opcode_name(cmd));
}
goto out_hw_error;
}
@@ -989,12 +992,10 @@ out:
break;
}
if (abort) {
TRACE_MGMT_DBG("Black hole: aborting cmd %p (op %x, "
"initiator %s)", cmd, cmd->cdb[0],
TRACE_MGMT_DBG("Black hole: aborting cmd %p (op %s, "
"initiator %s)", cmd, scst_get_opcode_name(cmd),
sess->initiator_name);
spin_lock_irq(&sess->sess_list_lock);
scst_abort_cmd(cmd, NULL, false, false);
spin_unlock_irq(&sess->sess_list_lock);
}
}
@@ -1304,7 +1305,9 @@ void scst_restart_cmd(struct scst_cmd *cmd, int status,
break;
case SCST_PREPROCESS_STATUS_ERROR_FATAL:
set_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
cmd->delivery_status = SCST_CMD_DELIVERY_FAILED;
/* go through */
case SCST_PREPROCESS_STATUS_ERROR:
if (cmd->sense != NULL)
@@ -1515,7 +1518,6 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
scst_set_rdy_to_xfer_time(cmd);
TRACE_DBG("Preferred context: %d", pref_context);
TRACE(TRACE_SCSI, "cmd %p, status %#x", cmd, status);
cmd->cmd_hw_pending = 0;
@@ -1540,7 +1542,10 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
break;
#endif
/* Small context optimization */
/*
* Make sure that the exec phase runs in thread context since
* invoking I/O functions from atomic context is not allowed.
*/
if ((pref_context == SCST_CONTEXT_TASKLET) ||
(pref_context == SCST_CONTEXT_DIRECT_ATOMIC) ||
((pref_context == SCST_CONTEXT_SAME) &&
@@ -1549,6 +1554,7 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
break;
case SCST_RX_STATUS_ERROR_SENSE_SET:
TRACE(TRACE_SCSI, "cmd %p, RX data error status %#x", cmd, status);
if (!cmd->write_not_received_set)
scst_cmd_set_write_no_data_received(cmd);
scst_set_cmd_abnormal_done_state(cmd);
@@ -1556,9 +1562,12 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
break;
case SCST_RX_STATUS_ERROR_FATAL:
set_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
cmd->delivery_status = SCST_CMD_DELIVERY_FAILED;
/* go through */
case SCST_RX_STATUS_ERROR:
TRACE(TRACE_SCSI, "cmd %p, RX data error status %#x", cmd, status);
if (!cmd->write_not_received_set)
scst_cmd_set_write_no_data_received(cmd);
scst_set_cmd_error(cmd,
@@ -1676,7 +1685,9 @@ static int scst_tgt_pre_exec(struct scst_cmd *cmd)
scst_set_cmd_abnormal_done_state(cmd);
goto out;
case SCST_PREPROCESS_STATUS_ERROR_FATAL:
set_bit(SCST_CMD_ABORTED, &cmd->cmd_flags);
set_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags);
cmd->delivery_status = SCST_CMD_DELIVERY_FAILED;
/* go through */
case SCST_PREPROCESS_STATUS_ERROR:
scst_set_cmd_error(cmd,
@@ -1718,7 +1729,7 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
scst_set_resp_data_len(cmd, cmd->resp_data_len - resid);
/*
* We ignore write direction residue, because from the
* initiator's POV we already transferred all the data.
* initiator's POV we have already transferred all the data.
*/
}
@@ -1805,11 +1816,12 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state,
#ifdef CONFIG_SCST_EXTRACHECKS
if ((next_state != SCST_CMD_STATE_PRE_DEV_DONE) &&
(next_state != SCST_CMD_STATE_PRE_XMIT_RESP) &&
(next_state != SCST_CMD_STATE_PRE_XMIT_RESP1) &&
(next_state != SCST_CMD_STATE_PRE_XMIT_RESP2) &&
(next_state != SCST_CMD_STATE_FINISHED) &&
(next_state != SCST_CMD_STATE_FINISHED_INTERNAL)) {
PRINT_ERROR("%s() received invalid cmd state %d (opcode %d)",
__func__, next_state, cmd->cdb[0]);
PRINT_ERROR("%s() received invalid cmd state %d (opcode %s)",
__func__, next_state, scst_get_opcode_name(cmd));
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
scst_set_cmd_abnormal_done_state(cmd);
@@ -1842,15 +1854,18 @@ static int scst_report_luns_local(struct scst_cmd *cmd)
if ((cmd->cdb[2] != 0) && (cmd->cdb[2] != 2)) {
PRINT_ERROR("Unsupported SELECT REPORT value %x in REPORT "
"LUNS command", cmd->cdb[2]);
goto out_err;
scst_set_invalid_field_in_cdb(cmd, 2, 0);
goto out_compl;
}
buffer_size = scst_get_buf_full_sense(cmd, &buffer);
if (unlikely(buffer_size <= 0))
goto out_compl;
if (buffer_size < 16)
if (buffer_size < 16) {
scst_set_invalid_field_in_cdb(cmd, 6, 0);
goto out_put_err;
}
memset(buffer, 0, buffer_size);
offs = 8;
@@ -1928,10 +1943,6 @@ out_compl:
out_put_err:
scst_put_buf_full(cmd, buffer);
out_err:
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
goto out_compl;
}
@@ -2025,8 +2036,8 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
sl = tgt_dev->tgt_dev_valid_sense_len;
else {
sl = buffer_size;
TRACE(TRACE_MINOR, "%s: Being returned sense truncated "
"to size %d (needed %d)", cmd->op_name,
TRACE(TRACE_SCSI|TRACE_MINOR, "%s: Being returned sense "
"truncated to size %d (needed %d)", cmd->op_name,
buffer_size, tgt_dev->tgt_dev_valid_sense_len);
}
memcpy(buffer, tgt_dev->tgt_dev_sense, sl);
@@ -2124,20 +2135,15 @@ static int scst_report_supported_opcodes(struct scst_cmd *cmd)
int req_sa = get_unaligned_be16(&cmd->cdb[4]);
const struct scst_opcode_descriptor *op = NULL;
const struct scst_opcode_descriptor **supp_opcodes = NULL;
int supp_opcodes_cnt;
int supp_opcodes_cnt, rc;
TRACE_ENTRY();
if (cmd->devt->get_supported_opcodes == NULL) {
TRACE(TRACE_MINOR, "Unknown opcode 0x%02x", cmd->cdb[0]);
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode));
/* get_cdb_info_min() ensures that get_supported_opcodes is not NULL here */
rc = cmd->devt->get_supported_opcodes(cmd, &supp_opcodes, &supp_opcodes_cnt);
if (rc != 0)
goto out_compl;
} else {
int rc = cmd->devt->get_supported_opcodes(cmd, &supp_opcodes,
&supp_opcodes_cnt);
if (rc != 0)
goto out_compl;
}
TRACE_DBG("cmd %p, options %d, req_opcode %x, req_sa %x, rctd %d",
cmd, options, req_opcode, req_sa, rctd);
@@ -2243,7 +2249,7 @@ static int scst_report_supported_opcodes(struct scst_cmd *cmd)
switch (options) {
case 0: /* all */
put_unaligned_be32(buf_len - 3, &buf[0]);
put_unaligned_be32(buf_len - 4, &buf[0]);
offs = 4;
for (i = 0; i < supp_opcodes_cnt; i++) {
op = supp_opcodes[i];
@@ -2354,7 +2360,7 @@ static int scst_reserve_local(struct scst_cmd *cmd)
/*
* There's no need to block this device, even for
* SCST_CONTR_MODE_ONE_TASK_SET, or anyhow else protect reservations
* SCST_TST_0_SINGLE_TASK_SET, or anyhow else protect reservations
* changes, because:
*
* 1. The reservation changes are (rather) atomic, i.e., in contrast
@@ -2363,7 +2369,7 @@ static int scst_reserve_local(struct scst_cmd *cmd)
*
* 2. It's a duty of initiators to ensure order of regular commands
* around the reservation command either by ORDERED attribute, or by
* queue draining, or etc. For case of SCST_CONTR_MODE_ONE_TASK_SET
* queue draining, or etc. For case of SCST_TST_0_SINGLE_TASK_SET
* there are no target drivers which can ensure even for ORDERED
* commands order of their delivery, so, because initiators know
* it, also there's no point to do any extra protection actions.
@@ -2487,9 +2493,10 @@ static int scst_persistent_reserve_in_local(struct scst_cmd *cmd)
session = cmd->sess;
if (unlikely(dev->not_pr_supporting_tgt_devs_num != 0)) {
PRINT_WARNING("Persistent Reservation command %x refused for "
PRINT_WARNING("Persistent Reservation command %s refused for "
"device %s, because the device has not supporting PR "
"transports connected", cmd->cdb[0], dev->virt_name);
"transports connected", scst_get_opcode_name(cmd),
dev->virt_name);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_done;
@@ -2524,8 +2531,8 @@ static int scst_persistent_reserve_in_local(struct scst_cmd *cmd)
action = cmd->cdb[1] & 0x1f;
TRACE(TRACE_SCSI, "PR action %x for '%s' (LUN %llx) from '%s'", action,
dev->virt_name, tgt_dev->lun, session->initiator_name);
TRACE(TRACE_SCSI, "PR IN action %x for '%s' (LUN %llx) from '%s'",
action, dev->virt_name, tgt_dev->lun, session->initiator_name);
switch (action) {
case PR_READ_KEYS:
@@ -2586,18 +2593,18 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
session = cmd->sess;
if (unlikely(dev->not_pr_supporting_tgt_devs_num != 0)) {
PRINT_WARNING("Persistent Reservation command %x refused for "
PRINT_WARNING("Persistent Reservation command %s refused for "
"device %s, because the device has not supporting PR "
"transports connected", cmd->cdb[0], dev->virt_name);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
"transports connected", scst_get_opcode_name(cmd),
dev->virt_name);
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_opcode));
goto out_done;
}
action = cmd->cdb[1] & 0x1f;
TRACE(TRACE_SCSI, "PR action %x for '%s' (LUN %llx) from '%s'", action,
dev->virt_name, tgt_dev->lun, session->initiator_name);
TRACE(TRACE_SCSI, "PR OUT action %x for '%s' (LUN %llx) from '%s'",
action, dev->virt_name, tgt_dev->lun, session->initiator_name);
if (scst_dev_reserved(dev)) {
TRACE_PR("PR command rejected, because device %s holds regular "
@@ -2630,8 +2637,8 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
(action != PR_CLEAR) && (cmd->cdb[2] >> 4) != SCOPE_LU) {
TRACE_PR("Scope must be SCOPE_LU for action %x", action);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 2,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 4);
goto out_unlock;
}
@@ -2639,8 +2646,8 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_MOVE) &&
((buffer[20] >> 3) & 0x01)) {
TRACE_PR("SPEC_I_PT must be zero for action %x", action);
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_parm_list(cmd, 20,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 3);
goto out_unlock;
}
@@ -2648,8 +2655,8 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
(action != PR_REGISTER_AND_MOVE) && ((buffer[20] >> 2) & 0x01)) {
TRACE_PR("ALL_TG_PT must be zero for action %x", action);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_parm_list(cmd, 20,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 2);
goto out_unlock;
}
@@ -3000,10 +3007,11 @@ static int scst_do_real_exec(struct scst_cmd *cmd)
if (rc == -EINVAL &&
(cmd->bufflen >> 9) > queue_max_hw_sectors(scsi_dev->request_queue))
PRINT_ERROR("Too low max_hw_sectors %d sectors on %s "
"to serve command %#x with bufflen %d bytes."
"to serve command %s with bufflen %d bytes."
"See README for more details.",
queue_max_hw_sectors(scsi_dev->request_queue),
dev->virt_name, cmd->cdb[0], cmd->bufflen);
dev->virt_name, scst_get_opcode_name(cmd),
cmd->bufflen);
goto out_error;
}
@@ -3090,8 +3098,9 @@ static int scst_do_local_exec(struct scst_cmd *cmd)
if ((cmd->op_flags & SCST_WRITE_MEDIUM) &&
(tgt_dev->tgt_dev_rd_only || cmd->dev->swp)) {
PRINT_WARNING("Attempt of write access to read-only device: "
"initiator %s, LUN %lld, op %x",
cmd->sess->initiator_name, cmd->lun, cmd->cdb[0]);
"initiator %s, LUN %lld, op %s",
cmd->sess->initiator_name, cmd->lun,
scst_get_opcode_name(cmd));
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_data_protect));
goto out_done;
@@ -3294,7 +3303,7 @@ static int scst_exec_check_sn(struct scst_cmd **active_cmd)
if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
goto exec;
sBUG_ON(!cmd->sn_set);
EXTRACHECKS_BUG_ON(!cmd->sn_set);
expected_sn = ACCESS_ONCE(order_data->expected_sn);
/* Optimized for lockless fast path */
@@ -3330,7 +3339,7 @@ static int scst_exec_check_sn(struct scst_cmd **active_cmd)
TRACE_SN("Deferring cmd %p (sn=%d, set %d, "
"expected_sn=%d)", cmd, cmd->sn,
cmd->sn_set, expected_sn);
list_add_tail(&cmd->sn_cmd_list_entry,
list_add_tail(&cmd->deferred_cmd_list_entry,
&order_data->deferred_cmd_list);
res = SCST_CMD_STATE_RES_CONT_NEXT;
}
@@ -3360,8 +3369,11 @@ static int scst_check_sense(struct scst_cmd *cmd)
TRACE_ENTRY();
if (unlikely(cmd->ua_ignore))
if (unlikely(cmd->ua_ignore)) {
PRINT_BUFF_FLAG(TRACE_SCSI, "Local UA sense", cmd->sense,
cmd->sense_valid_len);
goto out;
}
/* If we had internal bus reset behind us, set the command error UA */
if ((dev->scsi_dev != NULL) &&
@@ -3466,8 +3478,8 @@ static bool scst_check_auto_sense(struct scst_cmd *cmd)
} else {
TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "Host "
"status 0x%x received, returning HARDWARE ERROR "
"instead (cmd %p, op 0x%x, target %s, device "
"%s)", cmd->host_status, cmd, cmd->cdb[0],
"instead (cmd %p, op %s, target %s, device "
"%s)", cmd->host_status, cmd, scst_get_opcode_name(cmd),
cmd->tgt->tgt_name, cmd->dev->virt_name);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
@@ -3484,10 +3496,11 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
TRACE_ENTRY();
if (unlikely(scst_check_auto_sense(cmd))) {
rc = scst_check_auto_sense(cmd);
if (unlikely(rc)) {
PRINT_INFO("Command finished with CHECK CONDITION, but "
"without sense data (opcode 0x%x), issuing "
"REQUEST SENSE", cmd->cdb[0]);
"without sense data (opcode %s), issuing "
"REQUEST SENSE", scst_get_opcode_name(cmd));
rc = scst_prepare_request_sense(cmd);
if (rc == 0)
res = SCST_CMD_STATE_RES_CONT_NEXT;
@@ -3498,7 +3511,10 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
SCST_LOAD_SENSE(scst_sense_hardw_error));
}
goto out;
} else if (unlikely(scst_check_sense(cmd))) {
}
rc = scst_check_sense(cmd);
if (unlikely(rc)) {
/*
* We can't allow atomic command on the exec stages, so
* restart to the thread
@@ -3507,7 +3523,8 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
goto out;
}
if (likely(scsi_status_is_good(cmd->status))) {
rc = scsi_status_is_good(cmd->status);
if (likely(rc)) {
unsigned char type = cmd->dev->type;
if (unlikely((cmd->cdb[0] == MODE_SENSE ||
cmd->cdb[0] == MODE_SENSE_10)) &&
@@ -3580,33 +3597,12 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
if (unlikely((cmd->cdb[0] == MODE_SELECT) ||
(cmd->cdb[0] == MODE_SELECT_10) ||
(cmd->cdb[0] == LOG_SELECT))) {
TRACE(TRACE_SCSI,
"MODE/LOG SELECT succeeded (LUN %lld)",
TRACE(TRACE_SCSI, "MODE/LOG SELECT succeeded (LUN %lld)",
(long long unsigned int)cmd->lun);
cmd->state = SCST_CMD_STATE_MODE_SELECT_CHECKS;
goto out;
}
} else {
TRACE(TRACE_SCSI, "cmd %p not succeeded with status %x",
cmd, cmd->status);
if ((cmd->cdb[0] == RESERVE) || (cmd->cdb[0] == RESERVE_10)) {
struct scst_device *dev = cmd->dev;
if (scst_is_reservation_holder(dev, cmd->sess)) {
TRACE(TRACE_SCSI, "RESERVE failed lun=%lld, "
"status=%x",
(long long unsigned int)cmd->lun,
cmd->status);
PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense,
cmd->sense_valid_len);
spin_lock_bh(&dev->dev_lock);
scst_clear_dev_reservation(dev);
spin_unlock_bh(&dev->dev_lock);
}
}
/* Check for MODE PARAMETERS CHANGED UA */
if ((cmd->dev->scsi_dev != NULL) &&
(cmd->status == SAM_STAT_CHECK_CONDITION) &&
@@ -3719,7 +3715,7 @@ static int scst_dev_done(struct scst_cmd *cmd)
TRACE_ENTRY();
state = SCST_CMD_STATE_PRE_XMIT_RESP;
state = SCST_CMD_STATE_PRE_XMIT_RESP1;
if (likely((cmd->op_flags & SCST_FULLY_LOCAL_CMD) == 0) &&
likely(devt->dev_done != NULL)) {
@@ -3750,7 +3746,8 @@ static int scst_dev_done(struct scst_cmd *cmd)
switch (state) {
#ifdef CONFIG_SCST_EXTRACHECKS
case SCST_CMD_STATE_PRE_XMIT_RESP:
case SCST_CMD_STATE_PRE_XMIT_RESP1:
case SCST_CMD_STATE_PRE_XMIT_RESP2:
case SCST_CMD_STATE_PARSE:
case SCST_CMD_STATE_PREPARE_SPACE:
case SCST_CMD_STATE_RDY_TO_XFER:
@@ -3805,7 +3802,8 @@ static int scst_dev_done(struct scst_cmd *cmd)
cmd->state = SCST_CMD_STATE_FINISHED_INTERNAL;
#ifndef CONFIG_SCST_TEST_IO_IN_SIRQ
if (cmd->state != SCST_CMD_STATE_PRE_XMIT_RESP) {
#ifdef CONFIG_SCST_EXTRACHECKS
if (cmd->state != SCST_CMD_STATE_PRE_XMIT_RESP1) {
/* We can't allow atomic command on the exec stages */
if (scst_cmd_atomic(cmd)) {
switch (state) {
@@ -3822,13 +3820,58 @@ static int scst_dev_done(struct scst_cmd *cmd)
}
}
#endif
#endif
out:
TRACE_EXIT_HRES(res);
return res;
}
static int scst_pre_xmit_response(struct scst_cmd *cmd)
static int scst_pre_xmit_response2(struct scst_cmd *cmd)
{
int res;
TRACE_ENTRY();
again:
if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
scst_xmit_process_aborted_cmd(cmd);
else if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION)) {
if (cmd->tgt_dev != NULL) {
int rc = scst_process_check_condition(cmd);
/* !! At this point cmd can be already dead !! */
if (rc == -1) {
res = SCST_CMD_STATE_RES_CONT_NEXT;
goto out;
} else if (rc == 1)
goto again;
}
}
if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) {
EXTRACHECKS_BUG_ON(!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags));
TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %llu), "
"skipping", cmd, (long long unsigned int)cmd->tag);
cmd->state = SCST_CMD_STATE_FINISHED;
goto out_same;
}
if (unlikely(cmd->resid_possible))
scst_adjust_resp_data_len(cmd);
else
cmd->adjusted_resp_data_len = cmd->resp_data_len;
cmd->state = SCST_CMD_STATE_XMIT_RESP;
out_same:
res = SCST_CMD_STATE_RES_CONT_SAME;
out:
TRACE_EXIT_RES(res);
return res;
}
static int scst_pre_xmit_response1(struct scst_cmd *cmd)
{
int res;
@@ -3838,7 +3881,7 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd)
#ifdef CONFIG_SCST_DEBUG_TM
if (cmd->tm_dbg_delayed &&
!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
if (scst_cmd_atomic(cmd)) {
TRACE_MGMT_DBG("%s",
"DEBUG_TM delayed cmd needs a thread");
@@ -3876,29 +3919,10 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd)
cmd->done = 1;
smp_mb(); /* to sync with scst_abort_cmd() */
if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)))
scst_xmit_process_aborted_cmd(cmd);
else if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION))
scst_store_sense(cmd);
cmd->state = SCST_CMD_STATE_PRE_XMIT_RESP2;
res = scst_pre_xmit_response2(cmd);
if (unlikely(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags))) {
TRACE_MGMT_DBG("Flag NO_RESP set for cmd %p (tag %llu), "
"skipping", cmd, (long long unsigned int)cmd->tag);
cmd->state = SCST_CMD_STATE_FINISHED;
res = SCST_CMD_STATE_RES_CONT_SAME;
goto out;
}
if (unlikely(cmd->resid_possible))
scst_adjust_resp_data_len(cmd);
else
cmd->adjusted_resp_data_len = cmd->resp_data_len;
cmd->state = SCST_CMD_STATE_XMIT_RESP;
res = SCST_CMD_STATE_RES_CONT_SAME;
out:
TRACE_EXIT_HRES(res);
TRACE_EXIT_RES(res);
return res;
}
@@ -4069,6 +4093,7 @@ static int scst_finish_cmd(struct scst_cmd *cmd)
if (unlikely(cmd->delivery_status != SCST_CMD_DELIVERY_SUCCESS)) {
if ((cmd->tgt_dev != NULL) &&
(cmd->status == SAM_STAT_CHECK_CONDITION) &&
scst_is_ua_sense(cmd->sense, cmd->sense_valid_len)) {
/* This UA delivery failed, so we need to requeue it */
if (scst_cmd_atomic(cmd) &&
@@ -4173,7 +4198,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
#endif
if (cmd->dev->queue_alg == SCST_CONTR_MODE_QUEUE_ALG_RESTRICTED_REORDER) {
if (cmd->dev->queue_alg == SCST_QUEUE_ALG_0_RESTRICTED_REORDER) {
if (likely(cmd->queue_type != SCST_CMD_QUEUE_HEAD_OF_QUEUE)) {
/*
* Not the best way, but good enough until there is a
@@ -4228,7 +4253,7 @@ again:
goto again;
case SCST_CMD_QUEUE_ORDERED:
TRACE_SN("ORDERED cmd %p (op %x)", cmd, cmd->cdb[0]);
TRACE_SN("ORDERED cmd %p (op %s)", cmd, scst_get_opcode_name(cmd));
ordered:
order_data->curr_sn++;
TRACE_SN("Incremented curr_sn %d", order_data->curr_sn);
@@ -4271,7 +4296,7 @@ ordered:
break;
case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
TRACE_SN("HQ cmd %p (op %x)", cmd, cmd->cdb[0]);
TRACE_SN("HQ cmd %p (op %s)", cmd, scst_get_opcode_name(cmd));
spin_lock_irqsave(&order_data->sn_lock, flags);
order_data->hq_cmd_count++;
spin_unlock_irqrestore(&order_data->sn_lock, flags);
@@ -4762,10 +4787,14 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
res = scst_dev_done(cmd);
break;
case SCST_CMD_STATE_PRE_XMIT_RESP:
res = scst_pre_xmit_response(cmd);
EXTRACHECKS_BUG_ON(res ==
SCST_CMD_STATE_RES_NEED_THREAD);
case SCST_CMD_STATE_PRE_XMIT_RESP1:
res = scst_pre_xmit_response1(cmd);
EXTRACHECKS_BUG_ON(res == SCST_CMD_STATE_RES_NEED_THREAD);
break;
case SCST_CMD_STATE_PRE_XMIT_RESP2:
res = scst_pre_xmit_response2(cmd);
EXTRACHECKS_BUG_ON(res == SCST_CMD_STATE_RES_NEED_THREAD);
break;
case SCST_CMD_STATE_XMIT_RESP:
@@ -4784,8 +4813,11 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
PRINT_CRIT_ERROR("cmd (%p) in state %d, but shouldn't "
"be", cmd, cmd->state);
sBUG();
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 < 6
/* For suppressing a gcc compiler warning */
res = SCST_CMD_STATE_RES_CONT_NEXT;
break;
#endif
}
} while (res == SCST_CMD_STATE_RES_CONT_SAME);
@@ -4817,8 +4849,10 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
cmd->state);
spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
sBUG();
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 < 6
spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
break;
#endif
}
#endif
wake_up(&cmd->cmd_threads->cmd_list_waitQ);
@@ -4918,21 +4952,16 @@ void scst_cmd_tasklet(long p)
}
/*
* Returns 0 on success, < 0 if there is no device handler or
* > 0 if SCST_FLAG_SUSPENDED set and SCST_FLAG_SUSPENDING - not.
* No locks, protection is done by the suspended activity.
* Returns 0 on success, or > 0 if SCST_FLAG_SUSPENDED set and
* SCST_FLAG_SUSPENDING - not. No locks, protection is done by the
* suspended activity.
*/
static int scst_mgmt_translate_lun(struct scst_mgmt_cmd *mcmd)
static int scst_get_mgmt(struct scst_mgmt_cmd *mcmd)
{
struct scst_tgt_dev *tgt_dev;
struct list_head *head;
int res = -1;
int res = 0;
TRACE_ENTRY();
TRACE_DBG("Finding tgt_dev for mgmt cmd %p (lun %lld)", mcmd,
(long long unsigned int)mcmd->lun);
mcmd->cpu_cmd_counter = scst_get();
if (unlikely(test_bit(SCST_FLAG_SUSPENDED, &scst_flags) &&
@@ -4943,6 +4972,33 @@ static int scst_mgmt_translate_lun(struct scst_mgmt_cmd *mcmd)
goto out;
}
out:
TRACE_EXIT_HRES(res);
return res;
}
/*
* Returns 0 on success, < 0 if there is no device handler or
* > 0 if SCST_FLAG_SUSPENDED set and SCST_FLAG_SUSPENDING - not.
* No locks, protection is done by the suspended activity.
*/
static int scst_mgmt_translate_lun(struct scst_mgmt_cmd *mcmd)
{
struct scst_tgt_dev *tgt_dev;
struct list_head *head;
int res;
TRACE_ENTRY();
TRACE_DBG("Finding tgt_dev for mgmt cmd %p (lun %lld)", mcmd,
(long long unsigned int)mcmd->lun);
res = scst_get_mgmt(mcmd);
if (unlikely(res != 0))
goto out;
res = -1;
head = &mcmd->sess->sess_tgt_dev_list[SESS_TGT_DEV_LIST_HASH_FN(mcmd->lun)];
list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) {
if (tgt_dev->lun == mcmd->lun) {
@@ -5208,8 +5264,8 @@ static inline int scst_is_strict_mgmt_fn(int mgmt_fn)
}
/*
* Must be called under sess_list_lock to sync with finished flag assignment in
* scst_finish_cmd()
* If mcmd != NULL, must be called under sess_list_lock to sync with "finished"
* flag assignment in scst_finish_cmd()
*/
void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
bool other_ini, bool call_dev_task_mgmt_fn_received)
@@ -5226,8 +5282,8 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
if (call_dev_task_mgmt_fn_received)
EXTRACHECKS_BUG_ON(!mcmd);
TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, "Aborting cmd %p (tag %llu, op %x)",
cmd, (long long unsigned int)cmd->tag, cmd->cdb[0]);
TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, "Aborting cmd %p (tag %llu, op %s)",
cmd, (long long unsigned int)cmd->tag, scst_get_opcode_name(cmd));
/* To protect from concurrent aborts */
spin_lock_irqsave(&other_ini_lock, flags);
@@ -5331,12 +5387,12 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
t = TRACE_MGMT_DEBUG;
TRACE(t, "cmd %p (tag %llu, "
"sn %u) being executed/xmitted (state %d, "
"op %x, proc time %ld sec., timeout %d sec.), "
"op %s, proc time %ld sec., timeout %d sec.), "
"deferring ABORT (cmd_done_wait_count %d, "
"cmd_finish_wait_count %d, internal %d, mcmd "
"fn %d (mcmd %p))", cmd,
(long long unsigned int)cmd->tag,
cmd->sn, cmd->state, cmd->cdb[0],
cmd->sn, cmd->state, scst_get_opcode_name(cmd),
(long)(jiffies - cmd->start_time) / HZ,
cmd->timeout / HZ, mcmd->cmd_done_wait_count,
mcmd->cmd_finish_wait_count, cmd->internal,
@@ -5484,7 +5540,7 @@ void scst_unblock_aborted_cmds(const struct scst_tgt *tgt,
spin_lock(&order_data->sn_lock);
list_for_each_entry_safe(cmd, tcmd,
&order_data->deferred_cmd_list,
sn_cmd_list_entry) {
deferred_cmd_list_entry) {
if ((tgt != NULL) && (tgt != cmd->tgt))
continue;
@@ -5492,7 +5548,7 @@ void scst_unblock_aborted_cmds(const struct scst_tgt *tgt,
continue;
if (__scst_check_unblock_aborted_cmd(cmd,
&cmd->sn_cmd_list_entry)) {
&cmd->deferred_cmd_list_entry)) {
TRACE_MGMT_DBG("Unblocked aborted SN "
"cmd %p (sn %u)", cmd, cmd->sn);
order_data->def_cmd_count--;
@@ -5679,6 +5735,18 @@ static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
list_for_each_entry(tgt_dev, &UA_tgt_devs,
extra_tgt_dev_list_entry) {
/*
* Potentially, setting UA here, when the aborted
* commands are still running, can lead to a situation
* that one of them could take it, then that would be
* detected and the UA requeued. But, meanwhile, one or
* more subsequent, i.e. not aborted, commands can
* "leak" executed normally. So, as result, the
* UA would be delivered one or more commands "later".
* However, that should be OK, because, if multiple
* commands are being executed in parallel, you can't
* control exact order of UA delivery anyway.
*/
scst_check_set_UA(tgt_dev, sense_buffer, sl, 0);
}
}
@@ -5742,6 +5810,21 @@ static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
}
case SCST_TARGET_RESET:
/*
* Needed to protect against race, when a device added after
* blocking, so unblocking then will make dev->block_count
* of the new device negative.
*/
rc = scst_get_mgmt(mcmd);
if (rc == 0) {
mcmd->state = SCST_MCMD_STATE_EXEC;
mcmd->scst_get_called = 1;
} else {
EXTRACHECKS_BUG_ON(rc < 0);
res = rc;
}
break;
case SCST_NEXUS_LOSS_SESS:
case SCST_ABORT_ALL_TASKS_SESS:
case SCST_NEXUS_LOSS:
@@ -5950,7 +6033,7 @@ static void scst_do_nexus_loss_sess(struct scst_mgmt_cmd *mcmd)
/* Returns 0 if the command processing should be continued, <0 otherwise */
static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
int nexus_loss)
int nexus_loss_unreg_sess)
{
int res;
int i;
@@ -5959,8 +6042,8 @@ static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd,
TRACE_ENTRY();
if (nexus_loss) {
TRACE_MGMT_DBG("Nexus loss for sess %p (mcmd %p)",
if (nexus_loss_unreg_sess) {
TRACE_MGMT_DBG("Nexus loss or UNREG SESS for sess %p (mcmd %p)",
sess, mcmd);
} else {
TRACE_MGMT_DBG("Aborting all from sess %p (mcmd %p)",
@@ -6125,8 +6208,7 @@ static int scst_mgmt_cmd_exec(struct scst_mgmt_cmd *mcmd)
break;
case SCST_CLEAR_TASK_SET:
if (mcmd->mcmd_tgt_dev->dev->tst ==
SCST_CONTR_MODE_SEP_TASK_SETS)
if (mcmd->mcmd_tgt_dev->dev->tst == SCST_TST_1_SEP_TASK_SETS)
res = scst_abort_task_set(mcmd);
else
res = scst_clear_task_set(mcmd);
@@ -6416,8 +6498,11 @@ static int scst_process_mgmt_cmd(struct scst_mgmt_cmd *mcmd)
mcmd->cmd_finish_wait_count,
mcmd->cmd_done_wait_count);
sBUG();
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 < 6
/* For suppressing a gcc compiler warning */
res = -1;
goto out;
#endif
}
}
@@ -274,10 +274,10 @@ sub lunTest {
Dumper(undef, "luns(): Target 'no-such-target' is not available"));
ok(Dumper($SCST->luns('scst_local', 'local1')),
Dumper({ '0' => 'disk01', '1' => 'disk02', '2' => 'disk01',
'3' => 'disk02' }, undef));
'3' => 'disk02' }));
ok(Dumper($SCST->luns('scst_local', 'local1', 'group1')),
Dumper({ '0' => 'disk01', '2' => 'disk02', '4' => 'disk01',
'6' => 'disk02' }, undef));
'6' => 'disk02' }));
ok(lunReadOnly($SCST, 'scst_local', 'local1', 0), '0');
ok($SCST->setLunAttribute(), $SCST->SCST_C_LUN_SETATTR_FAIL);
@@ -302,11 +302,11 @@ sub lunTest {
ok($SCST->replaceLun('scst_local', 'local1', 0, 'disk02', {}), 0);
ok(Dumper($SCST->luns('scst_local', 'local1')),
Dumper({ '0' => 'disk02', '1' => 'disk02', '2' => 'disk01',
'3' => 'disk02' }, undef));
'3' => 'disk02' }));
ok($SCST->replaceLun('scst_local', 'local1', 0, 'disk01', {}), 0);
ok(Dumper($SCST->luns('scst_local', 'local1')),
Dumper({ '0' => 'disk01', '1' => 'disk02', '2' => 'disk01',
'3' => 'disk02' }, undef));
'3' => 'disk02' }));
ok($SCST->clearLuns(undef, undef), $SCST->SCST_C_TGT_CLR_LUN_FAIL);
ok($SCST->clearLuns(undef, undef, 'group1'),
@@ -322,16 +322,16 @@ sub lunTest {
ok($SCST->removeLun('scst_local', 'local1', '8', 'group1'),
$SCST->SCST_C_GRP_NO_LUN);
ok($SCST->clearLuns('scst_local', 'local1'), 0);
ok(Dumper($SCST->luns('scst_local', 'local1')), Dumper({ }, undef));
ok(Dumper($SCST->luns('scst_local', 'local1')), Dumper({ }));
ok(Dumper($SCST->luns('scst_local', 'local1', 'group1')),
Dumper({ '0' => 'disk01', '2' => 'disk02', '4' => 'disk01',
'6' => 'disk02' }, undef));
'6' => 'disk02' }));
ok($SCST->removeLun('scst_local', 'local1', '4', 'group1'), 0);
ok(Dumper($SCST->luns('scst_local', 'local1', 'group1')),
Dumper({ '0' => 'disk01', '2' => 'disk02', '6' => 'disk02' }, undef));
Dumper({ '0' => 'disk01', '2' => 'disk02', '6' => 'disk02' }));
ok($SCST->clearLuns('scst_local', 'local1', 'group1'), 0);
ok(Dumper($SCST->luns('scst_local', 'local1', 'group1')),
Dumper({ }, undef));
Dumper({ }));
ok($SCST->removeInitiator('scst_local', 'local1', 'group1', 'ini1'), 0);
ok($SCST->removeGroup('scst_local', 'local1', 'group1'), 0);
+33 -20
View File
@@ -47,19 +47,30 @@ SRC_FILES=$(wildcard */*.[ch])
MODULE_SYMVERS:=$(shell if [ -e $(KDIR)/Module.symvers ]; then \
echo Module.symvers; else echo Modules.symvers; fi)
# Whether or not the OFED kernel modules have been installed.
OFED_KERNEL_IB_RPM_INSTALLED:=$(shell if rpm -q kernel-ib 2>/dev/null | grep -q $$(uname -r | sed 's/-/_/g'); then echo true; else echo false; fi)
# Name of the OFED kernel RPM.
OFED_KERNEL_IB_RPM:=$(shell for r in kernel-ib mlnx-ofa_kernel compat-rdma; do rpm -q $$r 2>/dev/null | grep -q "^$$r" && echo $$r && break; done)
# Whether or not the OFED kernel-ib-devel RPM has been installed.
OFED_KERNEL_IB_DEVEL_RPM_INSTALLED:=$(shell if rpm -q kernel-ib-devel 2>/dev/null | grep -q $$(uname -r | sed 's/-/_/g'); then echo true; else echo false; fi)
# Name of the OFED kernel development RPM.
OFED_KERNEL_IB_DEVEL_RPM:=$(shell for r in kernel-ib-devel mlnx-ofa_kernel-devel compat-rdma-devel; do rpm -q $$r 2>/dev/null | grep -q "^$$r" && echo $$r && break; done)
ifeq ($(OFED_KERNEL_IB_DEVEL_RPM_INSTALLED),true)
# Read OFED's config.mk, which contains the definition of the variable
ifeq ($(OFED_KERNEL_IB_RPM),kernel-ib)
OFED_KERNEL_DIR:=/usr/src/ofa_kernel
# Read OFED 1.x's config.mk, which contains the definition of the variable
# BACKPORT_INCLUDES.
include /usr/src/ofa_kernel/config.mk
include $(OFED_KERNEL_DIR)/config.mk
OFED_CFLAGS:=$(BACKPORT_INCLUDES) -I$(OFED_KERNEL_DIR)/include
endif
ifeq ($(OFED_KERNEL_IB_RPM),mlnx-ofa_kernel)
OFED_KERNEL_DIR:=/usr/src/ofa_kernel/default
OFED_CFLAGS:=-I$(OFED_KERNEL_DIR)/default/include
endif
ifeq ($(OFED_KERNEL_IB_RPM),compat-rdma)
OFED_KERNEL_DIR:=/usr/src/compat-rdma
OFED_CFLAGS:=-I$(OFED_KERNEL_DIR)/include
endif
ifneq ($(OFED_KERNEL_IB_RPM),)
OFED_MODULE_SYMVERS:=$(OFED_KERNEL_DIR)/Module.symvers
endif
OFED_CFLAGS:=$(shell if $(OFED_KERNEL_IB_DEVEL_RPM_INSTALLED); then echo $(BACKPORT_INCLUDES) -I/usr/src/ofa_kernel/include; fi)
# Path of the OFED ib_srpt.ko kernel module.
OFED_SRPT_PATH:=/lib/modules/$(KVER)/updates/kernel/drivers/infiniband/ulp/srpt/ib_srpt.ko
@@ -82,14 +93,15 @@ uninstall:
-/sbin/depmod -b $(INSTALL_MOD_PATH)/ -a $(KVER)
src/Module.symvers src/Modules.symvers: $(SCST_SYMVERS_DIR)/$(MODULE_SYMVERS)
@if $(OFED_KERNEL_IB_RPM_INSTALLED); then \
if ! $(OFED_KERNEL_IB_DEVEL_RPM_INSTALLED); then \
echo "Error: the OFED package kernel-ib-devel has not yet been" \
"installed."; \
@if [ -n "$(OFED_KERNEL_IB_RPM)" ]; then \
if [ -z "$(OFED_KERNEL_IB_DEVEL_RPM)" ]; then \
echo "Error: the OFED package $(OFED_KERNEL_IB_RPM)-devel has" \
"not yet been installed."; \
false; \
elif [ -e /lib/modules/$(KVER)/kernel/drivers/infiniband ]; then \
echo "Error: the distro-provided InfiniBand kernel drivers" \
"must be removed first."; \
"must be removed first" \
" (/lib/modules/$(KVER)/kernel/drivers/infiniband)."; \
false; \
elif $(OFED_SRPT_INSTALLED); then \
echo "Error: OFED has been built with srpt=y in ofed.conf."; \
@@ -97,21 +109,22 @@ src/Module.symvers src/Modules.symvers: $(SCST_SYMVERS_DIR)/$(MODULE_SYMVERS)
false; \
elif [ -e $(KDIR)/scripts/Makefile.lib ] \
&& ! grep -wq '^c_flags .*PRE_CFLAGS' \
$(KDIR)/scripts/Makefile.lib \
$(KDIR)/scripts/Makefile.lib \
&& ! grep -wq '^LINUXINCLUDE .*PRE_CFLAGS' \
$(KDIR)/Makefile; then \
$(KDIR)/Makefile; then \
echo "Error: the kernel build system has not yet been patched.";\
false; \
else \
echo " Building against OFED InfiniBand kernel headers."; \
echo " Building against $(OFED_KERNEL_IB_RPM) InfiniBand" \
"kernel headers."; \
( \
grep -v drivers/infiniband/ $<; \
cat /usr/src/ofa_kernel/Module.symvers \
cat $(OFED_MODULE_SYMVERS) \
) >$@; \
fi \
else \
if $(OFED_KERNEL_IB_DEVEL_RPM_INSTALLED); then \
echo "Error: the OFED package kernel-ib has not yet been" \
if [ -n "$(OFED_KERNEL_IB_DEVEL_RPM)" ]; then \
echo "Error: the OFED kernel package has not yet been" \
"installed."; \
false; \
else \
+1 -1
View File
@@ -156,7 +156,7 @@ When using RoCE or iWARP, log in to the target system to determine the id_ext
and ioc_guid parameters and use these to log in. An example:
[ target system ]
# sed 's/,\(pkey\|dgid\|ioc_guid\)=[^,]*//g' $(find /sys/kernel/scst_tgt/targets/ib_srpt -name login_info) | uniq
# sed 's/,\(pkey\|dgid\|service_id\)=[^,]*//g' $(find /sys/kernel/scst_tgt/targets/ib_srpt -name login_info) | uniq
id_ext=0002c90300a34270,ioc_guid=0002c90300a34270
[ initiator system ]
+134 -72
View File
@@ -335,6 +335,8 @@ static const char *get_ch_state_name(enum rdma_ch_state s)
return "live";
case CH_DISCONNECTING:
return "disconnecting";
case CH_DRAINING:
return "draining";
case CH_DISCONNECTED:
return "disconnected";
}
@@ -2175,10 +2177,57 @@ static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch)
ib_destroy_cq(ch->cq);
}
/**
* srpt_close_ch() - Close an RDMA channel.
*
* Make sure all resources associated with the channel will be deallocated at
* an appropriate time.
*
* Returns true if and only if the channel state has been modified into
* CH_DRAINING.
*/
static bool srpt_close_ch(struct srpt_rdma_ch *ch)
{
int ret;
if (!srpt_set_ch_state(ch, CH_DRAINING))
return false;
kref_get(&ch->kref);
ret = srpt_ch_qp_err(ch);
if (ret < 0)
PRINT_ERROR("%s: changing queue pair into error state"
" failed: %d", ch->sess_name, ret);
ret = srpt_zerolength_write(ch);
if (ret < 0) {
PRINT_ERROR("%s: queuing zero-length write failed: %d",
ch->sess_name, ret);
WARN_ON_ONCE(!srpt_set_ch_state(ch, CH_DISCONNECTED));
}
kref_put(&ch->kref, srpt_free_ch);
return true;
}
/*
* Change the channel state into CH_DISCONNECTING. If a channel has not yet
* reached the connected state, close it. If a channel is in the connected
* state, send a DREQ. If a DREQ has been received, send a DREP. Note: it is
* the responsibility of the caller to ensure that this function is not
* invoked concurrently with the code that accepts a connection. This means
* that this function must either be invoked from inside a CM callback
* function or that it must be invoked with the srpt_tgt.mutex held.
*/
static int srpt_disconnect_ch(struct srpt_rdma_ch *ch)
{
int ret;
if (!srpt_set_ch_state(ch, CH_DISCONNECTING))
return -ENOTCONN;
if (ch->using_rdma_cm) {
ret = rdma_disconnect(ch->rdma_cm.cm_id);
} else {
@@ -2187,45 +2236,12 @@ static int srpt_disconnect_ch(struct srpt_rdma_ch *ch)
ret = ib_send_cm_drep(ch->ib_cm.cm_id, NULL, 0);
}
if (ret < 0 && srpt_close_ch(ch))
ret = 0;
return ret;
}
/**
* srpt_close_ch() - Close an RDMA channel.
*
* Make sure all resources associated with the channel will be deallocated at
* an appropriate time.
*
* Returns true if and only if the channel state has been modified from
* CH_CONNECTING or CH_LIVE into CH_DISCONNECTING.
*/
static bool srpt_close_ch(struct srpt_rdma_ch *ch)
{
int ret;
bool was_live;
was_live = srpt_set_ch_state(ch, CH_DISCONNECTING);
if (was_live) {
kref_get(&ch->kref);
ret = srpt_ch_qp_err(ch);
if (ret < 0)
PRINT_ERROR("%s: changing queue pair into error state"
" failed: %d", ch->sess_name, ret);
ret = srpt_zerolength_write(ch);
if (ret < 0) {
PRINT_ERROR("%s: queuing zero-length write failed: %d",
ch->sess_name, ret);
WARN_ON_ONCE(!srpt_set_ch_state(ch, CH_DISCONNECTED));
}
kref_put(&ch->kref, srpt_free_ch);
}
return was_live;
}
static void __srpt_close_all_ch(struct srpt_tgt *srpt_tgt)
{
struct srpt_nexus *nexus;
@@ -2354,7 +2370,8 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
struct ib_cm_id *ib_cm_id,
struct rdma_cm_id *rdma_cm_id,
u8 port_num, __be16 pkey,
const struct srp_login_req *req)
const struct srp_login_req *req,
const char *src_addr)
{
struct srpt_port *const sport = &sdev->port[port_num - 1];
const __be16 *const raw_port_gid = (__be16 *)sport->gid.raw;
@@ -2514,16 +2531,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
}
if (one_target_per_port) {
snprintf(ch->sess_name, sizeof(ch->sess_name),
"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
be16_to_cpu(raw_port_gid[0]),
be16_to_cpu(raw_port_gid[1]),
be16_to_cpu(raw_port_gid[2]),
be16_to_cpu(raw_port_gid[3]),
be16_to_cpu(raw_port_gid[4]),
be16_to_cpu(raw_port_gid[5]),
be16_to_cpu(raw_port_gid[6]),
be16_to_cpu(raw_port_gid[7]));
strlcpy(ch->sess_name, src_addr, sizeof(ch->sess_name));
} else if (use_port_guid_in_session_name) {
/*
* If the kernel module parameter use_port_guid_in_session_name
@@ -2644,10 +2652,20 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
rep_param->ib_cm.initiator_depth = 4;
}
if (ch->using_rdma_cm)
ret = rdma_accept(rdma_cm_id, &rep_param->rdma_cm);
else
ret = ib_send_cm_rep(ib_cm_id, &rep_param->ib_cm);
/*
* Hold the srpt_tgt mutex while accepting a connection to avoid that
* srpt_disconnect_ch() is invoked concurrently with this code.
*/
mutex_lock(&srpt_tgt->mutex);
if (srpt_tgt->enabled && ch->state == CH_CONNECTING) {
if (ch->using_rdma_cm)
ret = rdma_accept(rdma_cm_id, &rep_param->rdma_cm);
else
ret = ib_send_cm_rep(ib_cm_id, &rep_param->ib_cm);
} else {
ret = -EINVAL;
}
mutex_unlock(&srpt_tgt->mutex);
switch (ret) {
case 0:
@@ -2717,9 +2735,36 @@ static int srpt_ib_cm_req_recv(struct ib_cm_id *cm_id,
struct ib_cm_req_event_param *param,
void *private_data)
{
__be16 *const raw_sgid = (__be16 *)param->primary_path->dgid.raw;
char sgid[40];
scnprintf(sgid, sizeof(sgid), "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
be16_to_cpu(raw_sgid[0]), be16_to_cpu(raw_sgid[1]),
be16_to_cpu(raw_sgid[2]), be16_to_cpu(raw_sgid[3]),
be16_to_cpu(raw_sgid[4]), be16_to_cpu(raw_sgid[5]),
be16_to_cpu(raw_sgid[6]), be16_to_cpu(raw_sgid[7]));
return srpt_cm_req_recv(cm_id->context, cm_id, NULL, param->port,
param->primary_path->pkey,
private_data);
private_data, sgid);
}
static const char *inet_ntop(const void *sa, char *dst, unsigned size)
{
switch (((struct sockaddr *)sa)->sa_family) {
case AF_INET:
snprintf(dst, size, "%pI4",
&((struct sockaddr_in *)sa)->sin_addr);
break;
case AF_INET6:
snprintf(dst, size, "%pI6",
&((struct sockaddr_in6 *)sa)->sin6_addr);
break;
default:
snprintf(dst, size, "???");
break;
}
return dst;
}
static int srpt_rdma_cm_req_recv(struct rdma_cm_id *cm_id,
@@ -2728,6 +2773,7 @@ static int srpt_rdma_cm_req_recv(struct rdma_cm_id *cm_id,
struct srpt_device *sdev;
struct srp_login_req req;
const struct srp_login_req_rdma *req_rdma;
char src_addr[40];
sdev = ib_get_client_data(cm_id->device, &srpt_client);
if (!sdev)
@@ -2747,13 +2793,15 @@ static int srpt_rdma_cm_req_recv(struct rdma_cm_id *cm_id,
memcpy(req.initiator_port_id, req_rdma->initiator_port_id, 16);
memcpy(req.target_port_id, req_rdma->target_port_id, 16);
inet_ntop(&cm_id->route.addr.src_addr, src_addr, sizeof(src_addr));
return srpt_cm_req_recv(sdev, NULL, cm_id, cm_id->port_num,
cm_id->route.path_rec->pkey, &req);
cm_id->route.path_rec->pkey, &req, src_addr);
}
static void srpt_cm_rej_recv(struct ib_cm_id *cm_id)
static void srpt_cm_rej_recv(struct srpt_rdma_ch *ch)
{
PRINT_INFO("Received InfiniBand REJ packet for cm_id %p.", cm_id);
PRINT_INFO("Received CM REJ for ch %s.", ch->sess_name);
}
static void srpt_check_timeout(struct srpt_rdma_ch *ch)
@@ -2825,13 +2873,13 @@ static void srpt_cm_rtu_recv(struct srpt_rdma_ch *ch)
static void srpt_cm_timewait_exit(struct srpt_rdma_ch *ch)
{
PRINT_INFO("Received InfiniBand TimeWait exit for ch %p.", ch);
PRINT_INFO("Received CM TimeWait exit for ch %s.", ch->sess_name);
srpt_close_ch(ch);
}
static void srpt_cm_rep_error(struct ib_cm_id *cm_id)
static void srpt_cm_rep_error(struct srpt_rdma_ch *ch)
{
PRINT_INFO("Received InfiniBand REP error for cm_id %p.", cm_id);
PRINT_INFO("Received CM REP error for ch %s.", ch->sess_name);
}
/**
@@ -2848,7 +2896,7 @@ static int srpt_cm_dreq_recv(struct srpt_rdma_ch *ch)
*/
static void srpt_cm_drep_recv(struct srpt_rdma_ch *ch)
{
PRINT_INFO("Received InfiniBand DREP message for ch %p.", ch);
PRINT_INFO("Received CM DREP message for ch %s.", ch->sess_name);
srpt_close_ch(ch);
}
@@ -2864,6 +2912,7 @@ static void srpt_cm_drep_recv(struct srpt_rdma_ch *ch)
*/
static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
{
struct srpt_rdma_ch *ch = cm_id->context;
int ret;
BUG_ON(!cm_id->context);
@@ -2875,29 +2924,29 @@ static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
event->private_data);
break;
case IB_CM_REJ_RECEIVED:
srpt_cm_rej_recv(cm_id);
srpt_cm_rej_recv(ch);
break;
case IB_CM_RTU_RECEIVED:
case IB_CM_USER_ESTABLISHED:
srpt_cm_rtu_recv((struct srpt_rdma_ch *)cm_id->context);
srpt_cm_rtu_recv(ch);
break;
case IB_CM_DREQ_RECEIVED:
ret = srpt_cm_dreq_recv((struct srpt_rdma_ch *)cm_id->context);
ret = srpt_cm_dreq_recv(ch);
break;
case IB_CM_DREP_RECEIVED:
srpt_cm_drep_recv((struct srpt_rdma_ch *)cm_id->context);
srpt_cm_drep_recv(ch);
break;
case IB_CM_TIMEWAIT_EXIT:
srpt_cm_timewait_exit((struct srpt_rdma_ch *)cm_id->context);
srpt_cm_timewait_exit(ch);
break;
case IB_CM_REP_ERROR:
srpt_cm_rep_error(cm_id);
srpt_cm_rep_error(ch);
break;
case IB_CM_DREQ_ERROR:
PRINT_INFO("Received IB DREQ ERROR event.");
PRINT_INFO("Received CM DREQ ERROR event.");
break;
case IB_CM_MRA_RECEIVED:
PRINT_INFO("Received IB MRA event");
PRINT_INFO("Received CM MRA event");
break;
default:
PRINT_ERROR("received unrecognized IB CM event %d",
@@ -2911,23 +2960,32 @@ static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
static int srpt_rdma_cm_handler(struct rdma_cm_id *cm_id,
struct rdma_cm_event *event)
{
struct srpt_rdma_ch *ch = cm_id->context;
int ret = 0;
switch (event->event) {
case RDMA_CM_EVENT_CONNECT_REQUEST:
ret = srpt_rdma_cm_req_recv(cm_id, event);
break;
case RDMA_CM_EVENT_REJECTED:
srpt_cm_rej_recv(ch);
break;
case RDMA_CM_EVENT_ESTABLISHED:
srpt_cm_rtu_recv(cm_id->context);
srpt_cm_rtu_recv(ch);
break;
case RDMA_CM_EVENT_DISCONNECTED:
srpt_cm_dreq_recv(cm_id->context);
if (ch->state < CH_DISCONNECTING)
srpt_cm_dreq_recv(ch);
else
srpt_cm_drep_recv(ch);
break;
case RDMA_CM_EVENT_TIMEWAIT_EXIT:
srpt_cm_timewait_exit(cm_id->context);
srpt_cm_timewait_exit(ch);
break;
case RDMA_CM_EVENT_UNREACHABLE:
srpt_cm_rep_error(ch);
break;
case RDMA_CM_EVENT_DEVICE_REMOVAL:
break;
case RDMA_CM_EVENT_ADDR_CHANGE:
break;
default:
@@ -3579,8 +3637,11 @@ static int srpt_detect(struct scst_tgt_template *tp)
static int srpt_close_session(struct scst_session *sess)
{
struct srpt_rdma_ch *ch = scst_sess_get_tgt_priv(sess);
struct srpt_tgt *srpt_tgt = ch->srpt_tgt;
mutex_lock(&srpt_tgt->mutex);
srpt_disconnect_ch(ch);
mutex_unlock(&srpt_tgt->mutex);
return 0;
}
@@ -4339,7 +4400,8 @@ static void __exit srpt_cleanup_module(void)
{
TRACE_ENTRY();
rdma_destroy_id(rdma_cm_id);
if (rdma_cm_id)
rdma_destroy_id(rdma_cm_id);
ib_unregister_client(&srpt_client);
#ifdef CONFIG_SCST_PROC
srpt_unregister_procfs_entry(&srpt_template);
+16 -6
View File
@@ -41,7 +41,6 @@
#include <rdma/ib_verbs.h>
#include <rdma/ib_sa.h>
#include <rdma/ib_cm.h>
#include <rdma/rdma_cm.h>
#include <scsi/srp.h>
#if defined(INSIDE_KERNEL_TREE)
#include <scst/scst.h>
@@ -49,6 +48,14 @@
#include <linux/version.h>
#include <scst.h>
#endif
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 == 5
#define vlan_dev_vlan_id(dev) (panic("RHEL 5 misses vlan_dev_vlan_id()"),0)
#endif
#if defined(RHEL_MAJOR)
#define __ethtool_get_settings(dev, cmd) (panic("RHEL misses __ethtool_get_settings()"),0)
#endif
#include <linux/rtnetlink.h>
#include <rdma/rdma_cm.h>
#include "ib_dm_mad.h"
/*
@@ -139,7 +146,8 @@ enum {
LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 76)) && \
!(defined(RHEL_MAJOR) && \
(RHEL_MAJOR -0 > 6 || \
RHEL_MAJOR -0 == 6 && RHEL_MINOR -0 >= 5))
RHEL_MAJOR -0 == 6 && RHEL_MINOR -0 >= 5 || \
RHEL_MAJOR -0 == 5 && RHEL_MINOR -0 >= 9))
/* See also patch "IB/core: Add GID change event" (commit 761d90ed4). */
enum { IB_EVENT_GID_CHANGE = 18 };
#endif
@@ -284,15 +292,17 @@ struct srpt_send_ioctx {
* enum rdma_ch_state - SRP channel state.
* @CH_CONNECTING: QP is in RTR state; waiting for RTU.
* @CH_LIVE: QP is in RTS state.
* @CH_DISCONNECTING: DREQ has been received and waiting for DREP or DREQ has
* been sent and waiting for DREP or channel is being closed
* for another reason.
* @CH_DISCONNECTED: Last WQE has been received.
* @CH_DISCONNECTING: DREQ has been sent and waiting for DREP or DREQ has
* been received.
* @CH_DRAINING: DREP has been received or waiting for DREP timed out
* and last work request has been queued.
* @CH_DISCONNECTED: Last completion has been received.
*/
enum rdma_ch_state {
CH_CONNECTING,
CH_LIVE,
CH_DISCONNECTING,
CH_DRAINING,
CH_DISCONNECTED,
};
+5 -3
View File
@@ -383,9 +383,11 @@ int start(int argc, char **argv)
desc.opt.on_free_cmd_type = on_free_cmd_type;
desc.opt.memory_reuse_type = memory_reuse_type;
desc.opt.tst = SCST_CONTR_MODE_SEP_TASK_SETS;
desc.opt.queue_alg = SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER;
desc.opt.d_sense = SCST_CONTR_MODE_FIXED_SENSE;
desc.opt.tst = SCST_TST_1_SEP_TASK_SETS;
desc.opt.tmf_only = 0;
desc.opt.queue_alg = SCST_QUEUE_ALG_1_UNRESTRICTED_REORDER;
desc.opt.qerr = SCST_QERR_0_ALL_RESUME;
desc.opt.d_sense = SCST_D_SENSE_0_FIXED_SENSE;
res = ioctl(devs[i].scst_usr_fd, SCST_USER_REGISTER_DEVICE, &desc);
if (res != 0) {