]>
Commit | Line | Data |
---|---|---|
b3b94faa DT |
1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | |
3a8a9a10 | 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
b3b94faa DT |
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 | |
e9fc2aa0 | 7 | * of the GNU General Public License version 2. |
b3b94faa DT |
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> | |
5c676f6d | 17 | #include <linux/gfs2_ondisk.h> |
7d308590 | 18 | #include <linux/lm_interface.h> |
b3b94faa DT |
19 | |
20 | #include "gfs2.h" | |
5c676f6d | 21 | #include "incore.h" |
b3b94faa DT |
22 | #include "daemon.h" |
23 | #include "glock.h" | |
24 | #include "log.h" | |
25 | #include "quota.h" | |
26 | #include "recovery.h" | |
27 | #include "super.h" | |
5c676f6d | 28 | #include "util.h" |
b3b94faa DT |
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. | |
907b9bce | 33 | |
b3b94faa DT |
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 | { | |
b800a1cb | 46 | struct gfs2_sbd *sdp = data; |
b3b94faa DT |
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 | { | |
b800a1cb | 68 | struct gfs2_sbd *sdp = data; |
b3b94faa DT |
69 | |
70 | while (!kthread_should_stop()) { | |
71 | while (atomic_read(&sdp->sd_reclaim_count)) | |
72 | gfs2_reclaim_glock(sdp); | |
73 | ||
b800a1cb SW |
74 | wait_event_interruptible(sdp->sd_reclaim_wq, |
75 | (atomic_read(&sdp->sd_reclaim_count) || | |
76 | kthread_should_stop())); | |
b3b94faa DT |
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 | { | |
b800a1cb | 90 | struct gfs2_sbd *sdp = data; |
b3b94faa DT |
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 | { | |
b800a1cb | 112 | struct gfs2_sbd *sdp = data; |
b3b94faa DT |
113 | struct gfs2_holder ji_gh; |
114 | unsigned long t; | |
b004157a | 115 | int need_flush; |
b3b94faa DT |
116 | |
117 | while (!kthread_should_stop()) { | |
118 | /* Advance the log tail */ | |
119 | ||
120 | t = sdp->sd_log_flush_time + | |
121 | gfs2_tune_get(sdp, gt_log_flush_secs) * HZ; | |
122 | ||
123 | gfs2_ail1_empty(sdp, DIO_ALL); | |
b004157a SW |
124 | gfs2_log_lock(sdp); |
125 | need_flush = sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks); | |
126 | gfs2_log_unlock(sdp); | |
127 | if (need_flush || time_after_eq(jiffies, t)) { | |
b09e593d | 128 | gfs2_log_flush(sdp, NULL); |
b3b94faa DT |
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 | ||
156 | int gfs2_quotad(void *data) | |
157 | { | |
b800a1cb | 158 | struct gfs2_sbd *sdp = data; |
b3b94faa DT |
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 |