linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] target/iscsi networkportal race fixes
@ 2014-01-25  0:18 Andy Grover
  2014-01-25  0:18 ` [PATCH 1/3] target/iscsi: Set np_thread_state to ACTIVE before adding to g_np_list Andy Grover
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Andy Grover @ 2014-01-25  0:18 UTC (permalink / raw)
  To: target-devel; +Cc: linux-scsi

see https://bugzilla.redhat.com/show_bug.cgi?id=1055064

Summary: if thread doesn't run before 2nd identical portal is created,
it misses the existing one and the kernel_bind returns an error.

The first one-line patch fixes the issue for a single thread creating
multiple network portals via configfs.

The second two close the race between multiple threads creating
network portals.

Testing: failing test script now works.

Regards -- Andy

Andy Grover (3):
  target/iscsi: Set np_thread_state to ACTIVE before adding to
    g_np_list
  target/iscsi: Convert np_lock from a spinlock to a mutex
  target/iscsi: hold np_lock mutex across adding new net portal to
    g_np_list

 drivers/target/iscsi/iscsi_target.c |   29 +++++++++++++++++------------
 1 files changed, 17 insertions(+), 12 deletions(-)


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] target/iscsi: Set np_thread_state to ACTIVE before adding to g_np_list
  2014-01-25  0:18 [PATCH 0/3] target/iscsi networkportal race fixes Andy Grover
@ 2014-01-25  0:18 ` Andy Grover
  2014-01-25  0:18 ` [PATCH 2/3] target/iscsi: Convert np_lock from a spinlock to a mutex Andy Grover
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Andy Grover @ 2014-01-25  0:18 UTC (permalink / raw)
  To: target-devel; +Cc: linux-scsi

When creating network portals rapidly, such as when restoring a
configuration, LIO's code to reuse existing portals can return a false
negative if the thread hasn't run yet and set np_thread_state to
ISCSI_NP_THREAD_ACTIVE. This causes an error in the network stack
when attempting to bind to the same address/port.

This patch sets NP_THREAD_ACTIVE before the np is placed on g_np_list,
so even if the thread hasn't run yet, iscsit_get_np will return the
existing np.

Signed-off-by: Andy Grover <agrover@redhat.com>
---
 drivers/target/iscsi/iscsi_target.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index d70e911..bfd4bf7 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -400,6 +400,7 @@ struct iscsi_np *iscsit_add_np(
 	 * point because iscsi_np has not been added to g_np_list yet.
 	 */
 	np->np_exports = 1;
+	np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
 
 	spin_lock_bh(&np_lock);
 	list_add_tail(&np->np_list, &g_np_list);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] target/iscsi: Convert np_lock from a spinlock to a mutex
  2014-01-25  0:18 [PATCH 0/3] target/iscsi networkportal race fixes Andy Grover
  2014-01-25  0:18 ` [PATCH 1/3] target/iscsi: Set np_thread_state to ACTIVE before adding to g_np_list Andy Grover
@ 2014-01-25  0:18 ` Andy Grover
  2014-01-25  0:18 ` [PATCH 3/3] target/iscsi: hold np_lock mutex across adding new net portal to g_np_list Andy Grover
  2014-01-28 19:15 ` [PATCH 0/3] target/iscsi networkportal race fixes Nicholas A. Bellinger
  3 siblings, 0 replies; 6+ messages in thread
From: Andy Grover @ 2014-01-25  0:18 UTC (permalink / raw)
  To: target-devel; +Cc: linux-scsi

All callers are in process context.

Convert spin_lock to spin_lock_bh in iscsit_get_np since outer spin_lock_bh
is now not there.

Signed-off-by: Andy Grover <agrover@redhat.com>
---
 drivers/target/iscsi/iscsi_target.c |   22 +++++++++++-----------
 1 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index bfd4bf7..45ec498 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -52,7 +52,7 @@
 static LIST_HEAD(g_tiqn_list);
 static LIST_HEAD(g_np_list);
 static DEFINE_SPINLOCK(tiqn_lock);
-static DEFINE_SPINLOCK(np_lock);
+static DEFINE_MUTEX(np_lock);
 
 static struct idr tiqn_idr;
 struct idr sess_idr;
@@ -314,9 +314,9 @@ static struct iscsi_np *iscsit_get_np(
 	struct iscsi_np *np;
 	bool match;
 
-	spin_lock_bh(&np_lock);
+	mutex_lock(&np_lock);
 	list_for_each_entry(np, &g_np_list, np_list) {
-		spin_lock(&np->np_thread_lock);
+		spin_lock_bh(&np->np_thread_lock);
 		if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
 			spin_unlock(&np->np_thread_lock);
 			continue;
@@ -330,13 +330,13 @@ static struct iscsi_np *iscsit_get_np(
 			 * while iscsi_tpg_add_network_portal() is called.
 			 */
 			np->np_exports++;
-			spin_unlock(&np->np_thread_lock);
-			spin_unlock_bh(&np_lock);
+			spin_unlock_bh(&np->np_thread_lock);
+			mutex_unlock(&np_lock);
 			return np;
 		}
-		spin_unlock(&np->np_thread_lock);
+		spin_unlock_bh(&np->np_thread_lock);
 	}
-	spin_unlock_bh(&np_lock);
+	mutex_unlock(&np_lock);
 
 	return NULL;
 }
@@ -402,9 +402,9 @@ struct iscsi_np *iscsit_add_np(
 	np->np_exports = 1;
 	np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
 
-	spin_lock_bh(&np_lock);
+	mutex_lock(&np_lock);
 	list_add_tail(&np->np_list, &g_np_list);
-	spin_unlock_bh(&np_lock);
+	mutex_unlock(&np_lock);
 
 	pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n",
 		np->np_ip, np->np_port, np->np_transport->name);
@@ -470,9 +470,9 @@ int iscsit_del_np(struct iscsi_np *np)
 
 	np->np_transport->iscsit_free_np(np);
 
-	spin_lock_bh(&np_lock);
+	mutex_lock(&np_lock);
 	list_del(&np->np_list);
-	spin_unlock_bh(&np_lock);
+	mutex_unlock(&np_lock);
 
 	pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n",
 		np->np_ip, np->np_port, np->np_transport->name);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] target/iscsi: hold np_lock mutex across adding new net portal to g_np_list
  2014-01-25  0:18 [PATCH 0/3] target/iscsi networkportal race fixes Andy Grover
  2014-01-25  0:18 ` [PATCH 1/3] target/iscsi: Set np_thread_state to ACTIVE before adding to g_np_list Andy Grover
  2014-01-25  0:18 ` [PATCH 2/3] target/iscsi: Convert np_lock from a spinlock to a mutex Andy Grover
@ 2014-01-25  0:18 ` Andy Grover
  2014-01-28 19:15 ` [PATCH 0/3] target/iscsi networkportal race fixes Nicholas A. Bellinger
  3 siblings, 0 replies; 6+ messages in thread
From: Andy Grover @ 2014-01-25  0:18 UTC (permalink / raw)
  To: target-devel; +Cc: linux-scsi

This prevents a race where two threads may attempt to create the same
network portal, resulting in one of them failing.

Signed-off-by: Andy Grover <agrover@redhat.com>
---
 drivers/target/iscsi/iscsi_target.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 45ec498..4e91586 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -307,6 +307,9 @@ bool iscsit_check_np_match(
 	return false;
 }
 
+/*
+ * Called with mutex np_lock held
+ */
 static struct iscsi_np *iscsit_get_np(
 	struct __kernel_sockaddr_storage *sockaddr,
 	int network_transport)
@@ -314,7 +317,6 @@ static struct iscsi_np *iscsit_get_np(
 	struct iscsi_np *np;
 	bool match;
 
-	mutex_lock(&np_lock);
 	list_for_each_entry(np, &g_np_list, np_list) {
 		spin_lock_bh(&np->np_thread_lock);
 		if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
@@ -331,12 +333,10 @@ static struct iscsi_np *iscsit_get_np(
 			 */
 			np->np_exports++;
 			spin_unlock_bh(&np->np_thread_lock);
-			mutex_unlock(&np_lock);
 			return np;
 		}
 		spin_unlock_bh(&np->np_thread_lock);
 	}
-	mutex_unlock(&np_lock);
 
 	return NULL;
 }
@@ -350,12 +350,17 @@ struct iscsi_np *iscsit_add_np(
 	struct sockaddr_in6 *sock_in6;
 	struct iscsi_np *np;
 	int ret;
+
+	mutex_lock(&np_lock);
+
 	/*
 	 * Locate the existing struct iscsi_np if already active..
 	 */
 	np = iscsit_get_np(sockaddr, network_transport);
-	if (np)
+	if (np) {
+		mutex_unlock(&np_lock);
 		return np;
+	}
 
 	np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL);
 	if (!np) {
@@ -402,7 +407,6 @@ struct iscsi_np *iscsit_add_np(
 	np->np_exports = 1;
 	np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
 
-	mutex_lock(&np_lock);
 	list_add_tail(&np->np_list, &g_np_list);
 	mutex_unlock(&np_lock);
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] target/iscsi networkportal race fixes
  2014-01-25  0:18 [PATCH 0/3] target/iscsi networkportal race fixes Andy Grover
                   ` (2 preceding siblings ...)
  2014-01-25  0:18 ` [PATCH 3/3] target/iscsi: hold np_lock mutex across adding new net portal to g_np_list Andy Grover
@ 2014-01-28 19:15 ` Nicholas A. Bellinger
  2014-01-28 20:04   ` Andy Grover
  3 siblings, 1 reply; 6+ messages in thread
From: Nicholas A. Bellinger @ 2014-01-28 19:15 UTC (permalink / raw)
  To: Andy Grover; +Cc: target-devel, linux-scsi

Hi Andy,

On Fri, 2014-01-24 at 16:18 -0800, Andy Grover wrote:
> see https://bugzilla.redhat.com/show_bug.cgi?id=1055064
> 
> Summary: if thread doesn't run before 2nd identical portal is created,
> it misses the existing one and the kernel_bind returns an error.
> 
> The first one-line patch fixes the issue for a single thread creating
> multiple network portals via configfs.
> 
> The second two close the race between multiple threads creating
> network portals.
> 
> Testing: failing test script now works.
> 

Applied, squashed into a single bugfix patch, and adding a CC'ed to
stable.

FYI, on patch #3, there where a few exception path mutex_unlocks
missing, so the following incremental has been applied + squashed as
well.

Thanks,

--nab

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 13868ff..1ab9b18 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -365,6 +365,7 @@ struct iscsi_np *iscsit_add_np(
        np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL);
        if (!np) {
                pr_err("Unable to allocate memory for struct iscsi_np\n");
+               mutex_unlock(&np_lock);
                return ERR_PTR(-ENOMEM);
        }
 
@@ -387,6 +388,7 @@ struct iscsi_np *iscsit_add_np(
        ret = iscsi_target_setup_login_socket(np, sockaddr);
        if (ret != 0) {
                kfree(np);
+               mutex_unlock(&np_lock);
                return ERR_PTR(ret);
        }
 
@@ -395,6 +397,7 @@ struct iscsi_np *iscsit_add_np(
                pr_err("Unable to create kthread: iscsi_np\n");
                ret = PTR_ERR(np->np_thread);
                kfree(np);
+               mutex_unlock(&np_lock);
                return ERR_PTR(ret);
        }
        /*



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] target/iscsi networkportal race fixes
  2014-01-28 19:15 ` [PATCH 0/3] target/iscsi networkportal race fixes Nicholas A. Bellinger
