Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.20-rc4 205 lines 4.7 kB view raw
1/* kafstimod.c: AFS timeout daemon 2 * 3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/sched.h> 15#include <linux/completion.h> 16#include <linux/freezer.h> 17#include "cell.h" 18#include "volume.h" 19#include "kafstimod.h" 20#include <asm/errno.h> 21#include "internal.h" 22 23static DECLARE_COMPLETION(kafstimod_alive); 24static DECLARE_COMPLETION(kafstimod_dead); 25static DECLARE_WAIT_QUEUE_HEAD(kafstimod_sleepq); 26static int kafstimod_die; 27 28static LIST_HEAD(kafstimod_list); 29static DEFINE_SPINLOCK(kafstimod_lock); 30 31static int kafstimod(void *arg); 32 33/*****************************************************************************/ 34/* 35 * start the timeout daemon 36 */ 37int afs_kafstimod_start(void) 38{ 39 int ret; 40 41 ret = kernel_thread(kafstimod, NULL, 0); 42 if (ret < 0) 43 return ret; 44 45 wait_for_completion(&kafstimod_alive); 46 47 return ret; 48} /* end afs_kafstimod_start() */ 49 50/*****************************************************************************/ 51/* 52 * stop the timeout daemon 53 */ 54void afs_kafstimod_stop(void) 55{ 56 /* get rid of my daemon */ 57 kafstimod_die = 1; 58 wake_up(&kafstimod_sleepq); 59 wait_for_completion(&kafstimod_dead); 60 61} /* end afs_kafstimod_stop() */ 62 63/*****************************************************************************/ 64/* 65 * timeout processing daemon 66 */ 67static int kafstimod(void *arg) 68{ 69 struct afs_timer *timer; 70 71 DECLARE_WAITQUEUE(myself, current); 72 73 printk("kAFS: Started kafstimod %d\n", current->pid); 74 75 daemonize("kafstimod"); 76 77 complete(&kafstimod_alive); 78 79 /* loop around looking for things to attend to */ 80 loop: 81 set_current_state(TASK_INTERRUPTIBLE); 82 add_wait_queue(&kafstimod_sleepq, &myself); 83 84 for (;;) { 85 unsigned long jif; 86 signed long timeout; 87 88 /* deal with the server being asked to die */ 89 if (kafstimod_die) { 90 remove_wait_queue(&kafstimod_sleepq, &myself); 91 _leave(""); 92 complete_and_exit(&kafstimod_dead, 0); 93 } 94 95 try_to_freeze(); 96 97 /* discard pending signals */ 98 afs_discard_my_signals(); 99 100 /* work out the time to elapse before the next event */ 101 spin_lock(&kafstimod_lock); 102 if (list_empty(&kafstimod_list)) { 103 timeout = MAX_SCHEDULE_TIMEOUT; 104 } 105 else { 106 timer = list_entry(kafstimod_list.next, 107 struct afs_timer, link); 108 timeout = timer->timo_jif; 109 jif = jiffies; 110 111 if (time_before_eq((unsigned long) timeout, jif)) 112 goto immediate; 113 114 else { 115 timeout = (long) timeout - (long) jiffies; 116 } 117 } 118 spin_unlock(&kafstimod_lock); 119 120 schedule_timeout(timeout); 121 122 set_current_state(TASK_INTERRUPTIBLE); 123 } 124 125 /* the thing on the front of the queue needs processing 126 * - we come here with the lock held and timer pointing to the expired 127 * entry 128 */ 129 immediate: 130 remove_wait_queue(&kafstimod_sleepq, &myself); 131 set_current_state(TASK_RUNNING); 132 133 _debug("@@@ Begin Timeout of %p", timer); 134 135 /* dequeue the timer */ 136 list_del_init(&timer->link); 137 spin_unlock(&kafstimod_lock); 138 139 /* call the timeout function */ 140 timer->ops->timed_out(timer); 141 142 _debug("@@@ End Timeout"); 143 goto loop; 144 145} /* end kafstimod() */ 146 147/*****************************************************************************/ 148/* 149 * (re-)queue a timer 150 */ 151void afs_kafstimod_add_timer(struct afs_timer *timer, unsigned long timeout) 152{ 153 struct afs_timer *ptimer; 154 struct list_head *_p; 155 156 _enter("%p,%lu", timer, timeout); 157 158 spin_lock(&kafstimod_lock); 159 160 list_del(&timer->link); 161 162 /* the timer was deferred or reset - put it back in the queue at the 163 * right place */ 164 timer->timo_jif = jiffies + timeout; 165 166 list_for_each(_p, &kafstimod_list) { 167 ptimer = list_entry(_p, struct afs_timer, link); 168 if (time_before(timer->timo_jif, ptimer->timo_jif)) 169 break; 170 } 171 172 list_add_tail(&timer->link, _p); /* insert before stopping point */ 173 174 spin_unlock(&kafstimod_lock); 175 176 wake_up(&kafstimod_sleepq); 177 178 _leave(""); 179} /* end afs_kafstimod_add_timer() */ 180 181/*****************************************************************************/ 182/* 183 * dequeue a timer 184 * - returns 0 if the timer was deleted or -ENOENT if it wasn't queued 185 */ 186int afs_kafstimod_del_timer(struct afs_timer *timer) 187{ 188 int ret = 0; 189 190 _enter("%p", timer); 191 192 spin_lock(&kafstimod_lock); 193 194 if (list_empty(&timer->link)) 195 ret = -ENOENT; 196 else 197 list_del_init(&timer->link); 198 199 spin_unlock(&kafstimod_lock); 200 201 wake_up(&kafstimod_sleepq); 202 203 _leave(" = %d", ret); 204 return ret; 205} /* end afs_kafstimod_del_timer() */