Commit e0963ce5 authored by Sergey Bashirov's avatar Sergey Bashirov Committed by Chuck Lever
Browse files

NFSD: Allow layoutcommit during grace period



If the loca_reclaim field is set to TRUE, this indicates that the client
is attempting to commit changes to a layout after the restart of the
metadata server during the metadata server's recovery grace period. This
type of request may be necessary when the client has uncommitted writes
to provisionally allocated byte-ranges of a file that were sent to the
storage devices before the restart of the metadata server. See RFC 8881,
section 18.42.3.

Without this, the client is not able to increase the file size and commit
preallocated extents when the block/scsi layout server is restarted
during a write and is in a grace period. And when the grace period ends,
the client also cannot perform layoutcommit because the old layout state
becomes invalid, resulting in file corruption.

Co-developed-by: default avatarKonstantin Evtushenko <koevtushenko@yandex.com>
Signed-off-by: default avatarKonstantin Evtushenko <koevtushenko@yandex.com>
Signed-off-by: default avatarSergey Bashirov <sergeybashirov@gmail.com>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent db155b7c
Loading
Loading
Loading
Loading
+25 −13
Original line number Diff line number Diff line
@@ -2526,6 +2526,7 @@ static __be32
nfsd4_layoutcommit(struct svc_rqst *rqstp,
		struct nfsd4_compound_state *cstate, union nfsd4_op_u *u)
{
	struct net *net = SVC_NET(rqstp);
	struct nfsd4_layoutcommit *lcp = &u->layoutcommit;
	const struct nfsd4_layout_seg *seg = &lcp->lc_seg;
	struct svc_fh *current_fh = &cstate->current_fh;
@@ -2561,9 +2562,16 @@ nfsd4_layoutcommit(struct svc_rqst *rqstp,
		}
	}

	nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lcp->lc_sid,
						false, lcp->lc_layout_type,
						&ls);
	nfserr = nfserr_grace;
	if (locks_in_grace(net) && !lcp->lc_reclaim)
		goto out;
	nfserr = nfserr_no_grace;
	if (!locks_in_grace(net) && lcp->lc_reclaim)
		goto out;

	if (!lcp->lc_reclaim) {
		nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate,
				&lcp->lc_sid, false, lcp->lc_layout_type, &ls);
		if (nfserr) {
			trace_nfsd_layout_commit_lookup_fail(&lcp->lc_sid);
			/* fixup error code as per RFC5661 */
@@ -2574,10 +2582,14 @@ nfsd4_layoutcommit(struct svc_rqst *rqstp,

		/* LAYOUTCOMMIT does not require any serialization */
		mutex_unlock(&ls->ls_mutex);
	}

	nfserr = ops->proc_layoutcommit(inode, rqstp, lcp);

	if (!lcp->lc_reclaim) {
		nfsd4_file_mark_deleg_written(ls->ls_stid.sc_file);
		nfs4_put_stid(&ls->ls_stid);
	}
out:
	return nfserr;
}