Add dm-daemon. --- diff/drivers/md/Makefile 2004-02-18 09:04:00.000000000 +0000 +++ source/drivers/md/Makefile 2004-02-18 09:08:57.000000000 +0000 @@ -3,7 +3,7 @@ # dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ - dm-ioctl.o + dm-ioctl.o dm-daemon.o raid6-objs := raid6main.o raid6algos.o raid6recov.o raid6tables.o \ raid6int1.o raid6int2.o raid6int4.o \ raid6int8.o raid6int16.o raid6int32.o \ --- diff/drivers/md/dm.h 2004-02-18 09:08:48.000000000 +0000 +++ source/drivers/md/dm.h 2004-02-18 09:08:57.000000000 +0000 @@ -20,6 +20,11 @@ #define DMINFO(f, x...) printk(KERN_INFO DM_NAME ": " f "\n" , ## x) /* + * FIXME: There must be a better place for this. + */ +typedef typeof(jiffies) jiffy_t; + +/* * FIXME: I think this should be with the definition of sector_t * in types.h. */ --- diff/drivers/md/dm-daemon.c 1970-01-01 01:00:00.000000000 +0100 +++ source/drivers/md/dm-daemon.c 2004-02-18 09:08:57.000000000 +0000 @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the LGPL. + */ + +#include "dm.h" +#include "dm-daemon.h" + +#include +#include +#include +#include + +static int daemon(void *arg) +{ + struct dm_daemon *dd = (struct dm_daemon *) arg; + DECLARE_WAITQUEUE(wq, current); + jiffy_t timeout; + + daemonize("%s", dd->name); + + atomic_set(&dd->please_die, 0); + + add_wait_queue(&dd->job_queue, &wq); + + complete(&dd->start); + + /* + * dd->fn() could do anything, very likely it will + * suspend. So we can't set the state to + * TASK_INTERRUPTIBLE before calling it. In order to + * prevent a race with a waking thread we do this little + * dance with the dd->woken variable. + */ + while (1) { + if (atomic_read(&dd->please_die)) + goto out; + + if (current->flags & PF_FREEZE) + refrigerator(PF_IOTHREAD); + + do { + set_current_state(TASK_RUNNING); + atomic_set(&dd->woken, 0); + timeout = dd->fn(); + set_current_state(TASK_INTERRUPTIBLE); + + } while (atomic_read(&dd->woken)); + + if (timeout) + schedule_timeout(timeout); + else + schedule(); + } + + out: + remove_wait_queue(&dd->job_queue, &wq); + complete_and_exit(&dd->run, 0); +} + +int dm_daemon_start(struct dm_daemon *dd, const char *name, jiffy_t (*fn)(void)) +{ + pid_t pid = 0; + + /* + * Initialise the dm_daemon. + */ + dd->fn = fn; + strncpy(dd->name, name, sizeof(dd->name) - 1); + init_completion(&dd->start); + init_completion(&dd->run); + init_waitqueue_head(&dd->job_queue); + + /* + * Start the new thread. + */ + pid = kernel_thread(daemon, dd, CLONE_KERNEL); + if (pid <= 0) { + DMERR("Failed to start %s thread", name); + return -EAGAIN; + } + + /* + * wait for the daemon to up this mutex. + */ + wait_for_completion(&dd->start); + + return 0; +} + +void dm_daemon_stop(struct dm_daemon *dd) +{ + atomic_set(&dd->please_die, 1); + dm_daemon_wake(dd); + wait_for_completion(&dd->run); +} + +void dm_daemon_wake(struct dm_daemon *dd) +{ + atomic_set(&dd->woken, 1); + wake_up_interruptible(&dd->job_queue); +} + +EXPORT_SYMBOL(dm_daemon_start); +EXPORT_SYMBOL(dm_daemon_stop); +EXPORT_SYMBOL(dm_daemon_wake); --- diff/drivers/md/dm-daemon.h 1970-01-01 01:00:00.000000000 +0100 +++ source/drivers/md/dm-daemon.h 2004-02-18 09:08:57.000000000 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2003 Sistina Software + * + * This file is released under the LGPL. + */ + +#ifndef DM_DAEMON_H +#define DM_DAEMON_H + +#include +#include + +/* + * The daemons work function returns a *hint* as to when it + * should next be woken up. + */ +struct dm_daemon { + jiffy_t (*fn)(void); + char name[16]; + atomic_t please_die; + struct completion start; + struct completion run; + + atomic_t woken; + wait_queue_head_t job_queue; +}; + +int dm_daemon_start(struct dm_daemon *dd, const char *name, jiffy_t (*fn)(void)); +void dm_daemon_stop(struct dm_daemon *dd); +void dm_daemon_wake(struct dm_daemon *dd); +int dm_daemon_running(struct dm_daemon *dd); + +#endif