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:
Linus Torvalds 2021-11-10 16:45:54 -08:00
commit 38764c7340
43 changed files with 1149 additions and 1044 deletions

View File

@ -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.

View File

@ -11,3 +11,4 @@ NFS
rpc-server-gss
nfs41-server
knfsd-stats
reexport

View 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.

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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))

View File

@ -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) &&

View File

@ -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;

View File

@ -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;
}
/*

View File

@ -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);
}
/*

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}
/*

View File

@ -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.

View File

@ -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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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;
}
/**

View File

@ -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.

View File

@ -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,

View File

@ -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 *);

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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(

View File

@ -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),

View File

@ -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 */

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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];

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}
/**