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
44int 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
66int 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
88int 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
110int gfs2_logd(void *data)
111{
112	struct gfs2_sbd *sdp = data;
113	struct gfs2_holder ji_gh;
114	unsigned long t;
115	int need_flush;
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);
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)) {
128			gfs2_log_flush(sdp, NULL);
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 = 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