From: Trond Myklebust <[email protected]>
According to RFC1813: "If count is 0, the WRITE will succeed
and return a count of 0, barring errors due to permissions checking."
Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfsd/vfs.c | 3 +++
net/sunrpc/svc.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index eb9818432149..85e579aa6944 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -967,6 +967,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
trace_nfsd_write_opened(rqstp, fhp, offset, *cnt);
+ if (!*cnt)
+ return nfs_ok;
+
if (sb->s_export_op)
exp_op_flags = sb->s_export_op->flags;
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 4292278a9552..72a7822fd257 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1638,7 +1638,7 @@ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
* entirely in rq_arg.pages. In this case, @first is empty.
*/
i = 0;
- if (first->iov_len) {
+ if (first->iov_len || !total) {
vec[i].iov_base = first->iov_base;
vec[i].iov_len = min_t(size_t, total, first->iov_len);
total -= vec[i].iov_len;
--
2.33.1
From: Trond Myklebust <[email protected]>
Since a clone error commit can cause the boot verifier to change,
we should trace those errors.
Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfsd/nfs4proc.c | 2 +-
fs/nfsd/trace.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++
fs/nfsd/vfs.c | 18 +++++++++++++++--
fs/nfsd/vfs.h | 3 ++-
4 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index a36261f89bdf..35f33959a083 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1101,7 +1101,7 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (status)
goto out;
- status = nfsd4_clone_file_range(src, clone->cl_src_pos,
+ status = nfsd4_clone_file_range(rqstp, src, clone->cl_src_pos,
dst, clone->cl_dst_pos, clone->cl_count,
EX_ISSYNC(cstate->current_fh.fh_export));
diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
index f1e0d3c51bc2..001444d9829d 100644
--- a/fs/nfsd/trace.h
+++ b/fs/nfsd/trace.h
@@ -413,6 +413,56 @@ TRACE_EVENT(nfsd_dirent,
)
)
+DECLARE_EVENT_CLASS(nfsd_copy_err_class,
+ TP_PROTO(struct svc_rqst *rqstp,
+ struct svc_fh *src_fhp,
+ loff_t src_offset,
+ struct svc_fh *dst_fhp,
+ loff_t dst_offset,
+ u64 count,
+ int status),
+ TP_ARGS(rqstp, src_fhp, src_offset, dst_fhp, dst_offset, count, status),
+ TP_STRUCT__entry(
+ __field(u32, xid)
+ __field(u32, src_fh_hash)
+ __field(loff_t, src_offset)
+ __field(u32, dst_fh_hash)
+ __field(loff_t, dst_offset)
+ __field(u64, count)
+ __field(int, status)
+ ),
+ TP_fast_assign(
+ __entry->xid = be32_to_cpu(rqstp->rq_xid);
+ __entry->src_fh_hash = knfsd_fh_hash(&src_fhp->fh_handle);
+ __entry->src_offset = src_offset;
+ __entry->dst_fh_hash = knfsd_fh_hash(&dst_fhp->fh_handle);
+ __entry->dst_offset = dst_offset;
+ __entry->count = count;
+ __entry->status = status;
+ ),
+ TP_printk("xid=0x%08x src_fh_hash=0x%08x src_offset=%lld "
+ "dst_fh_hash=0x%08x dst_offset=%lld "
+ "count=%llu status=%d",
+ __entry->xid, __entry->src_fh_hash, __entry->src_offset,
+ __entry->dst_fh_hash, __entry->dst_offset,
+ (unsigned long long)__entry->count,
+ __entry->status)
+)
+
+#define DEFINE_NFSD_COPY_ERR_EVENT(name) \
+DEFINE_EVENT(nfsd_copy_err_class, nfsd_##name, \
+ TP_PROTO(struct svc_rqst *rqstp, \
+ struct svc_fh *src_fhp, \
+ loff_t src_offset, \
+ struct svc_fh *dst_fhp, \
+ loff_t dst_offset, \
+ u64 count, \
+ int status), \
+ TP_ARGS(rqstp, src_fhp, src_offset, dst_fhp, dst_offset, \
+ count, status))
+
+DEFINE_NFSD_COPY_ERR_EVENT(clone_file_range_err);
+
#include "state.h"
#include "filecache.h"
#include "vfs.h"
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 85e579aa6944..4d2964d08097 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -40,6 +40,7 @@
#include "../internal.h"
#include "acl.h"
#include "idmap.h"
+#include "xdr4.h"
#endif /* CONFIG_NFSD_V4 */
#include "nfsd.h"
@@ -517,8 +518,15 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
}
#endif
-__be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
- struct nfsd_file *nf_dst, u64 dst_pos, u64 count, bool sync)
+static struct nfsd4_compound_state *nfsd4_get_cstate(struct svc_rqst *rqstp)
+{
+ return &((struct nfsd4_compoundres *)rqstp->rq_resp)->cstate;
+}
+
+__be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
+ struct nfsd_file *nf_src, u64 src_pos,
+ struct nfsd_file *nf_dst, u64 dst_pos,
+ u64 count, bool sync)
{
struct file *src = nf_src->nf_file;
struct file *dst = nf_dst->nf_file;
@@ -542,6 +550,12 @@ __be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
if (!status)
status = commit_inode_metadata(file_inode(src));
if (status < 0) {
+ trace_nfsd_clone_file_range_err(rqstp,
+ &nfsd4_get_cstate(rqstp)->save_fh,
+ src_pos,
+ &nfsd4_get_cstate(rqstp)->current_fh,
+ dst_pos,
+ count, status);
nfsd_reset_boot_verifier(net_generic(nf_dst->nf_net,
nfsd_net_id));
ret = nfserrno(status);
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 6edae1b9a96e..3dba6397d452 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -57,7 +57,8 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
struct xdr_netobj *);
__be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
struct file *, loff_t, loff_t, int);
-__be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
+__be32 nfsd4_clone_file_range(struct svc_rqst *,
+ struct nfsd_file *nf_src, u64 src_pos,
struct nfsd_file *nf_dst, u64 dst_pos,
u64 count, bool sync);
#endif /* CONFIG_NFSD_V4 */
--
2.33.1
> On Dec 18, 2021, at 8:37 PM, [email protected] wrote:
>
> From: Trond Myklebust <[email protected]>
>
> According to RFC1813: "If count is 0, the WRITE will succeed
> and return a count of 0, barring errors due to permissions checking."
If you resend this series, please move this patch to the front.
> Signed-off-by: Trond Myklebust <[email protected]>
> ---
> fs/nfsd/vfs.c | 3 +++
> net/sunrpc/svc.c | 2 +-
> 2 files changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index eb9818432149..85e579aa6944 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -967,6 +967,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
>
> trace_nfsd_write_opened(rqstp, fhp, offset, *cnt);
>
> + if (!*cnt)
> + return nfs_ok;
> +
> if (sb->s_export_op)
> exp_op_flags = sb->s_export_op->flags;
>
> diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
> index 4292278a9552..72a7822fd257 100644
> --- a/net/sunrpc/svc.c
> +++ b/net/sunrpc/svc.c
> @@ -1638,7 +1638,7 @@ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
> * entirely in rq_arg.pages. In this case, @first is empty.
> */
> i = 0;
> - if (first->iov_len) {
> + if (first->iov_len || !total) {
> vec[i].iov_base = first->iov_base;
> vec[i].iov_len = min_t(size_t, total, first->iov_len);
> total -= vec[i].iov_len;
> --
> 2.33.1
>
--
Chuck Lever
Hi-
> On Dec 18, 2021, at 8:38 PM, [email protected] wrote:
>
> From: Trond Myklebust <[email protected]>
>
> Since a clone error commit can cause the boot verifier to change,
> we should trace those errors.
I've applied this one, but wanted to follow up.
I like the idea of tracing boot verifier reset events. I might
just code something up.
One more comment below.
>
> Signed-off-by: Trond Myklebust <[email protected]>
> ---
> fs/nfsd/nfs4proc.c | 2 +-
> fs/nfsd/trace.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++
> fs/nfsd/vfs.c | 18 +++++++++++++++--
> fs/nfsd/vfs.h | 3 ++-
> 4 files changed, 69 insertions(+), 4 deletions(-)
>
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index a36261f89bdf..35f33959a083 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -1101,7 +1101,7 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> if (status)
> goto out;
>
> - status = nfsd4_clone_file_range(src, clone->cl_src_pos,
> + status = nfsd4_clone_file_range(rqstp, src, clone->cl_src_pos,
> dst, clone->cl_dst_pos, clone->cl_count,
> EX_ISSYNC(cstate->current_fh.fh_export));
>
> diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
> index f1e0d3c51bc2..001444d9829d 100644
> --- a/fs/nfsd/trace.h
> +++ b/fs/nfsd/trace.h
> @@ -413,6 +413,56 @@ TRACE_EVENT(nfsd_dirent,
> )
> )
>
> +DECLARE_EVENT_CLASS(nfsd_copy_err_class,
> + TP_PROTO(struct svc_rqst *rqstp,
> + struct svc_fh *src_fhp,
> + loff_t src_offset,
> + struct svc_fh *dst_fhp,
> + loff_t dst_offset,
> + u64 count,
> + int status),
> + TP_ARGS(rqstp, src_fhp, src_offset, dst_fhp, dst_offset, count, status),
> + TP_STRUCT__entry(
> + __field(u32, xid)
> + __field(u32, src_fh_hash)
> + __field(loff_t, src_offset)
> + __field(u32, dst_fh_hash)
> + __field(loff_t, dst_offset)
> + __field(u64, count)
> + __field(int, status)
> + ),
> + TP_fast_assign(
> + __entry->xid = be32_to_cpu(rqstp->rq_xid);
> + __entry->src_fh_hash = knfsd_fh_hash(&src_fhp->fh_handle);
> + __entry->src_offset = src_offset;
> + __entry->dst_fh_hash = knfsd_fh_hash(&dst_fhp->fh_handle);
> + __entry->dst_offset = dst_offset;
> + __entry->count = count;
> + __entry->status = status;
> + ),
> + TP_printk("xid=0x%08x src_fh_hash=0x%08x src_offset=%lld "
> + "dst_fh_hash=0x%08x dst_offset=%lld "
> + "count=%llu status=%d",
> + __entry->xid, __entry->src_fh_hash, __entry->src_offset,
> + __entry->dst_fh_hash, __entry->dst_offset,
> + (unsigned long long)__entry->count,
> + __entry->status)
> +)
> +
> +#define DEFINE_NFSD_COPY_ERR_EVENT(name) \
> +DEFINE_EVENT(nfsd_copy_err_class, nfsd_##name, \
> + TP_PROTO(struct svc_rqst *rqstp, \
> + struct svc_fh *src_fhp, \
> + loff_t src_offset, \
> + struct svc_fh *dst_fhp, \
> + loff_t dst_offset, \
> + u64 count, \
> + int status), \
> + TP_ARGS(rqstp, src_fhp, src_offset, dst_fhp, dst_offset, \
> + count, status))
> +
> +DEFINE_NFSD_COPY_ERR_EVENT(clone_file_range_err);
> +
> #include "state.h"
> #include "filecache.h"
> #include "vfs.h"
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index 85e579aa6944..4d2964d08097 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -40,6 +40,7 @@
> #include "../internal.h"
> #include "acl.h"
> #include "idmap.h"
> +#include "xdr4.h"
> #endif /* CONFIG_NFSD_V4 */
>
> #include "nfsd.h"
> @@ -517,8 +518,15 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
> }
> #endif
>
> -__be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
> - struct nfsd_file *nf_dst, u64 dst_pos, u64 count, bool sync)
> +static struct nfsd4_compound_state *nfsd4_get_cstate(struct svc_rqst *rqstp)
> +{
> + return &((struct nfsd4_compoundres *)rqstp->rq_resp)->cstate;
> +}
> +
> +__be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
> + struct nfsd_file *nf_src, u64 src_pos,
> + struct nfsd_file *nf_dst, u64 dst_pos,
> + u64 count, bool sync)
> {
> struct file *src = nf_src->nf_file;
> struct file *dst = nf_dst->nf_file;
> @@ -542,6 +550,12 @@ __be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
> if (!status)
> status = commit_inode_metadata(file_inode(src));
> if (status < 0) {
> + trace_nfsd_clone_file_range_err(rqstp,
> + &nfsd4_get_cstate(rqstp)->save_fh,
> + src_pos,
> + &nfsd4_get_cstate(rqstp)->current_fh,
> + dst_pos,
> + count, status);
> nfsd_reset_boot_verifier(net_generic(nf_dst->nf_net,
> nfsd_net_id));
> ret = nfserrno(status);
> diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
> index 6edae1b9a96e..3dba6397d452 100644
> --- a/fs/nfsd/vfs.h
> +++ b/fs/nfsd/vfs.h
> @@ -57,7 +57,8 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
> struct xdr_netobj *);
> __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
> struct file *, loff_t, loff_t, int);
> -__be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
> +__be32 nfsd4_clone_file_range(struct svc_rqst *,
> + struct nfsd_file *nf_src, u64 src_pos,
checkpatch.pl complained about the missing "rqstp". I added it before
applying.
> struct nfsd_file *nf_dst, u64 dst_pos,
> u64 count, bool sync);
> #endif /* CONFIG_NFSD_V4 */
> --
> 2.33.1
>
--
Chuck Lever