Commit 24717cfb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'nfsd-5.10' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields:
 "The one new feature this time, from Anna Schumaker, is READ_PLUS,
  which has the same arguments as READ but allows the server to return
  an array of data and hole extents.

  Otherwise it's a lot of cleanup and bugfixes"

* tag 'nfsd-5.10' of git://linux-nfs.org/~bfields/linux: (43 commits)
  NFSv4.2: Fix NFS4ERR_STALE error when doing inter server copy
  SUNRPC: fix copying of multiple pages in gss_read_proxy_verf()
  sunrpc: raise kernel RPC channel buffer size
  svcrdma: fix bounce buffers for unaligned offsets and multiple pages
  nfsd: remove unneeded break
  net/sunrpc: Fix return value for sysctl sunrpc.transports
  NFSD: Encode a full READ_PLUS reply
  NFSD: Return both a hole and a data segment
  NFSD: Add READ_PLUS hole segment encoding
  NFSD: Add READ_PLUS data support
  NFSD: Hoist status code encoding into XDR encoder functions
  NFSD: Map nfserr_wrongsec outside of nfsd_dispatch
  NFSD: Remove the RETURN_STATUS() macro
  NFSD: Call NFSv2 encoders on error returns
  NFSD: Fix .pc_release method for NFSv2
  NFSD: Remove vestigial typedefs
  NFSD: Refactor nfsd_dispatch() error paths
  NFSD: Clean up nfsd_dispatch() variables
  NFSD: Clean up stale comments in nfsd_dispatch()
  NFSD: Clean up switch statement in nfsd_dispatch()
  ...
parents 9b06f57b 0cfcd405
Loading
Loading
Loading
Loading
+0 −70
Original line number Diff line number Diff line
===================
NFS Fault Injection
===================

Fault injection is a method for forcing errors that may not normally occur, or
may be difficult to reproduce.  Forcing these errors in a controlled environment
can help the developer find and fix bugs before their code is shipped in a
production system.  Injecting an error on the Linux NFS server will allow us to
observe how the client reacts and if it manages to recover its state correctly.

NFSD_FAULT_INJECTION must be selected when configuring the kernel to use this
feature.


Using Fault Injection
=====================
On the client, mount the fault injection server through NFS v4.0+ and do some
work over NFS (open files, take locks, ...).

On the server, mount the debugfs filesystem to <debug_dir> and ls
<debug_dir>/nfsd.  This will show a list of files that will be used for
injecting faults on the NFS server.  As root, write a number n to the file
corresponding to the action you want the server to take.  The server will then
process the first n items it finds.  So if you want to forget 5 locks, echo '5'
to <debug_dir>/nfsd/forget_locks.  A value of 0 will tell the server to forget
all corresponding items.  A log message will be created containing the number
of items forgotten (check dmesg).

Go back to work on the client and check if the client recovered from the error
correctly.


Available Faults
================
forget_clients:
     The NFS server keeps a list of clients that have placed a mount call.  If
     this list is cleared, the server will have no knowledge of who the client
     is, forcing the client to reauthenticate with the server.

forget_openowners:
     The NFS server keeps a list of what files are currently opened and who
     they were opened by.  Clearing this list will force the client to reopen
     its files.

forget_locks:
     The NFS server keeps a list of what files are currently locked in the VFS.
     Clearing this list will force the client to reclaim its locks (files are
     unlocked through the VFS as they are cleared from this list).

forget_delegations:
     A delegation is used to assure the client that a file, or part of a file,
     has not changed since the delegation was awarded.  Clearing this list will
     force the client to reacquire its delegation before accessing the file
     again.

recall_delegations:
     Delegations can be recalled by the server when another client attempts to
     access a file.  This test will notify the client that its delegation has
     been revoked, forcing the client to reacquire the delegation before using
     the file again.


tools/nfs/inject_faults.sh script
=================================
This script has been created to ease the fault injection process.  This script
will detect the mounted debugfs directory and write to the files located there
based on the arguments passed by the user.  For example, running
`inject_faults.sh forget_locks 1` as root will instruct the server to forget
one lock.  Running `inject_faults forget_locks` will instruct the server to
forgetall locks.
+0 −1
Original line number Diff line number Diff line
@@ -12,4 +12,3 @@ NFS
    nfs-idmapper
    pnfs-block-server
    pnfs-scsi-server
    fault_injection
+2 −3
Original line number Diff line number Diff line
@@ -13,10 +13,9 @@ RPCGSS is specified in a few IETF documents:
 - RFC2203 v1: https://tools.ietf.org/rfc/rfc2203.txt
 - RFC5403 v2: https://tools.ietf.org/rfc/rfc5403.txt

and there is a 3rd version  being proposed:
There is a third version that we don't currently implement:

 - https://tools.ietf.org/id/draft-williams-rpcsecgssv3.txt
   (At draft n. 02 at the time of writing)
 - RFC7861 v3: https://tools.ietf.org/rfc/rfc7861.txt

Background
==========
+2 −0
Original line number Diff line number Diff line
@@ -9556,6 +9556,7 @@ F: include/linux/sunrpc/
F:	include/uapi/linux/nfsd/
F:	include/uapi/linux/sunrpc/
F:	net/sunrpc/
F:	Documentation/filesystems/nfs/
KERNEL SELFTEST FRAMEWORK
M:	Shuah Khan <shuah@kernel.org>
@@ -12337,6 +12338,7 @@ F: include/linux/sunrpc/
F:	include/uapi/linux/nfs*
F:	include/uapi/linux/sunrpc/
F:	net/sunrpc/
F:	Documentation/filesystems/nfs/
NILFS2 FILESYSTEM
M:	Ryusuke Konishi <konishi.ryusuke@gmail.com>
+199 −49
Original line number Diff line number Diff line
@@ -486,65 +486,215 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp)
        return rpc_success;
}

static __be32
nlm4svc_proc_unused(struct svc_rqst *rqstp)
{
	return rpc_proc_unavail;
}


/*
 * NLM Server procedures.
 */

#define nlm4svc_encode_norep	nlm4svc_encode_void
#define nlm4svc_decode_norep	nlm4svc_decode_void
#define nlm4svc_decode_testres	nlm4svc_decode_void
#define nlm4svc_decode_lockres	nlm4svc_decode_void
#define nlm4svc_decode_unlockres	nlm4svc_decode_void
#define nlm4svc_decode_cancelres	nlm4svc_decode_void
#define nlm4svc_decode_grantedres	nlm4svc_decode_void

#define nlm4svc_proc_none	nlm4svc_proc_null
#define nlm4svc_proc_test_res	nlm4svc_proc_null
#define nlm4svc_proc_lock_res	nlm4svc_proc_null
#define nlm4svc_proc_cancel_res	nlm4svc_proc_null
#define nlm4svc_proc_unlock_res	nlm4svc_proc_null

struct nlm_void			{ int dummy; };

#define PROC(name, xargt, xrest, argt, rest, respsize)	\
 { .pc_func	= nlm4svc_proc_##name,	\
   .pc_decode	= nlm4svc_decode_##xargt,	\
   .pc_encode	= nlm4svc_encode_##xrest,	\
   .pc_release	= NULL,					\
   .pc_argsize	= sizeof(struct nlm_##argt),		\
   .pc_ressize	= sizeof(struct nlm_##rest),		\
   .pc_xdrressize = respsize,				\
 }
#define	Ck	(1+XDR_QUADLEN(NLM_MAXCOOKIELEN))	/* cookie */
#define	No	(1+1024/4)				/* netobj */
#define	St	1					/* status */
#define	Rg	4					/* range (offset + length) */
const struct svc_procedure nlmsvc_procedures4[] = {
  PROC(null,		void,		void,		void,	void, 1),
  PROC(test,		testargs,	testres,	args,	res, Ck+St+2+No+Rg),
  PROC(lock,		lockargs,	res,		args,	res, Ck+St),
  PROC(cancel,		cancargs,	res,		args,	res, Ck+St),
  PROC(unlock,		unlockargs,	res,		args,	res, Ck+St),
  PROC(granted,		testargs,	res,		args,	res, Ck+St),
  PROC(test_msg,	testargs,	norep,		args,	void, 1),
  PROC(lock_msg,	lockargs,	norep,		args,	void, 1),
  PROC(cancel_msg,	cancargs,	norep,		args,	void, 1),
  PROC(unlock_msg,	unlockargs,	norep,		args,	void, 1),
  PROC(granted_msg,	testargs,	norep,		args,	void, 1),
  PROC(test_res,	testres,	norep,		res,	void, 1),
  PROC(lock_res,	lockres,	norep,		res,	void, 1),
  PROC(cancel_res,	cancelres,	norep,		res,	void, 1),
  PROC(unlock_res,	unlockres,	norep,		res,	void, 1),
  PROC(granted_res,	res,		norep,		res,	void, 1),
  /* statd callback */
  PROC(sm_notify,	reboot,		void,		reboot,	void, 1),
  PROC(none,		void,		void,		void,	void, 0),
  PROC(none,		void,		void,		void,	void, 0),
  PROC(none,		void,		void,		void,	void, 0),
  PROC(share,		shareargs,	shareres,	args,	res, Ck+St+1),
  PROC(unshare,		shareargs,	shareres,	args,	res, Ck+St+1),
  PROC(nm_lock,		lockargs,	res,		args,	res, Ck+St),
  PROC(free_all,	notify,		void,		args,	void, 1),

const struct svc_procedure nlmsvc_procedures4[24] = {
	[NLMPROC_NULL] = {
		.pc_func = nlm4svc_proc_null,
		.pc_decode = nlm4svc_decode_void,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_void),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_TEST] = {
		.pc_func = nlm4svc_proc_test,
		.pc_decode = nlm4svc_decode_testargs,
		.pc_encode = nlm4svc_encode_testres,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_res),
		.pc_xdrressize = Ck+St+2+No+Rg,
	},
	[NLMPROC_LOCK] = {
		.pc_func = nlm4svc_proc_lock,
		.pc_decode = nlm4svc_decode_lockargs,
		.pc_encode = nlm4svc_encode_res,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_res),
		.pc_xdrressize = Ck+St,
	},
	[NLMPROC_CANCEL] = {
		.pc_func = nlm4svc_proc_cancel,
		.pc_decode = nlm4svc_decode_cancargs,
		.pc_encode = nlm4svc_encode_res,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_res),
		.pc_xdrressize = Ck+St,
	},
	[NLMPROC_UNLOCK] = {
		.pc_func = nlm4svc_proc_unlock,
		.pc_decode = nlm4svc_decode_unlockargs,
		.pc_encode = nlm4svc_encode_res,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_res),
		.pc_xdrressize = Ck+St,
	},
	[NLMPROC_GRANTED] = {
		.pc_func = nlm4svc_proc_granted,
		.pc_decode = nlm4svc_decode_testargs,
		.pc_encode = nlm4svc_encode_res,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_res),
		.pc_xdrressize = Ck+St,
	},
	[NLMPROC_TEST_MSG] = {
		.pc_func = nlm4svc_proc_test_msg,
		.pc_decode = nlm4svc_decode_testargs,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_LOCK_MSG] = {
		.pc_func = nlm4svc_proc_lock_msg,
		.pc_decode = nlm4svc_decode_lockargs,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_CANCEL_MSG] = {
		.pc_func = nlm4svc_proc_cancel_msg,
		.pc_decode = nlm4svc_decode_cancargs,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_UNLOCK_MSG] = {
		.pc_func = nlm4svc_proc_unlock_msg,
		.pc_decode = nlm4svc_decode_unlockargs,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_GRANTED_MSG] = {
		.pc_func = nlm4svc_proc_granted_msg,
		.pc_decode = nlm4svc_decode_testargs,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_TEST_RES] = {
		.pc_func = nlm4svc_proc_null,
		.pc_decode = nlm4svc_decode_void,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_res),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_LOCK_RES] = {
		.pc_func = nlm4svc_proc_null,
		.pc_decode = nlm4svc_decode_void,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_res),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_CANCEL_RES] = {
		.pc_func = nlm4svc_proc_null,
		.pc_decode = nlm4svc_decode_void,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_res),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_UNLOCK_RES] = {
		.pc_func = nlm4svc_proc_null,
		.pc_decode = nlm4svc_decode_void,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_res),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_GRANTED_RES] = {
		.pc_func = nlm4svc_proc_granted_res,
		.pc_decode = nlm4svc_decode_res,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_res),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[NLMPROC_NSM_NOTIFY] = {
		.pc_func = nlm4svc_proc_sm_notify,
		.pc_decode = nlm4svc_decode_reboot,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_reboot),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
	[17] = {
		.pc_func = nlm4svc_proc_unused,
		.pc_decode = nlm4svc_decode_void,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_void),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = 0,
	},
	[18] = {
		.pc_func = nlm4svc_proc_unused,
		.pc_decode = nlm4svc_decode_void,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_void),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = 0,
	},
	[19] = {
		.pc_func = nlm4svc_proc_unused,
		.pc_decode = nlm4svc_decode_void,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_void),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = 0,
	},
	[NLMPROC_SHARE] = {
		.pc_func = nlm4svc_proc_share,
		.pc_decode = nlm4svc_decode_shareargs,
		.pc_encode = nlm4svc_encode_shareres,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_res),
		.pc_xdrressize = Ck+St+1,
	},
	[NLMPROC_UNSHARE] = {
		.pc_func = nlm4svc_proc_unshare,
		.pc_decode = nlm4svc_decode_shareargs,
		.pc_encode = nlm4svc_encode_shareres,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_res),
		.pc_xdrressize = Ck+St+1,
	},
	[NLMPROC_NM_LOCK] = {
		.pc_func = nlm4svc_proc_nm_lock,
		.pc_decode = nlm4svc_decode_lockargs,
		.pc_encode = nlm4svc_encode_res,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_res),
		.pc_xdrressize = Ck+St,
	},
	[NLMPROC_FREE_ALL] = {
		.pc_func = nlm4svc_proc_free_all,
		.pc_decode = nlm4svc_decode_notify,
		.pc_encode = nlm4svc_encode_void,
		.pc_argsize = sizeof(struct nlm_args),
		.pc_ressize = sizeof(struct nlm_void),
		.pc_xdrressize = St,
	},
};
Loading