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

Commit 06735b34 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4: Fix up handling of open_to_lock sequence ids

parent faf5f49c
Loading
Loading
Loading
Loading
+32 −37
Original line number Diff line number Diff line
@@ -2889,11 +2889,23 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
	struct inode *inode = state->inode;
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
	struct nfs_lock_opargs largs = {
		.lock_stateid = &lsp->ls_stateid,
		.open_stateid = &state->stateid,
		.lock_owner = {
			.clientid = server->nfs4_state->cl_clientid,
			.id = lsp->ls_id,
		},
		.reclaim = reclaim,
	};
	struct nfs_lockargs arg = {
		.fh = NFS_FH(inode),
		.type = nfs4_lck_type(cmd, request),
		.offset = request->fl_start,
		.length = nfs4_lck_length(request),
		.u = {
			.lock = &largs,
		},
	};
	struct nfs_lockres res = {
		.server = server,
@@ -2904,56 +2916,39 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
		.rpc_resp       = &res,
		.rpc_cred	= state->owner->so_cred,
	};
	struct nfs_lock_opargs largs = {
		.reclaim = reclaim,
		.new_lock_owner = 0,
	};
	struct nfs_seqid *lock_seqid;
	int status = -ENOMEM;

	lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
	if (lock_seqid == NULL)
	largs.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
	if (largs.lock_seqid == NULL)
		return -ENOMEM;
	if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) {
		struct nfs4_state_owner *owner = state->owner;
		struct nfs_open_to_lock otl = {
			.lock_owner = {
				.clientid = server->nfs4_state->cl_clientid,
			},
		};

		otl.lock_seqid = lock_seqid;
		otl.lock_owner.id = lsp->ls_id;
		memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid));
		largs.u.open_lock = &otl;
		largs.open_seqid = nfs_alloc_seqid(&owner->so_seqid);
		if (largs.open_seqid == NULL)
			goto out;
		largs.new_lock_owner = 1;
		arg.u.lock = &largs;
		otl.open_seqid = nfs_alloc_seqid(&owner->so_seqid);
		if (otl.open_seqid != NULL) {
		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
			/* increment seqid on success, and seqid mutating errors */
			nfs_increment_open_seqid(status, otl.open_seqid);
			nfs_free_seqid(otl.open_seqid);
		}
		/* increment open seqid on success, and seqid mutating errors */
		if (largs.new_lock_owner != 0) {
			nfs_increment_open_seqid(status, largs.open_seqid);
			if (status == 0)
				nfs_confirm_seqid(&lsp->ls_seqid, 0);
	} else {
		struct nfs_exist_lock el;
		memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid));
		largs.u.exist_lock = ⪙
		arg.u.lock = &largs;
		el.seqid = lock_seqid;
		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
		}
	/* increment seqid on success, and seqid mutating errors*/
	nfs_increment_lock_seqid(status, lock_seqid);
		nfs_free_seqid(largs.open_seqid);
	} else
		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
	/* increment lock seqid on success, and seqid mutating errors*/
	nfs_increment_lock_seqid(status, largs.lock_seqid);
	/* save the returned stateid. */
	if (status == 0) {
		memcpy(lsp->ls_stateid.data, res.u.stateid.data, sizeof(lsp->ls_stateid.data));
		memcpy(lsp->ls_stateid.data, res.u.stateid.data,
				sizeof(lsp->ls_stateid.data));
		lsp->ls_flags |= NFS_LOCK_INITIALIZED;
	} else if (status == -NFS4ERR_DENIED)
		status = -EAGAIN;
	nfs_free_seqid(lock_seqid);
out:
	nfs_free_seqid(largs.lock_seqid);
	return status;
}

+13 −19
Original line number Diff line number Diff line
@@ -729,22 +729,18 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
	WRITE64(arg->length);
	WRITE32(opargs->new_lock_owner);
	if (opargs->new_lock_owner){
		struct nfs_open_to_lock *ol = opargs->u.open_lock;

		RESERVE_SPACE(40);
		WRITE32(ol->open_seqid->sequence->counter);
		WRITEMEM(&ol->open_stateid, sizeof(ol->open_stateid));
		WRITE32(ol->lock_seqid->sequence->counter);
		WRITE64(ol->lock_owner.clientid);
		WRITE32(opargs->open_seqid->sequence->counter);
		WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data));
		WRITE32(opargs->lock_seqid->sequence->counter);
		WRITE64(opargs->lock_owner.clientid);
		WRITE32(4);
		WRITE32(ol->lock_owner.id);
		WRITE32(opargs->lock_owner.id);
	}
	else {
		struct nfs_exist_lock *el = opargs->u.exist_lock;

		RESERVE_SPACE(20);
		WRITEMEM(&el->stateid, sizeof(el->stateid));
		WRITE32(el->seqid->sequence->counter);
		WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data));
		WRITE32(opargs->lock_seqid->sequence->counter);
	}

	return 0;
@@ -1535,16 +1531,14 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_locka
		.nops   = 2,
	};
	struct nfs_lock_opargs *opargs = args->u.lock;
	struct nfs_seqid *seqid;
	int status;

	if (opargs->new_lock_owner)
		seqid = opargs->u.open_lock->lock_seqid;
	else
		seqid = opargs->u.exist_lock->seqid;
	status = nfs_wait_on_sequence(seqid, req->rq_task);
	status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task);
	if (status != 0)
		goto out;
	/* Do we need to do an open_to_lock_owner? */
	if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)
		opargs->new_lock_owner = 0;
	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
	encode_compound_hdr(&xdr, &hdr);
	status = encode_putfh(&xdr, args->fh);
@@ -2908,8 +2902,8 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res)

	status = decode_op_hdr(xdr, OP_LOCK);
	if (status == 0) {
		READ_BUF(sizeof(nfs4_stateid));
		COPYMEM(&res->u.stateid, sizeof(res->u.stateid));
		READ_BUF(sizeof(res->u.stateid.data));
		COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
	} else if (status == -NFS4ERR_DENIED)
		return decode_lock_denied(xdr, &res->u.denied);
	return status;
+4 −15
Original line number Diff line number Diff line
@@ -165,25 +165,14 @@ struct nfs_lowner {
	u32                     id;
};

struct nfs_open_to_lock {
	struct nfs_seqid *	open_seqid;
	nfs4_stateid            open_stateid;
struct nfs_lock_opargs {
	struct nfs_seqid *	lock_seqid;
	nfs4_stateid *		lock_stateid;
	struct nfs_seqid *	open_seqid;
	nfs4_stateid *		open_stateid;
	struct nfs_lowner       lock_owner;
};

struct nfs_exist_lock {
	nfs4_stateid            stateid;
	struct nfs_seqid *	seqid;
};

struct nfs_lock_opargs {
	__u32                   reclaim;
	__u32                   new_lock_owner;
	union {
		struct nfs_open_to_lock *open_lock;
		struct nfs_exist_lock   *exist_lock;
	} u;
};

struct nfs_locku_opargs {