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