Re: iSCSI login failure, possible race condition

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Nick

Please find patch below:

Solves an issue with frequent "iSCSI Login negotiation failed."  observed
during target discovery from Microsoft client initiator running inside a
virtual machine to a target running in another virtual machine inside the
same host under VMWare.
iscsi_target_sk_data_ready() callback is received too soon before
LOGIN_FLAGS_READY flag is set.
The patch fixes the problem by moving the section that checks the various
LOGIN_FLAGS_* from the iscsi_target_sk_data_ready() callback to the worker
function iscsi_target_do_login_rx() and in case  LOGIN_FLAGS_READY is not
set, sleeps and checks it a second time before exiting.

Maged Mokhtar mmokhtar@xxxxxxxxxxxxxxxxxx


diff -up a/drivers/target/iscsi/iscsi_target_nego.c 
b/drivers/target/iscsi/iscsi_target_nego.c
--- a/drivers/target/iscsi/iscsi_target_nego.c  2016-02-08
18:07:32.282055751 -0500
+++ b/drivers/target/iscsi/iscsi_target_nego.c  2016-02-08
18:28:59.655937903 -0500
@@ -409,34 +409,11 @@ static void iscsi_target_sk_data_ready(s
        bool rc;

        pr_debug("Entering iscsi_target_sk_data_ready: conn: %p\n", conn);
-
-       write_lock_bh(&sk->sk_callback_lock);
-       if (!sk->sk_user_data) {
-               write_unlock_bh(&sk->sk_callback_lock);
-               return;
-       }
-       if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) {
-               write_unlock_bh(&sk->sk_callback_lock);
-               pr_debug("Got LOGIN_FLAGS_READY=0, conn: %p >>>>\n", conn);
-               return;
-       }
-       if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) {
-               write_unlock_bh(&sk->sk_callback_lock);
-               pr_debug("Got LOGIN_FLAGS_CLOSED=1, conn: %p >>>>\n", conn);
-               return;
-       }
-       if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) {
-               write_unlock_bh(&sk->sk_callback_lock);
-               pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p >>>>\n",
conn);
-               return;
-       }
-
        rc = schedule_delayed_work(&conn->login_work, 0);
        if (!rc) {
                pr_debug("iscsi_target_sk_data_ready, schedule_delayed_work"
                         " got false\n");
        }
-       write_unlock_bh(&sk->sk_callback_lock);
 }

 static void iscsi_target_sk_state_change(struct sock *);
@@ -551,6 +528,35 @@ static void iscsi_target_do_login_rx(str

        if (conn->sock) {
                struct sock *sk = conn->sock->sk;
+               write_lock_bh(&sk->sk_callback_lock);
+               if (!sk->sk_user_data) {
+                       write_unlock_bh(&sk->sk_callback_lock);
+                       return;
+               }
+               if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) {
+                       write_unlock_bh(&sk->sk_callback_lock);
+                       pr_debug("Got LOGIN_FLAGS_READY=0, conn: %p
>>>>\n", conn);
+                       /* retry a second time in case we are called too
soon before LOGIN_FLAGS_READY is set */
+                       msleep(100);
+                       write_lock_bh(&sk->sk_callback_lock);
+                       if (!test_bit(LOGIN_FLAGS_READY,
&conn->login_flags)) {
+                               write_unlock_bh(&sk->sk_callback_lock);
+                               pr_debug("Second retry. Got
LOGIN_FLAGS_READY=0, conn: %p >>>>\n", conn);
+                               return;
+                       }
+               }
+               if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) {
+                       write_unlock_bh(&sk->sk_callback_lock);
+                       pr_debug("Got LOGIN_FLAGS_CLOSED=1, conn: %p
>>>>\n", conn);
+                       return;
+               }
+               if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE,
&conn->login_flags)) {
+                       write_unlock_bh(&sk->sk_callback_lock);
+                       pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p
>>>>\n", conn);
+                       return;
+               }
+
+               write_unlock_bh(&sk->sk_callback_lock);

                read_lock_bh(&sk->sk_callback_lock);
                state = iscsi_target_sk_state_check(sk);



--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux