dlm: fix locking of lockspace list in dlm_scand
authorDavid Teigland <teigland@redhat.com>
Mon, 18 Aug 2008 19:03:25 +0000 (14:03 -0500)
committerDavid Teigland <teigland@redhat.com>
Thu, 28 Aug 2008 16:50:07 +0000 (11:50 -0500)
The dlm_scand thread needs to lock the list of lockspaces
when going through it.

Signed-off-by: David Teigland <teigland@redhat.com>
fs/dlm/dlm_internal.h
fs/dlm/lockspace.c

index 9e0622a..868e4c9 100644 (file)
@@ -445,6 +445,7 @@ struct dlm_ls {
                                                   the dlm using this ls */
        int                     ls_create_count; /* create/release refcount */
        unsigned long           ls_flags;       /* LSFL_ */
+       unsigned long           ls_scan_time;
        struct kobject          ls_kobj;
 
        struct dlm_rsbtable     *ls_rsbtbl;
index ba672fe..d910501 100644 (file)
@@ -212,19 +212,41 @@ void dlm_lockspace_exit(void)
        kset_unregister(dlm_kset);
 }
 
+static struct dlm_ls *find_ls_to_scan(void)
+{
+       struct dlm_ls *ls;
+
+       spin_lock(&lslist_lock);
+       list_for_each_entry(ls, &lslist, ls_list) {
+               if (time_after_eq(jiffies, ls->ls_scan_time +
+                                           dlm_config.ci_scan_secs * HZ)) {
+                       spin_unlock(&lslist_lock);
+                       return ls;
+               }
+       }
+       spin_unlock(&lslist_lock);
+       return NULL;
+}
+
 static int dlm_scand(void *data)
 {
        struct dlm_ls *ls;
+       int timeout_jiffies = dlm_config.ci_scan_secs * HZ;
 
        while (!kthread_should_stop()) {
-               list_for_each_entry(ls, &lslist, ls_list) {
+               ls = find_ls_to_scan();
+               if (ls) {
                        if (dlm_lock_recovery_try(ls)) {
+                               ls->ls_scan_time = jiffies;
                                dlm_scan_rsbs(ls);
                                dlm_scan_timeout(ls);
                                dlm_unlock_recovery(ls);
+                       } else {
+                               ls->ls_scan_time += HZ;
                        }
+               } else {
+                       schedule_timeout_interruptible(timeout_jiffies);
                }
-               schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
        }
        return 0;
 }
@@ -418,6 +440,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
        ls->ls_lvblen = lvblen;
        ls->ls_count = 0;
        ls->ls_flags = 0;
+       ls->ls_scan_time = jiffies;
 
        if (flags & DLM_LSFL_TIMEWARN)
                set_bit(LSFL_TIMEWARN, &ls->ls_flags);