| 1 | |
| 2 | |
| 3 | *
|
| 4 | * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
|
| 5 | * Written by David Howells ([email protected])
|
| 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 |
|
| 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 | }
|