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