main.c 2.8 KB

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