mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
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() ...
This commit is contained in:
@@ -1,70 +0,0 @@
|
||||
===================
|
||||
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.
|
||||
@@ -12,4 +12,3 @@ NFS
|
||||
nfs-idmapper
|
||||
pnfs-block-server
|
||||
pnfs-scsi-server
|
||||
fault_injection
|
||||
|
||||
@@ -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
|
||||
==========
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -529,66 +529,214 @@ nlmsvc_proc_granted_res(struct svc_rqst *rqstp)
|
||||
return rpc_success;
|
||||
}
|
||||
|
||||
static __be32
|
||||
nlmsvc_proc_unused(struct svc_rqst *rqstp)
|
||||
{
|
||||
return rpc_proc_unavail;
|
||||
}
|
||||
|
||||
/*
|
||||
* NLM Server procedures.
|
||||
*/
|
||||
|
||||
#define nlmsvc_encode_norep nlmsvc_encode_void
|
||||
#define nlmsvc_decode_norep nlmsvc_decode_void
|
||||
#define nlmsvc_decode_testres nlmsvc_decode_void
|
||||
#define nlmsvc_decode_lockres nlmsvc_decode_void
|
||||
#define nlmsvc_decode_unlockres nlmsvc_decode_void
|
||||
#define nlmsvc_decode_cancelres nlmsvc_decode_void
|
||||
#define nlmsvc_decode_grantedres nlmsvc_decode_void
|
||||
|
||||
#define nlmsvc_proc_none nlmsvc_proc_null
|
||||
#define nlmsvc_proc_test_res nlmsvc_proc_null
|
||||
#define nlmsvc_proc_lock_res nlmsvc_proc_null
|
||||
#define nlmsvc_proc_cancel_res nlmsvc_proc_null
|
||||
#define nlmsvc_proc_unlock_res nlmsvc_proc_null
|
||||
|
||||
struct nlm_void { int dummy; };
|
||||
|
||||
#define PROC(name, xargt, xrest, argt, rest, respsize) \
|
||||
{ .pc_func = nlmsvc_proc_##name, \
|
||||
.pc_decode = nlmsvc_decode_##xargt, \
|
||||
.pc_encode = nlmsvc_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 St 1 /* status */
|
||||
#define No (1+1024/4) /* Net Obj */
|
||||
#define Rg 2 /* range - offset + size */
|
||||
|
||||
const struct svc_procedure nlmsvc_procedures[] = {
|
||||
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, 1),
|
||||
PROC(none, void, void, void, void, 1),
|
||||
PROC(none, void, void, void, void, 1),
|
||||
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, 0),
|
||||
|
||||
const struct svc_procedure nlmsvc_procedures[24] = {
|
||||
[NLMPROC_NULL] = {
|
||||
.pc_func = nlmsvc_proc_null,
|
||||
.pc_decode = nlmsvc_decode_void,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_void),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_TEST] = {
|
||||
.pc_func = nlmsvc_proc_test,
|
||||
.pc_decode = nlmsvc_decode_testargs,
|
||||
.pc_encode = nlmsvc_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 = nlmsvc_proc_lock,
|
||||
.pc_decode = nlmsvc_decode_lockargs,
|
||||
.pc_encode = nlmsvc_encode_res,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_res),
|
||||
.pc_xdrressize = Ck+St,
|
||||
},
|
||||
[NLMPROC_CANCEL] = {
|
||||
.pc_func = nlmsvc_proc_cancel,
|
||||
.pc_decode = nlmsvc_decode_cancargs,
|
||||
.pc_encode = nlmsvc_encode_res,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_res),
|
||||
.pc_xdrressize = Ck+St,
|
||||
},
|
||||
[NLMPROC_UNLOCK] = {
|
||||
.pc_func = nlmsvc_proc_unlock,
|
||||
.pc_decode = nlmsvc_decode_unlockargs,
|
||||
.pc_encode = nlmsvc_encode_res,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_res),
|
||||
.pc_xdrressize = Ck+St,
|
||||
},
|
||||
[NLMPROC_GRANTED] = {
|
||||
.pc_func = nlmsvc_proc_granted,
|
||||
.pc_decode = nlmsvc_decode_testargs,
|
||||
.pc_encode = nlmsvc_encode_res,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_res),
|
||||
.pc_xdrressize = Ck+St,
|
||||
},
|
||||
[NLMPROC_TEST_MSG] = {
|
||||
.pc_func = nlmsvc_proc_test_msg,
|
||||
.pc_decode = nlmsvc_decode_testargs,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_LOCK_MSG] = {
|
||||
.pc_func = nlmsvc_proc_lock_msg,
|
||||
.pc_decode = nlmsvc_decode_lockargs,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_CANCEL_MSG] = {
|
||||
.pc_func = nlmsvc_proc_cancel_msg,
|
||||
.pc_decode = nlmsvc_decode_cancargs,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_UNLOCK_MSG] = {
|
||||
.pc_func = nlmsvc_proc_unlock_msg,
|
||||
.pc_decode = nlmsvc_decode_unlockargs,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_GRANTED_MSG] = {
|
||||
.pc_func = nlmsvc_proc_granted_msg,
|
||||
.pc_decode = nlmsvc_decode_testargs,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_TEST_RES] = {
|
||||
.pc_func = nlmsvc_proc_null,
|
||||
.pc_decode = nlmsvc_decode_void,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_res),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_LOCK_RES] = {
|
||||
.pc_func = nlmsvc_proc_null,
|
||||
.pc_decode = nlmsvc_decode_void,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_res),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_CANCEL_RES] = {
|
||||
.pc_func = nlmsvc_proc_null,
|
||||
.pc_decode = nlmsvc_decode_void,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_res),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_UNLOCK_RES] = {
|
||||
.pc_func = nlmsvc_proc_null,
|
||||
.pc_decode = nlmsvc_decode_void,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_res),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_GRANTED_RES] = {
|
||||
.pc_func = nlmsvc_proc_granted_res,
|
||||
.pc_decode = nlmsvc_decode_res,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_res),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_NSM_NOTIFY] = {
|
||||
.pc_func = nlmsvc_proc_sm_notify,
|
||||
.pc_decode = nlmsvc_decode_reboot,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_reboot),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[17] = {
|
||||
.pc_func = nlmsvc_proc_unused,
|
||||
.pc_decode = nlmsvc_decode_void,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_void),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[18] = {
|
||||
.pc_func = nlmsvc_proc_unused,
|
||||
.pc_decode = nlmsvc_decode_void,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_void),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[19] = {
|
||||
.pc_func = nlmsvc_proc_unused,
|
||||
.pc_decode = nlmsvc_decode_void,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_void),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = St,
|
||||
},
|
||||
[NLMPROC_SHARE] = {
|
||||
.pc_func = nlmsvc_proc_share,
|
||||
.pc_decode = nlmsvc_decode_shareargs,
|
||||
.pc_encode = nlmsvc_encode_shareres,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_res),
|
||||
.pc_xdrressize = Ck+St+1,
|
||||
},
|
||||
[NLMPROC_UNSHARE] = {
|
||||
.pc_func = nlmsvc_proc_unshare,
|
||||
.pc_decode = nlmsvc_decode_shareargs,
|
||||
.pc_encode = nlmsvc_encode_shareres,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_res),
|
||||
.pc_xdrressize = Ck+St+1,
|
||||
},
|
||||
[NLMPROC_NM_LOCK] = {
|
||||
.pc_func = nlmsvc_proc_nm_lock,
|
||||
.pc_decode = nlmsvc_decode_lockargs,
|
||||
.pc_encode = nlmsvc_encode_res,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_res),
|
||||
.pc_xdrressize = Ck+St,
|
||||
},
|
||||
[NLMPROC_FREE_ALL] = {
|
||||
.pc_func = nlmsvc_proc_free_all,
|
||||
.pc_decode = nlmsvc_decode_notify,
|
||||
.pc_encode = nlmsvc_encode_void,
|
||||
.pc_argsize = sizeof(struct nlm_args),
|
||||
.pc_ressize = sizeof(struct nlm_void),
|
||||
.pc_xdrressize = 0,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/nfs_ssc.h>
|
||||
#include "delegation.h"
|
||||
#include "internal.h"
|
||||
#include "iostat.h"
|
||||
@@ -315,9 +316,8 @@ out:
|
||||
static int read_name_gen = 1;
|
||||
#define SSC_READ_NAME_BODY "ssc_read_%d"
|
||||
|
||||
struct file *
|
||||
nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
|
||||
nfs4_stateid *stateid)
|
||||
static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
|
||||
struct nfs_fh *src_fh, nfs4_stateid *stateid)
|
||||
{
|
||||
struct nfs_fattr fattr;
|
||||
struct file *filep, *res;
|
||||
@@ -399,14 +399,40 @@ out_filep:
|
||||
fput(filep);
|
||||
goto out_free_name;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs42_ssc_open);
|
||||
void nfs42_ssc_close(struct file *filep)
|
||||
|
||||
static void __nfs42_ssc_close(struct file *filep)
|
||||
{
|
||||
struct nfs_open_context *ctx = nfs_file_open_context(filep);
|
||||
|
||||
ctx->state->flags = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs42_ssc_close);
|
||||
|
||||
static const struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_tbl = {
|
||||
.sco_open = __nfs42_ssc_open,
|
||||
.sco_close = __nfs42_ssc_close,
|
||||
};
|
||||
|
||||
/**
|
||||
* nfs42_ssc_register_ops - Wrapper to register NFS_V4 ops in nfs_common
|
||||
*
|
||||
* Return values:
|
||||
* None
|
||||
*/
|
||||
void nfs42_ssc_register_ops(void)
|
||||
{
|
||||
nfs42_ssc_register(&nfs4_ssc_clnt_ops_tbl);
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs42_ssc_unregister_ops - wrapper to un-register NFS_V4 ops in nfs_common
|
||||
*
|
||||
* Return values:
|
||||
* None.
|
||||
*/
|
||||
void nfs42_ssc_unregister_ops(void)
|
||||
{
|
||||
nfs42_ssc_unregister(&nfs4_ssc_clnt_ops_tbl);
|
||||
}
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
const struct file_operations nfs4_file_operations = {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/mount.h>
|
||||
#include <linux/nfs4_mount.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/nfs_ssc.h>
|
||||
#include "delegation.h"
|
||||
#include "internal.h"
|
||||
#include "nfs4_fs.h"
|
||||
@@ -279,6 +280,9 @@ static int __init init_nfs_v4(void)
|
||||
if (err)
|
||||
goto out2;
|
||||
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
nfs42_ssc_register_ops();
|
||||
#endif
|
||||
register_nfs_version(&nfs_v4);
|
||||
return 0;
|
||||
out2:
|
||||
@@ -297,6 +301,7 @@ static void __exit exit_nfs_v4(void)
|
||||
unregister_nfs_version(&nfs_v4);
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
nfs4_xattr_cache_exit();
|
||||
nfs42_ssc_unregister_ops();
|
||||
#endif
|
||||
nfs4_unregister_sysctl();
|
||||
nfs_idmap_quit();
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/nfs_ssc.h>
|
||||
|
||||
#include "nfs4_fs.h"
|
||||
#include "callback.h"
|
||||
@@ -85,6 +86,10 @@ const struct super_operations nfs_sops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(nfs_sops);
|
||||
|
||||
static const struct nfs_ssc_client_ops nfs_ssc_clnt_ops_tbl = {
|
||||
.sco_sb_deactive = nfs_sb_deactive,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_NFS_V4)
|
||||
static int __init register_nfs4_fs(void)
|
||||
{
|
||||
@@ -106,6 +111,16 @@ static void unregister_nfs4_fs(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void nfs_ssc_register_ops(void)
|
||||
{
|
||||
nfs_ssc_register(&nfs_ssc_clnt_ops_tbl);
|
||||
}
|
||||
|
||||
static void nfs_ssc_unregister_ops(void)
|
||||
{
|
||||
nfs_ssc_unregister(&nfs_ssc_clnt_ops_tbl);
|
||||
}
|
||||
|
||||
static struct shrinker acl_shrinker = {
|
||||
.count_objects = nfs_access_cache_count,
|
||||
.scan_objects = nfs_access_cache_scan,
|
||||
@@ -133,6 +148,7 @@ int __init register_nfs_fs(void)
|
||||
ret = register_shrinker(&acl_shrinker);
|
||||
if (ret < 0)
|
||||
goto error_3;
|
||||
nfs_ssc_register_ops();
|
||||
return 0;
|
||||
error_3:
|
||||
nfs_unregister_sysctl();
|
||||
@@ -152,6 +168,7 @@ void __exit unregister_nfs_fs(void)
|
||||
unregister_shrinker(&acl_shrinker);
|
||||
nfs_unregister_sysctl();
|
||||
unregister_nfs4_fs();
|
||||
nfs_ssc_unregister_ops();
|
||||
unregister_filesystem(&nfs_fs_type);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,3 +7,4 @@ obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o
|
||||
nfs_acl-objs := nfsacl.o
|
||||
|
||||
obj-$(CONFIG_GRACE_PERIOD) += grace.o
|
||||
obj-$(CONFIG_GRACE_PERIOD) += nfs_ssc.o
|
||||
|
||||
94
fs/nfs_common/nfs_ssc.c
Normal file
94
fs/nfs_common/nfs_ssc.c
Normal file
@@ -0,0 +1,94 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* fs/nfs_common/nfs_ssc_comm.c
|
||||
*
|
||||
* Helper for knfsd's SSC to access ops in NFS client modules
|
||||
*
|
||||
* Author: Dai Ngo <dai.ngo@oracle.com>
|
||||
*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/nfs_ssc.h>
|
||||
#include "../nfs/nfs4_fs.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
|
||||
EXPORT_SYMBOL_GPL(nfs_ssc_client_tbl);
|
||||
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
/**
|
||||
* nfs42_ssc_register - install the NFS_V4 client ops in the nfs_ssc_client_tbl
|
||||
* @ops: NFS_V4 ops to be installed
|
||||
*
|
||||
* Return values:
|
||||
* None
|
||||
*/
|
||||
void nfs42_ssc_register(const struct nfs4_ssc_client_ops *ops)
|
||||
{
|
||||
nfs_ssc_client_tbl.ssc_nfs4_ops = ops;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs42_ssc_register);
|
||||
|
||||
/**
|
||||
* nfs42_ssc_unregister - uninstall the NFS_V4 client ops from
|
||||
* the nfs_ssc_client_tbl
|
||||
* @ops: ops to be uninstalled
|
||||
*
|
||||
* Return values:
|
||||
* None
|
||||
*/
|
||||
void nfs42_ssc_unregister(const struct nfs4_ssc_client_ops *ops)
|
||||
{
|
||||
if (nfs_ssc_client_tbl.ssc_nfs4_ops != ops)
|
||||
return;
|
||||
|
||||
nfs_ssc_client_tbl.ssc_nfs4_ops = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs42_ssc_unregister);
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
/**
|
||||
* nfs_ssc_register - install the NFS_FS client ops in the nfs_ssc_client_tbl
|
||||
* @ops: NFS_FS ops to be installed
|
||||
*
|
||||
* Return values:
|
||||
* None
|
||||
*/
|
||||
void nfs_ssc_register(const struct nfs_ssc_client_ops *ops)
|
||||
{
|
||||
nfs_ssc_client_tbl.ssc_nfs_ops = ops;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_ssc_register);
|
||||
|
||||
/**
|
||||
* nfs_ssc_unregister - uninstall the NFS_FS client ops from
|
||||
* the nfs_ssc_client_tbl
|
||||
* @ops: ops to be uninstalled
|
||||
*
|
||||
* Return values:
|
||||
* None
|
||||
*/
|
||||
void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops)
|
||||
{
|
||||
if (nfs_ssc_client_tbl.ssc_nfs_ops != ops)
|
||||
return;
|
||||
nfs_ssc_client_tbl.ssc_nfs_ops = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_ssc_unregister);
|
||||
|
||||
#else
|
||||
void nfs_ssc_register(const struct nfs_ssc_client_ops *ops)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_ssc_register);
|
||||
|
||||
void nfs_ssc_unregister(const struct nfs_ssc_client_ops *ops)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_ssc_unregister);
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
@@ -136,7 +136,7 @@ config NFSD_FLEXFILELAYOUT
|
||||
|
||||
config NFSD_V4_2_INTER_SSC
|
||||
bool "NFSv4.2 inter server to server COPY"
|
||||
depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2 && NFS_FS=y
|
||||
depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2
|
||||
help
|
||||
This option enables support for NFSv4.2 inter server to
|
||||
server copy where the destination server calls the NFSv4.2
|
||||
@@ -156,13 +156,3 @@ config NFSD_V4_SECURITY_LABEL
|
||||
|
||||
If you do not wish to enable fine-grained security labels SELinux or
|
||||
Smack policies on NFSv4 files, say N.
|
||||
|
||||
config NFSD_FAULT_INJECTION
|
||||
bool "NFS server manual fault injection"
|
||||
depends on NFSD_V4 && DEBUG_KERNEL && DEBUG_FS && BROKEN
|
||||
help
|
||||
This option enables support for manually injecting faults
|
||||
into the NFS server. This is intended to be used for
|
||||
testing error recovery on the NFS client.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
@@ -13,7 +13,6 @@ nfsd-y += trace.o
|
||||
nfsd-y += nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
|
||||
export.o auth.o lockd.o nfscache.o nfsxdr.o \
|
||||
stats.o filecache.o
|
||||
nfsd-$(CONFIG_NFSD_FAULT_INJECTION) += fault_inject.o
|
||||
nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
|
||||
nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
|
||||
nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
|
||||
|
||||
@@ -1002,7 +1002,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
|
||||
if (nfsd4_spo_must_allow(rqstp))
|
||||
return 0;
|
||||
|
||||
return nfserr_wrongsec;
|
||||
return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -889,7 +889,7 @@ nfsd_file_find_locked(struct inode *inode, unsigned int may_flags,
|
||||
|
||||
hlist_for_each_entry_rcu(nf, &nfsd_file_hashtbl[hashval].nfb_head,
|
||||
nf_node, lockdep_is_held(&nfsd_file_hashtbl[hashval].nfb_lock)) {
|
||||
if ((need & nf->nf_may) != need)
|
||||
if (nf->nf_may != need)
|
||||
continue;
|
||||
if (nf->nf_inode != inode)
|
||||
continue;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "vfs.h"
|
||||
|
||||
#define NFSDDBG_FACILITY NFSDDBG_PROC
|
||||
#define RETURN_STATUS(st) { resp->status = (st); return (st); }
|
||||
|
||||
/*
|
||||
* NULL call.
|
||||
@@ -22,7 +21,7 @@
|
||||
static __be32
|
||||
nfsacld_proc_null(struct svc_rqst *rqstp)
|
||||
{
|
||||
return nfs_ok;
|
||||
return rpc_success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -35,24 +34,25 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp)
|
||||
struct posix_acl *acl;
|
||||
struct inode *inode;
|
||||
svc_fh *fh;
|
||||
__be32 nfserr = 0;
|
||||
|
||||
dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
|
||||
|
||||
fh = fh_copy(&resp->fh, &argp->fh);
|
||||
nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
|
||||
if (nfserr)
|
||||
RETURN_STATUS(nfserr);
|
||||
resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
|
||||
inode = d_inode(fh->fh_dentry);
|
||||
|
||||
if (argp->mask & ~NFS_ACL_MASK)
|
||||
RETURN_STATUS(nfserr_inval);
|
||||
if (argp->mask & ~NFS_ACL_MASK) {
|
||||
resp->status = nfserr_inval;
|
||||
goto out;
|
||||
}
|
||||
resp->mask = argp->mask;
|
||||
|
||||
nfserr = fh_getattr(fh, &resp->stat);
|
||||
if (nfserr)
|
||||
RETURN_STATUS(nfserr);
|
||||
resp->status = fh_getattr(fh, &resp->stat);
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
|
||||
if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
|
||||
acl = get_acl(inode, ACL_TYPE_ACCESS);
|
||||
@@ -61,7 +61,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp)
|
||||
acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
|
||||
}
|
||||
if (IS_ERR(acl)) {
|
||||
nfserr = nfserrno(PTR_ERR(acl));
|
||||
resp->status = nfserrno(PTR_ERR(acl));
|
||||
goto fail;
|
||||
}
|
||||
resp->acl_access = acl;
|
||||
@@ -71,19 +71,20 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp)
|
||||
of a non-directory! */
|
||||
acl = get_acl(inode, ACL_TYPE_DEFAULT);
|
||||
if (IS_ERR(acl)) {
|
||||
nfserr = nfserrno(PTR_ERR(acl));
|
||||
resp->status = nfserrno(PTR_ERR(acl));
|
||||
goto fail;
|
||||
}
|
||||
resp->acl_default = acl;
|
||||
}
|
||||
|
||||
/* resp->acl_{access,default} are released in nfssvc_release_getacl. */
|
||||
RETURN_STATUS(0);
|
||||
out:
|
||||
return rpc_success;
|
||||
|
||||
fail:
|
||||
posix_acl_release(resp->acl_access);
|
||||
posix_acl_release(resp->acl_default);
|
||||
RETURN_STATUS(nfserr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -95,14 +96,13 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)
|
||||
struct nfsd_attrstat *resp = rqstp->rq_resp;
|
||||
struct inode *inode;
|
||||
svc_fh *fh;
|
||||
__be32 nfserr = 0;
|
||||
int error;
|
||||
|
||||
dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
|
||||
|
||||
fh = fh_copy(&resp->fh, &argp->fh);
|
||||
nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
|
||||
if (nfserr)
|
||||
resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
|
||||
inode = d_inode(fh->fh_dentry);
|
||||
@@ -124,19 +124,20 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)
|
||||
|
||||
fh_drop_write(fh);
|
||||
|
||||
nfserr = fh_getattr(fh, &resp->stat);
|
||||
resp->status = fh_getattr(fh, &resp->stat);
|
||||
|
||||
out:
|
||||
/* argp->acl_{access,default} may have been allocated in
|
||||
nfssvc_decode_setaclargs. */
|
||||
posix_acl_release(argp->acl_access);
|
||||
posix_acl_release(argp->acl_default);
|
||||
return nfserr;
|
||||
return rpc_success;
|
||||
|
||||
out_drop_lock:
|
||||
fh_unlock(fh);
|
||||
fh_drop_write(fh);
|
||||
out_errno:
|
||||
nfserr = nfserrno(error);
|
||||
resp->status = nfserrno(error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -147,15 +148,16 @@ static __be32 nfsacld_proc_getattr(struct svc_rqst *rqstp)
|
||||
{
|
||||
struct nfsd_fhandle *argp = rqstp->rq_argp;
|
||||
struct nfsd_attrstat *resp = rqstp->rq_resp;
|
||||
__be32 nfserr;
|
||||
|
||||
dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
|
||||
|
||||
fh_copy(&resp->fh, &argp->fh);
|
||||
nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
|
||||
if (nfserr)
|
||||
return nfserr;
|
||||
nfserr = fh_getattr(&resp->fh, &resp->stat);
|
||||
return nfserr;
|
||||
resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
resp->status = fh_getattr(&resp->fh, &resp->stat);
|
||||
out:
|
||||
return rpc_success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -165,7 +167,6 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
|
||||
{
|
||||
struct nfsd3_accessargs *argp = rqstp->rq_argp;
|
||||
struct nfsd3_accessres *resp = rqstp->rq_resp;
|
||||
__be32 nfserr;
|
||||
|
||||
dprintk("nfsd: ACCESS(2acl) %s 0x%x\n",
|
||||
SVCFH_fmt(&argp->fh),
|
||||
@@ -173,16 +174,22 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
|
||||
|
||||
fh_copy(&resp->fh, &argp->fh);
|
||||
resp->access = argp->access;
|
||||
nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
|
||||
if (nfserr)
|
||||
return nfserr;
|
||||
nfserr = fh_getattr(&resp->fh, &resp->stat);
|
||||
return nfserr;
|
||||
resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
resp->status = fh_getattr(&resp->fh, &resp->stat);
|
||||
out:
|
||||
return rpc_success;
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR decode functions
|
||||
*/
|
||||
static int nfsaclsvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_getaclargs *argp = rqstp->rq_argp;
|
||||
@@ -268,6 +275,10 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
int n;
|
||||
int w;
|
||||
|
||||
*p++ = resp->status;
|
||||
if (resp->status != nfs_ok)
|
||||
return xdr_ressize_check(rqstp, p);
|
||||
|
||||
/*
|
||||
* Since this is version 2, the check for nfserr in
|
||||
* nfsd_dispatch actually ensures the following cannot happen.
|
||||
@@ -307,7 +318,12 @@ static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd_attrstat *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
|
||||
p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
|
||||
out:
|
||||
return xdr_ressize_check(rqstp, p);
|
||||
}
|
||||
|
||||
@@ -316,8 +332,13 @@ static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_accessres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
|
||||
p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
|
||||
*p++ = htonl(resp->access);
|
||||
out:
|
||||
return xdr_ressize_check(rqstp, p);
|
||||
}
|
||||
|
||||
@@ -347,36 +368,63 @@ static void nfsaclsvc_release_access(struct svc_rqst *rqstp)
|
||||
fh_put(&resp->fh);
|
||||
}
|
||||
|
||||
#define nfsaclsvc_decode_voidargs NULL
|
||||
#define nfsaclsvc_release_void NULL
|
||||
#define nfsd3_fhandleargs nfsd_fhandle
|
||||
#define nfsd3_attrstatres nfsd_attrstat
|
||||
#define nfsd3_voidres nfsd3_voidargs
|
||||
struct nfsd3_voidargs { int dummy; };
|
||||
|
||||
#define PROC(name, argt, rest, relt, cache, respsize) \
|
||||
{ \
|
||||
.pc_func = nfsacld_proc_##name, \
|
||||
.pc_decode = nfsaclsvc_decode_##argt##args, \
|
||||
.pc_encode = nfsaclsvc_encode_##rest##res, \
|
||||
.pc_release = nfsaclsvc_release_##relt, \
|
||||
.pc_argsize = sizeof(struct nfsd3_##argt##args), \
|
||||
.pc_ressize = sizeof(struct nfsd3_##rest##res), \
|
||||
.pc_cachetype = cache, \
|
||||
.pc_xdrressize = respsize, \
|
||||
}
|
||||
|
||||
#define ST 1 /* status*/
|
||||
#define AT 21 /* attributes */
|
||||
#define pAT (1+AT) /* post attributes - conditional */
|
||||
#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
|
||||
|
||||
static const struct svc_procedure nfsd_acl_procedures2[] = {
|
||||
PROC(null, void, void, void, RC_NOCACHE, ST),
|
||||
PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
|
||||
PROC(setacl, setacl, attrstat, attrstat, RC_NOCACHE, ST+AT),
|
||||
PROC(getattr, fhandle, attrstat, attrstat, RC_NOCACHE, ST+AT),
|
||||
PROC(access, access, access, access, RC_NOCACHE, ST+AT+1),
|
||||
static const struct svc_procedure nfsd_acl_procedures2[5] = {
|
||||
[ACLPROC2_NULL] = {
|
||||
.pc_func = nfsacld_proc_null,
|
||||
.pc_decode = nfsaclsvc_decode_voidarg,
|
||||
.pc_encode = nfsaclsvc_encode_voidres,
|
||||
.pc_argsize = sizeof(struct nfsd3_voidargs),
|
||||
.pc_ressize = sizeof(struct nfsd3_voidargs),
|
||||
.pc_cachetype = RC_NOCACHE,
|
||||
.pc_xdrressize = ST,
|
||||
},
|
||||
[ACLPROC2_GETACL] = {
|
||||
.pc_func = nfsacld_proc_getacl,
|
||||
.pc_decode = nfsaclsvc_decode_getaclargs,
|
||||
.pc_encode = nfsaclsvc_encode_getaclres,
|
||||
.pc_release = nfsaclsvc_release_getacl,
|
||||
.pc_argsize = sizeof(struct nfsd3_getaclargs),
|
||||
.pc_ressize = sizeof(struct nfsd3_getaclres),
|
||||
.pc_cachetype = RC_NOCACHE,
|
||||
.pc_xdrressize = ST+1+2*(1+ACL),
|
||||
},
|
||||
[ACLPROC2_SETACL] = {
|
||||
.pc_func = nfsacld_proc_setacl,
|
||||
.pc_decode = nfsaclsvc_decode_setaclargs,
|
||||
.pc_encode = nfsaclsvc_encode_attrstatres,
|
||||
.pc_release = nfsaclsvc_release_attrstat,
|
||||
.pc_argsize = sizeof(struct nfsd3_setaclargs),
|
||||
.pc_ressize = sizeof(struct nfsd_attrstat),
|
||||
.pc_cachetype = RC_NOCACHE,
|
||||
.pc_xdrressize = ST+AT,
|
||||
},
|
||||
[ACLPROC2_GETATTR] = {
|
||||
.pc_func = nfsacld_proc_getattr,
|
||||
.pc_decode = nfsaclsvc_decode_fhandleargs,
|
||||
.pc_encode = nfsaclsvc_encode_attrstatres,
|
||||
.pc_release = nfsaclsvc_release_attrstat,
|
||||
.pc_argsize = sizeof(struct nfsd_fhandle),
|
||||
.pc_ressize = sizeof(struct nfsd_attrstat),
|
||||
.pc_cachetype = RC_NOCACHE,
|
||||
.pc_xdrressize = ST+AT,
|
||||
},
|
||||
[ACLPROC2_ACCESS] = {
|
||||
.pc_func = nfsacld_proc_access,
|
||||
.pc_decode = nfsaclsvc_decode_accessargs,
|
||||
.pc_encode = nfsaclsvc_encode_accessres,
|
||||
.pc_release = nfsaclsvc_release_access,
|
||||
.pc_argsize = sizeof(struct nfsd3_accessargs),
|
||||
.pc_ressize = sizeof(struct nfsd3_accessres),
|
||||
.pc_cachetype = RC_NOCACHE,
|
||||
.pc_xdrressize = ST+AT+1,
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)];
|
||||
|
||||
@@ -13,15 +13,13 @@
|
||||
#include "xdr3.h"
|
||||
#include "vfs.h"
|
||||
|
||||
#define RETURN_STATUS(st) { resp->status = (st); return (st); }
|
||||
|
||||
/*
|
||||
* NULL call.
|
||||
*/
|
||||
static __be32
|
||||
nfsd3_proc_null(struct svc_rqst *rqstp)
|
||||
{
|
||||
return nfs_ok;
|
||||
return rpc_success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -34,17 +32,18 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp)
|
||||
struct posix_acl *acl;
|
||||
struct inode *inode;
|
||||
svc_fh *fh;
|
||||
__be32 nfserr = 0;
|
||||
|
||||
fh = fh_copy(&resp->fh, &argp->fh);
|
||||
nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
|
||||
if (nfserr)
|
||||
RETURN_STATUS(nfserr);
|
||||
resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
|
||||
inode = d_inode(fh->fh_dentry);
|
||||
|
||||
if (argp->mask & ~NFS_ACL_MASK)
|
||||
RETURN_STATUS(nfserr_inval);
|
||||
if (argp->mask & ~NFS_ACL_MASK) {
|
||||
resp->status = nfserr_inval;
|
||||
goto out;
|
||||
}
|
||||
resp->mask = argp->mask;
|
||||
|
||||
if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
|
||||
@@ -54,7 +53,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp)
|
||||
acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
|
||||
}
|
||||
if (IS_ERR(acl)) {
|
||||
nfserr = nfserrno(PTR_ERR(acl));
|
||||
resp->status = nfserrno(PTR_ERR(acl));
|
||||
goto fail;
|
||||
}
|
||||
resp->acl_access = acl;
|
||||
@@ -64,19 +63,20 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst *rqstp)
|
||||
of a non-directory! */
|
||||
acl = get_acl(inode, ACL_TYPE_DEFAULT);
|
||||
if (IS_ERR(acl)) {
|
||||
nfserr = nfserrno(PTR_ERR(acl));
|
||||
resp->status = nfserrno(PTR_ERR(acl));
|
||||
goto fail;
|
||||
}
|
||||
resp->acl_default = acl;
|
||||
}
|
||||
|
||||
/* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
|
||||
RETURN_STATUS(0);
|
||||
out:
|
||||
return rpc_success;
|
||||
|
||||
fail:
|
||||
posix_acl_release(resp->acl_access);
|
||||
posix_acl_release(resp->acl_default);
|
||||
RETURN_STATUS(nfserr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -88,12 +88,11 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)
|
||||
struct nfsd3_attrstat *resp = rqstp->rq_resp;
|
||||
struct inode *inode;
|
||||
svc_fh *fh;
|
||||
__be32 nfserr = 0;
|
||||
int error;
|
||||
|
||||
fh = fh_copy(&resp->fh, &argp->fh);
|
||||
nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
|
||||
if (nfserr)
|
||||
resp->status = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
|
||||
if (resp->status != nfs_ok)
|
||||
goto out;
|
||||
|
||||
inode = d_inode(fh->fh_dentry);
|
||||
@@ -113,13 +112,13 @@ out_drop_lock:
|
||||
fh_unlock(fh);
|
||||
fh_drop_write(fh);
|
||||
out_errno:
|
||||
nfserr = nfserrno(error);
|
||||
resp->status = nfserrno(error);
|
||||
out:
|
||||
/* argp->acl_{access,default} may have been allocated in
|
||||
nfs3svc_decode_setaclargs. */
|
||||
posix_acl_release(argp->acl_access);
|
||||
posix_acl_release(argp->acl_default);
|
||||
RETURN_STATUS(nfserr);
|
||||
return rpc_success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -174,6 +173,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
struct nfsd3_getaclres *resp = rqstp->rq_resp;
|
||||
struct dentry *dentry = resp->fh.fh_dentry;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
|
||||
if (resp->status == 0 && dentry && d_really_is_positive(dentry)) {
|
||||
struct inode *inode = d_inode(dentry);
|
||||
@@ -218,8 +218,8 @@ static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_attrstat *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
|
||||
|
||||
return xdr_ressize_check(rqstp, p);
|
||||
}
|
||||
|
||||
@@ -235,33 +235,43 @@ static void nfs3svc_release_getacl(struct svc_rqst *rqstp)
|
||||
posix_acl_release(resp->acl_default);
|
||||
}
|
||||
|
||||
#define nfs3svc_decode_voidargs NULL
|
||||
#define nfs3svc_release_void NULL
|
||||
#define nfsd3_setaclres nfsd3_attrstat
|
||||
#define nfsd3_voidres nfsd3_voidargs
|
||||
struct nfsd3_voidargs { int dummy; };
|
||||
|
||||
#define PROC(name, argt, rest, relt, cache, respsize) \
|
||||
{ \
|
||||
.pc_func = nfsd3_proc_##name, \
|
||||
.pc_decode = nfs3svc_decode_##argt##args, \
|
||||
.pc_encode = nfs3svc_encode_##rest##res, \
|
||||
.pc_release = nfs3svc_release_##relt, \
|
||||
.pc_argsize = sizeof(struct nfsd3_##argt##args), \
|
||||
.pc_ressize = sizeof(struct nfsd3_##rest##res), \
|
||||
.pc_cachetype = cache, \
|
||||
.pc_xdrressize = respsize, \
|
||||
}
|
||||
|
||||
#define ST 1 /* status*/
|
||||
#define AT 21 /* attributes */
|
||||
#define pAT (1+AT) /* post attributes - conditional */
|
||||
#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
|
||||
|
||||
static const struct svc_procedure nfsd_acl_procedures3[] = {
|
||||
PROC(null, void, void, void, RC_NOCACHE, ST),
|
||||
PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
|
||||
PROC(setacl, setacl, setacl, fhandle, RC_NOCACHE, ST+pAT),
|
||||
static const struct svc_procedure nfsd_acl_procedures3[3] = {
|
||||
[ACLPROC3_NULL] = {
|
||||
.pc_func = nfsd3_proc_null,
|
||||
.pc_decode = nfs3svc_decode_voidarg,
|
||||
.pc_encode = nfs3svc_encode_voidres,
|
||||
.pc_argsize = sizeof(struct nfsd3_voidargs),
|
||||
.pc_ressize = sizeof(struct nfsd3_voidargs),
|
||||
.pc_cachetype = RC_NOCACHE,
|
||||
.pc_xdrressize = ST,
|
||||
},
|
||||
[ACLPROC3_GETACL] = {
|
||||
.pc_func = nfsd3_proc_getacl,
|
||||
.pc_decode = nfs3svc_decode_getaclargs,
|
||||
.pc_encode = nfs3svc_encode_getaclres,
|
||||
.pc_release = nfs3svc_release_getacl,
|
||||
.pc_argsize = sizeof(struct nfsd3_getaclargs),
|
||||
.pc_ressize = sizeof(struct nfsd3_getaclres),
|
||||
.pc_cachetype = RC_NOCACHE,
|
||||
.pc_xdrressize = ST+1+2*(1+ACL),
|
||||
},
|
||||
[ACLPROC3_SETACL] = {
|
||||
.pc_func = nfsd3_proc_setacl,
|
||||
.pc_decode = nfs3svc_decode_setaclargs,
|
||||
.pc_encode = nfs3svc_encode_setaclres,
|
||||
.pc_release = nfs3svc_release_fhandle,
|
||||
.pc_argsize = sizeof(struct nfsd3_setaclargs),
|
||||
.pc_ressize = sizeof(struct nfsd3_attrstat),
|
||||
.pc_cachetype = RC_NOCACHE,
|
||||
.pc_xdrressize = ST+pAT,
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned int nfsd_acl_count3[ARRAY_SIZE(nfsd_acl_procedures3)];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -304,6 +304,12 @@ void fill_post_wcc(struct svc_fh *fhp)
|
||||
/*
|
||||
* XDR decode functions
|
||||
*/
|
||||
int
|
||||
nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
@@ -635,10 +641,7 @@ nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
/*
|
||||
* XDR encode functions
|
||||
*/
|
||||
/*
|
||||
* There must be an encoding function for void results so svc_process
|
||||
* will work properly.
|
||||
*/
|
||||
|
||||
int
|
||||
nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
@@ -651,6 +654,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_attrstat *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
if (resp->status == 0) {
|
||||
lease_get_mtime(d_inode(resp->fh.fh_dentry),
|
||||
&resp->stat.mtime);
|
||||
@@ -665,6 +669,7 @@ nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_attrstat *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_wcc_data(rqstp, p, &resp->fh);
|
||||
return xdr_ressize_check(rqstp, p);
|
||||
}
|
||||
@@ -675,6 +680,7 @@ nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_diropres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
if (resp->status == 0) {
|
||||
p = encode_fh(p, &resp->fh);
|
||||
p = encode_post_op_attr(rqstp, p, &resp->fh);
|
||||
@@ -689,6 +695,7 @@ nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_accessres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_post_op_attr(rqstp, p, &resp->fh);
|
||||
if (resp->status == 0)
|
||||
*p++ = htonl(resp->access);
|
||||
@@ -701,6 +708,7 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_readlinkres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_post_op_attr(rqstp, p, &resp->fh);
|
||||
if (resp->status == 0) {
|
||||
*p++ = htonl(resp->len);
|
||||
@@ -723,6 +731,7 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_readres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_post_op_attr(rqstp, p, &resp->fh);
|
||||
if (resp->status == 0) {
|
||||
*p++ = htonl(resp->count);
|
||||
@@ -748,6 +757,7 @@ nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_writeres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_wcc_data(rqstp, p, &resp->fh);
|
||||
if (resp->status == 0) {
|
||||
*p++ = htonl(resp->count);
|
||||
@@ -764,6 +774,7 @@ nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_diropres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
if (resp->status == 0) {
|
||||
*p++ = xdr_one;
|
||||
p = encode_fh(p, &resp->fh);
|
||||
@@ -779,6 +790,7 @@ nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_renameres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_wcc_data(rqstp, p, &resp->ffh);
|
||||
p = encode_wcc_data(rqstp, p, &resp->tfh);
|
||||
return xdr_ressize_check(rqstp, p);
|
||||
@@ -790,6 +802,7 @@ nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_linkres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_post_op_attr(rqstp, p, &resp->fh);
|
||||
p = encode_wcc_data(rqstp, p, &resp->tfh);
|
||||
return xdr_ressize_check(rqstp, p);
|
||||
@@ -801,6 +814,7 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_readdirres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_post_op_attr(rqstp, p, &resp->fh);
|
||||
|
||||
if (resp->status == 0) {
|
||||
@@ -1053,6 +1067,7 @@ nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p)
|
||||
struct kstatfs *s = &resp->stats;
|
||||
u64 bs = s->f_bsize;
|
||||
|
||||
*p++ = resp->status;
|
||||
*p++ = xdr_zero; /* no post_op_attr */
|
||||
|
||||
if (resp->status == 0) {
|
||||
@@ -1073,6 +1088,7 @@ nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_fsinfores *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
*p++ = xdr_zero; /* no post_op_attr */
|
||||
|
||||
if (resp->status == 0) {
|
||||
@@ -1118,6 +1134,7 @@ nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
struct nfsd3_commitres *resp = rqstp->rq_resp;
|
||||
|
||||
*p++ = resp->status;
|
||||
p = encode_wcc_data(rqstp, p, &resp->fh);
|
||||
/* Write verifier */
|
||||
if (resp->status == 0) {
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sunrpc/addr.h>
|
||||
#include <linux/nfs_ssc.h>
|
||||
|
||||
#include "idmap.h"
|
||||
#include "cache.h"
|
||||
@@ -1247,7 +1248,7 @@ out_err:
|
||||
static void
|
||||
nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
|
||||
{
|
||||
nfs_sb_deactive(ss_mnt->mnt_sb);
|
||||
nfs_do_sb_deactive(ss_mnt->mnt_sb);
|
||||
mntput(ss_mnt);
|
||||
}
|
||||
|
||||
@@ -2165,7 +2166,7 @@ nfsd4_removexattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
static __be32
|
||||
nfsd4_proc_null(struct svc_rqst *rqstp)
|
||||
{
|
||||
return nfs_ok;
|
||||
return rpc_success;
|
||||
}
|
||||
|
||||
static inline void nfsd4_increment_op_stats(u32 opnum)
|
||||
@@ -2457,15 +2458,14 @@ encode_op:
|
||||
nfsd4_increment_op_stats(op->opnum);
|
||||
}
|
||||
|
||||
cstate->status = status;
|
||||
fh_put(current_fh);
|
||||
fh_put(save_fh);
|
||||
BUG_ON(cstate->replay_owner);
|
||||
out:
|
||||
cstate->status = status;
|
||||
/* Reset deferral mechanism for RPC deferrals */
|
||||
set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
|
||||
dprintk("nfsv4 compound returned %d\n", ntohl(status));
|
||||
return status;
|
||||
return rpc_success;
|
||||
}
|
||||
|
||||
#define op_encode_hdr_size (2)
|
||||
@@ -2591,6 +2591,20 @@ static inline u32 nfsd4_read_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
|
||||
return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32);
|
||||
}
|
||||
|
||||
static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
|
||||
{
|
||||
u32 maxcount = svc_max_payload(rqstp);
|
||||
u32 rlen = min(op->u.read.rd_length, maxcount);
|
||||
/*
|
||||
* If we detect that the file changed during hole encoding, then we
|
||||
* recover by encoding the remaining reply as data. This means we need
|
||||
* to set aside enough room to encode two data segments.
|
||||
*/
|
||||
u32 seg_len = 2 * (1 + 2 + 1);
|
||||
|
||||
return (op_encode_hdr_size + 2 + seg_len + XDR_QUADLEN(rlen)) * sizeof(__be32);
|
||||
}
|
||||
|
||||
static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
|
||||
{
|
||||
u32 maxcount = 0, rlen = 0;
|
||||
@@ -3163,6 +3177,13 @@ static const struct nfsd4_operation nfsd4_ops[] = {
|
||||
.op_name = "OP_COPY",
|
||||
.op_rsize_bop = nfsd4_copy_rsize,
|
||||
},
|
||||
[OP_READ_PLUS] = {
|
||||
.op_func = nfsd4_read,
|
||||
.op_release = nfsd4_read_release,
|
||||
.op_name = "OP_READ_PLUS",
|
||||
.op_rsize_bop = nfsd4_read_plus_rsize,
|
||||
.op_get_currentstateid = nfsd4_get_readstateid,
|
||||
},
|
||||
[OP_SEEK] = {
|
||||
.op_func = nfsd4_seek,
|
||||
.op_name = "OP_SEEK",
|
||||
@@ -3231,7 +3252,7 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
|
||||
if (!cstate->minorversion)
|
||||
return false;
|
||||
|
||||
if (cstate->spo_must_allowed == true)
|
||||
if (cstate->spo_must_allowed)
|
||||
return true;
|
||||
|
||||
opiter = resp->opcnt;
|
||||
@@ -3279,6 +3300,7 @@ struct nfsd4_voidargs { int dummy; };
|
||||
static const struct svc_procedure nfsd_procedures4[2] = {
|
||||
[NFSPROC4_NULL] = {
|
||||
.pc_func = nfsd4_proc_null,
|
||||
.pc_decode = nfs4svc_decode_voidarg,
|
||||
.pc_encode = nfs4svc_encode_voidres,
|
||||
.pc_argsize = sizeof(struct nfsd4_voidargs),
|
||||
.pc_ressize = sizeof(struct nfsd4_voidres),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user