Commit a70f6526 authored by David Howells's avatar David Howells

cachefiles: Add some error injection support

Add support for injecting ENOSPC or EIO errors.  This needs to be enabled
by CONFIG_CACHEFILES_ERROR_INJECTION=y.  Once enabled, ENOSPC on things
like write and mkdir can be triggered by:

        echo 1 >/proc/sys/cachefiles/error_injection

and EIO can be triggered on most operations by:

        echo 2 >/proc/sys/cachefiles/error_injection
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/163819624706.215744.6911916249119962943.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906925343.143852.5465695512984025812.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967134412.1823006.7354285948280296595.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021532340.640689.18209494225772443698.stgit@warthog.procyon.org.uk/ # v4
parent 8390fbc4
...@@ -19,3 +19,10 @@ config CACHEFILES_DEBUG ...@@ -19,3 +19,10 @@ config CACHEFILES_DEBUG
caching on files module. If this is set, the debugging output may be caching on files module. If this is set, the debugging output may be
enabled by setting bits in /sys/modules/cachefiles/parameter/debug or enabled by setting bits in /sys/modules/cachefiles/parameter/debug or
by including a debugging specifier in /etc/cachefilesd.conf. by including a debugging specifier in /etc/cachefilesd.conf.
config CACHEFILES_ERROR_INJECTION
bool "Provide error injection for cachefiles"
depends on CACHEFILES && SYSCTL
help
This permits error injection to be enabled in cachefiles whilst a
cache is in service.
...@@ -6,4 +6,6 @@ ...@@ -6,4 +6,6 @@
cachefiles-y := \ cachefiles-y := \
main.o main.o
cachefiles-$(CONFIG_CACHEFILES_ERROR_INJECTION) += error_inject.o
obj-$(CONFIG_CACHEFILES) := cachefiles.o obj-$(CONFIG_CACHEFILES) := cachefiles.o
// SPDX-License-Identifier: GPL-2.0-or-later
/* Error injection handling.
*
* Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#include <linux/sysctl.h>
#include "internal.h"
unsigned int cachefiles_error_injection_state;
static struct ctl_table_header *cachefiles_sysctl;
static struct ctl_table cachefiles_sysctls[] = {
{
.procname = "error_injection",
.data = &cachefiles_error_injection_state,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_douintvec,
},
{}
};
static struct ctl_table cachefiles_sysctls_root[] = {
{
.procname = "cachefiles",
.mode = 0555,
.child = cachefiles_sysctls,
},
{}
};
int __init cachefiles_register_error_injection(void)
{
cachefiles_sysctl = register_sysctl_table(cachefiles_sysctls_root);
if (!cachefiles_sysctl)
return -ENOMEM;
return 0;
}
void cachefiles_unregister_error_injection(void)
{
unregister_sysctl_table(cachefiles_sysctl);
}
...@@ -64,7 +64,47 @@ struct cachefiles_cache { ...@@ -64,7 +64,47 @@ struct cachefiles_cache {
/* /*
* Debug tracing. * error_inject.c
*/
#ifdef CONFIG_CACHEFILES_ERROR_INJECTION
extern unsigned int cachefiles_error_injection_state;
extern int cachefiles_register_error_injection(void);
extern void cachefiles_unregister_error_injection(void);
#else
#define cachefiles_error_injection_state 0
static inline int cachefiles_register_error_injection(void)
{
return 0;
}
static inline void cachefiles_unregister_error_injection(void)
{
}
#endif
static inline int cachefiles_inject_read_error(void)
{
return cachefiles_error_injection_state & 2 ? -EIO : 0;
}
static inline int cachefiles_inject_write_error(void)
{
return cachefiles_error_injection_state & 2 ? -EIO :
cachefiles_error_injection_state & 1 ? -ENOSPC :
0;
}
static inline int cachefiles_inject_remove_error(void)
{
return cachefiles_error_injection_state & 2 ? -EIO : 0;
}
/*
* Debug tracing
*/ */
extern unsigned cachefiles_debug; extern unsigned cachefiles_debug;
#define CACHEFILES_DEBUG_KENTER 1 #define CACHEFILES_DEBUG_KENTER 1
......
...@@ -36,8 +36,18 @@ MODULE_LICENSE("GPL"); ...@@ -36,8 +36,18 @@ MODULE_LICENSE("GPL");
*/ */
static int __init cachefiles_init(void) static int __init cachefiles_init(void)
{ {
int ret;
ret = cachefiles_register_error_injection();
if (ret < 0)
goto error_einj;
pr_info("Loaded\n"); pr_info("Loaded\n");
return 0; return 0;
error_einj:
pr_err("failed to register: %d\n", ret);
return ret;
} }
fs_initcall(cachefiles_init); fs_initcall(cachefiles_init);
...@@ -48,6 +58,8 @@ fs_initcall(cachefiles_init); ...@@ -48,6 +58,8 @@ fs_initcall(cachefiles_init);
static void __exit cachefiles_exit(void) static void __exit cachefiles_exit(void)
{ {
pr_info("Unloading\n"); pr_info("Unloading\n");
cachefiles_unregister_error_injection();
} }
module_exit(cachefiles_exit); module_exit(cachefiles_exit);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment