cache.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /* AFS caching stuff
  2. *
  3. * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/sched.h>
  12. #include "internal.h"
  13. static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
  14. void *buffer, uint16_t buflen);
  15. static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
  16. void *buffer, uint16_t buflen);
  17. static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
  18. const void *buffer,
  19. uint16_t buflen);
  20. static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
  21. void *buffer, uint16_t buflen);
  22. static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
  23. void *buffer, uint16_t buflen);
  24. static enum fscache_checkaux afs_vlocation_cache_check_aux(
  25. void *cookie_netfs_data, const void *buffer, uint16_t buflen);
  26. static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
  27. void *buffer, uint16_t buflen);
  28. static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
  29. void *buffer, uint16_t buflen);
  30. static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
  31. uint64_t *size);
  32. static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
  33. void *buffer, uint16_t buflen);
  34. static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
  35. const void *buffer,
  36. uint16_t buflen);
  37. struct fscache_netfs afs_cache_netfs = {
  38. .name = "afs",
  39. .version = 0,
  40. };
  41. struct fscache_cookie_def afs_cell_cache_index_def = {
  42. .name = "AFS.cell",
  43. .type = FSCACHE_COOKIE_TYPE_INDEX,
  44. .get_key = afs_cell_cache_get_key,
  45. .get_aux = afs_cell_cache_get_aux,
  46. .check_aux = afs_cell_cache_check_aux,
  47. };
  48. struct fscache_cookie_def afs_vlocation_cache_index_def = {
  49. .name = "AFS.vldb",
  50. .type = FSCACHE_COOKIE_TYPE_INDEX,
  51. .get_key = afs_vlocation_cache_get_key,
  52. .get_aux = afs_vlocation_cache_get_aux,
  53. .check_aux = afs_vlocation_cache_check_aux,
  54. };
  55. struct fscache_cookie_def afs_volume_cache_index_def = {
  56. .name = "AFS.volume",
  57. .type = FSCACHE_COOKIE_TYPE_INDEX,
  58. .get_key = afs_volume_cache_get_key,
  59. };
  60. struct fscache_cookie_def afs_vnode_cache_index_def = {
  61. .name = "AFS.vnode",
  62. .type = FSCACHE_COOKIE_TYPE_DATAFILE,
  63. .get_key = afs_vnode_cache_get_key,
  64. .get_attr = afs_vnode_cache_get_attr,
  65. .get_aux = afs_vnode_cache_get_aux,
  66. .check_aux = afs_vnode_cache_check_aux,
  67. };
  68. /*
  69. * set the key for the index entry
  70. */
  71. static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
  72. void *buffer, uint16_t bufmax)
  73. {
  74. const struct afs_cell *cell = cookie_netfs_data;
  75. uint16_t klen;
  76. _enter("%p,%p,%u", cell, buffer, bufmax);
  77. klen = strlen(cell->name);
  78. if (klen > bufmax)
  79. return 0;
  80. memcpy(buffer, cell->name, klen);
  81. return klen;
  82. }
  83. /*
  84. * provide new auxiliary cache data
  85. */
  86. static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
  87. void *buffer, uint16_t bufmax)
  88. {
  89. const struct afs_cell *cell = cookie_netfs_data;
  90. uint16_t dlen;
  91. _enter("%p,%p,%u", cell, buffer, bufmax);
  92. dlen = cell->vl_naddrs * sizeof(cell->vl_addrs[0]);
  93. dlen = min(dlen, bufmax);
  94. dlen &= ~(sizeof(cell->vl_addrs[0]) - 1);
  95. memcpy(buffer, cell->vl_addrs, dlen);
  96. return dlen;
  97. }
  98. /*
  99. * check that the auxiliary data indicates that the entry is still valid
  100. */
  101. static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
  102. const void *buffer,
  103. uint16_t buflen)
  104. {
  105. _leave(" = OKAY");
  106. return FSCACHE_CHECKAUX_OKAY;
  107. }
  108. /*****************************************************************************/
  109. /*
  110. * set the key for the index entry
  111. */
  112. static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
  113. void *buffer, uint16_t bufmax)
  114. {
  115. const struct afs_vlocation *vlocation = cookie_netfs_data;
  116. uint16_t klen;
  117. _enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
  118. klen = strnlen(vlocation->vldb.name, sizeof(vlocation->vldb.name));
  119. if (klen > bufmax)
  120. return 0;
  121. memcpy(buffer, vlocation->vldb.name, klen);
  122. _leave(" = %u", klen);
  123. return klen;
  124. }
  125. /*
  126. * provide new auxiliary cache data
  127. */
  128. static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
  129. void *buffer, uint16_t bufmax)
  130. {
  131. const struct afs_vlocation *vlocation = cookie_netfs_data;
  132. uint16_t dlen;
  133. _enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
  134. dlen = sizeof(struct afs_cache_vlocation);
  135. dlen -= offsetof(struct afs_cache_vlocation, nservers);
  136. if (dlen > bufmax)
  137. return 0;
  138. memcpy(buffer, (uint8_t *)&vlocation->vldb.nservers, dlen);
  139. _leave(" = %u", dlen);
  140. return dlen;
  141. }
  142. /*
  143. * check that the auxiliary data indicates that the entry is still valid
  144. */
  145. static
  146. enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data,
  147. const void *buffer,
  148. uint16_t buflen)
  149. {
  150. const struct afs_cache_vlocation *cvldb;
  151. struct afs_vlocation *vlocation = cookie_netfs_data;
  152. uint16_t dlen;
  153. _enter("{%s},%p,%u", vlocation->vldb.name, buffer, buflen);
  154. /* check the size of the data is what we're expecting */
  155. dlen = sizeof(struct afs_cache_vlocation);
  156. dlen -= offsetof(struct afs_cache_vlocation, nservers);
  157. if (dlen != buflen)
  158. return FSCACHE_CHECKAUX_OBSOLETE;
  159. cvldb = container_of(buffer, struct afs_cache_vlocation, nservers);
  160. /* if what's on disk is more valid than what's in memory, then use the
  161. * VL record from the cache */
  162. if (!vlocation->valid || vlocation->vldb.rtime == cvldb->rtime) {
  163. memcpy((uint8_t *)&vlocation->vldb.nservers, buffer, dlen);
  164. vlocation->valid = 1;
  165. _leave(" = SUCCESS [c->m]");
  166. return FSCACHE_CHECKAUX_OKAY;
  167. }
  168. /* need to update the cache if the cached info differs */
  169. if (memcmp(&vlocation->vldb, buffer, dlen) != 0) {
  170. /* delete if the volume IDs for this name differ */
  171. if (memcmp(&vlocation->vldb.vid, &cvldb->vid,
  172. sizeof(cvldb->vid)) != 0
  173. ) {
  174. _leave(" = OBSOLETE");
  175. return FSCACHE_CHECKAUX_OBSOLETE;
  176. }
  177. _leave(" = UPDATE");
  178. return FSCACHE_CHECKAUX_NEEDS_UPDATE;
  179. }
  180. _leave(" = OKAY");
  181. return FSCACHE_CHECKAUX_OKAY;
  182. }
  183. /*****************************************************************************/
  184. /*
  185. * set the key for the volume index entry
  186. */
  187. static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
  188. void *buffer, uint16_t bufmax)
  189. {
  190. const struct afs_volume *volume = cookie_netfs_data;
  191. uint16_t klen;
  192. _enter("{%u},%p,%u", volume->type, buffer, bufmax);
  193. klen = sizeof(volume->type);
  194. if (klen > bufmax)
  195. return 0;
  196. memcpy(buffer, &volume->type, sizeof(volume->type));
  197. _leave(" = %u", klen);
  198. return klen;
  199. }
  200. /*****************************************************************************/
  201. /*
  202. * set the key for the index entry
  203. */
  204. static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
  205. void *buffer, uint16_t bufmax)
  206. {
  207. const struct afs_vnode *vnode = cookie_netfs_data;
  208. uint16_t klen;
  209. _enter("{%x,%x,%llx},%p,%u",
  210. vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
  211. buffer, bufmax);
  212. klen = sizeof(vnode->fid.vnode);
  213. if (klen > bufmax)
  214. return 0;
  215. memcpy(buffer, &vnode->fid.vnode, sizeof(vnode->fid.vnode));
  216. _leave(" = %u", klen);
  217. return klen;
  218. }
  219. /*
  220. * provide updated file attributes
  221. */
  222. static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
  223. uint64_t *size)
  224. {
  225. const struct afs_vnode *vnode = cookie_netfs_data;
  226. _enter("{%x,%x,%llx},",
  227. vnode->fid.vnode, vnode->fid.unique,
  228. vnode->status.data_version);
  229. *size = vnode->status.size;
  230. }
  231. /*
  232. * provide new auxiliary cache data
  233. */
  234. static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
  235. void *buffer, uint16_t bufmax)
  236. {
  237. const struct afs_vnode *vnode = cookie_netfs_data;
  238. uint16_t dlen;
  239. _enter("{%x,%x,%Lx},%p,%u",
  240. vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
  241. buffer, bufmax);
  242. dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
  243. if (dlen > bufmax)
  244. return 0;
  245. memcpy(buffer, &vnode->fid.unique, sizeof(vnode->fid.unique));
  246. buffer += sizeof(vnode->fid.unique);
  247. memcpy(buffer, &vnode->status.data_version,
  248. sizeof(vnode->status.data_version));
  249. _leave(" = %u", dlen);
  250. return dlen;
  251. }
  252. /*
  253. * check that the auxiliary data indicates that the entry is still valid
  254. */
  255. static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
  256. const void *buffer,
  257. uint16_t buflen)
  258. {
  259. struct afs_vnode *vnode = cookie_netfs_data;
  260. uint16_t dlen;
  261. _enter("{%x,%x,%llx},%p,%u",
  262. vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
  263. buffer, buflen);
  264. /* check the size of the data is what we're expecting */
  265. dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
  266. if (dlen != buflen) {
  267. _leave(" = OBSOLETE [len %hx != %hx]", dlen, buflen);
  268. return FSCACHE_CHECKAUX_OBSOLETE;
  269. }
  270. if (memcmp(buffer,
  271. &vnode->fid.unique,
  272. sizeof(vnode->fid.unique)
  273. ) != 0) {
  274. unsigned unique;
  275. memcpy(&unique, buffer, sizeof(unique));
  276. _leave(" = OBSOLETE [uniq %x != %x]",
  277. unique, vnode->fid.unique);
  278. return FSCACHE_CHECKAUX_OBSOLETE;
  279. }
  280. if (memcmp(buffer + sizeof(vnode->fid.unique),
  281. &vnode->status.data_version,
  282. sizeof(vnode->status.data_version)
  283. ) != 0) {
  284. afs_dataversion_t version;
  285. memcpy(&version, buffer + sizeof(vnode->fid.unique),
  286. sizeof(version));
  287. _leave(" = OBSOLETE [vers %llx != %llx]",
  288. version, vnode->status.data_version);
  289. return FSCACHE_CHECKAUX_OBSOLETE;
  290. }
  291. _leave(" = SUCCESS");
  292. return FSCACHE_CHECKAUX_OKAY;
  293. }