pnfs.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * pNFS functions to call and manage layout drivers.
  3. *
  4. * Copyright (c) 2002 [year of first publication]
  5. * The Regents of the University of Michigan
  6. * All Rights Reserved
  7. *
  8. * Dean Hildebrand <dhildebz@umich.edu>
  9. *
  10. * Permission is granted to use, copy, create derivative works, and
  11. * redistribute this software and such derivative works for any purpose,
  12. * so long as the name of the University of Michigan is not used in
  13. * any advertising or publicity pertaining to the use or distribution
  14. * of this software without specific, written prior authorization. If
  15. * the above copyright notice or any other identification of the
  16. * University of Michigan is included in any copy of any portion of
  17. * this software, then the disclaimer below must also be included.
  18. *
  19. * This software is provided as is, without representation or warranty
  20. * of any kind either express or implied, including without limitation
  21. * the implied warranties of merchantability, fitness for a particular
  22. * purpose, or noninfringement. The Regents of the University of
  23. * Michigan shall not be liable for any damages, including special,
  24. * indirect, incidental, or consequential damages, with respect to any
  25. * claim arising out of or in connection with the use of the software,
  26. * even if it has been or is hereafter advised of the possibility of
  27. * such damages.
  28. */
  29. #include <linux/nfs_fs.h>
  30. #include "pnfs.h"
  31. #define NFSDBG_FACILITY NFSDBG_PNFS
  32. /* Locking:
  33. *
  34. * pnfs_spinlock:
  35. * protects pnfs_modules_tbl.
  36. */
  37. static DEFINE_SPINLOCK(pnfs_spinlock);
  38. /*
  39. * pnfs_modules_tbl holds all pnfs modules
  40. */
  41. static LIST_HEAD(pnfs_modules_tbl);
  42. /* Return the registered pnfs layout driver module matching given id */
  43. static struct pnfs_layoutdriver_type *
  44. find_pnfs_driver_locked(u32 id)
  45. {
  46. struct pnfs_layoutdriver_type *local;
  47. list_for_each_entry(local, &pnfs_modules_tbl, pnfs_tblid)
  48. if (local->id == id)
  49. goto out;
  50. local = NULL;
  51. out:
  52. dprintk("%s: Searching for id %u, found %p\n", __func__, id, local);
  53. return local;
  54. }
  55. static struct pnfs_layoutdriver_type *
  56. find_pnfs_driver(u32 id)
  57. {
  58. struct pnfs_layoutdriver_type *local;
  59. spin_lock(&pnfs_spinlock);
  60. local = find_pnfs_driver_locked(id);
  61. spin_unlock(&pnfs_spinlock);
  62. return local;
  63. }
  64. void
  65. unset_pnfs_layoutdriver(struct nfs_server *nfss)
  66. {
  67. if (nfss->pnfs_curr_ld) {
  68. nfss->pnfs_curr_ld->uninitialize_mountpoint(nfss);
  69. module_put(nfss->pnfs_curr_ld->owner);
  70. }
  71. nfss->pnfs_curr_ld = NULL;
  72. }
  73. /*
  74. * Try to set the server's pnfs module to the pnfs layout type specified by id.
  75. * Currently only one pNFS layout driver per filesystem is supported.
  76. *
  77. * @id layout type. Zero (illegal layout type) indicates pNFS not in use.
  78. */
  79. void
  80. set_pnfs_layoutdriver(struct nfs_server *server, u32 id)
  81. {
  82. struct pnfs_layoutdriver_type *ld_type = NULL;
  83. if (id == 0)
  84. goto out_no_driver;
  85. if (!(server->nfs_client->cl_exchange_flags &
  86. (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) {
  87. printk(KERN_ERR "%s: id %u cl_exchange_flags 0x%x\n", __func__,
  88. id, server->nfs_client->cl_exchange_flags);
  89. goto out_no_driver;
  90. }
  91. ld_type = find_pnfs_driver(id);
  92. if (!ld_type) {
  93. request_module("%s-%u", LAYOUT_NFSV4_1_MODULE_PREFIX, id);
  94. ld_type = find_pnfs_driver(id);
  95. if (!ld_type) {
  96. dprintk("%s: No pNFS module found for %u.\n",
  97. __func__, id);
  98. goto out_no_driver;
  99. }
  100. }
  101. if (!try_module_get(ld_type->owner)) {
  102. dprintk("%s: Could not grab reference on module\n", __func__);
  103. goto out_no_driver;
  104. }
  105. server->pnfs_curr_ld = ld_type;
  106. if (ld_type->initialize_mountpoint(server)) {
  107. printk(KERN_ERR
  108. "%s: Error initializing mount point for layout driver %u.\n",
  109. __func__, id);
  110. module_put(ld_type->owner);
  111. goto out_no_driver;
  112. }
  113. dprintk("%s: pNFS module for %u set\n", __func__, id);
  114. return;
  115. out_no_driver:
  116. dprintk("%s: Using NFSv4 I/O\n", __func__);
  117. server->pnfs_curr_ld = NULL;
  118. }
  119. int
  120. pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
  121. {
  122. int status = -EINVAL;
  123. struct pnfs_layoutdriver_type *tmp;
  124. if (ld_type->id == 0) {
  125. printk(KERN_ERR "%s id 0 is reserved\n", __func__);
  126. return status;
  127. }
  128. spin_lock(&pnfs_spinlock);
  129. tmp = find_pnfs_driver_locked(ld_type->id);
  130. if (!tmp) {
  131. list_add(&ld_type->pnfs_tblid, &pnfs_modules_tbl);
  132. status = 0;
  133. dprintk("%s Registering id:%u name:%s\n", __func__, ld_type->id,
  134. ld_type->name);
  135. } else {
  136. printk(KERN_ERR "%s Module with id %d already loaded!\n",
  137. __func__, ld_type->id);
  138. }
  139. spin_unlock(&pnfs_spinlock);
  140. return status;
  141. }
  142. EXPORT_SYMBOL_GPL(pnfs_register_layoutdriver);
  143. void
  144. pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
  145. {
  146. dprintk("%s Deregistering id:%u\n", __func__, ld_type->id);
  147. spin_lock(&pnfs_spinlock);
  148. list_del(&ld_type->pnfs_tblid);
  149. spin_unlock(&pnfs_spinlock);
  150. }
  151. EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver);
  152. static void
  153. get_layout_hdr_locked(struct pnfs_layout_hdr *lo)
  154. {
  155. assert_spin_locked(&lo->inode->i_lock);
  156. lo->refcount++;
  157. }
  158. static void
  159. put_layout_hdr_locked(struct pnfs_layout_hdr *lo)
  160. {
  161. assert_spin_locked(&lo->inode->i_lock);
  162. BUG_ON(lo->refcount == 0);
  163. lo->refcount--;
  164. if (!lo->refcount) {
  165. dprintk("%s: freeing layout cache %p\n", __func__, lo);
  166. NFS_I(lo->inode)->layout = NULL;
  167. kfree(lo);
  168. }
  169. }
  170. void
  171. pnfs_destroy_layout(struct nfs_inode *nfsi)
  172. {
  173. struct pnfs_layout_hdr *lo;
  174. spin_lock(&nfsi->vfs_inode.i_lock);
  175. lo = nfsi->layout;
  176. if (lo) {
  177. /* Matched by refcount set to 1 in alloc_init_layout_hdr */
  178. put_layout_hdr_locked(lo);
  179. }
  180. spin_unlock(&nfsi->vfs_inode.i_lock);
  181. }
  182. /* STUB - pretend LAYOUTGET to server failed */
  183. static struct pnfs_layout_segment *
  184. send_layoutget(struct pnfs_layout_hdr *lo,
  185. struct nfs_open_context *ctx,
  186. u32 iomode)
  187. {
  188. struct inode *ino = lo->inode;
  189. set_bit(lo_fail_bit(iomode), &lo->state);
  190. spin_lock(&ino->i_lock);
  191. put_layout_hdr_locked(lo);
  192. spin_unlock(&ino->i_lock);
  193. return NULL;
  194. }
  195. static struct pnfs_layout_hdr *
  196. alloc_init_layout_hdr(struct inode *ino)
  197. {
  198. struct pnfs_layout_hdr *lo;
  199. lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL);
  200. if (!lo)
  201. return NULL;
  202. lo->refcount = 1;
  203. lo->inode = ino;
  204. return lo;
  205. }
  206. static struct pnfs_layout_hdr *
  207. pnfs_find_alloc_layout(struct inode *ino)
  208. {
  209. struct nfs_inode *nfsi = NFS_I(ino);
  210. struct pnfs_layout_hdr *new = NULL;
  211. dprintk("%s Begin ino=%p layout=%p\n", __func__, ino, nfsi->layout);
  212. assert_spin_locked(&ino->i_lock);
  213. if (nfsi->layout)
  214. return nfsi->layout;
  215. spin_unlock(&ino->i_lock);
  216. new = alloc_init_layout_hdr(ino);
  217. spin_lock(&ino->i_lock);
  218. if (likely(nfsi->layout == NULL)) /* Won the race? */
  219. nfsi->layout = new;
  220. else
  221. kfree(new);
  222. return nfsi->layout;
  223. }
  224. /* STUB - LAYOUTGET never succeeds, so cache is empty */
  225. static struct pnfs_layout_segment *
  226. pnfs_has_layout(struct pnfs_layout_hdr *lo, u32 iomode)
  227. {
  228. return NULL;
  229. }
  230. /*
  231. * Layout segment is retreived from the server if not cached.
  232. * The appropriate layout segment is referenced and returned to the caller.
  233. */
  234. struct pnfs_layout_segment *
  235. pnfs_update_layout(struct inode *ino,
  236. struct nfs_open_context *ctx,
  237. enum pnfs_iomode iomode)
  238. {
  239. struct nfs_inode *nfsi = NFS_I(ino);
  240. struct pnfs_layout_hdr *lo;
  241. struct pnfs_layout_segment *lseg = NULL;
  242. if (!pnfs_enabled_sb(NFS_SERVER(ino)))
  243. return NULL;
  244. spin_lock(&ino->i_lock);
  245. lo = pnfs_find_alloc_layout(ino);
  246. if (lo == NULL) {
  247. dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
  248. goto out_unlock;
  249. }
  250. /* Check to see if the layout for the given range already exists */
  251. lseg = pnfs_has_layout(lo, iomode);
  252. if (lseg) {
  253. dprintk("%s: Using cached lseg %p for iomode %d)\n",
  254. __func__, lseg, iomode);
  255. goto out_unlock;
  256. }
  257. /* if LAYOUTGET already failed once we don't try again */
  258. if (test_bit(lo_fail_bit(iomode), &nfsi->layout->state))
  259. goto out_unlock;
  260. get_layout_hdr_locked(lo);
  261. spin_unlock(&ino->i_lock);
  262. lseg = send_layoutget(lo, ctx, iomode);
  263. out:
  264. dprintk("%s end, state 0x%lx lseg %p\n", __func__,
  265. nfsi->layout->state, lseg);
  266. return lseg;
  267. out_unlock:
  268. spin_unlock(&ino->i_lock);
  269. goto out;
  270. }