mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-07 08:36:45 +00:00
Merge of the pr branch with additional fixes for problems found during extra testing
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1714 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -82,6 +82,18 @@ help:
|
||||
@echo " srpt_install : srp target: install"
|
||||
@echo " srpt_uninstall : srp target: uninstall"
|
||||
@echo ""
|
||||
@echo " mvsas : make MVSAS target"
|
||||
@echo " mvsas_clean : mvsas target: clean "
|
||||
@echo " mvsas_extraclean : mvsas target: clean + clean dependencies"
|
||||
@echo " mvsas_install : mvsas target: install"
|
||||
@echo " mvsas_uninstall : mvsas target: uninstall"
|
||||
@echo ""
|
||||
@echo " fcst : make FCoE target"
|
||||
@echo " fcst_clean : FCoE target: clean "
|
||||
@echo " fcst_extraclean : FCoE target: clean + clean dependencies"
|
||||
@echo " fcst_install : FCoE target: install"
|
||||
@echo " fcst_uninstall : FCoE target: uninstall"
|
||||
@echo ""
|
||||
@echo " scst_local : make scst_local target"
|
||||
@echo " scst_local_install : scst_local target: install"
|
||||
@echo " scst_local_uninstall : scst_local target: uninstall"
|
||||
|
||||
+5
-5
@@ -56,7 +56,7 @@ static struct ft_tport *ft_tport_create(struct fc_lport *lport)
|
||||
if (!tport)
|
||||
return NULL;
|
||||
|
||||
tport->tgt = scst_register(&ft_scst_template, name);
|
||||
tport->tgt = scst_register_target(&ft_scst_template, name);
|
||||
if (!tport->tgt) {
|
||||
kfree(tport);
|
||||
return NULL;
|
||||
@@ -94,7 +94,7 @@ static void ft_tport_delete(struct ft_tport *tport)
|
||||
tgt = tport->tgt;
|
||||
BUG_ON(!tgt);
|
||||
FT_SESS_DBG("delete %s\n", scst_get_tgt_name(tgt));
|
||||
scst_unregister(tgt);
|
||||
scst_unregister_target(tgt);
|
||||
lport = tport->lport;
|
||||
BUG_ON(tport != lport->prov[FC_TYPE_FCP]);
|
||||
rcu_assign_pointer(lport->prov[FC_TYPE_FCP], NULL);
|
||||
@@ -214,7 +214,8 @@ static int ft_sess_create(struct ft_tport *tport, struct fc_rport_priv *rdata,
|
||||
|
||||
ft_format_wwn(name, sizeof(name), rdata->ids.port_name);
|
||||
FT_SESS_DBG("register %s\n", name);
|
||||
scst_sess = scst_register_session(tport->tgt, 0, name, NULL, NULL);
|
||||
scst_sess = scst_register_session(tport->tgt, 0, name, sess, NULL,
|
||||
NULL);
|
||||
if (!scst_sess) {
|
||||
kfree(sess);
|
||||
return FC_SPP_RESP_RES; /* out of resources */
|
||||
@@ -236,7 +237,6 @@ static int ft_sess_create(struct ft_tport *tport, struct fc_rport_priv *rdata,
|
||||
sess->params = fcp_parm;
|
||||
|
||||
rdata->prli_count++;
|
||||
scst_sess_set_tgt_priv(scst_sess, sess);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -474,7 +474,7 @@ void ft_recv(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp)
|
||||
|
||||
/*
|
||||
* Release all sessions for a target.
|
||||
* Called through scst_unregister() as well as directly.
|
||||
* Called through scst_unregister_target() as well as directly.
|
||||
* Caller holds ft_lport_lock.
|
||||
*/
|
||||
int ft_tgt_release(struct scst_tgt *tgt)
|
||||
|
||||
@@ -805,6 +805,13 @@ in/out in the kernel's module Makefile:
|
||||
|
||||
- CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES - simulates digest failures in
|
||||
random places.
|
||||
|
||||
- CONFIG_SCST_ISCSI_SKIP_ISID - makes iSCSI-SCST to always use iSCSI
|
||||
initiator port TransportID format 0, i.e. always identify initiators
|
||||
only by names and ignore ISID part in TransportIDs. This is useful
|
||||
for Persistent Reservations with initiators which don't use ISID in a
|
||||
standards confirming way, for instance by always incrementing it on
|
||||
each reconnect, as well as to debug Persistent Reservations.
|
||||
|
||||
|
||||
Creating version of put_page_callback patch for your kernel
|
||||
|
||||
@@ -701,6 +701,13 @@ in/out in the kernel's module Makefile:
|
||||
- CONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES - simulates digest failures in
|
||||
random places.
|
||||
|
||||
- CONFIG_SCST_ISCSI_SKIP_ISID - makes iSCSI-SCST to always use iSCSI
|
||||
initiator port TransportID format 0, i.e. always identify initiators
|
||||
only by names and ignore ISID part in TransportIDs. This is useful
|
||||
for Persistent Reservations with initiators which don't use ISID in a
|
||||
standards confirming way, for instance by always incrementing it on
|
||||
each reconnect, as well as to debug Persistent Reservations.
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
@@ -23,3 +23,17 @@ config SCST_ISCSI_DEBUG_DIGEST_FAILURES
|
||||
iSCSI initiator that is talking to SCST.
|
||||
|
||||
If unsure, say "N".
|
||||
|
||||
config CONFIG_SCST_ISCSI_SKIP_ISID
|
||||
bool "Do not use ISID in initiator port transport id"
|
||||
depends on SCST_ISCSI
|
||||
help
|
||||
Makes iSCSI-SCST to always use iSCSI initiator port
|
||||
TransportID format 0, i.e. always identify initiators only by
|
||||
names and ignore ISID part in TransportIDs. This is useful for
|
||||
Persistent Reservations with initiators which don't use ISID
|
||||
in a standards confirming way, for instance by always
|
||||
incrementing it on each reconnect, as well as to debug
|
||||
Persistent Reservations.
|
||||
|
||||
If unsure, say "N".
|
||||
|
||||
@@ -29,6 +29,8 @@ EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG -g -fno-inline -fno-inline-functions
|
||||
|
||||
#EXTRA_CFLAGS += -DCONFIG_SCST_ISCSI_DEBUG_DIGEST_FAILURES
|
||||
|
||||
#EXTRA_CFLAGS += -DCONFIG_SCST_ISCSI_SKIP_ISID
|
||||
|
||||
obj-m += iscsi-scst.o
|
||||
iscsi-scst-objs := iscsi.o nthread.o config.o digest.o \
|
||||
conn.o session.o target.o event.o param.o
|
||||
|
||||
@@ -260,6 +260,10 @@ static ssize_t iscsi_version_show(struct kobject *kobj,
|
||||
strcat(buf, "DEBUG_DIGEST_FAILURES\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_ISCSI_SKIP_ISID
|
||||
strcat(buf, "CONFIG_SCST_ISCSI_SKIP_ISID\n");
|
||||
#endif
|
||||
|
||||
TRACE_EXIT();
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
@@ -613,12 +613,12 @@ static int conn_setup_sock(struct iscsi_conn *conn)
|
||||
mm_segment_t oldfs;
|
||||
struct iscsi_session *session = conn->session;
|
||||
|
||||
TRACE_DBG("%llu", (long long unsigned int)session->sid);
|
||||
TRACE_DBG("%llx", (long long unsigned int)session->sid);
|
||||
|
||||
conn->sock = SOCKET_I(conn->file->f_dentry->d_inode);
|
||||
|
||||
if (conn->sock->ops->sendpage == NULL) {
|
||||
PRINT_ERROR("Socket for sid %llu doesn't support sendpage()",
|
||||
PRINT_ERROR("Socket for sid %llx doesn't support sendpage()",
|
||||
(long long unsigned int)session->sid);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
#include <linux/hash.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <net/tcp.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "digest.h"
|
||||
@@ -3118,8 +3121,7 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
|
||||
u8 *sense = scst_cmd_get_sense_buffer(scst_cmd);
|
||||
int sense_len = scst_cmd_get_sense_buffer_len(scst_cmd);
|
||||
|
||||
if (unlikely(scst_cmd_atomic(scst_cmd)))
|
||||
return SCST_TGT_RES_NEED_THREAD_CTX;
|
||||
EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
|
||||
|
||||
scst_cmd_set_tgt_priv(scst_cmd, NULL);
|
||||
|
||||
@@ -3494,6 +3496,56 @@ static int iscsi_report_aen(struct scst_aen *aen)
|
||||
return res;
|
||||
}
|
||||
|
||||
int iscsi_get_initiator_port_transport_id(struct scst_session *scst_sess,
|
||||
uint8_t **transport_id)
|
||||
{
|
||||
struct iscsi_session *sess;
|
||||
int res = 0;
|
||||
union iscsi_sid sid;
|
||||
int tr_id_size;
|
||||
uint8_t *tr_id;
|
||||
uint8_t q;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
sess = (struct iscsi_session *)scst_sess_get_tgt_priv(scst_sess);
|
||||
|
||||
sid = *(union iscsi_sid *)&sess->sid;
|
||||
sid.id.tsih = 0;
|
||||
|
||||
tr_id_size = 4 + strlen(sess->initiator_name) + 5 +
|
||||
snprintf(&q, sizeof(q), "%llx", sid.id64) + 1;
|
||||
tr_id_size = (tr_id_size + 3) & -4;
|
||||
|
||||
tr_id = kzalloc(tr_id_size, GFP_KERNEL);
|
||||
if (tr_id == NULL) {
|
||||
PRINT_ERROR("Allocation of TrandportID (size %d) failed",
|
||||
tr_id_size);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCST_ISCSI_SKIP_ISID
|
||||
tr_id[0] = 0x0 | SCSI_TRANSPORTID_PROTOCOLID_ISCSI;
|
||||
tr_id_size = 4 + sprintf(&tr_id[4], "%s", sess->initiator_name) + 1;
|
||||
tr_id_size = (tr_id_size + 3) & -4;
|
||||
#else
|
||||
tr_id[0] = 0x40 | SCSI_TRANSPORTID_PROTOCOLID_ISCSI;
|
||||
sprintf(&tr_id[4], "%s,i,0x%llx", sess->initiator_name, sid.id64);
|
||||
#endif
|
||||
|
||||
put_unaligned(cpu_to_be16(tr_id_size - 4),
|
||||
(__be16 *)&tr_id[2]);
|
||||
|
||||
*transport_id = tr_id;
|
||||
|
||||
TRACE_DBG("Created tid '%s'", &tr_id[4]);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void iscsi_send_nop_in(struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_cmnd *req, *rsp;
|
||||
@@ -3615,6 +3667,7 @@ struct scst_tgt_template iscsi_template = {
|
||||
.task_mgmt_affected_cmds_done = iscsi_task_mgmt_affected_cmds_done,
|
||||
.task_mgmt_fn_done = iscsi_task_mgmt_fn_done,
|
||||
.report_aen = iscsi_report_aen,
|
||||
.get_initiator_port_transport_id = iscsi_get_initiator_port_transport_id,
|
||||
};
|
||||
|
||||
static __init int iscsi_run_threads(int count, char *name, int (*fn)(void *))
|
||||
@@ -3691,6 +3744,12 @@ static int __init iscsi_init(void)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_ISCSI_SKIP_ISID
|
||||
PRINT_WARNING("%s", "CONFIG_SCST_ISCSI_SKIP_ISID defined: identifying "
|
||||
"initiators only by names and ignoring ISID part in "
|
||||
"TransportIDs");
|
||||
#endif
|
||||
|
||||
ctr_major = register_chrdev(0, ctr_name, &ctr_fops);
|
||||
if (ctr_major < 0) {
|
||||
PRINT_ERROR("failed to register the control device %d",
|
||||
@@ -3729,6 +3788,12 @@ static int __init iscsi_init(void)
|
||||
if (err != 0)
|
||||
goto out_thr;
|
||||
|
||||
#ifdef CONFIG_SCST_ISCSI_SKIP_ISID
|
||||
iscsi_tid_name_only = true;
|
||||
#else
|
||||
iscsi_tid_name_only = false;
|
||||
#endif
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
||||
|
||||
@@ -326,12 +326,17 @@ void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd)
|
||||
struct iscsi_session *sess = conn->session;
|
||||
struct iscsi_conn *c;
|
||||
|
||||
if (sess->sess_reinst_successor != NULL)
|
||||
scst_reassign_persistent_sess_states(
|
||||
sess->sess_reinst_successor->scst_sess,
|
||||
sess->scst_sess);
|
||||
|
||||
mutex_lock(&sess->target->target_mutex);
|
||||
|
||||
/*
|
||||
* We can't mark sess as shutting down earlier, because until
|
||||
* now it might have pending commands. Otherwise, in case of
|
||||
* reinstatement it might lead to data corruption, because
|
||||
* reinstatement, it might lead to data corruption, because
|
||||
* commands in being reinstated session can be executed
|
||||
* after commands in the new session.
|
||||
*/
|
||||
@@ -374,6 +379,8 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
typeof(jiffies) shut_start_waiting = start_waiting;
|
||||
bool pending_reported = 0, wait_expired = 0, shut_expired = 0;
|
||||
bool reinst;
|
||||
uint32_t tid, cid;
|
||||
uint64_t sid;
|
||||
|
||||
#define CONN_PENDING_TIMEOUT ((typeof(jiffies))10*HZ)
|
||||
#define CONN_WAIT_TIMEOUT ((typeof(jiffies))10*HZ)
|
||||
@@ -548,10 +555,9 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
|
||||
wait_for_completion(&conn->ready_to_free);
|
||||
|
||||
TRACE_CONN_CLOSE("Notifying user space about closing connection %p",
|
||||
conn);
|
||||
event_send(target->tid, session->sid, conn->cid, 0, E_CONN_CLOSE,
|
||||
NULL, NULL);
|
||||
tid = target->tid;
|
||||
sid = session->sid;
|
||||
cid = conn->cid;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
mutex_lock(&target->target_mutex);
|
||||
@@ -561,6 +567,17 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
kobject_put(&conn->iscsi_conn_kobj);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We can't send E_CONN_CLOSE earlier, because otherwise we would have
|
||||
* a race, when the user space tried to destroy session, which still
|
||||
* has connections.
|
||||
*
|
||||
* !! All target, session and conn can be already dead here !!
|
||||
*/
|
||||
TRACE_CONN_CLOSE("Notifying user space about closing connection %p",
|
||||
conn);
|
||||
event_send(tid, sid, cid, 0, E_CONN_CLOSE, NULL, NULL);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ static int iscsi_session_alloc(struct iscsi_target *target,
|
||||
session->next_ttt = 1;
|
||||
|
||||
session->scst_sess = scst_register_session(target->scst_tgt, 0,
|
||||
name, NULL, NULL);
|
||||
name, session, NULL, NULL);
|
||||
if (session->scst_sess == NULL) {
|
||||
PRINT_ERROR("%s", "scst_register_session() failed");
|
||||
err = -ENOMEM;
|
||||
@@ -92,8 +92,6 @@ static int iscsi_session_alloc(struct iscsi_target *target,
|
||||
kfree(name);
|
||||
#endif
|
||||
|
||||
scst_sess_set_tgt_priv(session->scst_sess, session);
|
||||
|
||||
TRACE_MGMT_DBG("Session %p created: target %p, tid %u, sid %#Lx",
|
||||
session, target, target->tid, info->sid);
|
||||
|
||||
@@ -346,7 +344,7 @@ int __del_session(struct iscsi_target *target, u64 sid)
|
||||
return -ENOENT;
|
||||
|
||||
if (!list_empty(&session->conn_list)) {
|
||||
PRINT_ERROR("%llu still have connections",
|
||||
PRINT_ERROR("%llx still have connections",
|
||||
(long long unsigned int)session->sid);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -523,7 +521,7 @@ static ssize_t iscsi_sess_force_close_store(struct kobject *kobj,
|
||||
goto out;
|
||||
}
|
||||
|
||||
PRINT_INFO("Deleting session %llu with initiator %s (%p)",
|
||||
PRINT_INFO("Deleting session %llx with initiator %s (%p)",
|
||||
(long long unsigned int)sess->sid, sess->initiator_name, sess);
|
||||
|
||||
list_for_each_entry(conn, &sess->conn_list, conn_list_entry) {
|
||||
|
||||
@@ -89,9 +89,9 @@ static int iscsi_target_create(struct iscsi_kern_target_info *info, u32 tid,
|
||||
INIT_LIST_HEAD(&target->attrs_list);
|
||||
#endif
|
||||
|
||||
target->scst_tgt = scst_register(&iscsi_template, target->name);
|
||||
target->scst_tgt = scst_register_target(&iscsi_template, target->name);
|
||||
if (!target->scst_tgt) {
|
||||
PRINT_ERROR("%s", "scst_register() failed");
|
||||
PRINT_ERROR("%s", "scst_register_target() failed");
|
||||
err = -EBUSY;
|
||||
goto out_free;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ static void target_destroy(struct iscsi_target *target)
|
||||
}
|
||||
#endif
|
||||
|
||||
scst_unregister(target->scst_tgt);
|
||||
scst_unregister_target(target->scst_tgt);
|
||||
|
||||
kfree(target);
|
||||
|
||||
|
||||
+6
-8
@@ -381,9 +381,9 @@ mptstm_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
atomic_set(&tgt->sess_count, 0);
|
||||
init_waitqueue_head(&tgt->waitQ);
|
||||
|
||||
tgt->scst_tgt = scst_register(&tgt_template, MYNAM);
|
||||
tgt->scst_tgt = scst_register_target(&tgt_template, MYNAM);
|
||||
if (tgt->scst_tgt == NULL) {
|
||||
PRINT_ERROR(MYNAM ": scst_register() "
|
||||
PRINT_ERROR(MYNAM ": scst_register_target() "
|
||||
"failed for host %p", pdev);
|
||||
|
||||
ret = -ENODEV;
|
||||
@@ -399,7 +399,7 @@ mptstm_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
PRINT_ERROR("Not enough memory to register "
|
||||
"target driver %s entry %s in /proc",
|
||||
tgt_template.name, name);
|
||||
scst_unregister(tgt->scst_tgt);
|
||||
scst_unregister_target(tgt->scst_tgt);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@@ -437,7 +437,7 @@ static struct mpt_pci_driver mptstm_driver = {
|
||||
*
|
||||
* this function is intended to detect the target adapters that are present in
|
||||
* the system. Each found adapter should be registered by calling
|
||||
* scst_register(). The function should return a value >= 0 to signify
|
||||
* scst_register_target(). The function should return a value >= 0 to signify
|
||||
* the number of detected target adapters. A negative value should be
|
||||
* returned whenever there is an error.
|
||||
*/
|
||||
@@ -592,8 +592,6 @@ mpt_alloc_session_done(struct scst_session *scst_sess, void *data, int result)
|
||||
|
||||
TRACE_ENTRY();
|
||||
if (result == 0) {
|
||||
scst_sess_set_tgt_priv(scst_sess, sess);
|
||||
|
||||
while (!list_empty(&sess->delayed_cmds)) {
|
||||
cmd = list_entry(sess->delayed_cmds.next,
|
||||
typeof(*cmd), delayed_cmds_entry);
|
||||
@@ -979,7 +977,8 @@ stmapp_tgt_command(MPT_STM_PRIV *priv, u32 reply_word)
|
||||
INIT_LIST_HEAD(&sess->delayed_cmds);
|
||||
|
||||
sess->scst_sess = scst_register_session(tgt->scst_tgt, 1,
|
||||
"", sess, mpt_alloc_session_done);
|
||||
"", sess, sess,
|
||||
mpt_alloc_session_done);
|
||||
if (sess->scst_sess == NULL) {
|
||||
PRINT_ERROR(MYNAM ": scst_register_session failed %p",
|
||||
tgt);
|
||||
@@ -990,7 +989,6 @@ stmapp_tgt_command(MPT_STM_PRIV *priv, u32 reply_word)
|
||||
__set_bit(MPT_SESS_INITING, &sess->sess_flags);
|
||||
|
||||
tgt->sess[init_index] = sess;
|
||||
scst_sess_set_tgt_priv(sess->scst_sess, sess);
|
||||
|
||||
cmd->sess = sess;
|
||||
list_add_tail(&cmd->delayed_cmds_entry, &sess->delayed_cmds);
|
||||
|
||||
+8
-8
@@ -1593,7 +1593,7 @@ int mvst_send_cmd_to_scst(struct mvs_info *mvi,
|
||||
}
|
||||
|
||||
sess->scst_sess = scst_register_session(
|
||||
tgt->scst_tgt, SCST_ATOMIC, name, sess,
|
||||
tgt->scst_tgt, SCST_ATOMIC, name, sess, sess,
|
||||
mvst_alloc_session_done);
|
||||
kfree(name);
|
||||
}
|
||||
@@ -1606,7 +1606,6 @@ int mvst_send_cmd_to_scst(struct mvs_info *mvi,
|
||||
res = -EFAULT;
|
||||
goto out_free_sess;
|
||||
}
|
||||
scst_sess_set_tgt_priv(sess->scst_sess, sess);
|
||||
|
||||
/* add session data to host data structure */
|
||||
list_add(&sess->sess_entry, &tgt->sess_list);
|
||||
@@ -2112,9 +2111,9 @@ static void mvst_register_tgt_handler(struct mvs_info *mvi)
|
||||
INIT_LIST_HEAD(&tgt->sess_list);
|
||||
init_waitqueue_head(&tgt->waitQ);
|
||||
|
||||
tgt->scst_tgt = scst_register(&tgt_template, MVST_NAME);
|
||||
tgt->scst_tgt = scst_register_target(&tgt_template, MVST_NAME);
|
||||
if (!tgt->scst_tgt) {
|
||||
PRINT_ERROR("mvst tgt(%ld): scst_register() "
|
||||
PRINT_ERROR("mvst tgt(%ld): scst_register_target() "
|
||||
"failed for host %ld(%p)", mvi->instance,
|
||||
mvi->host_no, mvi);
|
||||
kfree(tgt);
|
||||
@@ -2141,11 +2140,11 @@ static void mvst_unregister_tgt_handler(struct mvs_info *mvi)
|
||||
|
||||
TRACE_DBG("Shutting down host %ld(%ld,%p)",
|
||||
mvi->host_no, mvi->instance, mvi);
|
||||
scst_unregister(tgt->scst_tgt);
|
||||
scst_unregister_target(tgt->scst_tgt);
|
||||
mvi->flags &= ~MVF_TARGET_MODE_ENABLE;
|
||||
/*
|
||||
* Free of tgt happens via callback mvst_target_release
|
||||
* called from scst_unregister, so we shouldn't touch it again
|
||||
* called from scst_unregister_target, so we shouldn't touch it again
|
||||
*/
|
||||
tgt = NULL;
|
||||
}
|
||||
@@ -2340,11 +2339,12 @@ static void mvst_host_action(struct mvs_info *mvi,
|
||||
|
||||
TRACE_DBG("Shutting down host %ld(%ld,%p)",
|
||||
mvi->host_no, mvi->instance, mvi);
|
||||
scst_unregister(tgt->scst_tgt);
|
||||
scst_unregister_target(tgt->scst_tgt);
|
||||
mvi->flags &= ~MVF_TARGET_MODE_ENABLE;
|
||||
/*
|
||||
* Free of tgt happens via callback mvst_target_release
|
||||
* called from scst_unregister, so we shouldn't touch it again
|
||||
* called from scst_unregister_target, so we shouldn't touch
|
||||
* it again
|
||||
*/
|
||||
tgt = NULL;
|
||||
break;
|
||||
|
||||
@@ -625,8 +625,7 @@ static struct q2t_sess *q2t_create_sess(scsi_qla_host_t *ha, fc_port_t *fcport,
|
||||
|
||||
/* Let's do the session creation async'ly */
|
||||
sess->scst_sess = scst_register_session(tgt->scst_tgt, 1, wwn_str,
|
||||
sess, q2t_alloc_session_done);
|
||||
|
||||
sess, sess, q2t_alloc_session_done);
|
||||
if (sess->scst_sess == NULL) {
|
||||
PRINT_CRIT_ERROR("qla2x00t(%ld): scst_register_session() "
|
||||
"failed for host %ld (wwn %s, loop_id %d), all "
|
||||
@@ -634,7 +633,6 @@ static struct q2t_sess *q2t_create_sess(scsi_qla_host_t *ha, fc_port_t *fcport,
|
||||
ha->host_no, wwn_str, fcport->loop_id);
|
||||
goto out_free_sess_wwn;
|
||||
}
|
||||
scst_sess_set_tgt_priv(sess->scst_sess, sess);
|
||||
|
||||
spin_lock_irq(&ha->hardware_lock);
|
||||
TRACE_MGMT_DBG("Adding sess %p to tgt %p", sess, tgt);
|
||||
@@ -2125,8 +2123,7 @@ static int q2x_xmit_response(struct scst_cmd *scst_cmd)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD
|
||||
if (scst_cmd_atomic(scst_cmd))
|
||||
return SCST_TGT_RES_NEED_THREAD_CTX;
|
||||
EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
|
||||
#endif
|
||||
|
||||
if (is_send_status)
|
||||
@@ -5020,12 +5017,12 @@ static int q2t_add_target(scsi_qla_host_t *ha)
|
||||
if (q2t_get_target_name(ha, &wwn) != 0)
|
||||
goto out_free;
|
||||
|
||||
tgt->scst_tgt = scst_register(&tgt2x_template, wwn);
|
||||
tgt->scst_tgt = scst_register_target(&tgt2x_template, wwn);
|
||||
|
||||
kfree(wwn);
|
||||
|
||||
if (!tgt->scst_tgt) {
|
||||
PRINT_ERROR("qla2x00t(%ld): scst_register() "
|
||||
PRINT_ERROR("qla2x00t(%ld): scst_register_target() "
|
||||
"failed for host %ld(%p)", ha->instance,
|
||||
ha->host_no, ha);
|
||||
res = -ENOMEM;
|
||||
@@ -5093,10 +5090,10 @@ static int q2t_remove_target(scsi_qla_host_t *ha)
|
||||
}
|
||||
|
||||
TRACE_DBG("Unregistering target for host %ld(%p)", ha->host_no, ha);
|
||||
scst_unregister(ha->tgt->scst_tgt);
|
||||
scst_unregister_target(ha->tgt->scst_tgt);
|
||||
/*
|
||||
* Free of tgt happens via callback q2t_target_release
|
||||
* called from scst_unregister, so we shouldn't touch
|
||||
* called from scst_unregister_target, so we shouldn't touch
|
||||
* it again.
|
||||
*/
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ alloc_ini(bus_chan_t *bc, uint64_t iid)
|
||||
GET(7), GET(6), GET(5) , GET(4), GET(3), GET(2), GET(1), GET(0));
|
||||
#undef GET
|
||||
|
||||
nptr->ini_scst_sess = scst_register_session(bc->scst_tgt, 0, ini_name, NULL, NULL);
|
||||
nptr->ini_scst_sess = scst_register_session(bc->scst_tgt, 0, ini_name, NULL, NULL, NULL);
|
||||
if (!nptr->ini_scst_sess) {
|
||||
Eprintk("cannot register SCST session\n");
|
||||
kfree(nptr);
|
||||
@@ -1637,7 +1637,7 @@ register_hba(bus_t *bp)
|
||||
}
|
||||
|
||||
isp_tgt_template.sg_tablesize = get_sg_tablesize(bp->h.r_identity);
|
||||
scst_tgt = scst_register(&isp_tgt_template, name);
|
||||
scst_tgt = scst_register_target(&isp_tgt_template, name);
|
||||
if (scst_tgt == NULL) {
|
||||
Eprintk("cannot register scst device %s for %s%d\n", name, bp->h.r_name, bp->h.r_inst);
|
||||
goto err_free_chan;
|
||||
@@ -1672,7 +1672,7 @@ register_hba(bus_t *bp)
|
||||
err_free_chan:
|
||||
for (chan = bp->h.r_nchannels -1; chan >= 0; chan--) {
|
||||
if (bchan[chan].scst_tgt) {
|
||||
scst_unregister(bchan[chan].scst_tgt);
|
||||
scst_unregister_target(bchan[chan].scst_tgt);
|
||||
}
|
||||
}
|
||||
kfree(bchan);
|
||||
@@ -1726,7 +1726,7 @@ unregister_hba(bus_t *bp, hba_register_t *unreg_hp)
|
||||
BUS_DBG(bp, "Chan %d waiting for finishing %d sessions\n", chan, atomic_read(&bc->sess_count));
|
||||
wait_event(bc->wait_queue, atomic_read(&bc->sess_count) == 0);
|
||||
BUS_DBG(bp, "Chan %d all sessions finished\n", chan);
|
||||
scst_unregister(bc->scst_tgt);
|
||||
scst_unregister_target(bc->scst_tgt);
|
||||
}
|
||||
}
|
||||
kfree(bp->bchan);
|
||||
|
||||
+46
-18
@@ -271,17 +271,20 @@ in/out in Makefile:
|
||||
patching is necessary for pass-through device handlers (scst_disk,
|
||||
etc.).
|
||||
|
||||
- CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ - if defined, it will be
|
||||
allowed to submit pass-through commands to real SCSI devices via the SCSI
|
||||
middle layer using scsi_execute_async() function from soft IRQ
|
||||
context (tasklets). This used to be the default, but currently it
|
||||
seems the SCSI middle layer starts expecting only thread context on
|
||||
the IO submit path, so it is disabled now by default. Enabling it
|
||||
will decrease amount of context switches and improve performance. It
|
||||
is more or less safe, in the worst case, if in your configuration the
|
||||
SCSI middle layer really doesn't expect SIRQ context in
|
||||
scsi_execute_async() function, you will get a warning message in the
|
||||
kernel log.
|
||||
- CONFIG_SCST_TEST_IO_IN_SIRQ - if defined, allows SCST to submit selected
|
||||
SCSI commands (TUR and READ/WRITE) from soft-IRQ context (tasklets).
|
||||
Enabling it will decrease amount of context switches and slightly
|
||||
improve performance. The goal of this option is to be able to measure
|
||||
overhead of the context switches. If after enabling this option you
|
||||
don't see under load in vmstat output on the target significant
|
||||
decrease of amount of context switches, then your target driver
|
||||
doesn't submit commands to SCST in IRQ context. For instance,
|
||||
iSCSI-SCST doesn't do that, but qla2x00t with
|
||||
CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD disabled - does. This option is
|
||||
designed to be used with vdisk NULLIO backend.
|
||||
|
||||
WARNING! Using with other backend than vdisk NULLIO is unsafe and can
|
||||
lead you to a kernel crash!
|
||||
|
||||
- CONFIG_SCST_STRICT_SECURITY - if defined, makes SCST zero allocated data
|
||||
buffers. Undefining it (default) considerably improves performance
|
||||
@@ -1285,6 +1288,34 @@ IMPORTANT: Some disk and partition table management utilities don't support
|
||||
work with files on such file system.
|
||||
|
||||
|
||||
Persistent Reservations
|
||||
-----------------------
|
||||
|
||||
SCST implements Persistent Reservations with full set of capabilities,
|
||||
including "Persistence Through Power Loss".
|
||||
|
||||
The "Persistence Through Power Loss" data are saved in /var/lib/scst/pr
|
||||
with files with names the same as the names of the corresponding
|
||||
devices. Also this directory contains backup versions of those files
|
||||
with suffix ".1". Those backup files are used in case of power or other
|
||||
failure to prevent Persistent Reservation information from corruption
|
||||
during update.
|
||||
|
||||
The Persistent Reservations available on all transports implementing
|
||||
get_initiator_port_transport_id() callback. Transports not implementing
|
||||
this callback will act in one of 2 possible scenarios ("all or
|
||||
nothing"):
|
||||
|
||||
1. If a device has such transport connected and doesn't have persistent
|
||||
reservations, it will refuse Persistent Reservations commands as if it
|
||||
doesn't support them.
|
||||
|
||||
2. If a device has persistent reservations, all initiators newly
|
||||
connecting via such transports will not see this device. After all
|
||||
persistent reservations from this device are released, upon reconnect
|
||||
the initiators will see it.
|
||||
|
||||
|
||||
Caching
|
||||
-------
|
||||
|
||||
@@ -1473,7 +1504,8 @@ you, so the resulting performance will, in average, be better
|
||||
you can by manual tuning improve it even more.
|
||||
|
||||
If you want to get maximum performance from your target, RHEL/CentOS 5.x
|
||||
kernels are not recommended, because they are based on very outdated
|
||||
kernels are not recommended on both target and initiators, if you are
|
||||
using Linux initiators, because those kernels are based on very outdated
|
||||
2.6.18 kernel, hence, missed >3 years of important improvements in the
|
||||
kernel's storage area. You should use at least long maintained vanilla
|
||||
2.6.27.x kernel, although 2.6.29+ would be even better.
|
||||
@@ -1490,9 +1522,6 @@ In order to get the maximum performance you should:
|
||||
- Disable in Makefile CONFIG_SCST_STRICT_SERIALIZING, CONFIG_SCST_EXTRACHECKS,
|
||||
CONFIG_SCST_TRACING, CONFIG_SCST_DEBUG*, CONFIG_SCST_STRICT_SECURITY
|
||||
|
||||
- For pass-through devices enable
|
||||
CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ.
|
||||
|
||||
2. For target drivers:
|
||||
|
||||
- Disable in Makefiles CONFIG_SCST_EXTRACHECKS, CONFIG_SCST_TRACING,
|
||||
@@ -1502,14 +1531,13 @@ In order to get the maximum performance you should:
|
||||
|
||||
- Disable in Makefile CONFIG_SCST_TRACING and CONFIG_SCST_DEBUG.
|
||||
|
||||
|
||||
IMPORTANT: The development version of SCST in the SVN is optimized for
|
||||
========= development and bug hunting, not for performance. To reconfigure
|
||||
it for performance you should run "make debug2perf" in the
|
||||
root of your source code (e.g. trunk/). It will set the above
|
||||
options as needed. The only option it doesn't set is
|
||||
CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ, so, if
|
||||
needed, you should change it manually.
|
||||
CONFIG_SCST_TEST_IO_IN_SIRQ, so, if needed, you should change
|
||||
it manually.
|
||||
|
||||
IMPORTANT: You can't use debug SCST drivers with non-debug SCST core.
|
||||
========= So, after disabling both CONFIG_SCST_TRACING and CONFIG_SCST_DEBUG
|
||||
|
||||
+42
-14
@@ -196,17 +196,20 @@ your favorite kernel configuration Makefile target, e.g. "make xconfig":
|
||||
patching is necessary for pass-through device handlers (scst_disk,
|
||||
etc.).
|
||||
|
||||
- CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ - if defined, it will be
|
||||
allowed to submit pass-through commands to real SCSI devices via the SCSI
|
||||
middle layer using scsi_execute_async() function from soft IRQ
|
||||
context (tasklets). This used to be the default, but currently it
|
||||
seems the SCSI middle layer starts expecting only thread context on
|
||||
the IO submit path, so it is disabled now by default. Enabling it
|
||||
will decrease amount of context switches and improve performance. It
|
||||
is more or less safe, in the worst case, if in your configuration the
|
||||
SCSI middle layer really doesn't expect SIRQ context in
|
||||
scsi_execute_async() function, you will get a warning message in the
|
||||
kernel log.
|
||||
- CONFIG_SCST_TEST_IO_IN_SIRQ - if defined, allows SCST to submit selected
|
||||
SCSI commands (TUR and READ/WRITE) from soft-IRQ context (tasklets).
|
||||
Enabling it will decrease amount of context switches and slightly
|
||||
improve performance. The goal of this option is to be able to measure
|
||||
overhead of the context switches. If after enabling this option you
|
||||
don't see under load in vmstat output on the target significant
|
||||
decrease of amount of context switches, then your target driver
|
||||
doesn't submit commands to SCST in IRQ context. For instance,
|
||||
iSCSI-SCST doesn't do that, but qla2x00t with
|
||||
CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD disabled - does. This option is
|
||||
designed to be used with vdisk NULLIO backend.
|
||||
|
||||
WARNING! Using with other backend than vdisk NULLIO is unsafe and can
|
||||
lead you to a kernel crash!
|
||||
|
||||
- CONFIG_SCST_STRICT_SECURITY - if defined, makes SCST zero allocated data
|
||||
buffers. Undefining it (default) considerably improves performance
|
||||
@@ -869,6 +872,34 @@ IMPORTANT: Some disk and partition table management utilities don't support
|
||||
work with files on such file system.
|
||||
|
||||
|
||||
Persistent Reservations
|
||||
-----------------------
|
||||
|
||||
SCST implements Persistent Reservations with full set of capabilities,
|
||||
including "Persistence Through Power Loss".
|
||||
|
||||
The "Persistence Through Power Loss" data are saved in /var/lib/scst/pr
|
||||
with files with names the same as the names of the corresponding
|
||||
devices. Also this directory contains backup versions of those files
|
||||
with suffix ".1". Those backup files are used in case of power or other
|
||||
failure to prevent Persistent Reservation information from corruption
|
||||
during update.
|
||||
|
||||
The Persistent Reservations available on all transports implementing
|
||||
get_initiator_port_transport_id() callback. Transports not implementing
|
||||
this callback will act in one of 2 possible scenarios ("all or
|
||||
nothing"):
|
||||
|
||||
1. If a device has such transport connected and doesn't have persistent
|
||||
reservations, it will refuse Persistent Reservations commands as if it
|
||||
doesn't support them.
|
||||
|
||||
2. If a device has persistent reservations, all initiators newly
|
||||
connecting via such transports will not see this device. After all
|
||||
persistent reservations from this device are released, upon reconnect
|
||||
the initiators will see it.
|
||||
|
||||
|
||||
Caching
|
||||
-------
|
||||
|
||||
@@ -1068,9 +1099,6 @@ In order to get the maximum performance you should:
|
||||
- Disable in Makefile CONFIG_SCST_STRICT_SERIALIZING, CONFIG_SCST_EXTRACHECKS,
|
||||
CONFIG_SCST_TRACING, CONFIG_SCST_DEBUG*, CONFIG_SCST_STRICT_SECURITY
|
||||
|
||||
- For pass-through devices enable
|
||||
CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ.
|
||||
|
||||
2. For target drivers:
|
||||
|
||||
- Disable in Makefiles CONFIG_SCST_EXTRACHECKS, CONFIG_SCST_TRACING,
|
||||
|
||||
+182
-61
@@ -64,7 +64,7 @@ typedef _Bool bool;
|
||||
#else
|
||||
#define SCST_VERSION_STRING_SUFFIX
|
||||
#endif
|
||||
#define SCST_VERSION_STRING "2.0.0-pre1" SCST_VERSION_STRING_SUFFIX
|
||||
#define SCST_VERSION_STRING "2.0.0-rc1" SCST_VERSION_STRING_SUFFIX
|
||||
#define SCST_INTERFACE_VERSION \
|
||||
SCST_VERSION_STRING "$Revision$" SCST_CONST_VERSION
|
||||
|
||||
@@ -200,22 +200,25 @@ static inline int list_is_last(const struct list_head *list,
|
||||
*************************************************************/
|
||||
|
||||
/* LUN translation (mcmd->tgt_dev assignment) */
|
||||
#define SCST_MCMD_STATE_INIT 0
|
||||
#define SCST_MCMD_STATE_INIT 0
|
||||
|
||||
/* Mgmt cmd is ready for processing */
|
||||
#define SCST_MCMD_STATE_READY 1
|
||||
/* Mgmt cmd is being processed */
|
||||
#define SCST_MCMD_STATE_EXEC 1
|
||||
|
||||
/* Mgmt cmd is being executing */
|
||||
#define SCST_MCMD_STATE_EXECUTING 2
|
||||
/* Waiting for affected commands done */
|
||||
#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_DONE 2
|
||||
|
||||
/* Post check when affected commands done */
|
||||
#define SCST_MCMD_STATE_POST_AFFECTED_CMDS_DONE 3
|
||||
/* Post actions when affected commands done */
|
||||
#define SCST_MCMD_STATE_AFFECTED_CMDS_DONE 3
|
||||
|
||||
/* Waiting for affected local commands finished */
|
||||
#define SCST_MCMD_STATE_WAITING_AFFECTED_CMDS_FINISHED 4
|
||||
|
||||
/* Target driver's task_mgmt_fn_done() is going to be called */
|
||||
#define SCST_MCMD_STATE_DONE 4
|
||||
#define SCST_MCMD_STATE_DONE 5
|
||||
|
||||
/* The mcmd finished */
|
||||
#define SCST_MCMD_STATE_FINISHED 5
|
||||
#define SCST_MCMD_STATE_FINISHED 6
|
||||
|
||||
/*************************************************************
|
||||
** Constants for "atomic" parameter of SCST's functions
|
||||
@@ -309,9 +312,6 @@ enum scst_exec_context {
|
||||
*/
|
||||
#define SCST_PREPROCESS_STATUS_ERROR_FATAL 3
|
||||
|
||||
/* Thread context requested */
|
||||
#define SCST_PREPROCESS_STATUS_NEED_THREAD 4
|
||||
|
||||
/*************************************************************
|
||||
** Values for AEN functions
|
||||
*************************************************************/
|
||||
@@ -374,12 +374,6 @@ enum scst_exec_context {
|
||||
/* The cmd should be sent to SCSI mid-level */
|
||||
#define SCST_EXEC_NOT_COMPLETED 1
|
||||
|
||||
/*
|
||||
* Thread context is required to execute the command.
|
||||
* Exec() will be called again in the thread context.
|
||||
*/
|
||||
#define SCST_EXEC_NEED_THREAD 2
|
||||
|
||||
/*
|
||||
* Set if cmd is finished and there is status/sense to be sent.
|
||||
* The status should be not sent (i.e. the flag not set) if the
|
||||
@@ -463,11 +457,7 @@ enum scst_exec_context {
|
||||
|
||||
/* Set if the corresponding context is atomic */
|
||||
#define SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC 5
|
||||
#define SCST_TGT_DEV_AFTER_INIT_OTH_ATOMIC 6
|
||||
#define SCST_TGT_DEV_AFTER_RESTART_WR_ATOMIC 7
|
||||
#define SCST_TGT_DEV_AFTER_RESTART_OTH_ATOMIC 8
|
||||
#define SCST_TGT_DEV_AFTER_RX_DATA_ATOMIC 9
|
||||
#define SCST_TGT_DEV_AFTER_EXEC_ATOMIC 10
|
||||
#define SCST_TGT_DEV_AFTER_EXEC_ATOMIC 6
|
||||
|
||||
#define SCST_TGT_DEV_CLUST_POOL 11
|
||||
|
||||
@@ -735,10 +725,6 @@ struct scst_tgt_template {
|
||||
* This command is expected to be NON-BLOCKING.
|
||||
* If it is blocking, consider to set threads_num to some none 0 number.
|
||||
*
|
||||
* Pay attention to "atomic" attribute of the cmd, which can be get
|
||||
* by scst_cmd_atomic(): it is true if the function called in the
|
||||
* atomic (non-sleeping) context.
|
||||
*
|
||||
* OPTIONAL
|
||||
*/
|
||||
int (*pre_exec) (struct scst_cmd *cmd);
|
||||
@@ -816,6 +802,20 @@ struct scst_tgt_template {
|
||||
int length, int *eof, struct scst_tgt *tgt);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function returns in tr_id the corresponding to sess initiator
|
||||
* port TransporID in the form as it's used by PR commands, see
|
||||
* "Transport Identifiers" in SPC. Space for the initiator port
|
||||
* TransporID must be allocated via kmalloc(). Caller supposed to
|
||||
* kfree() it, when it isn't needed anymore.
|
||||
*
|
||||
* Returns 0 on success or negative error code otherwise.
|
||||
*
|
||||
* SHOULD HAVE, because it's required for Persistent Reservations.
|
||||
*/
|
||||
int (*get_initiator_port_transport_id) (struct scst_session *sess,
|
||||
uint8_t **transport_id);
|
||||
|
||||
/*
|
||||
* This function allows to enable or disable particular target.
|
||||
* A disabled target doesn't receive and process any SCSI commands.
|
||||
@@ -972,7 +972,6 @@ struct scst_dev_type {
|
||||
*/
|
||||
unsigned parse_atomic:1;
|
||||
unsigned alloc_data_buf_atomic:1;
|
||||
unsigned exec_atomic:1;
|
||||
unsigned dev_done_atomic:1;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
@@ -986,6 +985,13 @@ struct scst_dev_type {
|
||||
*/
|
||||
unsigned exec_sync:1;
|
||||
|
||||
/*
|
||||
* Should be set if the device wants to receive notification of
|
||||
* Persistent Reservation commands (PR OUT only)
|
||||
* Note: The notification will not be send if the command failed
|
||||
*/
|
||||
unsigned pr_cmds_notifications:1;
|
||||
|
||||
/*
|
||||
* Called to parse CDB from the cmd and initialize
|
||||
* cmd->bufflen and cmd->data_direction (both - REQUIRED).
|
||||
@@ -1032,15 +1038,9 @@ struct scst_dev_type {
|
||||
* cmd->scst_cmd_done() callback.
|
||||
* Returns:
|
||||
* - SCST_EXEC_COMPLETED - the cmd is done, go to other ones
|
||||
* - SCST_EXEC_NEED_THREAD - thread context is required to execute
|
||||
* the command. Exec() will be called again in the thread context.
|
||||
* - SCST_EXEC_NOT_COMPLETED - the cmd should be sent to SCSI
|
||||
* mid-level.
|
||||
*
|
||||
* Pay attention to "atomic" attribute of the cmd, which can be get
|
||||
* by scst_cmd_atomic(): it is true if the function called in the
|
||||
* atomic (non-sleeping) context.
|
||||
*
|
||||
* If this function provides sync execution, you should set
|
||||
* exec_sync flag and consider to setup dedicated threads by
|
||||
* setting threads_num > 0.
|
||||
@@ -1385,6 +1385,9 @@ struct scst_session {
|
||||
/* Access control for this session and list entry there */
|
||||
struct scst_acg *acg;
|
||||
|
||||
/* Initiator port transport id */
|
||||
uint8_t *transport_id;
|
||||
|
||||
/* List entry for the sessions list inside ACG */
|
||||
struct list_head acg_sess_list_entry;
|
||||
|
||||
@@ -1459,6 +1462,29 @@ struct scst_session {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* SCST_PR_ABORT_ALL TM function helper structure
|
||||
*/
|
||||
struct scst_pr_abort_all_pending_mgmt_cmds_counter {
|
||||
/*
|
||||
* How many there are pending for this cmd SCST_PR_ABORT_ALL TM
|
||||
* commands.
|
||||
*/
|
||||
atomic_t pr_abort_pending_cnt;
|
||||
|
||||
/* Saved completition routine */
|
||||
void (*saved_cmd_done) (struct scst_cmd *cmd, int next_state,
|
||||
enum scst_exec_context pref_context);
|
||||
|
||||
/*
|
||||
* How many there are pending for this cmd SCST_PR_ABORT_ALL TM
|
||||
* commands, which not yet aborted all affected commands and
|
||||
* a completion to signal, when it's done.
|
||||
*/
|
||||
atomic_t pr_aborting_cnt;
|
||||
struct completion pr_aborting_cmpl;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to control commands' queuing and threads pool processing the queue
|
||||
*/
|
||||
@@ -1567,6 +1593,12 @@ struct scst_cmd {
|
||||
*/
|
||||
unsigned int sg_buff_modified:1;
|
||||
|
||||
/*
|
||||
* Set if cmd buffer was vmallocated and copied from more
|
||||
* then one sg chunk
|
||||
*/
|
||||
unsigned int sg_buff_vmallocated:1;
|
||||
|
||||
/*
|
||||
* Set if scst_cmd_init_stage1_done() called and the target
|
||||
* want that preprocessing_done() will be called
|
||||
@@ -1761,12 +1793,18 @@ struct scst_cmd {
|
||||
/* Used to retry commands in case of double UA */
|
||||
int dbl_ua_orig_resp_data_len, dbl_ua_orig_data_direction;
|
||||
|
||||
/* List corresponding mgmt cmd, if any, protected by sess_list_lock */
|
||||
/*
|
||||
* List of the corresponding mgmt cmds, if any. Protected by
|
||||
* sess_list_lock.
|
||||
*/
|
||||
struct list_head mgmt_cmd_list;
|
||||
|
||||
/* List entry for dev's blocked_cmd_list */
|
||||
struct list_head blocked_cmd_list_entry;
|
||||
|
||||
/* Counter of the corresponding SCST_PR_ABORT_ALL TM commands */
|
||||
struct scst_pr_abort_all_pending_mgmt_cmds_counter *pr_abort_counter;
|
||||
|
||||
struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */
|
||||
|
||||
#ifdef CONFIG_SCST_MEASURE_LATENCY
|
||||
@@ -1806,8 +1844,11 @@ struct scst_mgmt_cmd_stub {
|
||||
/* List entry in cmd->mgmt_cmd_list */
|
||||
struct list_head cmd_mgmt_cmd_list_entry;
|
||||
|
||||
/* set if the cmd was counted in mcmd->cmd_done_wait_count */
|
||||
/* Set if the cmd was counted in mcmd->cmd_done_wait_count */
|
||||
unsigned int done_counted:1;
|
||||
|
||||
/* Set if the cmd was counted in mcmd->cmd_finish_wait_count */
|
||||
unsigned int finish_counted:1;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1824,13 +1865,10 @@ struct scst_mgmt_cmd {
|
||||
|
||||
int fn; /* task management function */
|
||||
|
||||
unsigned int completed:1; /* set, if the mcmd is completed */
|
||||
/* Set if device(s) should be unblocked after mcmd's finish */
|
||||
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 */
|
||||
/* set, if scst_mgmt_affected_cmds_done was called */
|
||||
unsigned int affected_cmds_done_called:1;
|
||||
|
||||
/*
|
||||
* Number of commands to finish before sending response,
|
||||
@@ -1862,18 +1900,36 @@ struct scst_mgmt_cmd {
|
||||
/* completition status, one of the SCST_MGMT_STATUS_* constants */
|
||||
int status;
|
||||
|
||||
/* Used for storage of target driver private stuff */
|
||||
void *tgt_priv;
|
||||
/* Used for storage of target driver private stuff or origin PR cmd */
|
||||
union {
|
||||
void *tgt_priv;
|
||||
struct scst_cmd *origin_pr_cmd;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Persistent reservations registrant
|
||||
*/
|
||||
struct scst_dev_registrant {
|
||||
uint8_t *transport_id;
|
||||
uint16_t rel_tgt_id;
|
||||
uint64_t key;
|
||||
|
||||
/* tgt_dev (I_T nexus) for this registrant, if any */
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
|
||||
/* List entry for dev_registrants_list */
|
||||
struct list_head dev_registrants_list_entry;
|
||||
|
||||
/* 2 auxiliary fields used to rollback changes for errors, etc. */
|
||||
struct list_head aux_list_entry;
|
||||
uint64_t rollback_key;
|
||||
};
|
||||
|
||||
/*
|
||||
* SCST device
|
||||
*/
|
||||
struct scst_device {
|
||||
struct scst_dev_type *handler; /* corresponding dev handler */
|
||||
|
||||
struct scst_mem_lim dev_mem_lim;
|
||||
|
||||
unsigned short type; /* SCSI type of the device */
|
||||
|
||||
/*************************************************************
|
||||
@@ -1890,12 +1946,15 @@ struct scst_device {
|
||||
/* If set, dev is read only */
|
||||
unsigned short rd_only:1;
|
||||
|
||||
/* Set if tgt_kobj was initialized */
|
||||
unsigned short dev_kobj_initialized:1;
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
/*************************************************************
|
||||
** Dev's control mode page related values. Updates serialized
|
||||
** by scst_block_dev(). It's long to not interfere with the
|
||||
** above flags.
|
||||
** neighbour fields.
|
||||
*************************************************************/
|
||||
|
||||
unsigned long queue_alg:4;
|
||||
@@ -1913,6 +1972,23 @@ struct scst_device {
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
/* Set if dev is persistently reserved. Protected by dev_pr_mutex. */
|
||||
unsigned short pr_is_set:1;
|
||||
|
||||
/*
|
||||
* Set if there is a thread changing or going to change PR state(s).
|
||||
* Protected by dev_pr_mutex.
|
||||
*/
|
||||
unsigned short pr_writer_active:1;
|
||||
|
||||
/*
|
||||
* How many threads are checking commands for PR allowance. Used to
|
||||
* implement lockless read-only fast path.
|
||||
*/
|
||||
atomic_t pr_readers_count;
|
||||
|
||||
struct scst_dev_type *handler; /* corresponding dev handler */
|
||||
|
||||
/* Used for storage of dev handler private stuff */
|
||||
void *dh_priv;
|
||||
|
||||
@@ -1924,16 +2000,20 @@ struct scst_device {
|
||||
/* Corresponding real SCSI device, could be NULL for virtual devices */
|
||||
struct scsi_device *scsi_dev;
|
||||
|
||||
/* Lists of commands with lock, if dedicated threads are used */
|
||||
/* List of commands with lock, if dedicated threads are used */
|
||||
struct scst_cmd_threads dev_cmd_threads;
|
||||
|
||||
/* Memory limits for this device */
|
||||
struct scst_mem_lim dev_mem_lim;
|
||||
|
||||
/* How many cmds alive on this dev */
|
||||
atomic_t dev_cmd_count;
|
||||
|
||||
/* How many write cmds alive on this dev. Temporary, ToDo */
|
||||
atomic_t write_cmd_count;
|
||||
|
||||
spinlock_t dev_lock; /* device lock */
|
||||
/*
|
||||
* How many there are "on_dev" commands, i.e. ones those are being
|
||||
* executed by the underlying SCSI/virtual device.
|
||||
*/
|
||||
atomic_t on_dev_count;
|
||||
|
||||
/*
|
||||
* How many times device was blocked for new cmds execution.
|
||||
@@ -1941,11 +2021,48 @@ struct scst_device {
|
||||
*/
|
||||
int block_count;
|
||||
|
||||
/* How many write cmds alive on this dev. Temporary, ToDo */
|
||||
atomic_t write_cmd_count;
|
||||
|
||||
/*************************************************************
|
||||
** Persistent reservation fields. Protected by dev_pr_mutex.
|
||||
*************************************************************/
|
||||
|
||||
/* True if persist through power loss is activated */
|
||||
unsigned short pr_aptpl:1;
|
||||
|
||||
/* Persistent reservation type */
|
||||
uint8_t pr_type;
|
||||
|
||||
/* Persistent reservation scope */
|
||||
uint8_t pr_scope;
|
||||
|
||||
/* Mutex to protect PR operations */
|
||||
struct mutex dev_pr_mutex;
|
||||
|
||||
/* Persistent reservation generation value */
|
||||
uint32_t pr_generation;
|
||||
|
||||
/* Reference to registrant - persistent reservation holder */
|
||||
struct scst_dev_registrant *pr_holder;
|
||||
|
||||
/* List of dev's registrants */
|
||||
struct list_head dev_registrants_list;
|
||||
|
||||
/*
|
||||
* How many there are "on_dev" commands, i.e. ones those are being
|
||||
* executed by the underlying SCSI/virtual device.
|
||||
* Count of connected tgt_devs from transports, which don't support
|
||||
* PRs, i.e. don't have get_initiator_port_transport_id(). Protected
|
||||
* by scst_mutex.
|
||||
*/
|
||||
atomic_t on_dev_count;
|
||||
int not_pr_supporting_tgt_devs_num;
|
||||
|
||||
/* Persist through power loss files */
|
||||
char *pr_file_name;
|
||||
char *pr_file_name1;
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
spinlock_t dev_lock; /* device lock */
|
||||
|
||||
struct list_head blocked_cmd_list; /* protected by dev_lock */
|
||||
|
||||
@@ -1979,9 +2096,6 @@ struct scst_device {
|
||||
/* Threads pool type of the device. Valid only if threads_num > 0. */
|
||||
enum scst_dev_type_threads_pool_type threads_pool_type;
|
||||
|
||||
/* Set if tgt_kobj was initialized */
|
||||
unsigned int dev_kobj_initialized:1;
|
||||
|
||||
/*
|
||||
* Used to protect sysfs attributes to be called after this
|
||||
* object was unregistered.
|
||||
@@ -2094,6 +2208,9 @@ struct scst_tgt_dev {
|
||||
struct scst_session *sess; /* corresponding session */
|
||||
struct scst_acg_dev *acg_dev; /* corresponding acg_dev */
|
||||
|
||||
/* Reference to registrant to find quicker */
|
||||
struct scst_dev_registrant *registrant;
|
||||
|
||||
/* List entry in dev->dev_tgt_dev_list */
|
||||
struct list_head dev_tgt_dev_list_entry;
|
||||
|
||||
@@ -2258,12 +2375,12 @@ static inline int scst_register_target_template(struct scst_tgt_template *vtt)
|
||||
|
||||
void scst_unregister_target_template(struct scst_tgt_template *vtt);
|
||||
|
||||
struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
|
||||
struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
|
||||
const char *target_name);
|
||||
void scst_unregister(struct scst_tgt *tgt);
|
||||
void scst_unregister_target(struct scst_tgt *tgt);
|
||||
|
||||
struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
|
||||
const char *initiator_name, void *data,
|
||||
const char *initiator_name, void *tgt_priv, void *result_fn_data,
|
||||
void (*result_fn) (struct scst_session *sess, void *data, int result));
|
||||
void scst_unregister_session(struct scst_session *sess, int wait,
|
||||
void (*unreg_done_fn) (struct scst_session *sess));
|
||||
@@ -3194,6 +3311,7 @@ struct scst_trace_log {
|
||||
};
|
||||
|
||||
extern struct mutex scst_mutex;
|
||||
extern bool iscsi_tid_name_only;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
|
||||
@@ -3395,6 +3513,9 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd,
|
||||
|
||||
int scst_obtain_device_parameters(struct scst_device *dev);
|
||||
|
||||
void scst_reassign_persistent_sess_states(struct scst_session *new_sess,
|
||||
struct scst_session *old_sess);
|
||||
|
||||
int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun);
|
||||
|
||||
/*
|
||||
|
||||
+64
-24
@@ -63,12 +63,12 @@
|
||||
/*************************************************************
|
||||
** Values for task management functions
|
||||
*************************************************************/
|
||||
#define SCST_ABORT_TASK 0
|
||||
#define SCST_ABORT_TASK_SET 1
|
||||
#define SCST_CLEAR_ACA 2
|
||||
#define SCST_CLEAR_TASK_SET 3
|
||||
#define SCST_LUN_RESET 4
|
||||
#define SCST_TARGET_RESET 5
|
||||
#define SCST_ABORT_TASK 0
|
||||
#define SCST_ABORT_TASK_SET 1
|
||||
#define SCST_CLEAR_ACA 2
|
||||
#define SCST_CLEAR_TASK_SET 3
|
||||
#define SCST_LUN_RESET 4
|
||||
#define SCST_TARGET_RESET 5
|
||||
|
||||
/** SCST extensions **/
|
||||
|
||||
@@ -77,20 +77,20 @@
|
||||
* Aborts all tasks there, resets the reservation, if any, and sets
|
||||
* up the I_T Nexus loss UA.
|
||||
*/
|
||||
#define SCST_NEXUS_LOSS_SESS 6
|
||||
#define SCST_NEXUS_LOSS_SESS 6
|
||||
|
||||
/* Aborts all tasks in the corresponding session */
|
||||
#define SCST_ABORT_ALL_TASKS_SESS 7
|
||||
#define SCST_ABORT_ALL_TASKS_SESS 7
|
||||
|
||||
/*
|
||||
* Notifies about I_T nexus loss event. Aborts all tasks in all sessions
|
||||
* of the tgt, resets the reservations, if any, and sets up the I_T Nexus
|
||||
* loss UA.
|
||||
*/
|
||||
#define SCST_NEXUS_LOSS 8
|
||||
#define SCST_NEXUS_LOSS 8
|
||||
|
||||
/* Aborts all tasks in all sessions of the tgt */
|
||||
#define SCST_ABORT_ALL_TASKS 9
|
||||
#define SCST_ABORT_ALL_TASKS 9
|
||||
|
||||
/*
|
||||
* Internal TM command issued by SCST in scst_unregister_session(). It is the
|
||||
@@ -99,9 +99,24 @@
|
||||
* - it doesn't call task_mgmt_fn_done()
|
||||
* - it doesn't queue NEXUS LOSS UA.
|
||||
*
|
||||
* Target driver shall NEVER use it!!
|
||||
* Target drivers must NEVER use it!!
|
||||
*/
|
||||
#define SCST_UNREG_SESS_TM 10
|
||||
#define SCST_UNREG_SESS_TM 10
|
||||
|
||||
/*
|
||||
* Internal TM command issued by SCST in scst_pr_abort_reg(). It aborts all
|
||||
* tasks from mcmd->origin_pr_cmd->tgt_dev, except mcmd->origin_pr_cmd.
|
||||
* Additionally:
|
||||
* - it signals pr_aborting_cmpl completion when all affected
|
||||
* commands marked as aborted.
|
||||
* - it doesn't call task_mgmt_affected_cmds_done()
|
||||
* - it doesn't call task_mgmt_fn_done()
|
||||
* - it calls mcmd->origin_pr_cmd->scst_cmd_done() when all affected
|
||||
* commands aborted.
|
||||
*
|
||||
* Target drivers must NEVER use it!!
|
||||
*/
|
||||
#define SCST_PR_ABORT_ALL 11
|
||||
|
||||
/*************************************************************
|
||||
** Values for mgmt cmd's status field. Codes taken from iSCSI
|
||||
@@ -128,18 +143,23 @@ enum scst_cmd_queue_type {
|
||||
** CDB flags
|
||||
*************************************************************/
|
||||
enum scst_cdb_flags {
|
||||
SCST_TRANSFER_LEN_TYPE_FIXED = 0x001,
|
||||
SCST_SMALL_TIMEOUT = 0x002,
|
||||
SCST_LONG_TIMEOUT = 0x004,
|
||||
SCST_UNKNOWN_LENGTH = 0x008,
|
||||
SCST_INFO_VALID = 0x010, /* must be single bit */
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x020,
|
||||
SCST_IMPLICIT_HQ = 0x040,
|
||||
SCST_SKIP_UA = 0x080,
|
||||
SCST_WRITE_MEDIUM = 0x100,
|
||||
SCST_LOCAL_CMD = 0x200,
|
||||
SCST_FULLY_LOCAL_CMD = 0x400,
|
||||
SCST_REG_RESERVE_ALLOWED = 0x800,
|
||||
SCST_TRANSFER_LEN_TYPE_FIXED = 0x0001,
|
||||
SCST_SMALL_TIMEOUT = 0x0002,
|
||||
SCST_LONG_TIMEOUT = 0x0004,
|
||||
SCST_UNKNOWN_LENGTH = 0x0008,
|
||||
SCST_INFO_VALID = 0x0010, /* must be single bit */
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED = 0x0020,
|
||||
SCST_IMPLICIT_HQ = 0x0040,
|
||||
SCST_SKIP_UA = 0x0080,
|
||||
SCST_WRITE_MEDIUM = 0x0100,
|
||||
SCST_LOCAL_CMD = 0x0200,
|
||||
SCST_FULLY_LOCAL_CMD = 0x0400,
|
||||
SCST_REG_RESERVE_ALLOWED = 0x0800,
|
||||
SCST_WRITE_EXCL_ALLOWED = 0x1000,
|
||||
SCST_EXCL_ACCESS_ALLOWED = 0x2000,
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED = 0x8000,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*************************************************************
|
||||
@@ -188,6 +208,9 @@ enum scst_cdb_flags {
|
||||
#define scst_sense_invalid_field_in_cdb ILLEGAL_REQUEST, 0x24, 0
|
||||
#define scst_sense_invalid_field_in_parm_list ILLEGAL_REQUEST, 0x26, 0
|
||||
#define scst_sense_parameter_value_invalid ILLEGAL_REQUEST, 0x26, 2
|
||||
#define scst_sense_invalid_release ILLEGAL_REQUEST, 0x26, 4
|
||||
#define scst_sense_parameter_list_length_invalid \
|
||||
ILLEGAL_REQUEST, 0x1A, 0
|
||||
#define scst_sense_reset_UA UNIT_ATTENTION, 0x29, 0
|
||||
#define scst_sense_nexus_loss_UA UNIT_ATTENTION, 0x29, 0x7
|
||||
#define scst_sense_saving_params_unsup ILLEGAL_REQUEST, 0x39, 0
|
||||
@@ -202,6 +225,9 @@ enum scst_cdb_flags {
|
||||
#define scst_sense_invalid_message ILLEGAL_REQUEST, 0x49, 0
|
||||
#define scst_sense_cleared_by_another_ini_UA UNIT_ATTENTION, 0x2F, 0
|
||||
#define scst_sense_capacity_data_changed UNIT_ATTENTION, 0x2A, 0x9
|
||||
#define scst_sense_reservation_preempted UNIT_ATTENTION, 0x2A, 0x03
|
||||
#define scst_sense_reservation_released UNIT_ATTENTION, 0x2A, 0x04
|
||||
#define scst_sense_registrations_preempted UNIT_ATTENTION, 0x2A, 0x05
|
||||
#define scst_sense_reported_luns_data_changed UNIT_ATTENTION, 0x3F, 0xE
|
||||
#define scst_sense_inquery_data_changed UNIT_ATTENTION, 0x3F, 0x3
|
||||
|
||||
@@ -306,6 +332,16 @@ enum scst_cdb_flags {
|
||||
#define SCST_CONTR_MODE_FIXED_SENSE 0
|
||||
#define SCST_CONTR_MODE_DESCR_SENSE 1
|
||||
|
||||
/*************************************************************
|
||||
** TransportID protocol identifiers
|
||||
*************************************************************/
|
||||
|
||||
#define SCSI_TRANSPORTID_PROTOCOLID_FCP2 0
|
||||
#define SCSI_TRANSPORTID_PROTOCOLID_SPI5 1
|
||||
#define SCSI_TRANSPORTID_PROTOCOLID_SRP 4
|
||||
#define SCSI_TRANSPORTID_PROTOCOLID_ISCSI 5
|
||||
#define SCSI_TRANSPORTID_PROTOCOLID_SAS 6
|
||||
|
||||
/*************************************************************
|
||||
** Misc SCSI constants
|
||||
*************************************************************/
|
||||
@@ -366,6 +402,10 @@ enum scst_cdb_flags {
|
||||
*************************************************************/
|
||||
#define SCST_SYSFS_BLOCK_SIZE PAGE_SIZE
|
||||
|
||||
#define SCST_PR_DIR "/var/lib/scst/pr"
|
||||
|
||||
#define TID_COMMON_SIZE 24
|
||||
|
||||
#define SCST_SYSFS_KEY_MARK "[key]"
|
||||
|
||||
#define SCST_MIN_REL_TGT_ID 1
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
#define TRACE_SCSI 0x00001000
|
||||
#define TRACE_SPECIAL 0x00002000 /* filtering debug, etc */
|
||||
#define TRACE_FLOW_CONTROL 0x00004000 /* flow control in action */
|
||||
#define TRACE_PRES 0x00008000
|
||||
#define TRACE_ALL 0xffffffff
|
||||
/* Flags 0xXXXX0000 are local for users */
|
||||
|
||||
@@ -204,6 +205,9 @@ do { \
|
||||
#define TRACE_MGMT_DBG(args...) TRACE_DBG_FLAG(TRACE_MGMT_DEBUG, args)
|
||||
#define TRACE_MGMT_DBG_SPECIAL(args...) \
|
||||
TRACE_DBG_FLAG(TRACE_MGMT_DEBUG|TRACE_SPECIAL, args)
|
||||
#define TRACE_PR(args...) TRACE_DBG_FLAG(TRACE_PRES, args)
|
||||
|
||||
const char *debug_transport_id_to_initiator_name(const uint8_t *transport_id);
|
||||
|
||||
#define TRACE_BUFFER(message, buff, len) \
|
||||
do { \
|
||||
@@ -318,6 +322,7 @@ do { \
|
||||
#define TRACE_DBG_SPECIAL(format, args...) do {} while (0)
|
||||
#define TRACE_MGMT_DBG(format, args...) do {} while (0)
|
||||
#define TRACE_MGMT_DBG_SPECIAL(format, args...) do {} while (0)
|
||||
#define TRACE_PR(format, args...) do {} while (0)
|
||||
#define TRACE_BUFFER(message, buff, len) do {} while (0)
|
||||
#define TRACE_BUFF_FLAG(flag, message, buff, len) do {} while (0)
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ struct scst_user_dev_desc {
|
||||
int32_t sgv_purge_interval;
|
||||
struct scst_user_opt opt;
|
||||
uint32_t block_size;
|
||||
uint8_t enable_pr_cmds_notifications;
|
||||
char name[SCST_MAX_NAME];
|
||||
char sgv_name[SCST_MAX_NAME];
|
||||
};
|
||||
|
||||
@@ -92,20 +92,18 @@ config SCST_STRICT_SECURITY
|
||||
|
||||
If unsure, say "N".
|
||||
|
||||
config SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
|
||||
bool "Allow pass-through commands to be sent from soft-IRQ context"
|
||||
config SCST_TEST_IO_IN_SIRQ
|
||||
bool "Allow test I/O from soft-IRQ context"
|
||||
depends on SCST
|
||||
help
|
||||
Allows SCST to submit SCSI pass-through commands to real SCSI devices
|
||||
via the SCSI middle layer using scsi_execute_async() function from
|
||||
soft-IRQ context (tasklets). This used to be the default, but
|
||||
currently it seems the SCSI middle layer starts expecting only thread
|
||||
context on the IO submit path, so it is disabled now by default.
|
||||
Enabling it will decrease amount of context switches and improve
|
||||
performance. It is more or less safe. In the worst case, if in your
|
||||
configuration the SCSI middle layer really doesn't expect SIRQ
|
||||
context in scsi_execute_async() function, you will get a warning
|
||||
message in the kernel log.
|
||||
Allows SCST to submit selected SCSI commands (TUR and
|
||||
READ/WRITE) from soft-IRQ context (tasklets). Enabling it will
|
||||
decrease amount of context switches and slightly improve
|
||||
performance. The goal of this option is to be able to measure
|
||||
overhead of the context switches. See more info about it in
|
||||
README.scst.
|
||||
|
||||
WARNING! Improperly used, this option can lead you to a kernel crash!
|
||||
|
||||
If unsure, say "N".
|
||||
|
||||
|
||||
+4
-2
@@ -43,6 +43,7 @@ scst-y += scst_proc.o
|
||||
#scst-y += scst_sysfs.o
|
||||
scst-y += scst_mem.o
|
||||
scst-y += scst_debug.o
|
||||
scst-y += scst_pres.o
|
||||
obj-$(CONFIG_SCST) += scst.o dev_handlers/
|
||||
|
||||
obj-$(BUILD_DEV) += $(DEV_HANDLERS_DIR)/
|
||||
@@ -86,6 +87,7 @@ ifneq ($(MOD_VERS),)
|
||||
install -m 644 Module.symvers $(INSTALL_DIR_H)
|
||||
endif
|
||||
-/sbin/depmod -a $(KVER)
|
||||
mkdir -p /var/lib/scst/pr
|
||||
@echo "****************************************************************"
|
||||
@echo "*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*"
|
||||
@echo "*!! !!*"
|
||||
@@ -122,8 +124,8 @@ EXTRA_CFLAGS += -I$(SCST_INC_DIR) -Wextra -Wno-unused-parameter \
|
||||
EXTRA_CFLAGS += -DCONFIG_SCST_EXTRACHECKS
|
||||
|
||||
#EXTRA_CFLAGS += -DCONFIG_SCST_USE_EXPECTED_VALUES
|
||||
#EXTRA_CFLAGS += -DALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
|
||||
#EXTRA_CFLAGS += -DABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING
|
||||
#EXTRA_CFLAGS += -DCONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
#EXTRA_CFLAGS += -DCONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING
|
||||
|
||||
#EXTRA_CFLAGS += -fno-inline
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ static struct scst_dev_type disk_devtype = {
|
||||
.type = TYPE_DISK,
|
||||
.parse_atomic = 1,
|
||||
.dev_done_atomic = 1,
|
||||
.exec_atomic = 1,
|
||||
.attach = disk_attach,
|
||||
.detach = disk_detach,
|
||||
.parse = disk_parse,
|
||||
@@ -67,7 +66,6 @@ static struct scst_dev_type disk_devtype_perf = {
|
||||
.type = TYPE_DISK,
|
||||
.parse_atomic = 1,
|
||||
.dev_done_atomic = 1,
|
||||
.exec_atomic = 1,
|
||||
.attach = disk_attach,
|
||||
.detach = disk_detach,
|
||||
.parse = disk_parse,
|
||||
|
||||
@@ -51,7 +51,6 @@ static struct scst_dev_type modisk_devtype = {
|
||||
.type = TYPE_MOD,
|
||||
.parse_atomic = 1,
|
||||
.dev_done_atomic = 1,
|
||||
.exec_atomic = 1,
|
||||
.attach = modisk_attach,
|
||||
.detach = modisk_detach,
|
||||
.parse = modisk_parse,
|
||||
@@ -67,7 +66,6 @@ static struct scst_dev_type modisk_devtype_perf = {
|
||||
.type = TYPE_MOD,
|
||||
.parse_atomic = 1,
|
||||
.dev_done_atomic = 1,
|
||||
.exec_atomic = 1,
|
||||
.attach = modisk_attach,
|
||||
.detach = modisk_detach,
|
||||
.parse = modisk_parse,
|
||||
|
||||
@@ -56,7 +56,6 @@ static struct scst_dev_type tape_devtype = {
|
||||
.type = TYPE_TAPE,
|
||||
.parse_atomic = 1,
|
||||
.dev_done_atomic = 1,
|
||||
.exec_atomic = 1,
|
||||
.attach = tape_attach,
|
||||
.detach = tape_detach,
|
||||
.parse = tape_parse,
|
||||
@@ -72,7 +71,6 @@ static struct scst_dev_type tape_devtype_perf = {
|
||||
.type = TYPE_TAPE,
|
||||
.parse_atomic = 1,
|
||||
.dev_done_atomic = 1,
|
||||
.exec_atomic = 1,
|
||||
.attach = tape_attach,
|
||||
.detach = tape_detach,
|
||||
.parse = tape_parse,
|
||||
|
||||
@@ -928,18 +928,6 @@ static int dev_user_exec(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
#if 0 /* We set exec_atomic in 0 to let SCST core know that we need a thread
|
||||
* context to complete the necessary actions, but all we are going to
|
||||
* do in this function is, in fact, atomic, so let's skip this check.
|
||||
*/
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
TRACE_DBG("%s", "User exec() can not be called in atomic "
|
||||
"context, rescheduling to the thread");
|
||||
res = SCST_EXEC_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
TRACE_DBG("Preparing EXEC for user space (ucmd=%p, h=%d, "
|
||||
"bufflen %d, data_len %d, ubuff %lx)", ucmd, ucmd->h,
|
||||
cmd->bufflen, cmd->data_len, ucmd->ubuff);
|
||||
@@ -2891,7 +2879,6 @@ static int dev_user_register_dev(struct file *file,
|
||||
dev->devtype.threads_num = -1;
|
||||
dev->devtype.parse_atomic = 1;
|
||||
dev->devtype.alloc_data_buf_atomic = 1;
|
||||
dev->devtype.exec_atomic = 0; /* no point to make it 1 */
|
||||
dev->devtype.dev_done_atomic = 1;
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
dev->devtype.no_proc = 1;
|
||||
@@ -2905,8 +2892,8 @@ static int dev_user_register_dev(struct file *file,
|
||||
dev->devtype.exec = dev_user_exec;
|
||||
dev->devtype.on_free_cmd = dev_user_on_free_cmd;
|
||||
dev->devtype.task_mgmt_fn = dev_user_task_mgmt_fn;
|
||||
|
||||
dev->devtype.parent = &dev_user_devtype;
|
||||
if (dev_desc->enable_pr_cmds_notifications)
|
||||
dev->devtype.pr_cmds_notifications = 1;
|
||||
|
||||
init_completion(&dev->cleanup_cmpl);
|
||||
dev->block = block;
|
||||
|
||||
@@ -429,7 +429,6 @@ static struct scst_dev_type vdisk_file_devtype = {
|
||||
.exec_sync = 1,
|
||||
.threads_num = -1,
|
||||
.parse_atomic = 1,
|
||||
.exec_atomic = 0,
|
||||
.dev_done_atomic = 1,
|
||||
.attach = vdisk_attach,
|
||||
.detach = vdisk_detach,
|
||||
@@ -465,7 +464,6 @@ static struct scst_dev_type vdisk_blk_devtype = {
|
||||
.type = TYPE_DISK,
|
||||
.threads_num = 0,
|
||||
.parse_atomic = 1,
|
||||
.exec_atomic = 0,
|
||||
.dev_done_atomic = 1,
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
.no_proc = 1,
|
||||
@@ -499,7 +497,6 @@ static struct scst_dev_type vdisk_null_devtype = {
|
||||
.type = TYPE_DISK,
|
||||
.threads_num = 0,
|
||||
.parse_atomic = 1,
|
||||
.exec_atomic = 1,
|
||||
.dev_done_atomic = 1,
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
.no_proc = 1,
|
||||
@@ -533,7 +530,6 @@ static struct scst_dev_type vcdrom_devtype = {
|
||||
.exec_sync = 1,
|
||||
.threads_num = -1,
|
||||
.parse_atomic = 1,
|
||||
.exec_atomic = 0,
|
||||
.dev_done_atomic = 1,
|
||||
.attach = vdisk_attach,
|
||||
.detach = vdisk_detach,
|
||||
@@ -643,7 +639,7 @@ static int vdisk_get_file_size(const char *filename, bool blockio,
|
||||
}
|
||||
|
||||
if (S_ISREG(inode->i_mode))
|
||||
/* Nothing to do*/;
|
||||
/* Nothing to do */;
|
||||
else if (S_ISBLK(inode->i_mode))
|
||||
inode = inode->i_bdev->bd_inode;
|
||||
else {
|
||||
@@ -1286,8 +1282,7 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
buf = kzalloc(INQ_BUF_SZ,
|
||||
scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
|
||||
buf = kzalloc(INQ_BUF_SZ, GFP_KERNEL);
|
||||
if (buf == NULL) {
|
||||
scst_set_busy(cmd);
|
||||
goto out;
|
||||
@@ -1357,8 +1352,25 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
|
||||
|
||||
num += 4;
|
||||
|
||||
/* Binary */
|
||||
buf[num + 0] = 0x01;
|
||||
/*
|
||||
* Relative target port identifier
|
||||
*/
|
||||
buf[num + 0] = 0x01; /* binary */
|
||||
/* Relative target port id */
|
||||
buf[num + 1] = 0x10 | 0x04;
|
||||
|
||||
put_unaligned(cpu_to_be16(cmd->tgt->rel_tgt_id),
|
||||
(__be16 *)&buf[num + 4 + 2]);
|
||||
|
||||
buf[num + 3] = 4;
|
||||
num += buf[num + 3];
|
||||
|
||||
num += 4;
|
||||
|
||||
/*
|
||||
* IEEE id
|
||||
*/
|
||||
buf[num + 0] = 0x01; /* binary */
|
||||
|
||||
/* EUI-64 */
|
||||
buf[num + 1] = 0x02;
|
||||
@@ -1662,8 +1674,7 @@ static void vdisk_exec_mode_sense(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
buf = kzalloc(MSENSE_BUF_SZ,
|
||||
scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL);
|
||||
buf = kzalloc(MSENSE_BUF_SZ, GFP_KERNEL);
|
||||
if (buf == NULL) {
|
||||
scst_set_busy(cmd);
|
||||
goto out;
|
||||
@@ -2206,12 +2217,9 @@ static void vdisk_exec_prevent_allow_medium_removal(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]);
|
||||
|
||||
if (cmd->dev->type == TYPE_ROM) {
|
||||
spin_lock(&virt_dev->flags_lock);
|
||||
virt_dev->prevent_allow_medium_removal =
|
||||
cmd->cdb[4] & 0x01 ? 1 : 0;
|
||||
spin_unlock(&virt_dev->flags_lock);
|
||||
}
|
||||
spin_lock(&virt_dev->flags_lock);
|
||||
virt_dev->prevent_allow_medium_removal = cmd->cdb[4] & 0x01 ? 1 : 0;
|
||||
spin_unlock(&virt_dev->flags_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -2876,7 +2884,16 @@ static int vdisk_task_mgmt_fn(struct scst_mgmt_cmd *mcmd,
|
||||
dev->swp = DEF_SWP;
|
||||
dev->tas = DEF_TAS;
|
||||
|
||||
spin_lock(&virt_dev->flags_lock);
|
||||
virt_dev->prevent_allow_medium_removal = 0;
|
||||
spin_unlock(&virt_dev->flags_lock);
|
||||
} else if (mcmd->fn == SCST_PR_ABORT_ALL) {
|
||||
struct scst_device *dev = tgt_dev->dev;
|
||||
struct scst_vdisk_dev *virt_dev =
|
||||
(struct scst_vdisk_dev *)dev->dh_priv;
|
||||
spin_lock(&virt_dev->flags_lock);
|
||||
virt_dev->prevent_allow_medium_removal = 0;
|
||||
spin_unlock(&virt_dev->flags_lock);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
|
||||
@@ -137,4 +137,95 @@ void debug_print_buffer(const void *data, int len)
|
||||
}
|
||||
EXPORT_SYMBOL(debug_print_buffer);
|
||||
|
||||
#ifdef CONFIG_SCST_DEBUG
|
||||
|
||||
/*
|
||||
* This function converts transport_id in a string form into internal per-CPU
|
||||
* static buffer. This buffer isn't anyhow protected, because it's acceptable
|
||||
* if the name corrupted in the debug logs because of the race for this buffer.
|
||||
*
|
||||
* Note! You can't call this function 2 or more times in a single logging
|
||||
* (printk) statement, because then each new call of this functon will override
|
||||
* data written in this buffer by the previous call. You should instead split
|
||||
* that logging statement on smaller statements each calling
|
||||
* debug_transport_id_to_initiator_name() only once.
|
||||
*/
|
||||
const char *debug_transport_id_to_initiator_name(const uint8_t *transport_id)
|
||||
{
|
||||
/*
|
||||
* No external protection, because it's acceptable if the name
|
||||
* corrupted in the debug logs because of the race for this
|
||||
* buffer.
|
||||
*/
|
||||
#define SIZEOF_NAME_BUF 256
|
||||
static char name_bufs[NR_CPUS][SIZEOF_NAME_BUF];
|
||||
char *name_buf;
|
||||
unsigned long flags;
|
||||
|
||||
sBUG_ON(transport_id == NULL); /* better to catch it not under lock */
|
||||
|
||||
spin_lock_irqsave(&trace_buf_lock, flags);
|
||||
|
||||
name_buf = name_bufs[smp_processor_id()];
|
||||
|
||||
/*
|
||||
* To prevent external racing with us users from accidentally
|
||||
* missing their NULL terminator.
|
||||
*/
|
||||
memset(name_buf, 0, SIZEOF_NAME_BUF);
|
||||
smp_mb();
|
||||
|
||||
switch (transport_id[0] & 0x0f) {
|
||||
case SCSI_TRANSPORTID_PROTOCOLID_ISCSI:
|
||||
scnprintf(name_buf, SIZEOF_NAME_BUF, "%s",
|
||||
&transport_id[4]);
|
||||
break;
|
||||
case SCSI_TRANSPORTID_PROTOCOLID_FCP2:
|
||||
scnprintf(name_buf, SIZEOF_NAME_BUF,
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
transport_id[8], transport_id[9],
|
||||
transport_id[10], transport_id[11],
|
||||
transport_id[12], transport_id[13],
|
||||
transport_id[14], transport_id[15]);
|
||||
break;
|
||||
case SCSI_TRANSPORTID_PROTOCOLID_SPI5:
|
||||
scnprintf(name_buf, SIZEOF_NAME_BUF,
|
||||
"%x:%x", be16_to_cpu((uint16_t)transport_id[2]),
|
||||
be16_to_cpu((uint16_t)transport_id[6]));
|
||||
break;
|
||||
case SCSI_TRANSPORTID_PROTOCOLID_SRP:
|
||||
scnprintf(name_buf, SIZEOF_NAME_BUF,
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
transport_id[8], transport_id[9],
|
||||
transport_id[10], transport_id[11],
|
||||
transport_id[12], transport_id[13],
|
||||
transport_id[14], transport_id[15],
|
||||
transport_id[16], transport_id[17],
|
||||
transport_id[18], transport_id[19],
|
||||
transport_id[20], transport_id[21],
|
||||
transport_id[22], transport_id[23]);
|
||||
break;
|
||||
case SCSI_TRANSPORTID_PROTOCOLID_SAS:
|
||||
scnprintf(name_buf, SIZEOF_NAME_BUF,
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
transport_id[4], transport_id[5],
|
||||
transport_id[6], transport_id[7],
|
||||
transport_id[8], transport_id[9],
|
||||
transport_id[10], transport_id[11]);
|
||||
break;
|
||||
default:
|
||||
scnprintf(name_buf, SIZEOF_NAME_BUF,
|
||||
"(Not known protocol ID %x)", transport_id[0] & 0x0f);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&trace_buf_lock, flags);
|
||||
|
||||
return name_buf;
|
||||
#undef SIZEOF_NAME_BUF
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SCST_DEBUG */
|
||||
|
||||
#endif /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
|
||||
|
||||
+396
-87
@@ -36,6 +36,8 @@
|
||||
#include "scst_priv.h"
|
||||
#include "scst_mem.h"
|
||||
|
||||
#include "scst_pres.h"
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
struct scsi_io_context {
|
||||
unsigned int full_cdb_used:1;
|
||||
@@ -160,17 +162,25 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x00, "MMMMMMMMMMMMMMMM", "TEST UNIT READY",
|
||||
/* let's be HQ to don't look dead under high load */
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|
|
||||
SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x01, " M ", "REWIND",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
{0x01, "O V OO OO ", "REZERO UNIT",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x02, "VVVVVV V ", "REQUEST BLOCK ADDR",
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT, 0, get_trans_len_none},
|
||||
{0x03, "MMMMMMMMMMMMMMMM", "REQUEST SENSE",
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_SKIP_UA|SCST_LOCAL_CMD|
|
||||
SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
4, get_trans_len_1},
|
||||
{0x04, "M O O ", "FORMAT UNIT",
|
||||
SCST_DATA_WRITE, SCST_LONG_TIMEOUT|SCST_UNKNOWN_LENGTH|SCST_WRITE_MEDIUM,
|
||||
@@ -178,22 +188,36 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x04, " O ", "FORMAT",
|
||||
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
|
||||
{0x05, "VMVVVV V ", "READ BLOCK LIMITS",
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
0, get_trans_len_block_limit},
|
||||
{0x07, " O ", "INITIALIZE ELEMENT STATUS",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
{0x07, "OVV O OV ", "REASSIGN BLOCKS",
|
||||
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
|
||||
{0x08, "O ", "READ(6)",
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 4, get_trans_len_1_256},
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
4, get_trans_len_1_256},
|
||||
{0x08, " MV OO OV ", "READ(6)",
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3},
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
2, get_trans_len_3},
|
||||
{0x08, " M ", "GET MESSAGE(6)",
|
||||
SCST_DATA_READ, FLAG_NONE, 2, get_trans_len_3},
|
||||
{0x08, " O ", "RECEIVE",
|
||||
SCST_DATA_READ, FLAG_NONE, 2, get_trans_len_3},
|
||||
{0x0A, "O ", "WRITE(6)",
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_WRITE_MEDIUM,
|
||||
4, get_trans_len_1_256},
|
||||
{0x0A, " M O OV ", "WRITE(6)",
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
|
||||
@@ -216,30 +240,41 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT|SCST_WRITE_MEDIUM,
|
||||
0, get_trans_len_none},
|
||||
{0x0F, "VOVVVV V ", "READ REVERSE",
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3},
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
2, get_trans_len_3},
|
||||
{0x10, "VM V V ", "WRITE FILEMARKS",
|
||||
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
|
||||
{0x10, " O O ", "SYNCHRONIZE BUFFER",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
{0x11, "VMVVVV ", "SPACE",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x12, "MMMMMMMMMMMMMMMM", "INQUIRY",
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA|
|
||||
SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
|
||||
4, get_trans_len_1},
|
||||
{0x13, "VOVVVV ", "VERIFY(6)",
|
||||
SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED,
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
2, get_trans_len_3},
|
||||
{0x14, "VOOVVV ", "RECOVER BUFFERED DATA",
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 2, get_trans_len_3},
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
2, get_trans_len_3},
|
||||
{0x15, "OMOOOOOOOOOOOOOO", "MODE SELECT(6)",
|
||||
SCST_DATA_WRITE, SCST_LOCAL_CMD, 4, get_trans_len_1},
|
||||
{0x16, "MMMMMMMMMMMMMMMM", "RESERVE",
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD,
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
|
||||
SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x17, "MMMMMMMMMMMMMMMM", "RELEASE",
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x18, "OOOOOOOO ", "COPY",
|
||||
SCST_DATA_WRITE, SCST_LONG_TIMEOUT, 2, get_trans_len_3},
|
||||
@@ -272,25 +307,39 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x24, "V VVM ", "SET WINDOW",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3},
|
||||
{0x25, "M MM M ", "READ CAPACITY",
|
||||
SCST_DATA_READ, SCST_IMPLICIT_HQ|SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_DATA_READ, SCST_IMPLICIT_HQ|
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
0, get_trans_len_read_capacity},
|
||||
{0x25, " O ", "GET WINDOW",
|
||||
SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_3},
|
||||
{0x28, "M MMMM ", "READ(10)",
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 7, get_trans_len_2},
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
7, get_trans_len_2},
|
||||
{0x28, " O ", "GET MESSAGE(10)",
|
||||
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
|
||||
{0x29, "V VV O ", "READ GENERATION",
|
||||
SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_1},
|
||||
{0x2A, "O MO M ", "WRITE(10)",
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_WRITE_MEDIUM,
|
||||
7, get_trans_len_2},
|
||||
{0x2A, " O ", "SEND MESSAGE(10)",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
|
||||
{0x2A, " O ", "SEND(10)",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 7, get_trans_len_2},
|
||||
{0x2B, " O ", "LOCATE",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x2B, " O ", "POSITION TO ELEMENT",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
{0x2B, "O OO O ", "SEEK(10)",
|
||||
@@ -305,22 +354,27 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
7, get_trans_len_2},
|
||||
{0x2F, "O OO O ", "VERIFY(10)",
|
||||
SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED,
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
7, get_trans_len_2},
|
||||
{0x33, "O OO O ", "SET LIMITS(10)",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
{0x34, " O ", "READ POSITION",
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT, 7, get_trans_len_read_pos},
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
7, get_trans_len_read_pos},
|
||||
{0x34, " O ", "GET DATA BUFFER STATUS",
|
||||
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
|
||||
{0x34, "O OO O ", "PRE-FETCH",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x35, "O OO O ", "SYNCHRONIZE CACHE",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
{0x36, "O OO O ", "LOCK UNLOCK CACHE",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
{0x37, "O O ", "READ DEFECT DATA(10)",
|
||||
SCST_DATA_READ, FLAG_NONE, 8, get_trans_len_1},
|
||||
SCST_DATA_READ, SCST_WRITE_EXCL_ALLOWED,
|
||||
8, get_trans_len_1},
|
||||
{0x37, " O ", "INIT ELEMENT STATUS WRANGE",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
{0x38, " O O ", "MEDIUM SCAN",
|
||||
@@ -350,7 +404,10 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x43, " O ", "READ TOC/PMA/ATIP",
|
||||
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
|
||||
{0x44, " M ", "REPORT DENSITY SUPPORT",
|
||||
SCST_DATA_READ, SCST_REG_RESERVE_ALLOWED, 7, get_trans_len_2},
|
||||
SCST_DATA_READ, SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
7, get_trans_len_2},
|
||||
{0x44, " O ", "READ HEADER",
|
||||
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_2},
|
||||
{0x45, " O ", "PLAY AUDIO(10)",
|
||||
@@ -370,7 +427,10 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x4C, "OOOOOOOOOOOOOOOO", "LOG SELECT",
|
||||
SCST_DATA_WRITE, SCST_SMALL_TIMEOUT, 7, get_trans_len_2},
|
||||
{0x4D, "OOOOOOOOOOOOOOOO", "LOG SENSE",
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
7, get_trans_len_2},
|
||||
{0x4E, " O ", "STOP PLAY/SCAN",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
@@ -392,7 +452,8 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD,
|
||||
0, get_trans_len_none},
|
||||
{0x57, "OOOOOOOOOOOOOOOO", "RELEASE(10)",
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_DATA_NONE, SCST_SMALL_TIMEOUT|SCST_LOCAL_CMD|
|
||||
SCST_REG_RESERVE_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x58, " O ", "REPAIR TRACK",
|
||||
SCST_DATA_NONE, SCST_WRITE_MEDIUM, 0, get_trans_len_none},
|
||||
@@ -405,9 +466,17 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x5D, " O ", "SEND CUE SHEET",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_3},
|
||||
{0x5E, "OOOOO OOOO ", "PERSISTENT RESERV IN",
|
||||
SCST_DATA_READ, FLAG_NONE, 5, get_trans_len_4},
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|
|
||||
SCST_LOCAL_CMD|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
5, get_trans_len_4},
|
||||
{0x5F, "OOOOO OOOO ", "PERSISTENT RESERV OUT",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 5, get_trans_len_4},
|
||||
SCST_DATA_WRITE, SCST_SMALL_TIMEOUT|
|
||||
SCST_LOCAL_CMD|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
5, get_trans_len_4},
|
||||
|
||||
/* 16-bytes length CDB */
|
||||
{0x80, "O OO O ", "XDWRITE EXTENDED",
|
||||
@@ -423,13 +492,28 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x84, "OOOOOOOOOOOOOOOO", "RECEIVE COPY RESULT",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 10, get_trans_len_4},
|
||||
{0x86, "OOOOOOOOOO ", "ACCESS CONTROL IN",
|
||||
SCST_DATA_NONE, SCST_REG_RESERVE_ALLOWED, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x87, "OOOOOOOOOO ", "ACCESS CONTROL OUT",
|
||||
SCST_DATA_NONE, SCST_REG_RESERVE_ALLOWED, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|
|
||||
SCST_EXCL_ACCESS_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x88, "M MMMM ", "READ(16)",
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 10, get_trans_len_4},
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
10, get_trans_len_4},
|
||||
{0x8A, "O OO O ", "WRITE(16)",
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_WRITE_MEDIUM,
|
||||
10, get_trans_len_4},
|
||||
{0x8C, "OOOOOOOOOO ", "READ ATTRIBUTE",
|
||||
SCST_DATA_READ, FLAG_NONE, 10, get_trans_len_4},
|
||||
@@ -443,15 +527,20 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED,
|
||||
10, get_trans_len_4},
|
||||
{0x90, "O OO O ", "PRE-FETCH(16)",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_WRITE_EXCL_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x91, "O OO O ", "SYNCHRONIZE CACHE(16)",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
{0x91, " M ", "SPACE(16)",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x92, "O OO O ", "LOCK UNLOCK CACHE(16)",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
{0x92, " O ", "LOCATE(16)",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
0, get_trans_len_none},
|
||||
{0x93, "O O ", "WRITE SAME(16)",
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
|
||||
10, get_trans_len_4},
|
||||
@@ -465,14 +554,17 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0xA0, "VVVVVVVVVV M ", "REPORT LUNS",
|
||||
SCST_DATA_READ, SCST_SMALL_TIMEOUT|SCST_IMPLICIT_HQ|SCST_SKIP_UA|
|
||||
SCST_FULLY_LOCAL_CMD|SCST_LOCAL_CMD|
|
||||
SCST_REG_RESERVE_ALLOWED,
|
||||
SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
|
||||
6, get_trans_len_4},
|
||||
{0xA1, " O ", "BLANK",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
{0xA3, " O ", "SEND KEY",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 8, get_trans_len_2},
|
||||
{0xA3, "OOOOO OOOO ", "REPORT DEVICE IDENTIDIER",
|
||||
SCST_DATA_READ, SCST_REG_RESERVE_ALLOWED, 6, get_trans_len_4},
|
||||
SCST_DATA_READ, SCST_REG_RESERVE_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED|SCST_EXCL_ACCESS_ALLOWED,
|
||||
6, get_trans_len_4},
|
||||
{0xA3, " M ", "MAINTENANCE(IN)",
|
||||
SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
|
||||
{0xA4, " O ", "REPORT KEY",
|
||||
@@ -490,11 +582,20 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0xA8, " O ", "GET MESSAGE(12)",
|
||||
SCST_DATA_READ, FLAG_NONE, 6, get_trans_len_4},
|
||||
{0xA8, "O OO O ", "READ(12)",
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED, 6, get_trans_len_4},
|
||||
SCST_DATA_READ, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
6, get_trans_len_4},
|
||||
{0xA9, " O ", "PLAY TRACK RELATIVE(12)",
|
||||
SCST_DATA_NONE, FLAG_NONE, 0, get_trans_len_none},
|
||||
{0xAA, "O OO O ", "WRITE(12)",
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|SCST_WRITE_MEDIUM,
|
||||
SCST_DATA_WRITE, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
SCST_TEST_IO_IN_SIRQ_ALLOWED|
|
||||
#endif
|
||||
SCST_WRITE_MEDIUM,
|
||||
6, get_trans_len_4},
|
||||
{0xAA, " O ", "SEND MESSAGE(12)",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 6, get_trans_len_4},
|
||||
@@ -509,7 +610,8 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
6, get_trans_len_4},
|
||||
{0xAF, "O OO O ", "VERIFY(12)",
|
||||
SCST_DATA_NONE, SCST_TRANSFER_LEN_TYPE_FIXED|
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED,
|
||||
SCST_VERIFY_BYTCHK_MISMATCH_ALLOWED|
|
||||
SCST_WRITE_EXCL_ALLOWED,
|
||||
6, get_trans_len_4},
|
||||
#if 0 /* No need to support at all */
|
||||
{0xB0, " OO O ", "SEARCH DATA HIGH(12)",
|
||||
@@ -528,7 +630,8 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0xB6, " M ", "SET STREAMING",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 9, get_trans_len_2},
|
||||
{0xB7, " O ", "READ DEFECT DATA(12)",
|
||||
SCST_DATA_READ, FLAG_NONE, 9, get_trans_len_1},
|
||||
SCST_DATA_READ, SCST_WRITE_EXCL_ALLOWED,
|
||||
9, get_trans_len_1},
|
||||
{0xB8, " O ", "READ ELEMENT STATUS",
|
||||
SCST_DATA_READ, FLAG_NONE, 7, get_trans_len_3_read_elem_stat},
|
||||
{0xB9, " O ", "READ CD MSF",
|
||||
@@ -574,8 +677,8 @@ static void scst_free_all_UA(struct scst_tgt_dev *tgt_dev);
|
||||
static void scst_release_space(struct scst_cmd *cmd);
|
||||
static void scst_unblock_cmds(struct scst_device *dev);
|
||||
static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev);
|
||||
static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
struct scst_acg_dev *acg_dev);
|
||||
static int scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
struct scst_acg_dev *acg_dev, struct scst_tgt_dev **out_tgt_dev);
|
||||
static void scst_tgt_retry_timer_fn(unsigned long arg);
|
||||
|
||||
#ifdef CONFIG_SCST_DEBUG_TM
|
||||
@@ -1540,7 +1643,7 @@ static void scst_check_reassign_sess(struct scst_session *sess)
|
||||
{
|
||||
struct scst_acg *acg, *old_acg;
|
||||
struct scst_acg_dev *acg_dev;
|
||||
int i;
|
||||
int i, rc;
|
||||
struct list_head *shead;
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
bool luns_changed = false;
|
||||
@@ -1592,8 +1695,10 @@ retry_add:
|
||||
TRACE_MGMT_DBG("sess %p: Allocing new tgt_dev for LUN %lld",
|
||||
sess, (unsigned long long)acg_dev->lun);
|
||||
|
||||
tgt_dev = scst_alloc_add_tgt_dev(sess, acg_dev);
|
||||
if (tgt_dev == NULL) {
|
||||
rc = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
|
||||
if (rc == -EPERM)
|
||||
continue;
|
||||
else if (rc != 0) {
|
||||
add_failed = true;
|
||||
break;
|
||||
}
|
||||
@@ -2026,7 +2131,8 @@ restart:
|
||||
return;
|
||||
}
|
||||
|
||||
bool scst_is_relative_target_port_id_unique(uint16_t id, struct scst_tgt *t)
|
||||
bool scst_is_relative_target_port_id_unique(uint16_t id,
|
||||
const struct scst_tgt *t)
|
||||
{
|
||||
bool res = true;
|
||||
struct scst_tgt_template *tgtt;
|
||||
@@ -2165,6 +2271,15 @@ int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev)
|
||||
dev->dev_double_ua_possible = 1;
|
||||
dev->queue_alg = SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER;
|
||||
|
||||
mutex_init(&dev->dev_pr_mutex);
|
||||
atomic_set(&dev->pr_readers_count, 0);
|
||||
dev->pr_generation = 0;
|
||||
dev->pr_is_set = 0;
|
||||
dev->pr_holder = NULL;
|
||||
dev->pr_scope = SCOPE_LU;
|
||||
dev->pr_type = TYPE_UNSPECIFIED;
|
||||
INIT_LIST_HEAD(&dev->dev_registrants_list);
|
||||
|
||||
scst_init_threads(&dev->dev_cmd_threads);
|
||||
|
||||
*out_dev = dev;
|
||||
@@ -2802,14 +2917,15 @@ void scst_tgt_dev_stop_threads(struct scst_tgt_dev *tgt_dev)
|
||||
* scst_mutex supposed to be held, there must not be parallel activity in this
|
||||
* session.
|
||||
*/
|
||||
static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
struct scst_acg_dev *acg_dev)
|
||||
static int scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
struct scst_acg_dev *acg_dev, struct scst_tgt_dev **out_tgt_dev)
|
||||
{
|
||||
int res = 0;
|
||||
int ini_sg, ini_unchecked_isa_dma, ini_use_clustering;
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
struct scst_device *dev = acg_dev->dev;
|
||||
struct list_head *sess_tgt_dev_list_head;
|
||||
int rc, i, sl;
|
||||
int i, sl;
|
||||
uint8_t sense_buffer[SCST_STANDARD_SENSE_LEN];
|
||||
|
||||
TRACE_ENTRY();
|
||||
@@ -2820,8 +2936,9 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
tgt_dev = kmem_cache_zalloc(scst_tgtd_cachep, GFP_KERNEL);
|
||||
#endif
|
||||
if (tgt_dev == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s",
|
||||
"Allocation of scst_tgt_dev failed");
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of scst_tgt_dev "
|
||||
"failed");
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
|
||||
@@ -2878,18 +2995,6 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic)
|
||||
__set_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
if (dev->handler->exec_atomic)
|
||||
__set_bit(SCST_TGT_DEV_AFTER_INIT_OTH_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
}
|
||||
if (dev->handler->exec_atomic) {
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic)
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RESTART_WR_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RESTART_OTH_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RX_DATA_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
}
|
||||
if (dev->handler->dev_done_atomic &&
|
||||
sess->tgt->tgtt->xmit_response_atomic) {
|
||||
@@ -2901,17 +3006,34 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
dev->d_sense, SCST_LOAD_SENSE(scst_sense_reset_UA));
|
||||
scst_alloc_set_UA(tgt_dev, sense_buffer, sl, 0);
|
||||
|
||||
rc = scst_tgt_dev_setup_threads(tgt_dev);
|
||||
if (rc != 0)
|
||||
goto out_free;
|
||||
if (sess->tgt->tgtt->get_initiator_port_transport_id == NULL) {
|
||||
if (!list_empty(&dev->dev_registrants_list)) {
|
||||
PRINT_WARNING("Initiators from target %s can't connect "
|
||||
"to device %s, because the device has PR "
|
||||
"registrants and the target doesn't support "
|
||||
"Persistent Reservations", sess->tgt->tgtt->name,
|
||||
dev->virt_name);
|
||||
res = -EPERM;
|
||||
goto out_free;
|
||||
}
|
||||
dev->not_pr_supporting_tgt_devs_num++;
|
||||
}
|
||||
|
||||
res = scst_pr_init_tgt_dev(tgt_dev);
|
||||
if (res != 0)
|
||||
goto out_dec_free;
|
||||
|
||||
res = scst_tgt_dev_setup_threads(tgt_dev);
|
||||
if (res != 0)
|
||||
goto out_pr_clear;
|
||||
|
||||
if (dev->handler && dev->handler->attach_tgt) {
|
||||
TRACE_DBG("Calling dev handler's attach_tgt(%p)", tgt_dev);
|
||||
rc = dev->handler->attach_tgt(tgt_dev);
|
||||
res = dev->handler->attach_tgt(tgt_dev);
|
||||
TRACE_DBG("%s", "Dev handler's attach_tgt() returned");
|
||||
if (rc != 0) {
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Device handler's %s attach_tgt() "
|
||||
"failed: %d", dev->handler->name, rc);
|
||||
"failed: %d", dev->handler->name, res);
|
||||
goto out_stop_threads;
|
||||
}
|
||||
}
|
||||
@@ -2927,18 +3049,25 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
list_add_tail(&tgt_dev->sess_tgt_dev_list_entry,
|
||||
sess_tgt_dev_list_head);
|
||||
|
||||
*out_tgt_dev = tgt_dev;
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return tgt_dev;
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_stop_threads:
|
||||
scst_tgt_dev_stop_threads(tgt_dev);
|
||||
|
||||
out_pr_clear:
|
||||
scst_pr_clear_tgt_dev(tgt_dev);
|
||||
|
||||
out_dec_free:
|
||||
if (tgt_dev->sess->tgt->tgtt->get_initiator_port_transport_id == NULL)
|
||||
dev->not_pr_supporting_tgt_devs_num--;
|
||||
|
||||
out_free:
|
||||
scst_free_all_UA(tgt_dev);
|
||||
|
||||
kmem_cache_free(scst_tgtd_cachep, tgt_dev);
|
||||
tgt_dev = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2983,7 +3112,11 @@ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev)
|
||||
|
||||
list_del(&tgt_dev->sess_tgt_dev_list_entry);
|
||||
|
||||
if (tgt_dev->sess->tgt->tgtt->get_initiator_port_transport_id == NULL)
|
||||
dev->not_pr_supporting_tgt_devs_num--;
|
||||
|
||||
scst_clear_reservation(tgt_dev);
|
||||
scst_pr_clear_tgt_dev(tgt_dev);
|
||||
scst_free_all_UA(tgt_dev);
|
||||
|
||||
if (dev->handler && dev->handler->detach_tgt) {
|
||||
@@ -3014,11 +3147,11 @@ int scst_sess_alloc_tgt_devs(struct scst_session *sess)
|
||||
|
||||
list_for_each_entry(acg_dev, &sess->acg->acg_dev_list,
|
||||
acg_dev_list_entry) {
|
||||
tgt_dev = scst_alloc_add_tgt_dev(sess, acg_dev);
|
||||
if (tgt_dev == NULL) {
|
||||
res = -ENOMEM;
|
||||
res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
|
||||
if (res == -EPERM)
|
||||
continue;
|
||||
else if (res != 0)
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -3083,11 +3216,12 @@ int scst_acg_add_dev(struct scst_acg *acg, struct scst_device *dev,
|
||||
list_add_tail(&acg_dev->dev_acg_dev_list_entry, &dev->dev_acg_dev_list);
|
||||
|
||||
list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
|
||||
tgt_dev = scst_alloc_add_tgt_dev(sess, acg_dev);
|
||||
if (tgt_dev == NULL) {
|
||||
res = -ENOMEM;
|
||||
res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev);
|
||||
if (res == -EPERM)
|
||||
continue;
|
||||
else if (res != 0)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
|
||||
&tmp_tgt_dev_list);
|
||||
}
|
||||
@@ -3646,6 +3780,8 @@ void scst_free_session(struct scst_session *sess)
|
||||
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
kfree(sess->transport_id);
|
||||
|
||||
scst_sess_sysfs_put(sess); /* must not be called under scst_mutex */
|
||||
|
||||
TRACE_EXIT();
|
||||
@@ -3984,7 +4120,7 @@ int scst_alloc_request(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = 0;
|
||||
struct scsi_request *req;
|
||||
int gm = scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL;
|
||||
int gm = GFP_KERNEL;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -4315,7 +4451,7 @@ int scst_scsi_exec_async(struct scst_cmd *cmd,
|
||||
struct request *rq;
|
||||
struct scsi_io_context *sioc;
|
||||
int write = (cmd->data_direction & SCST_DATA_WRITE) ? WRITE : READ;
|
||||
gfp_t gfp = scst_cmd_atomic(cmd) ? GFP_ATOMIC : GFP_KERNEL;
|
||||
gfp_t gfp = GFP_KERNEL;
|
||||
int cmd_len = cmd->cdb_len;
|
||||
|
||||
if (cmd->ext_cdb_len == 0) {
|
||||
@@ -4477,6 +4613,95 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_copy_sg);
|
||||
|
||||
int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
EXTRACHECKS_BUG_ON(cmd->sg_buff_vmallocated);
|
||||
|
||||
if (scst_get_buf_count(cmd) > 1) {
|
||||
int len;
|
||||
uint8_t *tmp_buf;
|
||||
int full_size;
|
||||
|
||||
full_size = 0;
|
||||
len = scst_get_buf_first(cmd, &tmp_buf);
|
||||
while (len > 0) {
|
||||
full_size += len;
|
||||
scst_put_buf(cmd, tmp_buf);
|
||||
len = scst_get_buf_next(cmd, &tmp_buf);
|
||||
}
|
||||
|
||||
*buf = vmalloc(full_size);
|
||||
if (*buf == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "vmalloc() failed for opcode "
|
||||
"%x", cmd->cdb[0]);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
cmd->sg_buff_vmallocated = 1;
|
||||
|
||||
if (scst_cmd_get_data_direction(cmd) == SCST_DATA_WRITE) {
|
||||
uint8_t *buf_ptr;
|
||||
|
||||
buf_ptr = *buf;
|
||||
|
||||
len = scst_get_buf_first(cmd, &tmp_buf);
|
||||
while (len > 0) {
|
||||
memcpy(buf_ptr, tmp_buf, len);
|
||||
buf_ptr += len;
|
||||
|
||||
scst_put_buf(cmd, tmp_buf);
|
||||
len = scst_get_buf_next(cmd, &tmp_buf);
|
||||
}
|
||||
}
|
||||
res = full_size;
|
||||
} else
|
||||
res = scst_get_buf_first(cmd, buf);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (buf == NULL)
|
||||
goto out;
|
||||
|
||||
if (cmd->sg_buff_vmallocated) {
|
||||
if (scst_cmd_get_data_direction(cmd) == SCST_DATA_READ) {
|
||||
int len;
|
||||
uint8_t *tmp_buf, *buf_p;
|
||||
|
||||
buf_p = buf;
|
||||
|
||||
len = scst_get_buf_first(cmd, &tmp_buf);
|
||||
while (len > 0) {
|
||||
memcpy(tmp_buf, buf_p, len);
|
||||
buf_p += len;
|
||||
|
||||
scst_put_buf(cmd, tmp_buf);
|
||||
len = scst_get_buf_next(cmd, &tmp_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cmd->sg_buff_vmallocated = 0;
|
||||
|
||||
vfree(buf);
|
||||
} else
|
||||
scst_put_buf(cmd, buf);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
static const int SCST_CDB_LENGTH[8] = { 6, 10, 10, -1, 16, 12, -1, -1 };
|
||||
|
||||
#define SCST_CDB_GROUP(opcode) ((opcode >> 5) & 0x7)
|
||||
@@ -4584,14 +4809,16 @@ static int get_trans_len_prevent_allow_medium_removal(struct scst_cmd *cmd,
|
||||
uint8_t off)
|
||||
{
|
||||
if ((cmd->cdb[4] & 3) == 0)
|
||||
cmd->op_flags |= SCST_REG_RESERVE_ALLOWED;
|
||||
cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
|
||||
SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_trans_len_start_stop(struct scst_cmd *cmd, uint8_t off)
|
||||
{
|
||||
if ((cmd->cdb[4] & 0xF1) == 0x1)
|
||||
cmd->op_flags |= SCST_REG_RESERVE_ALLOWED;
|
||||
cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
|
||||
SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4605,8 +4832,8 @@ static int get_trans_len_3_read_elem_stat(struct scst_cmd *cmd, uint8_t off)
|
||||
cmd->bufflen |= ((u32)p[2]);
|
||||
|
||||
if ((cmd->cdb[6] & 0x2) == 0x2)
|
||||
cmd->op_flags |= SCST_REG_RESERVE_ALLOWED;
|
||||
|
||||
cmd->op_flags |= SCST_REG_RESERVE_ALLOWED |
|
||||
SCST_WRITE_EXCL_ALLOWED | SCST_EXCL_ACCESS_ALLOWED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6414,6 +6641,88 @@ int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun)
|
||||
}
|
||||
EXPORT_SYMBOL(scst_get_max_lun_commands);
|
||||
|
||||
/**
|
||||
* scst_reassign_persistent_sess_states() - reassigns persistent states
|
||||
*
|
||||
* Reassigns persistent states from old_sess to new_sess.
|
||||
*/
|
||||
void scst_reassign_persistent_sess_states(struct scst_session *new_sess,
|
||||
struct scst_session *old_sess)
|
||||
{
|
||||
struct scst_device *dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Reassigning persistent states from old_sess %p to "
|
||||
"new_sess %p", old_sess, new_sess);
|
||||
|
||||
if ((new_sess == NULL) || (old_sess == NULL)) {
|
||||
TRACE_DBG("%s", "new_sess or old_sess is NULL");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((new_sess->transport_id == NULL) ||
|
||||
(old_sess->transport_id == NULL)) {
|
||||
TRACE_DBG("%s", "new_sess or old_sess doesn't support PRs");
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
struct scst_tgt_dev *new_tgt_dev = NULL, *old_tgt_dev = NULL;
|
||||
|
||||
TRACE_DBG("Processing dev %s", dev->virt_name);
|
||||
|
||||
list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
|
||||
dev_tgt_dev_list_entry) {
|
||||
if (tgt_dev->sess == new_sess) {
|
||||
new_tgt_dev = tgt_dev;
|
||||
if (old_tgt_dev != NULL)
|
||||
break;
|
||||
}
|
||||
if (tgt_dev->sess == old_sess) {
|
||||
old_tgt_dev = tgt_dev;
|
||||
if (new_tgt_dev != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((new_tgt_dev == NULL) || (old_tgt_dev == NULL)) {
|
||||
TRACE_DBG("new_tgt_dev %p or old_sess %p is NULL, "
|
||||
"skipping (dev %s)", new_tgt_dev, old_tgt_dev,
|
||||
dev->virt_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
scst_pr_write_lock(dev);
|
||||
|
||||
if (old_tgt_dev->registrant != NULL) {
|
||||
TRACE_PR("Reassigning reg %p from tgt_dev %p to %p",
|
||||
old_tgt_dev->registrant, old_tgt_dev,
|
||||
new_tgt_dev);
|
||||
|
||||
if (new_tgt_dev->registrant != NULL)
|
||||
new_tgt_dev->registrant->tgt_dev = NULL;
|
||||
|
||||
new_tgt_dev->registrant = old_tgt_dev->registrant;
|
||||
new_tgt_dev->registrant->tgt_dev = new_tgt_dev;
|
||||
|
||||
old_tgt_dev->registrant = NULL;
|
||||
}
|
||||
|
||||
scst_pr_write_unlock(dev);
|
||||
}
|
||||
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_reassign_persistent_sess_states);
|
||||
|
||||
/**
|
||||
* scst_get_next_lexem() - parse and return next lexem in the string
|
||||
*
|
||||
|
||||
+40
-27
@@ -33,6 +33,7 @@
|
||||
#include "scst.h"
|
||||
#include "scst_priv.h"
|
||||
#include "scst_mem.h"
|
||||
#include "scst_pres.h"
|
||||
|
||||
#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G)
|
||||
#warning "HIGHMEM kernel configurations are fully supported, but not\
|
||||
@@ -214,6 +215,10 @@ int __scst_register_target_template(struct scst_tgt_template *vtt,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (vtt->get_initiator_port_transport_id == NULL)
|
||||
PRINT_WARNING("Target driver %s doesn't support Persistent "
|
||||
"Reservations", vtt->name);
|
||||
|
||||
if (vtt->threads_num < 0) {
|
||||
PRINT_ERROR("Wrong threads_num value %d for "
|
||||
"target \"%s\"", vtt->threads_num,
|
||||
@@ -223,13 +228,12 @@ int __scst_register_target_template(struct scst_tgt_template *vtt,
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
if (!vtt->enable_target || !vtt->is_target_enabled) {
|
||||
if (!vtt->enable_target || !vtt->is_target_enabled)
|
||||
PRINT_WARNING("Target driver %s doesn't have enable_target() "
|
||||
"and/or is_target_enabled() method(s). This is unsafe "
|
||||
"and can lead that initiators connected on the "
|
||||
"initialization time can see an unexpected set of "
|
||||
"devices or no devices at all!", vtt->name);
|
||||
}
|
||||
|
||||
if (((vtt->add_target != NULL) && (vtt->del_target == NULL)) ||
|
||||
((vtt->add_target == NULL) && (vtt->del_target != NULL))) {
|
||||
@@ -333,7 +337,7 @@ void scst_unregister_target_template(struct scst_tgt_template *vtt)
|
||||
restart:
|
||||
list_for_each_entry(tgt, &vtt->tgt_list, tgt_list_entry) {
|
||||
mutex_unlock(&scst_mutex);
|
||||
scst_unregister(tgt);
|
||||
scst_unregister_target(tgt);
|
||||
mutex_lock(&scst_mutex);
|
||||
goto restart;
|
||||
}
|
||||
@@ -365,7 +369,7 @@ EXPORT_SYMBOL(scst_unregister_target_template);
|
||||
* Registers a target for template vtt and returns new target structure on
|
||||
* success or NULL otherwise.
|
||||
*/
|
||||
struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
|
||||
struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
|
||||
const char *target_name)
|
||||
{
|
||||
struct scst_tgt *tgt;
|
||||
@@ -391,6 +395,7 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
|
||||
int len = strlen(target_name) +
|
||||
strlen(SCST_DEFAULT_ACG_NAME) + 1 + 1;
|
||||
|
||||
|
||||
tgt->default_group_name = kmalloc(len, GFP_KERNEL);
|
||||
if (tgt->default_group_name == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "Allocation of default "
|
||||
@@ -505,7 +510,7 @@ out_err:
|
||||
vtt->name, rc);
|
||||
goto out;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_register);
|
||||
EXPORT_SYMBOL(scst_register_target);
|
||||
|
||||
static inline int test_sess_list(struct scst_tgt *tgt)
|
||||
{
|
||||
@@ -519,7 +524,7 @@ static inline int test_sess_list(struct scst_tgt *tgt)
|
||||
/**
|
||||
* scst_unregister_target() - unregister target
|
||||
*/
|
||||
void scst_unregister(struct scst_tgt *tgt)
|
||||
void scst_unregister_target(struct scst_tgt *tgt)
|
||||
{
|
||||
struct scst_session *sess;
|
||||
struct scst_tgt_template *vtt = tgt->tgtt;
|
||||
@@ -585,7 +590,7 @@ again:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_unregister);
|
||||
EXPORT_SYMBOL(scst_unregister_target);
|
||||
|
||||
static int scst_susp_wait(bool interruptible)
|
||||
{
|
||||
@@ -956,14 +961,6 @@ static int scst_dev_handler_check(struct scst_dev_type *dev_handler)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dev_handler->exec == NULL) {
|
||||
#ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
|
||||
dev_handler->exec_atomic = 1;
|
||||
#else
|
||||
dev_handler->exec_atomic = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dev_handler->alloc_data_buf == NULL)
|
||||
dev_handler->alloc_data_buf_atomic = 1;
|
||||
|
||||
@@ -1009,14 +1006,6 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
|
||||
if (strcmp(dev->virt_name, dev_name) == 0) {
|
||||
PRINT_ERROR("Device %s already exists", dev_name);
|
||||
res = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
res = scst_suspend_activity(true);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
@@ -1026,6 +1015,14 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
goto out_resume;
|
||||
}
|
||||
|
||||
list_for_each_entry(dev, &scst_dev_list, dev_list_entry) {
|
||||
if (strcmp(dev->virt_name, dev_name) == 0) {
|
||||
PRINT_ERROR("Device %s already exists", dev_name);
|
||||
res = -EEXIST;
|
||||
goto out_up;
|
||||
}
|
||||
}
|
||||
|
||||
res = scst_alloc_device(GFP_KERNEL, &dev);
|
||||
if (res != 0)
|
||||
goto out_up;
|
||||
@@ -1051,12 +1048,18 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
goto out_free_del;
|
||||
}
|
||||
|
||||
rc = scst_assign_dev_handler(dev, dev_handler);
|
||||
rc = scst_pr_init_dev(dev);
|
||||
if (rc != 0) {
|
||||
res = rc;
|
||||
goto out_free_del;
|
||||
}
|
||||
|
||||
rc = scst_assign_dev_handler(dev, dev_handler);
|
||||
if (rc != 0) {
|
||||
res = rc;
|
||||
goto out_pr_clear_dev;
|
||||
}
|
||||
|
||||
out_up:
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
@@ -1073,6 +1076,9 @@ out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_pr_clear_dev:
|
||||
scst_pr_clear_dev(dev);
|
||||
|
||||
out_free_del:
|
||||
list_del(&dev->dev_list_entry);
|
||||
|
||||
@@ -1117,6 +1123,8 @@ void scst_unregister_virtual_device(int id)
|
||||
scst_acg_remove_dev(acg_dev->acg, dev, true);
|
||||
}
|
||||
|
||||
scst_pr_clear_dev(dev);
|
||||
|
||||
scst_assign_dev_handler(dev, &scst_null_devtype);
|
||||
|
||||
PRINT_INFO("Detached from virtual device %s (id %d)",
|
||||
@@ -1773,6 +1781,7 @@ static void scst_stop_all_threads(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* It does NOT stop ran threads on error! */
|
||||
static int scst_start_all_threads(int num)
|
||||
{
|
||||
int res;
|
||||
@@ -1969,14 +1978,14 @@ static void __init scst_print_config(void)
|
||||
(j == i) ? "" : ", ");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
i += snprintf(&buf[i], sizeof(buf) - i,
|
||||
"%sALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ",
|
||||
"%sTEST_IO_IN_SIRQ",
|
||||
(j == i) ? "" : ", ");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_STRICT_SECURITY
|
||||
i += snprintf(&buf[i], sizeof(buf) - i, "%sSCST_STRICT_SECURITY",
|
||||
i += snprintf(&buf[i], sizeof(buf) - i, "%sSTRICT_SECURITY",
|
||||
(j == i) ? "" : ", ");
|
||||
#endif
|
||||
|
||||
@@ -2190,6 +2199,10 @@ static int __init init_scst(void)
|
||||
res = scst_proc_init_module();
|
||||
if (res != 0)
|
||||
goto out_thread_free;
|
||||
#else
|
||||
res = scst_pr_check_pr_path();
|
||||
if (res != 0)
|
||||
goto out_thread_free;
|
||||
#endif
|
||||
|
||||
PRINT_INFO("SCST version %s loaded successfully (max mem for "
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* scst_pres.c
|
||||
*
|
||||
* Copyright (C) 2009 - 2010 Alexey Obitotskiy <alexeyo1@open-e.com>
|
||||
* Copyright (C) 2009 - 2010 Open-E, Inc.
|
||||
* Copyright (C) 2009 - 2010 Vladislav Bolkhovitin <vst@vlnb.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, version 2
|
||||
* of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef SCST_PRES_H_
|
||||
#define SCST_PRES_H_
|
||||
|
||||
#define PR_REGISTER 0x00
|
||||
#define PR_RESERVE 0x01
|
||||
#define PR_RELEASE 0x02
|
||||
#define PR_CLEAR 0x03
|
||||
#define PR_PREEMPT 0x04
|
||||
#define PR_PREEMPT_AND_ABORT 0x05
|
||||
#define PR_REGISTER_AND_IGNORE 0x06
|
||||
#define PR_REGISTER_AND_MOVE 0x07
|
||||
|
||||
#define PR_READ_KEYS 0x00
|
||||
#define PR_READ_RESERVATION 0x01
|
||||
#define PR_REPORT_CAPS 0x02
|
||||
#define PR_READ_FULL_STATUS 0x03
|
||||
|
||||
#define TYPE_UNSPECIFIED (-1)
|
||||
#define TYPE_WRITE_EXCLUSIVE 0x01
|
||||
#define TYPE_EXCLUSIVE_ACCESS 0x03
|
||||
#define TYPE_WRITE_EXCLUSIVE_REGONLY 0x05
|
||||
#define TYPE_EXCLUSIVE_ACCESS_REGONLY 0x06
|
||||
#define TYPE_WRITE_EXCLUSIVE_ALL_REG 0x07
|
||||
#define TYPE_EXCLUSIVE_ACCESS_ALL_REG 0x08
|
||||
|
||||
#define SCOPE_LU 0x00
|
||||
|
||||
static inline bool scst_pr_type_valid(uint8_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case TYPE_WRITE_EXCLUSIVE:
|
||||
case TYPE_EXCLUSIVE_ACCESS:
|
||||
case TYPE_WRITE_EXCLUSIVE_REGONLY:
|
||||
case TYPE_EXCLUSIVE_ACCESS_REGONLY:
|
||||
case TYPE_WRITE_EXCLUSIVE_ALL_REG:
|
||||
case TYPE_EXCLUSIVE_ACCESS_ALL_REG:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
int scst_pr_check_pr_path(void);
|
||||
#endif
|
||||
|
||||
static inline bool scst_pr_read_lock(struct scst_device *dev)
|
||||
{
|
||||
bool unlock = false;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
atomic_inc(&dev->pr_readers_count);
|
||||
smp_mb__after_atomic_inc(); /* to sync with scst_pr_write_lock() */
|
||||
|
||||
if (unlikely(dev->pr_writer_active)) {
|
||||
unlock = true;
|
||||
atomic_dec(&dev->pr_readers_count);
|
||||
mutex_lock(&dev->dev_pr_mutex);
|
||||
}
|
||||
|
||||
TRACE_EXIT_RES(unlock);
|
||||
return unlock;
|
||||
}
|
||||
|
||||
static inline void scst_pr_read_unlock(struct scst_device *dev, bool unlock)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (unlikely(unlock))
|
||||
mutex_unlock(&dev->dev_pr_mutex);
|
||||
else {
|
||||
/*
|
||||
* To sync with scst_pr_write_lock(). We need it to ensure
|
||||
* order of our reads with the writer's writes.
|
||||
*/
|
||||
smp_mb__before_atomic_dec();
|
||||
atomic_dec(&dev->pr_readers_count);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void scst_pr_write_lock(struct scst_device *dev)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
mutex_lock(&dev->dev_pr_mutex);
|
||||
|
||||
dev->pr_writer_active = 1;
|
||||
|
||||
/* to sync with scst_pr_read_lock() and unlock() */
|
||||
smp_mb();
|
||||
|
||||
while (atomic_read(&dev->pr_readers_count) != 0) {
|
||||
TRACE_DBG("Waiting for %d readers (dev %p)",
|
||||
atomic_read(&dev->pr_readers_count), dev);
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void scst_pr_write_unlock(struct scst_device *dev)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev->pr_writer_active = 0;
|
||||
|
||||
mutex_unlock(&dev->dev_pr_mutex);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
int scst_pr_init_dev(struct scst_device *dev);
|
||||
void scst_pr_clear_dev(struct scst_device *dev);
|
||||
|
||||
int scst_pr_init_tgt_dev(struct scst_tgt_dev *tgt_dev);
|
||||
void scst_pr_clear_tgt_dev(struct scst_tgt_dev *tgt_dev);
|
||||
|
||||
bool scst_pr_crh_case(struct scst_cmd *cmd);
|
||||
bool scst_pr_is_cmd_allowed(struct scst_cmd *cmd);
|
||||
|
||||
void scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
|
||||
void scst_pr_register_and_ignore(struct scst_cmd *cmd, uint8_t *buffer,
|
||||
int buffer_size);
|
||||
void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
|
||||
int buffer_size);
|
||||
void scst_pr_reserve(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
|
||||
void scst_pr_release(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
|
||||
void scst_pr_clear(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
|
||||
void scst_pr_preempt(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
|
||||
void scst_pr_preempt_and_abort(struct scst_cmd *cmd, uint8_t *buffer,
|
||||
int buffer_size);
|
||||
|
||||
void scst_pr_read_keys(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
|
||||
void scst_pr_read_reservation(struct scst_cmd *cmd, uint8_t *buffer,
|
||||
int buffer_size);
|
||||
void scst_pr_report_caps(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size);
|
||||
void scst_pr_read_full_status(struct scst_cmd *cmd, uint8_t *buffer,
|
||||
int buffer_size);
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
void scst_pr_sync_device_file(struct scst_tgt_dev *tgt_dev, struct scst_cmd *cmd);
|
||||
#endif
|
||||
|
||||
#endif /* SCST_PRES_H_ */
|
||||
+11
-3
@@ -108,7 +108,7 @@ extern unsigned long scst_trace_flag;
|
||||
**/
|
||||
#define SCST_CMD_STATE_RES_CONT_NEXT SCST_EXEC_COMPLETED
|
||||
#define SCST_CMD_STATE_RES_CONT_SAME SCST_EXEC_NOT_COMPLETED
|
||||
#define SCST_CMD_STATE_RES_NEED_THREAD SCST_EXEC_NEED_THREAD
|
||||
#define SCST_CMD_STATE_RES_NEED_THREAD (SCST_EXEC_NOT_COMPLETED+1)
|
||||
|
||||
/**
|
||||
** Maximum count of uncompleted commands that an initiator could
|
||||
@@ -197,6 +197,10 @@ static inline bool scst_set_io_context(struct scst_cmd *cmd,
|
||||
{
|
||||
bool res;
|
||||
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (cmd->cmd_threads == &scst_main_cmd_threads) {
|
||||
EXTRACHECKS_BUG_ON(in_interrupt());
|
||||
/*
|
||||
@@ -414,6 +418,9 @@ int scst_alloc_space(struct scst_cmd *cmd);
|
||||
int scst_lib_init(void);
|
||||
void scst_lib_exit(void);
|
||||
|
||||
int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf);
|
||||
void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf);
|
||||
|
||||
uint64_t scst_pack_lun(const uint64_t lun, unsigned int addr_method);
|
||||
uint64_t scst_unpack_lun(const uint8_t *lun, int len);
|
||||
|
||||
@@ -567,7 +574,7 @@ int scst_set_pending_UA(struct scst_cmd *cmd);
|
||||
void scst_report_luns_changed(struct scst_acg *acg);
|
||||
|
||||
void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
|
||||
int other_ini, int call_dev_task_mgmt_fn);
|
||||
bool other_ini, bool call_dev_task_mgmt_fn);
|
||||
void scst_process_reset(struct scst_device *dev,
|
||||
struct scst_session *originator, struct scst_cmd *exclude_cmd,
|
||||
struct scst_mgmt_cmd *mcmd, bool setUA);
|
||||
@@ -732,8 +739,9 @@ static inline int scst_sn_before(uint32_t seq1, uint32_t seq2)
|
||||
return (int32_t)(seq1-seq2) < 0;
|
||||
}
|
||||
|
||||
bool scst_is_relative_target_port_id_unique(uint16_t id, struct scst_tgt *t);
|
||||
int gen_relative_target_port_id(uint16_t *id);
|
||||
bool scst_is_relative_target_port_id_unique(uint16_t id,
|
||||
const struct scst_tgt *t);
|
||||
|
||||
#ifdef CONFIG_SCST_MEASURE_LATENCY
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ static struct scst_trace_log scst_proc_trace_tbl[] = {
|
||||
{ TRACE_MGMT, "mgmt" },
|
||||
{ TRACE_MGMT_DEBUG, "mgmt_dbg" },
|
||||
{ TRACE_FLOW_CONTROL, "flow_control" },
|
||||
{ TRACE_PRES, "pr" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
@@ -2311,12 +2312,12 @@ static int scst_version_info_show(struct seq_file *seq, void *v)
|
||||
seq_printf(seq, "USE_EXPECTED_VALUES\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
|
||||
seq_printf(seq, "ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ\n");
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
seq_printf(seq, "TEST_IO_IN_SIRQ\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_STRICT_SECURITY
|
||||
seq_printf(seq, "SCST_STRICT_SECURITY\n");
|
||||
seq_printf(seq, "STRICT_SECURITY\n");
|
||||
#endif
|
||||
|
||||
TRACE_EXIT();
|
||||
|
||||
@@ -85,6 +85,7 @@ static struct scst_trace_log scst_trace_tbl[] = {
|
||||
{ TRACE_MGMT, "mgmt" },
|
||||
{ TRACE_MGMT_DEBUG, "mgmt_dbg" },
|
||||
{ TRACE_FLOW_CONTROL, "flow_control" },
|
||||
{ TRACE_PRES, "pr" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
@@ -694,7 +695,7 @@ int scst_create_tgt_sysfs(struct scst_tgt *tgt)
|
||||
|
||||
retval = sysfs_create_file(tgt->tgt_luns_kobj, &scst_luns_mgmt.attr);
|
||||
if (retval != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_luns_mgmt.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
}
|
||||
@@ -710,7 +711,7 @@ int scst_create_tgt_sysfs(struct scst_tgt *tgt)
|
||||
retval = sysfs_create_file(tgt->tgt_ini_grp_kobj,
|
||||
&scst_ini_group_mgmt.attr);
|
||||
if (retval != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||
scst_ini_group_mgmt.attr.name, tgt->tgt_name);
|
||||
goto out;
|
||||
}
|
||||
@@ -2445,7 +2446,7 @@ static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
|
||||
if (res != 0)
|
||||
goto out_err;
|
||||
|
||||
TRACE_DBG("Try to set relative target port id %d",
|
||||
TRACE_DBG("Trying to set relative target port id %d",
|
||||
(uint16_t)rel_tgt_id);
|
||||
|
||||
if (rel_tgt_id < SCST_MIN_REL_TGT_ID ||
|
||||
@@ -3051,7 +3052,7 @@ static ssize_t scst_trace_level_show(const struct scst_trace_log *local_tbl,
|
||||
#endif
|
||||
" special, scsi, mgmt, minor,\n"
|
||||
" mgmt_dbg, scsi_serializing,\n"
|
||||
" retry, recv_bot, send_bot, recv_top,\n"
|
||||
" retry, recv_bot, send_bot, recv_top, pr\n"
|
||||
" send_top%s]", help != NULL ? help : "");
|
||||
|
||||
return pos;
|
||||
@@ -3288,12 +3289,12 @@ static ssize_t scst_version_show(struct kobject *kobj,
|
||||
strcat(buf, "USE_EXPECTED_VALUES\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
|
||||
strcat(buf, "ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ\n");
|
||||
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
|
||||
strcat(buf, "TEST_IO_IN_SIRQ\n");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCST_STRICT_SECURITY
|
||||
strcat(buf, "SCST_STRICT_SECURITY\n");
|
||||
strcat(buf, "STRICT_SECURITY\n");
|
||||
#endif
|
||||
|
||||
TRACE_EXIT();
|
||||
|
||||
+606
-244
File diff suppressed because it is too large
Load Diff
@@ -644,7 +644,7 @@ static void scst_local_release_adapter(struct device *dev)
|
||||
if (scst_lcl_host->session[i])
|
||||
scst_unregister_session(
|
||||
scst_lcl_host->session[i], TRUE, NULL);
|
||||
scst_unregister(scst_lcl_host->target);
|
||||
scst_unregister_target(scst_lcl_host->target);
|
||||
kfree(scst_lcl_host);
|
||||
}
|
||||
|
||||
@@ -683,7 +683,8 @@ static int scst_local_add_adapter(void)
|
||||
* Register a target with SCST and add a session
|
||||
*/
|
||||
sprintf(name, "scstlcltgt%d", scst_local_add_host);
|
||||
scst_lcl_host->target = scst_register(&scst_local_targ_tmpl, name);
|
||||
scst_lcl_host->target = scst_register_target(&scst_local_targ_tmpl,
|
||||
name);
|
||||
if (!scst_lcl_host) {
|
||||
printk(KERN_WARNING "scst_register_target failed:\n");
|
||||
error = -1;
|
||||
@@ -697,7 +698,7 @@ static int scst_local_add_adapter(void)
|
||||
sprintf(name, "scstlclhst%d:%d", scst_local_add_host, i);
|
||||
scst_lcl_host->session[i] = scst_register_session(
|
||||
scst_lcl_host->target,
|
||||
0, name, NULL, NULL);
|
||||
0, name, NULL, NULL, NULL);
|
||||
if (!scst_lcl_host->session[i]) {
|
||||
printk(KERN_WARNING "scst_register_session failed:\n");
|
||||
error = -1;
|
||||
@@ -732,7 +733,7 @@ unregister_session:
|
||||
TRUE, NULL);
|
||||
}
|
||||
unregister_target:
|
||||
scst_unregister(scst_lcl_host->target);
|
||||
scst_unregister_target(scst_lcl_host->target);
|
||||
cleanup:
|
||||
kfree(scst_lcl_host);
|
||||
TRACE_EXIT();
|
||||
|
||||
+7
-13
@@ -2137,7 +2137,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
|
||||
|
||||
BUG_ON(!sdev->scst_tgt);
|
||||
ch->scst_sess = scst_register_session(sdev->scst_tgt, 0, ch->sess_name,
|
||||
NULL, NULL);
|
||||
ch, NULL, NULL);
|
||||
if (!ch->scst_sess) {
|
||||
rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
|
||||
TRACE_DBG("%s", "Failed to create scst sess");
|
||||
@@ -2147,8 +2147,6 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
|
||||
TRACE_DBG("Establish connection sess=%p name=%s cm_id=%p",
|
||||
ch->scst_sess, ch->sess_name, ch->cm_id);
|
||||
|
||||
scst_sess_set_tgt_priv(ch->scst_sess, ch);
|
||||
|
||||
/* create srp_login_response */
|
||||
rsp->opcode = SRP_LOGIN_RSP;
|
||||
rsp->tag = req->tag;
|
||||
@@ -2775,11 +2773,7 @@ static int srpt_xmit_response(struct scst_cmd *scmnd)
|
||||
int resp_len;
|
||||
enum srpt_command_state prev_state;
|
||||
|
||||
if (unlikely(scst_cmd_atomic(scmnd))) {
|
||||
TRACE_DBG("%s", "Switching to thread context.");
|
||||
ret = SCST_TGT_RES_NEED_THREAD_CTX;
|
||||
goto out;
|
||||
}
|
||||
EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd));
|
||||
|
||||
ioctx = scst_cmd_get_tgt_priv(scmnd);
|
||||
BUG_ON(!ioctx);
|
||||
@@ -2971,8 +2965,8 @@ static int srpt_detect(struct scst_tgt_template *tp)
|
||||
/**
|
||||
* srpt_release() - SCST release callback function.
|
||||
*
|
||||
* Callback function called by the SCST core from scst_unregister() to free up
|
||||
* the resources associated with device scst_tgt.
|
||||
* Callback function called by the SCST core from scst_unregister_target() to
|
||||
* free up the resources associated with device scst_tgt.
|
||||
*/
|
||||
static int srpt_release(struct scst_tgt *scst_tgt)
|
||||
{
|
||||
@@ -3157,7 +3151,7 @@ static void srpt_add_one(struct ib_device *device)
|
||||
if (!sdev)
|
||||
return;
|
||||
|
||||
sdev->scst_tgt = scst_register(&srpt_template, NULL);
|
||||
sdev->scst_tgt = scst_register_target(&srpt_template, NULL);
|
||||
if (!sdev->scst_tgt) {
|
||||
PRINT_ERROR("SCST registration failed for %s.",
|
||||
sdev->device->name);
|
||||
@@ -3306,7 +3300,7 @@ err_dev:
|
||||
device_unregister(&sdev->dev);
|
||||
#endif
|
||||
unregister_tgt:
|
||||
scst_unregister(sdev->scst_tgt);
|
||||
scst_unregister_target(sdev->scst_tgt);
|
||||
free_dev:
|
||||
kfree(sdev);
|
||||
|
||||
@@ -3366,7 +3360,7 @@ static void srpt_remove_one(struct ib_device *device)
|
||||
* such that no new SRP_LOGIN_REQ information units can arrive while
|
||||
* destroying the SCST target.
|
||||
*/
|
||||
scst_unregister(sdev->scst_tgt);
|
||||
scst_unregister_target(sdev->scst_tgt);
|
||||
sdev->scst_tgt = NULL;
|
||||
|
||||
srpt_free_ioctx_ring(sdev, sdev->ioctx_ring,
|
||||
|
||||
+12
-9
@@ -646,6 +646,7 @@ static int do_tm(struct vdisk_cmd *vcmd)
|
||||
{
|
||||
struct scst_user_get_cmd *cmd = vcmd->cmd;
|
||||
struct scst_user_reply_cmd *reply = vcmd->reply;
|
||||
struct vdisk_dev *dev = vcmd->dev;
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
@@ -659,6 +660,16 @@ static int do_tm(struct vdisk_cmd *vcmd)
|
||||
cmd->tm_cmd.fn, cmd->tm_cmd.sess_h,
|
||||
cmd->tm_cmd.cmd_h_to_abort);
|
||||
|
||||
switch (cmd->tm_cmd.fn) {
|
||||
case SCST_LUN_RESET:
|
||||
case SCST_TARGET_RESET:
|
||||
case SCST_PR_ABORT_ALL:
|
||||
pthread_mutex_lock(&dev->dev_mutex);
|
||||
dev->prevent_allow_medium_removal = 0;
|
||||
pthread_mutex_unlock(&dev->dev_mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
memset(reply, 0, sizeof(*reply));
|
||||
reply->cmd_h = cmd->cmd_h;
|
||||
reply->subcode = cmd->subcode;
|
||||
@@ -1618,15 +1629,7 @@ static void exec_prevent_allow_medium_removal(struct vdisk_cmd *vcmd)
|
||||
TRACE_DBG("PERSIST/PREVENT 0x%02x", cmd->cdb[4]);
|
||||
|
||||
pthread_mutex_lock(&dev->dev_mutex);
|
||||
if (dev->type == TYPE_ROM)
|
||||
dev->prevent_allow_medium_removal =
|
||||
cmd->cdb[4] & 0x01 ? 1 : 0;
|
||||
else {
|
||||
PRINT_ERROR("%s", "Prevent allow medium removal for "
|
||||
"non-CDROM device");
|
||||
set_cmd_error(vcmd,
|
||||
SCST_LOAD_SENSE(scst_sense_invalid_opcode));
|
||||
}
|
||||
dev->prevent_allow_medium_removal = cmd->cdb[4] & 0x01 ? 1 : 0;
|
||||
pthread_mutex_unlock(&dev->dev_mutex);
|
||||
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user