Merged revisions 6693-6701 via svnmerge from

svn://svn.code.sf.net/p/scst/svn/trunk

........
  r6693 | vlnb | 2015-11-17 19:59:30 -0800 (Tue, 17 Nov 2015) | 5 lines
  
  scst: Add user space control for suspend/resume activities
  
  Useful to speed up mass management
........
  r6694 | vlnb | 2015-11-17 20:09:50 -0800 (Tue, 17 Nov 2015) | 6 lines
  
  scst: Rework Copy Manager's sysfs interface
  
  The old version had management incompatible with scstadmin and had
  issues with LUNs management.
........
  r6695 | bvassche | 2015-11-18 11:36:01 -0800 (Wed, 18 Nov 2015) | 8 lines
  
  scst: Make it easier to build without DLM support
  
  With this change all that is required to build without DLM support
  is to add the following in scst_priv.h:
  
  #undef CONFIG_DLM
  #undef CONFIG_DLM_MODULE
........
  r6696 | bvassche | 2015-11-18 14:10:03 -0800 (Wed, 18 Nov 2015) | 2 lines
  
  scst_pres: Suppress a compiler warning when building against a kernel with no DLM support
........
  r6697 | bvassche | 2015-11-18 14:10:33 -0800 (Wed, 18 Nov 2015) | 1 line
  
  scst_vdisk: Kernel v4.4 build fix
........
  r6698 | bvassche | 2015-11-18 14:10:54 -0800 (Wed, 18 Nov 2015) | 1 line
  
  ib_srpt: Kernel v4.4 build fix
........
  r6699 | bvassche | 2015-11-18 14:11:37 -0800 (Wed, 18 Nov 2015) | 1 line
  
  isert-scst: Port to Linux kernel v4.4
........
  r6700 | bvassche | 2015-11-18 14:44:29 -0800 (Wed, 18 Nov 2015) | 1 line
  
  scst: Do not build cluster PR support if CONFIG_SCST_NO_DLM has been set
........
  r6701 | vlnb | 2015-11-18 21:20:43 -0800 (Wed, 18 Nov 2015) | 3 lines
  
  scst: fix explicit ALUA disabled DIF type 2 handling
........


