Commit 6fddcb77 authored by Mike Christie's avatar Mike Christie Committed by Nicholas Bellinger

tcmu: remove commands_lock

No need for the commands_lock. The cmdr_lock is already held during
idr addition and deletion, so just grab it during traversal.

Note: This also fixes a issue where we should have been using at
least _bh locking in tcmu_handle_completions when taking the commands
lock to prevent the case where tcmu_handle_completions could be
interrupted by a timer softirq while the commands_lock is held.
Signed-off-by: default avatarMike Christie <mchristi@redhat.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 488ebe4c
...@@ -139,7 +139,6 @@ struct tcmu_dev { ...@@ -139,7 +139,6 @@ struct tcmu_dev {
struct radix_tree_root data_blocks; struct radix_tree_root data_blocks;
struct idr commands; struct idr commands;
spinlock_t commands_lock;
struct timer_list timeout; struct timer_list timeout;
unsigned int cmd_time_out; unsigned int cmd_time_out;
...@@ -1014,10 +1013,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev) ...@@ -1014,10 +1013,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
} }
WARN_ON(tcmu_hdr_get_op(entry->hdr.len_op) != TCMU_OP_CMD); WARN_ON(tcmu_hdr_get_op(entry->hdr.len_op) != TCMU_OP_CMD);
spin_lock(&udev->commands_lock);
cmd = idr_remove(&udev->commands, entry->hdr.cmd_id); cmd = idr_remove(&udev->commands, entry->hdr.cmd_id);
spin_unlock(&udev->commands_lock);
if (!cmd) { if (!cmd) {
pr_err("cmd_id not found, ring is broken\n"); pr_err("cmd_id not found, ring is broken\n");
set_bit(TCMU_DEV_BIT_BROKEN, &udev->flags); set_bit(TCMU_DEV_BIT_BROKEN, &udev->flags);
...@@ -1115,7 +1111,6 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) ...@@ -1115,7 +1111,6 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
INIT_LIST_HEAD(&udev->timedout_entry); INIT_LIST_HEAD(&udev->timedout_entry);
idr_init(&udev->commands); idr_init(&udev->commands);
spin_lock_init(&udev->commands_lock);
timer_setup(&udev->timeout, tcmu_device_timedout, 0); timer_setup(&udev->timeout, tcmu_device_timedout, 0);
...@@ -1333,16 +1328,14 @@ static void tcmu_dev_kref_release(struct kref *kref) ...@@ -1333,16 +1328,14 @@ static void tcmu_dev_kref_release(struct kref *kref)
spin_unlock_bh(&timed_out_udevs_lock); spin_unlock_bh(&timed_out_udevs_lock);
/* Upper layer should drain all requests before calling this */ /* Upper layer should drain all requests before calling this */
spin_lock_irq(&udev->commands_lock); mutex_lock(&udev->cmdr_lock);
idr_for_each_entry(&udev->commands, cmd, i) { idr_for_each_entry(&udev->commands, cmd, i) {
if (tcmu_check_and_free_pending_cmd(cmd) != 0) if (tcmu_check_and_free_pending_cmd(cmd) != 0)
all_expired = false; all_expired = false;
} }
idr_destroy(&udev->commands); idr_destroy(&udev->commands);
spin_unlock_irq(&udev->commands_lock);
WARN_ON(!all_expired); WARN_ON(!all_expired);
mutex_lock(&udev->cmdr_lock);
tcmu_blocks_release(&udev->data_blocks, 0, udev->dbi_max + 1); tcmu_blocks_release(&udev->data_blocks, 0, udev->dbi_max + 1);
mutex_unlock(&udev->cmdr_lock); mutex_unlock(&udev->cmdr_lock);
...@@ -2060,9 +2053,9 @@ static void check_timedout_devices(void) ...@@ -2060,9 +2053,9 @@ static void check_timedout_devices(void)
list_del_init(&udev->timedout_entry); list_del_init(&udev->timedout_entry);
spin_unlock_bh(&timed_out_udevs_lock); spin_unlock_bh(&timed_out_udevs_lock);
spin_lock(&udev->commands_lock); mutex_lock(&udev->cmdr_lock);
idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL); idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL);
spin_unlock(&udev->commands_lock); mutex_unlock(&udev->cmdr_lock);
spin_lock_bh(&timed_out_udevs_lock); spin_lock_bh(&timed_out_udevs_lock);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment