Commit 38764c73 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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} tracep...
parents 2ec20f48 80479eb8
Showing with 555 additions and 474 deletions
+555 -474
......@@ -3253,6 +3253,19 @@
driver. A non-zero value sets the minimum interval
in seconds between layoutstats transmissions.
nfsd.inter_copy_offload_enable =
[NFSv4.2] When set to 1, the server will support
server-to-server copies for which this server is
the destination of the copy.
nfsd.nfsd4_ssc_umount_timeout =
[NFSv4.2] When used as the destination of a
server-to-server copy, knfsd temporarily mounts
the source server. It caches the mount in case
it will be needed again, and discards it if not
used for the number of milliseconds specified by
this parameter.
nfsd.nfs4_disable_idmapping=
[NFSv4] When set to the default of '1', the NFSv4
server will return only numeric uids and gids to
......@@ -3260,6 +3273,7 @@
and gids from such clients. This is intended to ease
migration from NFSv2/v3.
nmi_backtrace.backtrace_idle [KNL]
Dump stacks even of idle CPUs in response to an
NMI stack-backtrace request.
......
......@@ -11,3 +11,4 @@ NFS
rpc-server-gss
nfs41-server
knfsd-stats
reexport
Reexporting NFS filesystems
===========================
Overview
--------
It is possible to reexport an NFS filesystem over NFS. However, this
feature comes with a number of limitations. Before trying it, we
recommend some careful research to determine whether it will work for
your purposes.
A discussion of current known limitations follows.
"fsid=" required, crossmnt broken
---------------------------------
We require the "fsid=" export option on any reexport of an NFS
filesystem. You can use "uuidgen -r" to generate a unique argument.
The "crossmnt" export does not propagate "fsid=", so it will not allow
traversing into further nfs filesystems; if you wish to export nfs
filesystems mounted under the exported filesystem, you'll need to export
them explicitly, assigning each its own unique "fsid= option.
Reboot recovery
---------------
The NFS protocol's normal reboot recovery mechanisms don't work for the
case when the reexport server reboots. Clients will lose any locks
they held before the reboot, and further IO will result in errors.
Closing and reopening files should clear the errors.
Filehandle limits
-----------------
If the original server uses an X byte filehandle for a given object, the
reexport server's filehandle for the reexported object will be X+22
bytes, rounded up to the nearest multiple of four bytes.
The result must fit into the RFC-mandated filehandle size limits:
+-------+-----------+
| NFSv2 | 32 bytes |
+-------+-----------+
| NFSv3 | 64 bytes |
+-------+-----------+
| NFSv4 | 128 bytes |
+-------+-----------+
So, for example, you will only be able to reexport a filesystem over
NFSv2 if the original server gives you filehandles that fit in 10
bytes--which is unlikely.
In general there's no way to know the maximum filehandle size given out
by an NFS server without asking the server vendor.
But the following table gives a few examples. The first column is the
typical length of the filehandle from a Linux server exporting the given
filesystem, the second is the length after that nfs export is reexported
by another Linux host:
+--------+-------------------+----------------+
| | filehandle length | after reexport |
+========+===================+================+
| ext4: | 28 bytes | 52 bytes |
+--------+-------------------+----------------+
| xfs: | 32 bytes | 56 bytes |
+--------+-------------------+----------------+
| btrfs: | 40 bytes | 64 bytes |
+--------+-------------------+----------------+
All will therefore fit in an NFSv3 or NFSv4 filehandle after reexport,
but none are reexportable over NFSv2.
Linux server filehandles are a bit more complicated than this, though;
for example:
- The (non-default) "subtreecheck" export option generally
requires another 4 to 8 bytes in the filehandle.
- If you export a subdirectory of a filesystem (instead of
exporting the filesystem root), that also usually adds 4 to 8
bytes.
- If you export over NFSv2, knfsd usually uses a shorter
filesystem identifier that saves 8 bytes.
- The root directory of an export uses a filehandle that is
shorter.
As you can see, the 128-byte NFSv4 filehandle is large enough that
you're unlikely to have trouble using NFSv4 to reexport any filesystem
exported from a Linux server. In general, if the original server is
something that also supports NFSv3, you're *probably* OK. Re-exporting
over NFSv3 may be dicier, and reexporting over NFSv2 will probably
never work.
For more details of Linux filehandle structure, the best reference is
the source code and comments; see in particular:
- include/linux/exportfs.h:enum fid_type
- include/uapi/linux/nfsd/nfsfh.h:struct nfs_fhbase_new
- fs/nfsd/nfsfh.c:set_version_and_fsid_type
- fs/nfs/export.c:nfs_encode_fh
Open DENY bits ignored
----------------------
NFS since NFSv4 supports ALLOW and DENY bits taken from Windows, which
allow you, for example, to open a file in a mode which forbids other
read opens or write opens. The Linux client doesn't use them, and the
server's support has always been incomplete: they are enforced only
against other NFS users, not against processes accessing the exported
filesystem locally. A reexport server will also not pass them along to
the original server, so they will not be enforced between clients of
different reexport servers.
......@@ -780,11 +780,9 @@ module_exit(exit_nlm);
static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp)
{
const struct svc_procedure *procp = rqstp->rq_procinfo;
struct kvec *argv = rqstp->rq_arg.head;
struct kvec *resv = rqstp->rq_res.head;
svcxdr_init_decode(rqstp);
if (!procp->pc_decode(rqstp, argv->iov_base))
if (!procp->pc_decode(rqstp, &rqstp->rq_arg_stream))
goto out_decode_err;
*statp = procp->pc_func(rqstp);
......@@ -794,7 +792,7 @@ static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp)
return 1;
svcxdr_init_encode(rqstp);
if (!procp->pc_encode(rqstp, resv->iov_base + resv->iov_len))
if (!procp->pc_encode(rqstp, &rqstp->rq_res_stream))
goto out_encode_err;
return 1;
......
......@@ -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;
}
......@@ -144,136 +144,131 @@ svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
* Decode Call arguments
*/
int
nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
return 1;
return true;
}
int
nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
u32 exclusive;
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
return false;
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
return 0;
return false;
if (!svcxdr_decode_lock(xdr, &argp->lock))
return 0;
return false;
if (exclusive)
argp->lock.fl.fl_type = F_WRLCK;
return 1;
return true;
}
int
nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
u32 exclusive;
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
return false;
if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
return 0;
return false;
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
return 0;
return false;
if (!svcxdr_decode_lock(xdr, &argp->lock))
return 0;
return false;
if (exclusive)
argp->lock.fl.fl_type = F_WRLCK;
if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
return 0;
return false;
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
return 0;
return false;
argp->monitor = 1; /* monitor client by default */
return 1;
return true;
}
int
nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
u32 exclusive;
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
return false;
if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
return 0;
return false;
if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
return 0;
return false;
if (!svcxdr_decode_lock(xdr, &argp->lock))
return 0;
return false;
if (exclusive)
argp->lock.fl.fl_type = F_WRLCK;
return 1;
return true;
}
int
nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
return false;
if (!svcxdr_decode_lock(xdr, &argp->lock))
return 0;
return false;
argp->lock.fl.fl_type = F_UNLCK;
return 1;
return true;
}
int
nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_res *resp = rqstp->rq_argp;
if (!svcxdr_decode_cookie(xdr, &resp->cookie))
return 0;
return false;
if (!svcxdr_decode_stats(xdr, &resp->status))
return 0;
return false;
return 1;
return true;
}
int
nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_reboot *argp = rqstp->rq_argp;
__be32 *p;
u32 len;
if (xdr_stream_decode_u32(xdr, &len) < 0)
return 0;
return false;
if (len > SM_MAXSTRLEN)
return 0;
return false;
p = xdr_inline_decode(xdr, len);
if (!p)
return 0;
return false;
argp->len = len;
argp->mon = (char *)p;
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
return 0;
return false;
p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
if (!p)
return 0;
return false;
memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
return 1;
return true;
}
int
nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_lock *lock = &argp->lock;
......@@ -282,35 +277,34 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
lock->svid = ~(u32)0;
if (!svcxdr_decode_cookie(xdr, &argp->cookie))
return 0;
return false;
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
return 0;
return false;
if (!svcxdr_decode_fhandle(xdr, &lock->fh))
return 0;
return false;
if (!svcxdr_decode_owner(xdr, &lock->oh))
return 0;
return false;
/* XXX: Range checks are missing in the original code */
if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
return 0;
return false;
if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
return 0;
return false;
return 1;
return true;
}
int
nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_lock *lock = &argp->lock;
if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
return 0;
return false;
if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
return 0;
return false;
return 1;
return true;
}
......@@ -318,45 +312,42 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)
* Encode Reply results
*/
int
nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
return 1;
return true;
}
int
nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;
return svcxdr_encode_cookie(xdr, &resp->cookie) &&
svcxdr_encode_testrply(xdr, resp);
}
int
nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;
return svcxdr_encode_cookie(xdr, &resp->cookie) &&
svcxdr_encode_stats(xdr, resp->status);
}
int
nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p)
bool
nlm4svc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nlm_res *resp = rqstp->rq_resp;
if (!svcxdr_encode_cookie(xdr, &resp->cookie))
return 0;
return false;
if (!svcxdr_encode_stats(xdr, resp->status))
return 0;
return false;
/* sequence */
if (xdr_stream_encode_u32(xdr, 0) < 0)
return 0;
return false;
return 1;
return true;
}
......@@ -67,9 +67,9 @@ static __be32 nfs4_callback_null(struct svc_rqst *rqstp)
* svc_process_common() looks for an XDR encoder to know when
* not to drop a Reply.
*/
static int nfs4_encode_void(struct svc_rqst *rqstp, __be32 *p)
static bool nfs4_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
return xdr_ressize_check(rqstp, p);
return true;
}
static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len,
......
......@@ -61,7 +61,7 @@ nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
goto out_error;
fl->fh.size = fhp->fh_handle.fh_size;
memcpy(fl->fh.data, &fhp->fh_handle.fh_base, fl->fh.size);
memcpy(fl->fh.data, &fhp->fh_handle.fh_raw, fl->fh.size);
/* Give whole file layout segments */
seg->offset = 0;
......
......@@ -35,7 +35,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
/* must initialize before using! but maxsize doesn't matter */
fh_init(&fh,0);
fh.fh_handle.fh_size = f->size;
memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
memcpy(&fh.fh_handle.fh_raw, f->data, f->size);
fh.fh_export = NULL;
access = (mode == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ;
......
......@@ -188,51 +188,51 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
* XDR decode functions
*/
static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
static bool
nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nfsd3_getaclargs *argp = rqstp->rq_argp;
if (!svcxdr_decode_fhandle(xdr, &argp->fh))
return 0;
return false;
if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
return 0;
return false;
return 1;
return true;
}
static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
static bool
nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nfsd3_setaclargs *argp = rqstp->rq_argp;
if (!svcxdr_decode_fhandle(xdr, &argp->fh))
return 0;
return false;
if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
return 0;
return false;
if (argp->mask & ~NFS_ACL_MASK)
return 0;
return false;
if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_ACL) ?
&argp->acl_access : NULL))
return 0;
return false;
if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_DFACL) ?
&argp->acl_default : NULL))
return 0;
return false;
return 1;
return true;
}
static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
static bool
nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nfsd3_accessargs *args = rqstp->rq_argp;
if (!svcxdr_decode_fhandle(xdr, &args->fh))
return 0;
return false;
if (xdr_stream_decode_u32(xdr, &args->access) < 0)
return 0;
return false;
return 1;
return true;
}
/*
......@@ -240,9 +240,9 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
*/
/* GETACL */
static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
static bool
nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nfsd3_getaclres *resp = rqstp->rq_resp;
struct dentry *dentry = resp->fh.fh_dentry;
struct inode *inode;
......@@ -280,9 +280,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
}
/* ACCESS */
static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
static bool
nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nfsd3_accessres *resp = rqstp->rq_resp;
if (!svcxdr_encode_stat(xdr, resp->status))
......
......@@ -127,38 +127,38 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)
* XDR decode functions
*/
static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
static bool
nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nfsd3_getaclargs *args = rqstp->rq_argp;
if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
return 0;
return false;
if (xdr_stream_decode_u32(xdr, &args->mask) < 0)
return 0;
return false;
return 1;
return true;
}
static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
static bool
nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_arg_stream;
struct nfsd3_setaclargs *argp = rqstp->rq_argp;
if (!svcxdr_decode_nfs_fh3(xdr, &argp->fh))
return 0;
return false;
if (xdr_stream_decode_u32(xdr, &argp->mask) < 0)
return 0;
return false;
if (argp->mask & ~NFS_ACL_MASK)
return 0;
return false;
if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_ACL) ?
&argp->acl_access : NULL))
return 0;
return false;
if (!nfs_stream_decode_acl(xdr, NULL, (argp->mask & NFS_DFACL) ?
&argp->acl_default : NULL))
return 0;
return false;
return 1;
return true;
}
/*
......@@ -166,9 +166,9 @@ static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
*/
/* GETACL */
static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
static bool
nfs3svc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nfsd3_getaclres *resp = rqstp->rq_resp;
struct dentry *dentry = resp->fh.fh_dentry;
struct kvec *head = rqstp->rq_res.head;
......@@ -178,14 +178,14 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
int w;
if (!svcxdr_encode_nfsstat3(xdr, resp->status))
return 0;
return false;
switch (resp->status) {
case nfs_ok:
inode = d_inode(dentry);
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
return 0;
return false;
if (xdr_stream_encode_u32(xdr, resp->mask) < 0)
return 0;
return false;
base = (char *)xdr->p - (char *)head->iov_base;
......@@ -194,7 +194,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
(resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
while (w > 0) {
if (!*(rqstp->rq_next_page++))
return 0;
return false;
w -= PAGE_SIZE;
}
......@@ -207,20 +207,20 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
resp->mask & NFS_DFACL,
NFS_ACL_DEFAULT);
if (n <= 0)
return 0;
return false;
break;
default:
if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
return 0;
return false;
}
return 1;
return true;
}
/* SETACL */
static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, __be32 *p)
static bool
nfs3svc_encode_setaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
{
struct xdr_stream *xdr = &rqstp->rq_res_stream;
struct nfsd3_attrstat *resp = rqstp->rq_resp;
return svcxdr_encode_nfsstat3(xdr, resp->status) &&
......
......@@ -201,8 +201,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
fh_copy(&resp->fh, &argp->fh);
resp->committed = argp->stable;
nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
&argp->first, cnt);
nvecs = svc_fill_write_vector(rqstp, &argp->payload);
if (!nvecs) {
resp->status = nfserr_io;
goto out;
......
This diff is collapsed.
......@@ -121,7 +121,7 @@ static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh)
BUG_ON(length > NFS4_FHSIZE);
p = xdr_reserve_space(xdr, 4 + length);
xdr_encode_opaque(p, &fh->fh_base, length);
xdr_encode_opaque(p, &fh->fh_raw, length);
}
/*
......
......@@ -519,7 +519,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
fh_put(&cstate->current_fh);
cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
memcpy(&cstate->current_fh.fh_handle.fh_raw, putfh->pf_fhval,
putfh->pf_fhlen);
ret = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
#ifdef CONFIG_NFSD_V4_2_INTER_SSC
......@@ -1033,8 +1033,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
write->wr_how_written = write->wr_stable_how;
nvecs = svc_fill_write_vector(rqstp, write->wr_payload.pages,
write->wr_payload.head, write->wr_buflen);
nvecs = svc_fill_write_vector(rqstp, &write->wr_payload);
WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf,
......@@ -1178,7 +1177,7 @@ extern void nfs_sb_deactive(struct super_block *sb);
static __be32 nfsd4_ssc_setup_dul(struct nfsd_net *nn, char *ipaddr,
struct nfsd4_ssc_umount_item **retwork, struct vfsmount **ss_mnt)
{
struct nfsd4_ssc_umount_item *ni = 0;
struct nfsd4_ssc_umount_item *ni = NULL;
struct nfsd4_ssc_umount_item *work = NULL;
struct nfsd4_ssc_umount_item *tmp;
DEFINE_WAIT(wait);
......@@ -1383,7 +1382,7 @@ nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
s_fh = &cstate->save_fh;
copy->c_fh.size = s_fh->fh_handle.fh_size;
memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_base, copy->c_fh.size);
memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_raw, copy->c_fh.size);
copy->stateid.seqid = cpu_to_be32(s_stid->si_generation);
memcpy(copy->stateid.other, (void *)&s_stid->si_opaque,
sizeof(stateid_opaque_t));
......@@ -2462,11 +2461,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
__be32 status;
resp->xdr = &rqstp->rq_res_stream;
resp->statusp = resp->xdr->p;
/* reserve space for: NFS status code */
xdr_reserve_space(resp->xdr, XDR_UNIT);
resp->tagp = resp->xdr->p;
/* reserve space for: taglen, tag, and opcnt */
xdr_reserve_space(resp->xdr, XDR_UNIT * 2 + args->taglen);
resp->taglen = args->taglen;
......
......@@ -1010,7 +1010,7 @@ static int delegation_blocked(struct knfsd_fh *fh)
}
spin_unlock(&blocked_delegations_lock);
}
hash = jhash(&fh->fh_base, fh->fh_size, 0);
hash = jhash(&fh->fh_raw, fh->fh_size, 0);
if (test_bit(hash&255, bd->set[0]) &&
test_bit((hash>>8)&255, bd->set[0]) &&
test_bit((hash>>16)&255, bd->set[0]))
......@@ -1029,7 +1029,7 @@ static void block_delegations(struct knfsd_fh *fh)
u32 hash;
struct bloom_pair *bd = &blocked_delegations;
hash = jhash(&fh->fh_base, fh->fh_size, 0);
hash = jhash(&fh->fh_raw, fh->fh_size, 0);
spin_lock(&blocked_delegations_lock);
__set_bit(hash&255, bd->set[bd->new]);
......@@ -5541,7 +5541,7 @@ static void nfsd4_ssc_shutdown_umount(struct nfsd_net *nn)
static void nfsd4_ssc_expire_umount(struct nfsd_net *nn)
{
bool do_wakeup = false;
struct nfsd4_ssc_umount_item *ni = 0;
struct nfsd4_ssc_umount_item *ni = NULL;
struct nfsd4_ssc_umount_item *tmp;
spin_lock(&nn->nfsd_ssc_lock);
......
......@@ -2322,7 +2322,7 @@ nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op)
return true;
}
static int
static bool
nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
{
struct nfsd4_op *op;
......@@ -2335,25 +2335,25 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
int i;
if (xdr_stream_decode_u32(argp->xdr, &argp->taglen) < 0)
return 0;
return false;
max_reply += XDR_UNIT;
argp->tag = NULL;
if (unlikely(argp->taglen)) {
if (argp->taglen > NFSD4_MAX_TAGLEN)
return 0;
return false;
p = xdr_inline_decode(argp->xdr, argp->taglen);
if (!p)
return 0;
return false;
argp->tag = svcxdr_savemem(argp, p, argp->taglen);
if (!argp->tag)
return 0;
return false;
max_reply += xdr_align_size(argp->taglen);
}
if (xdr_stream_decode_u32(argp->xdr, &argp->minorversion) < 0)
return 0;
return false;
if (xdr_stream_decode_u32(argp->xdr, &argp->opcnt) < 0)
return 0;
return false;
/*
* NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS
......@@ -2361,14 +2361,14 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
* nfsd4_proc can handle this is an NFS-level error.
*/
if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
return 1;
return true;
if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
if (!argp->ops) {
argp->ops = argp->iops;
dprintk("nfsd: couldn't allocate room for COMPOUND\n");
return 0;
return false;
}
}
......@@ -2380,7 +2380,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
op->replay = NULL;
if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0)
return 0;
return false;
if (nfsd4_opnum_in_range(argp, op)) {
op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
if (op->status != nfs_ok)
......@@ -2427,7 +2427,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack)
clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags);
return 1;
return true;
}
static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
......@@ -3110,7 +3110,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
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;
*p++ = resp->cstate.status;
rqstp->rq_next_page = resp->xdr->page_ptr + 1;
rqstp->rq_next_page = xdr->page_ptr + 1;
p = resp->tagp;
*p++ = htonl(resp->taglen);
memcpy(p, resp->tag, resp->taglen);
p += XDR_QUADLEN(resp->taglen);
*p++ = htonl(resp->opcnt);
nfsd4_sequence_done(resp);
return 1;
return true;
}
......@@ -241,8 +241,8 @@ lru_put_end(struct nfsd_drc_bucket *b, struct svc_cacherep *rp)
list_move_tail(&rp->c_lru, &b->lru_head);
}
static long
prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn)
static long prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn,
unsigned int max)
{
struct svc_cacherep *rp, *tmp;
long freed = 0;
......@@ -258,11 +258,17 @@ prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn)
time_before(jiffies, rp->c_timestamp + RC_EXPIRE))
break;
nfsd_reply_cache_free_locked(b, rp, nn);
freed++;
if (max && freed++ > max)
break;
}
return freed;
}
static long nfsd_prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn)
{
return prune_bucket(b, nn, 3);
}
/*
* Walk the LRU list and prune off entries that are older than RC_EXPIRE.
* Also prune the oldest ones when the total exceeds the max number of entries.
......@@ -279,7 +285,7 @@ prune_cache_entries(struct nfsd_net *nn)
if (list_empty(&b->lru_head))
continue;
spin_lock(&b->cache_lock);
freed += prune_bucket(b, nn);
freed += prune_bucket(b, nn, 0);
spin_unlock(&b->cache_lock);
}
return freed;
......@@ -453,8 +459,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp)
atomic_inc(&nn->num_drc_entries);
nfsd_stats_drc_mem_usage_add(nn, sizeof(*rp));
/* go ahead and prune the cache */
prune_bucket(b, nn);
nfsd_prune_bucket(b, nn);
out_unlock:
spin_unlock(&b->cache_lock);
......
......@@ -395,12 +395,12 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
auth_domain_put(dom);
if (len)
return len;
mesg = buf;
len = SIMPLE_TRANSACTION_LIMIT;
qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
qword_addhex(&mesg, &len, fh.fh_raw, fh.fh_size);
mesg[-1] = '\n';
return mesg - buf;
return mesg - buf;
}
/*
......
......@@ -78,8 +78,10 @@ extern const struct seq_operations nfs_exports_op;
*/
struct nfsd_voidargs { };
struct nfsd_voidres { };
int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p);
int nfssvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p);
bool nfssvc_decode_voidarg(struct svc_rqst *rqstp,
struct xdr_stream *xdr);
bool nfssvc_encode_voidres(struct svc_rqst *rqstp,
struct xdr_stream *xdr);
/*
* Function prototypes.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment