Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linus Torvalds committed Jun 1, 2013
2 parents 0f7dafd + aafc9d1 commit 008bd2d
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 89 deletions.
34 changes: 25 additions & 9 deletions drivers/infiniband/ulp/srpt/ib_srpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2226,6 +2226,27 @@ static void srpt_close_ch(struct srpt_rdma_ch *ch)
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.
* @cm_id: Pointer to the CM ID of the channel to be drained.
Expand Down Expand Up @@ -2264,6 +2285,9 @@ static void srpt_drain_channel(struct ib_cm_id *cm_id)
spin_unlock_irq(&sdev->spinlock);

if (do_reset) {
if (ch->sess)
srpt_shutdown_session(ch->sess);

ret = srpt_ch_qp_err(ch);
if (ret < 0)
printk(KERN_ERR "Setting queue pair in error state"
Expand Down Expand Up @@ -2328,7 +2352,7 @@ static void srpt_release_channel_work(struct work_struct *w)
se_sess = ch->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(se_sess);
Expand Down Expand Up @@ -3466,14 +3490,6 @@ static void srpt_release_cmd(struct se_cmd *se_cmd)
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.
*
Expand Down
1 change: 1 addition & 0 deletions drivers/infiniband/ulp/srpt/ib_srpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ struct srpt_rdma_ch {
u8 sess_name[36];
struct work_struct release_work;
struct completion *release_done;
bool in_shutdown;
};

/**
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/qla2xxx/tcm_qla2xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1370,7 +1370,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
dump_stack();
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(sess->se_sess);
Expand Down
12 changes: 6 additions & 6 deletions drivers/target/iscsi/iscsi_target.c
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ static int iscsit_add_reject(
cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
if (!cmd->buf_ptr) {
pr_err("Unable to allocate memory for cmd->buf_ptr\n");
iscsit_release_cmd(cmd);
iscsit_free_cmd(cmd, false);
return -1;
}

Expand Down Expand Up @@ -697,7 +697,7 @@ int iscsit_add_reject_from_cmd(
cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
if (!cmd->buf_ptr) {
pr_err("Unable to allocate memory for cmd->buf_ptr\n");
iscsit_release_cmd(cmd);
iscsit_free_cmd(cmd, false);
return -1;
}

Expand Down Expand Up @@ -1743,7 +1743,7 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
return 0;
out:
if (cmd)
iscsit_release_cmd(cmd);
iscsit_free_cmd(cmd, false);
ping_out:
kfree(ping_data);
return ret;
Expand Down Expand Up @@ -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) {
pr_err("Received logout request on connection that"
" is not in logged in state, ignoring request.\n");
iscsit_release_cmd(cmd);
iscsit_free_cmd(cmd, false);
return 0;
}

Expand Down Expand Up @@ -3665,7 +3665,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state
list_del(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);

iscsit_free_cmd(cmd);
iscsit_free_cmd(cmd, false);
break;
case ISTATE_SEND_NOPIN_WANT_RESPONSE:
iscsit_mod_nopin_response_timer(conn);
Expand Down Expand Up @@ -4122,7 +4122,7 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)

iscsit_increment_maxcmdsn(cmd, sess);

iscsit_free_cmd(cmd);
iscsit_free_cmd(cmd, true);

spin_lock_bh(&conn->cmd_lock);
}
Expand Down
12 changes: 6 additions & 6 deletions drivers/target/iscsi/iscsi_target_erl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
list_del(&cmd->i_conn_node);
cmd->conn = NULL;
spin_unlock(&cr->conn_recovery_cmd_lock);
iscsit_free_cmd(cmd);
iscsit_free_cmd(cmd, true);
spin_lock(&cr->conn_recovery_cmd_lock);
}
spin_unlock(&cr->conn_recovery_cmd_lock);
Expand All @@ -165,7 +165,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
list_del(&cmd->i_conn_node);
cmd->conn = NULL;
spin_unlock(&cr->conn_recovery_cmd_lock);
iscsit_free_cmd(cmd);
iscsit_free_cmd(cmd, true);
spin_lock(&cr->conn_recovery_cmd_lock);
}
spin_unlock(&cr->conn_recovery_cmd_lock);
Expand Down Expand Up @@ -248,7 +248,7 @@ void iscsit_discard_cr_cmds_by_expstatsn(
iscsit_remove_cmd_from_connection_recovery(cmd, sess);

spin_unlock(&cr->conn_recovery_cmd_lock);
iscsit_free_cmd(cmd);
iscsit_free_cmd(cmd, true);
spin_lock(&cr->conn_recovery_cmd_lock);
}
spin_unlock(&cr->conn_recovery_cmd_lock);
Expand Down Expand Up @@ -302,7 +302,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
list_del(&cmd->i_conn_node);

spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd);
iscsit_free_cmd(cmd, true);
spin_lock_bh(&conn->cmd_lock);
}
spin_unlock_bh(&conn->cmd_lock);
Expand Down Expand Up @@ -355,7 +355,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)

list_del(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd);
iscsit_free_cmd(cmd, true);
spin_lock_bh(&conn->cmd_lock);
continue;
}
Expand All @@ -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)) {
list_del(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd);
iscsit_free_cmd(cmd, true);
spin_lock_bh(&conn->cmd_lock);
continue;
}
Expand Down
8 changes: 3 additions & 5 deletions drivers/target/iscsi/iscsi_target_parameters.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,9 +758,9 @@ static int iscsi_add_notunderstood_response(
}
INIT_LIST_HEAD(&extra_response->er_list);

strncpy(extra_response->key, key, strlen(key) + 1);
strncpy(extra_response->value, NOTUNDERSTOOD,
strlen(NOTUNDERSTOOD) + 1);
strlcpy(extra_response->key, key, sizeof(extra_response->key));
strlcpy(extra_response->value, NOTUNDERSTOOD,
sizeof(extra_response->value));

list_add_tail(&extra_response->er_list,
&param_list->extra_response_list);
Expand Down Expand Up @@ -1629,8 +1629,6 @@ int iscsi_decode_text_input(

if (phase & PHASE_SECURITY) {
if (iscsi_check_for_auth_key(key) > 0) {
char *tmpptr = key + strlen(key);
*tmpptr = '=';
kfree(tmpbuf);
return 1;
}
Expand Down
4 changes: 3 additions & 1 deletion drivers/target/iscsi/iscsi_target_parameters.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#ifndef ISCSI_PARAMETERS_H
#define ISCSI_PARAMETERS_H

#include <scsi/iscsi_proto.h>

struct iscsi_extra_response {
char key[64];
char key[KEY_MAXLEN];
char value[32];
struct list_head er_list;
} ____cacheline_aligned;
Expand Down
50 changes: 37 additions & 13 deletions drivers/target/iscsi/iscsi_target_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,40 +676,56 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)

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->pdu_list);
kfree(cmd->seq_list);
kfree(cmd->tmr_req);
kfree(cmd->iov_data);

if (conn) {
kmem_cache_free(lio_cmd_cache, 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);
}

kmem_cache_free(lio_cmd_cache, cmd);
}

void iscsit_free_cmd(struct iscsi_cmd *cmd)
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
* this struct iscsi_cmd.
*/
switch (cmd->iscsi_opcode) {
case ISCSI_OP_SCSI_CMD:
if (cmd->data_direction == DMA_TO_DEVICE)
iscsit_stop_dataout_timer(cmd);
se_cmd = &cmd->se_cmd;
__iscsit_free_cmd(cmd, true, shutdown);
/*
* Fallthrough
*/
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;
case ISCSI_OP_REJECT:
/*
Expand All @@ -718,11 +734,19 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
* associated cmd->se_cmd needs to be released.
*/
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;
}
/* Fall-through */
default:
__iscsit_free_cmd(cmd, false, shutdown);
cmd->release_cmd(cmd);
break;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/target/iscsi/iscsi_target_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
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 void iscsit_dec_session_usage_count(struct iscsi_session *);
extern void iscsit_inc_session_usage_count(struct iscsi_session *);
Expand Down
11 changes: 6 additions & 5 deletions drivers/target/target_core_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ static int fd_configure_device(struct se_device *dev)
struct request_queue *q = bdev_get_queue(inode->i_bdev);
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
* one (1) logical sector from underlying struct block_device
Expand Down Expand Up @@ -199,6 +200,7 @@ static int fd_configure_device(struct se_device *dev)
goto fail;
}

fd_dev->fd_block_size = FD_BLOCKSIZE;
/*
* Limit UNMAP emulation to 8k Number of LBAs (NoLB)
*/
Expand All @@ -217,9 +219,7 @@ static int fd_configure_device(struct se_device *dev)
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_BLOCKSIZE;
dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;
dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;

Expand Down Expand Up @@ -694,11 +694,12 @@ static sector_t fd_get_blocks(struct se_device *dev)
* to handle underlying block_device resize operations.
*/
if (S_ISBLK(i->i_mode))
dev_size = (i_size_read(i) - fd_dev->fd_block_size);
dev_size = i_size_read(i);
else
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 = {
Expand Down
Loading

0 comments on commit 008bd2d

Please sign in to comment.