mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-25 01:23:14 +00:00
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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user