Since iscsi responses from the kernel are multicast we might get into
a situation where multiple discoveryd handle the same response.
With this commit we use a shared mutex to lock between the discoveryd forks
so each fork will handle its intended portal.
So we wait for login and stale logouts to finish between releasing the mutex.

Signed-off-by: Roi Dayan <[email protected]>
---

Hi,

The issue was discovered after working with discoveryd and offload driver
which needed the following patch that was already submitted to the mailing list:

[PATCH] Discovery daemon via non-tcp transport needs 'ipc' set

Thanks,
Roi


 usr/Makefile       |  2 +-
 usr/discoveryd.c   | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 usr/session_mgmt.c | 10 ++++++++++
 3 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/usr/Makefile b/usr/Makefile
index e23fee1..dca7b6e 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -55,7 +55,7 @@ all: $(PROGRAMS)
 
 iscsid: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(DISCOVERY_SRCS) \
        iscsid.o session_mgmt.o discoveryd.o
-       $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@  -L../utils/open-isns -lisns -lrt 
-lmount
+       $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@  -L../utils/open-isns -lisns -lrt 
-lmount -pthread
 
 iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o
        $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ -L../utils/open-isns -lisns
diff --git a/usr/discoveryd.c b/usr/discoveryd.c
index 2d3ccbc..e08143e 100644
--- a/usr/discoveryd.c
+++ b/usr/discoveryd.c
@@ -27,6 +27,10 @@
 #include <time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <fcntl.h>
 
 #include "discovery.h"
 #include "idbm.h"
@@ -47,6 +51,9 @@
 #include "iscsi_err.h"
 
 #define DISC_DEF_POLL_INVL     30
+#define MUTEX "/lock"
+
+pthread_mutex_t *mutex = NULL;
 
 static LIST_HEAD(iscsi_targets);
 static int stop_discoveryd;
@@ -62,6 +69,43 @@ static void isns_reg_refresh_by_eid_qry(void *data);
 typedef void (do_disc_and_login_fn)(const char *def_iname,
                                    struct discovery_rec *drec, int poll_inval);
 
+static void discoveryd_create_shared_mutex(void)
+{
+       int mode = S_IRWXU | S_IRWXG;
+       int des_mutex;
+       pthread_mutexattr_t attr;
+
+       des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR | O_TRUNC, mode);
+
+       if (des_mutex < 0) {
+           log_error("Error creating mutex");
+           return;
+       }
+
+       if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1) {
+               log_error("Error on truncate");
+               return;
+       }
+
+       mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t),
+                   PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0);
+
+       if (mutex == MAP_FAILED ) {
+               log_error("Error on mmap");
+               return;
+       }
+
+       pthread_mutexattr_init(&attr);
+       pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+       pthread_mutex_init(mutex, &attr);
+       pthread_mutexattr_destroy(&attr);
+}
+
+static void discoveryd_destroy_shared_mutex(void)
+{
+       pthread_mutex_destroy(mutex);
+}
+
 static int logout_session(void *data, struct list_head *list,
                          struct session_info *info)
 {
@@ -96,6 +140,7 @@ static void discoveryd_stop(void)
        }
 
 done:
+       discoveryd_destroy_shared_mutex();
        exit(0);
 }
 
@@ -174,7 +219,7 @@ static void update_sessions(struct list_head *new_rec_list,
 
        list_for_each_entry_safe(rec, tmp_rec, new_rec_list, list) {
                if (!iscsi_check_for_running_session(rec))
-                       iscsi_login_portal_nowait(rec);
+                       iscsi_login_portal_wait(rec);
 
                if (!idbm_find_rec_in_list(&iscsi_targets, rec->name,
                                           rec->conn[0].address,
@@ -190,7 +235,7 @@ static void update_sessions(struct list_head *new_rec_list,
        }
 
        if (!list_empty(&stale_rec_list)) {
-               iscsi_logout_portals(&stale_rec_list, &nr_found, 0,
+               iscsi_logout_portals(&stale_rec_list, &nr_found, 1,
                                     logout_session);
                list_for_each_entry_safe(rec, tmp_rec, &stale_rec_list, list) {
                        list_del(&rec->list);
@@ -1059,7 +1104,12 @@ static void do_st_disc_and_login(const char *def_iname,
                poll_inval = DISC_DEF_POLL_INVL;
 
        do {
+               pthread_mutex_lock(mutex);
+               log_debug(1, "discoveryd start scan %s:%d", drec->address, 
drec->port);
                __do_st_disc_and_login(drec);
+               pthread_mutex_unlock(mutex);
+               log_debug(1, "discoveryd end scan %s:%d", drec->address, 
drec->port);
+
                if (!poll_inval)
                        break;
        } while (!stop_discoveryd && !sleep(poll_inval));
@@ -1081,6 +1131,9 @@ static int st_start(void *data, struct discovery_rec 
*drec)
 
 static void discoveryd_st_start(void)
 {
+       discoveryd_create_shared_mutex();
+       if (mutex == NULL)
+           return;
        idbm_for_each_st_drec(NULL, st_start);
 }
 
diff --git a/usr/session_mgmt.c b/usr/session_mgmt.c
index 596085b..b397eaa 100644
--- a/usr/session_mgmt.c
+++ b/usr/session_mgmt.c
@@ -223,6 +223,16 @@ int iscsi_login_portal_nowait(struct node_rec *rec)
        return 0;
 }
 
+int iscsi_login_portal_wait(struct node_rec *rec)
+{
+       int err;
+
+       err = iscsi_login_portal(NULL, NULL, rec);
+       if (err > 0)
+               return err;
+       return 0;
+}
+
 /**
  * __iscsi_login_portals - login into portals on @rec_list,
  * @data: data to pass to login_fn
-- 
1.8.4.3

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/open-iscsi.
For more options, visit https://groups.google.com/d/optout.

Reply via email to