git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.1.x@6702 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2015-11-19 05:21:59 +00:00
parent 7a043f2618
commit e35e79706e
17 changed files with 453 additions and 249 deletions
+4
View File
@@ -98,7 +98,11 @@ struct isert_wr {
struct ib_sge *sge_list;
union {
struct ib_recv_wr recv_wr;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
struct ib_send_wr send_wr;
#else
struct ib_rdma_wr send_wr;
#endif
};
} ____cacheline_aligned;
+19
View File
@@ -238,9 +238,14 @@ int isert_wr_init(struct isert_wr *wr,
buff_offset = -EFAULT;
goto out;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
wr->send_wr.wr.rdma.remote_addr = pdu->rem_write_va +
buff_offset;
wr->send_wr.wr.rdma.rkey = pdu->rem_write_stag;
#else
wr->send_wr.remote_addr = pdu->rem_write_va + buff_offset;
wr->send_wr.rkey = pdu->rem_write_stag;
#endif
break;
case ISER_WR_RDMA_WRITE:
send_wr_op = IB_WR_RDMA_WRITE;
@@ -250,9 +255,14 @@ int isert_wr_init(struct isert_wr *wr,
buff_offset = -EFAULT;
goto out;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
wr->send_wr.wr.rdma.remote_addr = pdu->rem_read_va +
buff_offset;
wr->send_wr.wr.rdma.rkey = pdu->rem_read_stag;
#else
wr->send_wr.remote_addr = pdu->rem_read_va + buff_offset;
wr->send_wr.rkey = pdu->rem_read_stag;
#endif
break;
default:
BUG();
@@ -278,12 +288,21 @@ int isert_wr_init(struct isert_wr *wr,
wr->recv_wr.sg_list = wr->sge_list;
wr->recv_wr.num_sge = sg_cnt;
} else {
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
wr->send_wr.next = NULL;
wr->send_wr.wr_id = _ptr_to_u64(wr);
wr->send_wr.sg_list = wr->sge_list;
wr->send_wr.num_sge = sg_cnt;
wr->send_wr.opcode = send_wr_op;
wr->send_wr.send_flags = send_flags;
#else
wr->send_wr.wr.next = NULL;
wr->send_wr.wr.wr_id = _ptr_to_u64(wr);
wr->send_wr.wr.sg_list = wr->sge_list;
wr->send_wr.wr.num_sge = sg_cnt;
wr->send_wr.wr.opcode = send_wr_op;
wr->send_wr.wr.send_flags = send_flags;
#endif
}
out:
+23
View File
@@ -214,7 +214,11 @@ out:
static inline void isert_link_send_wrs(struct isert_wr *from_wr,
struct isert_wr *to_wr)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
from_wr->send_wr.next = &to_wr->send_wr;
#else
from_wr->send_wr.wr.next = &to_wr->send_wr.wr;
#endif
}
static inline void isert_link_send_pdu_wrs(struct isert_cmnd *from_pdu,
@@ -222,7 +226,11 @@ static inline void isert_link_send_pdu_wrs(struct isert_cmnd *from_pdu,
int wr_cnt)
{
isert_link_send_wrs(&from_pdu->wr[wr_cnt - 1], &to_pdu->wr[0]);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
to_pdu->wr[0].send_wr.next = NULL;
#else
to_pdu->wr[0].send_wr.wr.next = NULL;
#endif
}
int isert_prepare_rdma(struct isert_cmnd *isert_pdu,
@@ -281,8 +289,14 @@ int isert_prepare_rdma(struct isert_cmnd *isert_pdu,
isert_link_send_wrs(&isert_pdu->wr[i - 1], &isert_pdu->wr[i]);
if (op == ISER_WR_RDMA_READ) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
isert_pdu->wr[wr_cnt - 1].send_wr.send_flags = IB_SEND_SIGNALED;
isert_pdu->wr[wr_cnt - 1].send_wr.next = NULL;
#else
isert_pdu->wr[wr_cnt - 1].send_wr.wr.send_flags =
IB_SEND_SIGNALED;
isert_pdu->wr[wr_cnt - 1].send_wr.wr.next = NULL;
#endif
}
out:
@@ -574,7 +588,11 @@ int isert_pdu_send(struct isert_connection *isert_conn,
#endif
wr = &tx_pdu->wr[0];
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
wr->send_wr.num_sge = isert_pdu_prepare_send(isert_conn, tx_pdu);
#else
wr->send_wr.wr.num_sge = isert_pdu_prepare_send(isert_conn, tx_pdu);
#endif
err = isert_post_send(isert_conn, wr, 1);
if (unlikely(err)) {
@@ -595,8 +613,13 @@ int isert_pdu_post_rdma_write(struct isert_connection *isert_conn,
TRACE_ENTRY();
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
isert_rsp->wr[0].send_wr.num_sge = isert_pdu_prepare_send(isert_conn,
isert_rsp);
#else
isert_rsp->wr[0].send_wr.wr.num_sge = isert_pdu_prepare_send(isert_conn,
isert_rsp);
#endif
isert_link_send_pdu_wrs(isert_cmd, isert_rsp, wr_cnt);
err = isert_post_send(isert_conn, &isert_cmd->wr[0], wr_cnt + 1);
if (unlikely(err)) {
+27 -4
View File
@@ -103,7 +103,11 @@ int isert_post_send(struct isert_connection *isert_conn,
struct isert_wr *first_wr,
int num_wr)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
struct ib_send_wr *first_ib_wr = &first_wr->send_wr;
#else
struct ib_send_wr *first_ib_wr = &first_wr->send_wr.wr;
#endif
struct ib_send_wr *bad_wr;
int num_posted;
int err;
@@ -131,9 +135,19 @@ void isert_post_drain(struct isert_connection *isert_conn)
isert_wr_set_fields(&isert_conn->drain_wr, isert_conn, NULL);
isert_conn->drain_wr.wr_op = ISER_WR_SEND;
isert_conn->drain_wr.send_wr.wr_id = _ptr_to_u64(&isert_conn->drain_wr);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
isert_conn->drain_wr.send_wr.wr_id =
_ptr_to_u64(&isert_conn->drain_wr);
isert_conn->drain_wr.send_wr.opcode = IB_WR_SEND;
err = ib_post_send(isert_conn->qp, &isert_conn->drain_wr.send_wr, &bad_wr);
err = ib_post_send(isert_conn->qp,
&isert_conn->drain_wr.send_wr, &bad_wr);
#else
isert_conn->drain_wr.send_wr.wr.wr_id =
_ptr_to_u64(&isert_conn->drain_wr);
isert_conn->drain_wr.send_wr.wr.opcode = IB_WR_SEND;
err = ib_post_send(isert_conn->qp,
&isert_conn->drain_wr.send_wr.wr, &bad_wr);
#endif
if (unlikely(err)) {
pr_err("Failed to post drain wr, err:%d\n", err);
/*
@@ -601,6 +615,7 @@ static void isert_handle_wc_error(struct ib_wc *wc)
struct isert_buf *isert_buf = wr->buf;
struct isert_device *isert_dev = wr->isert_dev;
struct ib_device *ib_dev = isert_dev->ib_dev;
u32 num_sge;
TRACE_ENTRY();
@@ -615,7 +630,12 @@ static void isert_handle_wc_error(struct ib_wc *wc)
switch (wr->wr_op) {
case ISER_WR_SEND:
if (unlikely(wr->send_wr.num_sge == 0)) /* Drain WR */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
num_sge = wr->send_wr.num_sge;
#else
num_sge = wr->send_wr.wr.num_sge;
#endif
if (unlikely(num_sge == 0)) /* Drain WR */
isert_sched_conn_drained(isert_conn);
else
isert_pdu_err(&isert_pdu->iscsi);
@@ -1648,9 +1668,12 @@ struct isert_portal *isert_portal_create(void)
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0) && \
(!defined(RHEL_MAJOR) || RHEL_MAJOR -0 <= 5)
cm_id = rdma_create_id(isert_cm_evt_handler, portal, RDMA_PS_TCP);
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
cm_id = rdma_create_id(isert_cm_evt_handler, portal, RDMA_PS_TCP,
IB_QPT_RC);
#else
cm_id = rdma_create_id(&init_net, isert_cm_evt_handler, portal,
RDMA_PS_TCP, IB_QPT_RC);
#endif
if (unlikely(IS_ERR(cm_id))) {
err = PTR_ERR(cm_id);
+21 -17
View File
@@ -441,6 +441,19 @@ following entries:
have different IDs and SNs. For instance, VDISK dev handler uses this
ID to generate T10 vendor specific identifier and SN of the devices.
- suspend - globally suspends or releases all SCSI activities on all
devices. Useful for mass management, like adding or deleting LUNs.
Writing to it value v:
* v > 0 - suspends activities, but waits no more, than v seconds
* v = 0 - suspends activities, waits indefinitely
* V < 0 - releases activities.
Reading from this attribute returns number of previous suspend
requests.
- threads - allows to read and set number of global SCST I/O threads.
Those threads used with async. dev handlers, for instance, vdisk
BLOCKIO or NULLIO.
@@ -1846,34 +1859,25 @@ EXTENDED COPY
~~~~~~~~~~~~~
SCST implements EXTENDED COPY via internal Copy Manager target. This
target has the following specific attributes in its sysfs:
target has the following specific attribute in its sysfs:
- allow_not_connected_copy - if not set (default), an initiator can
perform copy only between devices it has direct access to via any
target/session. If set, any initiator can copy between any devices in
the system.
- mgmt - this attribute allows to control data from which devices can
be copied using Copy Manager. By default, devices belonging to dev
handlers with flag auto_cm_assignment_possible set are auto assigned to
the Copy Manager on the registration. Currently, only vdisk has this
flag set, so all other devices (pass-through, user space, etc.) should
be assigned to the Copy Manager manually.
Mgmt attribute supports the following commands:
- add [vname|H:C:I:L] - adds device with name vname or H:C:I:L numbers
(pass-through) to the Copy Manager.
- del [vname|H:C:I:L] - deletes device with name vname or H:C:I:L numbers
(pass-through) from the Copy Manager.
The Copy Manager has access only to those devices, for which it has LUNs
in /sys/kernel/scst_tgt/targets/copy_manager/copy_manager_tgt/luns/.
Devices from scst_vdisk dev handler added to it automatically upon
registration, but for other devices you need to manually add LUNs there
the same way as for any target driver. You can also delete any device at
any time from the Copy Manager visibility by deleting the corresponding
LUN from the sysfs. It might be useful during ALUA state switching.
Internally SCST implements EXTENDED COPY as generation of sets of
internal READ(16) and WRITE(16) SCSI commands. Dev handlers don't need
any manual actions to use it.
Also SCST provides for dev handlers possibility to remap blocks instead
of copy them, if they support this feature. It allows them to perform
EXTENDED COPY command much faster by just metadata update of their
+21 -17
View File
@@ -305,6 +305,19 @@ following entries:
have different IDs and SNs. For instance, VDISK dev handler uses this
ID to generate T10 vendor specific identifier and SN of the devices.
- suspend - globally suspends or releases all SCSI activities on all
devices. Useful for mass management, like adding or deleting LUNs.
Writing to it value v:
* v > 0 - suspends activities, but waits no more, than v seconds
* v = 0 - suspends activities, waits indefinitely
* V < 0 - releases activities.
Reading from this attribute returns number of previous suspend
requests.
- threads - allows to read and set number of global SCST I/O threads.
Those threads used with async. dev handlers, for instance, vdisk
BLOCKIO or NULLIO.
@@ -1699,34 +1712,25 @@ EXTENDED COPY
~~~~~~~~~~~~~
SCST implements EXTENDED COPY via internal Copy Manager target. This
target has the following specific attributes in its sysfs:
target has the following specific attribute in its sysfs:
- allow_not_connected_copy - if not set (default), an initiator can
perform copy only between devices it has direct access to via any
target/session. If set, any initiator can copy between any devices in
the system.
- mgmt - this attribute allows to control data from which devices can
be copied using Copy Manager. By default, devices belonging to dev
handlers with flag auto_cm_assignment_possible set are auto assigned to
the Copy Manager on the registration. Currently, only vdisk has this
flag set, so all other devices (pass-through, user space, etc.) should
be assigned to the Copy Manager manually.
Mgmt attribute supports the following commands:
- add [vname|H:C:I:L] - adds device with name vname or H:C:I:L numbers
(pass-through) to the Copy Manager.
- del [vname|H:C:I:L] - deletes device with name vname or H:C:I:L numbers
(pass-through) from the Copy Manager.
The Copy Manager has access only to those devices, for which it has LUNs
in /sys/kernel/scst_tgt/targets/copy_manager/copy_manager_tgt/luns/.
Devices from scst_vdisk dev handler added to it automatically upon
registration, but for other devices you need to manually add LUNs there
the same way as for any target driver. You can also delete any device at
any time from the Copy Manager visibility by deleting the corresponding
LUN from the sysfs. It might be useful during ALUA state switching.
Internally SCST implements EXTENDED COPY as generation of sets of
internal READ(16) and WRITE(16) SCSI commands. Dev handlers don't need
any manual actions to use it.
Also SCST provides for dev handlers possibility to remap blocks instead
of copy them, if they support this feature. It allows them to perform
EXTENDED COPY command much faster by just metadata update of their
+2 -6
View File
@@ -49,12 +49,7 @@ scst-y += scst_mem.o
scst-y += scst_debug.o
scst-y += scst_pres.o
scst-y += scst_no_dlm.o
ifdef CONFIG_DLM
scst-y += scst_dlm.o
endif
ifdef CONFIG_DLM_MODULE
scst-y += scst_dlm.o
endif
scst-y += scst_tg.o
scst-y += scst_event.o
scst-y += scst_copy_mgr.o
@@ -160,7 +155,8 @@ INSTALL_DIR_H := $(DESTDIR)$(PREFIX)/include/scst
enable-Wextra = $(shell uname_r="$$(uname -r)"; if [ "$${uname_r%.el5}" = "$${uname_r}" ]; then echo "$(1)"; fi)
EXTRA_CFLAGS += -I$(SCST_INC_DIR) $(call enable-Wextra,-Wextra \
-Wno-unused-parameter -Wno-missing-field-initializers)
-Wno-unused-parameter -Wno-missing-field-initializers) \
$(shell [ -n "${CONFIG_SCST_NO_DLM}" ] && echo -DCONFIG_SCST_NO_DLM)
#EXTRA_CFLAGS += -DCONFIG_SCST_STRICT_SERIALIZING
+13 -6
View File
@@ -1407,6 +1407,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
struct inode *inode;
struct file *fd;
struct blk_integrity *bi;
const char *bi_profile_name;
TRACE_ENTRY();
@@ -1430,9 +1431,14 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
goto out_no_bi;
}
TRACE_DBG("BI name %s", bi->name);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
bi_profile_name = bi->name;
#else
bi_profile_name = bi->profile->name;
#endif
TRACE_DBG("BI name %s", bi_profile_name);
if (!strcmp(bi->name, "T10-DIF-TYPE1-CRC")) {
if (!strcmp(bi_profile_name, "T10-DIF-TYPE1-CRC")) {
dev->dev_dif_ip_not_supported = 1;
if (virt_dev->dif_type != 1) {
PRINT_ERROR("Integrity type mismatch, %d expected, "
@@ -1441,7 +1447,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
res = -EINVAL;
goto out_close;
}
} else if (!strcmp(bi->name, "T10-DIF-TYPE1-IP")) {
} else if (!strcmp(bi_profile_name, "T10-DIF-TYPE1-IP")) {
if (virt_dev->dif_type != 1) {
PRINT_ERROR("Integrity type mismatch, %d expected, "
"but block device has 1 (dev %s)",
@@ -1449,7 +1455,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
res = -EINVAL;
goto out_close;
}
} else if (!strcmp(bi->name, "T10-DIF-TYPE3-CRC")) {
} else if (!strcmp(bi_profile_name, "T10-DIF-TYPE3-CRC")) {
dev->dev_dif_ip_not_supported = 1;
if (virt_dev->dif_type != 3) {
PRINT_ERROR("Integrity type mismatch, %d expected, "
@@ -1458,7 +1464,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
res = -EINVAL;
goto out_close;
}
} else if (!strcmp(bi->name, "T10-DIF-TYPE3-IP")) {
} else if (!strcmp(bi_profile_name, "T10-DIF-TYPE3-IP")) {
if (virt_dev->dif_type != 3) {
PRINT_ERROR("Integrity type mismatch, %d expected, "
"but block device has 3 (dev %s)",
@@ -1468,7 +1474,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev)
}
} else {
PRINT_ERROR("Unable to understand integrity name %s"
"(dev %s)", bi->name, dev->virt_name);
"(dev %s)", bi_profile_name, dev->virt_name);
res = -EINVAL;
goto out_close;
}
@@ -2790,6 +2796,7 @@ static const struct scst_opcode_descriptor *vdisk_opcode_descriptors_type2[] = {
&scst_op_descr_write_verify32,
&scst_op_descr_write_same32,
SCST_OPCODE_DESCRIPTORS
&scst_op_descr_stpg, /* must be last, see vdisk_get_supported_opcodes()! */
};
static const struct scst_opcode_descriptor *vcdrom_opcode_descriptors[] = {
+115 -158
View File
@@ -2519,14 +2519,16 @@ static bool scst_cm_is_lun_free(unsigned int lun)
}
/* scst_mutex supposed to be held and activities suspended */
static int scst_cm_dev_register(struct scst_device *dev)
static int scst_cm_dev_register(struct scst_device *dev, uint64_t lun)
{
int res, i;
unsigned int lun;
struct scst_acg_dev *acg_dev;
bool add_lun;
TRACE_ENTRY();
TRACE_DBG("dev %s, LUN %ld", dev->virt_name, (unsigned long)lun);
for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) {
struct scst_tgt_dev *tgt_dev;
struct list_head *head = &scst_cm_sess->sess_tgt_dev_list[i];
@@ -2541,18 +2543,25 @@ static int scst_cm_dev_register(struct scst_device *dev)
}
}
while (1) {
lun = scst_cm_next_lun++;
if (lun == SCST_MAX_LUN)
continue;
if (scst_cm_is_lun_free(lun))
break;
};
if (lun == SCST_MAX_LUN) {
add_lun = true;
while (1) {
lun = scst_cm_next_lun++;
if (lun == SCST_MAX_LUN)
continue;
if (scst_cm_is_lun_free(lun))
break;
}
} else
add_lun = false;
res = scst_acg_add_lun(scst_cm_tgt->default_acg,
scst_cm_tgt->tgt_luns_kobj, dev, lun, false, false, &acg_dev);
if (res != 0)
goto out_err;
if (add_lun) {
res = scst_acg_add_lun(scst_cm_tgt->default_acg,
scst_cm_tgt->tgt_luns_kobj, dev, lun, SCST_ADD_LUN_CM,
&acg_dev);
if (res != 0)
goto out_err;
}
spin_lock_bh(&dev->dev_lock);
scst_block_dev(dev);
@@ -2578,13 +2587,15 @@ out_err:
}
/* scst_mutex supposed to be held and activities suspended */
static void scst_cm_dev_unregister(struct scst_device *dev)
static void scst_cm_dev_unregister(struct scst_device *dev, bool del_lun)
{
int i;
struct scst_cm_desig *des, *t;
TRACE_ENTRY();
TRACE_DBG("dev %s, del_lun %d", dev->virt_name, del_lun);
list_for_each_entry_safe(des, t, &scst_cm_desig_list, cm_desig_list_entry) {
if (des->desig_tgt_dev->dev == dev) {
TRACE_DBG("Deleting des %p", des);
@@ -2593,6 +2604,9 @@ static void scst_cm_dev_unregister(struct scst_device *dev)
}
}
if (!del_lun)
goto out;
for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) {
struct scst_tgt_dev *tgt_dev;
struct list_head *head = &scst_cm_sess->sess_tgt_dev_list[i];
@@ -2606,6 +2620,7 @@ static void scst_cm_dev_unregister(struct scst_device *dev)
}
}
out:
TRACE_EXIT();
return;
}
@@ -2620,7 +2635,7 @@ int scst_cm_on_dev_register(struct scst_device *dev)
if (!dev->handler->auto_cm_assignment_possible)
goto out;
res = scst_cm_dev_register(dev);
res = scst_cm_dev_register(dev, SCST_MAX_LUN);
out:
TRACE_EXIT_RES(res);
@@ -2632,12 +2647,87 @@ void scst_cm_on_dev_unregister(struct scst_device *dev)
{
TRACE_ENTRY();
scst_cm_dev_unregister(dev);
scst_cm_dev_unregister(dev, true);
TRACE_EXIT();
return;
}
/* scst_mutex supposed to be held and activities suspended */
int scst_cm_on_add_acg(struct scst_acg *acg)
{
int res = 0;
TRACE_ENTRY();
if (scst_cm_tgt == NULL)
goto out;
if (acg->tgt != scst_cm_tgt)
goto out;
if (acg != scst_cm_tgt->default_acg) {
PRINT_ERROR("Copy Manager does not support security groups");
res = -EINVAL;
goto out;
}
out:
TRACE_EXIT_RES(res);
return res;
}
/* scst_mutex supposed to be held and activities suspended */
void scst_cm_on_del_acg(struct scst_acg *acg)
{
/* Nothing to do */
}
/* scst_mutex supposed to be held and activities suspended */
int scst_cm_on_add_lun(struct scst_acg_dev *acg_dev, uint64_t lun,
unsigned int *flags)
{
int res = 0;
TRACE_ENTRY();
if (acg_dev->acg != scst_cm_tgt->default_acg)
goto out;
if (acg_dev->acg_dev_rd_only || acg_dev->dev->dev_rd_only) {
PRINT_ERROR("Copy Manager does not support read only devices");
res = -EINVAL;
goto out;
}
*flags &= ~SCST_ADD_LUN_GEN_UA;
res = scst_cm_dev_register(acg_dev->dev, lun);
out:
TRACE_EXIT_RES(res);
return res;
}
/* scst_mutex supposed to be held and activities suspended */
bool scst_cm_on_del_lun(struct scst_acg_dev *acg_dev, bool gen_report_luns_changed)
{
bool res = gen_report_luns_changed;
TRACE_ENTRY();
if (acg_dev->acg != scst_cm_tgt->default_acg)
goto out;
scst_cm_dev_unregister(acg_dev->dev, false);
res = false;
out:
TRACE_EXIT_RES(res);
return res;
}
/* scst_mutex supposed to be locked */
static bool scst_cm_check_access_acg(const char *initiator_name,
const struct scst_device *dev, const struct scst_acg *acg,
@@ -3480,148 +3570,8 @@ static struct kobj_attribute scst_cm_allow_not_conn_copy_attr =
scst_cm_allow_not_conn_copy_show,
scst_cm_allow_not_conn_copy_store);
static ssize_t scst_cm_mgmt_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
static const char help[] =
"Usage: echo \"add H:C:I:L\" >mgmt\n"
" echo \"add VNAME\" >mgmt\n"
" echo \"del H:C:I:L\" >mgmt\n"
" echo \"del VNAME\" >mgmt\n";
return sprintf(buf, "%s", help);
}
static int scst_cm_mgmt(struct scst_sysfs_work_item *work)
{
int res = 0;
char *pp, *action, *devstr;
unsigned int host, channel, id, lun;
char *buf = work->buf;
bool vdev;
struct scst_device *d, *dev = NULL;
TRACE_ENTRY();
TRACE_DBG("buffer %s", buf);
pp = buf;
action = scst_get_next_lexem(&pp);
devstr = scst_get_next_lexem(&pp);
if (*devstr == '\0') {
PRINT_ERROR("%s", "Device required");
res = -EINVAL;
goto out;
}
if (*scst_get_next_lexem(&pp) != '\0') {
PRINT_ERROR("%s", "Too many parameters");
res = -EINVAL;
goto out_syntax_err;
}
if (sscanf(devstr, "%u:%u:%u:%u", &host, &channel, &id, &lun) != 4) {
vdev = true;
TRACE_DBG("Virt dev %s", devstr);
} else {
vdev = false;
TRACE_DBG("Pass-through dev %d:%d:%d:%d", host, channel, id, lun);
}
res = scst_suspend_activity(SCST_SUSPEND_TIMEOUT_USER);
if (res != 0)
goto out;
res = mutex_lock_interruptible(&scst_mutex);
if (res != 0)
goto out_resume;
list_for_each_entry(d, &scst_dev_list, dev_list_entry) {
if (vdev) {
if ((d->scsi_dev == NULL) &&
(strcmp(d->virt_name, devstr) == 0)) {
dev = d;
break;
}
} else if (d->scsi_dev != NULL &&
d->scsi_dev->host->host_no == host &&
d->scsi_dev->channel == channel &&
d->scsi_dev->id == id &&
d->scsi_dev->lun == lun) {
dev = d;
break;
}
}
if (dev == NULL) {
PRINT_ERROR("Device %s not found", devstr);
res = -EINVAL;
goto out_unlock;
} else
TRACE_DBG("Dev %p (%s) found", dev, dev->virt_name);
if (strcasecmp("add", action) == 0)
res = scst_cm_dev_register(dev);
else if (strcasecmp("del", action) == 0)
scst_cm_dev_unregister(dev);
else {
PRINT_ERROR("Action %s not understood", action);
res = -EINVAL;
}
out_unlock:
mutex_unlock(&scst_mutex);
out_resume:
scst_resume_activity();
out:
TRACE_EXIT_RES(res);
return res;
out_syntax_err:
PRINT_ERROR("Syntax error on \"%s\"", buf);
res = -EINVAL;
goto out;
}
static ssize_t scst_cm_mgmt_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buffer, size_t size)
{
int res;
struct scst_sysfs_work_item *work;
char *i_buf;
TRACE_ENTRY();
i_buf = kasprintf(GFP_KERNEL, "%.*s", (int)size, buffer);
if (i_buf == NULL) {
PRINT_ERROR("Unable to alloc intermediate buffer with size %zd",
size+1);
res = -ENOMEM;
goto out;
}
res = scst_alloc_sysfs_work(scst_cm_mgmt, false, &work);
if (res != 0)
goto out;
work->buf = i_buf;
res = scst_sysfs_queue_wait_work(work);
if (res == 0)
res = size;
out:
TRACE_EXIT_RES(res);
return res;
}
static struct kobj_attribute scst_cm_mgmt_attr =
__ATTR(mgmt, S_IRUGO|S_IWUSR, scst_cm_mgmt_show, scst_cm_mgmt_store);
static const struct attribute *scst_cm_attrs[] = {
static const struct attribute *scst_cm_tgtt_attrs[] = {
&scst_cm_allow_not_conn_copy_attr.attr,
&scst_cm_mgmt_attr.attr,
NULL,
};
@@ -3693,6 +3643,12 @@ static void scst_cm_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd)
return;
}
static int scst_cm_report_aen(struct scst_aen *aen)
{
/* Nothing to do */
return 0;
}
static struct scst_tgt_template scst_cm_tgtt = {
.name = SCST_CM_NAME,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
@@ -3710,9 +3666,10 @@ static struct scst_tgt_template scst_cm_tgtt = {
.release = scst_cm_release,
.xmit_response = scst_cm_xmit_response,
.task_mgmt_fn_done = scst_cm_task_mgmt_fn_done,
.report_aen = scst_cm_report_aen,
.get_initiator_port_transport_id = scst_cm_get_initiator_port_transport_id,
#ifndef CONFIG_SCST_PROC
.tgtt_attrs = scst_cm_attrs,
.tgtt_attrs = scst_cm_tgtt_attrs,
#endif
};
+5
View File
@@ -30,6 +30,9 @@
#include "scst_pres.h"
#include "scst_dlm.h"
#if (defined(CONFIG_DLM) || defined(CONFIG_DLM_MODULE)) && \
!defined(CONFIG_SCST_NO_DLM)
static void scst_pr_dlm_cleanup(struct scst_device *dev);
static void scst_dlm_pre_bast(void *bastarg, int mode);
static void scst_dlm_post_bast(void *bastarg, int mode);
@@ -1493,3 +1496,5 @@ const struct scst_cl_ops scst_dlm_cl_ops = {
.is_not_rsv_holder = scst_dlm_is_not_rsv_holder,
.reserve = scst_dlm_reserve,
};
#endif
+43 -17
View File
@@ -4373,8 +4373,8 @@ out:
/* The activity supposed to be suspended and scst_mutex held */
int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
struct scst_device *dev, uint64_t lun, int read_only,
bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev)
struct scst_device *dev, uint64_t lun, unsigned int flags,
struct scst_acg_dev **out_acg_dev)
{
int res;
struct scst_acg_dev *acg_dev;
@@ -4395,7 +4395,7 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
res = -ENOMEM;
goto out;
}
acg_dev->acg_dev_rd_only = read_only;
acg_dev->acg_dev_rd_only = ((flags & SCST_ADD_LUN_READ_ONLY) != 0);
if (dev->dev_dif_mode & SCST_DIF_MODE_DEV_STORE) {
/* Devices are allowed to store only CRCs */
acg_dev->acg_dev_dif_guard_format = SCST_DIF_GUARD_FORMAT_CRC;
@@ -4410,6 +4410,12 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
list_add_tail(&acg_dev->acg_dev_list_entry, &acg->acg_dev_list);
list_add_tail(&acg_dev->dev_acg_dev_list_entry, &dev->dev_acg_dev_list);
if (!(flags & SCST_ADD_LUN_CM)) {
res = scst_cm_on_add_lun(acg_dev, lun, &flags);
if (res != 0)
goto out_free;
}
list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
if (res == -EPERM)
@@ -4423,14 +4429,14 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
res = scst_acg_dev_sysfs_create(acg_dev, parent);
if (res != 0)
goto out_free;
goto out_on_del;
if (gen_scst_report_luns_changed)
if (flags & SCST_ADD_LUN_GEN_UA)
scst_report_luns_changed(acg);
PRINT_INFO("Added device %s to group %s (LUN %lld, "
"rd_only %d) to target %s", dev->virt_name, acg->acg_name,
lun, read_only, acg->tgt ? acg->tgt->tgt_name : "?");
"flags 0x%x) to target %s", dev->virt_name, acg->acg_name,
lun, flags, acg->tgt ? acg->tgt->tgt_name : "?");
if (out_acg_dev != NULL)
*out_acg_dev = acg_dev;
@@ -4439,6 +4445,10 @@ out:
TRACE_EXIT_RES(res);
return res;
out_on_del:
if (!(flags & SCST_ADD_LUN_CM))
scst_cm_on_del_lun(acg_dev, false);
out_free:
list_for_each_entry_safe(tgt_dev, tt, &tmp_tgt_dev_list,
extra_tgt_dev_list_entry) {
@@ -4450,7 +4460,7 @@ out_free:
/* The activity supposed to be suspended and scst_mutex held */
int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
bool gen_scst_report_luns_changed)
bool gen_report_luns_changed)
{
int res = 0;
struct scst_acg_dev *acg_dev = NULL, *a;
@@ -4470,6 +4480,8 @@ int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
goto out;
}
gen_report_luns_changed = scst_cm_on_del_lun(acg_dev, gen_report_luns_changed);
list_for_each_entry_safe(tgt_dev, tt, &acg_dev->dev->dev_tgt_dev_list,
dev_tgt_dev_list_entry) {
if (tgt_dev->acg_dev == acg_dev)
@@ -4478,7 +4490,7 @@ int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
scst_del_free_acg_dev(acg_dev, true);
if (gen_scst_report_luns_changed)
if (gen_report_luns_changed)
scst_report_luns_changed(acg);
PRINT_INFO("Removed LUN %lld from group %s (target %s)",
@@ -4490,16 +4502,18 @@ out:
}
/* The activity supposed to be suspended and scst_mutex held */
struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
const char *acg_name, bool tgt_acg)
int scst_alloc_add_acg(struct scst_tgt *tgt, const char *acg_name,
bool tgt_acg, struct scst_acg **out_acg)
{
struct scst_acg *acg;
int res;
TRACE_ENTRY();
acg = kzalloc(sizeof(*acg), GFP_KERNEL);
if (acg == NULL) {
PRINT_ERROR("%s", "Allocation of acg failed");
res = -ENOMEM;
goto out;
}
@@ -4512,9 +4526,14 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
acg->acg_name = kstrdup(acg_name, GFP_KERNEL);
if (acg->acg_name == NULL) {
PRINT_ERROR("%s", "Allocation of acg_name failed");
res = -ENOMEM;
goto out_free;
}
res = scst_cm_on_add_acg(acg);
if (res != 0)
goto out_undup;
#ifdef CONFIG_SCST_PROC
acg->addr_method = tgt && tgt->tgtt ? tgt->tgtt->preferred_addr_method
: SCST_LUN_ADDR_METHOD_PERIPHERAL;
@@ -4527,30 +4546,35 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
acg->addr_method = tgt->tgtt->preferred_addr_method;
if (tgt_acg) {
int rc;
TRACE_DBG("Adding acg '%s' to device '%s' acg_list", acg_name,
tgt->tgt_name);
list_add_tail(&acg->acg_list_entry, &tgt->tgt_acg_list);
acg->tgt_acg = 1;
rc = scst_acg_sysfs_create(tgt, acg);
if (rc != 0)
res = scst_acg_sysfs_create(tgt, acg);
if (res != 0)
goto out_del;
}
kobject_get(&tgt->tgt_kobj);
#endif
res = 0;
out:
TRACE_EXIT_HRES(acg);
return acg;
*out_acg = acg;
TRACE_EXIT_RES(res);
return res;
#ifndef CONFIG_SCST_PROC
out_del:
list_del(&acg->acg_list_entry);
#endif
out_undup:
kfree(acg->acg_name);
out_free:
kfree(acg);
acg = NULL;
@@ -4573,6 +4597,8 @@ static void scst_del_acg(struct scst_acg *acg)
scst_assert_activity_suspended();
lockdep_assert_held(&scst_mutex);
scst_cm_on_del_acg(acg);
list_for_each_entry_safe(acg_dev, acg_dev_tmp, &acg->acg_dev_list,
acg_dev_list_entry)
scst_del_acg_dev(acg_dev, true);
+14 -6
View File
@@ -550,8 +550,8 @@ struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
if (rc < 0)
goto out_unlock;
tgt->default_acg = scst_alloc_add_acg(tgt, tgt->tgt_name, false);
if (tgt->default_acg == NULL)
rc = scst_alloc_add_acg(tgt, tgt->tgt_name, false, &tgt->default_acg);
if (rc != 0)
goto out_sysfs_del;
#endif
@@ -1057,6 +1057,11 @@ static void __scst_resume_activity(void)
TRACE_ENTRY();
if (suspend_count == 0) {
PRINT_WARNING("Resume without suspend");
goto out;
}
suspend_count--;
TRACE_MGMT_DBG("suspend_count %d left", suspend_count);
if (suspend_count > 0)
@@ -1117,6 +1122,11 @@ void scst_resume_activity(void)
}
EXPORT_SYMBOL_GPL(scst_resume_activity);
int scst_get_suspend_count(void)
{
return suspend_count;
}
static int scst_register_device(struct scsi_device *scsidp)
{
int res;
@@ -2640,11 +2650,9 @@ static int __init init_scst(void)
goto out_sysfs_cleanup;
#ifdef CONFIG_SCST_PROC
scst_default_acg = scst_alloc_add_acg(NULL, SCST_DEFAULT_ACG_NAME, false);
if (scst_default_acg == NULL) {
res = -ENOMEM;
res = scst_alloc_add_acg(NULL, SCST_DEFAULT_ACG_NAME, false, &scst_default_acg);
if (res != 0)
goto out_destroy_sgv_pool;
}
#endif
res = scsi_register_interface(&scst_interface);
+6 -3
View File
@@ -1173,10 +1173,12 @@ void scst_pr_cleanup(struct scst_device *dev)
int scst_pr_set_cluster_mode(struct scst_device *dev, bool cluster_mode,
const char *cl_dev_id)
{
bool cluster_mode_enabled = false;
int res = 0;
#if defined(CONFIG_DLM) || defined(CONFIG_DLM_MODULE)
#if defined(CONFIG_DLM) || defined(CONFIG_DLM_MODULE) && \
!defined(CONFIG_SCST_NO_DLM)
bool cluster_mode_enabled = false;
cluster_mode_enabled = dev->cl_ops == &scst_dlm_cl_ops;
if (cluster_mode_enabled == cluster_mode)
@@ -1192,11 +1194,12 @@ int scst_pr_set_cluster_mode(struct scst_device *dev, bool cluster_mode,
dev->virt_name, cluster_mode, res);
dev->cl_ops = &scst_no_dlm_cl_ops;
}
out:
#else
res = cluster_mode ? -ENOTSUPP : 0;
#endif
out:
return res;
}
EXPORT_SYMBOL(scst_pr_set_cluster_mode);
+17 -5
View File
@@ -347,8 +347,8 @@ int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev);
void scst_free_device(struct scst_device *dev);
bool scst_device_is_exported(struct scst_device *dev);
struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
const char *acg_name, bool tgt_acg);
int scst_alloc_add_acg(struct scst_tgt *tgt, const char *acg_name,
bool tgt_acg, struct scst_acg **out_acg);
int scst_del_free_acg(struct scst_acg *acg, bool close_sessions);
void scst_get_acg(struct scst_acg *acg);
void scst_put_acg(struct scst_acg *acg);
@@ -363,11 +363,14 @@ void scst_sess_free_tgt_devs(struct scst_session *sess);
struct scst_tgt_dev *scst_lookup_tgt_dev(struct scst_session *sess, u64 lun);
void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA);
#define SCST_ADD_LUN_READ_ONLY 1
#define SCST_ADD_LUN_GEN_UA 2
#define SCST_ADD_LUN_CM 4
int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
struct scst_device *dev, uint64_t lun, int read_only,
bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev);
struct scst_device *dev, uint64_t lun, unsigned int flags,
struct scst_acg_dev **out_acg_dev);
int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
bool gen_scst_report_luns_changed);
bool gen_report_luns_changed);
int scst_acg_add_acn(struct scst_acg *acg, const char *name);
#ifdef CONFIG_SCST_PROC
@@ -729,6 +732,8 @@ void scst_ext_unblock_dev(struct scst_device *dev, bool stpg);
void __scst_ext_blocking_done(struct scst_device *dev);
void scst_ext_blocking_done(struct scst_device *dev);
int scst_get_suspend_count(void);
/*
* Increases global SCST ref counters which prevent from entering into suspended
* activities stage, so protects from any global management operations.
@@ -855,6 +860,13 @@ static inline bool scst_lba1_inside_lba2(int64_t lba1,
int scst_cm_on_dev_register(struct scst_device *dev);
void scst_cm_on_dev_unregister(struct scst_device *dev);
int scst_cm_on_add_acg(struct scst_acg *acg);
void scst_cm_on_del_acg(struct scst_acg *acg);
int scst_cm_on_add_lun(struct scst_acg_dev *acg_dev, uint64_t lun,
unsigned int *flags);
bool scst_cm_on_del_lun(struct scst_acg_dev *acg_dev,
bool gen_report_luns_changed);
int scst_cm_parse_descriptors(struct scst_cmd *cmd);
void scst_cm_free_descriptors(struct scst_cmd *cmd);
+5 -3
View File
@@ -948,8 +948,8 @@ static int scst_proc_group_add(const char *p, unsigned int addr_method)
}
strlcpy(name, p, len);
acg = scst_alloc_add_acg(NULL, name, false);
if (acg == NULL) {
res = scst_alloc_add_acg(NULL, name, false, &acg);
if (res != 0) {
PRINT_ERROR("scst_alloc_add_acg() (name %s) failed", name);
goto out_free;
}
@@ -969,6 +969,7 @@ out_free_acg:
out_free:
kfree(name);
goto out;
out_nomem:
res = -ENOMEM;
@@ -2069,7 +2070,8 @@ static ssize_t scst_proc_groups_devices_write(struct file *file,
}
}
rc = scst_acg_add_lun(acg, NULL, dev, virt_lun, read_only,
rc = scst_acg_add_lun(acg, NULL, dev, virt_lun,
read_only ? SCST_ADD_LUN_READ_ONLY : 0,
false, NULL);
if (rc) {
res = rc;
+58 -3
View File
@@ -1327,6 +1327,7 @@ static int __scst_process_luns_mgmt_store(char *buffer,
case SCST_LUN_ACTION_REPLACE:
{
bool dev_replaced = false;
unsigned int flags = 0;
e = scst_get_next_lexem(&pp);
res = kstrtoul(e, 0, &virt_lun);
@@ -1414,9 +1415,13 @@ static int __scst_process_luns_mgmt_store(char *buffer,
}
}
if (read_only)
flags |= SCST_ADD_LUN_READ_ONLY;
if (!dev_replaced)
flags |= SCST_ADD_LUN_GEN_UA;
res = scst_acg_add_lun(acg,
tgt_kobj ? tgt->tgt_luns_kobj : acg->luns_kobj,
dev, virt_lun, read_only, !dev_replaced, NULL);
dev, virt_lun, flags, NULL);
if (res != 0)
goto out_unlock;
@@ -2174,8 +2179,8 @@ static int scst_process_ini_group_mgmt_store(char *buffer,
res = -EINVAL;
goto out_unlock;
}
acg = scst_alloc_add_acg(tgt, p, true);
if (acg == NULL)
res = scst_alloc_add_acg(tgt, p, true, &acg);
if (res != 0)
goto out_unlock;
break;
case SCST_INI_GROUP_ACTION_DEL:
@@ -7056,6 +7061,55 @@ static struct kobj_attribute scst_max_tasklet_cmd_attr =
__ATTR(max_tasklet_cmd, S_IRUGO | S_IWUSR, scst_max_tasklet_cmd_show,
scst_max_tasklet_cmd_store);
static ssize_t scst_suspend_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
int count;
TRACE_ENTRY();
count = sprintf(buf, "%d\n", scst_get_suspend_count());
TRACE_EXIT();
return count;
}
static ssize_t scst_suspend_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
int res;
long val;
TRACE_ENTRY();
res = kstrtol(buf, 0, &val);
if (res != 0) {
PRINT_ERROR("kstrtoul() for %s failed: %d ", buf, res);
goto out;
}
if (val >= 0) {
PRINT_INFO("SYSFS: suspending activities (timeout %ld)...", val);
res = scst_suspend_activity(val*HZ);
if (res == 0)
PRINT_INFO("sysfs suspending done");
} else {
PRINT_INFO("SYSFS: resuming activities");
scst_resume_activity();
}
if (res == 0)
res = count;
out:
TRACE_EXIT_RES(res);
return res;
}
static struct kobj_attribute scst_suspend_attr =
__ATTR(suspend, S_IRUGO | S_IWUSR, scst_suspend_show,
scst_suspend_store);
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
static ssize_t scst_main_trace_level_show(struct kobject *kobj,
@@ -7281,6 +7335,7 @@ static struct attribute *scst_sysfs_root_default_attrs[] = {
&scst_threads_attr.attr,
&scst_setup_id_attr.attr,
&scst_max_tasklet_cmd_attr.attr,
&scst_suspend_attr.attr,
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
&scst_main_trace_level_attr.attr,
#endif
+60 -4
View File
@@ -3356,7 +3356,11 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
struct srpt_send_ioctx *ioctx,
scst_data_direction dir)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
struct ib_send_wr wr;
#else
struct ib_rdma_wr wr;
#endif
struct ib_send_wr *bad_wr;
struct rdma_iu *riu;
int i;
@@ -3377,6 +3381,7 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
memset(&wr, 0, sizeof(wr));
for (i = 0; i < n_rdma; ++i, ++riu) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
if (dir == SCST_DATA_READ) {
wr.opcode = IB_WR_RDMA_WRITE;
wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
@@ -3401,6 +3406,32 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
wr.send_flags = IB_SEND_SIGNALED;
ret = ib_post_send(ch->qp, &wr, &bad_wr);
#else
if (dir == SCST_DATA_READ) {
wr.wr.opcode = IB_WR_RDMA_WRITE;
wr.wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
SRPT_RDMA_WRITE_LAST :
SRPT_RDMA_MID,
ioctx->ioctx.index);
} else {
wr.wr.opcode = IB_WR_RDMA_READ;
wr.wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
SRPT_RDMA_READ_LAST :
SRPT_RDMA_MID,
ioctx->ioctx.index);
}
wr.wr.next = NULL;
wr.remote_addr = riu->raddr;
wr.rkey = riu->rkey;
wr.wr.num_sge = riu->sge_cnt;
wr.wr.sg_list = riu->sge;
/* only get completion event for the last rdma wr */
if (i == (n_rdma - 1) && dir == SCST_DATA_WRITE)
wr.wr.send_flags = IB_SEND_SIGNALED;
ret = ib_post_send(ch->qp, &wr.wr, &bad_wr);
#endif
if (ret)
break;
}
@@ -3409,6 +3440,7 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
pr_err("%s: ib_post_send() returned %d for %d/%d\n", __func__,
ret, i, n_rdma);
if (ret && i > 0) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
wr.num_sge = 0;
wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
wr.send_flags = IB_SEND_SIGNALED;
@@ -3420,13 +3452,34 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
ioctx->ioctx.index);
msleep(1000);
}
#else
wr.wr.num_sge = 0;
wr.wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
wr.wr.send_flags = IB_SEND_SIGNALED;
pr_info("Trying to abort failed RDMA transfer [%d]\n",
ioctx->ioctx.index);
while (ch->state == CH_LIVE &&
ib_post_send(ch->qp, &wr.wr, &bad_wr) != 0) {
pr_info("Trying to abort failed RDMA transfer [%d]\n",
ioctx->ioctx.index);
msleep(1000);
}
#endif
pr_info("Waiting until RDMA abort finished [%d]\n",
ioctx->ioctx.index);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
while (ch->state < CH_DISCONNECTED && !ioctx->rdma_aborted) {
pr_info("Waiting until RDMA abort finished [%d]\n",
ioctx->ioctx.index);
msleep(1000);
}
#else
while (ch->state < CH_DISCONNECTED && !ioctx->rdma_aborted) {
pr_info("Waiting until RDMA abort finished [%d]\n",
ioctx->ioctx.index);
msleep(1000);
}
#endif
pr_info("%s[%d]: done\n", __func__, __LINE__);
}
@@ -4480,13 +4533,16 @@ static int __init srpt_init_module(void)
if (rdma_cm_port) {
struct sockaddr_in addr;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) || \
defined(RHEL_MAJOR) && RHEL_MAJOR -0 >= 6
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0) && \
(!defined(RHEL_MAJOR) || RHEL_MAJOR -0 < 6)
rdma_cm_id = rdma_create_id(srpt_rdma_cm_handler, NULL,
RDMA_PS_TCP);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
rdma_cm_id = rdma_create_id(srpt_rdma_cm_handler, NULL,
RDMA_PS_TCP, IB_QPT_RC);
#else
rdma_cm_id = rdma_create_id(srpt_rdma_cm_handler, NULL,
RDMA_PS_TCP);
rdma_cm_id = rdma_create_id(&init_net, srpt_rdma_cm_handler,
NULL, RDMA_PS_TCP, IB_QPT_RC);
#endif
if (IS_ERR(rdma_cm_id)) {
rdma_cm_id = NULL;