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/malloc.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/spinlock.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 * Spinlock
57 */
58 spinlock_t nfs_flushd_lock = SPIN_LOCK_UNLOCKED;
59
60 /*
61 * Local function declarations.
62 */
63 static void nfs_flushd(struct rpc_task *);
64 static void nfs_flushd_exit(struct rpc_task *);
65
66
67 int nfs_reqlist_init(struct nfs_server *server)
68 {
69 struct nfs_reqlist *cache;
70 struct rpc_task *task;
71 int status = 0;
72
73 dprintk("NFS: writecache_init\n");
74 spin_lock(&nfs_flushd_lock);
75 cache = server->rw_requests;
76
77 if (cache->task)
78 goto out_unlock;
79
80 /* Create the RPC task */
81 status = -ENOMEM;
82 task = rpc_new_task(server->client, NULL, RPC_TASK_ASYNC);
83 if (!task)
84 goto out_unlock;
85
86 task->tk_calldata = server;
87
88 cache->task = task;
89
90 /* Run the task */
91 cache->runat = jiffies;
92
93 cache->auth = server->client->cl_auth;
94 task->tk_action = nfs_flushd;
95 task->tk_exit = nfs_flushd_exit;
96
97 spin_unlock(&nfs_flushd_lock);
98 rpc_execute(task);
99 return 0;
100 out_unlock:
101 spin_unlock(&nfs_flushd_lock);
102 return status;
103 }
104
105 void nfs_reqlist_exit(struct nfs_server *server)
106 {
107 struct nfs_reqlist *cache;
108
109 cache = server->rw_requests;
110 if (!cache)
111 return;
112
113 dprintk("NFS: reqlist_exit (ptr %p rpc %p)\n", cache, cache->task);
114 while (cache->task || cache->inodes) {
115 spin_lock(&nfs_flushd_lock);
116 if (!cache->task) {
117 spin_unlock(&nfs_flushd_lock);
118 nfs_reqlist_init(server);
119 } else {
120 cache->task->tk_status = -ENOMEM;
121 rpc_wake_up_task(cache->task);
122 spin_unlock(&nfs_flushd_lock);
123 }
124 interruptible_sleep_on_timeout(&cache->request_wait, 1 * HZ);
125 }
126 }
127
128 int nfs_reqlist_alloc(struct nfs_server *server)
129 {
130 struct nfs_reqlist *cache;
131 if (server->rw_requests)
132 return 0;
133
134 cache = (struct nfs_reqlist *)kmalloc(sizeof(*cache), GFP_KERNEL);
135 if (!cache)
136 return -ENOMEM;
137
138 memset(cache, 0, sizeof(*cache));
139 atomic_set(&cache->nr_requests, 0);
140 init_waitqueue_head(&cache->request_wait);
141 server->rw_requests = cache;
142
143 return 0;
144 }
145
146 void nfs_reqlist_free(struct nfs_server *server)
147 {
148 if (server->rw_requests) {
149 kfree(server->rw_requests);
150 server->rw_requests = NULL;
151 }
152 }
153
154 void nfs_wake_flushd()
155 {
156 rpc_wake_up_status(&flushd_queue, -ENOMEM);
157 }
158
159 static void inode_append_flushd(struct inode *inode)
160 {
161 struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
162 struct inode **q;
163
164 spin_lock(&nfs_flushd_lock);
165 if (NFS_FLAGS(inode) & NFS_INO_FLUSH)
166 goto out;
167 inode->u.nfs_i.hash_next = NULL;
168
169 q = &cache->inodes;
170 while (*q)
171 q = &(*q)->u.nfs_i.hash_next;
172 *q = inode;
173
174 /* Note: we increase the inode i_count in order to prevent
175 * it from disappearing when on the flush list
176 */
177 NFS_FLAGS(inode) |= NFS_INO_FLUSH;
178 atomic_inc(&inode->i_count);
179 out:
180 spin_unlock(&nfs_flushd_lock);
181 }
182
183 void inode_remove_flushd(struct inode *inode)
184 {
185 struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
186 struct inode **q;
187
188 spin_lock(&nfs_flushd_lock);
189 if (!(NFS_FLAGS(inode) & NFS_INO_FLUSH))
190 goto out;
191
192 q = &cache->inodes;
193 while (*q && *q != inode)
194 q = &(*q)->u.nfs_i.hash_next;
195 if (*q) {
196 *q = inode->u.nfs_i.hash_next;
197 NFS_FLAGS(inode) &= ~NFS_INO_FLUSH;
198 iput(inode);
199 }
200 out:
201 spin_unlock(&nfs_flushd_lock);
202 }
203
204 void inode_schedule_scan(struct inode *inode, unsigned long time)
205 {
206 struct nfs_reqlist *cache = NFS_REQUESTLIST(inode);
207 struct rpc_task *task;
208 unsigned long mintimeout;
209
210 if (time_after(NFS_NEXTSCAN(inode), time))
211 NFS_NEXTSCAN(inode) = time;
212 mintimeout = jiffies + 1 * HZ;
213 if (time_before(mintimeout, NFS_NEXTSCAN(inode)))
214 mintimeout = NFS_NEXTSCAN(inode);
215 inode_append_flushd(inode);
216
217 spin_lock(&nfs_flushd_lock);
218 task = cache->task;
219 if (!task) {
220 spin_unlock(&nfs_flushd_lock);
221 nfs_reqlist_init(NFS_SERVER(inode));
222 } else {
223 if (time_after(cache->runat, mintimeout))
224 rpc_wake_up_task(task);
225 spin_unlock(&nfs_flushd_lock);
226 }
227 }
228
229
230 static void
231 nfs_flushd(struct rpc_task *task)
232 {
233 struct nfs_server *server;
234 struct nfs_reqlist *cache;
235 struct inode *inode, *next;
236 unsigned long delay = jiffies + NFS_WRITEBACK_LOCKDELAY;
237 int flush = (task->tk_status == -ENOMEM);
238
239 dprintk("NFS: %4d flushd starting\n", task->tk_pid);
240 server = (struct nfs_server *) task->tk_calldata;
241 cache = server->rw_requests;
242
243 spin_lock(&nfs_flushd_lock);
244 next = cache->inodes;
245 cache->inodes = NULL;
246 spin_unlock(&nfs_flushd_lock);
247
248 while ((inode = next) != NULL) {
249 next = next->u.nfs_i.hash_next;
250 inode->u.nfs_i.hash_next = NULL;
251 NFS_FLAGS(inode) &= ~NFS_INO_FLUSH;
252
253 if (flush) {
254 nfs_pagein_inode(inode, 0, 0);
255 nfs_sync_file(inode, NULL, 0, 0, FLUSH_AGING);
256 } else if (time_after(jiffies, NFS_NEXTSCAN(inode))) {
257 NFS_NEXTSCAN(inode) = jiffies + NFS_WRITEBACK_LOCKDELAY;
258 nfs_pagein_timeout(inode);
259 nfs_flush_timeout(inode, FLUSH_AGING);
260 #ifdef CONFIG_NFS_V3
261 nfs_commit_timeout(inode, FLUSH_AGING);
262 #endif
263 }
264
265 if (nfs_have_writebacks(inode) || nfs_have_read(inode)) {
266 inode_append_flushd(inode);
267 if (time_after(delay, NFS_NEXTSCAN(inode)))
268 delay = NFS_NEXTSCAN(inode);
269 }
270 iput(inode);
271 }
272
273 dprintk("NFS: %4d flushd back to sleep\n", task->tk_pid);
274 if (time_after(jiffies + 1 * HZ, delay))
275 delay = 1 * HZ;
276 else
277 delay = delay - jiffies;
278 task->tk_status = 0;
279 task->tk_action = nfs_flushd;
280 task->tk_timeout = delay;
281 cache->runat = jiffies + task->tk_timeout;
282
283 spin_lock(&nfs_flushd_lock);
284 if (!atomic_read(&cache->nr_requests) && !cache->inodes) {
285 cache->task = NULL;
286 task->tk_action = NULL;
287 } else
288 rpc_sleep_on(&flushd_queue, task, NULL, NULL);
289 spin_unlock(&nfs_flushd_lock);
290 }
291
292 static void
293 nfs_flushd_exit(struct rpc_task *task)
294 {
295 struct nfs_server *server;
296 struct nfs_reqlist *cache;
297 server = (struct nfs_server *) task->tk_calldata;
298 cache = server->rw_requests;
299
300 spin_lock(&nfs_flushd_lock);
301 if (cache->task == task)
302 cache->task = NULL;
303 spin_unlock(&nfs_flushd_lock);
304 wake_up(&cache->request_wait);
305 }
306
307
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.