File: /usr/src/linux/fs/nfs/flushd.c
1 /*
2 * linux/fs/nfs/flushd.c
3 *
4 * For each NFS mount, there is a separate cache object that contains
5 * a hash table of all clusters. With this cache, an async RPC task
6 * (`flushd') is associated, which wakes up occasionally to inspect
7 * its list of dirty buffers.
8 * (Note that RPC tasks aren't kernel threads. Take a look at the
9 * rpciod code to understand what they are).
10 *
11 * Inside the cache object, we also maintain a count of the current number
12 * of dirty pages, which may not exceed a certain threshold.
13 * (FIXME: This threshold should be configurable).
14 *
15 * The code is streamlined for what I think is the prevalent case for
16 * NFS traffic, which is sequential write access without concurrent
17 * access by different processes.
18 *
19 * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
20 *
21 * Rewritten 6/3/2000 by Trond Myklebust
22 * Copyright (C) 1999, 2000, Trond Myklebust <trond.myklebust@fys.uio.no>
23 */
24
25 #include <linux/config.h>
26 #include <linux/types.h>
27 #include <linux/slab.h>
28 #include <linux/pagemap.h>
29 #include <linux/file.h>
30
31 #include <linux/sched.h>
32
33 #include <linux/sunrpc/auth.h>
34 #include <linux/sunrpc/clnt.h>
35 #include <linux/sunrpc/sched.h>
36
37 #include <linux/smp_lock.h>
38
39 #include <linux/nfs.h>
40 #include <linux/nfs_fs.h>
41 #include <linux/nfs_fs_sb.h>
42 #include <linux/nfs_flushd.h>
43 #include <linux/nfs_mount.h>
44
45 /*
46 * Various constants
47 */
48 #define NFSDBG_FACILITY NFSDBG_PAGECACHE
49
50 /*
51 * This is the wait queue all cluster daemons sleep on
52 */
53 static struct rpc_wait_queue flushd_queue = RPC_INIT_WAITQ("nfs_flushd");
54
55 /*
56 * Local function declarations.
57 */
58 static void nfs_flushd(struct rpc_task *);
59 static void nfs_flushd_exit(struct rpc_task *);
60
61
62 int nfs_reqlist_init(struct nfs_server *server)
63 {
64 struct nfs_reqlist *cache;
65 struct rpc_task *task;
66 int status;
67
68 dprintk("NFS: writecache_init\n");
69
70 lock_kernel();
71 status = -ENOMEM;
72 /* Create the RPC task */
73 if (!(task = rpc_new_task(server->client, NULL, RPC_TASK_ASYNC)))
74 goto out_unlock;
75
76 cache = server->rw_requests;
77
78 status = 0;
79 if (cache->task)
80 goto out_unlock;
81
82 task->tk_calldata = server;
83
84 cache->task = task;
85
86 /* Run the task */
87 cache->runat = jiffies;
88
89 cache->auth = server->client->cl_auth;
90 task->tk_action = nfs_flushd;
91 task->tk_exit = nfs_flushd_exit;
92
93 rpc_execute(task);
94 unlock_kernel();
95 return 0;
96 out_unlock:
97 if (task)
98 rpc_release_task(task);
99 unlock_kernel();
100 return status;
101 }
102
103 void nfs_reqlist_exit(struct nfs_server *server)
104 {
105 struct nfs_reqlist *cache;
106
107 lock_kernel();
108 cache = server->rw_requests;
109 if (!cache)
110 goto out;
111
112 dprintk("NFS: reqlist_exit (ptr %p rpc %p)\n", cache, cache->task);
113
114 while (cache->task || cache->inodes) {
115 if (!cache->task) {
116 nfs_reqlist_init(server);
117 } else {
118 cache->task->tk_status = -ENOMEM;
119 rpc_wake_up_task(cache->task);
120 }
121 interruptible_sleep_on_timeout(&cache->request_wait, 1 * HZ);
122 }
123 out:
124 unlock_kernel();
125 }
126
127 int nfs_reqlist_alloc(struct nfs_server *server)
128 {
129 struct nfs_reqlist *cache;
130 if (server->rw_requests)
131 return 0;
132
133 cache = (struct nfs_reqlist *)kmalloc(sizeof(*cache), GFP_KERNEL);
134 if (!cache)
135 return -ENOMEM;
136
137 memset(cache, 0, sizeof(*cache));
138 atomic_set(&cache->nr_requests, 0);
139 init_waitqueue_head(&cache->request_wait);
140 server->rw_requests = cache;
141
142 return 0;
143 }
144
145 void nfs_reqlist_free(struct nfs_server *server)
146 {
147 if (server->rw_requests) {
148 kfree(server->rw_requests);
149 server->rw_requests = NULL;
150 }
151 }
152
153 void nfs_wake_flushd()
154 {
155 rpc_wake_up_status(&flushd_queue, -ENOMEM);
156 }
157
158 static void inode_append_flushd(struct inode *inode)
159 {
160 struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
161 struct inode **q;
162
163 if (NFS_FLAGS(inode) & NFS_INO_FLUSH)
164 goto out;
165 inode->u.nfs_i.hash_next = NULL;
166
167 q = &cache->inodes;
168 while (*q)
169 q = &(*q)->u.nfs_i.hash_next;
170 *q = inode;
171
172 /* Note: we increase the inode i_count in order to prevent
173 * it from disappearing when on the flush list
174 */
175 NFS_FLAGS(inode) |= NFS_INO_FLUSH;
176 atomic_inc(&inode->i_count);
177 out:;
178 }
179
180 /* Protect me using the BKL */
181 void inode_remove_flushd(struct inode *inode)
182 {
183 struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
184 struct inode **q;
185
186 if (!(NFS_FLAGS(inode) & NFS_INO_FLUSH))
187 return;
188
189 q = &cache->inodes;
190 while (*q && *q != inode)
191 q = &(*q)->u.nfs_i.hash_next;
192 if (*q) {
193 *q = inode->u.nfs_i.hash_next;
194 NFS_FLAGS(inode) &= ~NFS_INO_FLUSH;
195 iput(inode);
196 }
197 }
198
199 void inode_schedule_scan(struct inode *inode, unsigned long time)
200 {
201 struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
202 struct rpc_task *task;
203 unsigned long mintimeout;
204
205 lock_kernel();
206 if (time_after(NFS_NEXTSCAN(inode), time))
207 NFS_NEXTSCAN(inode) = time;
208 mintimeout = jiffies + 1 * HZ;
209 if (time_before(mintimeout, NFS_NEXTSCAN(inode)))
210 mintimeout = NFS_NEXTSCAN(inode);
211 inode_append_flushd(inode);
212
213 task = cache->task;
214 if (!task) {
215 nfs_reqlist_init(NFS_SERVER(inode));
216 } else {
217 if (time_after(cache->runat, mintimeout))
218 rpc_wake_up_task(task);
219 }
220 unlock_kernel();
221 }
222
223
224 static void
225 nfs_flushd(struct rpc_task *task)
226 {
227 struct nfs_server *server;
228 struct nfs_reqlist *cache;
229 struct inode *inode, *next;
230 unsigned long delay = jiffies + NFS_WRITEBACK_LOCKDELAY;
231 int flush = (task->tk_status == -ENOMEM);
232
233 dprintk("NFS: %4d flushd starting\n", task->tk_pid);
234 server = (struct nfs_server *) task->tk_calldata;
235 cache = server->rw_requests;
236
237 next = cache->inodes;
238 cache->inodes = NULL;
239
240 while ((inode = next) != NULL) {
241 next = next->u.nfs_i.hash_next;
242 inode->u.nfs_i.hash_next = NULL;
243 NFS_FLAGS(inode) &= ~NFS_INO_FLUSH;
244
245 if (flush) {
246 nfs_pagein_inode(inode, 0, 0);
247 nfs_sync_file(inode, NULL, 0, 0, FLUSH_AGING);
248 } else if (time_after(jiffies, NFS_NEXTSCAN(inode))) {
249 NFS_NEXTSCAN(inode) = jiffies + NFS_WRITEBACK_LOCKDELAY;
250 nfs_pagein_timeout(inode);
251 nfs_flush_timeout(inode, FLUSH_AGING);
252 #ifdef CONFIG_NFS_V3
253 nfs_commit_timeout(inode, FLUSH_AGING);
254 #endif
255 }
256
257 if (nfs_have_writebacks(inode) || nfs_have_read(inode)) {
258 inode_append_flushd(inode);
259 if (time_after(delay, NFS_NEXTSCAN(inode)))
260 delay = NFS_NEXTSCAN(inode);
261 }
262 iput(inode);
263 }
264
265 dprintk("NFS: %4d flushd back to sleep\n", task->tk_pid);
266 if (time_after(jiffies + 1 * HZ, delay))
267 delay = 1 * HZ;
268 else
269 delay = delay - jiffies;
270 task->tk_status = 0;
271 task->tk_action = nfs_flushd;
272 task->tk_timeout = delay;
273 cache->runat = jiffies + task->tk_timeout;
274
275 if (!atomic_read(&cache->nr_requests) && !cache->inodes) {
276 cache->task = NULL;
277 task->tk_action = NULL;
278 } else
279 rpc_sleep_on(&flushd_queue, task, NULL, NULL);
280 }
281
282 static void
283 nfs_flushd_exit(struct rpc_task *task)
284 {
285 struct nfs_server *server;
286 struct nfs_reqlist *cache;
287 server = (struct nfs_server *) task->tk_calldata;
288 cache = server->rw_requests;
289
290 if (cache->task == task)
291 cache->task = NULL;
292 wake_up(&cache->request_wait);
293 }
294
295