@ 2014-01-28 20:04   ` Andy Grover
  0 siblings, 0 replies; 6+ messages in thread
From: Andy Grover @ 2014-01-28 20:04 UTC (permalink / raw)
  To: Nicholas A. Bellinger; +Cc: target-devel, linux-scsi

On 01/28/2014 11:15 AM, Nicholas A. Bellinger wrote:
> Hi Andy,
> 
> On Fri, 2014-01-24 at 16:18 -0800, Andy Grover wrote:
>> see https://bugzilla.redhat.com/show_bug.cgi?id=1055064
>>
>> Summary: if thread doesn't run before 2nd identical portal is created,
>> it misses the existing one and the kernel_bind returns an error.

> Applied, squashed into a single bugfix patch, and adding a CC'ed to
> stable.
> 
> FYI, on patch #3, there where a few exception path mutex_unlocks
> missing, so the following incremental has been applied + squashed as
> well.

Thanks for the review and fixes! -- Andy

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-01-28 20:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-25  0:18 [PATCH 0/3] target/iscsi networkportal race fixes Andy Grover
2014-01-25  0:18 ` [PATCH 1/3] target/iscsi: Set np_thread_state to ACTIVE before adding to g_np_list Andy Grover
2014-01-25  0:18 ` [PATCH 2/3] target/iscsi: Convert np_lock from a spinlock to a mutex Andy Grover
2014-01-25  0:18 ` [PATCH 3/3] target/iscsi: hold np_lock mutex across adding new net portal to g_np_list Andy Grover
2014-01-28 19:15 ` [PATCH 0/3] target/iscsi networkportal race fixes Nicholas A. Bellinger
2014-01-28 20:04   ` Andy Grover

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).