Split the fscache initialisation so that /proc/fs/fscache/stats is always created, if FSCACHE_STATS=y, thereby allowing it to be used if the read helper is enabled, but not the rest of the caching infrastructure. Signed-off-by: David Howells <dhowells@xxxxxxxxxx> --- fs/fscache/Makefile | 3 + fs/fscache/cache_init.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++ fs/fscache/internal.h | 12 +++- fs/fscache/main.c | 115 ++++----------------------------------- fs/fscache/proc.c | 52 +----------------- fs/fscache/stats.c | 8 +++ 6 files changed, 174 insertions(+), 155 deletions(-) create mode 100644 fs/fscache/cache_init.c diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile index 3caf66810e7b..5d3284f6fe2d 100644 --- a/fs/fscache/Makefile +++ b/fs/fscache/Makefile @@ -5,6 +5,7 @@ fscache-y := \ cache.o \ + cache_init.o \ cookie.o \ dispatcher.o \ fsdef.o \ @@ -15,8 +16,8 @@ fscache-y := \ object_bits.o fscache-$(CONFIG_PROC_FS) += proc.o -fscache-$(CONFIG_FSCACHE_STATS) += stats.o fscache-$(CONFIG_FSCACHE_HISTOGRAM) += histogram.o fscache-$(CONFIG_FSCACHE_OBJECT_LIST) += object-list.o +fscache-$(CONFIG_FSCACHE_STATS) += stats.o obj-$(CONFIG_FSCACHE) := fscache.o diff --git a/fs/fscache/cache_init.c b/fs/fscache/cache_init.c new file mode 100644 index 000000000000..8cade2e00050 --- /dev/null +++ b/fs/fscache/cache_init.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* General filesystem local caching manager + * + * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@xxxxxxxxxx) + */ + +#define FSCACHE_DEBUG_LEVEL CACHE +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/completion.h> +#include <linux/slab.h> +#include <linux/seq_file.h> +#define CREATE_TRACE_POINTS +#include "internal.h" + +struct kobject *fscache_root; +struct workqueue_struct *fscache_op_wq; + +/* these values serve as lower bounds, will be adjusted in fscache_init() */ +static unsigned fscache_object_max_active = 4; +static unsigned fscache_op_max_active = 2; + +#ifdef CONFIG_SYSCTL +static struct ctl_table_header *fscache_sysctl_header; + +static int fscache_max_active_sysctl(struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + struct workqueue_struct **wqp = table->extra1; + unsigned int *datap = table->data; + int ret; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + if (ret == 0) + workqueue_set_max_active(*wqp, *datap); + return ret; +} + +static struct ctl_table fscache_sysctls[] = { + { + .procname = "operation_max_active", + .data = &fscache_op_max_active, + .maxlen = sizeof(unsigned), + .mode = 0644, + .proc_handler = fscache_max_active_sysctl, + .extra1 = &fscache_op_wq, + }, + {} +}; + +static struct ctl_table fscache_sysctls_root[] = { + { + .procname = "fscache", + .mode = 0555, + .child = fscache_sysctls, + }, + {} +}; +#endif + +/* + * Initialise the caching code. + */ +int __init fscache_init_caching(void) +{ + int ret; + + fscache_op_max_active = + clamp_val(fscache_object_max_active / 2, + fscache_op_max_active, WQ_UNBOUND_MAX_ACTIVE); + + ret = -ENOMEM; + fscache_op_wq = alloc_workqueue("fscache_operation", WQ_UNBOUND, + fscache_op_max_active); + if (!fscache_op_wq) + goto error_op_wq; + + ret = fscache_init_dispatchers(); + if (ret < 0) + goto error_dispatchers; + + ret = fscache_proc_caching_init(); + if (ret < 0) + goto error_proc; + +#ifdef CONFIG_SYSCTL + ret = -ENOMEM; + fscache_sysctl_header = register_sysctl_table(fscache_sysctls_root); + if (!fscache_sysctl_header) + goto error_sysctl; +#endif + + fscache_cookie_jar = kmem_cache_create("fscache_cookie_jar", + sizeof(struct fscache_cookie), + 0, 0, NULL); + if (!fscache_cookie_jar) { + pr_notice("Failed to allocate a cookie jar\n"); + ret = -ENOMEM; + goto error_cookie_jar; + } + + fscache_root = kobject_create_and_add("fscache", kernel_kobj); + if (!fscache_root) + goto error_kobj; + + return 0; + +error_kobj: + kmem_cache_destroy(fscache_cookie_jar); +error_cookie_jar: +#ifdef CONFIG_SYSCTL + unregister_sysctl_table(fscache_sysctl_header); +error_sysctl: +#endif + fscache_kill_dispatchers(); +error_dispatchers: +error_proc: + destroy_workqueue(fscache_op_wq); +error_op_wq: + return ret; +} + +/* + * clean up on module removal + */ +void __exit fscache_exit_caching(void) +{ + _enter(""); + + kobject_put(fscache_root); + kmem_cache_destroy(fscache_cookie_jar); +#ifdef CONFIG_SYSCTL + unregister_sysctl_table(fscache_sysctl_header); +#endif + fscache_kill_dispatchers(); + destroy_workqueue(fscache_op_wq); +} diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index ae05f636faac..1721823b8cac 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -56,6 +56,12 @@ static inline void fscache_put_cache_tag(struct fscache_cache_tag *tag) kfree(tag); } +/* + * cache_init.c + */ +extern int __init fscache_init_caching(void); +extern void __exit fscache_exit_caching(void); + /* * cookie.c */ @@ -164,11 +170,9 @@ extern void fscache_objlist_remove(struct fscache_object *); * proc.c */ #ifdef CONFIG_PROC_FS -extern int __init fscache_proc_init(void); -extern void fscache_proc_cleanup(void); +extern int __init fscache_proc_caching_init(void); #else #define fscache_proc_init() (0) -#define fscache_proc_cleanup() do {} while (0) #endif /* @@ -230,11 +234,13 @@ static inline void fscache_stat_d(atomic_t *stat) #define __fscache_stat(stat) (stat) int fscache_stats_show(struct seq_file *m, void *v); +extern int __init fscache_proc_stats_init(void); #else #define __fscache_stat(stat) (NULL) #define fscache_stat(stat) do {} while (0) #define fscache_stat_d(stat) do {} while (0) +#define fscache_proc_stats_init(void) 0 #endif static inline diff --git a/fs/fscache/main.c b/fs/fscache/main.c index 003e53d17245..9bdcd9557aa6 100644 --- a/fs/fscache/main.c +++ b/fs/fscache/main.c @@ -11,8 +11,7 @@ #include <linux/sched.h> #include <linux/completion.h> #include <linux/slab.h> -#include <linux/seq_file.h> -#define CREATE_TRACE_POINTS +#include <linux/proc_fs.h> #include "internal.h" MODULE_DESCRIPTION("FS Cache Manager"); @@ -25,115 +24,31 @@ module_param_named(debug, fscache_debug, uint, MODULE_PARM_DESC(fscache_debug, "FS-Cache debugging mask"); -struct kobject *fscache_root; -struct workqueue_struct *fscache_op_wq; - -/* these values serve as lower bounds, will be adjusted in fscache_init() */ -static unsigned fscache_object_max_active = 4; -static unsigned fscache_op_max_active = 2; - -#ifdef CONFIG_SYSCTL -static struct ctl_table_header *fscache_sysctl_header; - -static int fscache_max_active_sysctl(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct workqueue_struct **wqp = table->extra1; - unsigned int *datap = table->data; - int ret; - - ret = proc_dointvec(table, write, buffer, lenp, ppos); - if (ret == 0) - workqueue_set_max_active(*wqp, *datap); - return ret; -} - -static struct ctl_table fscache_sysctls[] = { - { - .procname = "operation_max_active", - .data = &fscache_op_max_active, - .maxlen = sizeof(unsigned), - .mode = 0644, - .proc_handler = fscache_max_active_sysctl, - .extra1 = &fscache_op_wq, - }, - {} -}; - -static struct ctl_table fscache_sysctls_root[] = { - { - .procname = "fscache", - .mode = 0555, - .child = fscache_sysctls, - }, - {} -}; -#endif - /* - * initialise the fs caching module + * Initialise the module */ static int __init fscache_init(void) { int ret; - fscache_op_max_active = - clamp_val(fscache_object_max_active / 2, - fscache_op_max_active, WQ_UNBOUND_MAX_ACTIVE); - - ret = -ENOMEM; - fscache_op_wq = alloc_workqueue("fscache_operation", WQ_UNBOUND, - fscache_op_max_active); - if (!fscache_op_wq) - goto error_op_wq; + if (!proc_mkdir("fs/fscache", NULL)) + return -ENOMEM; - ret = fscache_init_dispatchers(); + ret = fscache_proc_stats_init(); if (ret < 0) - goto error_dispatchers; + goto error; - ret = fscache_proc_init(); + ret = fscache_init_caching(); if (ret < 0) - goto error_proc; - -#ifdef CONFIG_SYSCTL - ret = -ENOMEM; - fscache_sysctl_header = register_sysctl_table(fscache_sysctls_root); - if (!fscache_sysctl_header) - goto error_sysctl; -#endif - - fscache_cookie_jar = kmem_cache_create("fscache_cookie_jar", - sizeof(struct fscache_cookie), - 0, 0, NULL); - if (!fscache_cookie_jar) { - pr_notice("Failed to allocate a cookie jar\n"); - ret = -ENOMEM; - goto error_cookie_jar; - } - - fscache_root = kobject_create_and_add("fscache", kernel_kobj); - if (!fscache_root) - goto error_kobj; + goto error; pr_notice("Loaded\n"); return 0; -error_kobj: - kmem_cache_destroy(fscache_cookie_jar); -error_cookie_jar: -#ifdef CONFIG_SYSCTL - unregister_sysctl_table(fscache_sysctl_header); -error_sysctl: -#endif - fscache_kill_dispatchers(); -error_dispatchers: - fscache_proc_cleanup(); -error_proc: - destroy_workqueue(fscache_op_wq); -error_op_wq: +error: + remove_proc_subtree("fs/fscache", NULL); return ret; } - fs_initcall(fscache_init); /* @@ -143,14 +58,8 @@ static void __exit fscache_exit(void) { _enter(""); - kobject_put(fscache_root); - kmem_cache_destroy(fscache_cookie_jar); -#ifdef CONFIG_SYSCTL - unregister_sysctl_table(fscache_sysctl_header); -#endif - fscache_proc_cleanup(); - fscache_kill_dispatchers(); - destroy_workqueue(fscache_op_wq); + remove_proc_subtree("fs/fscache", NULL); + fscache_exit_caching(); pr_notice("Unloaded\n"); } diff --git a/fs/fscache/proc.c b/fs/fscache/proc.c index 729d083f1e91..7e156b21bb1d 100644 --- a/fs/fscache/proc.c +++ b/fs/fscache/proc.c @@ -14,67 +14,23 @@ /* * initialise the /proc/fs/fscache/ directory */ -int __init fscache_proc_init(void) +int __init fscache_proc_caching_init(void) { - if (!proc_mkdir("fs/fscache", NULL)) - goto error_dir; - if (!proc_create_seq("fs/fscache/cookies", S_IFREG | 0444, NULL, &fscache_cookies_seq_ops)) - goto error_cookies; - -#ifdef CONFIG_FSCACHE_STATS - if (!proc_create_single("fs/fscache/stats", S_IFREG | 0444, NULL, - fscache_stats_show)) - goto error_stats; -#endif + return -ENOMEM; #ifdef CONFIG_FSCACHE_HISTOGRAM if (!proc_create_seq("fs/fscache/histogram", S_IFREG | 0444, NULL, &fscache_histogram_ops)) - goto error_histogram; + return -ENOMEM; #endif #ifdef CONFIG_FSCACHE_OBJECT_LIST if (!proc_create("fs/fscache/objects", S_IFREG | 0444, NULL, &fscache_objlist_proc_ops)) - goto error_objects; + return -ENOMEM; #endif return 0; - -#ifdef CONFIG_FSCACHE_OBJECT_LIST -error_objects: -#endif -#ifdef CONFIG_FSCACHE_HISTOGRAM - remove_proc_entry("fs/fscache/histogram", NULL); -error_histogram: -#endif -#ifdef CONFIG_FSCACHE_STATS - remove_proc_entry("fs/fscache/stats", NULL); -error_stats: -#endif - remove_proc_entry("fs/fscache/cookies", NULL); -error_cookies: - remove_proc_entry("fs/fscache", NULL); -error_dir: - return -ENOMEM; -} - -/* - * clean up the /proc/fs/fscache/ directory - */ -void fscache_proc_cleanup(void) -{ -#ifdef CONFIG_FSCACHE_OBJECT_LIST - remove_proc_entry("fs/fscache/objects", NULL); -#endif -#ifdef CONFIG_FSCACHE_HISTOGRAM - remove_proc_entry("fs/fscache/histogram", NULL); -#endif -#ifdef CONFIG_FSCACHE_STATS - remove_proc_entry("fs/fscache/stats", NULL); -#endif - remove_proc_entry("fs/fscache/cookies", NULL); - remove_proc_entry("fs/fscache", NULL); } diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c index dffe6925aadb..bf2935571de5 100644 --- a/fs/fscache/stats.c +++ b/fs/fscache/stats.c @@ -115,3 +115,11 @@ int fscache_stats_show(struct seq_file *m, void *v) atomic_read(&fscache_n_cache_culled_objects)); return 0; } + +int __init fscache_proc_stats_init(void) +{ + if (!proc_create_single("fs/fscache/stats", S_IFREG | 0444, NULL, + fscache_stats_show)) + return -ENOMEM; + return 0; +}