flushd.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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. #include <linux/config.h>
  25. #include <linux/types.h>
  26. #include <linux/slab.h>
  27. #include <linux/pagemap.h>
  28. #include <linux/file.h>
  29. #include <linux/sched.h>
  30. #include <linux/sunrpc/auth.h>
  31. #include <linux/sunrpc/clnt.h>
  32. #include <linux/sunrpc/sched.h>
  33. #include <linux/smp_lock.h>
  34. #include <linux/nfs.h>
  35. #include <linux/nfs_fs.h>
  36. #include <linux/nfs_page.h>
  37. #include <linux/nfs_fs_sb.h>
  38. #include <linux/nfs_flushd.h>
  39. /*
  40.  * Various constants
  41.  */
  42. #define NFSDBG_FACILITY         NFSDBG_PAGECACHE
  43. /*
  44.  * This is the wait queue all cluster daemons sleep on
  45.  */
  46. static RPC_WAITQ(flushd_queue, "nfs_flushd");
  47. /*
  48.  * Local function declarations.
  49.  */
  50. static void nfs_flushd(struct rpc_task *);
  51. static void nfs_flushd_exit(struct rpc_task *);
  52. static int nfs_reqlist_init(struct nfs_server *server)
  53. {
  54. struct nfs_reqlist *cache;
  55. struct rpc_task *task;
  56. int status;
  57. dprintk("NFS: writecache_initn");
  58. lock_kernel();
  59. status = -ENOMEM;
  60. /* Create the RPC task */
  61. if (!(task = rpc_new_task(server->client, NULL, RPC_TASK_ASYNC)))
  62. goto out_unlock;
  63. cache = server->rw_requests;
  64. status = 0;
  65. if (cache->task)
  66. goto out_unlock;
  67. task->tk_calldata = server;
  68. cache->task = task;
  69. /* Run the task */
  70. cache->runat = jiffies;
  71. cache->auth = server->client->cl_auth;
  72. task->tk_action   = nfs_flushd;
  73. task->tk_exit   = nfs_flushd_exit;
  74. rpc_execute(task);
  75. unlock_kernel();
  76. return 0;
  77.  out_unlock:
  78. if (task)
  79. rpc_release_task(task);
  80. unlock_kernel();
  81. return status;
  82. }
  83. void nfs_reqlist_exit(struct nfs_server *server)
  84. {
  85. struct nfs_reqlist      *cache;
  86. lock_kernel();
  87. cache = server->rw_requests;
  88. if (!cache)
  89. goto out;
  90. dprintk("NFS: reqlist_exit (ptr %p rpc %p)n", cache, cache->task);
  91. while (cache->task) {
  92. rpc_exit(cache->task, 0);
  93. rpc_wake_up_task(cache->task);
  94. interruptible_sleep_on_timeout(&cache->request_wait, 1 * HZ);
  95. }
  96.  out:
  97. unlock_kernel();
  98. }
  99. int nfs_reqlist_alloc(struct nfs_server *server)
  100. {
  101. struct nfs_reqlist *cache;
  102. if (server->rw_requests)
  103. return 0;
  104. cache = (struct nfs_reqlist *)kmalloc(sizeof(*cache), GFP_KERNEL);
  105. if (!cache)
  106. return -ENOMEM;
  107. memset(cache, 0, sizeof(*cache));
  108. atomic_set(&cache->nr_requests, 0);
  109. init_waitqueue_head(&cache->request_wait);
  110. server->rw_requests = cache;
  111. return nfs_reqlist_init(server);
  112. }
  113. void nfs_reqlist_free(struct nfs_server *server)
  114. {
  115. if (server->rw_requests) {
  116. kfree(server->rw_requests);
  117. server->rw_requests = NULL;
  118. }
  119. }
  120. #define NFS_FLUSHD_TIMEOUT (30*HZ)
  121. static void
  122. nfs_flushd(struct rpc_task *task)
  123. {
  124. struct nfs_server *server;
  125. struct nfs_reqlist *cache;
  126. LIST_HEAD(head);
  127.         dprintk("NFS: %4d flushd startingn", task->tk_pid);
  128. server = (struct nfs_server *) task->tk_calldata;
  129.         cache = server->rw_requests;
  130. for(;;) {
  131. spin_lock(&nfs_wreq_lock);
  132. if (nfs_scan_lru_dirty_timeout(server, &head)) {
  133. spin_unlock(&nfs_wreq_lock);
  134. nfs_flush_list(&head, server->wpages, FLUSH_AGING);
  135. continue;
  136. }
  137. if (nfs_scan_lru_read_timeout(server, &head)) {
  138. spin_unlock(&nfs_wreq_lock);
  139. nfs_pagein_list(&head, server->rpages);
  140. continue;
  141. }
  142. #ifdef CONFIG_NFS_V3
  143. if (nfs_scan_lru_commit_timeout(server, &head)) {
  144. spin_unlock(&nfs_wreq_lock);
  145. nfs_commit_list(&head, FLUSH_AGING);
  146. continue;
  147. }
  148. #endif
  149. spin_unlock(&nfs_wreq_lock);
  150. break;
  151. }
  152. dprintk("NFS: %4d flushd back to sleepn", task->tk_pid);
  153. if (task->tk_action) {
  154. task->tk_timeout = NFS_FLUSHD_TIMEOUT;
  155. cache->runat = jiffies + task->tk_timeout;
  156. rpc_sleep_on(&flushd_queue, task, NULL, NULL);
  157. }
  158. }
  159. static void
  160. nfs_flushd_exit(struct rpc_task *task)
  161. {
  162. struct nfs_server *server;
  163. struct nfs_reqlist *cache;
  164. server = (struct nfs_server *) task->tk_calldata;
  165. cache = server->rw_requests;
  166. if (cache->task == task)
  167. cache->task = NULL;
  168. wake_up(&cache->request_wait);
  169. }