fscache_main.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* General filesystem local caching manager
  3. *
  4. * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #define FSCACHE_DEBUG_LEVEL CACHE
  8. #include <linux/module.h>
  9. #include <linux/init.h>
  10. #include "internal.h"
  11. #define CREATE_TRACE_POINTS
  12. #include <trace/events/fscache.h>
  13. EXPORT_TRACEPOINT_SYMBOL(fscache_access_cache);
  14. EXPORT_TRACEPOINT_SYMBOL(fscache_access_volume);
  15. EXPORT_TRACEPOINT_SYMBOL(fscache_access);
  16. struct workqueue_struct *fscache_wq;
  17. EXPORT_SYMBOL(fscache_wq);
  18. /*
  19. * Mixing scores (in bits) for (7,20):
  20. * Input delta: 1-bit 2-bit
  21. * 1 round: 330.3 9201.6
  22. * 2 rounds: 1246.4 25475.4
  23. * 3 rounds: 1907.1 31295.1
  24. * 4 rounds: 2042.3 31718.6
  25. * Perfect: 2048 31744
  26. * (32*64) (32*31/2 * 64)
  27. */
  28. #define HASH_MIX(x, y, a) \
  29. ( x ^= (a), \
  30. y ^= x, x = rol32(x, 7),\
  31. x += y, y = rol32(y,20),\
  32. y *= 9 )
  33. static inline unsigned int fold_hash(unsigned long x, unsigned long y)
  34. {
  35. /* Use arch-optimized multiply if one exists */
  36. return __hash_32(y ^ __hash_32(x));
  37. }
  38. /*
  39. * Generate a hash. This is derived from full_name_hash(), but we want to be
  40. * sure it is arch independent and that it doesn't change as bits of the
  41. * computed hash value might appear on disk. The caller must guarantee that
  42. * the source data is a multiple of four bytes in size.
  43. */
  44. unsigned int fscache_hash(unsigned int salt, const void *data, size_t len)
  45. {
  46. const __le32 *p = data;
  47. unsigned int a, x = 0, y = salt, n = len / sizeof(__le32);
  48. for (; n; n--) {
  49. a = le32_to_cpu(*p++);
  50. HASH_MIX(x, y, a);
  51. }
  52. return fold_hash(x, y);
  53. }
  54. /*
  55. * initialise the fs caching module
  56. */
  57. int __init fscache_init(void)
  58. {
  59. int ret = -ENOMEM;
  60. fscache_wq = alloc_workqueue("fscache", WQ_UNBOUND | WQ_FREEZABLE, 0);
  61. if (!fscache_wq)
  62. goto error_wq;
  63. ret = fscache_proc_init();
  64. if (ret < 0)
  65. goto error_proc;
  66. fscache_cookie_jar = kmem_cache_create("fscache_cookie_jar",
  67. sizeof(struct fscache_cookie),
  68. 0, 0, NULL);
  69. if (!fscache_cookie_jar) {
  70. pr_notice("Failed to allocate a cookie jar\n");
  71. ret = -ENOMEM;
  72. goto error_cookie_jar;
  73. }
  74. pr_notice("FS-Cache loaded\n");
  75. return 0;
  76. error_cookie_jar:
  77. fscache_proc_cleanup();
  78. error_proc:
  79. destroy_workqueue(fscache_wq);
  80. error_wq:
  81. return ret;
  82. }
  83. /*
  84. * clean up on module removal
  85. */
  86. void __exit fscache_exit(void)
  87. {
  88. _enter("");
  89. kmem_cache_destroy(fscache_cookie_jar);
  90. fscache_proc_cleanup();
  91. timer_shutdown_sync(&fscache_cookie_lru_timer);
  92. destroy_workqueue(fscache_wq);
  93. pr_notice("FS-Cache unloaded\n");
  94. }