Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* General filesystem local caching manager
0003  *
0004  * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #define FSCACHE_DEBUG_LEVEL CACHE
0009 #include <linux/module.h>
0010 #include <linux/init.h>
0011 #define CREATE_TRACE_POINTS
0012 #include "internal.h"
0013 
0014 MODULE_DESCRIPTION("FS Cache Manager");
0015 MODULE_AUTHOR("Red Hat, Inc.");
0016 MODULE_LICENSE("GPL");
0017 
0018 unsigned fscache_debug;
0019 module_param_named(debug, fscache_debug, uint,
0020            S_IWUSR | S_IRUGO);
0021 MODULE_PARM_DESC(fscache_debug,
0022          "FS-Cache debugging mask");
0023 
0024 EXPORT_TRACEPOINT_SYMBOL(fscache_access_cache);
0025 EXPORT_TRACEPOINT_SYMBOL(fscache_access_volume);
0026 EXPORT_TRACEPOINT_SYMBOL(fscache_access);
0027 
0028 struct workqueue_struct *fscache_wq;
0029 EXPORT_SYMBOL(fscache_wq);
0030 
0031 /*
0032  * Mixing scores (in bits) for (7,20):
0033  * Input delta: 1-bit      2-bit
0034  * 1 round:     330.3     9201.6
0035  * 2 rounds:   1246.4    25475.4
0036  * 3 rounds:   1907.1    31295.1
0037  * 4 rounds:   2042.3    31718.6
0038  * Perfect:    2048      31744
0039  *            (32*64)   (32*31/2 * 64)
0040  */
0041 #define HASH_MIX(x, y, a)   \
0042     (   x ^= (a),   \
0043     y ^= x, x = rol32(x, 7),\
0044     x += y, y = rol32(y,20),\
0045     y *= 9          )
0046 
0047 static inline unsigned int fold_hash(unsigned long x, unsigned long y)
0048 {
0049     /* Use arch-optimized multiply if one exists */
0050     return __hash_32(y ^ __hash_32(x));
0051 }
0052 
0053 /*
0054  * Generate a hash.  This is derived from full_name_hash(), but we want to be
0055  * sure it is arch independent and that it doesn't change as bits of the
0056  * computed hash value might appear on disk.  The caller must guarantee that
0057  * the source data is a multiple of four bytes in size.
0058  */
0059 unsigned int fscache_hash(unsigned int salt, const void *data, size_t len)
0060 {
0061     const __le32 *p = data;
0062     unsigned int a, x = 0, y = salt, n = len / sizeof(__le32);
0063 
0064     for (; n; n--) {
0065         a = le32_to_cpu(*p++);
0066         HASH_MIX(x, y, a);
0067     }
0068     return fold_hash(x, y);
0069 }
0070 
0071 /*
0072  * initialise the fs caching module
0073  */
0074 static int __init fscache_init(void)
0075 {
0076     int ret = -ENOMEM;
0077 
0078     fscache_wq = alloc_workqueue("fscache", WQ_UNBOUND | WQ_FREEZABLE, 0);
0079     if (!fscache_wq)
0080         goto error_wq;
0081 
0082     ret = fscache_proc_init();
0083     if (ret < 0)
0084         goto error_proc;
0085 
0086     fscache_cookie_jar = kmem_cache_create("fscache_cookie_jar",
0087                            sizeof(struct fscache_cookie),
0088                            0, 0, NULL);
0089     if (!fscache_cookie_jar) {
0090         pr_notice("Failed to allocate a cookie jar\n");
0091         ret = -ENOMEM;
0092         goto error_cookie_jar;
0093     }
0094 
0095     pr_notice("Loaded\n");
0096     return 0;
0097 
0098 error_cookie_jar:
0099     fscache_proc_cleanup();
0100 error_proc:
0101     destroy_workqueue(fscache_wq);
0102 error_wq:
0103     return ret;
0104 }
0105 
0106 fs_initcall(fscache_init);
0107 
0108 /*
0109  * clean up on module removal
0110  */
0111 static void __exit fscache_exit(void)
0112 {
0113     _enter("");
0114 
0115     kmem_cache_destroy(fscache_cookie_jar);
0116     fscache_proc_cleanup();
0117     destroy_workqueue(fscache_wq);
0118     pr_notice("Unloaded\n");
0119 }
0120 
0121 module_exit(fscache_exit);