+static void daemon_exit(struct bitmap *bitmap, mdk_thread_t **daemon)
+{
+ mdk_thread_t *dmn;
+ unsigned long flags;
+
+ /* if no one is waiting on us, we'll free the md thread struct
+ * and exit, otherwise we let the waiter clean things up */
+ spin_lock_irqsave(&bitmap->lock, flags);
+ if ((dmn = *daemon)) { /* no one is waiting, cleanup and exit */
+ *daemon = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ kfree(dmn);
+ complete_and_exit(NULL, 0); /* do_exit not exported */
+ }
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+}
+
+static void bitmap_writeback_daemon(mddev_t *mddev)
+{
+ struct bitmap *bitmap = mddev->bitmap;
+ struct page *page;
+ struct page_list *item;
+ int err = 0;
+
+ if (signal_pending(current)) {
+ printk(KERN_INFO
+ "%s: bitmap writeback daemon got signal, exiting...\n",
+ bmname(bitmap));
+ err = -EINTR;
+ goto out;
+ }
+ if (bitmap == NULL)
+ /* about to be stopped. */
+ return;
+
+ PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
+ /* wait on bitmap page writebacks */
+ while ((item = dequeue_page(bitmap))) {
+ page = item->page;
+ mempool_free(item, bitmap->write_pool);
+ PRINTK("wait on page writeback: %p\n", page);
+ wait_on_page_writeback(page);
+ PRINTK("finished page writeback: %p\n", page);
+
+ err = PageError(page);
+ put_page(page);
+ if (err) {
+ printk(KERN_WARNING "%s: bitmap file writeback "
+ "failed (page %lu): %d\n",
+ bmname(bitmap), page->index, err);
+ bitmap_file_kick(bitmap);
+ goto out;
+ }
+ }
+ out:
+ wake_up(&bitmap->write_wait);
+ if (err) {
+ printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n",
+ bmname(bitmap), err);
+ daemon_exit(bitmap, &bitmap->writeback_daemon);
+ }
+}
+
+static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
+ void (*func)(mddev_t *), char *name)
+{
+ mdk_thread_t *daemon;
+ char namebuf[32];
+
+#ifdef INJECT_FATAL_FAULT_2
+ daemon = NULL;
+#else
+ sprintf(namebuf, "%%s_%s", name);
+ daemon = md_register_thread(func, bitmap->mddev, namebuf);
+#endif
+ if (!daemon) {
+ printk(KERN_ERR "%s: failed to start bitmap daemon\n",
+ bmname(bitmap));
+ return ERR_PTR(-ECHILD);
+ }
+
+ md_wakeup_thread(daemon); /* start it running */
+
+ PRINTK("%s: %s daemon (pid %d) started...\n",
+ bmname(bitmap), name, daemon->tsk->pid);
+
+ return daemon;
+}
+
+static void bitmap_stop_daemon(struct bitmap *bitmap)
+{
+ /* the daemon can't stop itself... it'll just exit instead... */
+ if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
+ current->pid != bitmap->writeback_daemon->tsk->pid) {
+ mdk_thread_t *daemon;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bitmap->lock, flags);
+ daemon = bitmap->writeback_daemon;
+ bitmap->writeback_daemon = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ if (daemon && ! IS_ERR(daemon))
+ md_unregister_thread(daemon); /* destroy the thread */
+ }
+}
+