From: "Nicholas A. Bellinger" <nab@linux-iscsi.org>
To: target-devel <target-devel@vger.kernel.org>,
linux-scsi <linux-scsi@vger.kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
Roland Dreier <roland@purestorage.com>
Subject: [PATCH 1/5] target: Fix race between multiple invocations of target_qf_do_work()
Date: Fri, 16 Sep 2011 10:38:22 +0000 [thread overview]
Message-ID: <1316169506-4441-2-git-send-email-nab@linux-iscsi.org> (raw)
In-Reply-To: <1316169506-4441-1-git-send-email-nab@linux-iscsi.org>
From: Roland Dreier <roland@purestorage.com>
When work is scheduled with schedule_work(), the work can end up
running on multiple CPUs at the same time -- this happens if
the work is already running on one CPU and schedule_work() is called
on another CPU. This leads to list corruption with target_qf_do_work(),
which is roughly doing:
spin_lock(...);
list_for_each_entry_safe(...) {
list_del(...);
spin_unlock(...);
// do stuff
spin_lock(...);
}
With multiple CPUs running this code, one CPU can end up deleting the
list entry that the other CPU is about to work on.
Fix this by splicing the list entries onto a local list and then
operating on that in the work function. This way, each invocation of
target_qf_do_work() operates on its own local list and so multiple
invocations don't corrupt each other's list. This also avoids dropping
and reacquiring the lock for each list entry.
Signed-off-by: Roland Dreier <roland@purestorage.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
drivers/target/target_core_transport.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 8d0c58e..a4b0a8d 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -977,15 +977,17 @@ static void target_qf_do_work(struct work_struct *work)
{
struct se_device *dev = container_of(work, struct se_device,
qf_work_queue);
+ LIST_HEAD(qf_cmd_list);
struct se_cmd *cmd, *cmd_tmp;
spin_lock_irq(&dev->qf_cmd_lock);
- list_for_each_entry_safe(cmd, cmd_tmp, &dev->qf_cmd_list, se_qf_node) {
+ list_splice_init(&dev->qf_cmd_list, &qf_cmd_list);
+ spin_unlock_irq(&dev->qf_cmd_lock);
+ list_for_each_entry_safe(cmd, cmd_tmp, &qf_cmd_list, se_qf_node) {
list_del(&cmd->se_qf_node);
atomic_dec(&dev->dev_qf_count);
smp_mb__after_atomic_dec();
- spin_unlock_irq(&dev->qf_cmd_lock);
pr_debug("Processing %s cmd: %p QUEUE_FULL in work queue"
" context: %s\n", cmd->se_tfo->get_fabric_name(), cmd,
@@ -997,10 +999,7 @@ static void target_qf_do_work(struct work_struct *work)
* has been added to head of queue
*/
transport_add_cmd_to_queue(cmd, cmd->t_state);
-
- spin_lock_irq(&dev->qf_cmd_lock);
}
- spin_unlock_irq(&dev->qf_cmd_lock);
}
unsigned char *transport_dump_cmd_direction(struct se_cmd *cmd)
--
1.5.6.5
next prev parent reply other threads:[~2011-09-16 11:04 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-16 10:38 [PATCH 0/5] target: Bugfixes for v3.1-rc6 Nicholas A. Bellinger
2011-09-16 10:38 ` Nicholas A. Bellinger [this message]
2011-09-17 19:23 ` [PATCH 1/5] target: Fix race between multiple invocations of target_qf_do_work() Linus Torvalds
2011-09-17 22:59 ` Christoph Hellwig
2011-09-16 10:38 ` [PATCH 2/5] tcm_fc: Invalidation of DDP context for FCoE target in error conditions Nicholas A. Bellinger
2011-09-16 10:38 ` [PATCH 3/5] tcm_fc: Work queue based approach instead of managing own thread and event based mechanism Nicholas A. Bellinger
2011-09-16 10:38 ` [PATCH 4/5] target: Skip non hex characters for EVPD=0x83 NAA IEEE Registered Extended Nicholas A. Bellinger
2011-09-16 13:59 ` Martin Svec
2011-09-16 14:19 ` Douglas Gilbert
2011-09-16 19:38 ` Nicholas A. Bellinger
2011-09-16 19:36 ` Nicholas A. Bellinger
2011-09-16 10:38 ` [PATCH 5/5] iscsi-target: Disable markers + remove dangerous local scope array usage Nicholas A. Bellinger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1316169506-4441-2-git-send-email-nab@linux-iscsi.org \
--to=nab@linux-iscsi.org \
--cc=linux-scsi@vger.kernel.org \
--cc=roland@purestorage.com \
--cc=target-devel@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox