Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: Cache deferral injection

Cache deferral injection stress-tests the cache deferral logic as
well as upper layer protocol deferred request handlers. This
facility is for developers and professional testers to ensure
coverage of the rqst deferral code paths. To date, we haven't
had an adequate way to ensure these code paths are covered
during testing, short of temporary code changes to force their
use.

A file called /sys/kernel/debug/fail_sunrpc/ignore-cache-wait
enables administrators to disable cache deferral injection while
allowing other types of sunrpc errors to be injected. The default
setting is that cache deferral injection is enabled (ignore=false).

To enable support for cache deferral injection,
CONFIG_FAULT_INJECTION, CONFIG_FAULT_INJECTION_DEBUG_FS, and
CONFIG_SUNRPC_DEBUG must all be set to "Y".

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+21 -2
+17 -1
net/sunrpc/cache.c
··· 33 33 #include <linux/sunrpc/stats.h> 34 34 #include <linux/sunrpc/rpc_pipe_fs.h> 35 35 #include <trace/events/sunrpc.h> 36 + 36 37 #include "netns.h" 38 + #include "fail.h" 37 39 38 40 #define RPCDBG_FACILITY RPCDBG_CACHE 39 41 ··· 690 688 discard->revisit(discard, 1); 691 689 } 692 690 691 + #if IS_ENABLED(CONFIG_FAIL_SUNRPC) 692 + static inline bool cache_defer_immediately(void) 693 + { 694 + return !fail_sunrpc.ignore_cache_wait && 695 + should_fail(&fail_sunrpc.attr, 1); 696 + } 697 + #else 698 + static inline bool cache_defer_immediately(void) 699 + { 700 + return false; 701 + } 702 + #endif 703 + 693 704 /* Return true if and only if a deferred request is queued. */ 694 705 static bool cache_defer_req(struct cache_req *req, struct cache_head *item) 695 706 { 696 707 struct cache_deferred_req *dreq; 697 708 698 - if (req->thread_wait) { 709 + if (!cache_defer_immediately()) { 699 710 cache_wait_req(req, item); 700 711 if (!test_bit(CACHE_PENDING, &item->flags)) 701 712 return false; 702 713 } 714 + 703 715 dreq = req->defer(req); 704 716 if (dreq == NULL) 705 717 return false;
+3
net/sunrpc/debugfs.c
··· 262 262 263 263 debugfs_create_bool("ignore-server-disconnect", S_IFREG | 0600, dir, 264 264 &fail_sunrpc.ignore_server_disconnect); 265 + 266 + debugfs_create_bool("ignore-cache-wait", S_IFREG | 0600, dir, 267 + &fail_sunrpc.ignore_cache_wait); 265 268 } 266 269 #else 267 270 static void fail_sunrpc_init(void)
+1 -1
net/sunrpc/fail.h
··· 14 14 struct fault_attr attr; 15 15 16 16 bool ignore_client_disconnect; 17 - 18 17 bool ignore_server_disconnect; 18 + bool ignore_cache_wait; 19 19 }; 20 20 21 21 extern struct fail_sunrpc_attr fail_sunrpc;