diff mbox series

[2/3] NFSv4: Refactor nfs_need_update_open_stateid()

Message ID d6c4cd73c3546057edfe8d80512b274bb431d68e.1600686204.git.bcodding@redhat.com
State New
Headers show
Series [1/3] NFSv4: Fix a livelock when CLOSE pre-emptively bumps state sequence | expand

Commit Message

Benjamin Coddington Sept. 21, 2020, 11:04 a.m. UTC
The logic was becoming difficult to follow.  Add some comments and local
variables to clarify the behavior.

Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
---
 fs/nfs/nfs4proc.c | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

Comments

Benjamin Coddington Sept. 21, 2020, 11:17 a.m. UTC | #1
NACK.  Please drop this patch..  This is a junk version of this patch 
that I was
using for debugging that I sent by mistake.  I'll send a cleaned up 
version separately.

Ben

On 21 Sep 2020, at 7:04, Benjamin Coddington wrote:

> The logic was becoming difficult to follow.  Add some comments and 
> local
> variables to clarify the behavior.
>
> Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
> ---
>  fs/nfs/nfs4proc.c | 39 +++++++++++++++++++++++++--------------
>  1 file changed, 25 insertions(+), 14 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 9ced7a62c05e..499f978d48aa 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -1568,23 +1568,34 @@ static void 
> nfs_test_and_clear_all_open_stateid(struct nfs4_state *state)
>  static bool nfs_need_update_open_stateid(struct nfs4_state *state,
>  		const nfs4_stateid *stateid)
>  {
> -	if (test_bit(NFS_OPEN_STATE, &state->flags) == 0 ||
> -	    !nfs4_stateid_match_other(stateid, &state->open_stateid)) {
> -		if (stateid->seqid == cpu_to_be32(1)) {
> +	bool state_matches_other = nfs4_stateid_match_other(stateid, 
> &state->open_stateid);
> +	bool seqid_one = stateid->seqid == cpu_to_be32(1);
> +
> +	if (test_bit(NFS_OPEN_STATE, &state->flags)) {
> +		/* The common case - we're updating to a new sequence number */
> +		if (state_matches_other && nfs4_stateid_is_newer(stateid, 
> &state->open_stateid)) {
> +			nfs_state_log_out_of_order_open_stateid(state, stateid);
> +			return true;
> +		}
> +		/* We lost a race with a self-bumping close, do recovery */
> +		if (!state_matches_other) {
> +			trace_printk("lost race to self-bump close\n");
> +			return false;
> +		}
> +	} else {
> +		/* The common case, this is the first OPEN */
> +		if (!state_matches_other && seqid_one) {
>  			nfs_state_log_update_open_stateid(state);
> -		} else {
> -			if (!nfs4_stateid_match_other(stateid, &state->open_stateid))
> -				return false;
> -			else
> -				set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
> +			return true;
> +		}
> +		/* We lost a race either with a self-bumping close, OR with the 
> first OPEN */
> +		if (!state_matches_other && !seqid_one) {
> +			trace_printk("lost race to self-bump close OR first OPEN\n");
> +			set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
> +			return true;
>  		}
> -		return true;
> -	}
> -
> -	if (nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
> -		nfs_state_log_out_of_order_open_stateid(state, stateid);
> -		return true;
>  	}
> +	/* Should be impossible to reach: */
>  	return false;
>  }
>
> -- 
> 2.20.1
diff mbox series

Patch

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9ced7a62c05e..499f978d48aa 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1568,23 +1568,34 @@  static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state)
 static bool nfs_need_update_open_stateid(struct nfs4_state *state,
 		const nfs4_stateid *stateid)
 {
-	if (test_bit(NFS_OPEN_STATE, &state->flags) == 0 ||
-	    !nfs4_stateid_match_other(stateid, &state->open_stateid)) {
-		if (stateid->seqid == cpu_to_be32(1)) {
+	bool state_matches_other = nfs4_stateid_match_other(stateid, &state->open_stateid);
+	bool seqid_one = stateid->seqid == cpu_to_be32(1);
+
+	if (test_bit(NFS_OPEN_STATE, &state->flags)) {
+		/* The common case - we're updating to a new sequence number */
+		if (state_matches_other && nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
+			nfs_state_log_out_of_order_open_stateid(state, stateid);
+			return true;
+		}
+		/* We lost a race with a self-bumping close, do recovery */
+		if (!state_matches_other) {
+			trace_printk("lost race to self-bump close\n");
+			return false;
+		}
+	} else {
+		/* The common case, this is the first OPEN */
+		if (!state_matches_other && seqid_one) {
 			nfs_state_log_update_open_stateid(state);
-		} else {
-			if (!nfs4_stateid_match_other(stateid, &state->open_stateid))
-				return false;
-			else
-				set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
+			return true;
+		}
+		/* We lost a race either with a self-bumping close, OR with the first OPEN */
+		if (!state_matches_other && !seqid_one) {
+			trace_printk("lost race to self-bump close OR first OPEN\n");
+			set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
+			return true;
 		}
-		return true;
-	}
-
-	if (nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
-		nfs_state_log_out_of_order_open_stateid(state, stateid);
-		return true;
 	}
+	/* Should be impossible to reach: */
 	return false;
 }