2023-06-30 01:53:17

by Dai Ngo

[permalink] [raw]
Subject: [PATCH v7 0/4] NFSD: add support for NFSv4.1+ write delegation

The NFSv4 server currently supports read delegation using VFS lease
which is implemented using file_lock.

This patch series add write delegation support for NFSv4.1+ client by:

. remove the check for F_WRLCK in generic_add_lease to allow
file_lock to be used for write delegation.

. grant write delegation for OPEN with NFS4_SHARE_ACCESS_WRITE
if there is no conflict with other OPENs.

Write delegation conflict with another OPEN, REMOVE, RENAME and SETATTR
are handled the same as read delegation using notify_change, try_break_deleg.

The write delegation support is for NFSv4.1+ client only since the NFSv4.0
Linux client behavior is not compliant with RFC 7530 Section 16.7.5. It
expects the server to look ahead in the compound to find a stateid in order
to determine whether the client that sends the GETATTR is the same client
that holds the write delegation. RFC 7530 spec does not call for the server
to look ahead in order to service the GETATTR op.

Changes since v1:

[PATCH 3/4] NFSD: add supports for CB_GETATTR callback
- remove WARN_ON_ONCE from encode_bitmap4
- replace decode_bitmap4 with xdr_stream_decode_uint32_array
- replace xdr_inline_decode and xdr_decode_hyper in decode_cb_getattr
with xdr_stream_decode_u64. Also remove the un-needed likely().
- modify signature of encode_cb_getattr4args to take pointer to
nfs4_cb_fattr
- replace decode_attr_length with xdr_stream_decode_u32
- rename decode_cb_getattr to decode_cb_fattr4
- fold the initialization of cb_cinfo and cb_fsize into decode_cb_fattr4
- rename ncf_cb_cinfo to ncf_cb_change to avoid confusion of cindo usage
in fs/nfsd/nfs4xdr.c
- correct NFS4_dec_cb_getattr_sz and update size description

[PATCH 4/4] NFSD: handle GETATTR conflict with write delegation
- change nfs4_handle_wrdeleg_conflict returns __be32 to fix test robot
- change ncf_cb_cinfo to ncf_cb_change to avoid confusion of cindo usage
in fs/nfsd/nfs4xdr.c

Changes since v2:

[PATCH 2/4] NFSD: enable support for write delegation
- rename 'deleg' to 'dl_type' in nfs4_set_delegation
- remove 'wdeleg' in nfs4_open_delegation

- drop [PATCH 3/4] NFSD: add supports for CB_GETATTR callback
and [PATCH 4/4] NFSD: handle GETATTR conflict with write delegation
for futher clarification of the benefits of these patches

Changes since v3:

- recall write delegation when there is GETATTR from 2nd client
- add trace point to track when write delegation is granted

Changes since v4:
- squash 4/4 into 2/4
- apply 1/4 last instead of first
- combine nfs4_wrdeleg_filelock and nfs4_handle_wrdeleg_conflict to
nfsd4_deleg_getattr_conflict and move it to fs/nfsd/nfs4state.c
- check for lock belongs to delegation before proceed and do it
under the fl_lock
- check and skip FL_LAYOUT file_locks

Changes since v5:
- [patch 2/5] disable write delegation for NFSv4.0 client

- [patch 4/5] allow client to use write delegation stateid for READ (same
behavior as Solaris server)

When the server receives a READ request with write delegation stateid
the server may returns the NFS4ERR_OPENMODE or allows the READ to proceed
to accommodate clients whose WRITE implementation may unavoidably do reads
(e.g., due to buffer cache constraints). Per RFC 8881 section 9.1.2. Use
of the Stateid and Locking

Returning NFS4ERR_OPENMODE causes the client and server to enter an infinite
loop of READ, NFS4ERR_OPENMODE, TEST_STATEID, READs, NFS4ERR_OPENMODEs,
TEST_STATEID, READs, NFS4ERR_OPENMODEs. The Linux NFS client can not recover
from NFS4ERR_OPENMODE for READ request if the file was opened with
OPEN4_SHARE_ACCESS_WRITE. This READ was initiated internally from the NFS
client and not from the read(2) system call.

- pass git regression test with 40 threads

Changes since v6:

- [patch 2/4] Patch 'NFSD: allow client to use write delegation stateid for READ'
was moved to before patch 'NFSD: Enable write delegation support for NFSv4.1+
client' to avoid bisect error.

- [patch 4/4] Update comment on why write delegation for NFSv4.0 client is
not supported.
Move to last in the series.

- [patch 3/4] Correct typo in function comment of nfsd4_deleg_getattr_conflict.
Add comment on the need for CB_GETATTR in commit message.

Squash patch 'NFSD: add counter for write delegation recall due to conflict
GETATTR' into this patch.


2023-06-30 02:05:46

by Dai Ngo

[permalink] [raw]
Subject: [PATCH v7 1/4] locks: allow support for write delegation

Remove the check for F_WRLCK in generic_add_lease to allow file_lock
to be used for write delegation.

First consumer is NFSD.

Signed-off-by: Dai Ngo <[email protected]>
---
fs/locks.c | 7 -------
1 file changed, 7 deletions(-)

diff --git a/fs/locks.c b/fs/locks.c
index df8b26a42524..08fb0b4fd4f8 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1729,13 +1729,6 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
if (is_deleg && !inode_trylock(inode))
return -EAGAIN;

- if (is_deleg && arg == F_WRLCK) {
- /* Write delegations are not currently supported: */
- inode_unlock(inode);
- WARN_ON_ONCE(1);
- return -EINVAL;
- }
-
percpu_down_read(&file_rwsem);
spin_lock(&ctx->flc_lock);
time_out_leases(inode, &dispose);
--
2.39.3


2023-06-30 02:06:19

by Dai Ngo

[permalink] [raw]
Subject: [PATCH v7 2/4] NFSD: allow client to use write delegation stateid for READ

Allow NFSv4 client to use write delegation stateid for READ operation.
Per RFC 8881 section 9.1.2. Use of the Stateid and Locking.

Signed-off-by: Dai Ngo <[email protected]>
---
fs/nfsd/nfs4proc.c | 16 ++++++++++++++--
fs/nfsd/nfs4xdr.c | 9 +++++++++
fs/nfsd/xdr4.h | 2 ++
3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 5ae670807449..3fa66cb38780 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -942,8 +942,18 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
/* check stateid */
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
&read->rd_stateid, RD_STATE,
- &read->rd_nf, NULL);
-
+ &read->rd_nf, &read->rd_wd_stid);
+ /*
+ * rd_wd_stid is needed for nfsd4_encode_read to allow write
+ * delegation stateid used for read. Its refcount is decremented
+ * by nfsd4_read_release when read is done.
+ */
+ if (!status && (read->rd_wd_stid->sc_type != NFS4_DELEG_STID ||
+ delegstateid(read->rd_wd_stid)->dl_type !=
+ NFS4_OPEN_DELEGATE_WRITE)) {
+ nfs4_put_stid(read->rd_wd_stid);
+ read->rd_wd_stid = NULL;
+ }
read->rd_rqstp = rqstp;
read->rd_fhp = &cstate->current_fh;
return status;
@@ -953,6 +963,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
static void
nfsd4_read_release(union nfsd4_op_u *u)
{
+ if (u->read.rd_wd_stid)
+ nfs4_put_stid(u->read.rd_wd_stid);
if (u->read.rd_nf)
nfsd_file_put(u->read.rd_nf);
trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp,
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 76db2fe29624..e0640b31d041 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -4120,6 +4120,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
struct file *file;
int starting_len = xdr->buf->len;
__be32 *p;
+ fmode_t o_fmode = 0;

if (nfserr)
return nfserr;
@@ -4139,10 +4140,18 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
maxcount = min_t(unsigned long, read->rd_length,
(xdr->buf->buflen - xdr->buf->len));

+ if (read->rd_wd_stid) {
+ /* allow READ using write delegation stateid */
+ o_fmode = file->f_mode;
+ file->f_mode |= FMODE_READ;
+ }
if (file->f_op->splice_read && splice_ok)
nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
else
nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
+ if (o_fmode)
+ file->f_mode = o_fmode;
+
if (nfserr) {
xdr_truncate_encode(xdr, starting_len);
return nfserr;
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 510978e602da..3ccc40f9274a 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -307,6 +307,8 @@ struct nfsd4_read {
struct svc_rqst *rd_rqstp; /* response */
struct svc_fh *rd_fhp; /* response */
u32 rd_eof; /* response */
+
+ struct nfs4_stid *rd_wd_stid; /* internal */
};

struct nfsd4_readdir {
--
2.39.3


2023-06-30 02:07:09

by Dai Ngo

[permalink] [raw]
Subject: [PATCH v7 3/4] NFSD: handle GETATTR conflict with write delegation

If the GETATTR request on a file that has write delegation in effect and
the request attributes include the change info and size attribute then
the write delegation is recalled. If the delegation is returned within
30ms then the GETATTR is serviced as normal otherwise the NFS4ERR_DELAY
error is returned for the GETATTR.

Add counter for write delegation recall due to conflict GETATTR. This is
used to evaluate the need to implement CB_GETATTR to adoid recalling the
delegation with conflit GETATTR.

Signed-off-by: Dai Ngo <[email protected]>
---
fs/nfsd/nfs4state.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
fs/nfsd/nfs4xdr.c | 5 ++++
fs/nfsd/state.h | 3 +++
fs/nfsd/stats.c | 2 ++
fs/nfsd/stats.h | 7 +++++
5 files changed, 83 insertions(+)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6e61fa3acaf1..4c96cfe19531 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -8343,3 +8343,69 @@ nfsd4_get_writestateid(struct nfsd4_compound_state *cstate,
{
get_stateid(cstate, &u->write.wr_stateid);
}
+
+/**
+ * nfsd4_deleg_getattr_conflict - Trigger recall if GETATTR causes conflict
+ * @rqstp: RPC transaction context
+ * @inode: file to be checked for a conflict
+ *
+ * This function is called when there is a conflict between a write
+ * delegation and a change/size GETATTR from another client. The server
+ * must either use the CB_GETATTR to get the current values of the
+ * attributes from the client that hold the delegation or recall the
+ * delegation before replying to the GETATTR. See RFC 8881 section
+ * 18.7.4.
+ *
+ * The current implementation does not support CB_GETATTR yet. However
+ * this feature is considered useful for avoid recalling the delegation
+ * in the case of GETATTR conflict and should be added in the follow up
+ * work.
+ *
+ * Returns 0 if there is no conflict; otherwise an nfs_stat
+ * code is returned.
+ */
+__be32
+nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode)
+{
+ __be32 status;
+ struct file_lock_context *ctx;
+ struct file_lock *fl;
+ struct nfs4_delegation *dp;
+
+ ctx = locks_inode_context(inode);
+ if (!ctx)
+ return 0;
+ spin_lock(&ctx->flc_lock);
+ list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
+ if (fl->fl_flags == FL_LAYOUT)
+ continue;
+ if (fl->fl_lmops != &nfsd_lease_mng_ops) {
+ /*
+ * non-nfs lease, if it's a lease with F_RDLCK then
+ * we are done; there isn't any write delegation
+ * on this inode
+ */
+ if (fl->fl_type == F_RDLCK)
+ break;
+ goto break_lease;
+ }
+ if (fl->fl_type == F_WRLCK) {
+ dp = fl->fl_owner;
+ if (dp->dl_recall.cb_clp == *(rqstp->rq_lease_breaker)) {
+ spin_unlock(&ctx->flc_lock);
+ return 0;
+ }
+break_lease:
+ spin_unlock(&ctx->flc_lock);
+ nfsd_stats_wdeleg_getattr_inc();
+ status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
+ if (status != nfserr_jukebox ||
+ !nfsd_wait_for_delegreturn(rqstp, inode))
+ return status;
+ return 0;
+ }
+ break;
+ }
+ spin_unlock(&ctx->flc_lock);
+ return 0;
+}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index e0640b31d041..833634cdc761 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2966,6 +2966,11 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
if (status)
goto out;
}
+ if (bmval0 & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
+ status = nfsd4_deleg_getattr_conflict(rqstp, d_inode(dentry));
+ if (status)
+ goto out;
+ }

err = vfs_getattr(&path, &stat,
STATX_BASIC_STATS | STATX_BTIME | STATX_CHANGE_COOKIE,
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index d49d3060ed4f..cbddcf484dba 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -732,4 +732,7 @@ static inline bool try_to_expire_client(struct nfs4_client *clp)
cmpxchg(&clp->cl_state, NFSD4_COURTESY, NFSD4_EXPIRABLE);
return clp->cl_state == NFSD4_EXPIRABLE;
}
+
+extern __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp,
+ struct inode *inode);
#endif /* NFSD4_STATE_H */
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 777e24e5da33..63797635e1c3 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -65,6 +65,8 @@ static int nfsd_show(struct seq_file *seq, void *v)
seq_printf(seq, " %lld",
percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_NFS4_OP(i)]));
}
+ seq_printf(seq, "\nwdeleg_getattr %lld",
+ percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_WDELEG_GETATTR]));

seq_putc(seq, '\n');
#endif
diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h
index 9b43dc3d9991..cf5524e7ca06 100644
--- a/fs/nfsd/stats.h
+++ b/fs/nfsd/stats.h
@@ -22,6 +22,7 @@ enum {
NFSD_STATS_FIRST_NFS4_OP, /* count of individual nfsv4 operations */
NFSD_STATS_LAST_NFS4_OP = NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP,
#define NFSD_STATS_NFS4_OP(op) (NFSD_STATS_FIRST_NFS4_OP + (op))
+ NFSD_STATS_WDELEG_GETATTR, /* count of getattr conflict with wdeleg */
#endif
NFSD_STATS_COUNTERS_NUM
};
@@ -93,4 +94,10 @@ static inline void nfsd_stats_drc_mem_usage_sub(struct nfsd_net *nn, s64 amount)
percpu_counter_sub(&nn->counter[NFSD_NET_DRC_MEM_USAGE], amount);
}

+#ifdef CONFIG_NFSD_V4
+static inline void nfsd_stats_wdeleg_getattr_inc(void)
+{
+ percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_WDELEG_GETATTR]);
+}
+#endif
#endif /* _NFSD_STATS_H */
--
2.39.3


2023-06-30 02:07:14

by Dai Ngo

[permalink] [raw]
Subject: [PATCH v7 4/4] NFSD: Enable write delegation support for NFSv4.1+ client

This patch grants write delegations for OPEN with NFS4_SHARE_ACCESS_WRITE
if there is no conflict with other OPENs.

Write delegation conflicts with another OPEN, REMOVE, RENAME and SETATTR
are handled the same as read delegation using notify_change,
try_break_deleg.

The NFSv4.0 protocol does not enable a server to determine that a
conflicting GETATTR originated from the client holding the
delegation versus coming from some other client. With NFSv4.1 and
later, the SEQUENCE operation that begins each COMPOUND contains a
client ID, so delegation recall can be safely squelched in this case.

With NFSv4.0, therefore, the server must recall or send a CB_GETATTR
(per RFC 7530 Section 16.7.5) even when the GETATTR originates from
the client holding that delegation.

An NFSv4.0 client can trigger a pathological situation if it always
sends a DELEGRETURN preceded by a conflicting GETATTR in the same
COMPOUND. COMPOUND execution will always stop at the GETATTR and the
DELEGRETURN will never get executed. The server eventually revokes
the delegation, which can result in loss of open or lock state.

Tracepoint added to track whether read or write delegation is granted.

Signed-off-by: Dai Ngo <[email protected]>
---
fs/nfsd/nfs4state.c | 40 +++++++++++++++++++++++++++++-----------
fs/nfsd/trace.h | 1 +
2 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 4c96cfe19531..15b5043eeca5 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1144,7 +1144,7 @@ static void block_delegations(struct knfsd_fh *fh)

static struct nfs4_delegation *
alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp,
- struct nfs4_clnt_odstate *odstate)
+ struct nfs4_clnt_odstate *odstate, u32 dl_type)
{
struct nfs4_delegation *dp;
long n;
@@ -1170,7 +1170,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp,
INIT_LIST_HEAD(&dp->dl_recall_lru);
dp->dl_clnt_odstate = odstate;
get_clnt_odstate(odstate);
- dp->dl_type = NFS4_OPEN_DELEGATE_READ;
+ dp->dl_type = dl_type;
dp->dl_retries = 1;
dp->dl_recalled = false;
nfsd4_init_cb(&dp->dl_recall, dp->dl_stid.sc_client,
@@ -5451,6 +5451,7 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
struct nfs4_delegation *dp;
struct nfsd_file *nf;
struct file_lock *fl;
+ u32 dl_type;

/*
* The fi_had_conflict and nfs_get_existing_delegation checks
@@ -5460,7 +5461,13 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
if (fp->fi_had_conflict)
return ERR_PTR(-EAGAIN);

- nf = find_readable_file(fp);
+ if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
+ nf = find_writeable_file(fp);
+ dl_type = NFS4_OPEN_DELEGATE_WRITE;
+ } else {
+ nf = find_readable_file(fp);
+ dl_type = NFS4_OPEN_DELEGATE_READ;
+ }
if (!nf) {
/*
* We probably could attempt another open and get a read
@@ -5491,11 +5498,11 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
return ERR_PTR(status);

status = -ENOMEM;
- dp = alloc_init_deleg(clp, fp, odstate);
+ dp = alloc_init_deleg(clp, fp, odstate, dl_type);
if (!dp)
goto out_delegees;

- fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
+ fl = nfs4_alloc_init_lease(dp, dl_type);
if (!fl)
goto out_clnt_odstate;

@@ -5570,8 +5577,13 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
/*
* Attempt to hand out a delegation.
*
- * Note we don't support write delegations, and won't until the vfs has
- * proper support for them.
+ * Note we don't support write delegations for NFSv4.0 client since the Linux
+ * client behavior is not compliant with RFC 7530 Section 16.7.5 with regard
+ * to handle the conflict GETATTR. It expects the server to look ahead in the
+ * compound (PUTFH, GETATTR, DELEGRETURN) to find a stateid in order to
+ * determine whether the client that sends the GETATTR is the same with the
+ * client that holds the write delegation. RFC 7530 spec does not call for
+ * the server to look ahead in order to service the conflict GETATTR op.
*/
static void
nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
@@ -5590,8 +5602,6 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
case NFS4_OPEN_CLAIM_PREVIOUS:
if (!cb_up)
open->op_recall = 1;
- if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ)
- goto out_no_deleg;
break;
case NFS4_OPEN_CLAIM_NULL:
parent = currentfh;
@@ -5606,6 +5616,9 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
goto out_no_deleg;
if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
goto out_no_deleg;
+ if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE &&
+ !clp->cl_minorversion)
+ goto out_no_deleg;
break;
default:
goto out_no_deleg;
@@ -5616,8 +5629,13 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,

memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));

- trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
- open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
+ if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
+ open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE;
+ trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
+ } else {
+ open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
+ trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
+ }
nfs4_put_stid(&dp->dl_stid);
return;
out_no_deleg:
diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
index 72a906a053dc..56f28364cc6b 100644
--- a/fs/nfsd/trace.h
+++ b/fs/nfsd/trace.h
@@ -607,6 +607,7 @@ DEFINE_STATEID_EVENT(layout_recall_release);

DEFINE_STATEID_EVENT(open);
DEFINE_STATEID_EVENT(deleg_read);
+DEFINE_STATEID_EVENT(deleg_write);
DEFINE_STATEID_EVENT(deleg_return);
DEFINE_STATEID_EVENT(deleg_recall);

--
2.39.3


2023-06-30 16:03:03

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH v7 4/4] NFSD: Enable write delegation support for NFSv4.1+ client



> On Jun 29, 2023, at 9:52 PM, Dai Ngo <[email protected]> wrote:
>
> This patch grants write delegations for OPEN with NFS4_SHARE_ACCESS_WRITE
> if there is no conflict with other OPENs.
>
> Write delegation conflicts with another OPEN, REMOVE, RENAME and SETATTR
> are handled the same as read delegation using notify_change,
> try_break_deleg.
>
> The NFSv4.0 protocol does not enable a server to determine that a
> conflicting GETATTR originated from the client holding the
> delegation versus coming from some other client. With NFSv4.1 and
> later, the SEQUENCE operation that begins each COMPOUND contains a
> client ID, so delegation recall can be safely squelched in this case.
>
> With NFSv4.0, therefore, the server must recall or send a CB_GETATTR
> (per RFC 7530 Section 16.7.5) even when the GETATTR originates from
> the client holding that delegation.
>
> An NFSv4.0 client can trigger a pathological situation if it always
> sends a DELEGRETURN preceded by a conflicting GETATTR in the same
> COMPOUND. COMPOUND execution will always stop at the GETATTR and the
> DELEGRETURN will never get executed. The server eventually revokes
> the delegation, which can result in loss of open or lock state.
>
> Tracepoint added to track whether read or write delegation is granted.
>
> Signed-off-by: Dai Ngo <[email protected]>
> ---
> fs/nfsd/nfs4state.c | 40 +++++++++++++++++++++++++++++-----------
> fs/nfsd/trace.h | 1 +
> 2 files changed, 30 insertions(+), 11 deletions(-)
>
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 4c96cfe19531..15b5043eeca5 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -1144,7 +1144,7 @@ static void block_delegations(struct knfsd_fh *fh)
>
> static struct nfs4_delegation *
> alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp,
> - struct nfs4_clnt_odstate *odstate)
> + struct nfs4_clnt_odstate *odstate, u32 dl_type)
> {
> struct nfs4_delegation *dp;
> long n;
> @@ -1170,7 +1170,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp,
> INIT_LIST_HEAD(&dp->dl_recall_lru);
> dp->dl_clnt_odstate = odstate;
> get_clnt_odstate(odstate);
> - dp->dl_type = NFS4_OPEN_DELEGATE_READ;
> + dp->dl_type = dl_type;
> dp->dl_retries = 1;
> dp->dl_recalled = false;
> nfsd4_init_cb(&dp->dl_recall, dp->dl_stid.sc_client,
> @@ -5451,6 +5451,7 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
> struct nfs4_delegation *dp;
> struct nfsd_file *nf;
> struct file_lock *fl;
> + u32 dl_type;
>
> /*
> * The fi_had_conflict and nfs_get_existing_delegation checks
> @@ -5460,7 +5461,13 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
> if (fp->fi_had_conflict)
> return ERR_PTR(-EAGAIN);
>
> - nf = find_readable_file(fp);
> + if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
> + nf = find_writeable_file(fp);
> + dl_type = NFS4_OPEN_DELEGATE_WRITE;
> + } else {
> + nf = find_readable_file(fp);
> + dl_type = NFS4_OPEN_DELEGATE_READ;
> + }
> if (!nf) {
> /*
> * We probably could attempt another open and get a read
> @@ -5491,11 +5498,11 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
> return ERR_PTR(status);
>
> status = -ENOMEM;
> - dp = alloc_init_deleg(clp, fp, odstate);
> + dp = alloc_init_deleg(clp, fp, odstate, dl_type);
> if (!dp)
> goto out_delegees;
>
> - fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
> + fl = nfs4_alloc_init_lease(dp, dl_type);
> if (!fl)
> goto out_clnt_odstate;
>
> @@ -5570,8 +5577,13 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
> /*
> * Attempt to hand out a delegation.
> *
> - * Note we don't support write delegations, and won't until the vfs has
> - * proper support for them.
> + * Note we don't support write delegations for NFSv4.0 client since the Linux
> + * client behavior is not compliant with RFC 7530 Section 16.7.5 with regard
> + * to handle the conflict GETATTR. It expects the server to look ahead in the
> + * compound (PUTFH, GETATTR, DELEGRETURN) to find a stateid in order to
> + * determine whether the client that sends the GETATTR is the same with the
> + * client that holds the write delegation. RFC 7530 spec does not call for
> + * the server to look ahead in order to service the conflict GETATTR op.

I'll take these 4 for v6.6, and update this comment to match the patch
description as I apply the patches.


> */
> static void
> nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
> @@ -5590,8 +5602,6 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
> case NFS4_OPEN_CLAIM_PREVIOUS:
> if (!cb_up)
> open->op_recall = 1;
> - if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ)
> - goto out_no_deleg;
> break;
> case NFS4_OPEN_CLAIM_NULL:
> parent = currentfh;
> @@ -5606,6 +5616,9 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
> goto out_no_deleg;
> if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
> goto out_no_deleg;
> + if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE &&
> + !clp->cl_minorversion)
> + goto out_no_deleg;
> break;
> default:
> goto out_no_deleg;
> @@ -5616,8 +5629,13 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
>
> memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
>
> - trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
> - open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
> + if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
> + open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE;
> + trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
> + } else {
> + open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
> + trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
> + }
> nfs4_put_stid(&dp->dl_stid);
> return;
> out_no_deleg:
> diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
> index 72a906a053dc..56f28364cc6b 100644
> --- a/fs/nfsd/trace.h
> +++ b/fs/nfsd/trace.h
> @@ -607,6 +607,7 @@ DEFINE_STATEID_EVENT(layout_recall_release);
>
> DEFINE_STATEID_EVENT(open);
> DEFINE_STATEID_EVENT(deleg_read);
> +DEFINE_STATEID_EVENT(deleg_write);
> DEFINE_STATEID_EVENT(deleg_return);
> DEFINE_STATEID_EVENT(deleg_recall);
>
> --
> 2.39.3
>

--
Chuck Lever



2023-08-11 17:36:39

by Jeffrey Layton

[permalink] [raw]
Subject: Re: [PATCH v7 2/4] NFSD: allow client to use write delegation stateid for READ

On Thu, 2023-06-29 at 18:52 -0700, Dai Ngo wrote:
> Allow NFSv4 client to use write delegation stateid for READ operation.
> Per RFC 8881 section 9.1.2. Use of the Stateid and Locking.
>
> Signed-off-by: Dai Ngo <[email protected]>
> ---
> fs/nfsd/nfs4proc.c | 16 ++++++++++++++--
> fs/nfsd/nfs4xdr.c | 9 +++++++++
> fs/nfsd/xdr4.h | 2 ++
> 3 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index 5ae670807449..3fa66cb38780 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -942,8 +942,18 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> /* check stateid */
> status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
> &read->rd_stateid, RD_STATE,
> - &read->rd_nf, NULL);
> -
> + &read->rd_nf, &read->rd_wd_stid);

