diff options
Diffstat (limited to 'fs/gfs2/daemon.c')
-rw-r--r-- | fs/gfs2/daemon.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c new file mode 100644 index 000000000000..cab1f68d4685 --- /dev/null +++ b/fs/gfs2/daemon.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
3 | * Copyright (C) 2004-2006 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 version 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 <linux/gfs2_ondisk.h> | ||
18 | #include <linux/lm_interface.h> | ||
19 | |||
20 | #include "gfs2.h" | ||
21 | #include "incore.h" | ||
22 | #include "daemon.h" | ||
23 | #include "glock.h" | ||
24 | #include "log.h" | ||
25 | #include "quota.h" | ||
26 | #include "recovery.h" | ||
27 | #include "super.h" | ||
28 | #include "util.h" | ||
29 | |||
30 | /* This uses schedule_timeout() instead of msleep() because it's good for | ||
31 | the daemons to wake up more often than the timeout when unmounting so | ||
32 | the user's unmount doesn't sit there forever. | ||
33 | |||
34 | The kthread functions used to start these daemons block and flush signals. */ | ||
35 | |||
36 | /** | ||
37 | * gfs2_scand - Look for cached glocks and inodes to toss from memory | ||
38 | * @sdp: Pointer to GFS2 superblock | ||
39 | * | ||
40 | * One of these daemons runs, finding candidates to add to sd_reclaim_list. | ||
41 | * See gfs2_glockd() | ||
42 | */ | ||
43 | |||
44 | int gfs2_scand(void *data) | ||
45 | { | ||
46 | struct gfs2_sbd *sdp = data; | ||
47 | unsigned long t; | ||
48 | |||
49 | while (!kthread_should_stop()) { | ||
50 | gfs2_scand_internal(sdp); | ||
51 | t = gfs2_tune_get(sdp, gt_scand_secs) * HZ; | ||
52 | schedule_timeout_interruptible(t); | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * gfs2_glockd - Reclaim unused glock structures | ||
60 | * @sdp: Pointer to GFS2 superblock | ||
61 | * | ||
62 | * One or more of these daemons run, reclaiming glocks on sd_reclaim_list. | ||
63 | * Number of daemons can be set by user, with num_glockd mount option. | ||
64 | */ | ||
65 | |||
66 | int gfs2_glockd(void *data) | ||
67 | { | ||
68 | struct gfs2_sbd *sdp = data; | ||
69 | |||
70 | while (!kthread_should_stop()) { | ||
71 | while (atomic_read(&sdp->sd_reclaim_count)) | ||
72 | gfs2_reclaim_glock(sdp); | ||
73 | |||
74 | wait_event_interruptible(sdp->sd_reclaim_wq, | ||
75 | (atomic_read(&sdp->sd_reclaim_count) || | ||
76 | kthread_should_stop())); | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * gfs2_recoverd - Recover dead machine's journals | ||
84 | * @sdp: Pointer to GFS2 superblock | ||
85 | * | ||
86 | */ | ||
87 | |||
88 | int gfs2_recoverd(void *data) | ||
89 | { | ||
90 | struct gfs2_sbd *sdp = data; | ||
91 | unsigned long t; | ||
92 | |||
93 | while (!kthread_should_stop()) { | ||
94 | gfs2_check_journals(sdp); | ||
95 | t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ; | ||
96 | schedule_timeout_interruptible(t); | ||
97 | } | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * gfs2_logd - Update log tail as Active Items get flushed to in-place blocks | ||
104 | * @sdp: Pointer to GFS2 superblock | ||
105 | * | ||
106 | * Also, periodically check to make sure that we're using the most recent | ||
107 | * journal index. | ||
108 | */ | ||
109 | |||
110 | int gfs2_logd(void *data) | ||
111 | { | ||
112 | struct gfs2_sbd *sdp = data; | ||
113 | struct gfs2_holder ji_gh; | ||
114 | unsigned long t; | ||
115 | |||
116 | while (!kthread_should_stop()) { | ||
117 | /* Advance the log tail */ | ||
118 | |||
119 | t = sdp->sd_log_flush_time + | ||
120 | gfs2_tune_get(sdp, gt_log_flush_secs) * HZ; | ||
121 | |||
122 | gfs2_ail1_empty(sdp, DIO_ALL); | ||
123 | |||
124 | if (time_after_eq(jiffies, t)) { | ||
125 | gfs2_log_flush(sdp, NULL); | ||
126 | sdp->sd_log_flush_time = jiffies; | ||
127 | } | ||
128 | |||
129 | /* Check for latest journal index */ | ||
130 | |||
131 | t = sdp->sd_jindex_refresh_time + | ||
132 | gfs2_tune_get(sdp, gt_jindex_refresh_secs) * HZ; | ||
133 | |||
134 | if (time_after_eq(jiffies, t)) { | ||
135 | if (!gfs2_jindex_hold(sdp, &ji_gh)) | ||
136 | gfs2_glock_dq_uninit(&ji_gh); | ||
137 | sdp->sd_jindex_refresh_time = jiffies; | ||
138 | } | ||
139 | |||
140 | t = gfs2_tune_get(sdp, gt_logd_secs) * HZ; | ||
141 | schedule_timeout_interruptible(t); | ||
142 | } | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * gfs2_quotad - Write cached quota changes into the quota file | ||
149 | * @sdp: Pointer to GFS2 superblock | ||
150 | * | ||
151 | */ | ||
152 | |||
153 | int gfs2_quotad(void *data) | ||
154 | { | ||
155 | struct gfs2_sbd *sdp = data; | ||
156 | unsigned long t; | ||
157 | int error; | ||
158 | |||
159 | while (!kthread_should_stop()) { | ||
160 | /* Update the master statfs file */ | ||
161 | |||
162 | t = sdp->sd_statfs_sync_time + | ||
163 | gfs2_tune_get(sdp, gt_statfs_quantum) * HZ; | ||
164 | |||
165 | if (time_after_eq(jiffies, t)) { | ||
166 | error = gfs2_statfs_sync(sdp); | ||
167 | if (error && | ||
168 | error != -EROFS && | ||
169 | !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | ||
170 | fs_err(sdp, "quotad: (1) error=%d\n", error); | ||
171 | sdp->sd_statfs_sync_time = jiffies; | ||
172 | } | ||
173 | |||
174 | /* Update quota file */ | ||
175 | |||
176 | t = sdp->sd_quota_sync_time + | ||
177 | gfs2_tune_get(sdp, gt_quota_quantum) * HZ; | ||
178 | |||
179 | if (time_after_eq(jiffies, t)) { | ||
180 | error = gfs2_quota_sync(sdp); | ||
181 | if (error && | ||
182 | error != -EROFS && | ||
183 | !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | ||
184 | fs_err(sdp, "quotad: (2) error=%d\n", error); | ||
185 | sdp->sd_quota_sync_time = jiffies; | ||
186 | } | ||
187 | |||
188 | gfs2_quota_scan(sdp); | ||
189 | |||
190 | t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ; | ||
191 | schedule_timeout_interruptible(t); | ||
192 | } | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||