cache.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * V9FS cache definitions.
  4. *
  5. * Copyright (C) 2009 by Abhishek Kulkarni <adkulkar@umail.iu.edu>
  6. */
  7. #include <linux/jiffies.h>
  8. #include <linux/file.h>
  9. #include <linux/slab.h>
  10. #include <linux/stat.h>
  11. #include <linux/sched.h>
  12. #include <linux/fs.h>
  13. #include <net/9p/9p.h>
  14. #include "v9fs.h"
  15. #include "cache.h"
  16. #define CACHETAG_LEN 11
  17. struct fscache_netfs v9fs_cache_netfs = {
  18. .name = "9p",
  19. .version = 0,
  20. };
  21. /**
  22. * v9fs_random_cachetag - Generate a random tag to be associated
  23. * with a new cache session.
  24. *
  25. * The value of jiffies is used for a fairly randomly cache tag.
  26. */
  27. static
  28. int v9fs_random_cachetag(struct v9fs_session_info *v9ses)
  29. {
  30. v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL);
  31. if (!v9ses->cachetag)
  32. return -ENOMEM;
  33. return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies);
  34. }
  35. const struct fscache_cookie_def v9fs_cache_session_index_def = {
  36. .name = "9P.session",
  37. .type = FSCACHE_COOKIE_TYPE_INDEX,
  38. };
  39. void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses)
  40. {
  41. /* If no cache session tag was specified, we generate a random one. */
  42. if (!v9ses->cachetag) {
  43. if (v9fs_random_cachetag(v9ses) < 0) {
  44. v9ses->fscache = NULL;
  45. kfree(v9ses->cachetag);
  46. v9ses->cachetag = NULL;
  47. return;
  48. }
  49. }
  50. v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index,
  51. &v9fs_cache_session_index_def,
  52. v9ses->cachetag,
  53. strlen(v9ses->cachetag),
  54. NULL, 0,
  55. v9ses, 0, true);
  56. p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n",
  57. v9ses, v9ses->fscache);
  58. }
  59. void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses)
  60. {
  61. p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n",
  62. v9ses, v9ses->fscache);
  63. fscache_relinquish_cookie(v9ses->fscache, NULL, false);
  64. v9ses->fscache = NULL;
  65. }
  66. static enum
  67. fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
  68. const void *buffer,
  69. uint16_t buflen,
  70. loff_t object_size)
  71. {
  72. const struct v9fs_inode *v9inode = cookie_netfs_data;
  73. if (buflen != sizeof(v9inode->qid.version))
  74. return FSCACHE_CHECKAUX_OBSOLETE;
  75. if (memcmp(buffer, &v9inode->qid.version,
  76. sizeof(v9inode->qid.version)))
  77. return FSCACHE_CHECKAUX_OBSOLETE;
  78. return FSCACHE_CHECKAUX_OKAY;
  79. }
  80. const struct fscache_cookie_def v9fs_cache_inode_index_def = {
  81. .name = "9p.inode",
  82. .type = FSCACHE_COOKIE_TYPE_DATAFILE,
  83. .check_aux = v9fs_cache_inode_check_aux,
  84. };
  85. void v9fs_cache_inode_get_cookie(struct inode *inode)
  86. {
  87. struct v9fs_inode *v9inode;
  88. struct v9fs_session_info *v9ses;
  89. if (!S_ISREG(inode->i_mode))
  90. return;
  91. v9inode = V9FS_I(inode);
  92. if (v9inode->fscache)
  93. return;
  94. v9ses = v9fs_inode2v9ses(inode);
  95. v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
  96. &v9fs_cache_inode_index_def,
  97. &v9inode->qid.path,
  98. sizeof(v9inode->qid.path),
  99. &v9inode->qid.version,
  100. sizeof(v9inode->qid.version),
  101. v9inode,
  102. i_size_read(&v9inode->vfs_inode),
  103. true);
  104. p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
  105. inode, v9inode->fscache);
  106. }
  107. void v9fs_cache_inode_put_cookie(struct inode *inode)
  108. {
  109. struct v9fs_inode *v9inode = V9FS_I(inode);
  110. if (!v9inode->fscache)
  111. return;
  112. p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n",
  113. inode, v9inode->fscache);
  114. fscache_relinquish_cookie(v9inode->fscache, &v9inode->qid.version,
  115. false);
  116. v9inode->fscache = NULL;
  117. }
  118. void v9fs_cache_inode_flush_cookie(struct inode *inode)
  119. {
  120. struct v9fs_inode *v9inode = V9FS_I(inode);
  121. if (!v9inode->fscache)
  122. return;
  123. p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n",
  124. inode, v9inode->fscache);
  125. fscache_relinquish_cookie(v9inode->fscache, NULL, true);
  126. v9inode->fscache = NULL;
  127. }
  128. void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp)
  129. {
  130. struct v9fs_inode *v9inode = V9FS_I(inode);
  131. if (!v9inode->fscache)
  132. return;
  133. mutex_lock(&v9inode->fscache_lock);
  134. if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
  135. v9fs_cache_inode_flush_cookie(inode);
  136. else
  137. v9fs_cache_inode_get_cookie(inode);
  138. mutex_unlock(&v9inode->fscache_lock);
  139. }
  140. void v9fs_cache_inode_reset_cookie(struct inode *inode)
  141. {
  142. struct v9fs_inode *v9inode = V9FS_I(inode);
  143. struct v9fs_session_info *v9ses;
  144. struct fscache_cookie *old;
  145. if (!v9inode->fscache)
  146. return;
  147. old = v9inode->fscache;
  148. mutex_lock(&v9inode->fscache_lock);
  149. fscache_relinquish_cookie(v9inode->fscache, NULL, true);
  150. v9ses = v9fs_inode2v9ses(inode);
  151. v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
  152. &v9fs_cache_inode_index_def,
  153. &v9inode->qid.path,
  154. sizeof(v9inode->qid.path),
  155. &v9inode->qid.version,
  156. sizeof(v9inode->qid.version),
  157. v9inode,
  158. i_size_read(&v9inode->vfs_inode),
  159. true);
  160. p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n",
  161. inode, old, v9inode->fscache);
  162. mutex_unlock(&v9inode->fscache_lock);
  163. }
  164. int __v9fs_fscache_release_page(struct page *page, gfp_t gfp)
  165. {
  166. struct inode *inode = page->mapping->host;
  167. struct v9fs_inode *v9inode = V9FS_I(inode);
  168. BUG_ON(!v9inode->fscache);
  169. return fscache_maybe_release_page(v9inode->fscache, page, gfp);
  170. }
  171. void __v9fs_fscache_invalidate_page(struct page *page)
  172. {
  173. struct inode *inode = page->mapping->host;
  174. struct v9fs_inode *v9inode = V9FS_I(inode);
  175. BUG_ON(!v9inode->fscache);
  176. if (PageFsCache(page)) {
  177. fscache_wait_on_page_write(v9inode->fscache, page);
  178. BUG_ON(!PageLocked(page));
  179. fscache_uncache_page(v9inode->fscache, page);
  180. }
  181. }
  182. static void v9fs_vfs_readpage_complete(struct page *page, void *data,
  183. int error)
  184. {
  185. if (!error)
  186. SetPageUptodate(page);
  187. unlock_page(page);
  188. }
  189. /**
  190. * __v9fs_readpage_from_fscache - read a page from cache
  191. *
  192. * Returns 0 if the pages are in cache and a BIO is submitted,
  193. * 1 if the pages are not in cache and -error otherwise.
  194. */
  195. int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page)
  196. {
  197. int ret;
  198. const struct v9fs_inode *v9inode = V9FS_I(inode);
  199. p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
  200. if (!v9inode->fscache)
  201. return -ENOBUFS;
  202. ret = fscache_read_or_alloc_page(v9inode->fscache,
  203. page,
  204. v9fs_vfs_readpage_complete,
  205. NULL,
  206. GFP_KERNEL);
  207. switch (ret) {
  208. case -ENOBUFS:
  209. case -ENODATA:
  210. p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d\n", ret);
  211. return 1;
  212. case 0:
  213. p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
  214. return ret;
  215. default:
  216. p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
  217. return ret;
  218. }
  219. }
  220. /**
  221. * __v9fs_readpages_from_fscache - read multiple pages from cache
  222. *
  223. * Returns 0 if the pages are in cache and a BIO is submitted,
  224. * 1 if the pages are not in cache and -error otherwise.
  225. */
  226. int __v9fs_readpages_from_fscache(struct inode *inode,
  227. struct address_space *mapping,
  228. struct list_head *pages,
  229. unsigned *nr_pages)
  230. {
  231. int ret;
  232. const struct v9fs_inode *v9inode = V9FS_I(inode);
  233. p9_debug(P9_DEBUG_FSC, "inode %p pages %u\n", inode, *nr_pages);
  234. if (!v9inode->fscache)
  235. return -ENOBUFS;
  236. ret = fscache_read_or_alloc_pages(v9inode->fscache,
  237. mapping, pages, nr_pages,
  238. v9fs_vfs_readpage_complete,
  239. NULL,
  240. mapping_gfp_mask(mapping));
  241. switch (ret) {
  242. case -ENOBUFS:
  243. case -ENODATA:
  244. p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d\n", ret);
  245. return 1;
  246. case 0:
  247. BUG_ON(!list_empty(pages));
  248. BUG_ON(*nr_pages != 0);
  249. p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
  250. return ret;
  251. default:
  252. p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
  253. return ret;
  254. }
  255. }
  256. /**
  257. * __v9fs_readpage_to_fscache - write a page to the cache
  258. *
  259. */
  260. void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page)
  261. {
  262. int ret;
  263. const struct v9fs_inode *v9inode = V9FS_I(inode);
  264. p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
  265. ret = fscache_write_page(v9inode->fscache, page,
  266. i_size_read(&v9inode->vfs_inode), GFP_KERNEL);
  267. p9_debug(P9_DEBUG_FSC, "ret = %d\n", ret);
  268. if (ret != 0)
  269. v9fs_uncache_page(inode, page);
  270. }
  271. /*
  272. * wait for a page to complete writing to the cache
  273. */
  274. void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
  275. {
  276. const struct v9fs_inode *v9inode = V9FS_I(inode);
  277. p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
  278. if (PageFsCache(page))
  279. fscache_wait_on_page_write(v9inode->fscache, page);
  280. }