Commit 281ae67c authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Implement CB_SEQUENCE referring call lists



The slot index number of the current COMPOUND has, until now, not
been needed outside of nfsd4_sequence(). But to record the tuple
that represents a referring call, the slot number will be needed
when processing subsequent operations in the COMPOUND.

Refactor the code that allocates a new struct nfsd4_slot to ensure
that the new sl_index field is always correctly initialized.

Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 4f3c8d8c
Loading
Loading
Loading
Loading
+21 −17
Original line number Diff line number Diff line
@@ -1987,26 +1987,30 @@ reduce_session_slots(struct nfsd4_session *ses, int dec)
	return ret;
}

static struct nfsd4_slot *nfsd4_alloc_slot(struct nfsd4_channel_attrs *fattrs,
					   int index, gfp_t gfp)
{
	struct nfsd4_slot *slot;
	size_t size;

	/*
 * We don't actually need to cache the rpc and session headers, so we
 * can allocate a little less for each slot:
	 * The RPC and NFS session headers are never saved in
	 * the slot reply cache buffer.
	 */
static inline u32 slot_bytes(struct nfsd4_channel_attrs *ca)
{
	u32 size;
	size = fattrs->maxresp_cached < NFSD_MIN_HDR_SEQ_SZ ?
		0 : fattrs->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;

	if (ca->maxresp_cached < NFSD_MIN_HDR_SEQ_SZ)
		size = 0;
	else
		size = ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
	return size + sizeof(struct nfsd4_slot);
	slot = kzalloc(struct_size(slot, sl_data, size), gfp);
	if (!slot)
		return NULL;
	slot->sl_index = index;
	return slot;
}

static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs,
					   struct nfsd4_channel_attrs *battrs)
{
	int numslots = fattrs->maxreqs;
	int slotsize = slot_bytes(fattrs);
	struct nfsd4_session *new;
	struct nfsd4_slot *slot;
	int i;
@@ -2015,14 +2019,14 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs,
	if (!new)
		return NULL;
	xa_init(&new->se_slots);
	/* allocate each struct nfsd4_slot and data cache in one piece */
	slot = kzalloc(slotsize, GFP_KERNEL);

	slot = nfsd4_alloc_slot(fattrs, 0, GFP_KERNEL);
	if (!slot || xa_is_err(xa_store(&new->se_slots, 0, slot, GFP_KERNEL)))
		goto out_free;

	for (i = 1; i < numslots; i++) {
		const gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
		slot = kzalloc(slotsize, gfp);
		slot = nfsd4_alloc_slot(fattrs, i, gfp);
		if (!slot)
			break;
		if (xa_is_err(xa_store(&new->se_slots, i, slot, gfp))) {
@@ -4438,7 +4442,7 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
			 * spinlock, and only succeeds if there is
			 * plenty of memory.
			 */
			slot = kzalloc(slot_bytes(&session->se_fchannel),
			slot = nfsd4_alloc_slot(&session->se_fchannel, s,
						GFP_NOWAIT);
			prev_slot = xa_load(&session->se_slots, s);
			if (xa_is_value(prev_slot) && slot) {
+1 −0
Original line number Diff line number Diff line
@@ -278,6 +278,7 @@ struct nfsd4_slot {
	u32	sl_seqid;
	__be32	sl_status;
	struct svc_cred sl_cred;
	u32	sl_index;
	u32	sl_datalen;
	u16	sl_opcnt;
	u16	sl_generation;