aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/daemon.c')
-rw-r--r--fs/gfs2/daemon.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c
new file mode 100644
index 000000000000..cff8d5368d21
--- /dev/null
+++ b/fs/gfs2/daemon.c
@@ -0,0 +1,225 @@
1/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
4 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License v.2.
8 */
9
10#include <linux/sched.h>
11#include <linux/slab.h>
12#include <linux/spinlock.h>
13#include <linux/completion.h>
14#include <linux/buffer_head.h>
15#include <linux/kthread.h>
16#include <linux/delay.h>
17#include <asm/semaphore.h>
18
19#include "gfs2.h"
20#include "daemon.h"
21#include "glock.h"
22#include "log.h"
23#include "quota.h"
24#include "recovery.h"
25#include "super.h"
26#include "unlinked.h"
27
28/* This uses schedule_timeout() instead of msleep() because it's good for
29 the daemons to wake up more often than the timeout when unmounting so
30 the user's unmount doesn't sit there forever.
31
32 The kthread functions used to start these daemons block and flush signals. */
33
34/**
35 * gfs2_scand - Look for cached glocks and inodes to toss from memory
36 * @sdp: Pointer to GFS2 superblock
37 *
38 * One of these daemons runs, finding candidates to add to sd_reclaim_list.
39 * See gfs2_glockd()
40 */
41
42int gfs2_scand(void *data)
43{
44 struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
45 unsigned long t;
46
47 while (!kthread_should_stop()) {
48 gfs2_scand_internal(sdp);
49 t = gfs2_tune_get(sdp, gt_scand_secs) * HZ;
50 schedule_timeout_interruptible(t);
51 }
52
53 return 0;
54}
55
56/**
57 * gfs2_glockd - Reclaim unused glock structures
58 * @sdp: Pointer to GFS2 superblock
59 *
60 * One or more of these daemons run, reclaiming glocks on sd_reclaim_list.
61 * Number of daemons can be set by user, with num_glockd mount option.
62 */
63
64int gfs2_glockd(void *data)
65{
66 struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
67 DECLARE_WAITQUEUE(wait_chan, current);
68
69 while (!kthread_should_stop()) {
70 while (atomic_read(&sdp->sd_reclaim_count))
71 gfs2_reclaim_glock(sdp);
72
73 set_current_state(TASK_INTERRUPTIBLE);
74 add_wait_queue(&sdp->sd_reclaim_wq, &wait_chan);
75 if (!atomic_read(&sdp->sd_reclaim_count) &&
76 !kthread_should_stop())
77 schedule();
78 remove_wait_queue(&sdp->sd_reclaim_wq, &wait_chan);
79 set_current_state(TASK_RUNNING);
80 }
81
82 return 0;
83}
84
85/**
86 * gfs2_recoverd - Recover dead machine's journals
87 * @sdp: Pointer to GFS2 superblock
88 *
89 */
90
91int gfs2_recoverd(void *data)
92{
93 struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
94 unsigned long t;
95
96 while (!kthread_should_stop()) {
97 gfs2_check_journals(sdp);
98 t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ;
99 schedule_timeout_interruptible(t);
100 }
101
102 return 0;
103}
104
105/**
106 * gfs2_logd - Update log tail as Active Items get flushed to in-place blocks
107 * @sdp: Pointer to GFS2 superblock
108 *
109 * Also, periodically check to make sure that we're using the most recent
110 * journal index.
111 */
112
113int gfs2_logd(void *data)
114{
115 struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
116 struct gfs2_holder ji_gh;
117 unsigned long t;
118
119 while (!kthread_should_stop()) {
120 /* Advance the log tail */
121
122 t = sdp->sd_log_flush_time +
123 gfs2_tune_get(sdp, gt_log_flush_secs) * HZ;
124
125 gfs2_ail1_empty(sdp, DIO_ALL);
126
127 if (time_after_eq(jiffies, t)) {
128 gfs2_log_flush(sdp);
129 sdp->sd_log_flush_time = jiffies;
130 }
131
132 /* Check for latest journal index */
133
134 t = sdp->sd_jindex_refresh_time +
135 gfs2_tune_get(sdp, gt_jindex_refresh_secs) * HZ;
136
137 if (time_after_eq(jiffies, t)) {
138 if (!gfs2_jindex_hold(sdp, &ji_gh))
139 gfs2_glock_dq_uninit(&ji_gh);
140 sdp->sd_jindex_refresh_time = jiffies;
141 }
142
143 t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
144 schedule_timeout_interruptible(t);
145 }
146
147 return 0;
148}
149
150/**
151 * gfs2_quotad - Write cached quota changes into the quota file
152 * @sdp: Pointer to GFS2 superblock
153 *
154 */
155
156int gfs2_quotad(void *data)
157{
158 struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
159 unsigned long t;
160 int error;
161
162 while (!kthread_should_stop()) {
163 /* Update the master statfs file */
164
165 t = sdp->sd_statfs_sync_time +
166 gfs2_tune_get(sdp, gt_statfs_quantum) * HZ;
167
168 if (time_after_eq(jiffies, t)) {
169 error = gfs2_statfs_sync(sdp);
170 if (error &&
171 error != -EROFS &&
172 !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
173 fs_err(sdp, "quotad: (1) error=%d\n", error);
174 sdp->sd_statfs_sync_time = jiffies;
175 }
176
177 /* Update quota file */
178
179 t = sdp->sd_quota_sync_time +
180 gfs2_tune_get(sdp, gt_quota_quantum) * HZ;
181
182 if (time_after_eq(jiffies, t)) {
183 error = gfs2_quota_sync(sdp);
184 if (error &&
185 error != -EROFS &&
186 !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
187 fs_err(sdp, "quotad: (2) error=%d\n", error);
188 sdp->sd_quota_sync_time = jiffies;
189 }
190
191 gfs2_quota_scan(sdp);
192
193 t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ;
194 schedule_timeout_interruptible(t);
195 }
196
197 return 0;
198}
199
200/**
201 * gfs2_inoded - Deallocate unlinked inodes
202 * @sdp: Pointer to GFS2 superblock
203 *
204 */
205
206int gfs2_inoded(void *data)
207{
208 struct gfs2_sbd *sdp = (struct gfs2_sbd *)data;
209 unsigned long t;
210 int error;
211
212 while (!kthread_should_stop()) {
213 error = gfs2_unlinked_dealloc(sdp);
214 if (error &&
215 error != -EROFS &&
216 !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
217 fs_err(sdp, "inoded: error = %d\n", error);
218
219 t = gfs2_tune_get(sdp, gt_inoded_secs) * HZ;
220 schedule_timeout_interruptible(t);
221 }
222
223 return 0;
224}
225