~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/nfs/flushd.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.