ocfs2: Wake up a starting region if it gets killed in the background.
authorJoel Becker <joel.becker@oracle.com>
Tue, 6 Feb 2007 23:45:39 +0000 (15:45 -0800)
committerMark Fasheh <mark.fasheh@oracle.com>
Wed, 11 Jul 2007 00:19:46 +0000 (17:19 -0700)
Tell o2cb_region_dev_write() to wake up if rmdir(2) happens on the
heartbeat region while it is starting up.  Then o2hb_region_dev_write()
can check to see if it is alive and act accordingly.  This prevents a hang
(not being woken) and a crash (if it's woken by a signal).

Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
fs/ocfs2/cluster/heartbeat.c

index 2877d46..2bd7f78 100644 (file)
@@ -1335,6 +1335,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        ret = wait_event_interruptible(o2hb_steady_queue,
                                atomic_read(&reg->hr_steady_iterations) == 0);
        if (ret) {
        ret = wait_event_interruptible(o2hb_steady_queue,
                                atomic_read(&reg->hr_steady_iterations) == 0);
        if (ret) {
+               /* We got interrupted (hello ptrace!).  Clean up */
                spin_lock(&o2hb_live_lock);
                hb_task = reg->hr_task;
                reg->hr_task = NULL;
                spin_lock(&o2hb_live_lock);
                hb_task = reg->hr_task;
                reg->hr_task = NULL;
@@ -1345,7 +1346,16 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
                goto out;
        }
 
                goto out;
        }
 
-       ret = count;
+       /* Ok, we were woken.  Make sure it wasn't by drop_item() */
+       spin_lock(&o2hb_live_lock);
+       hb_task = reg->hr_task;
+       spin_unlock(&o2hb_live_lock);
+
+       if (hb_task)
+               ret = count;
+       else
+               ret = -EIO;
+
 out:
        if (filp)
                fput(filp);
 out:
        if (filp)
                fput(filp);
@@ -1523,6 +1533,15 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
        if (hb_task)
                kthread_stop(hb_task);
 
        if (hb_task)
                kthread_stop(hb_task);
 
+       /*
+        * If we're racing a dev_write(), we need to wake them.  They will
+        * check reg->hr_task
+        */
+       if (atomic_read(&reg->hr_steady_iterations) != 0) {
+               atomic_set(&reg->hr_steady_iterations, 0);
+               wake_up(&o2hb_steady_queue);
+       }
+
        config_item_put(item);
 }
 
        config_item_put(item);
 }