mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 09:13:55 +08:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull more scsi target fixes from Nicholas Bellinger:
"This series is a second round of target fixes for v3.7-rc4 that have
come into target-devel over the last days, and are important enough to
be applied ASAP.
All are being CC'ed to stable. The most important two are:
- target: Re-add explict zeroing of INQUIRY bounce buffer memory to
fix a regression for handling zero-length payloads, a bug that went
during v3.7-rc1, and hit >= v3.6.3 stable. (nab + paolo)
- iscsi-target: Fix a long-standing missed R2T wakeup race in TX
thread processing when using a single queue slot. (Roland)
Thanks to Roland & PureStorage team for helping to track down this
long standing race with iscsi-target single queue slot operation.
Also, the tcm_fc(FCoE) regression bug that was observed recently with
-rc2 code has also been resolved with the cancel_delayed_work() return
bugfix (commit c0158ca64d
: "workqueue: cancel_delayed_work() should
return %false if work item is idle") now in -rc3. Thanks again to Yi
Zou, MDR, Robert Love @ Intel for helping to track this down."
* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
target: Fix incorrect usage of nested IRQ spinlocks in ABORT_TASK path
iscsi-target: Fix missed wakeup race in TX thread
target: Avoid integer overflow in se_dev_align_max_sectors()
target: Don't return success from module_init() if setup fails
target: Re-add explict zeroing of INQUIRY bounce buffer memory
This commit is contained in:
commit
23e44302b3
@ -3719,7 +3719,9 @@ restart:
|
|||||||
*/
|
*/
|
||||||
iscsit_thread_check_cpumask(conn, current, 1);
|
iscsit_thread_check_cpumask(conn, current, 1);
|
||||||
|
|
||||||
schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
|
wait_event_interruptible(conn->queues_wq,
|
||||||
|
!iscsit_conn_all_queues_empty(conn) ||
|
||||||
|
ts->status == ISCSI_THREAD_SET_RESET);
|
||||||
|
|
||||||
if ((ts->status == ISCSI_THREAD_SET_RESET) ||
|
if ((ts->status == ISCSI_THREAD_SET_RESET) ||
|
||||||
signal_pending(current))
|
signal_pending(current))
|
||||||
|
@ -486,6 +486,7 @@ struct iscsi_tmr_req {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct iscsi_conn {
|
struct iscsi_conn {
|
||||||
|
wait_queue_head_t queues_wq;
|
||||||
/* Authentication Successful for this connection */
|
/* Authentication Successful for this connection */
|
||||||
u8 auth_complete;
|
u8 auth_complete;
|
||||||
/* State connection is currently in */
|
/* State connection is currently in */
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
static int iscsi_login_init_conn(struct iscsi_conn *conn)
|
static int iscsi_login_init_conn(struct iscsi_conn *conn)
|
||||||
{
|
{
|
||||||
|
init_waitqueue_head(&conn->queues_wq);
|
||||||
INIT_LIST_HEAD(&conn->conn_list);
|
INIT_LIST_HEAD(&conn->conn_list);
|
||||||
INIT_LIST_HEAD(&conn->conn_cmd_list);
|
INIT_LIST_HEAD(&conn->conn_cmd_list);
|
||||||
INIT_LIST_HEAD(&conn->immed_queue_list);
|
INIT_LIST_HEAD(&conn->immed_queue_list);
|
||||||
|
@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(
|
|||||||
atomic_set(&conn->check_immediate_queue, 1);
|
atomic_set(&conn->check_immediate_queue, 1);
|
||||||
spin_unlock_bh(&conn->immed_queue_lock);
|
spin_unlock_bh(&conn->immed_queue_lock);
|
||||||
|
|
||||||
wake_up_process(conn->thread_set->tx_thread);
|
wake_up(&conn->queues_wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
|
struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
|
||||||
@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(
|
|||||||
atomic_inc(&cmd->response_queue_count);
|
atomic_inc(&cmd->response_queue_count);
|
||||||
spin_unlock_bh(&conn->response_queue_lock);
|
spin_unlock_bh(&conn->response_queue_lock);
|
||||||
|
|
||||||
wake_up_process(conn->thread_set->tx_thread);
|
wake_up(&conn->queues_wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
|
struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
|
||||||
@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn)
|
||||||
|
{
|
||||||
|
bool empty;
|
||||||
|
|
||||||
|
spin_lock_bh(&conn->immed_queue_lock);
|
||||||
|
empty = list_empty(&conn->immed_queue_list);
|
||||||
|
spin_unlock_bh(&conn->immed_queue_lock);
|
||||||
|
|
||||||
|
if (!empty)
|
||||||
|
return empty;
|
||||||
|
|
||||||
|
spin_lock_bh(&conn->response_queue_lock);
|
||||||
|
empty = list_empty(&conn->response_queue_list);
|
||||||
|
spin_unlock_bh(&conn->response_queue_lock);
|
||||||
|
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
|
void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
|
||||||
{
|
{
|
||||||
struct iscsi_queue_req *qr, *qr_tmp;
|
struct iscsi_queue_req *qr, *qr_tmp;
|
||||||
|
@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_
|
|||||||
extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
|
extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
|
||||||
extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
|
extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
|
||||||
extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
|
extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, 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 *);
|
||||||
|
@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (core_dev_setup_virtual_lun0() < 0)
|
ret = core_dev_setup_virtual_lun0();
|
||||||
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)
|
|||||||
|
|
||||||
static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
|
static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
|
||||||
{
|
{
|
||||||
u32 tmp, aligned_max_sectors;
|
u32 aligned_max_sectors;
|
||||||
|
u32 alignment;
|
||||||
/*
|
/*
|
||||||
* Limit max_sectors to a PAGE_SIZE aligned value for modern
|
* Limit max_sectors to a PAGE_SIZE aligned value for modern
|
||||||
* transport_allocate_data_tasks() operation.
|
* transport_allocate_data_tasks() operation.
|
||||||
*/
|
*/
|
||||||
tmp = rounddown((max_sectors * block_size), PAGE_SIZE);
|
alignment = max(1ul, PAGE_SIZE / block_size);
|
||||||
aligned_max_sectors = (tmp / block_size);
|
aligned_max_sectors = rounddown(max_sectors, alignment);
|
||||||
if (max_sectors != aligned_max_sectors) {
|
|
||||||
printk(KERN_INFO "Rounding down aligned max_sectors from %u"
|
|
||||||
" to %u\n", max_sectors, aligned_max_sectors);
|
|
||||||
return aligned_max_sectors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return max_sectors;
|
if (max_sectors != aligned_max_sectors)
|
||||||
|
pr_info("Rounding down aligned max_sectors from %u to %u\n",
|
||||||
|
max_sectors, aligned_max_sectors);
|
||||||
|
|
||||||
|
return aligned_max_sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
void se_dev_set_default_attribs(
|
void se_dev_set_default_attribs(
|
||||||
|
@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
|
|||||||
unsigned char buf[SE_INQUIRY_BUF];
|
unsigned char buf[SE_INQUIRY_BUF];
|
||||||
int p, ret;
|
int p, ret;
|
||||||
|
|
||||||
|
memset(buf, 0, SE_INQUIRY_BUF);
|
||||||
|
|
||||||
if (dev == tpg->tpg_virt_lun0.lun_se_dev)
|
if (dev == tpg->tpg_virt_lun0.lun_se_dev)
|
||||||
buf[0] = 0x3f; /* Not connected */
|
buf[0] = 0x3f; /* Not connected */
|
||||||
else
|
else
|
||||||
|
@ -140,15 +140,15 @@ void core_tmr_abort_task(
|
|||||||
printk("ABORT_TASK: Found referenced %s task_tag: %u\n",
|
printk("ABORT_TASK: Found referenced %s task_tag: %u\n",
|
||||||
se_cmd->se_tfo->get_fabric_name(), ref_tag);
|
se_cmd->se_tfo->get_fabric_name(), ref_tag);
|
||||||
|
|
||||||
spin_lock_irq(&se_cmd->t_state_lock);
|
spin_lock(&se_cmd->t_state_lock);
|
||||||
if (se_cmd->transport_state & CMD_T_COMPLETE) {
|
if (se_cmd->transport_state & CMD_T_COMPLETE) {
|
||||||
printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag);
|
printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag);
|
||||||
spin_unlock_irq(&se_cmd->t_state_lock);
|
spin_unlock(&se_cmd->t_state_lock);
|
||||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
se_cmd->transport_state |= CMD_T_ABORTED;
|
se_cmd->transport_state |= CMD_T_ABORTED;
|
||||||
spin_unlock_irq(&se_cmd->t_state_lock);
|
spin_unlock(&se_cmd->t_state_lock);
|
||||||
|
|
||||||
list_del_init(&se_cmd->se_cmd_list);
|
list_del_init(&se_cmd->se_cmd_list);
|
||||||
kref_get(&se_cmd->cmd_kref);
|
kref_get(&se_cmd->cmd_kref);
|
||||||
|
Loading…
Reference in New Issue
Block a user