The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nfs/flushd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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_page.h>
   42 #include <linux/nfs_fs_sb.h>
   43 #include <linux/nfs_flushd.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 RPC_WAITQ(flushd_queue, "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 static 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) {
  115                 rpc_exit(cache->task, 0);
  116                 rpc_wake_up_task(cache->task);
  117 
  118                 interruptible_sleep_on_timeout(&cache->request_wait, 1 * HZ);
  119         }
  120  out:
  121         unlock_kernel();
  122 }
  123 
  124 int nfs_reqlist_alloc(struct nfs_server *server)
  125 {
  126         struct nfs_reqlist      *cache;
  127         if (server->rw_requests)
  128                 return 0;
  129 
  130         cache = (struct nfs_reqlist *)kmalloc(sizeof(*cache), GFP_KERNEL);
  131         if (!cache)
  132                 return -ENOMEM;
  133 
  134         memset(cache, 0, sizeof(*cache));
  135         atomic_set(&cache->nr_requests, 0);
  136         init_waitqueue_head(&cache->request_wait);
  137         server->rw_requests = cache;
  138 
  139         return nfs_reqlist_init(server);
  140 }
  141 
  142 void nfs_reqlist_free(struct nfs_server *server)
  143 {
  144         if (server->rw_requests) {
  145                 kfree(server->rw_requests);
  146                 server->rw_requests = NULL;
  147         }
  148 }
  149 
  150 #define NFS_FLUSHD_TIMEOUT      (30*HZ)
  151 static void
  152 nfs_flushd(struct rpc_task *task)
  153 {
  154         struct nfs_server       *server;
  155         struct nfs_reqlist      *cache;
  156         LIST_HEAD(head);
  157 
  158         dprintk("NFS: %4d flushd starting\n", task->tk_pid);
  159         server = (struct nfs_server *) task->tk_calldata;
  160         cache = server->rw_requests;
  161 
  162         for(;;) {
  163                 spin_lock(&nfs_wreq_lock);
  164                 if (nfs_scan_lru_dirty_timeout(server, &head)) {
  165                         spin_unlock(&nfs_wreq_lock);
  166                         nfs_flush_list(&head, server->wpages, FLUSH_AGING);
  167                         continue;
  168                 }
  169                 if (nfs_scan_lru_read_timeout(server, &head)) {
  170                         spin_unlock(&nfs_wreq_lock);
  171                         nfs_pagein_list(&head, server->rpages);
  172                         continue;
  173                 }
  174 #ifdef CONFIG_NFS_V3
  175                 if (nfs_scan_lru_commit_timeout(server, &head)) {
  176                         spin_unlock(&nfs_wreq_lock);
  177                         nfs_commit_list(&head, FLUSH_AGING);
  178                         continue;
  179                 }
  180 #endif
  181                 spin_unlock(&nfs_wreq_lock);
  182                 break;
  183         }
  184 
  185         dprintk("NFS: %4d flushd back to sleep\n", task->tk_pid);
  186         if (task->tk_action) {
  187                 task->tk_timeout = NFS_FLUSHD_TIMEOUT;
  188                 cache->runat = jiffies + task->tk_timeout;
  189                 rpc_sleep_on(&flushd_queue, task, NULL, NULL);
  190         }
  191 }
  192 
  193 static void
  194 nfs_flushd_exit(struct rpc_task *task)
  195 {
  196         struct nfs_server       *server;
  197         struct nfs_reqlist      *cache;
  198         server = (struct nfs_server *) task->tk_calldata;
  199         cache = server->rw_requests;
  200 
  201         if (cache->task == task)
  202                 cache->task = NULL;
  203         wake_up(&cache->request_wait);
  204 }
  205 

Cache object: 7af8de124c006fb49442512258377222


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.