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