I think this patch is causing breakage with pynfs. WRT3 sends a READ
operation with the zero-stateid. On earlier kernels, this works, but a
linux-next kernel?rejects this with BAD_STATEID.

nfs4_preprocess_stateid_op seems to assume that if cstid is set, then
it's a copy operation and anonymous stateids aren't allowed. Maybe that
test should be something besides checking cstid == NULL?

> + /*
> + * rd_wd_stid is needed for nfsd4_encode_read to allow write
> + * delegation stateid used for read. Its refcount is decremented
> + * by nfsd4_read_release when read is done.
> + */
> + if (!status && (read->rd_wd_stid->sc_type != NFS4_DELEG_STID ||
> + delegstateid(read->rd_wd_stid)->dl_type !=
> + NFS4_OPEN_DELEGATE_WRITE)) {
> + nfs4_put_stid(read->rd_wd_stid);
> + read->rd_wd_stid = NULL;
> + }
> read->rd_rqstp = rqstp;
> read->rd_fhp = &cstate->current_fh;
> return status;
> @@ -953,6 +963,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> static void
> nfsd4_read_release(union nfsd4_op_u *u)
> {
> + if (u->read.rd_wd_stid)
> + nfs4_put_stid(u->read.rd_wd_stid);
> if (u->read.rd_nf)
> nfsd_file_put(u->read.rd_nf);
> trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp,
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index 76db2fe29624..e0640b31d041 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -4120,6 +4120,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
> struct file *file;
> int starting_len = xdr->buf->len;
> __be32 *p;
> + fmode_t o_fmode = 0;
>
> if (nfserr)
> return nfserr;
> @@ -4139,10 +4140,18 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
> maxcount = min_t(unsigned long, read->rd_length,
> (xdr->buf->buflen - xdr->buf->len));
>
> + if (read->rd_wd_stid) {
> + /* allow READ using write delegation stateid */
> + o_fmode = file->f_mode;
> + file->f_mode |= FMODE_READ;
> + }
> if (file->f_op->splice_read && splice_ok)
> nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
> else
> nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
> + if (o_fmode)
> + file->f_mode = o_fmode;
> +
> if (nfserr) {
> xdr_truncate_encode(xdr, starting_len);
> return nfserr;
> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> index 510978e602da..3ccc40f9274a 100644
> --- a/fs/nfsd/xdr4.h
> +++ b/fs/nfsd/xdr4.h
> @@ -307,6 +307,8 @@ struct nfsd4_read {
> struct svc_rqst *rd_rqstp; /* response */
> struct svc_fh *rd_fhp; /* response */
> u32 rd_eof; /* response */
> +
> + struct nfs4_stid *rd_wd_stid; /* internal */
> };
>
> struct nfsd4_readdir {

--
Jeff Layton <[email protected]>

2023-08-11 18:10:27

by Dai Ngo

[permalink] [raw]
Subject: Re: [PATCH v7 2/4] NFSD: allow client to use write delegation stateid for READ

Hi Jeff,

I have not looked at this carefully, but since now we only grant
write delegation for OPEN with both read and write access then
perhaps this patch is no longer needed?

-Dai

On 8/11/23 10:22 AM, Jeff Layton wrote:
> On Thu, 2023-06-29 at 18:52 -0700, Dai Ngo wrote:
>> Allow NFSv4 client to use write delegation stateid for READ operation.
>> Per RFC 8881 section 9.1.2. Use of the Stateid and Locking.
>>
>> Signed-off-by: Dai Ngo <[email protected]>
>> ---
>> fs/nfsd/nfs4proc.c | 16 ++++++++++++++--
>> fs/nfsd/nfs4xdr.c | 9 +++++++++
>> fs/nfsd/xdr4.h | 2 ++
>> 3 files changed, 25 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
>> index 5ae670807449..3fa66cb38780 100644
>> --- a/fs/nfsd/nfs4proc.c
>> +++ b/fs/nfsd/nfs4proc.c
>> @@ -942,8 +942,18 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>> /* check stateid */
>> status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
>> &read->rd_stateid, RD_STATE,
>> - &read->rd_nf, NULL);
>> -
>> + &read->rd_nf, &read->rd_wd_stid);
> I think this patch is causing breakage with pynfs. WRT3 sends a READ
> operation with the zero-stateid. On earlier kernels, this works, but a
> linux-next kernel rejects this with BAD_STATEID.
>
> nfs4_preprocess_stateid_op seems to assume that if cstid is set, then
> it's a copy operation and anonymous stateids aren't allowed. Maybe that
> test should be something besides checking cstid == NULL?
>
>> + /*
>> + * rd_wd_stid is needed for nfsd4_encode_read to allow write
>> + * delegation stateid used for read. Its refcount is decremented
>> + * by nfsd4_read_release when read is done.
>> + */
>> + if (!status && (read->rd_wd_stid->sc_type != NFS4_DELEG_STID ||
>> + delegstateid(read->rd_wd_stid)->dl_type !=
>> + NFS4_OPEN_DELEGATE_WRITE)) {
>> + nfs4_put_stid(read->rd_wd_stid);
>> + read->rd_wd_stid = NULL;
>> + }
>> read->rd_rqstp = rqstp;
>> read->rd_fhp = &cstate->current_fh;
>> return status;
>> @@ -953,6 +963,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>> static void
>> nfsd4_read_release(union nfsd4_op_u *u)
>> {
>> + if (u->read.rd_wd_stid)
>> + nfs4_put_stid(u->read.rd_wd_stid);
>> if (u->read.rd_nf)
>> nfsd_file_put(u->read.rd_nf);
>> trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp,
>> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
>> index 76db2fe29624..e0640b31d041 100644
>> --- a/fs/nfsd/nfs4xdr.c
>> +++ b/fs/nfsd/nfs4xdr.c
>> @@ -4120,6 +4120,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
>> struct file *file;
>> int starting_len = xdr->buf->len;
>> __be32 *p;
>> + fmode_t o_fmode = 0;
>>
>> if (nfserr)
>> return nfserr;
>> @@ -4139,10 +4140,18 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
>> maxcount = min_t(unsigned long, read->rd_length,
>> (xdr->buf->buflen - xdr->buf->len));
>>
>> + if (read->rd_wd_stid) {
>> + /* allow READ using write delegation stateid */
>> + o_fmode = file->f_mode;
>> + file->f_mode |= FMODE_READ;
>> + }
>> if (file->f_op->splice_read && splice_ok)
>> nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
>> else
>> nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
>> + if (o_fmode)
>> + file->f_mode = o_fmode;
>> +
>> if (nfserr) {
>> xdr_truncate_encode(xdr, starting_len);
>> return nfserr;
>> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
>> index 510978e602da..3ccc40f9274a 100644
>> --- a/fs/nfsd/xdr4.h
>> +++ b/fs/nfsd/xdr4.h
>> @@ -307,6 +307,8 @@ struct nfsd4_read {
>> struct svc_rqst *rd_rqstp; /* response */
>> struct svc_fh *rd_fhp; /* response */
>> u32 rd_eof; /* response */
>> +
>> + struct nfs4_stid *rd_wd_stid; /* internal */
>> };
>>
>> struct nfsd4_readdir {

2023-08-11 20:11:12

by Jeffrey Layton

[permalink] [raw]
Subject: Re: [PATCH v7 2/4] NFSD: allow client to use write delegation stateid for READ

Yep. Reverting that patch seemed to fix the problem. Chuck, mind just
dropping this patch from nfsd-next?

Thanks,
Jeff


On Fri, 2023-08-11 at 10:47 -0700, [email protected] wrote:
> Hi Jeff,
>
> I have not looked at this carefully, but since now we only grant
> write delegation for OPEN with both read and write access then
> perhaps this patch is no longer needed?
>
> -Dai
>
> On 8/11/23 10:22 AM, Jeff Layton wrote:
> > On Thu, 2023-06-29 at 18:52 -0700, Dai Ngo wrote:
> > > Allow NFSv4 client to use write delegation stateid for READ operation.
> > > Per RFC 8881 section 9.1.2. Use of the Stateid and Locking.
> > >
> > > Signed-off-by: Dai Ngo <[email protected]>
> > > ---
> > > fs/nfsd/nfs4proc.c | 16 ++++++++++++++--
> > > fs/nfsd/nfs4xdr.c | 9 +++++++++
> > > fs/nfsd/xdr4.h | 2 ++
> > > 3 files changed, 25 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> > > index 5ae670807449..3fa66cb38780 100644
> > > --- a/fs/nfsd/nfs4proc.c
> > > +++ b/fs/nfsd/nfs4proc.c
> > > @@ -942,8 +942,18 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> > > /* check stateid */
> > > status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
> > > &read->rd_stateid, RD_STATE,
> > > - &read->rd_nf, NULL);
> > > -
> > > + &read->rd_nf, &read->rd_wd_stid);
> > I think this patch is causing breakage with pynfs. WRT3 sends a READ
> > operation with the zero-stateid. On earlier kernels, this works, but a
> > linux-next kernel?rejects this with BAD_STATEID.
> >
> > nfs4_preprocess_stateid_op seems to assume that if cstid is set, then
> > it's a copy operation and anonymous stateids aren't allowed. Maybe that
> > test should be something besides checking cstid == NULL?
> >
> > > + /*
> > > + * rd_wd_stid is needed for nfsd4_encode_read to allow write
> > > + * delegation stateid used for read. Its refcount is decremented
> > > + * by nfsd4_read_release when read is done.
> > > + */
> > > + if (!status && (read->rd_wd_stid->sc_type != NFS4_DELEG_STID ||
> > > + delegstateid(read->rd_wd_stid)->dl_type !=
> > > + NFS4_OPEN_DELEGATE_WRITE)) {
> > > + nfs4_put_stid(read->rd_wd_stid);
> > > + read->rd_wd_stid = NULL;
> > > + }
> > > read->rd_rqstp = rqstp;
> > > read->rd_fhp = &cstate->current_fh;
> > > return status;
> > > @@ -953,6 +963,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> > > static void
> > > nfsd4_read_release(union nfsd4_op_u *u)
> > > {
> > > + if (u->read.rd_wd_stid)
> > > + nfs4_put_stid(u->read.rd_wd_stid);
> > > if (u->read.rd_nf)
> > > nfsd_file_put(u->read.rd_nf);
> > > trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp,
> > > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> > > index 76db2fe29624..e0640b31d041 100644
> > > --- a/fs/nfsd/nfs4xdr.c
> > > +++ b/fs/nfsd/nfs4xdr.c
> > > @@ -4120,6 +4120,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
> > > struct file *file;
> > > int starting_len = xdr->buf->len;
> > > __be32 *p;
> > > + fmode_t o_fmode = 0;
> > >
> > > if (nfserr)
> > > return nfserr;
> > > @@ -4139,10 +4140,18 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
> > > maxcount = min_t(unsigned long, read->rd_length,
> > > (xdr->buf->buflen - xdr->buf->len));
> > >
> > > + if (read->rd_wd_stid) {
> > > + /* allow READ using write delegation stateid */
> > > + o_fmode = file->f_mode;
> > > + file->f_mode |= FMODE_READ;
> > > + }
> > > if (file->f_op->splice_read && splice_ok)
> > > nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
> > > else
> > > nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
> > > + if (o_fmode)
> > > + file->f_mode = o_fmode;
> > > +
> > > if (nfserr) {
> > > xdr_truncate_encode(xdr, starting_len);
> > > return nfserr;
> > > diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> > > index 510978e602da..3ccc40f9274a 100644
> > > --- a/fs/nfsd/xdr4.h
> > > +++ b/fs/nfsd/xdr4.h
> > > @@ -307,6 +307,8 @@ struct nfsd4_read {
> > > struct svc_rqst *rd_rqstp; /* response */
> > > struct svc_fh *rd_fhp; /* response */
> > > u32 rd_eof; /* response */
> > > +
> > > + struct nfs4_stid *rd_wd_stid; /* internal */
> > > };
> > >
> > > struct nfsd4_readdir {

--
Jeff Layton <[email protected]>

2023-08-11 20:16:29

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH v7 2/4] NFSD: allow client to use write delegation stateid for READ



> On Aug 11, 2023, at 3:06 PM, Jeff Layton <[email protected]> wrote:
>
> Yep. Reverting that patch seemed to fix the problem. Chuck, mind just
> dropping this patch from nfsd-next?

I can, but let's make sure that doesn't break anything else first.
Send me any test results, and I'll run some tests here too.


--
Chuck Lever



2023-08-11 20:59:42

by Jeffrey Layton

[permalink] [raw]
Subject: Re: [PATCH v7 2/4] NFSD: allow client to use write delegation stateid for READ

On Fri, 2023-08-11 at 19:08 +0000, Chuck Lever III wrote:
>
> > On Aug 11, 2023, at 3:06 PM, Jeff Layton <[email protected]> wrote:
> >
> > Yep. Reverting that patch seemed to fix the problem. Chuck, mind just
> > dropping this patch from nfsd-next?
>
> I can, but let's make sure that doesn't break anything else first.
> Send me any test results, and I'll run some tests here too.
>
>

Sure, results attached from several runs. These are running "all" tests
in pynfs for both v4.0 and v4.1. The kernels are:

6.5.0-rc5-00050-gb1e667caad15: your nfsd-next branch as of today
6.5.0-rc5+: gb1e667caad15, but with this patch reverted

In summary:

[jlayton@tleilax pynfs-results]$ grep '"failures":' *
6.4.0-v4.0.json: "failures": 0,
6.4.0-v4.1.json: "failures": 0,
6.5.0-rc5-00050-gb1e667caad15-v4.0.json: "failures": 17,
6.5.0-rc5-00050-gb1e667caad15-v4.1.json: "failures": 1,
6.5.0-rc5-v4.0.json: "failures": 3,
6.5.0-rc5+-v4.0.json: "failures": 0,
6.5.0-rc5-v4.1.json: "failures": 0,
6.5.0-rc5+-v4.1.json: "failures": 0,

So, reverting this patch makes things look good in nfsd-next.

The more worrisome problem is that 6.5.0-rc5-v4.0.json shows 3
regressions in current mainline. It looks like some sort of data
corruption at first glance.

I'm still looking at that one.
--
Jeff Layton <[email protected]>


Attachments:
pynfs-results.tar.xz (38.64 kB)

2023-08-12 03:42:49

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH v7 2/4] NFSD: allow client to use write delegation stateid for READ



> On Aug 11, 2023, at 4:33 PM, Jeff Layton <[email protected]> wrote:
>
> On Fri, 2023-08-11 at 19:08 +0000, Chuck Lever III wrote:
>>
>>> On Aug 11, 2023, at 3:06 PM, Jeff Layton <[email protected]> wrote:
>>>
>>> Yep. Reverting that patch seemed to fix the problem. Chuck, mind just
>>> dropping this patch from nfsd-next?
>>
>> I can, but let's make sure that doesn't break anything else first.
>> Send me any test results, and I'll run some tests here too.
>
> Sure, results attached from several runs. These are running "all" tests
> in pynfs for both v4.0 and v4.1. The kernels are:
>
> 6.5.0-rc5-00050-gb1e667caad15: your nfsd-next branch as of today
> 6.5.0-rc5+: gb1e667caad15, but with this patch reverted

I haven't found any problems either, so I've dropped the patch
and refreshed nfsd-next and topic-sunrpc-thread-scheduling.


--
Chuck Lever