forked from Minki/linux
A slow cycle for nfsd: mainly cleanup, including Neil's patch dropping
support for a filehandle format deprecated 20 years ago, and further xdr-related cleanup from Chuck. -----BEGIN PGP SIGNATURE----- iQJJBAABCAAzFiEEYtFWavXG9hZotryuJ5vNeUKO4b4FAmGMPYkVHGJmaWVsZHNA ZmllbGRzZXMub3JnAAoJECebzXlCjuG+JVwQAKbrpgbzl91u+T6W9MUGgQVzDpeP XIy3NxCu/4pZ8SToWF3trz71sskokmkPPaZyuISD2C8e4DxO5LQ3fJLhtS9CjRFB x4iZUxH7V2BoWrb5SY6TDWBEqaq4MY9f7tIbvUu5xpa0FIupLqJjYh2CP8vqtsbm lblQKXz4ao0jwDzSVimNnPcTccpB25VIzwHsSOszRhN4rTjMgyHoETx2cqJne5IU Tx/hH0UlpnwuQ7aVpcjMoKqIyUWDTMejx51pyZhHB47DVKL7HsnZvg59mTpXFcBx 29edvWT9yy1+w3nGkTYSkOgO9DyHvCbmQzIsvoYlmbZ2sdmTKK8Wuv2Ehcw3OfvL MXGmy2EXIhzvTZXyN6pL1bBwwNSxdqJhVSxvrPLz1EymIkxf/IDI8eyUicVXd3Vq K2xOn+CXyIbXWCU85ru8UA77r1+x//gSwqcJvtKUavbNJUwNt935CE2n3+o/0OL/ pToZ89nhcaRyDP1jJKA37K48VLNtBXzZZQlRovyLelNojam/kzZkXX8dI6oV9VD1 Ymjm0mbdZzwhE3C1HxKlxwZqhN+7YoyxMQuWjFMp28wxH+dkz/USCulKZ3/H+neD 0YBSgvwe92JqkZTW2AOjipL+beAuKJ4zsfCCl2XZig/rHGutiwOf2GfgdRmJM6AD 6aiufVWKNNRQef9y =yKBl -----END PGP SIGNATURE----- Merge tag 'nfsd-5.16' of git://linux-nfs.org/~bfields/linux Pull nfsd updates from Bruce Fields: "A slow cycle for nfsd: mainly cleanup, including Neil's patch dropping support for a filehandle format deprecated 20 years ago, and further xdr-related cleanup from Chuck" * tag 'nfsd-5.16' of git://linux-nfs.org/~bfields/linux: (26 commits) nfsd4: remove obselete comment nfsd: document server-to-server-copy parameters NFSD:fix boolreturn.cocci warning nfsd: update create verifier comment SUNRPC: Change return value type of .pc_encode SUNRPC: Replace the "__be32 *p" parameter to .pc_encode NFSD: Save location of NFSv4 COMPOUND status SUNRPC: Change return value type of .pc_decode SUNRPC: Replace the "__be32 *p" parameter to .pc_decode SUNRPC: De-duplicate .pc_release() call sites SUNRPC: Simplify the SVC dispatch code path SUNRPC: Capture value of xdr_buf::page_base SUNRPC: Add trace event when alloc_pages_bulk() makes no progress svcrdma: Split svcrmda_wc_{read,write} tracepoints svcrdma: Split the svcrdma_wc_send() tracepoint svcrdma: Split the svcrdma_wc_receive() tracepoint NFSD: Have legacy NFSD WRITE decoders use xdr_stream_subsegment() SUNRPC: xdr_stream_subsegment() must handle non-zero page_bases NFSD: Initialize pointer ni with NULL and not plain integer 0 NFSD: simplify struct nfsfh ...
This commit is contained in:
commit
38764c7340
@ -3253,6 +3253,19 @@
|
||||
driver. A non-zero value sets the minimum interval
|
||||
in seconds between layoutstats transmissions.
|
||||
|
||||
nfsd.inter_copy_offload_enable =
|
||||
[NFSv4.2] When set to 1, the server will support
|
||||
server-to-server copies for which this server is
|
||||
the destination of the copy.
|
||||
|
||||
nfsd.nfsd4_ssc_umount_timeout =
|
||||
[NFSv4.2] When used as the destination of a
|
||||
server-to-server copy, knfsd temporarily mounts
|
||||
the source server. It caches the mount in case
|
||||
it will be needed again, and discards it if not
|
||||
used for the number of milliseconds specified by
|
||||
this parameter.
|
||||
|
||||
nfsd.nfs4_disable_idmapping=
|
||||
[NFSv4] When set to the default of '1', the NFSv4
|
||||
server will return only numeric uids and gids to
|
||||
@ -3260,6 +3273,7 @@
|
||||
and gids from such clients. This is intended to ease
|
||||
migration from NFSv2/v3.
|
||||
|
||||
|
||||
nmi_backtrace.backtrace_idle [KNL]
|
||||
Dump stacks even of idle CPUs in response to an
|
||||
NMI stack-backtrace request.
|
||||
|
@ -11,3 +11,4 @@ NFS
|
||||
rpc-server-gss
|
||||
nfs41-server
|
||||
knfsd-stats
|
||||
reexport
|
||||
|
113
Documentation/filesystems/nfs/reexport.rst
Normal file
113
Documentation/filesystems/nfs/reexport.rst
Normal file
@ -0,0 +1,113 @@
|
||||
Reexporting NFS filesystems
|
||||
===========================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
It is possible to reexport an NFS filesystem over NFS. However, this
|
||||
feature comes with a number of limitations. Before trying it, we
|
||||
recommend some careful research to determine whether it will work for
|
||||
your purposes.
|
||||
|
||||
A discussion of current known limitations follows.
|
||||
|
||||
"fsid=" required, crossmnt broken
|
||||
---------------------------------
|
||||
|
||||
We require the "fsid=" export option on any reexport of an NFS
|
||||
filesystem. You can use "uuidgen -r" to generate a unique argument.
|
||||
|
||||
The "crossmnt" export does not propagate "fsid=", so it will not allow
|
||||
traversing into further nfs filesystems; if you wish to export nfs
|
||||
filesystems mounted under the exported filesystem, you'll need to export
|
||||
them explicitly, assigning each its own unique "fsid= option.
|
||||
|
||||
Reboot recovery
|
||||
---------------
|
||||
|
||||
The NFS protocol's normal reboot recovery mechanisms don't work for the
|
||||
case when the reexport server reboots. Clients will lose any locks
|
||||
they held before the reboot, and further IO will result in errors.
|
||||
Closing and reopening files should clear the errors.
|
||||
|
||||
Filehandle limits
|
||||
-----------------
|
||||
|
||||
If the original server uses an X byte filehandle for a given object, the
|
||||
reexport server's filehandle for the reexported object will be X+22
|
||||
bytes, rounded up to the nearest multiple of four bytes.
|
||||
|
||||
The result must fit into the RFC-mandated filehandle size limits:
|
||||
|
||||
+-------+-----------+
|
||||
| NFSv2 | 32 bytes |
|
||||
+-------+-----------+
|
||||
| NFSv3 | 64 bytes |
|
||||
+-------+-----------+
|
||||
| NFSv4 | 128 bytes |
|
||||
+-------+-----------+
|
||||
|
||||
So, for example, you will only be able to reexport a filesystem over
|
||||
NFSv2 if the original server gives you filehandles that fit in 10
|
||||
bytes--which is unlikely.
|
||||
|
||||
In general there's no way to know the maximum filehandle size given out
|
||||
by an NFS server without asking the server vendor.
|
||||
|
||||
But the following table gives a few examples. The first column is the
|
||||
typical length of the filehandle from a Linux server exporting the given
|
||||
filesystem, the second is the length after that nfs export is reexported
|
||||
by another Linux host:
|
||||
|
||||
+--------+-------------------+----------------+
|
||||
| | filehandle length | after reexport |
|
||||
+========+===================+================+
|
||||
| ext4: | 28 bytes | 52 bytes |
|
||||
+--------+-------------------+----------------+
|
||||
| xfs: | 32 bytes | 56 bytes |
|
||||
+--------+-------------------+----------------+
|
||||
| btrfs: | 40 bytes | 64 bytes |
|
||||
+--------+-------------------+----------------+
|
||||
|
||||
All will therefore fit in an NFSv3 or NFSv4 filehandle after reexport,
|
||||
but none are reexportable over NFSv2.
|
||||
|
||||
Linux server filehandles are a bit more complicated than this, though;
|
||||
for example:
|
||||
|
||||
- The (non-default) "subtreecheck" export option generally
|
||||
requires another 4 to 8 bytes in the filehandle.
|
||||
- If you export a subdirectory of a filesystem (instead of
|
||||
exporting the filesystem root), that also usually adds 4 to 8
|
||||
bytes.
|
||||
- If you export over NFSv2, knfsd usually uses a shorter
|
||||
filesystem identifier that saves 8 bytes.
|
||||
- The root directory of an export uses a filehandle that is
|
||||
shorter.
|
||||
|
||||
As you can see, the 128-byte NFSv4 filehandle is large enough that
|
||||
you're unlikely to have trouble using NFSv4 to reexport any filesystem
|
||||
exported from a Linux server. In general, if the original server is
|
||||
something that also supports NFSv3, you're *probably* OK. Re-exporting
|
||||
over NFSv3 may be dicier, and reexporting over NFSv2 will probably
|
||||
never work.
|
||||
|
||||
For more details of Linux filehandle structure, the best reference is
|
||||
the source code and comments; see in particular:
|
||||
|
||||
- include/linux/exportfs.h:enum fid_type
|
||||
- include/uapi/linux/nfsd/nfsfh.h:struct nfs_fhbase_new
|
||||
- fs/nfsd/nfsfh.c:set_version_and_fsid_type
|
||||
- fs/nfs/export.c:nfs_encode_fh
|
||||
|
||||
Open DENY bits ignored
|
||||
----------------------
|
||||
|
||||
NFS since NFSv4 supports ALLOW and DENY bits taken from Windows, which
|
||||
allow you, for example, to open a file in a mode which forbids other
|
||||
read opens or write opens. The Linux client doesn't use them, and the
|
||||
server's support has always been incomplete: they are enforced only
|
||||
against other NFS users, not against processes accessing the exported
|
||||
filesystem locally. A reexport server will also not pass them along to
|
||||
the original server, so they will not be enforced between clients of
|
||||
different reexport servers.
|
@ -780,11 +780,9 @@ module_exit(exit_nlm);
|
||||
static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp)
|
||||
{
|
||||
const struct svc_procedure *procp = rqstp->rq_procinfo;
|
||||
struct kvec *argv = rqstp->rq_arg.head;
|
||||
struct kvec *resv = rqstp->rq_res.head;
|
||||
|
||||
svcxdr_init_decode(rqstp);
|
||||
if (!procp->pc_decode(rqstp, argv->iov_base))
|
||||
if (!procp->pc_decode(rqstp, &rqstp->rq_arg_stream))
|
||||
goto out_decode_err;
|
||||
|
||||
*statp = procp->pc_func(rqstp);
|
||||
@ -794,7 +792,7 @@ static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp)
|
||||
return 1;
|
||||
|
||||
svcxdr_init_encode(rqstp);
|
||||
if (!procp->pc_encode(rqstp, resv->iov_base + resv->iov_len))
|
||||
if (!procp->pc_encode(rqstp, &rqstp->rq_res_stream))
|
||||
goto out_encode_err;
|
||||
|
||||
return 1;
|
||||
|
152
fs/lockd/xdr.c
152
fs/lockd/xdr.c
@ -145,137 +145,131 @@ svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
|
||||
* Decode Call arguments
|
||||
*/
|
||||
|
||||
int
|
||||
nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
u32 exclusive;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
||||
return 0;
|
||||
return false;
|
||||
if (exclusive)
|
||||
argp->lock.fl.fl_type = F_WRLCK;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
u32 exclusive;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
||||
return 0;
|
||||
return false;
|
||||
if (exclusive)
|
||||
argp->lock.fl.fl_type = F_WRLCK;
|
||||
if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
argp->monitor = 1; /* monitor client by default */
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
u32 exclusive;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
||||
return 0;
|
||||
return false;
|
||||
if (exclusive)
|
||||
argp->lock.fl.fl_type = F_WRLCK;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
||||
return 0;
|
||||
return false;
|
||||
argp->lock.fl.fl_type = F_UNLCK;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_res *resp = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &resp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_stats(xdr, &resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_reboot *argp = rqstp->rq_argp;
|
||||
__be32 *p;
|
||||
u32 len;
|
||||
|
||||
if (xdr_stream_decode_u32(xdr, &len) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (len > SM_MAXSTRLEN)
|
||||
return 0;
|
||||
return false;
|
||||
p = xdr_inline_decode(xdr, len);
|
||||
if (!p)
|
||||
return 0;
|
||||
return false;
|
||||
argp->len = len;
|
||||
argp->mon = (char *)p;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
|
||||
if (!p)
|
||||
return 0;
|
||||
return false;
|
||||
memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
struct nlm_lock *lock = &argp->lock;
|
||||
|
||||
@ -284,35 +278,34 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
lock->svid = ~(u32)0;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_fhandle(xdr, &lock->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_owner(xdr, &lock->oh))
|
||||
return 0;
|
||||
return false;
|
||||
/* XXX: Range checks are missing in the original code */
|
||||
if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
struct nlm_lock *lock = &argp->lock;
|
||||
|
||||
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -320,45 +313,42 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
|
||||
* Encode Reply results
|
||||
*/
|
||||
|
||||
int
|
||||
nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nlm_res *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_cookie(xdr, &resp->cookie) &&
|
||||
svcxdr_encode_testrply(xdr, resp);
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nlm_res *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_cookie(xdr, &resp->cookie) &&
|
||||
svcxdr_encode_stats(xdr, resp->status);
|
||||
}
|
||||
|
||||
int
|
||||
nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlmsvc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nlm_res *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_cookie(xdr, &resp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_stats(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
/* sequence */
|
||||
if (xdr_stream_encode_u32(xdr, 0) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
153
fs/lockd/xdr4.c
153
fs/lockd/xdr4.c
@ -144,136 +144,131 @@ svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
|
||||
* Decode Call arguments
|
||||
*/
|
||||
|
||||
int
|
||||
nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
u32 exclusive;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
||||
return 0;
|
||||
return false;
|
||||
if (exclusive)
|
||||
argp->lock.fl.fl_type = F_WRLCK;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
u32 exclusive;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
||||
return 0;
|
||||
return false;
|
||||
if (exclusive)
|
||||
argp->lock.fl.fl_type = F_WRLCK;
|
||||
if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
argp->monitor = 1; /* monitor client by default */
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
u32 exclusive;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
||||
return 0;
|
||||
return false;
|
||||
if (exclusive)
|
||||
argp->lock.fl.fl_type = F_WRLCK;
|
||||
return 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_lock(xdr, &argp->lock))
|
||||
return 0;
|
||||
return false;
|
||||
argp->lock.fl.fl_type = F_UNLCK;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_res *resp = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &resp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_stats(xdr, &resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_reboot *argp = rqstp->rq_argp;
|
||||
__be32 *p;
|
||||
u32 len;
|
||||
|
||||
if (xdr_stream_decode_u32(xdr, &len) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (len > SM_MAXSTRLEN)
|
||||
return 0;
|
||||
return false;
|
||||
p = xdr_inline_decode(xdr, len);
|
||||
if (!p)
|
||||
return 0;
|
||||
return false;
|
||||
argp->len = len;
|
||||
argp->mon = (char *)p;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
|
||||
if (!p)
|
||||
return 0;
|
||||
return false;
|
||||
memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
struct nlm_lock *lock = &argp->lock;
|
||||
|
||||
@ -282,35 +277,34 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
lock->svid = ~(u32)0;
|
||||
|
||||
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_fhandle(xdr, &lock->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_owner(xdr, &lock->oh))
|
||||
return 0;
|
||||
return false;
|
||||
/* XXX: Range checks are missing in the original code */
|
||||
if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nlm_args *argp = rqstp->rq_argp;
|
||||
struct nlm_lock *lock = &argp->lock;
|
||||
|
||||
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -318,45 +312,42 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
|
||||
* Encode Reply results
|
||||
*/
|
||||
|
||||
int
|
||||
nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nlm_res *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_cookie(xdr, &resp->cookie) &&
|
||||
svcxdr_encode_testrply(xdr, resp);
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nlm_res *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_cookie(xdr, &resp->cookie) &&
|
||||
svcxdr_encode_stats(xdr, resp->status);
|
||||
}
|
||||
|
||||
int
|
||||
nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nlm4svc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nlm_res *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_cookie(xdr, &resp->cookie))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_stats(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
/* sequence */
|
||||
if (xdr_stream_encode_u32(xdr, 0) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
@ -67,9 +67,9 @@ static __be32 nfs4_callback_null(struct svc_rqst *rqstp)
|
||||
* svc_process_common() looks for an XDR encoder to know when
|
||||
* not to drop a Reply.
|
||||
*/
|
||||
static int nfs4_encode_void(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool nfs4_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
return xdr_ressize_check(rqstp, p);
|
||||
return true;
|
||||
}
|
||||
|
||||
static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len,
|
||||
|
@ -61,7 +61,7 @@ nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
|
||||
goto out_error;
|
||||
|
||||
fl->fh.size = fhp->fh_handle.fh_size;
|
||||
memcpy(fl->fh.data, &fhp->fh_handle.fh_base, fl->fh.size);
|
||||
memcpy(fl->fh.data, &fhp->fh_handle.fh_raw, fl->fh.size);
|
||||
|
||||
/* Give whole file layout segments */
|
||||
seg->offset = 0;
|
||||
|
@ -35,7 +35,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
|
||||
/* must initialize before using! but maxsize doesn't matter */
|
||||
fh_init(&fh,0);
|
||||
fh.fh_handle.fh_size = f->size;
|
||||
memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
|
||||
memcpy(&fh.fh_handle.fh_raw, f->data, f->size);
|
||||
fh.fh_export = NULL;
|
||||
|
||||
access = (mode == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ;
|
||||
|
@ -188,51 +188,51 @@ out:
|
||||
* XDR decode functions
|
||||
*/
|
||||
|
||||
static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_getaclargs *argp = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_fhandle(xdr, &argp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_setaclargs *argp = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_fhandle(xdr, &argp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (argp->mask & ~NFS_ACL_MASK)
|
||||
return 0;
|
||||
return false;
|
||||
if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_ACL) ?
|
||||
&argp->acl_access : NULL))
|
||||
return 0;
|
||||
return false;
|
||||
if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_DFACL) ?
|
||||
&argp->acl_default : NULL))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_accessargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_fhandle(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->access) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -240,9 +240,9 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
*/
|
||||
|
||||
/* GETACL */
|
||||
static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_getaclres *resp = rqstp->rq_resp;
|
||||
struct dentry *dentry = resp->fh.fh_dentry;
|
||||
struct inode *inode;
|
||||
@ -280,9 +280,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
}
|
||||
|
||||
/* ACCESS */
|
||||
static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_accessres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_stat(xdr, resp->status))
|
||||
|
@ -127,38 +127,38 @@ out:
|
||||
* XDR decode functions
|
||||
*/
|
||||
|
||||
static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_getaclargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->mask) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_setaclargs *argp = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_nfs_fh3(xdr, &argp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (argp->mask & ~NFS_ACL_MASK)
|
||||
return 0;
|
||||
return false;
|
||||
if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_ACL) ?
|
||||
&argp->acl_access : NULL))
|
||||
return 0;
|
||||
return false;
|
||||
if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_DFACL) ?
|
||||
&argp->acl_default : NULL))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -166,9 +166,9 @@ static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
*/
|
||||
|
||||
/* GETACL */
|
||||
static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfs3svc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_getaclres *resp = rqstp->rq_resp;
|
||||
struct dentry *dentry = resp->fh.fh_dentry;
|
||||
struct kvec *head = rqstp->rq_res.head;
|
||||
@ -178,14 +178,14 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
int w;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
inode = d_inode(dentry);
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_u32(xdr, resp->mask) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
base = (char *)xdr->p - (char *)head->iov_base;
|
||||
|
||||
@ -194,7 +194,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
(resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
|
||||
while (w > 0) {
|
||||
if (!*(rqstp->rq_next_page++))
|
||||
return 0;
|
||||
return false;
|
||||
w -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
@ -207,20 +207,20 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
resp->mask & NFS_DFACL,
|
||||
NFS_ACL_DEFAULT);
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* SETACL */
|
||||
static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p)
|
||||
static bool
|
||||
nfs3svc_encode_setaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_attrstat *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_nfsstat3(xdr, resp->status) &&
|
||||
|
@ -201,8 +201,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
|
||||
|
||||
fh_copy(&resp->fh, &argp->fh);
|
||||
resp->committed = argp->stable;
|
||||
nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
|
||||
&argp->first, cnt);
|
||||
nvecs = svc_fill_write_vector(rqstp, &argp->payload);
|
||||
if (!nvecs) {
|
||||
resp->status = nfserr_io;
|
||||
goto out;
|
||||
|
@ -92,7 +92,7 @@ svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)
|
||||
return false;
|
||||
fh_init(fhp, NFS3_FHSIZE);
|
||||
fhp->fh_handle.fh_size = size;
|
||||
memcpy(&fhp->fh_handle.fh_base, p, size);
|
||||
memcpy(&fhp->fh_handle.fh_raw, p, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -131,7 +131,7 @@ svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
|
||||
*p++ = cpu_to_be32(size);
|
||||
if (size)
|
||||
p[XDR_QUADLEN(size) - 1] = 0;
|
||||
memcpy(p, &fhp->fh_handle.fh_base, size);
|
||||
memcpy(p, &fhp->fh_handle.fh_raw, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -556,19 +556,17 @@ void fill_post_wcc(struct svc_fh *fhp)
|
||||
* XDR decode functions
|
||||
*/
|
||||
|
||||
int
|
||||
nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_fhandle *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_nfs_fh3(xdr, &args->fh);
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_sattrargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_nfs_fh3(xdr, &args->fh) &&
|
||||
@ -576,96 +574,83 @@ nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
svcxdr_decode_sattrguard3(xdr, args);
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_diropargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len);
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_accessargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->access) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_readargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_writeargs *args = rqstp->rq_argp;
|
||||
u32 max_blocksize = svc_max_payload(rqstp);
|
||||
struct kvec *head = rqstp->rq_arg.head;
|
||||
struct kvec *tail = rqstp->rq_arg.tail;
|
||||
size_t remaining;
|
||||
|
||||
if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->stable) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* opaque data */
|
||||
if (xdr_stream_decode_u32(xdr, &args->len) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* request sanity */
|
||||
if (args->count != args->len)
|
||||
return 0;
|
||||
remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
|
||||
remaining -= xdr_stream_pos(xdr);
|
||||
if (remaining < xdr_align_size(args->len))
|
||||
return 0;
|
||||
return false;
|
||||
if (args->count > max_blocksize) {
|
||||
args->count = max_blocksize;
|
||||
args->len = max_blocksize;
|
||||
}
|
||||
if (!xdr_stream_subsegment(xdr, &args->payload, args->count))
|
||||
return false;
|
||||
|
||||
args->first.iov_base = xdr->p;
|
||||
args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_createargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->createmode) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
switch (args->createmode) {
|
||||
case NFS3_CREATE_UNCHECKED:
|
||||
case NFS3_CREATE_GUARDED:
|
||||
@ -673,18 +658,17 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
case NFS3_CREATE_EXCLUSIVE:
|
||||
args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE);
|
||||
if (!args->verf)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_createargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_diropargs3(xdr, &args->fh,
|
||||
@ -692,44 +676,42 @@ nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_symlinkargs *args = rqstp->rq_argp;
|
||||
struct kvec *head = rqstp->rq_arg.head;
|
||||
struct kvec *tail = rqstp->rq_arg.tail;
|
||||
size_t remaining;
|
||||
|
||||
if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* request sanity */
|
||||
remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
|
||||
remaining -= xdr_stream_pos(xdr);
|
||||
if (remaining < xdr_align_size(args->tlen))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
args->first.iov_base = xdr->p;
|
||||
args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_mknodargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->ftype) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
switch (args->ftype) {
|
||||
case NF3CHR:
|
||||
case NF3BLK:
|
||||
@ -743,16 +725,15 @@ nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
/* Valid XDR but illegal file types */
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_renameargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_diropargs3(xdr, &args->ffh,
|
||||
@ -761,10 +742,9 @@ nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
&args->tname, &args->tlen);
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_linkargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_nfs_fh3(xdr, &args->ffh) &&
|
||||
@ -772,62 +752,59 @@ nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
&args->tname, &args->tlen);
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_readdirargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
|
||||
if (!args->verf)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_readdirargs *args = rqstp->rq_argp;
|
||||
u32 dircount;
|
||||
|
||||
if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
|
||||
if (!args->verf)
|
||||
return 0;
|
||||
return false;
|
||||
/* dircount is ignored */
|
||||
if (xdr_stream_decode_u32(xdr, &dircount) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd3_commitargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -835,30 +812,28 @@ nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
*/
|
||||
|
||||
/* GETATTR */
|
||||
int
|
||||
nfs3svc_encode_getattrres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_attrstat *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime);
|
||||
if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* SETATTR, REMOVE, RMDIR */
|
||||
int
|
||||
nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_attrstat *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_nfsstat3(xdr, resp->status) &&
|
||||
@ -866,174 +841,168 @@ nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p)
|
||||
}
|
||||
|
||||
/* LOOKUP */
|
||||
int nfs3svc_encode_lookupres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_diropres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ACCESS */
|
||||
int
|
||||
nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_accessres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_u32(xdr, resp->access) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* READLINK */
|
||||
int
|
||||
nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_readlinkres *resp = rqstp->rq_resp;
|
||||
struct kvec *head = rqstp->rq_res.head;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_u32(xdr, resp->len) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
xdr_write_pages(xdr, resp->pages, 0, resp->len);
|
||||
if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* READ */
|
||||
int
|
||||
nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_readres *resp = rqstp->rq_resp;
|
||||
struct kvec *head = rqstp->rq_res.head;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_u32(xdr, resp->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_bool(xdr, resp->eof) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_u32(xdr, resp->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base,
|
||||
resp->count);
|
||||
if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* WRITE */
|
||||
int
|
||||
nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_writeres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_u32(xdr, resp->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_u32(xdr, resp->committed) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_writeverf3(xdr, resp->verf))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* CREATE, MKDIR, SYMLINK, MKNOD */
|
||||
int
|
||||
nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_diropres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* RENAME */
|
||||
int
|
||||
nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_renameres *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_nfsstat3(xdr, resp->status) &&
|
||||
@ -1042,10 +1011,9 @@ nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p)
|
||||
}
|
||||
|
||||
/* LINK */
|
||||
int
|
||||
nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_linkres *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_nfsstat3(xdr, resp->status) &&
|
||||
@ -1054,34 +1022,33 @@ nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p)
|
||||
}
|
||||
|
||||
/* READDIR */
|
||||
int
|
||||
nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_readdirres *resp = rqstp->rq_resp;
|
||||
struct xdr_buf *dirlist = &resp->dirlist;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_cookieverf3(xdr, resp->verf))
|
||||
return 0;
|
||||
return false;
|
||||
xdr_write_pages(xdr, dirlist->pages, 0, dirlist->len);
|
||||
/* no more entries */
|
||||
if (xdr_stream_encode_item_absent(xdr) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static __be32
|
||||
@ -1308,27 +1275,26 @@ svcxdr_encode_fsstat3resok(struct xdr_stream *xdr,
|
||||
}
|
||||
|
||||
/* FSSTAT */
|
||||
int
|
||||
nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_fsstatres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_fsstat3resok(xdr, resp))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1355,27 +1321,26 @@ svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr,
|
||||
}
|
||||
|
||||
/* FSINFO */
|
||||
int
|
||||
nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_fsinfores *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_fsinfo3resok(xdr, resp))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1398,51 +1363,49 @@ svcxdr_encode_pathconf3resok(struct xdr_stream *xdr,
|
||||
}
|
||||
|
||||
/* PATHCONF */
|
||||
int
|
||||
nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_pathconfres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_pathconf3resok(xdr, resp))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* COMMIT */
|
||||
int
|
||||
nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd3_commitres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_writeverf3(xdr, resp->verf))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -121,7 +121,7 @@ static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh)
|
||||
|
||||
BUG_ON(length > NFS4_FHSIZE);
|
||||
p = xdr_reserve_space(xdr, 4 + length);
|
||||
xdr_encode_opaque(p, &fh->fh_base, length);
|
||||
xdr_encode_opaque(p, &fh->fh_raw, length);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -519,7 +519,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
fh_put(&cstate->current_fh);
|
||||
cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
|
||||
memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
|
||||
memcpy(&cstate->current_fh.fh_handle.fh_raw, putfh->pf_fhval,
|
||||
putfh->pf_fhlen);
|
||||
ret = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
|
||||
#ifdef CONFIG_NFSD_V4_2_INTER_SSC
|
||||
@ -1033,8 +1033,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
write->wr_how_written = write->wr_stable_how;
|
||||
|
||||
nvecs = svc_fill_write_vector(rqstp, write->wr_payload.pages,
|
||||
write->wr_payload.head, write->wr_buflen);
|
||||
nvecs = svc_fill_write_vector(rqstp, &write->wr_payload);
|
||||
WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
|
||||
|
||||
status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf,
|
||||
@ -1178,7 +1177,7 @@ extern void nfs_sb_deactive(struct super_block *sb);
|
||||
static __be32 nfsd4_ssc_setup_dul(struct nfsd_net *nn, char *ipaddr,
|
||||
struct nfsd4_ssc_umount_item **retwork, struct vfsmount **ss_mnt)
|
||||
{
|
||||
struct nfsd4_ssc_umount_item *ni = 0;
|
||||
struct nfsd4_ssc_umount_item *ni = NULL;
|
||||
struct nfsd4_ssc_umount_item *work = NULL;
|
||||
struct nfsd4_ssc_umount_item *tmp;
|
||||
DEFINE_WAIT(wait);
|
||||
@ -1383,7 +1382,7 @@ nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
|
||||
s_fh = &cstate->save_fh;
|
||||
|
||||
copy->c_fh.size = s_fh->fh_handle.fh_size;
|
||||
memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_base, copy->c_fh.size);
|
||||
memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_raw, copy->c_fh.size);
|
||||
copy->stateid.seqid = cpu_to_be32(s_stid->si_generation);
|
||||
memcpy(copy->stateid.other, (void *)&s_stid->si_opaque,
|
||||
sizeof(stateid_opaque_t));
|
||||
@ -2462,11 +2461,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
|
||||
__be32 status;
|
||||
|
||||
resp->xdr = &rqstp->rq_res_stream;
|
||||
resp->statusp = resp->xdr->p;
|
||||
|
||||
/* reserve space for: NFS status code */
|
||||
xdr_reserve_space(resp->xdr, XDR_UNIT);
|
||||
|
||||
resp->tagp = resp->xdr->p;
|
||||
/* reserve space for: taglen, tag, and opcnt */
|
||||
xdr_reserve_space(resp->xdr, XDR_UNIT * 2 + args->taglen);
|
||||
resp->taglen = args->taglen;
|
||||
|
@ -1010,7 +1010,7 @@ static int delegation_blocked(struct knfsd_fh *fh)
|
||||
}
|
||||
spin_unlock(&blocked_delegations_lock);
|
||||
}
|
||||
hash = jhash(&fh->fh_base, fh->fh_size, 0);
|
||||
hash = jhash(&fh->fh_raw, fh->fh_size, 0);
|
||||
if (test_bit(hash&255, bd->set[0]) &&
|
||||
test_bit((hash>>8)&255, bd->set[0]) &&
|
||||
test_bit((hash>>16)&255, bd->set[0]))
|
||||
@ -1029,7 +1029,7 @@ static void block_delegations(struct knfsd_fh *fh)
|
||||
u32 hash;
|
||||
struct bloom_pair *bd = &blocked_delegations;
|
||||
|
||||
hash = jhash(&fh->fh_base, fh->fh_size, 0);
|
||||
hash = jhash(&fh->fh_raw, fh->fh_size, 0);
|
||||
|
||||
spin_lock(&blocked_delegations_lock);
|
||||
__set_bit(hash&255, bd->set[bd->new]);
|
||||
@ -5541,7 +5541,7 @@ static void nfsd4_ssc_shutdown_umount(struct nfsd_net *nn)
|
||||
static void nfsd4_ssc_expire_umount(struct nfsd_net *nn)
|
||||
{
|
||||
bool do_wakeup = false;
|
||||
struct nfsd4_ssc_umount_item *ni = 0;
|
||||
struct nfsd4_ssc_umount_item *ni = NULL;
|
||||
struct nfsd4_ssc_umount_item *tmp;
|
||||
|
||||
spin_lock(&nn->nfsd_ssc_lock);
|
||||
|
@ -2322,7 +2322,7 @@ nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
static bool
|
||||
nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
||||
{
|
||||
struct nfsd4_op *op;
|
||||
@ -2335,25 +2335,25 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
||||
int i;
|
||||
|
||||
if (xdr_stream_decode_u32(argp->xdr, &argp->taglen) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
max_reply += XDR_UNIT;
|
||||
argp->tag = NULL;
|
||||
if (unlikely(argp->taglen)) {
|
||||
if (argp->taglen > NFSD4_MAX_TAGLEN)
|
||||
return 0;
|
||||
return false;
|
||||
p = xdr_inline_decode(argp->xdr, argp->taglen);
|
||||
if (!p)
|
||||
return 0;
|
||||
return false;
|
||||
argp->tag = svcxdr_savemem(argp, p, argp->taglen);
|
||||
if (!argp->tag)
|
||||
return 0;
|
||||
return false;
|
||||
max_reply += xdr_align_size(argp->taglen);
|
||||
}
|
||||
|
||||
if (xdr_stream_decode_u32(argp->xdr, &argp->minorversion) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(argp->xdr, &argp->opcnt) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS
|
||||
@ -2361,14 +2361,14 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
||||
* nfsd4_proc can handle this is an NFS-level error.
|
||||
*/
|
||||
if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
|
||||
argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
|
||||
if (!argp->ops) {
|
||||
argp->ops = argp->iops;
|
||||
dprintk("nfsd: couldn't allocate room for COMPOUND\n");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2380,7 +2380,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
||||
op->replay = NULL;
|
||||
|
||||
if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (nfsd4_opnum_in_range(argp, op)) {
|
||||
op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
|
||||
if (op->status != nfs_ok)
|
||||
@ -2427,7 +2427,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
||||
if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack)
|
||||
clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags);
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
|
||||
@ -3110,7 +3110,7 @@ out_acl:
|
||||
p = xdr_reserve_space(xdr, fhp->fh_handle.fh_size + 4);
|
||||
if (!p)
|
||||
goto out_resource;
|
||||
p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base,
|
||||
p = xdr_encode_opaque(p, &fhp->fh_handle.fh_raw,
|
||||
fhp->fh_handle.fh_size);
|
||||
}
|
||||
if (bmval0 & FATTR4_WORD0_FILEID) {
|
||||
@ -3670,7 +3670,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh
|
||||
p = xdr_reserve_space(xdr, len + 4);
|
||||
if (!p)
|
||||
return nfserr_resource;
|
||||
p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, len);
|
||||
p = xdr_encode_opaque(p, &fhp->fh_handle.fh_raw, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5414,40 +5414,46 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct nfsd4_compoundargs *args = rqstp->rq_argp;
|
||||
|
||||
/* svcxdr_tmp_alloc */
|
||||
args->to_free = NULL;
|
||||
|
||||
args->xdr = &rqstp->rq_arg_stream;
|
||||
args->xdr = xdr;
|
||||
args->ops = args->iops;
|
||||
args->rqstp = rqstp;
|
||||
|
||||
return nfsd4_decode_compound(args);
|
||||
}
|
||||
|
||||
int
|
||||
nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfs4svc_encode_compoundres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct nfsd4_compoundres *resp = rqstp->rq_resp;
|
||||
struct xdr_buf *buf = resp->xdr->buf;
|
||||
struct xdr_buf *buf = xdr->buf;
|
||||
__be32 *p;
|
||||
|
||||
WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len +
|
||||
buf->tail[0].iov_len);
|
||||
|
||||
*p = resp->cstate.status;
|
||||
/*
|
||||
* Send buffer space for the following items is reserved
|
||||
* at the top of nfsd4_proc_compound().
|
||||
*/
|
||||
p = resp->statusp;
|
||||
|
||||
rqstp->rq_next_page = resp->xdr->page_ptr + 1;
|
||||
*p++ = resp->cstate.status;
|
||||
|
||||
rqstp->rq_next_page = xdr->page_ptr + 1;
|
||||
|
||||
p = resp->tagp;
|
||||
*p++ = htonl(resp->taglen);
|
||||
memcpy(p, resp->tag, resp->taglen);
|
||||
p += XDR_QUADLEN(resp->taglen);
|
||||
*p++ = htonl(resp->opcnt);
|
||||
|
||||
nfsd4_sequence_done(resp);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
@ -241,8 +241,8 @@ lru_put_end(struct nfsd_drc_bucket *b, struct svc_cacherep *rp)
|
||||
list_move_tail(&rp->c_lru, &b->lru_head);
|
||||
}
|
||||
|
||||
static long
|
||||
prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn)
|
||||
static long prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn,
|
||||
unsigned int max)
|
||||
{
|
||||
struct svc_cacherep *rp, *tmp;
|
||||
long freed = 0;
|
||||
@ -258,11 +258,17 @@ prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn)
|
||||
time_before(jiffies, rp->c_timestamp + RC_EXPIRE))
|
||||
break;
|
||||
nfsd_reply_cache_free_locked(b, rp, nn);
|
||||
freed++;
|
||||
if (max && freed++ > max)
|
||||
break;
|
||||
}
|
||||
return freed;
|
||||
}
|
||||
|
||||
static long nfsd_prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn)
|
||||
{
|
||||
return prune_bucket(b, nn, 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the LRU list and prune off entries that are older than RC_EXPIRE.
|
||||
* Also prune the oldest ones when the total exceeds the max number of entries.
|
||||
@ -279,7 +285,7 @@ prune_cache_entries(struct nfsd_net *nn)
|
||||
if (list_empty(&b->lru_head))
|
||||
continue;
|
||||
spin_lock(&b->cache_lock);
|
||||
freed += prune_bucket(b, nn);
|
||||
freed += prune_bucket(b, nn, 0);
|
||||
spin_unlock(&b->cache_lock);
|
||||
}
|
||||
return freed;
|
||||
@ -453,8 +459,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp)
|
||||
atomic_inc(&nn->num_drc_entries);
|
||||
nfsd_stats_drc_mem_usage_add(nn, sizeof(*rp));
|
||||
|
||||
/* go ahead and prune the cache */
|
||||
prune_bucket(b, nn);
|
||||
nfsd_prune_bucket(b, nn);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&b->cache_lock);
|
||||
|
@ -395,12 +395,12 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
|
||||
auth_domain_put(dom);
|
||||
if (len)
|
||||
return len;
|
||||
|
||||
|
||||
mesg = buf;
|
||||
len = SIMPLE_TRANSACTION_LIMIT;
|
||||
qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
|
||||
qword_addhex(&mesg, &len, fh.fh_raw, fh.fh_size);
|
||||
mesg[-1] = '\n';
|
||||
return mesg - buf;
|
||||
return mesg - buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -78,8 +78,10 @@ extern const struct seq_operations nfs_exports_op;
|
||||
*/
|
||||
struct nfsd_voidargs { };
|
||||
struct nfsd_voidres { };
|
||||
int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p);
|
||||
int nfssvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p);
|
||||
bool nfssvc_decode_voidarg(struct svc_rqst *rqstp,
|
||||
struct xdr_stream *xdr);
|
||||
bool nfssvc_encode_voidres(struct svc_rqst *rqstp,
|
||||
struct xdr_stream *xdr);
|
||||
|
||||
/*
|
||||
* Function prototypes.
|
||||
|
167
fs/nfsd/nfsfh.c
167
fs/nfsd/nfsfh.c
@ -154,11 +154,12 @@ static inline __be32 check_pseudo_root(struct svc_rqst *rqstp,
|
||||
static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
|
||||
{
|
||||
struct knfsd_fh *fh = &fhp->fh_handle;
|
||||
struct fid *fid = NULL, sfid;
|
||||
struct fid *fid = NULL;
|
||||
struct svc_export *exp;
|
||||
struct dentry *dentry;
|
||||
int fileid_type;
|
||||
int data_left = fh->fh_size/4;
|
||||
int len;
|
||||
__be32 error;
|
||||
|
||||
error = nfserr_stale;
|
||||
@ -167,48 +168,35 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
|
||||
if (rqstp->rq_vers == 4 && fh->fh_size == 0)
|
||||
return nfserr_nofilehandle;
|
||||
|
||||
if (fh->fh_version == 1) {
|
||||
int len;
|
||||
if (fh->fh_version != 1)
|
||||
return error;
|
||||
|
||||
if (--data_left < 0)
|
||||
return error;
|
||||
if (fh->fh_auth_type != 0)
|
||||
return error;
|
||||
len = key_len(fh->fh_fsid_type) / 4;
|
||||
if (len == 0)
|
||||
return error;
|
||||
if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
|
||||
/* deprecated, convert to type 3 */
|
||||
len = key_len(FSID_ENCODE_DEV)/4;
|
||||
fh->fh_fsid_type = FSID_ENCODE_DEV;
|
||||
/*
|
||||
* struct knfsd_fh uses host-endian fields, which are
|
||||
* sometimes used to hold net-endian values. This
|
||||
* confuses sparse, so we must use __force here to
|
||||
* keep it from complaining.
|
||||
*/
|
||||
fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]),
|
||||
ntohl((__force __be32)fh->fh_fsid[1])));
|
||||
fh->fh_fsid[1] = fh->fh_fsid[2];
|
||||
}
|
||||
data_left -= len;
|
||||
if (data_left < 0)
|
||||
return error;
|
||||
exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_fsid);
|
||||
fid = (struct fid *)(fh->fh_fsid + len);
|
||||
} else {
|
||||
__u32 tfh[2];
|
||||
dev_t xdev;
|
||||
ino_t xino;
|
||||
|
||||
if (fh->fh_size != NFS_FHSIZE)
|
||||
return error;
|
||||
/* assume old filehandle format */
|
||||
xdev = old_decode_dev(fh->ofh_xdev);
|
||||
xino = u32_to_ino_t(fh->ofh_xino);
|
||||
mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
|
||||
exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
|
||||
if (--data_left < 0)
|
||||
return error;
|
||||
if (fh->fh_auth_type != 0)
|
||||
return error;
|
||||
len = key_len(fh->fh_fsid_type) / 4;
|
||||
if (len == 0)
|
||||
return error;
|
||||
if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
|
||||
/* deprecated, convert to type 3 */
|
||||
len = key_len(FSID_ENCODE_DEV)/4;
|
||||
fh->fh_fsid_type = FSID_ENCODE_DEV;
|
||||
/*
|
||||
* struct knfsd_fh uses host-endian fields, which are
|
||||
* sometimes used to hold net-endian values. This
|
||||
* confuses sparse, so we must use __force here to
|
||||
* keep it from complaining.
|
||||
*/
|
||||
fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]),
|
||||
ntohl((__force __be32)fh->fh_fsid[1])));
|
||||
fh->fh_fsid[1] = fh->fh_fsid[2];
|
||||
}
|
||||
data_left -= len;
|
||||
if (data_left < 0)
|
||||
return error;
|
||||
exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_fsid);
|
||||
fid = (struct fid *)(fh->fh_fsid + len);
|
||||
|
||||
error = nfserr_stale;
|
||||
if (IS_ERR(exp)) {
|
||||
@ -253,18 +241,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
|
||||
if (rqstp->rq_vers > 2)
|
||||
error = nfserr_badhandle;
|
||||
|
||||
if (fh->fh_version != 1) {
|
||||
sfid.i32.ino = fh->ofh_ino;
|
||||
sfid.i32.gen = fh->ofh_generation;
|
||||
sfid.i32.parent_ino = fh->ofh_dirino;
|
||||
fid = &sfid;
|
||||
data_left = 3;
|
||||
if (fh->ofh_dirino == 0)
|
||||
fileid_type = FILEID_INO32_GEN;
|
||||
else
|
||||
fileid_type = FILEID_INO32_GEN_PARENT;
|
||||
} else
|
||||
fileid_type = fh->fh_fileid_type;
|
||||
fileid_type = fh->fh_fileid_type;
|
||||
|
||||
if (fileid_type == FILEID_ROOT)
|
||||
dentry = dget(exp->ex_path.dentry);
|
||||
@ -452,20 +429,6 @@ static void _fh_update(struct svc_fh *fhp, struct svc_export *exp,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* for composing old style file handles
|
||||
*/
|
||||
static inline void _fh_update_old(struct dentry *dentry,
|
||||
struct svc_export *exp,
|
||||
struct knfsd_fh *fh)
|
||||
{
|
||||
fh->ofh_ino = ino_t_to_u32(d_inode(dentry)->i_ino);
|
||||
fh->ofh_generation = d_inode(dentry)->i_generation;
|
||||
if (d_is_dir(dentry) ||
|
||||
(exp->ex_flags & NFSEXP_NOSUBTREECHECK))
|
||||
fh->ofh_dirino = 0;
|
||||
}
|
||||
|
||||
static bool is_root_export(struct svc_export *exp)
|
||||
{
|
||||
return exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root;
|
||||
@ -562,9 +525,6 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
|
||||
/* ref_fh is a reference file handle.
|
||||
* if it is non-null and for the same filesystem, then we should compose
|
||||
* a filehandle which is of the same version, where possible.
|
||||
* Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
|
||||
* Then create a 32byte filehandle using nfs_fhbase_old
|
||||
*
|
||||
*/
|
||||
|
||||
struct inode * inode = d_inode(dentry);
|
||||
@ -600,35 +560,21 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
|
||||
fhp->fh_dentry = dget(dentry); /* our internal copy */
|
||||
fhp->fh_export = exp_get(exp);
|
||||
|
||||
if (fhp->fh_handle.fh_version == 0xca) {
|
||||
/* old style filehandle please */
|
||||
memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
|
||||
fhp->fh_handle.fh_size = NFS_FHSIZE;
|
||||
fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
|
||||
fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev);
|
||||
fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
|
||||
fhp->fh_handle.ofh_xino =
|
||||
ino_t_to_u32(d_inode(exp->ex_path.dentry)->i_ino);
|
||||
fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry));
|
||||
if (inode)
|
||||
_fh_update_old(dentry, exp, &fhp->fh_handle);
|
||||
} else {
|
||||
fhp->fh_handle.fh_size =
|
||||
key_len(fhp->fh_handle.fh_fsid_type) + 4;
|
||||
fhp->fh_handle.fh_auth_type = 0;
|
||||
fhp->fh_handle.fh_size =
|
||||
key_len(fhp->fh_handle.fh_fsid_type) + 4;
|
||||
fhp->fh_handle.fh_auth_type = 0;
|
||||
|
||||
mk_fsid(fhp->fh_handle.fh_fsid_type,
|
||||
fhp->fh_handle.fh_fsid,
|
||||
ex_dev,
|
||||
d_inode(exp->ex_path.dentry)->i_ino,
|
||||
exp->ex_fsid, exp->ex_uuid);
|
||||
mk_fsid(fhp->fh_handle.fh_fsid_type,
|
||||
fhp->fh_handle.fh_fsid,
|
||||
ex_dev,
|
||||
d_inode(exp->ex_path.dentry)->i_ino,
|
||||
exp->ex_fsid, exp->ex_uuid);
|
||||
|
||||
if (inode)
|
||||
_fh_update(fhp, exp, dentry);
|
||||
if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) {
|
||||
fh_put(fhp);
|
||||
return nfserr_opnotsupp;
|
||||
}
|
||||
if (inode)
|
||||
_fh_update(fhp, exp, dentry);
|
||||
if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) {
|
||||
fh_put(fhp);
|
||||
return nfserr_opnotsupp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -649,16 +595,12 @@ fh_update(struct svc_fh *fhp)
|
||||
dentry = fhp->fh_dentry;
|
||||
if (d_really_is_negative(dentry))
|
||||
goto out_negative;
|
||||
if (fhp->fh_handle.fh_version != 1) {
|
||||
_fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
|
||||
} else {
|
||||
if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
|
||||
return 0;
|
||||
if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
|
||||
return 0;
|
||||
|
||||
_fh_update(fhp, fhp->fh_export, dentry);
|
||||
if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID)
|
||||
return nfserr_opnotsupp;
|
||||
}
|
||||
_fh_update(fhp, fhp->fh_export, dentry);
|
||||
if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID)
|
||||
return nfserr_opnotsupp;
|
||||
return 0;
|
||||
out_bad:
|
||||
printk(KERN_ERR "fh_update: fh not verified!\n");
|
||||
@ -698,16 +640,11 @@ fh_put(struct svc_fh *fhp)
|
||||
char * SVCFH_fmt(struct svc_fh *fhp)
|
||||
{
|
||||
struct knfsd_fh *fh = &fhp->fh_handle;
|
||||
static char buf[2+1+1+64*3+1];
|
||||
|
||||
static char buf[80];
|
||||
sprintf(buf, "%d: %08x %08x %08x %08x %08x %08x",
|
||||
fh->fh_size,
|
||||
fh->fh_base.fh_pad[0],
|
||||
fh->fh_base.fh_pad[1],
|
||||
fh->fh_base.fh_pad[2],
|
||||
fh->fh_base.fh_pad[3],
|
||||
fh->fh_base.fh_pad[4],
|
||||
fh->fh_base.fh_pad[5]);
|
||||
if (fh->fh_size < 0 || fh->fh_size> 64)
|
||||
return "bad-fh";
|
||||
sprintf(buf, "%d: %*ph", fh->fh_size, fh->fh_size, fh->fh_raw);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -10,9 +10,56 @@
|
||||
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/sunrpc/svc.h>
|
||||
#include <uapi/linux/nfsd/nfsfh.h>
|
||||
#include <linux/iversion.h>
|
||||
#include <linux/exportfs.h>
|
||||
#include <linux/nfs4.h>
|
||||
|
||||
/*
|
||||
* The file handle starts with a sequence of four-byte words.
|
||||
* The first word contains a version number (1) and three descriptor bytes
|
||||
* that tell how the remaining 3 variable length fields should be handled.
|
||||
* These three bytes are auth_type, fsid_type and fileid_type.
|
||||
*
|
||||
* All four-byte values are in host-byte-order.
|
||||
*
|
||||
* The auth_type field is deprecated and must be set to 0.
|
||||
*
|
||||
* The fsid_type identifies how the filesystem (or export point) is
|
||||
* encoded.
|
||||
* Current values:
|
||||
* 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
|
||||
* NOTE: we cannot use the kdev_t device id value, because kdev_t.h
|
||||
* says we mustn't. We must break it up and reassemble.
|
||||
* 1 - 4 byte user specified identifier
|
||||
* 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
|
||||
* 3 - 4 byte device id, encoded for user-space, 4 byte inode number
|
||||
* 4 - 4 byte inode number and 4 byte uuid
|
||||
* 5 - 8 byte uuid
|
||||
* 6 - 16 byte uuid
|
||||
* 7 - 8 byte inode number and 16 byte uuid
|
||||
*
|
||||
* The fileid_type identifies how the file within the filesystem is encoded.
|
||||
* The values for this field are filesystem specific, exccept that
|
||||
* filesystems must not use the values '0' or '0xff'. 'See enum fid_type'
|
||||
* in include/linux/exportfs.h for currently registered values.
|
||||
*/
|
||||
|
||||
struct knfsd_fh {
|
||||
unsigned int fh_size; /*
|
||||
* Points to the current size while
|
||||
* building a new file handle.
|
||||
*/
|
||||
union {
|
||||
char fh_raw[NFS4_FHSIZE];
|
||||
struct {
|
||||
u8 fh_version; /* == 1 */
|
||||
u8 fh_auth_type; /* deprecated */
|
||||
u8 fh_fsid_type;
|
||||
u8 fh_fileid_type;
|
||||
u32 fh_fsid[]; /* flexible-array member */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
static inline __u32 ino_t_to_u32(ino_t ino)
|
||||
{
|
||||
@ -188,7 +235,7 @@ static inline void
|
||||
fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
|
||||
{
|
||||
dst->fh_size = src->fh_size;
|
||||
memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
|
||||
memcpy(&dst->fh_raw, &src->fh_raw, src->fh_size);
|
||||
}
|
||||
|
||||
static __inline__ struct svc_fh *
|
||||
@ -203,7 +250,7 @@ static inline bool fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
|
||||
{
|
||||
if (fh1->fh_size != fh2->fh_size)
|
||||
return false;
|
||||
if (memcmp(fh1->fh_base.fh_pad, fh2->fh_base.fh_pad, fh1->fh_size) != 0)
|
||||
if (memcmp(fh1->fh_raw, fh2->fh_raw, fh1->fh_size) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -227,7 +274,7 @@ static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
|
||||
*/
|
||||
static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh)
|
||||
{
|
||||
return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size);
|
||||
return ~crc32_le(0xFFFFFFFF, fh->fh_raw, fh->fh_size);
|
||||
}
|
||||
#else
|
||||
static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh)
|
||||
|
@ -234,8 +234,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
|
||||
SVCFH_fmt(&argp->fh),
|
||||
argp->len, argp->offset);
|
||||
|
||||
nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
|
||||
&argp->first, cnt);
|
||||
nvecs = svc_fill_write_vector(rqstp, &argp->payload);
|
||||
if (!nvecs) {
|
||||
resp->status = nfserr_io;
|
||||
goto out;
|
||||
|
@ -1004,9 +1004,6 @@ out:
|
||||
int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
|
||||
{
|
||||
const struct svc_procedure *proc = rqstp->rq_procinfo;
|
||||
struct kvec *argv = &rqstp->rq_arg.head[0];
|
||||
struct kvec *resv = &rqstp->rq_res.head[0];
|
||||
__be32 *p;
|
||||
|
||||
/*
|
||||
* Give the xdr decoder a chance to change this if it wants
|
||||
@ -1015,7 +1012,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
|
||||
rqstp->rq_cachetype = proc->pc_cachetype;
|
||||
|
||||
svcxdr_init_decode(rqstp);
|
||||
if (!proc->pc_decode(rqstp, argv->iov_base))
|
||||
if (!proc->pc_decode(rqstp, &rqstp->rq_arg_stream))
|
||||
goto out_decode_err;
|
||||
|
||||
switch (nfsd_cache_lookup(rqstp)) {
|
||||
@ -1031,14 +1028,13 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
|
||||
* Need to grab the location to store the status, as
|
||||
* NFSv4 does some encoding while processing
|
||||
*/
|
||||
p = resv->iov_base + resv->iov_len;
|
||||
svcxdr_init_encode(rqstp);
|
||||
|
||||
*statp = proc->pc_func(rqstp);
|
||||
if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags))
|
||||
goto out_update_drop;
|
||||
|
||||
if (!proc->pc_encode(rqstp, p))
|
||||
if (!proc->pc_encode(rqstp, &rqstp->rq_res_stream))
|
||||
goto out_encode_err;
|
||||
|
||||
nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
|
||||
@ -1065,29 +1061,29 @@ out_encode_err:
|
||||
/**
|
||||
* nfssvc_decode_voidarg - Decode void arguments
|
||||
* @rqstp: Server RPC transaction context
|
||||
* @p: buffer containing arguments to decode
|
||||
* @xdr: XDR stream positioned at arguments to decode
|
||||
*
|
||||
* Return values:
|
||||
* %0: Arguments were not valid
|
||||
* %1: Decoding was successful
|
||||
* %false: Arguments were not valid
|
||||
* %true: Decoding was successful
|
||||
*/
|
||||
int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool nfssvc_decode_voidarg(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfssvc_encode_voidres - Encode void results
|
||||
* @rqstp: Server RPC transaction context
|
||||
* @p: buffer in which to encode results
|
||||
* @xdr: XDR stream into which to encode results
|
||||
*
|
||||
* Return values:
|
||||
* %0: Local error while encoding
|
||||
* %1: Encoding was successful
|
||||
* %false: Local error while encoding
|
||||
* %true: Encoding was successful
|
||||
*/
|
||||
int nfssvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool nfssvc_encode_voidres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int nfsd_pool_stats_open(struct inode *inode, struct file *file)
|
||||
|
187
fs/nfsd/nfsxdr.c
187
fs/nfsd/nfsxdr.c
@ -64,7 +64,7 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp)
|
||||
if (!p)
|
||||
return false;
|
||||
fh_init(fhp, NFS_FHSIZE);
|
||||
memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
|
||||
memcpy(&fhp->fh_handle.fh_raw, p, NFS_FHSIZE);
|
||||
fhp->fh_handle.fh_size = NFS_FHSIZE;
|
||||
|
||||
return true;
|
||||
@ -78,7 +78,7 @@ svcxdr_encode_fhandle(struct xdr_stream *xdr, const struct svc_fh *fhp)
|
||||
p = xdr_reserve_space(xdr, NFS_FHSIZE);
|
||||
if (!p)
|
||||
return false;
|
||||
memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
|
||||
memcpy(p, &fhp->fh_handle.fh_raw, NFS_FHSIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -272,94 +272,81 @@ svcxdr_encode_fattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
||||
* XDR decode functions
|
||||
*/
|
||||
|
||||
int
|
||||
nfssvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_fhandle *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_fhandle(xdr, &args->fh);
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_sattrargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_fhandle(xdr, &args->fh) &&
|
||||
svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_diropargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_diropargs(xdr, &args->fh, &args->name, &args->len);
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_readargs *args = rqstp->rq_argp;
|
||||
u32 totalcount;
|
||||
|
||||
if (!svcxdr_decode_fhandle(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->offset) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
/* totalcount is ignored */
|
||||
if (xdr_stream_decode_u32(xdr, &totalcount) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_writeargs *args = rqstp->rq_argp;
|
||||
struct kvec *head = rqstp->rq_arg.head;
|
||||
struct kvec *tail = rqstp->rq_arg.tail;
|
||||
u32 beginoffset, totalcount;
|
||||
size_t remaining;
|
||||
|
||||
if (!svcxdr_decode_fhandle(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
/* beginoffset is ignored */
|
||||
if (xdr_stream_decode_u32(xdr, &beginoffset) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->offset) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
/* totalcount is ignored */
|
||||
if (xdr_stream_decode_u32(xdr, &totalcount) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* opaque data */
|
||||
if (xdr_stream_decode_u32(xdr, &args->len) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (args->len > NFSSVC_MAXBLKSIZE_V2)
|
||||
return 0;
|
||||
remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
|
||||
remaining -= xdr_stream_pos(xdr);
|
||||
if (remaining < xdr_align_size(args->len))
|
||||
return 0;
|
||||
args->first.iov_base = xdr->p;
|
||||
args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
|
||||
return false;
|
||||
if (!xdr_stream_subsegment(xdr, &args->payload, args->len))
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_createargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_diropargs(xdr, &args->fh,
|
||||
@ -367,10 +354,9 @@ nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_renameargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_diropargs(xdr, &args->ffh,
|
||||
@ -379,10 +365,9 @@ nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
&args->tname, &args->tlen);
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_linkargs *args = rqstp->rq_argp;
|
||||
|
||||
return svcxdr_decode_fhandle(xdr, &args->ffh) &&
|
||||
@ -390,178 +375,170 @@ nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
&args->tname, &args->tlen);
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_symlinkargs *args = rqstp->rq_argp;
|
||||
struct kvec *head = rqstp->rq_arg.head;
|
||||
|
||||
if (!svcxdr_decode_diropargs(xdr, &args->ffh, &args->fname, &args->flen))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (args->tlen == 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
|
||||
args->first.iov_base = xdr_inline_decode(xdr, args->tlen);
|
||||
if (!args->first.iov_base)
|
||||
return 0;
|
||||
return false;
|
||||
return svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
|
||||
struct nfsd_readdirargs *args = rqstp->rq_argp;
|
||||
|
||||
if (!svcxdr_decode_fhandle(xdr, &args->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->cookie) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(xdr, &args->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR encode functions
|
||||
*/
|
||||
|
||||
int
|
||||
nfssvc_encode_statres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_encode_statres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd_stat *resp = rqstp->rq_resp;
|
||||
|
||||
return svcxdr_encode_stat(xdr, resp->status);
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_encode_attrstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd_attrstat *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_stat(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_encode_diropres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd_diropres *resp = rqstp->rq_resp;
|
||||
|
||||
if (!svcxdr_encode_stat(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_fhandle(xdr, &resp->fh))
|
||||
return 0;
|
||||
return false;
|
||||
if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat))
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd_readlinkres *resp = rqstp->rq_resp;
|
||||
struct kvec *head = rqstp->rq_res.head;
|
||||
|
||||
if (!svcxdr_encode_stat(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (xdr_stream_encode_u32(xdr, resp->len) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
xdr_write_pages(xdr, &resp->page, 0, resp->len);
|
||||
if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd_readres *resp = rqstp->rq_resp;
|
||||
struct kvec *head = rqstp->rq_res.head;
|
||||
|
||||
if (!svcxdr_encode_stat(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat))
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_u32(xdr, resp->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base,
|
||||
resp->count);
|
||||
if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd_readdirres *resp = rqstp->rq_resp;
|
||||
struct xdr_buf *dirlist = &resp->dirlist;
|
||||
|
||||
if (!svcxdr_encode_stat(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
xdr_write_pages(xdr, dirlist->pages, 0, dirlist->len);
|
||||
/* no more entries */
|
||||
if (xdr_stream_encode_item_absent(xdr) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
|
||||
return 0;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p)
|
||||
bool
|
||||
nfssvc_encode_statfsres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_stream *xdr = &rqstp->rq_res_stream;
|
||||
struct nfsd_statfsres *resp = rqstp->rq_resp;
|
||||
struct kstatfs *stat = &resp->stats;
|
||||
__be32 *p;
|
||||
|
||||
if (!svcxdr_encode_stat(xdr, resp->status))
|
||||
return 0;
|
||||
return false;
|
||||
switch (resp->status) {
|
||||
case nfs_ok:
|
||||
p = xdr_reserve_space(xdr, XDR_UNIT * 5);
|
||||
if (!p)
|
||||
return 0;
|
||||
return false;
|
||||
*p++ = cpu_to_be32(NFSSVC_MAXBLKSIZE_V2);
|
||||
*p++ = cpu_to_be32(stat->f_bsize);
|
||||
*p++ = cpu_to_be32(stat->f_blocks);
|
||||
@ -570,7 +547,7 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p)
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,6 +244,7 @@ out_nfserr:
|
||||
* returned. Otherwise the covered directory is returned.
|
||||
* NOTE: this mountpoint crossing is not supported properly by all
|
||||
* clients and is explicitly disallowed for NFSv3
|
||||
* NeilBrown <neilb@cse.unsw.edu.au>
|
||||
*/
|
||||
__be32
|
||||
nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
|
||||
@ -729,9 +730,6 @@ __nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
|
||||
path.dentry = fhp->fh_dentry;
|
||||
inode = d_inode(path.dentry);
|
||||
|
||||
/* Disallow write access to files with the append-only bit set
|
||||
* or any access when mandatory locking enabled
|
||||
*/
|
||||
err = nfserr_perm;
|
||||
if (IS_APPEND(inode) && (may_flags & NFSD_MAY_WRITE))
|
||||
goto out;
|
||||
@ -1410,7 +1408,8 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
|
||||
if (nfsd_create_is_exclusive(createmode)) {
|
||||
/* solaris7 gets confused (bugid 4218508) if these have
|
||||
* the high bit set, so just clear the high bits. If this is
|
||||
* the high bit set, as do xfs filesystems without the
|
||||
* "bigtime" feature. So just clear the high bits. If this is
|
||||
* ever changed to use different attrs for storing the
|
||||
* verifier, then do_open_lookup() will also need to be fixed
|
||||
* accordingly.
|
||||
|
@ -33,7 +33,7 @@ struct nfsd_writeargs {
|
||||
svc_fh fh;
|
||||
__u32 offset;
|
||||
int len;
|
||||
struct kvec first;
|
||||
struct xdr_buf payload;
|
||||
};
|
||||
|
||||
struct nfsd_createargs {
|
||||
@ -141,23 +141,24 @@ union nfsd_xdrstore {
|
||||
#define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore)
|
||||
|
||||
|
||||
int nfssvc_decode_fhandleargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_sattrargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_diropargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_readargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_writeargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_createargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_renameargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_linkargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_encode_statres(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_encode_attrstatres(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_encode_diropres(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_encode_readlinkres(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_encode_readres(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_encode_statfsres(struct svc_rqst *, __be32 *);
|
||||
int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *);
|
||||
bool nfssvc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
|
||||
bool nfssvc_encode_statres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_encode_attrstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_encode_diropres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_encode_statfsres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfssvc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
|
||||
void nfssvc_encode_nfscookie(struct nfsd_readdirres *resp, u32 offset);
|
||||
int nfssvc_encode_entry(void *data, const char *name, int namlen,
|
||||
|
@ -40,7 +40,7 @@ struct nfsd3_writeargs {
|
||||
__u32 count;
|
||||
int stable;
|
||||
__u32 len;
|
||||
struct kvec first;
|
||||
struct xdr_buf payload;
|
||||
};
|
||||
|
||||
struct nfsd3_createargs {
|
||||
@ -265,36 +265,37 @@ union nfsd3_xdrstore {
|
||||
|
||||
#define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)
|
||||
|
||||
int nfs3svc_decode_fhandleargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_accessargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_readargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_writeargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_createargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_mkdirargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_mknodargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_renameargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_linkargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_symlinkargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_readdirargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_readdirplusargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_decode_commitargs(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_getattrres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_wccstat(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_lookupres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_accessres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_readlinkres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_readres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_writeres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_createres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_renameres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_linkres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_readdirres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_fsstatres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_fsinfores(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_pathconfres(struct svc_rqst *, __be32 *);
|
||||
int nfs3svc_encode_commitres(struct svc_rqst *, __be32 *);
|
||||
bool nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
|
||||
bool nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
|
||||
void nfs3svc_release_fhandle(struct svc_rqst *);
|
||||
void nfs3svc_release_fhandle2(struct svc_rqst *);
|
||||
|
@ -702,10 +702,11 @@ struct nfsd4_compoundres {
|
||||
struct xdr_stream *xdr;
|
||||
struct svc_rqst * rqstp;
|
||||
|
||||
__be32 *statusp;
|
||||
u32 taglen;
|
||||
char * tag;
|
||||
u32 opcnt;
|
||||
__be32 * tagp; /* tag, opcount encode location */
|
||||
|
||||
struct nfsd4_compound_state cstate;
|
||||
};
|
||||
|
||||
@ -756,8 +757,8 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
|
||||
|
||||
|
||||
bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp);
|
||||
int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *);
|
||||
int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *);
|
||||
bool nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nfs4svc_encode_compoundres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
__be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32);
|
||||
void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
|
||||
void nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op);
|
||||
|
@ -96,18 +96,19 @@ struct nlm_reboot {
|
||||
*/
|
||||
#define NLMSVC_XDRSIZE sizeof(struct nlm_args)
|
||||
|
||||
int nlmsvc_decode_testargs(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_encode_testres(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_decode_lockargs(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_decode_cancargs(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_decode_unlockargs(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_encode_res(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_decode_res(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_encode_void(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_decode_void(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_decode_shareargs(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_encode_shareres(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_decode_notify(struct svc_rqst *, __be32 *);
|
||||
int nlmsvc_decode_reboot(struct svc_rqst *, __be32 *);
|
||||
bool nlmsvc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
|
||||
bool nlmsvc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlmsvc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
|
||||
#endif /* LOCKD_XDR_H */
|
||||
|
@ -22,21 +22,20 @@
|
||||
#define nlm4_fbig cpu_to_be32(NLM_FBIG)
|
||||
#define nlm4_failed cpu_to_be32(NLM_FAILED)
|
||||
|
||||
bool nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
|
||||
|
||||
int nlm4svc_decode_testargs(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_encode_testres(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_decode_lockargs(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_decode_cancargs(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_decode_unlockargs(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_encode_res(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_decode_res(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_encode_void(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_decode_void(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_decode_shareargs(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_encode_shareres(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_decode_notify(struct svc_rqst *, __be32 *);
|
||||
int nlm4svc_decode_reboot(struct svc_rqst *, __be32 *);
|
||||
bool nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
bool nlm4svc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
||||
|
||||
extern const struct rpc_version nlm_version4;
|
||||
|
||||
|
@ -443,10 +443,7 @@ struct svc_version {
|
||||
/* Need xprt with congestion control */
|
||||
bool vs_need_cong_ctrl;
|
||||
|
||||
/* Override dispatch function (e.g. when caching replies).
|
||||
* A return value of 0 means drop the request.
|
||||
* vs_dispatch == NULL means use default dispatcher.
|
||||
*/
|
||||
/* Dispatch function */
|
||||
int (*vs_dispatch)(struct svc_rqst *, __be32 *);
|
||||
};
|
||||
|
||||
@ -457,9 +454,11 @@ struct svc_procedure {
|
||||
/* process the request: */
|
||||
__be32 (*pc_func)(struct svc_rqst *);
|
||||
/* XDR decode args: */
|
||||
int (*pc_decode)(struct svc_rqst *, __be32 *data);
|
||||
bool (*pc_decode)(struct svc_rqst *rqstp,
|
||||
struct xdr_stream *xdr);
|
||||
/* XDR encode result: */
|
||||
int (*pc_encode)(struct svc_rqst *, __be32 *data);
|
||||
bool (*pc_encode)(struct svc_rqst *rqstp,
|
||||
struct xdr_stream *xdr);
|
||||
/* XDR free result: */
|
||||
void (*pc_release)(struct svc_rqst *);
|
||||
unsigned int pc_argsize; /* argument struct size */
|
||||
@ -532,8 +531,7 @@ int svc_encode_result_payload(struct svc_rqst *rqstp,
|
||||
unsigned int offset,
|
||||
unsigned int length);
|
||||
unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
|
||||
struct page **pages,
|
||||
struct kvec *first, size_t total);
|
||||
struct xdr_buf *payload);
|
||||
char *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
|
||||
struct kvec *first, void *p,
|
||||
size_t total);
|
||||
|
@ -62,6 +62,74 @@ DECLARE_EVENT_CLASS(rpcrdma_completion_class,
|
||||
), \
|
||||
TP_ARGS(wc, cid))
|
||||
|
||||
DECLARE_EVENT_CLASS(rpcrdma_send_completion_class,
|
||||
TP_PROTO(
|
||||
const struct ib_wc *wc,
|
||||
const struct rpc_rdma_cid *cid
|
||||
),
|
||||
|
||||
TP_ARGS(wc, cid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, cq_id)
|
||||
__field(int, completion_id)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->cq_id = cid->ci_queue_id;
|
||||
__entry->completion_id = cid->ci_completion_id;
|
||||
),
|
||||
|
||||
TP_printk("cq.id=%u cid=%d",
|
||||
__entry->cq_id, __entry->completion_id
|
||||
)
|
||||
);
|
||||
|
||||
#define DEFINE_SEND_COMPLETION_EVENT(name) \
|
||||
DEFINE_EVENT(rpcrdma_send_completion_class, name, \
|
||||
TP_PROTO( \
|
||||
const struct ib_wc *wc, \
|
||||
const struct rpc_rdma_cid *cid \
|
||||
), \
|
||||
TP_ARGS(wc, cid))
|
||||
|
||||
DECLARE_EVENT_CLASS(rpcrdma_send_flush_class,
|
||||
TP_PROTO(
|
||||
const struct ib_wc *wc,
|
||||
const struct rpc_rdma_cid *cid
|
||||
),
|
||||
|
||||
TP_ARGS(wc, cid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, cq_id)
|
||||
__field(int, completion_id)
|
||||
__field(unsigned long, status)
|
||||
__field(unsigned int, vendor_err)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->cq_id = cid->ci_queue_id;
|
||||
__entry->completion_id = cid->ci_completion_id;
|
||||
__entry->status = wc->status;
|
||||
__entry->vendor_err = wc->vendor_err;
|
||||
),
|
||||
|
||||
TP_printk("cq.id=%u cid=%d status=%s (%lu/0x%x)",
|
||||
__entry->cq_id, __entry->completion_id,
|
||||
rdma_show_wc_status(__entry->status),
|
||||
__entry->status, __entry->vendor_err
|
||||
)
|
||||
);
|
||||
|
||||
#define DEFINE_SEND_FLUSH_EVENT(name) \
|
||||
DEFINE_EVENT(rpcrdma_send_flush_class, name, \
|
||||
TP_PROTO( \
|
||||
const struct ib_wc *wc, \
|
||||
const struct rpc_rdma_cid *cid \
|
||||
), \
|
||||
TP_ARGS(wc, cid))
|
||||
|
||||
DECLARE_EVENT_CLASS(rpcrdma_mr_completion_class,
|
||||
TP_PROTO(
|
||||
const struct ib_wc *wc,
|
||||
@ -147,6 +215,77 @@ DECLARE_EVENT_CLASS(rpcrdma_receive_completion_class,
|
||||
), \
|
||||
TP_ARGS(wc, cid))
|
||||
|
||||
DECLARE_EVENT_CLASS(rpcrdma_receive_success_class,
|
||||
TP_PROTO(
|
||||
const struct ib_wc *wc,
|
||||
const struct rpc_rdma_cid *cid
|
||||
),
|
||||
|
||||
TP_ARGS(wc, cid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, cq_id)
|
||||
__field(int, completion_id)
|
||||
__field(u32, received)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->cq_id = cid->ci_queue_id;
|
||||
__entry->completion_id = cid->ci_completion_id;
|
||||
__entry->received = wc->byte_len;
|
||||
),
|
||||
|
||||
TP_printk("cq.id=%u cid=%d received=%u",
|
||||
__entry->cq_id, __entry->completion_id,
|
||||
__entry->received
|
||||
)
|
||||
);
|
||||
|
||||
#define DEFINE_RECEIVE_SUCCESS_EVENT(name) \
|
||||
DEFINE_EVENT(rpcrdma_receive_success_class, name, \
|
||||
TP_PROTO( \
|
||||
const struct ib_wc *wc, \
|
||||
const struct rpc_rdma_cid *cid \
|
||||
), \
|
||||
TP_ARGS(wc, cid))
|
||||
|
||||
DECLARE_EVENT_CLASS(rpcrdma_receive_flush_class,
|
||||
TP_PROTO(
|
||||
const struct ib_wc *wc,
|
||||
const struct rpc_rdma_cid *cid
|
||||
),
|
||||
|
||||
TP_ARGS(wc, cid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, cq_id)
|
||||
__field(int, completion_id)
|
||||
__field(unsigned long, status)
|
||||
__field(unsigned int, vendor_err)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->cq_id = cid->ci_queue_id;
|
||||
__entry->completion_id = cid->ci_completion_id;
|
||||
__entry->status = wc->status;
|
||||
__entry->vendor_err = wc->vendor_err;
|
||||
),
|
||||
|
||||
TP_printk("cq.id=%u cid=%d status=%s (%lu/0x%x)",
|
||||
__entry->cq_id, __entry->completion_id,
|
||||
rdma_show_wc_status(__entry->status),
|
||||
__entry->status, __entry->vendor_err
|
||||
)
|
||||
);
|
||||
|
||||
#define DEFINE_RECEIVE_FLUSH_EVENT(name) \
|
||||
DEFINE_EVENT(rpcrdma_receive_flush_class, name, \
|
||||
TP_PROTO( \
|
||||
const struct ib_wc *wc, \
|
||||
const struct rpc_rdma_cid *cid \
|
||||
), \
|
||||
TP_ARGS(wc, cid))
|
||||
|
||||
DECLARE_EVENT_CLASS(xprtrdma_reply_class,
|
||||
TP_PROTO(
|
||||
const struct rpcrdma_rep *rep
|
||||
@ -1881,7 +2020,9 @@ TRACE_EVENT(svcrdma_post_send,
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_COMPLETION_EVENT(svcrdma_wc_send);
|
||||
DEFINE_SEND_COMPLETION_EVENT(svcrdma_wc_send);
|
||||
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_send_flush);
|
||||
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_send_err);
|
||||
|
||||
TRACE_EVENT(svcrdma_post_recv,
|
||||
TP_PROTO(
|
||||
@ -1905,7 +2046,9 @@ TRACE_EVENT(svcrdma_post_recv,
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_RECEIVE_COMPLETION_EVENT(svcrdma_wc_receive);
|
||||
DEFINE_RECEIVE_SUCCESS_EVENT(svcrdma_wc_recv);
|
||||
DEFINE_RECEIVE_FLUSH_EVENT(svcrdma_wc_recv_flush);
|
||||
DEFINE_RECEIVE_FLUSH_EVENT(svcrdma_wc_recv_err);
|
||||
|
||||
TRACE_EVENT(svcrdma_rq_post_err,
|
||||
TP_PROTO(
|
||||
@ -1969,8 +2112,42 @@ DEFINE_POST_CHUNK_EVENT(read);
|
||||
DEFINE_POST_CHUNK_EVENT(write);
|
||||
DEFINE_POST_CHUNK_EVENT(reply);
|
||||
|
||||
DEFINE_COMPLETION_EVENT(svcrdma_wc_read);
|
||||
DEFINE_COMPLETION_EVENT(svcrdma_wc_write);
|
||||
TRACE_EVENT(svcrdma_wc_read,
|
||||
TP_PROTO(
|
||||
const struct ib_wc *wc,
|
||||
const struct rpc_rdma_cid *cid,
|
||||
unsigned int totalbytes,
|
||||
const ktime_t posttime
|
||||
),
|
||||
|
||||
TP_ARGS(wc, cid, totalbytes, posttime),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, cq_id)
|
||||
__field(int, completion_id)
|
||||
__field(s64, read_latency)
|
||||
__field(unsigned int, totalbytes)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->cq_id = cid->ci_queue_id;
|
||||
__entry->completion_id = cid->ci_completion_id;
|
||||
__entry->totalbytes = totalbytes;
|
||||
__entry->read_latency = ktime_us_delta(ktime_get(), posttime);
|
||||
),
|
||||
|
||||
TP_printk("cq.id=%u cid=%d totalbytes=%u latency-us=%lld",
|
||||
__entry->cq_id, __entry->completion_id,
|
||||
__entry->totalbytes, __entry->read_latency
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_read_flush);
|
||||
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_read_err);
|
||||
|
||||
DEFINE_SEND_COMPLETION_EVENT(svcrdma_wc_write);
|
||||
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_write_flush);
|
||||
DEFINE_SEND_FLUSH_EVENT(svcrdma_wc_write_err);
|
||||
|
||||
TRACE_EVENT(svcrdma_qp_error,
|
||||
TP_PROTO(
|
||||
|
@ -64,6 +64,7 @@ DECLARE_EVENT_CLASS(rpc_xdr_buf_class,
|
||||
__field(size_t, head_len)
|
||||
__field(const void *, tail_base)
|
||||
__field(size_t, tail_len)
|
||||
__field(unsigned int, page_base)
|
||||
__field(unsigned int, page_len)
|
||||
__field(unsigned int, msg_len)
|
||||
),
|
||||
@ -76,15 +77,18 @@ DECLARE_EVENT_CLASS(rpc_xdr_buf_class,
|
||||
__entry->head_len = xdr->head[0].iov_len;
|
||||
__entry->tail_base = xdr->tail[0].iov_base;
|
||||
__entry->tail_len = xdr->tail[0].iov_len;
|
||||
__entry->page_base = xdr->page_base;
|
||||
__entry->page_len = xdr->page_len;
|
||||
__entry->msg_len = xdr->len;
|
||||
),
|
||||
|
||||
TP_printk(SUNRPC_TRACE_TASK_SPECIFIER
|
||||
" head=[%p,%zu] page=%u tail=[%p,%zu] len=%u",
|
||||
" head=[%p,%zu] page=%u(%u) tail=[%p,%zu] len=%u",
|
||||
__entry->task_id, __entry->client_id,
|
||||
__entry->head_base, __entry->head_len, __entry->page_len,
|
||||
__entry->tail_base, __entry->tail_len, __entry->msg_len
|
||||
__entry->head_base, __entry->head_len,
|
||||
__entry->page_len, __entry->page_base,
|
||||
__entry->tail_base, __entry->tail_len,
|
||||
__entry->msg_len
|
||||
)
|
||||
);
|
||||
|
||||
@ -1513,6 +1517,7 @@ DECLARE_EVENT_CLASS(svc_xdr_buf_class,
|
||||
__field(size_t, head_len)
|
||||
__field(const void *, tail_base)
|
||||
__field(size_t, tail_len)
|
||||
__field(unsigned int, page_base)
|
||||
__field(unsigned int, page_len)
|
||||
__field(unsigned int, msg_len)
|
||||
),
|
||||
@ -1523,14 +1528,17 @@ DECLARE_EVENT_CLASS(svc_xdr_buf_class,
|
||||
__entry->head_len = xdr->head[0].iov_len;
|
||||
__entry->tail_base = xdr->tail[0].iov_base;
|
||||
__entry->tail_len = xdr->tail[0].iov_len;
|
||||
__entry->page_base = xdr->page_base;
|
||||
__entry->page_len = xdr->page_len;
|
||||
__entry->msg_len = xdr->len;
|
||||
),
|
||||
|
||||
TP_printk("xid=0x%08x head=[%p,%zu] page=%u tail=[%p,%zu] len=%u",
|
||||
TP_printk("xid=0x%08x head=[%p,%zu] page=%u(%u) tail=[%p,%zu] len=%u",
|
||||
__entry->xid,
|
||||
__entry->head_base, __entry->head_len, __entry->page_len,
|
||||
__entry->tail_base, __entry->tail_len, __entry->msg_len
|
||||
__entry->head_base, __entry->head_len,
|
||||
__entry->page_len, __entry->page_base,
|
||||
__entry->tail_base, __entry->tail_len,
|
||||
__entry->msg_len
|
||||
)
|
||||
);
|
||||
|
||||
@ -1876,6 +1884,24 @@ TRACE_EVENT(svc_wake_up,
|
||||
TP_printk("pid=%d", __entry->pid)
|
||||
);
|
||||
|
||||
TRACE_EVENT(svc_alloc_arg_err,
|
||||
TP_PROTO(
|
||||
unsigned int pages
|
||||
),
|
||||
|
||||
TP_ARGS(pages),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, pages)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->pages = pages;
|
||||
),
|
||||
|
||||
TP_printk("pages=%u", __entry->pages)
|
||||
);
|
||||
|
||||
TRACE_EVENT(svc_handle_xprt,
|
||||
TP_PROTO(struct svc_xprt *xprt, int len),
|
||||
|
||||
|
@ -1,115 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* This file describes the layout of the file handles as passed
|
||||
* over the wire.
|
||||
*
|
||||
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_LINUX_NFSD_FH_H
|
||||
#define _UAPI_LINUX_NFSD_FH_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/nfs.h>
|
||||
#include <linux/nfs2.h>
|
||||
#include <linux/nfs3.h>
|
||||
#include <linux/nfs4.h>
|
||||
|
||||
/*
|
||||
* This is the old "dentry style" Linux NFSv2 file handle.
|
||||
*
|
||||
* The xino and xdev fields are currently used to transport the
|
||||
* ino/dev of the exported inode.
|
||||
*/
|
||||
struct nfs_fhbase_old {
|
||||
__u32 fb_dcookie; /* dentry cookie - always 0xfeebbaca */
|
||||
__u32 fb_ino; /* our inode number */
|
||||
__u32 fb_dirino; /* dir inode number, 0 for directories */
|
||||
__u32 fb_dev; /* our device */
|
||||
__u32 fb_xdev;
|
||||
__u32 fb_xino;
|
||||
__u32 fb_generation;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the new flexible, extensible style NFSv2/v3/v4 file handle.
|
||||
*
|
||||
* The file handle starts with a sequence of four-byte words.
|
||||
* The first word contains a version number (1) and three descriptor bytes
|
||||
* that tell how the remaining 3 variable length fields should be handled.
|
||||
* These three bytes are auth_type, fsid_type and fileid_type.
|
||||
*
|
||||
* All four-byte values are in host-byte-order.
|
||||
*
|
||||
* The auth_type field is deprecated and must be set to 0.
|
||||
*
|
||||
* The fsid_type identifies how the filesystem (or export point) is
|
||||
* encoded.
|
||||
* Current values:
|
||||
* 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
|
||||
* NOTE: we cannot use the kdev_t device id value, because kdev_t.h
|
||||
* says we mustn't. We must break it up and reassemble.
|
||||
* 1 - 4 byte user specified identifier
|
||||
* 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED
|
||||
* 3 - 4 byte device id, encoded for user-space, 4 byte inode number
|
||||
* 4 - 4 byte inode number and 4 byte uuid
|
||||
* 5 - 8 byte uuid
|
||||
* 6 - 16 byte uuid
|
||||
* 7 - 8 byte inode number and 16 byte uuid
|
||||
*
|
||||
* The fileid_type identified how the file within the filesystem is encoded.
|
||||
* The values for this field are filesystem specific, exccept that
|
||||
* filesystems must not use the values '0' or '0xff'. 'See enum fid_type'
|
||||
* in include/linux/exportfs.h for currently registered values.
|
||||
*/
|
||||
struct nfs_fhbase_new {
|
||||
union {
|
||||
struct {
|
||||
__u8 fb_version_aux; /* == 1, even => nfs_fhbase_old */
|
||||
__u8 fb_auth_type_aux;
|
||||
__u8 fb_fsid_type_aux;
|
||||
__u8 fb_fileid_type_aux;
|
||||
__u32 fb_auth[1];
|
||||
/* __u32 fb_fsid[0]; floating */
|
||||
/* __u32 fb_fileid[0]; floating */
|
||||
};
|
||||
struct {
|
||||
__u8 fb_version; /* == 1, even => nfs_fhbase_old */
|
||||
__u8 fb_auth_type;
|
||||
__u8 fb_fsid_type;
|
||||
__u8 fb_fileid_type;
|
||||
__u32 fb_auth_flex[]; /* flexible-array member */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct knfsd_fh {
|
||||
unsigned int fh_size; /* significant for NFSv3.
|
||||
* Points to the current size while building
|
||||
* a new file handle
|
||||
*/
|
||||
union {
|
||||
struct nfs_fhbase_old fh_old;
|
||||
__u32 fh_pad[NFS4_FHSIZE/4];
|
||||
struct nfs_fhbase_new fh_new;
|
||||
} fh_base;
|
||||
};
|
||||
|
||||
#define ofh_dcookie fh_base.fh_old.fb_dcookie
|
||||
#define ofh_ino fh_base.fh_old.fb_ino
|
||||
#define ofh_dirino fh_base.fh_old.fb_dirino
|
||||
#define ofh_dev fh_base.fh_old.fb_dev
|
||||
#define ofh_xdev fh_base.fh_old.fb_xdev
|
||||
#define ofh_xino fh_base.fh_old.fb_xino
|
||||
#define ofh_generation fh_base.fh_old.fb_generation
|
||||
|
||||
#define fh_version fh_base.fh_new.fb_version
|
||||
#define fh_fsid_type fh_base.fh_new.fb_fsid_type
|
||||
#define fh_auth_type fh_base.fh_new.fb_auth_type
|
||||
#define fh_fileid_type fh_base.fh_new.fb_fileid_type
|
||||
#define fh_fsid fh_base.fh_new.fb_auth_flex
|
||||
|
||||
/* Do not use, provided for userspace compatiblity. */
|
||||
#define fh_auth fh_base.fh_new.fb_auth
|
||||
|
||||
#endif /* _UAPI_LINUX_NFSD_FH_H */
|
@ -162,8 +162,10 @@ static int rpc_parse_scope_id(struct net *net, const char *buf,
|
||||
const size_t buflen, const char *delim,
|
||||
struct sockaddr_in6 *sin6)
|
||||
{
|
||||
char *p;
|
||||
char p[IPV6_SCOPE_ID_LEN + 1];
|
||||
size_t len;
|
||||
u32 scope_id = 0;
|
||||
struct net_device *dev;
|
||||
|
||||
if ((buf + buflen) == delim)
|
||||
return 1;
|
||||
@ -175,29 +177,23 @@ static int rpc_parse_scope_id(struct net *net, const char *buf,
|
||||
return 0;
|
||||
|
||||
len = (buf + buflen) - delim - 1;
|
||||
p = kmemdup_nul(delim + 1, len, GFP_KERNEL);
|
||||
if (p) {
|
||||
u32 scope_id = 0;
|
||||
struct net_device *dev;
|
||||
if (len > IPV6_SCOPE_ID_LEN)
|
||||
return 0;
|
||||
|
||||
dev = dev_get_by_name(net, p);
|
||||
if (dev != NULL) {
|
||||
scope_id = dev->ifindex;
|
||||
dev_put(dev);
|
||||
} else {
|
||||
if (kstrtou32(p, 10, &scope_id) != 0) {
|
||||
kfree(p);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
memcpy(p, delim + 1, len);
|
||||
p[len] = 0;
|
||||
|
||||
kfree(p);
|
||||
|
||||
sin6->sin6_scope_id = scope_id;
|
||||
return 1;
|
||||
dev = dev_get_by_name(net, p);
|
||||
if (dev != NULL) {
|
||||
scope_id = dev->ifindex;
|
||||
dev_put(dev);
|
||||
} else {
|
||||
if (kstrtou32(p, 10, &scope_id) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
sin6->sin6_scope_id = scope_id;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen,
|
||||
|
@ -781,7 +781,7 @@ gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
|
||||
svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS);
|
||||
xdr_seq = kmalloc(4, GFP_KERNEL);
|
||||
if (!xdr_seq)
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
*xdr_seq = htonl(seq);
|
||||
|
||||
iov.iov_base = xdr_seq;
|
||||
|
@ -1186,45 +1186,6 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
|
||||
static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {}
|
||||
#endif
|
||||
|
||||
static int
|
||||
svc_generic_dispatch(struct svc_rqst *rqstp, __be32 *statp)
|
||||
{
|
||||
struct kvec *argv = &rqstp->rq_arg.head[0];
|
||||
struct kvec *resv = &rqstp->rq_res.head[0];
|
||||
const struct svc_procedure *procp = rqstp->rq_procinfo;
|
||||
|
||||
/*
|
||||
* Decode arguments
|
||||
* XXX: why do we ignore the return value?
|
||||
*/
|
||||
if (procp->pc_decode &&
|
||||
!procp->pc_decode(rqstp, argv->iov_base)) {
|
||||
*statp = rpc_garbage_args;
|
||||
return 1;
|
||||
}
|
||||
|
||||
*statp = procp->pc_func(rqstp);
|
||||
|
||||
if (*statp == rpc_drop_reply ||
|
||||
test_bit(RQ_DROPME, &rqstp->rq_flags))
|
||||
return 0;
|
||||
|
||||
if (rqstp->rq_auth_stat != rpc_auth_ok)
|
||||
return 1;
|
||||
|
||||
if (*statp != rpc_success)
|
||||
return 1;
|
||||
|
||||
/* Encode reply */
|
||||
if (procp->pc_encode &&
|
||||
!procp->pc_encode(rqstp, resv->iov_base + resv->iov_len)) {
|
||||
dprintk("svc: failed to encode reply\n");
|
||||
/* serv->sv_stats->rpcsystemerr++; */
|
||||
*statp = rpc_system_err;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
__be32
|
||||
svc_generic_init_request(struct svc_rqst *rqstp,
|
||||
const struct svc_program *progp,
|
||||
@ -1291,7 +1252,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
|
||||
__be32 *statp;
|
||||
u32 prog, vers;
|
||||
__be32 rpc_stat;
|
||||
int auth_res;
|
||||
int auth_res, rc;
|
||||
__be32 *reply_statp;
|
||||
|
||||
rpc_stat = rpc_success;
|
||||
@ -1392,28 +1353,18 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
|
||||
svc_reserve_auth(rqstp, procp->pc_xdrressize<<2);
|
||||
|
||||
/* Call the function that processes the request. */
|
||||
if (!process.dispatch) {
|
||||
if (!svc_generic_dispatch(rqstp, statp))
|
||||
goto release_dropit;
|
||||
if (*statp == rpc_garbage_args)
|
||||
goto err_garbage;
|
||||
} else {
|
||||
dprintk("svc: calling dispatcher\n");
|
||||
if (!process.dispatch(rqstp, statp))
|
||||
goto release_dropit; /* Release reply info */
|
||||
}
|
||||
|
||||
rc = process.dispatch(rqstp, statp);
|
||||
if (procp->pc_release)
|
||||
procp->pc_release(rqstp);
|
||||
if (!rc)
|
||||
goto dropit;
|
||||
if (rqstp->rq_auth_stat != rpc_auth_ok)
|
||||
goto err_release_bad_auth;
|
||||
goto err_bad_auth;
|
||||
|
||||
/* Check RPC status result */
|
||||
if (*statp != rpc_success)
|
||||
resv->iov_len = ((void*)statp) - resv->iov_base + 4;
|
||||
|
||||
/* Release reply info */
|
||||
if (procp->pc_release)
|
||||
procp->pc_release(rqstp);
|
||||
|
||||
if (procp->pc_encode == NULL)
|
||||
goto dropit;
|
||||
|
||||
@ -1422,9 +1373,6 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
|
||||
goto close_xprt;
|
||||
return 1; /* Caller can now send it */
|
||||
|
||||
release_dropit:
|
||||
if (procp->pc_release)
|
||||
procp->pc_release(rqstp);
|
||||
dropit:
|
||||
svc_authorise(rqstp); /* doesn't hurt to call this twice */
|
||||
dprintk("svc: svc_process dropit\n");
|
||||
@ -1451,9 +1399,6 @@ err_bad_rpc:
|
||||
svc_putnl(resv, 2);
|
||||
goto sendit;
|
||||
|
||||
err_release_bad_auth:
|
||||
if (procp->pc_release)
|
||||
procp->pc_release(rqstp);
|
||||
err_bad_auth:
|
||||
dprintk("svc: authentication failed (%d)\n",
|
||||
be32_to_cpu(rqstp->rq_auth_stat));
|
||||
@ -1676,16 +1621,17 @@ EXPORT_SYMBOL_GPL(svc_encode_result_payload);
|
||||
/**
|
||||
* svc_fill_write_vector - Construct data argument for VFS write call
|
||||
* @rqstp: svc_rqst to operate on
|
||||
* @pages: list of pages containing data payload
|
||||
* @first: buffer containing first section of write payload
|
||||
* @total: total number of bytes of write payload
|
||||
* @payload: xdr_buf containing only the write data payload
|
||||
*
|
||||
* Fills in rqstp::rq_vec, and returns the number of elements.
|
||||
*/
|
||||
unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct page **pages,
|
||||
struct kvec *first, size_t total)
|
||||
unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
|
||||
struct xdr_buf *payload)
|
||||
{
|
||||
struct page **pages = payload->pages;
|
||||
struct kvec *first = payload->head;
|
||||
struct kvec *vec = rqstp->rq_vec;
|
||||
size_t total = payload->len;
|
||||
unsigned int i;
|
||||
|
||||
/* Some types of transport can present the write payload
|
||||
|
@ -687,6 +687,7 @@ static int svc_alloc_arg(struct svc_rqst *rqstp)
|
||||
set_current_state(TASK_RUNNING);
|
||||
return -EINTR;
|
||||
}
|
||||
trace_svc_alloc_arg_err(pages);
|
||||
schedule_timeout(msecs_to_jiffies(500));
|
||||
}
|
||||
rqstp->rq_page_end = &rqstp->rq_pages[pages];
|
||||
|
@ -1633,7 +1633,7 @@ EXPORT_SYMBOL_GPL(xdr_buf_subsegment);
|
||||
* Sets up @subbuf to represent a portion of @xdr. The portion
|
||||
* starts at the current offset in @xdr, and extends for a length
|
||||
* of @nbytes. If this is successful, @xdr is advanced to the next
|
||||
* position following that portion.
|
||||
* XDR data item following that portion.
|
||||
*
|
||||
* Return values:
|
||||
* %true: @subbuf has been initialized, and @xdr has been advanced.
|
||||
@ -1642,29 +1642,31 @@ EXPORT_SYMBOL_GPL(xdr_buf_subsegment);
|
||||
bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
unsigned int remaining, offset, len;
|
||||
unsigned int start = xdr_stream_pos(xdr);
|
||||
unsigned int remaining, len;
|
||||
|
||||
if (xdr_buf_subsegment(xdr->buf, subbuf, xdr_stream_pos(xdr), nbytes))
|
||||
/* Extract @subbuf and bounds-check the fn arguments */
|
||||
if (xdr_buf_subsegment(xdr->buf, subbuf, start, nbytes))
|
||||
return false;
|
||||
|
||||
if (subbuf->head[0].iov_len)
|
||||
if (!__xdr_inline_decode(xdr, subbuf->head[0].iov_len))
|
||||
return false;
|
||||
|
||||
remaining = subbuf->page_len;
|
||||
offset = subbuf->page_base;
|
||||
while (remaining) {
|
||||
len = min_t(unsigned int, remaining, PAGE_SIZE) - offset;
|
||||
|
||||
/* Advance @xdr by @nbytes */
|
||||
for (remaining = nbytes; remaining;) {
|
||||
if (xdr->p == xdr->end && !xdr_set_next_buffer(xdr))
|
||||
return false;
|
||||
if (!__xdr_inline_decode(xdr, len))
|
||||
return false;
|
||||
|
||||
len = (char *)xdr->end - (char *)xdr->p;
|
||||
if (remaining <= len) {
|
||||
xdr->p = (__be32 *)((char *)xdr->p +
|
||||
(remaining + xdr_pad_size(nbytes)));
|
||||
break;
|
||||
}
|
||||
|
||||
xdr->p = (__be32 *)((char *)xdr->p + len);
|
||||
xdr->end = xdr->p;
|
||||
remaining -= len;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
xdr_stream_set_pos(xdr, start + nbytes);
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xdr_stream_subsegment);
|
||||
|
@ -330,9 +330,9 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
|
||||
/* WARNING: Only wc->wr_cqe and wc->status are reliable */
|
||||
ctxt = container_of(cqe, struct svc_rdma_recv_ctxt, rc_cqe);
|
||||
|
||||
trace_svcrdma_wc_receive(wc, &ctxt->rc_cid);
|
||||
if (wc->status != IB_WC_SUCCESS)
|
||||
goto flushed;
|
||||
trace_svcrdma_wc_recv(wc, &ctxt->rc_cid);
|
||||
|
||||
/* If receive posting fails, the connection is about to be
|
||||
* lost anyway. The server will not be able to send a reply
|
||||
@ -345,7 +345,7 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
|
||||
*/
|
||||
if (rdma->sc_pending_recvs < rdma->sc_max_requests)
|
||||
if (!svc_rdma_refresh_recvs(rdma, rdma->sc_recv_batch, false))
|
||||
goto flushed;
|
||||
goto dropped;
|
||||
|
||||
/* All wc fields are now known to be valid */
|
||||
ctxt->rc_byte_len = wc->byte_len;
|
||||
@ -360,6 +360,11 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
|
||||
return;
|
||||
|
||||
flushed:
|
||||
if (wc->status == IB_WC_WR_FLUSH_ERR)
|
||||
trace_svcrdma_wc_recv_flush(wc, &ctxt->rc_cid);
|
||||
else
|
||||
trace_svcrdma_wc_recv_err(wc, &ctxt->rc_cid);
|
||||
dropped:
|
||||
svc_rdma_recv_ctxt_put(rdma, ctxt);
|
||||
svc_xprt_deferred_close(&rdma->sc_xprt);
|
||||
}
|
||||
|
@ -155,6 +155,7 @@ struct svc_rdma_chunk_ctxt {
|
||||
struct ib_cqe cc_cqe;
|
||||
struct svcxprt_rdma *cc_rdma;
|
||||
struct list_head cc_rwctxts;
|
||||
ktime_t cc_posttime;
|
||||
int cc_sqecount;
|
||||
enum ib_wc_status cc_status;
|
||||
struct completion cc_done;
|
||||
@ -267,7 +268,16 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||
struct svc_rdma_write_info *info =
|
||||
container_of(cc, struct svc_rdma_write_info, wi_cc);
|
||||
|
||||
trace_svcrdma_wc_write(wc, &cc->cc_cid);
|
||||
switch (wc->status) {
|
||||
case IB_WC_SUCCESS:
|
||||
trace_svcrdma_wc_write(wc, &cc->cc_cid);
|
||||
break;
|
||||
case IB_WC_WR_FLUSH_ERR:
|
||||
trace_svcrdma_wc_write_flush(wc, &cc->cc_cid);
|
||||
break;
|
||||
default:
|
||||
trace_svcrdma_wc_write_err(wc, &cc->cc_cid);
|
||||
}
|
||||
|
||||
svc_rdma_wake_send_waiters(rdma, cc->cc_sqecount);
|
||||
|
||||
@ -320,11 +330,22 @@ static void svc_rdma_wc_read_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||
struct ib_cqe *cqe = wc->wr_cqe;
|
||||
struct svc_rdma_chunk_ctxt *cc =
|
||||
container_of(cqe, struct svc_rdma_chunk_ctxt, cc_cqe);
|
||||
struct svcxprt_rdma *rdma = cc->cc_rdma;
|
||||
struct svc_rdma_read_info *info;
|
||||
|
||||
trace_svcrdma_wc_read(wc, &cc->cc_cid);
|
||||
switch (wc->status) {
|
||||
case IB_WC_SUCCESS:
|
||||
info = container_of(cc, struct svc_rdma_read_info, ri_cc);
|
||||
trace_svcrdma_wc_read(wc, &cc->cc_cid, info->ri_totalbytes,
|
||||
cc->cc_posttime);
|
||||
break;
|
||||
case IB_WC_WR_FLUSH_ERR:
|
||||
trace_svcrdma_wc_read_flush(wc, &cc->cc_cid);
|
||||
break;
|
||||
default:
|
||||
trace_svcrdma_wc_read_err(wc, &cc->cc_cid);
|
||||
}
|
||||
|
||||
svc_rdma_wake_send_waiters(rdma, cc->cc_sqecount);
|
||||
svc_rdma_wake_send_waiters(cc->cc_rdma, cc->cc_sqecount);
|
||||
cc->cc_status = wc->status;
|
||||
complete(&cc->cc_done);
|
||||
return;
|
||||
@ -363,6 +384,7 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc)
|
||||
do {
|
||||
if (atomic_sub_return(cc->cc_sqecount,
|
||||
&rdma->sc_sq_avail) > 0) {
|
||||
cc->cc_posttime = ktime_get();
|
||||
ret = ib_post_send(rdma->sc_qp, first_wr, &bad_wr);
|
||||
if (ret)
|
||||
break;
|
||||
|
@ -280,13 +280,21 @@ static void svc_rdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
|
||||
struct svc_rdma_send_ctxt *ctxt =
|
||||
container_of(cqe, struct svc_rdma_send_ctxt, sc_cqe);
|
||||
|
||||
trace_svcrdma_wc_send(wc, &ctxt->sc_cid);
|
||||
|
||||
svc_rdma_wake_send_waiters(rdma, 1);
|
||||
complete(&ctxt->sc_done);
|
||||
|
||||
if (unlikely(wc->status != IB_WC_SUCCESS))
|
||||
svc_xprt_deferred_close(&rdma->sc_xprt);
|
||||
goto flushed;
|
||||
|
||||
trace_svcrdma_wc_send(wc, &ctxt->sc_cid);
|
||||
return;
|
||||
|
||||
flushed:
|
||||
if (wc->status != IB_WC_WR_FLUSH_ERR)
|
||||
trace_svcrdma_wc_send_err(wc, &ctxt->sc_cid);
|
||||
else
|
||||
trace_svcrdma_wc_send_flush(wc, &ctxt->sc_cid);
|
||||
svc_xprt_deferred_close(&rdma->sc_xprt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user