mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-14 21:01:29 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull scsi target fixes from Nicholas Bellinger: "The highlights include: - Re-instate sess->wait_list in target_wait_for_sess_cmds() for active I/O shutdown handling in fabrics using se_cmd->cmd_kref - Make ib_srpt call target_sess_cmd_list_set_waiting() during session shutdown - Fix FILEIO off-by-one READ_CAPACITY bug for !S_ISBLK export - Fix iscsi-target login error heap buffer overflow (Kees) - Fix iscsi-target active I/O shutdown handling regression in v3.10-rc1 A big thanks to Kees Cook for fixing a long standing login error buffer overflow bug. All patches are CC'ed to stable with the exception of the v3.10-rc1 specific regression + other minor target cleanup." * git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: iscsi-target: Fix iscsit_free_cmd() se_cmd->cmd_kref shutdown handling target: Propigate up ->cmd_kref put return via transport_generic_free_cmd iscsi-target: fix heap buffer overflow on error target/file: Fix off-by-one READ_CAPACITY bug for !S_ISBLK export ib_srpt: Call target_sess_cmd_list_set_waiting during shutdown_session target: Re-instate sess_wait_list for target_wait_for_sess_cmds target: Remove unused wait_for_tasks bit in target_wait_for_sess_cmds
This commit is contained in:
commit
008bd2de94
@ -2226,6 +2226,27 @@ static void srpt_close_ch(struct srpt_rdma_ch *ch)
|
|||||||
spin_unlock_irq(&sdev->spinlock);
|
spin_unlock_irq(&sdev->spinlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* srpt_shutdown_session() - Whether or not a session may be shut down.
|
||||||
|
*/
|
||||||
|
static int srpt_shutdown_session(struct se_session *se_sess)
|
||||||
|
{
|
||||||
|
struct srpt_rdma_ch *ch = se_sess->fabric_sess_ptr;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ch->spinlock, flags);
|
||||||
|
if (ch->in_shutdown) {
|
||||||
|
spin_unlock_irqrestore(&ch->spinlock, flags);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch->in_shutdown = true;
|
||||||
|
target_sess_cmd_list_set_waiting(se_sess);
|
||||||
|
spin_unlock_irqrestore(&ch->spinlock, flags);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* srpt_drain_channel() - Drain a channel by resetting the IB queue pair.
|
* srpt_drain_channel() - Drain a channel by resetting the IB queue pair.
|
||||||
* @cm_id: Pointer to the CM ID of the channel to be drained.
|
* @cm_id: Pointer to the CM ID of the channel to be drained.
|
||||||
@ -2264,6 +2285,9 @@ static void srpt_drain_channel(struct ib_cm_id *cm_id)
|
|||||||
spin_unlock_irq(&sdev->spinlock);
|
spin_unlock_irq(&sdev->spinlock);
|
||||||
|
|
||||||
if (do_reset) {
|
if (do_reset) {
|
||||||
|
if (ch->sess)
|
||||||
|
srpt_shutdown_session(ch->sess);
|
||||||
|
|
||||||
ret = srpt_ch_qp_err(ch);
|
ret = srpt_ch_qp_err(ch);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
printk(KERN_ERR "Setting queue pair in error state"
|
printk(KERN_ERR "Setting queue pair in error state"
|
||||||
@ -2328,7 +2352,7 @@ static void srpt_release_channel_work(struct work_struct *w)
|
|||||||
se_sess = ch->sess;
|
se_sess = ch->sess;
|
||||||
BUG_ON(!se_sess);
|
BUG_ON(!se_sess);
|
||||||
|
|
||||||
target_wait_for_sess_cmds(se_sess, 0);
|
target_wait_for_sess_cmds(se_sess);
|
||||||
|
|
||||||
transport_deregister_session_configfs(se_sess);
|
transport_deregister_session_configfs(se_sess);
|
||||||
transport_deregister_session(se_sess);
|
transport_deregister_session(se_sess);
|
||||||
@ -3466,14 +3490,6 @@ static void srpt_release_cmd(struct se_cmd *se_cmd)
|
|||||||
spin_unlock_irqrestore(&ch->spinlock, flags);
|
spin_unlock_irqrestore(&ch->spinlock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* srpt_shutdown_session() - Whether or not a session may be shut down.
|
|
||||||
*/
|
|
||||||
static int srpt_shutdown_session(struct se_session *se_sess)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* srpt_close_session() - Forcibly close a session.
|
* srpt_close_session() - Forcibly close a session.
|
||||||
*
|
*
|
||||||
|
@ -325,6 +325,7 @@ struct srpt_rdma_ch {
|
|||||||
u8 sess_name[36];
|
u8 sess_name[36];
|
||||||
struct work_struct release_work;
|
struct work_struct release_work;
|
||||||
struct completion *release_done;
|
struct completion *release_done;
|
||||||
|
bool in_shutdown;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1370,7 +1370,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
|
|||||||
dump_stack();
|
dump_stack();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
target_wait_for_sess_cmds(se_sess, 0);
|
target_wait_for_sess_cmds(se_sess);
|
||||||
|
|
||||||
transport_deregister_session_configfs(sess->se_sess);
|
transport_deregister_session_configfs(sess->se_sess);
|
||||||
transport_deregister_session(sess->se_sess);
|
transport_deregister_session(sess->se_sess);
|
||||||
|
@ -651,7 +651,7 @@ static int iscsit_add_reject(
|
|||||||
cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
|
cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
|
||||||
if (!cmd->buf_ptr) {
|
if (!cmd->buf_ptr) {
|
||||||
pr_err("Unable to allocate memory for cmd->buf_ptr\n");
|
pr_err("Unable to allocate memory for cmd->buf_ptr\n");
|
||||||
iscsit_release_cmd(cmd);
|
iscsit_free_cmd(cmd, false);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,7 +697,7 @@ int iscsit_add_reject_from_cmd(
|
|||||||
cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
|
cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
|
||||||
if (!cmd->buf_ptr) {
|
if (!cmd->buf_ptr) {
|
||||||
pr_err("Unable to allocate memory for cmd->buf_ptr\n");
|
pr_err("Unable to allocate memory for cmd->buf_ptr\n");
|
||||||
iscsit_release_cmd(cmd);
|
iscsit_free_cmd(cmd, false);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1743,7 +1743,7 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||||||
return 0;
|
return 0;
|
||||||
out:
|
out:
|
||||||
if (cmd)
|
if (cmd)
|
||||||
iscsit_release_cmd(cmd);
|
iscsit_free_cmd(cmd, false);
|
||||||
ping_out:
|
ping_out:
|
||||||
kfree(ping_data);
|
kfree(ping_data);
|
||||||
return ret;
|
return ret;
|
||||||
@ -2251,7 +2251,7 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||||||
if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
|
if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
|
||||||
pr_err("Received logout request on connection that"
|
pr_err("Received logout request on connection that"
|
||||||
" is not in logged in state, ignoring request.\n");
|
" is not in logged in state, ignoring request.\n");
|
||||||
iscsit_release_cmd(cmd);
|
iscsit_free_cmd(cmd, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3665,7 +3665,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state
|
|||||||
list_del(&cmd->i_conn_node);
|
list_del(&cmd->i_conn_node);
|
||||||
spin_unlock_bh(&conn->cmd_lock);
|
spin_unlock_bh(&conn->cmd_lock);
|
||||||
|
|
||||||
iscsit_free_cmd(cmd);
|
iscsit_free_cmd(cmd, false);
|
||||||
break;
|
break;
|
||||||
case ISTATE_SEND_NOPIN_WANT_RESPONSE:
|
case ISTATE_SEND_NOPIN_WANT_RESPONSE:
|
||||||
iscsit_mod_nopin_response_timer(conn);
|
iscsit_mod_nopin_response_timer(conn);
|
||||||
@ -4122,7 +4122,7 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
|
|||||||
|
|
||||||
iscsit_increment_maxcmdsn(cmd, sess);
|
iscsit_increment_maxcmdsn(cmd, sess);
|
||||||
|
|
||||||
iscsit_free_cmd(cmd);
|
iscsit_free_cmd(cmd, true);
|
||||||
|
|
||||||
spin_lock_bh(&conn->cmd_lock);
|
spin_lock_bh(&conn->cmd_lock);
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
|
|||||||
list_del(&cmd->i_conn_node);
|
list_del(&cmd->i_conn_node);
|
||||||
cmd->conn = NULL;
|
cmd->conn = NULL;
|
||||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||||
iscsit_free_cmd(cmd);
|
iscsit_free_cmd(cmd, true);
|
||||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||||
@ -165,7 +165,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
|
|||||||
list_del(&cmd->i_conn_node);
|
list_del(&cmd->i_conn_node);
|
||||||
cmd->conn = NULL;
|
cmd->conn = NULL;
|
||||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||||
iscsit_free_cmd(cmd);
|
iscsit_free_cmd(cmd, true);
|
||||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||||
@ -248,7 +248,7 @@ void iscsit_discard_cr_cmds_by_expstatsn(
|
|||||||
iscsit_remove_cmd_from_connection_recovery(cmd, sess);
|
iscsit_remove_cmd_from_connection_recovery(cmd, sess);
|
||||||
|
|
||||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||||
iscsit_free_cmd(cmd);
|
iscsit_free_cmd(cmd, true);
|
||||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||||
}
|
}
|
||||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||||
@ -302,7 +302,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
|
|||||||
list_del(&cmd->i_conn_node);
|
list_del(&cmd->i_conn_node);
|
||||||
|
|
||||||
spin_unlock_bh(&conn->cmd_lock);
|
spin_unlock_bh(&conn->cmd_lock);
|
||||||
iscsit_free_cmd(cmd);
|
iscsit_free_cmd(cmd, true);
|
||||||
spin_lock_bh(&conn->cmd_lock);
|
spin_lock_bh(&conn->cmd_lock);
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&conn->cmd_lock);
|
spin_unlock_bh(&conn->cmd_lock);
|
||||||
@ -355,7 +355,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
|||||||
|
|
||||||
list_del(&cmd->i_conn_node);
|
list_del(&cmd->i_conn_node);
|
||||||
spin_unlock_bh(&conn->cmd_lock);
|
spin_unlock_bh(&conn->cmd_lock);
|
||||||
iscsit_free_cmd(cmd);
|
iscsit_free_cmd(cmd, true);
|
||||||
spin_lock_bh(&conn->cmd_lock);
|
spin_lock_bh(&conn->cmd_lock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -375,7 +375,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
|||||||
iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) {
|
iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) {
|
||||||
list_del(&cmd->i_conn_node);
|
list_del(&cmd->i_conn_node);
|
||||||
spin_unlock_bh(&conn->cmd_lock);
|
spin_unlock_bh(&conn->cmd_lock);
|
||||||
iscsit_free_cmd(cmd);
|
iscsit_free_cmd(cmd, true);
|
||||||
spin_lock_bh(&conn->cmd_lock);
|
spin_lock_bh(&conn->cmd_lock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -758,9 +758,9 @@ static int iscsi_add_notunderstood_response(
|
|||||||
}
|
}
|
||||||
INIT_LIST_HEAD(&extra_response->er_list);
|
INIT_LIST_HEAD(&extra_response->er_list);
|
||||||
|
|
||||||
strncpy(extra_response->key, key, strlen(key) + 1);
|
strlcpy(extra_response->key, key, sizeof(extra_response->key));
|
||||||
strncpy(extra_response->value, NOTUNDERSTOOD,
|
strlcpy(extra_response->value, NOTUNDERSTOOD,
|
||||||
strlen(NOTUNDERSTOOD) + 1);
|
sizeof(extra_response->value));
|
||||||
|
|
||||||
list_add_tail(&extra_response->er_list,
|
list_add_tail(&extra_response->er_list,
|
||||||
¶m_list->extra_response_list);
|
¶m_list->extra_response_list);
|
||||||
@ -1629,8 +1629,6 @@ int iscsi_decode_text_input(
|
|||||||
|
|
||||||
if (phase & PHASE_SECURITY) {
|
if (phase & PHASE_SECURITY) {
|
||||||
if (iscsi_check_for_auth_key(key) > 0) {
|
if (iscsi_check_for_auth_key(key) > 0) {
|
||||||
char *tmpptr = key + strlen(key);
|
|
||||||
*tmpptr = '=';
|
|
||||||
kfree(tmpbuf);
|
kfree(tmpbuf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#ifndef ISCSI_PARAMETERS_H
|
#ifndef ISCSI_PARAMETERS_H
|
||||||
#define ISCSI_PARAMETERS_H
|
#define ISCSI_PARAMETERS_H
|
||||||
|
|
||||||
|
#include <scsi/iscsi_proto.h>
|
||||||
|
|
||||||
struct iscsi_extra_response {
|
struct iscsi_extra_response {
|
||||||
char key[64];
|
char key[KEY_MAXLEN];
|
||||||
char value[32];
|
char value[32];
|
||||||
struct list_head er_list;
|
struct list_head er_list;
|
||||||
} ____cacheline_aligned;
|
} ____cacheline_aligned;
|
||||||
|
@ -676,40 +676,56 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
|
|||||||
|
|
||||||
void iscsit_release_cmd(struct iscsi_cmd *cmd)
|
void iscsit_release_cmd(struct iscsi_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct iscsi_conn *conn = cmd->conn;
|
|
||||||
|
|
||||||
iscsit_free_r2ts_from_list(cmd);
|
|
||||||
iscsit_free_all_datain_reqs(cmd);
|
|
||||||
|
|
||||||
kfree(cmd->buf_ptr);
|
kfree(cmd->buf_ptr);
|
||||||
kfree(cmd->pdu_list);
|
kfree(cmd->pdu_list);
|
||||||
kfree(cmd->seq_list);
|
kfree(cmd->seq_list);
|
||||||
kfree(cmd->tmr_req);
|
kfree(cmd->tmr_req);
|
||||||
kfree(cmd->iov_data);
|
kfree(cmd->iov_data);
|
||||||
|
|
||||||
if (conn) {
|
|
||||||
iscsit_remove_cmd_from_immediate_queue(cmd, conn);
|
|
||||||
iscsit_remove_cmd_from_response_queue(cmd, conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
kmem_cache_free(lio_cmd_cache, cmd);
|
kmem_cache_free(lio_cmd_cache, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void iscsit_free_cmd(struct iscsi_cmd *cmd)
|
static void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd,
|
||||||
|
bool check_queues)
|
||||||
{
|
{
|
||||||
|
struct iscsi_conn *conn = cmd->conn;
|
||||||
|
|
||||||
|
if (scsi_cmd) {
|
||||||
|
if (cmd->data_direction == DMA_TO_DEVICE) {
|
||||||
|
iscsit_stop_dataout_timer(cmd);
|
||||||
|
iscsit_free_r2ts_from_list(cmd);
|
||||||
|
}
|
||||||
|
if (cmd->data_direction == DMA_FROM_DEVICE)
|
||||||
|
iscsit_free_all_datain_reqs(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn && check_queues) {
|
||||||
|
iscsit_remove_cmd_from_immediate_queue(cmd, conn);
|
||||||
|
iscsit_remove_cmd_from_response_queue(cmd, conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
|
||||||
|
{
|
||||||
|
struct se_cmd *se_cmd = NULL;
|
||||||
|
int rc;
|
||||||
/*
|
/*
|
||||||
* Determine if a struct se_cmd is associated with
|
* Determine if a struct se_cmd is associated with
|
||||||
* this struct iscsi_cmd.
|
* this struct iscsi_cmd.
|
||||||
*/
|
*/
|
||||||
switch (cmd->iscsi_opcode) {
|
switch (cmd->iscsi_opcode) {
|
||||||
case ISCSI_OP_SCSI_CMD:
|
case ISCSI_OP_SCSI_CMD:
|
||||||
if (cmd->data_direction == DMA_TO_DEVICE)
|
se_cmd = &cmd->se_cmd;
|
||||||
iscsit_stop_dataout_timer(cmd);
|
__iscsit_free_cmd(cmd, true, shutdown);
|
||||||
/*
|
/*
|
||||||
* Fallthrough
|
* Fallthrough
|
||||||
*/
|
*/
|
||||||
case ISCSI_OP_SCSI_TMFUNC:
|
case ISCSI_OP_SCSI_TMFUNC:
|
||||||
transport_generic_free_cmd(&cmd->se_cmd, 1);
|
rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
|
||||||
|
if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
|
||||||
|
__iscsit_free_cmd(cmd, true, shutdown);
|
||||||
|
target_put_sess_cmd(se_cmd->se_sess, se_cmd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ISCSI_OP_REJECT:
|
case ISCSI_OP_REJECT:
|
||||||
/*
|
/*
|
||||||
@ -718,11 +734,19 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
|
|||||||
* associated cmd->se_cmd needs to be released.
|
* associated cmd->se_cmd needs to be released.
|
||||||
*/
|
*/
|
||||||
if (cmd->se_cmd.se_tfo != NULL) {
|
if (cmd->se_cmd.se_tfo != NULL) {
|
||||||
transport_generic_free_cmd(&cmd->se_cmd, 1);
|
se_cmd = &cmd->se_cmd;
|
||||||
|
__iscsit_free_cmd(cmd, true, shutdown);
|
||||||
|
|
||||||
|
rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
|
||||||
|
if (!rc && shutdown && se_cmd->se_sess) {
|
||||||
|
__iscsit_free_cmd(cmd, true, shutdown);
|
||||||
|
target_put_sess_cmd(se_cmd->se_sess, se_cmd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Fall-through */
|
/* Fall-through */
|
||||||
default:
|
default:
|
||||||
|
__iscsit_free_cmd(cmd, false, shutdown);
|
||||||
cmd->release_cmd(cmd);
|
cmd->release_cmd(cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_co
|
|||||||
extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);
|
extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);
|
||||||
extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
|
extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
|
||||||
extern void iscsit_release_cmd(struct iscsi_cmd *);
|
extern void iscsit_release_cmd(struct iscsi_cmd *);
|
||||||
extern void iscsit_free_cmd(struct iscsi_cmd *);
|
extern void iscsit_free_cmd(struct iscsi_cmd *, bool);
|
||||||
extern int iscsit_check_session_usage_count(struct iscsi_session *);
|
extern int iscsit_check_session_usage_count(struct iscsi_session *);
|
||||||
extern void iscsit_dec_session_usage_count(struct iscsi_session *);
|
extern void iscsit_dec_session_usage_count(struct iscsi_session *);
|
||||||
extern void iscsit_inc_session_usage_count(struct iscsi_session *);
|
extern void iscsit_inc_session_usage_count(struct iscsi_session *);
|
||||||
|
@ -153,6 +153,7 @@ static int fd_configure_device(struct se_device *dev)
|
|||||||
struct request_queue *q = bdev_get_queue(inode->i_bdev);
|
struct request_queue *q = bdev_get_queue(inode->i_bdev);
|
||||||
unsigned long long dev_size;
|
unsigned long long dev_size;
|
||||||
|
|
||||||
|
fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev);
|
||||||
/*
|
/*
|
||||||
* Determine the number of bytes from i_size_read() minus
|
* Determine the number of bytes from i_size_read() minus
|
||||||
* one (1) logical sector from underlying struct block_device
|
* one (1) logical sector from underlying struct block_device
|
||||||
@ -199,6 +200,7 @@ static int fd_configure_device(struct se_device *dev)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fd_dev->fd_block_size = FD_BLOCKSIZE;
|
||||||
/*
|
/*
|
||||||
* Limit UNMAP emulation to 8k Number of LBAs (NoLB)
|
* Limit UNMAP emulation to 8k Number of LBAs (NoLB)
|
||||||
*/
|
*/
|
||||||
@ -217,9 +219,7 @@ static int fd_configure_device(struct se_device *dev)
|
|||||||
dev->dev_attrib.max_write_same_len = 0x1000;
|
dev->dev_attrib.max_write_same_len = 0x1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_dev->fd_block_size = dev->dev_attrib.hw_block_size;
|
dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;
|
||||||
|
|
||||||
dev->dev_attrib.hw_block_size = FD_BLOCKSIZE;
|
|
||||||
dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
|
dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
|
||||||
dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
|
dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
|
||||||
|
|
||||||
@ -694,11 +694,12 @@ static sector_t fd_get_blocks(struct se_device *dev)
|
|||||||
* to handle underlying block_device resize operations.
|
* to handle underlying block_device resize operations.
|
||||||
*/
|
*/
|
||||||
if (S_ISBLK(i->i_mode))
|
if (S_ISBLK(i->i_mode))
|
||||||
dev_size = (i_size_read(i) - fd_dev->fd_block_size);
|
dev_size = i_size_read(i);
|
||||||
else
|
else
|
||||||
dev_size = fd_dev->fd_dev_size;
|
dev_size = fd_dev->fd_dev_size;
|
||||||
|
|
||||||
return div_u64(dev_size, dev->dev_attrib.block_size);
|
return div_u64(dev_size - dev->dev_attrib.block_size,
|
||||||
|
dev->dev_attrib.block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sbc_ops fd_sbc_ops = {
|
static struct sbc_ops fd_sbc_ops = {
|
||||||
|
@ -65,7 +65,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd);
|
|||||||
static void transport_handle_queue_full(struct se_cmd *cmd,
|
static void transport_handle_queue_full(struct se_cmd *cmd,
|
||||||
struct se_device *dev);
|
struct se_device *dev);
|
||||||
static int transport_generic_get_mem(struct se_cmd *cmd);
|
static int transport_generic_get_mem(struct se_cmd *cmd);
|
||||||
static void transport_put_cmd(struct se_cmd *cmd);
|
static int transport_put_cmd(struct se_cmd *cmd);
|
||||||
static void target_complete_ok_work(struct work_struct *work);
|
static void target_complete_ok_work(struct work_struct *work);
|
||||||
|
|
||||||
int init_se_kmem_caches(void)
|
int init_se_kmem_caches(void)
|
||||||
@ -221,6 +221,7 @@ struct se_session *transport_init_session(void)
|
|||||||
INIT_LIST_HEAD(&se_sess->sess_list);
|
INIT_LIST_HEAD(&se_sess->sess_list);
|
||||||
INIT_LIST_HEAD(&se_sess->sess_acl_list);
|
INIT_LIST_HEAD(&se_sess->sess_acl_list);
|
||||||
INIT_LIST_HEAD(&se_sess->sess_cmd_list);
|
INIT_LIST_HEAD(&se_sess->sess_cmd_list);
|
||||||
|
INIT_LIST_HEAD(&se_sess->sess_wait_list);
|
||||||
spin_lock_init(&se_sess->sess_cmd_lock);
|
spin_lock_init(&se_sess->sess_cmd_lock);
|
||||||
kref_init(&se_sess->sess_kref);
|
kref_init(&se_sess->sess_kref);
|
||||||
|
|
||||||
@ -1943,7 +1944,7 @@ static inline void transport_free_pages(struct se_cmd *cmd)
|
|||||||
* This routine unconditionally frees a command, and reference counting
|
* This routine unconditionally frees a command, and reference counting
|
||||||
* or list removal must be done in the caller.
|
* or list removal must be done in the caller.
|
||||||
*/
|
*/
|
||||||
static void transport_release_cmd(struct se_cmd *cmd)
|
static int transport_release_cmd(struct se_cmd *cmd)
|
||||||
{
|
{
|
||||||
BUG_ON(!cmd->se_tfo);
|
BUG_ON(!cmd->se_tfo);
|
||||||
|
|
||||||
@ -1955,11 +1956,11 @@ static void transport_release_cmd(struct se_cmd *cmd)
|
|||||||
* If this cmd has been setup with target_get_sess_cmd(), drop
|
* If this cmd has been setup with target_get_sess_cmd(), drop
|
||||||
* the kref and call ->release_cmd() in kref callback.
|
* the kref and call ->release_cmd() in kref callback.
|
||||||
*/
|
*/
|
||||||
if (cmd->check_release != 0) {
|
if (cmd->check_release != 0)
|
||||||
target_put_sess_cmd(cmd->se_sess, cmd);
|
return target_put_sess_cmd(cmd->se_sess, cmd);
|
||||||
return;
|
|
||||||
}
|
|
||||||
cmd->se_tfo->release_cmd(cmd);
|
cmd->se_tfo->release_cmd(cmd);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1968,7 +1969,7 @@ static void transport_release_cmd(struct se_cmd *cmd)
|
|||||||
*
|
*
|
||||||
* This routine releases our reference to the command and frees it if possible.
|
* This routine releases our reference to the command and frees it if possible.
|
||||||
*/
|
*/
|
||||||
static void transport_put_cmd(struct se_cmd *cmd)
|
static int transport_put_cmd(struct se_cmd *cmd)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
@ -1976,7 +1977,7 @@ static void transport_put_cmd(struct se_cmd *cmd)
|
|||||||
if (atomic_read(&cmd->t_fe_count) &&
|
if (atomic_read(&cmd->t_fe_count) &&
|
||||||
!atomic_dec_and_test(&cmd->t_fe_count)) {
|
!atomic_dec_and_test(&cmd->t_fe_count)) {
|
||||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
|
if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
|
||||||
@ -1986,8 +1987,7 @@ static void transport_put_cmd(struct se_cmd *cmd)
|
|||||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||||
|
|
||||||
transport_free_pages(cmd);
|
transport_free_pages(cmd);
|
||||||
transport_release_cmd(cmd);
|
return transport_release_cmd(cmd);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *transport_kmap_data_sg(struct se_cmd *cmd)
|
void *transport_kmap_data_sg(struct se_cmd *cmd)
|
||||||
@ -2152,13 +2152,15 @@ static void transport_write_pending_qf(struct se_cmd *cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
|
int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
|
if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
|
||||||
if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
|
if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
|
||||||
transport_wait_for_tasks(cmd);
|
transport_wait_for_tasks(cmd);
|
||||||
|
|
||||||
transport_release_cmd(cmd);
|
ret = transport_release_cmd(cmd);
|
||||||
} else {
|
} else {
|
||||||
if (wait_for_tasks)
|
if (wait_for_tasks)
|
||||||
transport_wait_for_tasks(cmd);
|
transport_wait_for_tasks(cmd);
|
||||||
@ -2166,8 +2168,9 @@ void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
|
|||||||
if (cmd->se_lun)
|
if (cmd->se_lun)
|
||||||
transport_lun_remove_cmd(cmd);
|
transport_lun_remove_cmd(cmd);
|
||||||
|
|
||||||
transport_put_cmd(cmd);
|
ret = transport_put_cmd(cmd);
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(transport_generic_free_cmd);
|
EXPORT_SYMBOL(transport_generic_free_cmd);
|
||||||
|
|
||||||
@ -2250,11 +2253,14 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
|
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
|
||||||
|
if (se_sess->sess_tearing_down) {
|
||||||
WARN_ON(se_sess->sess_tearing_down);
|
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
se_sess->sess_tearing_down = 1;
|
se_sess->sess_tearing_down = 1;
|
||||||
|
list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list);
|
||||||
|
|
||||||
list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list)
|
list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list)
|
||||||
se_cmd->cmd_wait_set = 1;
|
se_cmd->cmd_wait_set = 1;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||||
@ -2263,44 +2269,32 @@ EXPORT_SYMBOL(target_sess_cmd_list_set_waiting);
|
|||||||
|
|
||||||
/* target_wait_for_sess_cmds - Wait for outstanding descriptors
|
/* target_wait_for_sess_cmds - Wait for outstanding descriptors
|
||||||
* @se_sess: session to wait for active I/O
|
* @se_sess: session to wait for active I/O
|
||||||
* @wait_for_tasks: Make extra transport_wait_for_tasks call
|
|
||||||
*/
|
*/
|
||||||
void target_wait_for_sess_cmds(
|
void target_wait_for_sess_cmds(struct se_session *se_sess)
|
||||||
struct se_session *se_sess,
|
|
||||||
int wait_for_tasks)
|
|
||||||
{
|
{
|
||||||
struct se_cmd *se_cmd, *tmp_cmd;
|
struct se_cmd *se_cmd, *tmp_cmd;
|
||||||
bool rc = false;
|
unsigned long flags;
|
||||||
|
|
||||||
list_for_each_entry_safe(se_cmd, tmp_cmd,
|
list_for_each_entry_safe(se_cmd, tmp_cmd,
|
||||||
&se_sess->sess_cmd_list, se_cmd_list) {
|
&se_sess->sess_wait_list, se_cmd_list) {
|
||||||
list_del(&se_cmd->se_cmd_list);
|
list_del(&se_cmd->se_cmd_list);
|
||||||
|
|
||||||
pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:"
|
pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:"
|
||||||
" %d\n", se_cmd, se_cmd->t_state,
|
" %d\n", se_cmd, se_cmd->t_state,
|
||||||
se_cmd->se_tfo->get_cmd_state(se_cmd));
|
se_cmd->se_tfo->get_cmd_state(se_cmd));
|
||||||
|
|
||||||
if (wait_for_tasks) {
|
|
||||||
pr_debug("Calling transport_wait_for_tasks se_cmd: %p t_state: %d,"
|
|
||||||
" fabric state: %d\n", se_cmd, se_cmd->t_state,
|
|
||||||
se_cmd->se_tfo->get_cmd_state(se_cmd));
|
|
||||||
|
|
||||||
rc = transport_wait_for_tasks(se_cmd);
|
|
||||||
|
|
||||||
pr_debug("After transport_wait_for_tasks se_cmd: %p t_state: %d,"
|
|
||||||
" fabric state: %d\n", se_cmd, se_cmd->t_state,
|
|
||||||
se_cmd->se_tfo->get_cmd_state(se_cmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rc) {
|
|
||||||
wait_for_completion(&se_cmd->cmd_wait_comp);
|
wait_for_completion(&se_cmd->cmd_wait_comp);
|
||||||
pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d"
|
pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d"
|
||||||
" fabric state: %d\n", se_cmd, se_cmd->t_state,
|
" fabric state: %d\n", se_cmd, se_cmd->t_state,
|
||||||
se_cmd->se_tfo->get_cmd_state(se_cmd));
|
se_cmd->se_tfo->get_cmd_state(se_cmd));
|
||||||
}
|
|
||||||
|
|
||||||
se_cmd->se_tfo->release_cmd(se_cmd);
|
se_cmd->se_tfo->release_cmd(se_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
|
||||||
|
WARN_ON(!list_empty(&se_sess->sess_cmd_list));
|
||||||
|
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||||
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(target_wait_for_sess_cmds);
|
EXPORT_SYMBOL(target_wait_for_sess_cmds);
|
||||||
|
|
||||||
|
@ -543,6 +543,7 @@ struct se_session {
|
|||||||
struct list_head sess_list;
|
struct list_head sess_list;
|
||||||
struct list_head sess_acl_list;
|
struct list_head sess_acl_list;
|
||||||
struct list_head sess_cmd_list;
|
struct list_head sess_cmd_list;
|
||||||
|
struct list_head sess_wait_list;
|
||||||
spinlock_t sess_cmd_lock;
|
spinlock_t sess_cmd_lock;
|
||||||
struct kref sess_kref;
|
struct kref sess_kref;
|
||||||
};
|
};
|
||||||
|
@ -114,7 +114,7 @@ sense_reason_t transport_generic_new_cmd(struct se_cmd *);
|
|||||||
|
|
||||||
void target_execute_cmd(struct se_cmd *cmd);
|
void target_execute_cmd(struct se_cmd *cmd);
|
||||||
|
|
||||||
void transport_generic_free_cmd(struct se_cmd *, int);
|
int transport_generic_free_cmd(struct se_cmd *, int);
|
||||||
|
|
||||||
bool transport_wait_for_tasks(struct se_cmd *);
|
bool transport_wait_for_tasks(struct se_cmd *);
|
||||||
int transport_check_aborted_status(struct se_cmd *, int);
|
int transport_check_aborted_status(struct se_cmd *, int);
|
||||||
@ -123,7 +123,7 @@ int transport_send_check_condition_and_sense(struct se_cmd *,
|
|||||||
int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
|
int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
|
||||||
int target_put_sess_cmd(struct se_session *, struct se_cmd *);
|
int target_put_sess_cmd(struct se_session *, struct se_cmd *);
|
||||||
void target_sess_cmd_list_set_waiting(struct se_session *);
|
void target_sess_cmd_list_set_waiting(struct se_session *);
|
||||||
void target_wait_for_sess_cmds(struct se_session *, int);
|
void target_wait_for_sess_cmds(struct se_session *);
|
||||||
|
|
||||||
int core_alua_check_nonop_delay(struct se_cmd *);
|
int core_alua_check_nonop_delay(struct se_cmd *);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user