mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-19 06:22:22 +00:00
The bunch of pending changes. Sorry, it's quite big.
- "RECEIVE DIAGNOSTIC RESULTS" command handling fixed - Obtaining device queue parameters in scst_obtain_device_parameters() changed to handle NOT READY sense - Fixed possible dev_cmd_count underflow - Minor iSCSI-SCST connection closing cleanups and fixes - Semantic of other *_atomic flags changed a bit. Now they are intended only to allow SCST to optimize execution context. The corresponing functions now can *always* be called on atomic context and, if necessary, should manually determine that using scst_cmd_atomic() function and restart using corresponding *_NEED_THREAD_* return value. - scst_cmd_get_tgt_resp_flags() and SCST_TSC_FLAG_STATUS flag made obsolete and replaced by scst_cmd_get_is_send_status(). All in-tree drivers updated accordingly - Cleanup: preprocessing_done_atomic removed, now preprocessing_done() callback always called on thread context - 64-bit cleanups - Documented that iscsi-scst-adm is currently broken and explained why - In user space Makefile's added possibility to specify external linker flags - Minor performance optimizations - Other minor cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@350 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+13
-1
@@ -118,7 +118,6 @@ that issue.
|
||||
CAUTION: Working of target and initiator on the same host isn't
|
||||
======== supported. See SCST README file for details.
|
||||
|
||||
|
||||
Compilation options
|
||||
-------------------
|
||||
|
||||
@@ -136,6 +135,19 @@ in/out in the kernel's module Makefile:
|
||||
|
||||
- DEBUG_DIGEST_FAILURES - simulates digest failures in random places.
|
||||
|
||||
Known issues
|
||||
------------
|
||||
|
||||
Currently some iscsi-scst-adm functionality is broken. But, from one
|
||||
side, at the moment I don't have time to look at it and and, from other
|
||||
side, in contrast to IET, in iSCSI-SCST this utility doesn't worth much,
|
||||
since all devices management is done using SCST's /proc interface.
|
||||
What's remained for iscsi-scst-adm is managing iSCSI targets and their
|
||||
parameters, but in any case changing of any negotiable iSCSI parameter
|
||||
needs renegotiation, i.e. the corresponding session restart, i.e.
|
||||
iSCSI-SCST restart. But, if you decide to fix iscsi-scst-adm, I will
|
||||
appreciate your patches.
|
||||
|
||||
Creating version of put_page_callback patch for your kernel
|
||||
-----------------------------------------------------------
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
for adding support for ranges in the negotiation keys, so it needs to
|
||||
be fixed as well.
|
||||
|
||||
- Fix iscsi-scst-adm.
|
||||
|
||||
- Fix SNACK command handling. Currently it violates iSCSI RFC.
|
||||
|
||||
- Consider better integration with TCP internals on receive path to
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#define SCSI_ID_LEN 24
|
||||
|
||||
#ifndef aligned_u64
|
||||
#define aligned_u64 unsigned long long __attribute__((aligned(8)))
|
||||
#define aligned_u64 uint64_t __attribute__((aligned(8)))
|
||||
#endif
|
||||
|
||||
struct target_info {
|
||||
|
||||
@@ -50,8 +50,8 @@ static int iscsi_log_info_show(struct seq_file *seq, void *v)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int iscsi_proc_log_entry_write(struct file *file, const char __user *buf,
|
||||
size_t length, loff_t *off)
|
||||
static ssize_t iscsi_proc_log_entry_write(struct file *file,
|
||||
const char __user *buf, size_t length, loff_t *off)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
@@ -475,10 +475,10 @@ void iscsi_dump_iov(struct msghdr *msg)
|
||||
{
|
||||
if (trace_flag & TRACE_D_IOV) {
|
||||
int i;
|
||||
printk("%p, %d\n", msg->msg_iov, msg->msg_iovlen);
|
||||
printk("%p, %zd\n", msg->msg_iov, msg->msg_iovlen);
|
||||
for (i = 0; i < min_t(size_t, msg->msg_iovlen,
|
||||
ISCSI_CONN_IOV_MAX); i++) {
|
||||
printk("%d: %p,%d\n", i, msg->msg_iov[i].iov_base,
|
||||
printk("%d: %p,%zd\n", i, msg->msg_iov[i].iov_base,
|
||||
msg->msg_iov[i].iov_len);
|
||||
}
|
||||
}
|
||||
@@ -520,7 +520,7 @@ void iscsi_dump_pdu(struct iscsi_pdu *pdu)
|
||||
int i;
|
||||
|
||||
buf = (void *)&pdu->bhs;
|
||||
printk("BHS: (%p,%d)\n", buf, sizeof(pdu->bhs));
|
||||
printk("BHS: (%p,%zd)\n", buf, sizeof(pdu->bhs));
|
||||
for (i = 0; i < sizeof(pdu->bhs); i++)
|
||||
iscsi_dump_char(*buf++);
|
||||
iscsi_dump_char(-1);
|
||||
|
||||
@@ -281,7 +281,7 @@ static int iscsi_socket_bind(struct iscsi_conn *conn)
|
||||
mm_segment_t oldfs;
|
||||
struct iscsi_session *session = conn->session;
|
||||
|
||||
TRACE_DBG("%llu", (unsigned long long) session->sid);
|
||||
TRACE_DBG("%llu", session->sid);
|
||||
|
||||
conn->sock = SOCKET_I(conn->file->f_dentry->d_inode);
|
||||
|
||||
@@ -324,8 +324,7 @@ out:
|
||||
int conn_free(struct iscsi_conn *conn)
|
||||
{
|
||||
TRACE_MGMT_DBG("Freeing conn %p (sess=%p, %#Lx %u)", conn,
|
||||
conn->session, (unsigned long long)conn->session->sid,
|
||||
conn->cid);
|
||||
conn->session, conn->session->sid, conn->cid);
|
||||
|
||||
del_timer_sync(&conn->rsp_timer);
|
||||
|
||||
@@ -360,7 +359,7 @@ static int iscsi_conn_alloc(struct iscsi_session *session, struct conn_info *inf
|
||||
}
|
||||
|
||||
TRACE_MGMT_DBG("Creating connection %p for sid %#Lx, cid %u", conn,
|
||||
(unsigned long long)session->sid, info->cid);
|
||||
session->sid, info->cid);
|
||||
|
||||
/* Changing it, change ISCSI_CONN_IOV_MAX as well !! */
|
||||
conn->read_iov = (struct iovec *)get_zeroed_page(GFP_KERNEL);
|
||||
|
||||
+14
-15
@@ -1036,7 +1036,7 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn,
|
||||
break;
|
||||
}
|
||||
conn->read_iov[i].iov_len = PAGE_SIZE - offset;
|
||||
TRACE_DBG("idx=%d, offset=%u, size=%d, iov_len=%d, addr=%p",
|
||||
TRACE_DBG("idx=%d, offset=%u, size=%d, iov_len=%zd, addr=%p",
|
||||
idx, offset, size, conn->read_iov[i].iov_len, addr);
|
||||
size -= conn->read_iov[i].iov_len;
|
||||
offset = 0;
|
||||
@@ -1050,7 +1050,7 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn,
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
TRACE_DBG("msg_iov=%p, msg_iovlen=%d",
|
||||
TRACE_DBG("msg_iov=%p, msg_iovlen=%zd",
|
||||
conn->read_msg.msg_iov, conn->read_msg.msg_iovlen);
|
||||
|
||||
out:
|
||||
@@ -1244,7 +1244,7 @@ static int noop_out_start(struct iscsi_cmnd *cmnd)
|
||||
}
|
||||
sBUG_ON(size == 0);
|
||||
conn->read_msg.msg_iovlen = i;
|
||||
TRACE_DBG("msg_iov=%p, msg_iovlen=%d", conn->read_msg.msg_iov,
|
||||
TRACE_DBG("msg_iov=%p, msg_iovlen=%zd", conn->read_msg.msg_iov,
|
||||
conn->read_msg.msg_iovlen);
|
||||
}
|
||||
out:
|
||||
@@ -2493,7 +2493,7 @@ static void iscsi_try_local_processing(struct iscsi_conn *conn,
|
||||
|
||||
static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
int resp_flags = scst_cmd_get_tgt_resp_flags(scst_cmd);
|
||||
int is_send_status = scst_cmd_get_is_send_status(scst_cmd);
|
||||
struct iscsi_cmnd *req = (struct iscsi_cmnd*)
|
||||
scst_cmd_get_tgt_priv(scst_cmd);
|
||||
struct iscsi_conn *conn = req->conn;
|
||||
@@ -2507,6 +2507,9 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
|
||||
bool single_only = 0;
|
||||
#endif
|
||||
|
||||
if (scst_cmd_atomic(scst_cmd))
|
||||
return SCST_TGT_RES_NEED_THREAD_CTX;
|
||||
|
||||
scst_cmd_set_tgt_priv(scst_cmd, NULL);
|
||||
|
||||
req->tmfabort |= scst_cmd_aborted(scst_cmd) ? 1 : 0;
|
||||
@@ -2541,34 +2544,31 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
|
||||
req->sg = scst_cmd_get_sg(scst_cmd);
|
||||
req->sg_cnt = scst_cmd_get_sg_cnt(scst_cmd);
|
||||
|
||||
TRACE_DBG("req %p, resp_flags=%x, req->bufflen=%d, req->sg=%p, "
|
||||
"req->sg_cnt %d", req, resp_flags, req->bufflen, req->sg,
|
||||
TRACE_DBG("req %p, is_send_status=%x, req->bufflen=%d, req->sg=%p, "
|
||||
"req->sg_cnt %d", req, is_send_status, req->bufflen, req->sg,
|
||||
req->sg_cnt);
|
||||
|
||||
if (unlikely((req->bufflen != 0) &&
|
||||
!(resp_flags & SCST_TSC_FLAG_STATUS))) {
|
||||
if (unlikely((req->bufflen != 0) && !is_send_status)) {
|
||||
PRINT_CRIT_ERROR("%s", "Sending DATA without STATUS is unsupported");
|
||||
scst_set_cmd_error(scst_cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
resp_flags = scst_cmd_get_tgt_resp_flags(scst_cmd);
|
||||
sBUG();
|
||||
}
|
||||
|
||||
if (req->bufflen != 0) {
|
||||
/*
|
||||
* Check above makes sure that SCST_TSC_FLAG_STATUS is set,
|
||||
* Check above makes sure that is_send_status is set,
|
||||
* so status is valid here, but in future that could change.
|
||||
* ToDo
|
||||
*/
|
||||
if (status != SAM_STAT_CHECK_CONDITION) {
|
||||
send_data_rsp(req, status,
|
||||
resp_flags & SCST_TSC_FLAG_STATUS);
|
||||
send_data_rsp(req, status, is_send_status);
|
||||
} else {
|
||||
struct iscsi_cmnd *rsp;
|
||||
struct iscsi_scsi_rsp_hdr *rsp_hdr;
|
||||
int resid;
|
||||
send_data_rsp(req, 0, 0);
|
||||
if (resp_flags & SCST_TSC_FLAG_STATUS) {
|
||||
if (is_send_status) {
|
||||
rsp = create_status_rsp(req, status, sense,
|
||||
sense_len);
|
||||
rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
|
||||
@@ -2586,7 +2586,7 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd)
|
||||
ISCSI_INIT_WRITE_REMOVE_HASH);
|
||||
}
|
||||
}
|
||||
} else if (resp_flags & SCST_TSC_FLAG_STATUS) {
|
||||
} else if (is_send_status) {
|
||||
struct iscsi_cmnd *rsp;
|
||||
struct iscsi_scsi_rsp_hdr *rsp_hdr;
|
||||
u32 resid;
|
||||
@@ -2781,7 +2781,6 @@ struct scst_tgt_template iscsi_template = {
|
||||
.threads_num = 0,
|
||||
.no_clustering = 1,
|
||||
.xmit_response_atomic = 0,
|
||||
.preprocessing_done_atomic = 1,
|
||||
.detect = iscsi_target_detect,
|
||||
.release = iscsi_target_release,
|
||||
.xmit_response = iscsi_xmit_response,
|
||||
|
||||
+32
-25
@@ -183,10 +183,15 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct iscsi_target *target = conn->target;
|
||||
unsigned long start_waiting = jiffies;
|
||||
unsigned long shut_start_waiting = start_waiting;
|
||||
typeof(jiffies) start_waiting = jiffies;
|
||||
typeof(jiffies) shut_start_waiting = start_waiting;
|
||||
bool pending_reported = 0, wait_expired = 0, shut_expired = 0;
|
||||
|
||||
#define CONN_PENDING_TIMEOUT ((typeof(jiffies))10*HZ)
|
||||
#define CONN_WAIT_TIMEOUT ((typeof(jiffies))10*HZ)
|
||||
#define CONN_REG_SHUT_TIMEOUT ((typeof(jiffies))125*HZ)
|
||||
#define CONN_DEL_SHUT_TIMEOUT ((typeof(jiffies))10*HZ)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_CONN_CLOSE("Closing connection %p (conn_ref_cnt=%d)", conn,
|
||||
@@ -291,7 +296,7 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
} while(req_freed);
|
||||
spin_unlock(&session->sn_lock);
|
||||
|
||||
if (time_after(jiffies, start_waiting + 10*HZ)) {
|
||||
if (time_after(jiffies, start_waiting + CONN_PENDING_TIMEOUT)) {
|
||||
if (!pending_reported) {
|
||||
TRACE_CONN_CLOSE("%s", "Pending wait time expired");
|
||||
pending_reported = 1;
|
||||
@@ -331,7 +336,9 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
|
||||
iscsi_make_conn_wr_active(conn);
|
||||
|
||||
if (time_after(jiffies, start_waiting + 10*HZ) && !wait_expired) {
|
||||
/* That's for active close only, actually */
|
||||
if (time_after(jiffies, start_waiting + CONN_WAIT_TIMEOUT) &&
|
||||
!wait_expired) {
|
||||
TRACE_CONN_CLOSE("Wait time expired (conn %p, "
|
||||
"sk_state %d)", conn, conn->sock->sk->sk_state);
|
||||
conn->sock->ops->shutdown(conn->sock, SEND_SHUTDOWN);
|
||||
@@ -339,17 +346,20 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
shut_start_waiting = jiffies;
|
||||
}
|
||||
|
||||
if (conn->deleting) {
|
||||
if (wait_expired && !shut_expired &&
|
||||
time_after(jiffies, shut_start_waiting + 10*HZ)) {
|
||||
TRACE_CONN_CLOSE("Wait time after shutdown expired "
|
||||
"(conn %p, sk_state %d)", conn,
|
||||
conn->sock->sk->sk_state);
|
||||
conn->sock->sk->sk_prot->disconnect(conn->sock->sk, 0);
|
||||
shut_expired = 1;
|
||||
}
|
||||
if (wait_expired && !shut_expired &&
|
||||
time_after(jiffies, shut_start_waiting +
|
||||
conn->deleting ? CONN_DEL_SHUT_TIMEOUT :
|
||||
CONN_REG_SHUT_TIMEOUT)) {
|
||||
TRACE_CONN_CLOSE("Wait time after shutdown expired "
|
||||
"(conn %p, sk_state %d)", conn,
|
||||
conn->sock->sk->sk_state);
|
||||
conn->sock->sk->sk_prot->disconnect(conn->sock->sk, 0);
|
||||
shut_expired = 1;
|
||||
}
|
||||
|
||||
if (conn->deleting)
|
||||
msleep(200);
|
||||
} else
|
||||
else
|
||||
msleep(1000);
|
||||
|
||||
TRACE_CONN_CLOSE_DBG("conn %p, conn_ref_cnt %d left, wr_state %d, "
|
||||
@@ -362,7 +372,7 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (time_after(jiffies, start_waiting+10*HZ))
|
||||
if (time_after(jiffies, start_waiting + 10*HZ))
|
||||
trace_flag |= TRACE_CONN_OC_DBG;
|
||||
#endif
|
||||
|
||||
@@ -924,7 +934,7 @@ static int write_data(struct iscsi_conn *conn)
|
||||
struct scatterlist *sg;
|
||||
struct iovec *iop;
|
||||
int saved_size, size, sendsize;
|
||||
int offset, idx;
|
||||
int offset, idx, sg_offset;
|
||||
int flags, res, count;
|
||||
bool do_put = false;
|
||||
|
||||
@@ -947,7 +957,6 @@ static int write_data(struct iscsi_conn *conn)
|
||||
spin_unlock_bh(&conn->write_list_lock);
|
||||
}
|
||||
|
||||
#if 0 /* temp. ToDo */
|
||||
if (!timer_pending(&conn->rsp_timer)) {
|
||||
sBUG_ON(!ref_cmd->on_written_list);
|
||||
spin_lock_bh(&conn->write_list_lock);
|
||||
@@ -959,7 +968,6 @@ static int write_data(struct iscsi_conn *conn)
|
||||
}
|
||||
spin_unlock_bh(&conn->write_list_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = conn->file;
|
||||
saved_size = size = conn->write_size;
|
||||
@@ -976,8 +984,7 @@ retry:
|
||||
set_fs(KERNEL_DS);
|
||||
res = vfs_writev(file, (struct iovec __user *)iop, count, &off);
|
||||
set_fs(oldfs);
|
||||
TRACE_WRITE("%#Lx:%u: %d(%ld)",
|
||||
(unsigned long long)conn->session->sid, conn->cid,
|
||||
TRACE_WRITE("%#Lx:%u: %d(%ld)", conn->session->sid, conn->cid,
|
||||
res, (long)iop->iov_len);
|
||||
if (unlikely(res <= 0)) {
|
||||
if (res == -EAGAIN) {
|
||||
@@ -1020,7 +1027,8 @@ retry:
|
||||
__iscsi_get_page_callback(ref_cmd);
|
||||
do_put = true;
|
||||
|
||||
offset = conn->write_offset + sg[0].offset;
|
||||
sg_offset = sg[0].offset;
|
||||
offset = conn->write_offset + sg_offset;
|
||||
idx = offset >> PAGE_SHIFT;
|
||||
offset &= ~PAGE_MASK;
|
||||
|
||||
@@ -1074,7 +1082,7 @@ retry2:
|
||||
TRACE_WRITE("Final %s %#Lx:%u: %d(%lu,%u,%u, cmd %p, page %p)",
|
||||
(sendpage != sock_no_sendpage) ? "sendpage" :
|
||||
"sock_no_sendpage",
|
||||
(unsigned long long)conn->session->sid, conn->cid,
|
||||
conn->session->sid, conn->cid,
|
||||
res, sg_page(&sg[idx])->index, offset, size,
|
||||
write_cmnd, sg_page(&sg[idx]));
|
||||
if (unlikely(res <= 0)) {
|
||||
@@ -1124,7 +1132,7 @@ retry1:
|
||||
}
|
||||
|
||||
out_off:
|
||||
conn->write_offset = (idx << PAGE_SHIFT) + offset - sg[0].offset;
|
||||
conn->write_offset = (idx << PAGE_SHIFT) + offset - sg_offset;
|
||||
|
||||
out_iov:
|
||||
conn->write_size = size;
|
||||
@@ -1153,8 +1161,7 @@ out_err:
|
||||
#endif
|
||||
{
|
||||
PRINT_ERROR("error %d at sid:cid %#Lx:%u, cmnd %p", res,
|
||||
(unsigned long long)conn->session->sid, conn->cid,
|
||||
conn->write_cmnd);
|
||||
conn->session->sid, conn->cid, conn->write_cmnd);
|
||||
}
|
||||
if (ref_cmd->scst_cmd != NULL)
|
||||
scst_set_delivery_status(ref_cmd->scst_cmd,
|
||||
|
||||
@@ -94,7 +94,7 @@ static int iscsi_session_alloc(struct iscsi_target *target, struct session_info
|
||||
list_add(&session->session_list_entry, &target->session_list);
|
||||
|
||||
TRACE_MGMT_DBG("Session %p created: target %p, tid %u, sid %#Lx",
|
||||
session, target, target->tid, (unsigned long long) info->sid);
|
||||
session, target, target->tid, info->sid);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
@@ -129,8 +129,7 @@ int session_free(struct iscsi_session *session)
|
||||
{
|
||||
int i;
|
||||
|
||||
TRACE_MGMT_DBG("Freeing session %p:%#Lx", session,
|
||||
(unsigned long long)session->sid);
|
||||
TRACE_MGMT_DBG("Freeing session %p:%#Lx", session, session->sid);
|
||||
|
||||
sBUG_ON(!list_empty(&session->conn_list));
|
||||
if (unlikely(atomic_read(&session->active_cmds) != 0)) {
|
||||
@@ -163,8 +162,7 @@ int session_del(struct iscsi_target *target, u64 sid)
|
||||
return -ENOENT;
|
||||
|
||||
if (!list_empty(&session->conn_list)) {
|
||||
PRINT_ERROR("%llu still have connections",
|
||||
(unsigned long long)session->sid);
|
||||
PRINT_ERROR("%llu still have connections", session->sid);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@@ -178,8 +176,8 @@ static void iscsi_session_info_show(struct seq_file *seq, struct iscsi_target *t
|
||||
|
||||
list_for_each_entry(session, &target->session_list, session_list_entry) {
|
||||
seq_printf(seq, "\tsid:%llu initiator:%s shutting down %d\n",
|
||||
(unsigned long long)session->sid,
|
||||
session->initiator_name, session->shutting_down);
|
||||
session->sid, session->initiator_name,
|
||||
session->shutting_down);
|
||||
conn_info_show(seq, session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ LIBS = -lcrypto
|
||||
all: $(PROGRAMS)
|
||||
|
||||
iscsi-scstd: .depend_d $(OBJS_D)
|
||||
$(CC) $(OBJS_D) $(LIBS) -o $@
|
||||
$(CC) $(OBJS_D) $(LIBS) $(LOCAL_LD_FLAGS) -o $@
|
||||
|
||||
iscsi-scst-adm: .depend_adm $(OBJS_ADM)
|
||||
$(CC) $(OBJS_ADM) $(LIBS) -o $@
|
||||
$(CC) $(OBJS_ADM) $(LIBS) $(LOCAL_LD_FLAGS) -o $@
|
||||
|
||||
ifeq (.depend_d,$(wildcard .depend_d))
|
||||
-include .depend_d
|
||||
|
||||
+18
-6
@@ -1588,11 +1588,17 @@ mpt_xmit_response(struct scst_cmd *scst_cmd)
|
||||
int res = SCST_TGT_RES_SUCCESS;
|
||||
struct mpt_sess *sess;
|
||||
struct mpt_prm prm = { 0 };
|
||||
int resp_flags;
|
||||
int is_send_status;
|
||||
//uint16_t full_req_cnt;
|
||||
//int data_sense_flag = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
#ifdef DEBUG_WORK_IN_THREAD
|
||||
if (scst_cmd_atomic(scst_cmd))
|
||||
return SCST_TGT_RES_NEED_THREAD_CTX;
|
||||
#endif
|
||||
|
||||
prm.cmd = (struct mpt_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
sess = (struct mpt_sess *)
|
||||
scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
|
||||
@@ -1607,16 +1613,16 @@ mpt_xmit_response(struct scst_cmd *scst_cmd)
|
||||
prm.sense_buffer_len = scst_cmd_get_sense_buffer_len(scst_cmd);
|
||||
prm.tgt = sess->tgt;
|
||||
prm.seg_cnt = 0;
|
||||
resp_flags = scst_cmd_get_tgt_resp_flags(scst_cmd);
|
||||
is_send_status = scst_cmd_get_is_send_status(scst_cmd);
|
||||
|
||||
TRACE_DBG("rq_result=%x, resp_flags=%x, %x, %d", prm.rq_result,
|
||||
resp_flags, prm.bufflen, prm.sense_buffer_len);
|
||||
TRACE_DBG("rq_result=%x, is_send_status=%x, %x, %d", prm.rq_result,
|
||||
is_send_status, prm.bufflen, prm.sense_buffer_len);
|
||||
if ((prm.rq_result != 0) && (prm.sense_buffer != NULL))
|
||||
TRACE_BUFFER("Sense", prm.sense_buffer, prm.sense_buffer_len);
|
||||
|
||||
if ((resp_flags & SCST_TSC_FLAG_STATUS) == 0) {
|
||||
if (!is_send_status) {
|
||||
/* ToDo, after it's done in SCST */
|
||||
PRINT_ERROR(MYNAM ": SCST_TSC_FLAG_STATUS not set: "
|
||||
PRINT_ERROR(MYNAM ": is_send_status not set: "
|
||||
"feature not implemented %p", scst_cmd);
|
||||
res = SCST_TGT_RES_FATAL_ERROR;
|
||||
goto out_tgt_free;
|
||||
@@ -1740,6 +1746,12 @@ static int mpt_rdy_to_xfer(struct scst_cmd *scst_cmd)
|
||||
struct mpt_prm prm = { 0 };
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
#ifdef DEBUG_WORK_IN_THREAD
|
||||
if (scst_cmd_atomic(scst_cmd))
|
||||
return SCST_TGT_RES_NEED_THREAD_CTX;
|
||||
#endif
|
||||
|
||||
prm.cmd = (struct mpt_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
sess = (struct mpt_sess *)
|
||||
scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
|
||||
|
||||
@@ -672,7 +672,7 @@ static int q2t_xmit_response(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
int res = SCST_TGT_RES_SUCCESS;
|
||||
struct q2t_sess *sess;
|
||||
int resp_flags;
|
||||
int is_send_status;
|
||||
unsigned long flags = 0;
|
||||
struct q2t_prm prm = { 0 };
|
||||
int data_sense_flag = 0;
|
||||
@@ -681,6 +681,11 @@ static int q2t_xmit_response(struct scst_cmd *scst_cmd)
|
||||
TRACE_ENTRY();
|
||||
TRACE(TRACE_SCSI, "tag=%Ld", scst_cmd_get_tag(scst_cmd));
|
||||
|
||||
#ifdef DEBUG_WORK_IN_THREAD
|
||||
if (scst_cmd_atomic(scst_cmd))
|
||||
return SCST_TGT_RES_NEED_THREAD_CTX;
|
||||
#endif
|
||||
|
||||
prm.cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
sess = (struct q2t_sess *)
|
||||
scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
|
||||
@@ -709,15 +714,17 @@ static int q2t_xmit_response(struct scst_cmd *scst_cmd)
|
||||
prm.tgt = sess->tgt;
|
||||
prm.seg_cnt = 0;
|
||||
prm.req_cnt = 1;
|
||||
resp_flags = scst_cmd_get_tgt_resp_flags(scst_cmd);
|
||||
is_send_status = scst_cmd_get_is_send_status(scst_cmd);
|
||||
|
||||
TRACE_DBG("rq_result=%x, is_send_status=%x", prm.rq_result,
|
||||
is_send_status);
|
||||
|
||||
TRACE_DBG("rq_result=%x, resp_flags=%x", prm.rq_result, resp_flags);
|
||||
if (prm.rq_result != 0)
|
||||
TRACE_BUFFER("Sense", prm.sense_buffer, prm.sense_buffer_len);
|
||||
|
||||
if ((resp_flags & SCST_TSC_FLAG_STATUS) == 0) {
|
||||
if (!is_send_status) {
|
||||
/* ToDo, after it's done in SCST */
|
||||
PRINT_ERROR("qla2x00tgt(%ld): SCST_TSC_FLAG_STATUS not set: "
|
||||
PRINT_ERROR("qla2x00tgt(%ld): is_send_status not set: "
|
||||
"feature not implemented", prm.tgt->ha->instance);
|
||||
res = SCST_TGT_RES_FATAL_ERROR;
|
||||
goto out;
|
||||
@@ -827,6 +834,11 @@ static int q2t_rdy_to_xfer(struct scst_cmd *scst_cmd)
|
||||
TRACE_ENTRY();
|
||||
TRACE(TRACE_SCSI, "tag=%Ld", scst_cmd_get_tag(scst_cmd));
|
||||
|
||||
#ifdef DEBUG_WORK_IN_THREAD
|
||||
if (scst_cmd_atomic(scst_cmd))
|
||||
return SCST_TGT_RES_NEED_THREAD_CTX;
|
||||
#endif
|
||||
|
||||
prm.cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
sess = (struct q2t_sess *)
|
||||
scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
|
||||
@@ -2134,8 +2146,8 @@ static int q2t_log_info_show(struct seq_file *seq, void *v)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int q2t_proc_log_entry_write(struct file *file, const char __user *buf,
|
||||
size_t length, loff_t *off)
|
||||
static ssize_t q2t_proc_log_entry_write(struct file *file,
|
||||
const char __user *buf, size_t length, loff_t *off)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
@@ -2148,7 +2160,6 @@ static int q2t_proc_log_entry_write(struct file *file, const char __user *buf,
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static struct scst_proc_data q2t_log_proc_data = {
|
||||
SCST_DEF_RW_SEQ_OP(q2t_proc_log_entry_write)
|
||||
.show = q2t_log_info_show,
|
||||
|
||||
@@ -1089,7 +1089,7 @@ isp_xmit_response(struct scst_cmd *scst_cmd)
|
||||
xact->td_hflags &= ~TDFH_DATA_MASK;
|
||||
}
|
||||
|
||||
if (scst_cmd_get_tgt_resp_flags(scst_cmd) & SCST_TSC_FLAG_STATUS) {
|
||||
if (scst_cmd_get_is_send_status(scst_cmd)) {
|
||||
xact->td_hflags |= TDFH_STSVALID;
|
||||
tmd->cd_scsi_status = scst_cmd_get_status(scst_cmd);
|
||||
|
||||
|
||||
+3
-10
@@ -106,16 +106,6 @@ IMPORTANT: Working of target and initiator on the same host isn't
|
||||
request to the target -> target needs memory -> problem is
|
||||
possible.
|
||||
|
||||
IMPORTANT: Experience shows that if people work with out of SCST tree target
|
||||
========= drivers, like target driver for Infiniband or in case if they
|
||||
downloaded and use the released versions of SCST and target
|
||||
drivers, they are too often (actually, almost always) after
|
||||
upgrading SCST core forget to rebuild their target drivers,
|
||||
which then immediately after load crash in the hard to trace
|
||||
manner. So, after you reinstalled SCST core don't forget to
|
||||
rebuild and reinstall all your target drivers, custom dev
|
||||
handlers and necessary user space applications.
|
||||
|
||||
IMPORTANT: In the current version simultaneous access to local SCSI devices
|
||||
========= via standard high-level SCSI drivers (sd, st, sg, etc.) and
|
||||
SCST's target drivers is unsupported. Especially it is
|
||||
@@ -396,6 +386,9 @@ following files and directories under /proc/scsi_tgt:
|
||||
- "clear" to /proc/scsi_tgt/groups/GROUP/names clears the list of names
|
||||
for group "GROUP"
|
||||
|
||||
There must be LUN 0 in each security group, i.e. LUs numeration must not
|
||||
start from, e.g., 1.
|
||||
|
||||
Examples:
|
||||
|
||||
- "echo "add 1:0:1:0 0" >/proc/scsi_tgt/groups/Default/devices" will
|
||||
|
||||
+21
-17
@@ -293,16 +293,12 @@ typedef _Bool bool;
|
||||
*************************************************************/
|
||||
#define SCST_DEFAULT_TIMEOUT (30*HZ)
|
||||
|
||||
/*************************************************************
|
||||
** Flags of cmd->tgt_resp_flags
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
* 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
|
||||
* possibility to perform a command in "chunks" (i.e. with multiple
|
||||
* xmit_response()/rdy_to_xfer()) is used (not implemented and,
|
||||
* probably, will never be).
|
||||
* xmit_response()/rdy_to_xfer()) is used (not implemented yet).
|
||||
* Obsolete, use scst_cmd_get_is_send_status() instead.
|
||||
*/
|
||||
#define SCST_TSC_FLAG_STATUS 0x2
|
||||
|
||||
@@ -472,7 +468,6 @@ struct scst_tgt_template
|
||||
*/
|
||||
unsigned xmit_response_atomic:1;
|
||||
unsigned rdy_to_xfer_atomic:1;
|
||||
unsigned preprocessing_done_atomic:1;
|
||||
|
||||
/* True, if the template doesn't need the entry in /proc */
|
||||
unsigned no_proc_entry:1;
|
||||
@@ -752,7 +747,7 @@ struct scst_dev_type
|
||||
|
||||
/*
|
||||
* Called to notify dev handler about the result of cmd execution
|
||||
* and perform some post processing. Cmd's fields tgt_resp_flags and
|
||||
* and perform some post processing. Cmd's fields is_send_status and
|
||||
* resp_data_len should be set by this function, but SCST offers good
|
||||
* defaults.
|
||||
* Returns the command's next state or SCST_CMD_STATE_DEFAULT,
|
||||
@@ -1022,6 +1017,9 @@ struct scst_cmd
|
||||
/* Set if cmd is being processed in atomic context */
|
||||
unsigned int atomic:1;
|
||||
|
||||
/* Set if this command contains status */
|
||||
unsigned int is_send_status:1;
|
||||
|
||||
/*
|
||||
* Set if the cmd is being processed in the processable context. See
|
||||
* comment for SCST_CONTEXT_PROCESSABLE for what it means.
|
||||
@@ -1208,12 +1206,6 @@ struct scst_cmd
|
||||
/* scst_get_sg_buf_[first,next]() support */
|
||||
int get_sg_buf_entry_num;
|
||||
|
||||
/*
|
||||
* The following two fields should be corrected by the dev_done(),
|
||||
* if necessary
|
||||
*/
|
||||
int tgt_resp_flags; /* response flags (SCST_TSC_FLAG_* constants) */
|
||||
|
||||
/*
|
||||
* Response data length in data buffer. This field must not be set
|
||||
* directly, use scst_set_resp_data_len() for that
|
||||
@@ -1340,6 +1332,9 @@ struct scst_device
|
||||
/* 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;
|
||||
|
||||
unsigned short type; /* SCSI type of the device */
|
||||
|
||||
/*************************************************************
|
||||
@@ -2029,10 +2024,19 @@ static inline int scst_cmd_get_resp_data_len(struct scst_cmd *cmd)
|
||||
return cmd->resp_data_len;
|
||||
}
|
||||
|
||||
/* Returns cmd's response flags (SCST_TSC_FLAG_* constants) */
|
||||
static inline int scst_cmd_get_tgt_resp_flags(struct scst_cmd *cmd)
|
||||
/*
|
||||
* Returns cmd's response flags (SCST_TSC_FLAG_* constants). Obsolete, use
|
||||
* scst_cmd_get_is_send_status() instead.
|
||||
*/
|
||||
static inline __deprecated int scst_cmd_get_tgt_resp_flags(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->tgt_resp_flags;
|
||||
return cmd->is_send_status ? SCST_TSC_FLAG_STATUS : 0;
|
||||
}
|
||||
|
||||
/* Returns if status should be sent for cmd */
|
||||
static inline int scst_cmd_get_is_send_status(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->is_send_status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -177,7 +177,7 @@ int changer_done(struct scst_cmd *cmd)
|
||||
TRACE_ENTRY();
|
||||
|
||||
/*
|
||||
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
|
||||
* SCST sets good defaults for cmd->is_send_status and cmd->resp_data_len
|
||||
* based on cmd->status and cmd->data_direction, therefore change
|
||||
* them only if necessary
|
||||
*/
|
||||
|
||||
@@ -176,7 +176,7 @@ int processor_done(struct scst_cmd *cmd)
|
||||
TRACE_ENTRY();
|
||||
|
||||
/*
|
||||
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
|
||||
* SCST sets good defaults for cmd->is_send_status and cmd->resp_data_len
|
||||
* based on cmd->status and cmd->data_direction, therefore change
|
||||
* them only if necessary
|
||||
*/
|
||||
|
||||
@@ -176,7 +176,7 @@ int raid_done(struct scst_cmd *cmd)
|
||||
TRACE_ENTRY();
|
||||
|
||||
/*
|
||||
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
|
||||
* SCST sets good defaults for cmd->is_send_status and cmd->resp_data_len
|
||||
* based on cmd->status and cmd->data_direction, therefore change
|
||||
* them only if necessary
|
||||
*/
|
||||
|
||||
@@ -384,8 +384,8 @@ int tape_done(struct scst_cmd *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_DBG("cmd->tgt_resp_flags=%x, cmd->resp_data_len=%d, "
|
||||
"res=%d", cmd->tgt_resp_flags, cmd->resp_data_len, res);
|
||||
TRACE_DBG("cmd->is_send_status=%x, cmd->resp_data_len=%d, "
|
||||
"res=%d", cmd->is_send_status, cmd->resp_data_len, res);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
@@ -278,7 +278,7 @@ static inline struct scst_user_cmd *__ucmd_find_hash(struct scst_user_dev *dev,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void cmnd_insert_hash(struct scst_user_cmd *ucmd)
|
||||
static void cmd_insert_hash(struct scst_user_cmd *ucmd)
|
||||
{
|
||||
struct list_head *head;
|
||||
struct scst_user_dev *dev = ucmd->dev;
|
||||
@@ -298,7 +298,7 @@ static void cmnd_insert_hash(struct scst_user_cmd *ucmd)
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void cmnd_remove_hash(struct scst_user_cmd *ucmd)
|
||||
static inline void cmd_remove_hash(struct scst_user_cmd *ucmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&ucmd->dev->cmd_lists.cmd_list_lock, flags);
|
||||
@@ -315,7 +315,7 @@ static void dev_user_free_ucmd(struct scst_user_cmd *ucmd)
|
||||
|
||||
TRACE_MEM("Freeing ucmd %p", ucmd);
|
||||
|
||||
cmnd_remove_hash(ucmd);
|
||||
cmd_remove_hash(ucmd);
|
||||
EXTRACHECKS_BUG_ON(ucmd->cmd != NULL);
|
||||
|
||||
kmem_cache_free(user_cmd_cachep, ucmd);
|
||||
@@ -630,7 +630,7 @@ static struct scst_user_cmd *dev_user_alloc_ucmd(struct scst_user_dev *dev,
|
||||
ucmd->dev = dev;
|
||||
atomic_set(&ucmd->ucmd_ref, 1);
|
||||
|
||||
cmnd_insert_hash(ucmd);
|
||||
cmd_insert_hash(ucmd);
|
||||
|
||||
TRACE_MEM("ucmd %p allocated", ucmd);
|
||||
|
||||
@@ -784,9 +784,22 @@ out:
|
||||
static int dev_user_exec(struct scst_cmd *cmd)
|
||||
{
|
||||
struct scst_user_cmd *ucmd = (struct scst_user_cmd*)cmd->dh_priv;
|
||||
int res = SCST_EXEC_COMPLETED;
|
||||
|
||||
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);
|
||||
@@ -818,8 +831,8 @@ static int dev_user_exec(struct scst_cmd *cmd)
|
||||
|
||||
dev_user_add_to_ready(ucmd);
|
||||
|
||||
TRACE_EXIT();
|
||||
return SCST_EXEC_COMPLETED;
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void dev_user_free_sgv(struct scst_user_cmd *ucmd)
|
||||
@@ -2920,6 +2933,8 @@ static int dev_user_release(struct inode *inode, struct file *file)
|
||||
}
|
||||
file->private_data = NULL;
|
||||
|
||||
TRACE(TRACE_MGMT, "Releasing dev %s", dev->name);
|
||||
|
||||
spin_lock(&dev_list_lock);
|
||||
list_del(&dev->dev_list_entry);
|
||||
spin_unlock(&dev_list_lock);
|
||||
@@ -2928,8 +2943,6 @@ static int dev_user_release(struct inode *inode, struct file *file)
|
||||
|
||||
down_write(&dev->dev_rwsem);
|
||||
|
||||
TRACE_DBG("Releasing dev %p", dev);
|
||||
|
||||
spin_lock(&cleanup_lock);
|
||||
list_add_tail(&dev->cleanup_list_entry, &cleanup_list);
|
||||
spin_unlock(&cleanup_lock);
|
||||
|
||||
@@ -666,7 +666,7 @@ static inline int vdisk_need_pre_sync(enum scst_cmd_queue_type cur,
|
||||
|
||||
static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
{
|
||||
int rc;
|
||||
int rc, res;
|
||||
uint64_t lba_start = 0;
|
||||
loff_t data_len = 0;
|
||||
uint8_t *cdb = cmd->cdb;
|
||||
@@ -681,6 +681,13 @@ static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
TRACE_DBG("%s", "vdisk exec() can not be done in atomic "
|
||||
"context, requesting thread context");
|
||||
res = SCST_EXEC_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch(cmd->queue_type) {
|
||||
case SCST_CMD_QUEUE_ORDERED:
|
||||
TRACE(TRACE_ORDER, "ORDERED cmd %p", cmd);
|
||||
@@ -795,7 +802,7 @@ static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
case READ_16:
|
||||
if (virt_dev->blockio) {
|
||||
blockio_exec_rw(cmd, thr, lba_start, 0);
|
||||
goto out;
|
||||
goto out_thr;
|
||||
} else
|
||||
vdisk_exec_read(cmd, thr, loff);
|
||||
break;
|
||||
@@ -822,7 +829,7 @@ static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
}
|
||||
if (virt_dev->blockio) {
|
||||
blockio_exec_rw(cmd, thr, lba_start, 1);
|
||||
goto out;
|
||||
goto out_thr;
|
||||
} else
|
||||
vdisk_exec_write(cmd, thr, loff);
|
||||
/* O_SYNC flag is used for WT devices */
|
||||
@@ -882,7 +889,7 @@ static int vdisk_do_job(struct scst_cmd *cmd)
|
||||
vdisk_fsync(thr, loff, data_len, NULL);
|
||||
/* ToDo: vdisk_fsync() error processing */
|
||||
scst_cmd_put(cmd);
|
||||
goto out;
|
||||
goto out_thr;
|
||||
} else {
|
||||
vdisk_fsync(thr, loff, data_len, cmd);
|
||||
break;
|
||||
@@ -949,12 +956,15 @@ out_compl:
|
||||
out_done:
|
||||
cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT);
|
||||
|
||||
out:
|
||||
out_thr:
|
||||
if (likely(thr != NULL))
|
||||
scst_thr_data_put(&thr->hdr);
|
||||
|
||||
TRACE_EXIT();
|
||||
return SCST_EXEC_COMPLETED;
|
||||
res = SCST_EXEC_COMPLETED;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int vdisk_get_block_shift(struct scst_cmd *cmd)
|
||||
|
||||
@@ -197,7 +197,7 @@ static const struct scst_sdbops scst_scsi_op_table[] = {
|
||||
{0x1B, "O OO O O ", "STOP START UNIT",
|
||||
SCST_DATA_NONE, SCST_LONG_TIMEOUT, 0, get_trans_len_none},
|
||||
{0x1C, "OOOOOOOOOOOOOOOO", "RECEIVE DIAGNOSTIC RESULTS",
|
||||
SCST_DATA_READ, FLAG_NONE, 4, get_trans_len_1},
|
||||
SCST_DATA_READ, FLAG_NONE, 3, get_trans_len_2},
|
||||
{0x1D, "MMMMMMMMMMMMMMMM", "SEND DIAGNOSTIC",
|
||||
SCST_DATA_WRITE, FLAG_NONE, 4, get_trans_len_1},
|
||||
{0x1E, "OOOOOOOOOOOOOOOO", "PREVENT ALLOW MEDIUM REMOVAL",
|
||||
|
||||
+38
-25
@@ -94,7 +94,7 @@ void scst_set_cmd_error_status(struct scst_cmd *cmd, int status)
|
||||
cmd->host_status = DID_OK;
|
||||
|
||||
cmd->data_direction = SCST_DATA_NONE;
|
||||
cmd->tgt_resp_flags = SCST_TSC_FLAG_STATUS;
|
||||
cmd->is_send_status = 1;
|
||||
cmd->resp_data_len = 0;
|
||||
|
||||
cmd->completed = 1;
|
||||
@@ -233,6 +233,7 @@ int scst_alloc_device(int gfp_mask, struct scst_device **out_dev)
|
||||
dev->handler = &scst_null_devtype;
|
||||
dev->p_cmd_lists = &scst_main_cmd_lists;
|
||||
atomic_set(&dev->dev_cmd_count, 0);
|
||||
atomic_set(&dev->write_cmd_count, 0);
|
||||
spin_lock_init(&dev->dev_lock);
|
||||
atomic_set(&dev->on_dev_count, 0);
|
||||
INIT_LIST_HEAD(&dev->blocked_cmd_list);
|
||||
@@ -474,16 +475,18 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
atomic_set(&tgt_dev->sn_slots[i], 0);
|
||||
|
||||
if (dev->handler->parse_atomic &&
|
||||
sess->tgt->tgtt->preprocessing_done_atomic) {
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic)
|
||||
(sess->tgt->tgtt->preprocessing_done == NULL)) {
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic ||
|
||||
(sess->tgt->tgtt->rdy_to_xfer == NULL))
|
||||
__set_bit(SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
if (dev->handler->exec_atomic)
|
||||
if (dev->handler->exec_atomic || (dev->handler->exec == NULL))
|
||||
__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)
|
||||
if (dev->handler->exec_atomic || (dev->handler->exec == NULL)) {
|
||||
if (sess->tgt->tgtt->rdy_to_xfer_atomic ||
|
||||
(sess->tgt->tgtt->rdy_to_xfer == NULL))
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RESTART_WR_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RESTART_OTH_ATOMIC,
|
||||
@@ -491,7 +494,8 @@ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
__set_bit(SCST_TGT_DEV_AFTER_RX_DATA_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
}
|
||||
if (dev->handler->dev_done_atomic &&
|
||||
if ((dev->handler->dev_done_atomic ||
|
||||
(dev->handler->dev_done == NULL)) &&
|
||||
sess->tgt->tgtt->xmit_response_atomic) {
|
||||
__set_bit(SCST_TGT_DEV_AFTER_EXEC_ATOMIC,
|
||||
&tgt_dev->tgt_dev_flags);
|
||||
@@ -1301,7 +1305,7 @@ struct scst_cmd *scst_alloc_cmd(int gfp_mask)
|
||||
cmd->timeout = SCST_DEFAULT_TIMEOUT;
|
||||
cmd->retries = 0;
|
||||
cmd->data_len = -1;
|
||||
cmd->tgt_resp_flags = SCST_TSC_FLAG_STATUS;
|
||||
cmd->is_send_status = 1;
|
||||
cmd->resp_data_len = -1;
|
||||
|
||||
out:
|
||||
@@ -1677,7 +1681,7 @@ static int get_trans_len_read_pos(struct scst_cmd *cmd, uint8_t off)
|
||||
cmd->bufflen = 0;
|
||||
cmd->bufflen |= ((u32)p[0]) << 8;
|
||||
cmd->bufflen |= ((u32)p[1]);
|
||||
|
||||
|
||||
switch (cmd->cdb[1] & 0x1f) {
|
||||
case 0:
|
||||
case 1:
|
||||
@@ -2177,7 +2181,7 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd,
|
||||
TRACE_ENTRY();
|
||||
|
||||
/*
|
||||
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
|
||||
* SCST sets good defaults for cmd->is_send_status and cmd->resp_data_len
|
||||
* based on cmd->status and cmd->data_direction, therefore change
|
||||
* them only if necessary
|
||||
*/
|
||||
@@ -2215,8 +2219,8 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_DBG("cmd->tgt_resp_flags=%x, cmd->resp_data_len=%d, "
|
||||
"res=%d", cmd->tgt_resp_flags, cmd->resp_data_len, res);
|
||||
TRACE_DBG("cmd->is_send_status=%x, cmd->resp_data_len=%d, "
|
||||
"res=%d", cmd->is_send_status, cmd->resp_data_len, res);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -2234,7 +2238,7 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd,
|
||||
TRACE_ENTRY();
|
||||
|
||||
/*
|
||||
* SCST sets good defaults for cmd->tgt_resp_flags and cmd->resp_data_len
|
||||
* SCST sets good defaults for cmd->is_send_status and cmd->resp_data_len
|
||||
* based on cmd->status and cmd->data_direction, therefore change
|
||||
* them only if necessary
|
||||
*/
|
||||
@@ -2375,18 +2379,27 @@ int scst_obtain_device_parameters(struct scst_device *dev)
|
||||
#else
|
||||
if (
|
||||
#endif
|
||||
SCST_SENSE_VALID(sense_buffer) &&
|
||||
(sense_buffer[2] == ILLEGAL_REQUEST)) {
|
||||
TRACE(TRACE_SCSI|TRACE_MGMT_MINOR, "Device %d:%d:%d:%d "
|
||||
"doesn't support control mode page, using "
|
||||
"defaults: TST %x, QUEUE ALG %x, SWP %x, "
|
||||
"TAS %x, has_own_order_mgmt %d",
|
||||
dev->scsi_dev->host->host_no,
|
||||
dev->scsi_dev->channel, dev->scsi_dev->id,
|
||||
dev->scsi_dev->lun, dev->tst, dev->queue_alg,
|
||||
dev->swp, dev->tas, dev->has_own_order_mgmt);
|
||||
res = 0;
|
||||
goto out;
|
||||
SCST_SENSE_VALID(sense_buffer)) {
|
||||
if (sense_buffer[2] == ILLEGAL_REQUEST) {
|
||||
TRACE(TRACE_SCSI|TRACE_MGMT_MINOR, "Device "
|
||||
"%d:%d:%d:%d doesn't support control "
|
||||
"mode page, using defaults: TST "
|
||||
"%x, QUEUE ALG %x, SWP %x, TAS %x, "
|
||||
"has_own_order_mgmt %d",
|
||||
dev->scsi_dev->host->host_no,
|
||||
dev->scsi_dev->channel, dev->scsi_dev->id,
|
||||
dev->scsi_dev->lun, dev->tst, dev->queue_alg,
|
||||
dev->swp, dev->tas, dev->has_own_order_mgmt);
|
||||
res = 0;
|
||||
goto out;
|
||||
} else if (sense_buffer[2] == NOT_READY) {
|
||||
TRACE(TRACE_SCSI, "Device %d:%d:%d:%d not ready",
|
||||
dev->scsi_dev->host->host_no,
|
||||
dev->scsi_dev->channel, dev->scsi_dev->id,
|
||||
dev->scsi_dev->lun);
|
||||
res = 0;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
TRACE(TRACE_SCSI|TRACE_MGMT_MINOR, "Internal MODE SENSE to "
|
||||
"device %d:%d:%d:%d failed: %x",
|
||||
|
||||
@@ -204,9 +204,6 @@ int __scst_register_target_template(struct scst_tgt_template *vtt,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (vtt->preprocessing_done == NULL)
|
||||
vtt->preprocessing_done_atomic = 1;
|
||||
|
||||
if (mutex_lock_interruptible(&m) != 0)
|
||||
goto out_err;
|
||||
|
||||
|
||||
+40
-25
@@ -35,11 +35,10 @@
|
||||
#include "scst_priv.h"
|
||||
#include "scst_mem.h"
|
||||
|
||||
#define PURGE_INTERVAL (15 * HZ)
|
||||
#define PURGE_TIME_AFTER (15 * HZ)
|
||||
#define PURGE_INTERVAL (60 * HZ)
|
||||
#define PURGE_TIME_AFTER PURGE_INTERVAL
|
||||
#define SHRINK_TIME_AFTER (1 * HZ)
|
||||
|
||||
|
||||
static struct scst_sgv_pools_manager sgv_pools_mgr;
|
||||
|
||||
void scst_sgv_pool_use_norm(struct scst_tgt_dev *tgt_dev)
|
||||
@@ -342,8 +341,7 @@ static struct sgv_pool_obj *sgv_pool_cached_get(struct sgv_pool *pool,
|
||||
sgv_pools_mgr.mgr.thr.inactive_pages_total -= 1 << order;
|
||||
spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
EXTRACHECKS_BUG_ON(obj->order != order);
|
||||
|
||||
return obj;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pool->acc.cached_entries++;
|
||||
@@ -364,20 +362,43 @@ static struct sgv_pool_obj *sgv_pool_cached_get(struct sgv_pool *pool,
|
||||
spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void sgv_pool_cached_put(struct sgv_pool_obj *sgv)
|
||||
{
|
||||
struct sgv_pool *owner = sgv->owner_pool;
|
||||
struct list_head *entry;
|
||||
struct list_head *list = &owner->recycling_lists[sgv->order];
|
||||
int sched = 0;
|
||||
|
||||
spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
|
||||
list_add(&sgv->recycle_entry.recycling_list_entry,
|
||||
&owner->recycling_lists[sgv->order]);
|
||||
TRACE_MEM("sgv %p, order %d, sg_count %d", sgv, sgv->order,
|
||||
sgv->sg_count);
|
||||
|
||||
if (owner->clustered) {
|
||||
/* Make objects with less entries more preferred */
|
||||
__list_for_each(entry, list) {
|
||||
struct sgv_pool_obj *tmp = list_entry(entry,
|
||||
struct sgv_pool_obj,
|
||||
recycle_entry.recycling_list_entry);
|
||||
TRACE_DBG("tmp %p, order %d, sg_count %d", tmp,
|
||||
tmp->order, tmp->sg_count);
|
||||
if (sgv->sg_count <= tmp->sg_count)
|
||||
break;
|
||||
}
|
||||
entry = entry->prev;
|
||||
} else
|
||||
entry = list;
|
||||
|
||||
TRACE_DBG("Adding in %p (list %p)", entry, list);
|
||||
list_add(&sgv->recycle_entry.recycling_list_entry, entry);
|
||||
|
||||
list_add_tail(&sgv->recycle_entry.sorted_recycling_list_entry,
|
||||
&sgv_pools_mgr.mgr.sorted_recycling_list);
|
||||
|
||||
sgv->recycle_entry.time_stamp = jiffies;
|
||||
|
||||
sgv_pools_mgr.mgr.thr.inactive_pages_total += 1 << sgv->order;
|
||||
@@ -457,7 +478,7 @@ static int sgv_pool_hiwmk_check(int pages_to_alloc, int no_fail)
|
||||
|
||||
spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
|
||||
pages += sgv_pools_mgr.mgr.thr.active_pages_total;
|
||||
pages += atomic_read(&sgv_pools_mgr.mgr.thr.active_pages_total);
|
||||
pages += sgv_pools_mgr.mgr.thr.inactive_pages_total;
|
||||
|
||||
if (unlikely((u32)pages > sgv_pools_mgr.mgr.thr.hi_wmk)) {
|
||||
@@ -497,7 +518,7 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
|
||||
int pages_to_alloc;
|
||||
struct kmem_cache *cache;
|
||||
int no_cached = flags & SCST_POOL_ALLOC_NO_CACHED;
|
||||
int no_fail = ((gfp_mask & __GFP_NOFAIL) == __GFP_NOFAIL);
|
||||
bool no_fail = ((gfp_mask & __GFP_NOFAIL) == __GFP_NOFAIL);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -621,9 +642,7 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
|
||||
}
|
||||
|
||||
success:
|
||||
spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
sgv_pools_mgr.mgr.thr.active_pages_total += 1 << order;
|
||||
spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
atomic_add(1 << order, &sgv_pools_mgr.mgr.thr.active_pages_total);
|
||||
|
||||
if (cache) {
|
||||
int sg;
|
||||
@@ -725,9 +744,7 @@ void sgv_pool_free(struct sgv_pool_obj *sgv)
|
||||
kfree(sgv);
|
||||
}
|
||||
|
||||
spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
sgv_pools_mgr.mgr.thr.active_pages_total -= pages;
|
||||
spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
atomic_sub(pages, &sgv_pools_mgr.mgr.thr.active_pages_total);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -764,9 +781,7 @@ struct scatterlist *scst_alloc(int size, unsigned long gfp_mask, int *count)
|
||||
if (*count <= 0)
|
||||
goto out_free;
|
||||
|
||||
spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
sgv_pools_mgr.mgr.thr.active_pages_total += pages;
|
||||
spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
atomic_add(pages, &sgv_pools_mgr.mgr.thr.active_pages_total);
|
||||
|
||||
out:
|
||||
TRACE_MEM("Alloced sg %p (count %d)", res, *count);
|
||||
@@ -784,9 +799,7 @@ void scst_free(struct scatterlist *sg, int count)
|
||||
{
|
||||
TRACE_MEM("Freeing sg=%p", sg);
|
||||
|
||||
spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
sgv_pools_mgr.mgr.thr.active_pages_total -= count;
|
||||
spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
atomic_sub(count, &sgv_pools_mgr.mgr.thr.active_pages_total);
|
||||
|
||||
scst_free_sys_sg_entries(sg, count, NULL);
|
||||
kfree(sg);
|
||||
@@ -907,15 +920,15 @@ static void sgv_pool_evaluate_local_order(struct scst_sgv_pools_manager *pmgr)
|
||||
|
||||
TRACE_MEM("sgv_max_local_order %d, sgv_max_trans_order %d",
|
||||
pmgr->sgv_max_local_order, pmgr->sgv_max_trans_order);
|
||||
TRACE_MEM("max object size with embedded sgv & ttbl %d",
|
||||
TRACE_MEM("max object size with embedded sgv & ttbl %zd",
|
||||
(1 << pmgr->sgv_max_local_order) *
|
||||
(sizeof(struct trans_tbl_ent) + sizeof(struct scatterlist))
|
||||
+ sizeof(struct sgv_pool_obj));
|
||||
TRACE_MEM("max object size with embedded sgv (!clustered) %d",
|
||||
TRACE_MEM("max object size with embedded sgv (!clustered) %zd",
|
||||
(1 << pmgr->sgv_max_local_order) *
|
||||
(sizeof(struct scatterlist))
|
||||
+ sizeof(struct sgv_pool_obj));
|
||||
TRACE_MEM("max object size with embedded ttbl %d",
|
||||
TRACE_MEM("max object size with embedded ttbl %zd",
|
||||
(1 << pmgr->sgv_max_trans_order) * sizeof(struct trans_tbl_ent) +
|
||||
sizeof(struct sgv_pool_obj));
|
||||
}
|
||||
@@ -1087,6 +1100,8 @@ int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark)
|
||||
|
||||
memset(pools, 0, sizeof(*pools));
|
||||
|
||||
atomic_set(&sgv_pools_mgr.mgr.thr.active_pages_total, 0);
|
||||
|
||||
sgv_pools_mgr.mgr.thr.hi_wmk = mem_hwmark >> PAGE_SHIFT;
|
||||
sgv_pools_mgr.mgr.thr.lo_wmk = mem_lwmark >> PAGE_SHIFT;
|
||||
|
||||
@@ -1234,7 +1249,7 @@ int sgv_pool_procinfo_show(struct seq_file *seq, void *v)
|
||||
seq_printf(seq, "%-42s %d/%d\n%-42s %d/%d\n%-42s %d/%d\n\n",
|
||||
"Inactive/active pages",
|
||||
sgv_pools_mgr.mgr.thr.inactive_pages_total,
|
||||
sgv_pools_mgr.mgr.thr.active_pages_total,
|
||||
atomic_read(&sgv_pools_mgr.mgr.thr.active_pages_total),
|
||||
"Hi/lo watermarks [pages]", sgv_pools_mgr.mgr.thr.hi_wmk,
|
||||
sgv_pools_mgr.mgr.thr.lo_wmk, "Hi watermark releases/failures",
|
||||
sgv_pools_mgr.mgr.thr.releases_on_hiwmk,
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ struct scst_sgv_pools_manager
|
||||
|
||||
struct sgv_mem_throttling {
|
||||
u32 inactive_pages_total;
|
||||
u32 active_pages_total;
|
||||
atomic_t active_pages_total;
|
||||
|
||||
u32 hi_wmk; /* compared against inactive_pages_total + active_pages_total */
|
||||
u32 lo_wmk; /* compared against inactive_pages_total only */
|
||||
|
||||
+50
-70
@@ -435,19 +435,10 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||
int res = SCST_CMD_STATE_RES_CONT_SAME;
|
||||
int state;
|
||||
struct scst_device *dev = cmd->dev;
|
||||
int atomic = scst_cmd_atomic(cmd);
|
||||
int orig_bufflen = cmd->bufflen;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (atomic && !dev->handler->parse_atomic) {
|
||||
TRACE_DBG("Dev handler %s parse() can not be "
|
||||
"called in atomic context, rescheduling to the thread",
|
||||
dev->handler->name);
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (likely(!scst_is_cmd_local(cmd))) {
|
||||
TRACE_DBG("Calling dev handler %s parse(%p)",
|
||||
dev->handler->name, cmd);
|
||||
@@ -676,15 +667,6 @@ check:
|
||||
|
||||
prep_done:
|
||||
if (cmd->preprocessing_only) {
|
||||
if (scst_cmd_atomic(cmd) &&
|
||||
!cmd->tgtt->preprocessing_done_atomic) {
|
||||
TRACE_DBG("%s", "preprocessing_done() can not be "
|
||||
"called in atomic context, rescheduling to "
|
||||
"the thread");
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely(test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))) {
|
||||
TRACE_MGMT_DBG("ABORTED set, returning ABORTED for "
|
||||
"cmd %p", cmd);
|
||||
@@ -741,8 +723,7 @@ void scst_restart_cmd(struct scst_cmd *cmd, int status, int pref_context)
|
||||
|
||||
#ifdef EXTRACHECKS
|
||||
if (in_irq() && ((pref_context == SCST_CONTEXT_DIRECT) ||
|
||||
(pref_context == SCST_CONTEXT_DIRECT_ATOMIC)))
|
||||
{
|
||||
(pref_context == SCST_CONTEXT_DIRECT_ATOMIC))) {
|
||||
PRINT_ERROR("Wrong context %d in IRQ from target %s, use "
|
||||
"SCST_CONTEXT_TASKLET instead\n", pref_context,
|
||||
cmd->tgtt->name);
|
||||
@@ -847,7 +828,6 @@ out_unlock_tgt:
|
||||
static int scst_rdy_to_xfer(struct scst_cmd *cmd)
|
||||
{
|
||||
int res, rc;
|
||||
int atomic = scst_cmd_atomic(cmd);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -862,13 +842,6 @@ static int scst_rdy_to_xfer(struct scst_cmd *cmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (atomic && !cmd->tgtt->rdy_to_xfer_atomic) {
|
||||
TRACE_DBG("%s", "rdy_to_xfer() can not be "
|
||||
"called in atomic context, rescheduling to the thread");
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int finished_cmds = atomic_read(&cmd->sess->tgt->finished_cmds);
|
||||
|
||||
@@ -1707,15 +1680,6 @@ static int scst_do_send_to_midlev(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
/* Check here to let an out of SN cmd be queued w/o context switch */
|
||||
if (scst_cmd_atomic(cmd) && !handler->exec_atomic) {
|
||||
TRACE_DBG("Dev handler %s exec() can not be "
|
||||
"called in atomic context, rescheduling to the thread",
|
||||
handler->name);
|
||||
rc = SCST_EXEC_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->sent_to_midlev = 1;
|
||||
cmd->state = SCST_CMD_STATE_EXECUTING;
|
||||
cmd->scst_cmd_done = scst_cmd_done_local;
|
||||
@@ -1772,6 +1736,16 @@ static int scst_do_send_to_midlev(struct scst_cmd *cmd)
|
||||
if (unlikely(rc != 0))
|
||||
goto out_done;
|
||||
|
||||
#ifndef ALLOW_PASSTHROUGH_IO_SUBMIT_IN_SIRQ
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
TRACE_DBG("Pass-through exec() can not be called in atomic "
|
||||
"context, rescheduling to the thread (handler %s)",
|
||||
handler->name);
|
||||
rc = SCST_EXEC_NEED_THREAD;
|
||||
goto out_clear;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
if (unlikely(scst_alloc_request(cmd) != 0)) {
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
@@ -2207,7 +2181,8 @@ static int scst_done_cmd_check(struct scst_cmd *cmd, int *pres)
|
||||
|
||||
if (likely(scsi_status_is_good(cmd->status))) {
|
||||
unsigned char type = cmd->dev->handler->type;
|
||||
if ((cmd->cdb[0] == MODE_SENSE || cmd->cdb[0] == MODE_SENSE_10) &&
|
||||
if (unlikely((cmd->cdb[0] == MODE_SENSE ||
|
||||
cmd->cdb[0] == MODE_SENSE_10)) &&
|
||||
cmd->tgt_dev->acg_dev->rd_only_flag &&
|
||||
(type == TYPE_DISK || type == TYPE_WORM || type == TYPE_MOD ||
|
||||
type == TYPE_TAPE)) {
|
||||
@@ -2228,7 +2203,7 @@ static int scst_done_cmd_check(struct scst_cmd *cmd, int *pres)
|
||||
* Check and clear NormACA option for the device, if necessary,
|
||||
* since we don't support ACA
|
||||
*/
|
||||
if ((cmd->cdb[0] == INQUIRY) &&
|
||||
if (unlikely((cmd->cdb[0] == INQUIRY)) &&
|
||||
!(cmd->cdb[1] & SCST_INQ_EVPD/* Std INQUIRY data (no EVPD) */) &&
|
||||
(cmd->resp_data_len > SCST_INQ_BYTE3)) {
|
||||
uint8_t *buffer;
|
||||
@@ -2371,16 +2346,20 @@ static int scst_mode_select_checks(struct scst_cmd *cmd)
|
||||
} else if ((cmd->status == SAM_STAT_CHECK_CONDITION) &&
|
||||
SCST_SENSE_VALID(cmd->sense) &&
|
||||
scst_is_ua_sense(cmd->sense) &&
|
||||
(cmd->sense[12] == 0x2a) && (cmd->sense[13] == 0x01)) {
|
||||
(((cmd->sense[12] == 0x2a) && (cmd->sense[13] == 0x01)) ||
|
||||
(cmd->sense[12] == 0x29) /* reset */ ||
|
||||
(cmd->sense[12] == 0x28) /* medium changed */ ||
|
||||
(cmd->sense[12] == 0x2F) /* cleared by another ini (just in case) */)) {
|
||||
if (atomic) {
|
||||
TRACE_DBG("%s", "MODE PARAMETERS CHANGED UA: thread "
|
||||
"context required");
|
||||
TRACE_DBG("Possible parameters changed UA %x: "
|
||||
"thread context required", cmd->sense[12]);
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
TRACE(TRACE_SCSI, "MODE PARAMETERS CHANGED UA (lun %Ld): "
|
||||
"getting new parameters", (uint64_t)cmd->lun);
|
||||
TRACE(TRACE_SCSI, "Possible parameters changed UA %x "
|
||||
"(lun %Ld): getting new parameters", cmd->sense[12],
|
||||
(uint64_t)cmd->lun);
|
||||
|
||||
scst_obtain_device_parameters(cmd->dev);
|
||||
} else
|
||||
@@ -2405,18 +2384,9 @@ static int scst_dev_done(struct scst_cmd *cmd)
|
||||
{
|
||||
int res = SCST_CMD_STATE_RES_CONT_SAME;
|
||||
int state;
|
||||
int atomic = scst_cmd_atomic(cmd);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (atomic && !cmd->dev->handler->dev_done_atomic) {
|
||||
TRACE_DBG("Dev handler %s dev_done() can not be "
|
||||
"called in atomic context, rescheduling to the thread",
|
||||
cmd->dev->handler->name);
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
state = SCST_CMD_STATE_PRE_XMIT_RESP;
|
||||
if (likely(!scst_is_cmd_local(cmd)) &&
|
||||
likely(cmd->dev->handler->dev_done != NULL))
|
||||
@@ -2481,7 +2451,6 @@ static int scst_dev_done(struct scst_cmd *cmd)
|
||||
if (cmd->inc_expected_sn_on_done && cmd->sent_to_midlev)
|
||||
scst_inc_check_expected_sn(cmd);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_HRES(res);
|
||||
return res;
|
||||
}
|
||||
@@ -2508,6 +2477,9 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd)
|
||||
if (likely(cmd->tgt_dev != NULL)) {
|
||||
atomic_dec(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
atomic_dec(&cmd->dev->dev_cmd_count);
|
||||
/* If expected values not set, expected direction is UNKNOWN */
|
||||
if (cmd->expected_data_direction == SCST_DATA_WRITE)
|
||||
atomic_dec(&cmd->dev->write_cmd_count);
|
||||
|
||||
if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE))
|
||||
scst_on_hq_cmd_response(cmd);
|
||||
@@ -2582,17 +2554,9 @@ out:
|
||||
static int scst_xmit_response(struct scst_cmd *cmd)
|
||||
{
|
||||
int res, rc;
|
||||
int atomic = scst_cmd_atomic(cmd);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (atomic && !cmd->tgtt->xmit_response_atomic) {
|
||||
TRACE_DBG("%s", "xmit_response() can not be "
|
||||
"called in atomic context, rescheduling to the thread");
|
||||
res = SCST_CMD_STATE_RES_NEED_THREAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int finished_cmds = atomic_read(&cmd->sess->tgt->finished_cmds);
|
||||
|
||||
@@ -2755,7 +2719,8 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
|
||||
case SCST_CMD_QUEUE_UNTAGGED:
|
||||
#if 1 /* temporary, ToDo */
|
||||
if (scst_cmd_is_expected_set(cmd)) {
|
||||
if (cmd->expected_data_direction == SCST_DATA_READ)
|
||||
if ((cmd->expected_data_direction == SCST_DATA_READ) &&
|
||||
(atomic_read(&cmd->dev->write_cmd_count) == 0))
|
||||
goto ordered;
|
||||
} else
|
||||
goto ordered;
|
||||
@@ -2776,7 +2741,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
|
||||
tgt_dev->prev_cmd_ordered = 0;
|
||||
} else {
|
||||
TRACE(TRACE_MINOR, "***WARNING*** Not enough SN slots "
|
||||
"%d", ARRAY_SIZE(tgt_dev->sn_slots));
|
||||
"%zd", ARRAY_SIZE(tgt_dev->sn_slots));
|
||||
goto ordered;
|
||||
}
|
||||
break;
|
||||
@@ -2917,23 +2882,38 @@ static int __scst_init_cmd(struct scst_cmd *cmd)
|
||||
res = scst_translate_lun(cmd);
|
||||
if (likely(res == 0)) {
|
||||
int cnt;
|
||||
bool failure = false;
|
||||
|
||||
cmd->state = SCST_CMD_STATE_PRE_PARSE;
|
||||
|
||||
cnt = atomic_inc_return(&cmd->tgt_dev->tgt_dev_cmd_count);
|
||||
if (unlikely(cnt > SCST_MAX_TGT_DEV_COMMANDS)) {
|
||||
TRACE(TRACE_MGMT_MINOR, "Too many pending commands (%d) in "
|
||||
"session, returning BUSY to initiator \"%s\"",
|
||||
cnt, (cmd->sess->initiator_name[0] == '\0') ?
|
||||
"Anonymous" : cmd->sess->initiator_name);
|
||||
goto out_busy;
|
||||
failure = true;
|
||||
}
|
||||
|
||||
cnt = atomic_inc_return(&cmd->dev->dev_cmd_count);
|
||||
if (unlikely(cnt > SCST_MAX_DEV_COMMANDS)) {
|
||||
TRACE(TRACE_MGMT_MINOR, "Too many pending device commands "
|
||||
"(%d), returning BUSY to initiator \"%s\"",
|
||||
cnt, (cmd->sess->initiator_name[0] == '\0') ?
|
||||
"Anonymous" : cmd->sess->initiator_name);
|
||||
goto out_busy;
|
||||
if (!failure) {
|
||||
TRACE(TRACE_MGMT_MINOR, "Too many pending device "
|
||||
"commands (%d), returning BUSY to "
|
||||
"initiator \"%s\"", cnt,
|
||||
(cmd->sess->initiator_name[0] == '\0') ?
|
||||
"Anonymous" : cmd->sess->initiator_name);
|
||||
failure = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If expected values not set, expected direction is UNKNOWN */
|
||||
if (cmd->expected_data_direction == SCST_DATA_WRITE)
|
||||
atomic_inc(&cmd->dev->write_cmd_count);
|
||||
|
||||
if (unlikely(failure))
|
||||
goto out_busy;
|
||||
|
||||
if (!cmd->set_sn_on_restart_cmd)
|
||||
scst_cmd_set_sn(cmd);
|
||||
} else if (res < 0) {
|
||||
|
||||
+2
-2
@@ -41,10 +41,10 @@ CFLAGS += -DDEBUG -g
|
||||
all: $(PROGS)
|
||||
|
||||
fileio_tgt: .depend_f $(OBJS_F)
|
||||
$(CC) $(OBJS_F) $(LIBS) -o $@
|
||||
$(CC) $(OBJS_F) $(LIBS) $(LOCAL_LD_FLAGS) -o $@
|
||||
|
||||
#cdrom_tgt: .depend_c $(OBJS_C)
|
||||
# $(CC) $(OBJS_C) $(LIBS) -o $@
|
||||
# $(CC) $(OBJS_C) $(LIBS) $(LOCAL_LD_FLAGS) -o $@
|
||||
|
||||
ifeq (.depend_f,$(wildcard .depend_f))
|
||||
-include .depend_f
|
||||
|
||||
+54
-46
@@ -23,6 +23,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
@@ -224,7 +225,8 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
else
|
||||
#endif
|
||||
cmd->pbuf = (unsigned long)dev->alloc_fn(cmd->alloc_len);
|
||||
TRACE_MEM("Buf %Lx alloced, len %d", cmd->pbuf, cmd->alloc_len);
|
||||
TRACE_MEM("Buf %"PRIx64" alloced, len %d", cmd->pbuf,
|
||||
cmd->alloc_len);
|
||||
reply->pbuf = cmd->pbuf;
|
||||
if (cmd->pbuf == 0) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "Unable to allocate buffer "
|
||||
@@ -286,12 +288,12 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
}
|
||||
|
||||
loff = (loff_t)lba_start << dev->block_shift;
|
||||
TRACE_DBG("cmd %d, buf %Lx, lba_start %Ld, loff %Ld, data_len %Ld",
|
||||
vcmd->cmd->cmd_h, cmd->pbuf, lba_start, (uint64_t)loff,
|
||||
(uint64_t)data_len);
|
||||
TRACE_DBG("cmd %d, buf %"PRIx64", lba_start %"PRId64", loff %"PRId64
|
||||
", data_len %"PRId64, vcmd->cmd->cmd_h, cmd->pbuf, lba_start,
|
||||
(uint64_t)loff, (uint64_t)data_len);
|
||||
if ((loff < 0) || (data_len < 0) || ((loff + data_len) > dev->file_size)) {
|
||||
PRINT_INFO("Access beyond the end of the device "
|
||||
"(%lld of %lld, len %Ld)", (uint64_t)loff,
|
||||
"(%"PRId64" of %"PRId64", len %"PRId64")", (uint64_t)loff,
|
||||
(uint64_t)dev->file_size, (uint64_t)data_len);
|
||||
set_cmd_error(vcmd, SCST_LOAD_SENSE(
|
||||
scst_sense_block_out_range_error));
|
||||
@@ -304,8 +306,8 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
case WRITE_16:
|
||||
fua = (cdb[1] & 0x8);
|
||||
if (cdb[1] & 0x8) {
|
||||
TRACE(TRACE_ORDER, "FUA(%d): loff=%Ld, "
|
||||
"data_len=%Ld", fua, (uint64_t)loff,
|
||||
TRACE(TRACE_ORDER, "FUA(%d): loff=%"PRId64", "
|
||||
"data_len=%"PRId64, fua, (uint64_t)loff,
|
||||
(uint64_t)data_len);
|
||||
}
|
||||
break;
|
||||
@@ -329,7 +331,7 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
|
||||
tgt_dev = find_tgt_dev(dev, cmd->sess_h);
|
||||
if (tgt_dev == NULL) {
|
||||
PRINT_ERROR("Session %Lx not found",
|
||||
PRINT_ERROR("Session %"PRIx64" not found",
|
||||
cmd->sess_h);
|
||||
set_cmd_error(vcmd,
|
||||
SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
@@ -340,8 +342,8 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
tgt_dev->last_write_cmd_queue_type = cmd->queue_type;
|
||||
if (need_pre_sync(cmd->queue_type, last_queue_type)) {
|
||||
TRACE(TRACE_ORDER, "ORDERED "
|
||||
"WRITE(%d): loff=%Ld, data_len=%Ld",
|
||||
cmd->queue_type, (uint64_t)loff,
|
||||
"WRITE(%d): loff=%"PRId64", data_len=%"
|
||||
PRId64, cmd->queue_type, (uint64_t)loff,
|
||||
(uint64_t)data_len);
|
||||
do_fsync = 1;
|
||||
if (exec_fsync(vcmd) != 0)
|
||||
@@ -368,7 +370,7 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
|
||||
tgt_dev = find_tgt_dev(dev, cmd->sess_h);
|
||||
if (tgt_dev == NULL) {
|
||||
PRINT_ERROR("Session %Lx not found",
|
||||
PRINT_ERROR("Session %"PRIx64" not found",
|
||||
cmd->sess_h);
|
||||
set_cmd_error(vcmd,
|
||||
SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
@@ -379,9 +381,9 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
tgt_dev->last_write_cmd_queue_type = cmd->queue_type;
|
||||
if (need_pre_sync(cmd->queue_type, last_queue_type)) {
|
||||
TRACE(TRACE_ORDER, "ORDERED "
|
||||
"WRITE_VERIFY(%d): loff=%Ld, data_len=%Ld",
|
||||
cmd->queue_type, (uint64_t)loff,
|
||||
(uint64_t)data_len);
|
||||
"WRITE_VERIFY(%d): loff=%"PRId64", "
|
||||
"data_len=%"PRId64, cmd->queue_type,
|
||||
(uint64_t)loff, (uint64_t)data_len);
|
||||
do_fsync = 1;
|
||||
if (exec_fsync(vcmd) != 0)
|
||||
goto out;
|
||||
@@ -403,8 +405,8 @@ static int do_exec(struct vdisk_cmd *vcmd)
|
||||
{
|
||||
int immed = cdb[1] & 0x2;
|
||||
TRACE(TRACE_ORDER, "SYNCHRONIZE_CACHE: "
|
||||
"loff=%Ld, data_len=%Ld, immed=%d", (uint64_t)loff,
|
||||
(uint64_t)data_len, immed);
|
||||
"loff=%"PRId64", data_len=%"PRId64", immed=%d",
|
||||
(uint64_t)loff, (uint64_t)data_len, immed);
|
||||
if (immed) {
|
||||
/* ToDo: backgroung exec */
|
||||
exec_fsync(vcmd);
|
||||
@@ -478,7 +480,7 @@ static int do_alloc_mem(struct vdisk_cmd *vcmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_MEM("Alloc mem (cmd %d, sess_h %Lx, cdb_len %d, "
|
||||
TRACE_MEM("Alloc mem (cmd %d, sess_h %"PRIx64", cdb_len %d, "
|
||||
"alloc_len %d, queue_type %d, data_direction %d)", cmd->cmd_h,
|
||||
cmd->alloc_cmd.sess_h, cmd->alloc_cmd.cdb_len,
|
||||
cmd->alloc_cmd.alloc_len, cmd->alloc_cmd.queue_type,
|
||||
@@ -497,7 +499,7 @@ static int do_alloc_mem(struct vdisk_cmd *vcmd)
|
||||
#endif
|
||||
reply->alloc_reply.pbuf = (unsigned long)vcmd->dev->alloc_fn(
|
||||
cmd->alloc_cmd.alloc_len);
|
||||
TRACE_MEM("Buf %Lx alloced, len %d", reply->alloc_reply.pbuf,
|
||||
TRACE_MEM("Buf %"PRIx64" alloced, len %d", reply->alloc_reply.pbuf,
|
||||
cmd->alloc_cmd.alloc_len);
|
||||
if (reply->alloc_reply.pbuf == 0) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "Unable to allocate buffer (len %d)",
|
||||
@@ -516,7 +518,7 @@ static int do_cached_mem_free(struct vdisk_cmd *vcmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_MEM("Cached mem free (cmd %d, buf %Lx)", cmd->cmd_h,
|
||||
TRACE_MEM("Cached mem free (cmd %d, buf %"PRIx64")", cmd->cmd_h,
|
||||
cmd->on_cached_mem_free.pbuf);
|
||||
|
||||
free((void*)(unsigned long)cmd->on_cached_mem_free.pbuf);
|
||||
@@ -542,11 +544,12 @@ static int do_on_free_cmd(struct vdisk_cmd *vcmd)
|
||||
cmd->on_free_cmd.resp_data_len, cmd->on_free_cmd.aborted,
|
||||
cmd->on_free_cmd.status, cmd->on_free_cmd.delivery_status);
|
||||
|
||||
TRACE_MEM("On free cmd (cmd %d, buf %Lx, buffer_cached %d)", cmd->cmd_h,
|
||||
cmd->on_free_cmd.pbuf, cmd->on_free_cmd.buffer_cached);
|
||||
TRACE_MEM("On free cmd (cmd %d, buf %"PRIx64", buffer_cached %d)",
|
||||
cmd->cmd_h, cmd->on_free_cmd.pbuf,
|
||||
cmd->on_free_cmd.buffer_cached);
|
||||
|
||||
if (!cmd->on_free_cmd.buffer_cached && (cmd->on_free_cmd.pbuf != 0)) {
|
||||
TRACE_MEM("Freeing buf %Lx", cmd->on_free_cmd.pbuf);
|
||||
TRACE_MEM("Freeing buf %"PRIx64, cmd->on_free_cmd.pbuf);
|
||||
free((void*)(unsigned long)cmd->on_free_cmd.pbuf);
|
||||
}
|
||||
|
||||
@@ -567,7 +570,7 @@ static int do_tm(struct vdisk_cmd *vcmd)
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE((cmd->tm_cmd.fn == SCST_ABORT_TASK) ? TRACE_MGMT_MINOR : TRACE_MGMT,
|
||||
"TM fn %d (sess_h %Lx, cmd_h_to_abort %d)", cmd->tm_cmd.fn,
|
||||
"TM fn %d (sess_h %"PRIx64", cmd_h_to_abort %d)", cmd->tm_cmd.fn,
|
||||
cmd->tm_cmd.sess_h, cmd->tm_cmd.cmd_h_to_abort);
|
||||
|
||||
memset(reply, 0, sizeof(*reply));
|
||||
@@ -597,7 +600,7 @@ static int do_sess(struct vdisk_cmd *vcmd)
|
||||
|
||||
if (cmd->subcode == SCST_USER_ATTACH_SESS) {
|
||||
if (tgt_dev != NULL) {
|
||||
PRINT_ERROR("Session %Lx already exists)",
|
||||
PRINT_ERROR("Session %"PRIx64" already exists)",
|
||||
cmd->sess.sess_h);
|
||||
res = EEXIST;
|
||||
goto reply;
|
||||
@@ -605,8 +608,8 @@ static int do_sess(struct vdisk_cmd *vcmd)
|
||||
|
||||
tgt_dev = find_empty_tgt_dev(vcmd->dev);
|
||||
if (tgt_dev == NULL) {
|
||||
PRINT_ERROR("Too many initiators, session %Lx refused)",
|
||||
cmd->sess.sess_h);
|
||||
PRINT_ERROR("Too many initiators, session %"PRIx64
|
||||
" refused)", cmd->sess.sess_h);
|
||||
res = ENOMEM;
|
||||
goto reply;
|
||||
}
|
||||
@@ -614,19 +617,21 @@ static int do_sess(struct vdisk_cmd *vcmd)
|
||||
tgt_dev->sess_h = cmd->sess.sess_h;
|
||||
tgt_dev->last_write_cmd_queue_type = SCST_CMD_QUEUE_SIMPLE;
|
||||
|
||||
PRINT_INFO("Session from initiator %s attached (LUN %Lx, "
|
||||
"threads_num %d, rd_only %d, sess_h %Lx)",
|
||||
PRINT_INFO("Session from initiator %s attached (LUN %"PRIx64", "
|
||||
"threads_num %d, rd_only %d, sess_h %"PRIx64")",
|
||||
cmd->sess.initiator_name, cmd->sess.lun,
|
||||
cmd->sess.threads_num, cmd->sess.rd_only,
|
||||
cmd->sess.sess_h);
|
||||
} else {
|
||||
if (tgt_dev == NULL) {
|
||||
PRINT_ERROR("Session %Lx not found)", cmd->sess.sess_h);
|
||||
PRINT_ERROR("Session %"PRIx64" not found)",
|
||||
cmd->sess.sess_h);
|
||||
res = ESRCH;
|
||||
goto reply;
|
||||
}
|
||||
tgt_dev->sess_h = 0;
|
||||
PRINT_INFO("Session detached (sess_h %Lx)", cmd->sess.sess_h);
|
||||
PRINT_INFO("Session detached (sess_h %"PRIx64")",
|
||||
cmd->sess.sess_h);
|
||||
}
|
||||
|
||||
reply:
|
||||
@@ -824,7 +829,7 @@ out:
|
||||
PRINT_INFO("Thread %d exiting (res=%d)", gettid(), res);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return (void*)res;
|
||||
return (void*)(long)res;
|
||||
}
|
||||
|
||||
void *prio_loop(void *arg)
|
||||
@@ -896,7 +901,7 @@ out_close:
|
||||
PRINT_INFO("Prio thread %d exited (res=%d)", gettid(), res);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return (void*)res;
|
||||
return (void*)(long)res;
|
||||
}
|
||||
|
||||
static void exec_inquiry(struct vdisk_cmd *vcmd)
|
||||
@@ -1579,15 +1584,16 @@ static void exec_read(struct vdisk_cmd *vcmd, loff_t loff)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("reading off %lld, len %d", loff, length);
|
||||
TRACE_DBG("reading off %"PRId64", len %d", loff, length);
|
||||
if (dev->nullio)
|
||||
err = length;
|
||||
else {
|
||||
/* SEEK */
|
||||
err = lseek64(fd, loff, 0/*SEEK_SET*/);
|
||||
if (err != loff) {
|
||||
PRINT_ERROR("lseek trouble %Ld != %Ld (errno %d)",
|
||||
(uint64_t)err, (uint64_t)loff, errno);
|
||||
PRINT_ERROR("lseek trouble %"PRId64" != %"PRId64
|
||||
" (errno %d)", (uint64_t)err, (uint64_t)loff,
|
||||
errno);
|
||||
set_cmd_error(vcmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
goto out;
|
||||
}
|
||||
@@ -1596,7 +1602,7 @@ static void exec_read(struct vdisk_cmd *vcmd, loff_t loff)
|
||||
}
|
||||
|
||||
if ((err < 0) || (err < length)) {
|
||||
PRINT_ERROR("read() returned %Ld from %d (errno %d)",
|
||||
PRINT_ERROR("read() returned %"PRId64" from %d (errno %d)",
|
||||
(uint64_t)err, length, errno);
|
||||
if (err == -EAGAIN)
|
||||
set_busy(reply);
|
||||
@@ -1627,7 +1633,7 @@ static void exec_write(struct vdisk_cmd *vcmd, loff_t loff)
|
||||
TRACE_ENTRY();
|
||||
|
||||
restart:
|
||||
TRACE_DBG("writing off %lld, len %d", loff, length);
|
||||
TRACE_DBG("writing off %"PRId64", len %d", loff, length);
|
||||
|
||||
if (dev->nullio)
|
||||
err = length;
|
||||
@@ -1635,8 +1641,9 @@ restart:
|
||||
/* SEEK */
|
||||
err = lseek64(fd, loff, 0/*SEEK_SET*/);
|
||||
if (err != loff) {
|
||||
PRINT_ERROR("lseek trouble %Ld != %Ld (errno %d)",
|
||||
(uint64_t)err, (uint64_t)loff, errno);
|
||||
PRINT_ERROR("lseek trouble %"PRId64" != %"PRId64
|
||||
" (errno %d)", (uint64_t)err, (uint64_t)loff,
|
||||
errno);
|
||||
set_cmd_error(vcmd,
|
||||
SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
goto out;
|
||||
@@ -1647,8 +1654,8 @@ restart:
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
PRINT_ERROR("write() returned %Ld from %zd (errno %d, cmd_h "
|
||||
"%x)", (uint64_t)err, length, errno, vcmd->cmd->cmd_h);
|
||||
PRINT_ERROR("write() returned %"PRId64" from %d (errno %d, "
|
||||
"cmd_h %x)", err, length, errno, vcmd->cmd->cmd_h);
|
||||
if (err == -EAGAIN)
|
||||
set_busy(reply);
|
||||
else {
|
||||
@@ -1704,8 +1711,9 @@ static void exec_verify(struct vdisk_cmd *vcmd, loff_t loff)
|
||||
if (!dev->nullio) {
|
||||
err = lseek64(fd, loff, 0/*SEEK_SET*/);
|
||||
if (err != loff) {
|
||||
PRINT_ERROR("lseek trouble %Ld != %Ld (errno %d)",
|
||||
(uint64_t)err, (uint64_t)loff, errno);
|
||||
PRINT_ERROR("lseek trouble %"PRId64" != %"PRId64
|
||||
" (errno %d)", (uint64_t)err,
|
||||
(uint64_t)loff, errno);
|
||||
set_cmd_error(vcmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
goto out;
|
||||
}
|
||||
@@ -1727,8 +1735,8 @@ static void exec_verify(struct vdisk_cmd *vcmd, loff_t loff)
|
||||
else
|
||||
err = len_mem;
|
||||
if ((err < 0) || (err < len_mem)) {
|
||||
PRINT_ERROR("read() returned %Ld from %d (errno %d)",
|
||||
(uint64_t)err, len_mem, errno);
|
||||
PRINT_ERROR("read() returned %"PRId64" from %d "
|
||||
"(errno %d)", (uint64_t)err, len_mem, errno);
|
||||
if (err == -EAGAIN)
|
||||
set_busy(reply);
|
||||
else {
|
||||
@@ -1738,7 +1746,7 @@ static void exec_verify(struct vdisk_cmd *vcmd, loff_t loff)
|
||||
goto out;
|
||||
}
|
||||
if (compare && memcmp(address, mem_verify, len_mem) != 0) {
|
||||
TRACE_DBG("Verify: error memcmp length %zd", length);
|
||||
TRACE_DBG("Verify: error memcmp length %d", length);
|
||||
set_cmd_error(vcmd,
|
||||
SCST_LOAD_SENSE(scst_sense_miscompare_error));
|
||||
goto out;
|
||||
|
||||
+11
-7
@@ -24,6 +24,7 @@
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <malloc.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
@@ -287,9 +288,10 @@ int main(int argc, char **argv)
|
||||
|
||||
close(fd);
|
||||
|
||||
PRINT_INFO("Virtual device \"%s\", path \"%s\", size %LdMb, "
|
||||
"block size %d, nblocks %Ld, options:", dev.name, dev.file_name,
|
||||
dev.file_size/1024/1024, dev.block_size, dev.nblocks);
|
||||
PRINT_INFO("Virtual device \"%s\", path \"%s\", size %"PRId64"Mb, "
|
||||
"block size %d, nblocks %"PRId64", options:", dev.name,
|
||||
dev.file_name, (uint64_t)dev.file_size/1024/1024,
|
||||
dev.block_size, (uint64_t)dev.nblocks);
|
||||
if (dev.rd_only_flag)
|
||||
PRINT_INFO(" %s", "READ ONLY");
|
||||
if (dev.wt_flag)
|
||||
@@ -467,8 +469,9 @@ int main(int argc, char **argv)
|
||||
PRINT_ERROR("pthread_join() failed: %s",
|
||||
strerror(res));
|
||||
} else if (rc1 != NULL) {
|
||||
res = (int)rc1;
|
||||
PRINT_INFO("Thread %d exited, res %x", i, res);
|
||||
res = (long)rc1;
|
||||
PRINT_INFO("Thread %d exited, res %lx", i,
|
||||
(long)rc1);
|
||||
} else
|
||||
PRINT_INFO("Thread %d exited", i);
|
||||
}
|
||||
@@ -479,8 +482,9 @@ int main(int argc, char **argv)
|
||||
PRINT_ERROR("Prio pthread_join() failed: %s",
|
||||
strerror(res));
|
||||
} else if (rc1 != NULL) {
|
||||
res = (int)rc1;
|
||||
PRINT_INFO("Prio thread %d exited, res %x", i, res);
|
||||
res = (long)rc1;
|
||||
PRINT_INFO("Prio thread %d exited, res %lx", i,
|
||||
(long)rc1);
|
||||
} else
|
||||
PRINT_INFO("Prio thread %d exited", i);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user