Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d24433cd authored by Benny Halevy's avatar Benny Halevy Committed by J. Bruce Fields
Browse files

nfsd41: implement NFS4_SHARE_WANT_NO_DELEG, NFS4_OPEN_DELEGATE_NONE_EXT, why_no_deleg



Respect client request for not getting a delegation in NFSv4.1
Appropriately return delegation "type" NFS4_OPEN_DELEGATE_NONE_EXT
and WND4_NOT_WANTED reason.

[nfsd41: add missing break when encoding op_why_no_deleg]
Signed-off-by: default avatarBenny Halevy <bhalevy@tonian.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 03cfb420
Loading
Loading
Loading
Loading
+53 −7
Original line number Original line Diff line number Diff line
@@ -2866,7 +2866,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
	struct nfs4_delegation *dp;
	struct nfs4_delegation *dp;
	struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
	struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
	int cb_up;
	int cb_up;
	int status, flag = 0;
	int status = 0, flag = 0;


	cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
	cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
	flag = NFS4_OPEN_DELEGATE_NONE;
	flag = NFS4_OPEN_DELEGATE_NONE;
@@ -2907,11 +2907,32 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
	dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
	dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
		STATEID_VAL(&dp->dl_stid.sc_stateid));
		STATEID_VAL(&dp->dl_stid.sc_stateid));
out:
out:
	if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
			&& flag == NFS4_OPEN_DELEGATE_NONE
			&& open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
		dprintk("NFSD: WARNING: refusing delegation reclaim\n");
	open->op_delegate_type = flag;
	open->op_delegate_type = flag;
	if (flag == NFS4_OPEN_DELEGATE_NONE) {
		if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
		    open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
			dprintk("NFSD: WARNING: refusing delegation reclaim\n");

		if (open->op_deleg_want) {
			open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
			if (status == -EAGAIN)
				open->op_why_no_deleg = WND4_CONTENTION;
			else {
				open->op_why_no_deleg = WND4_RESOURCE;
				switch (open->op_deleg_want) {
				case NFS4_SHARE_WANT_READ_DELEG:
				case NFS4_SHARE_WANT_WRITE_DELEG:
				case NFS4_SHARE_WANT_ANY_DELEG:
					break;
				case NFS4_SHARE_WANT_CANCEL:
					open->op_why_no_deleg = WND4_CANCELLED;
					break;
				case NFS4_SHARE_WANT_NO_DELEG:
					BUG();	/* not supposed to get here */
				}
			}
		}
	}
	return;
	return;
out_free:
out_free:
	nfs4_put_delegation(dp);
	nfs4_put_delegation(dp);
@@ -2981,20 +3002,45 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
	update_stateid(&stp->st_stid.sc_stateid);
	update_stateid(&stp->st_stid.sc_stateid);
	memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
	memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));


	if (nfsd4_has_session(&resp->cstate))
	if (nfsd4_has_session(&resp->cstate)) {
		open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
		open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;


		if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
			open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
			open->op_why_no_deleg = WND4_NOT_WANTED;
			goto nodeleg;
		}
	}

	/*
	/*
	* Attempt to hand out a delegation. No error return, because the
	* Attempt to hand out a delegation. No error return, because the
	* OPEN succeeds even if we fail.
	* OPEN succeeds even if we fail.
	*/
	*/
	nfs4_open_delegation(current_fh, open, stp);
	nfs4_open_delegation(current_fh, open, stp);

nodeleg:
	status = nfs_ok;
	status = nfs_ok;


	dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
	dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
		STATEID_VAL(&stp->st_stid.sc_stateid));
		STATEID_VAL(&stp->st_stid.sc_stateid));
out:
out:
	/* 4.1 client trying to upgrade/downgrade delegation? */
	if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp &&
	    open->op_deleg_want) {
		if (open->op_deleg_want == NFS4_SHARE_WANT_READ_DELEG &&
		    dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) {
			open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
			open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE;
		} else if (open->op_deleg_want == NFS4_SHARE_WANT_WRITE_DELEG &&
			   dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) {
			open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
			open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE;
		}
		/* Otherwise the client must be confused wanting a delegation
		 * it already has, therefore we don't return
		 * NFS4_OPEN_DELEGATE_NONE_EXT and reason.
		 */
	}

	if (fp)
	if (fp)
		put_nfs4_file(fp);
		put_nfs4_file(fp);
	if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
	if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+14 −0
Original line number Original line Diff line number Diff line
@@ -2849,6 +2849,20 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
		WRITE32(0);   /* XXX: is NULL principal ok? */
		WRITE32(0);   /* XXX: is NULL principal ok? */
		ADJUST_ARGS();
		ADJUST_ARGS();
		break;
		break;
	case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */
		switch (open->op_why_no_deleg) {
		case WND4_CONTENTION:
		case WND4_RESOURCE:
			RESERVE_SPACE(8);
			WRITE32(open->op_why_no_deleg);
			WRITE32(0);	/* deleg signaling not supported yet */
			break;
		default:
			RESERVE_SPACE(4);
			WRITE32(open->op_why_no_deleg);
		}
		ADJUST_ARGS();
		break;
	default:
	default:
		BUG();
		BUG();
	}
	}
+1 −0
Original line number Original line Diff line number Diff line
@@ -223,6 +223,7 @@ struct nfsd4_open {
	struct xdr_netobj op_fname;	    /* request - everything but CLAIM_PREV */
	struct xdr_netobj op_fname;	    /* request - everything but CLAIM_PREV */
	u32		op_delegate_type;   /* request - CLAIM_PREV only */
	u32		op_delegate_type;   /* request - CLAIM_PREV only */
	stateid_t       op_delegate_stateid; /* request - response */
	stateid_t       op_delegate_stateid; /* request - response */
	u32		op_why_no_deleg;    /* response - DELEG_NONE_EXT only */
	u32		op_create;     	    /* request */
	u32		op_create;     	    /* request */
	u32		op_createmode;      /* request */
	u32		op_createmode;      /* request */
	u32		op_bmval[3];        /* request */
	u32		op_bmval[3];        /* request */
+14 −1
Original line number Original line Diff line number Diff line
@@ -441,7 +441,20 @@ enum limit_by4 {
enum open_delegation_type4 {
enum open_delegation_type4 {
	NFS4_OPEN_DELEGATE_NONE = 0,
	NFS4_OPEN_DELEGATE_NONE = 0,
	NFS4_OPEN_DELEGATE_READ = 1,
	NFS4_OPEN_DELEGATE_READ = 1,
	NFS4_OPEN_DELEGATE_WRITE = 2
	NFS4_OPEN_DELEGATE_WRITE = 2,
	NFS4_OPEN_DELEGATE_NONE_EXT = 3, /* 4.1 */
};

enum why_no_delegation4 { /* new to v4.1 */
	WND4_NOT_WANTED = 0,
	WND4_CONTENTION = 1,
	WND4_RESOURCE = 2,
	WND4_NOT_SUPP_FTYPE = 3,
	WND4_WRITE_DELEG_NOT_SUPP_FTYPE = 4,
	WND4_NOT_SUPP_UPGRADE = 5,
	WND4_NOT_SUPP_DOWNGRADE = 6,
	WND4_CANCELLED = 7,
	WND4_IS_DIR = 8,
};
};


enum lock_type4 {
enum lock_type4 {