Merge branch 'master'
[linux-2.6] / fs / gfs2 / daemon.c
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 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 <linux/gfs2_ondisk.h>
18
19 #include "gfs2.h"
20 #include "lm_interface.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