162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * fs/nfs/nfs4session.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2012 Trond Myklebust <Trond.Myklebust@netapp.com>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#ifndef __LINUX_FS_NFS_NFS4SESSION_H
962306a36Sopenharmony_ci#define __LINUX_FS_NFS_NFS4SESSION_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/* maximum number of slots to use */
1262306a36Sopenharmony_ci#define NFS4_DEF_SLOT_TABLE_SIZE (64U)
1362306a36Sopenharmony_ci#define NFS4_DEF_CB_SLOT_TABLE_SIZE (16U)
1462306a36Sopenharmony_ci#define NFS4_MAX_SLOT_TABLE (1024U)
1562306a36Sopenharmony_ci#define NFS4_MAX_SLOTID (NFS4_MAX_SLOT_TABLE - 1U)
1662306a36Sopenharmony_ci#define NFS4_NO_SLOT ((u32)-1)
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NFS_V4)
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/* Sessions slot seqid */
2162306a36Sopenharmony_cistruct nfs4_slot {
2262306a36Sopenharmony_ci	struct nfs4_slot_table	*table;
2362306a36Sopenharmony_ci	struct nfs4_slot	*next;
2462306a36Sopenharmony_ci	unsigned long		generation;
2562306a36Sopenharmony_ci	u32			slot_nr;
2662306a36Sopenharmony_ci	u32		 	seq_nr;
2762306a36Sopenharmony_ci	u32		 	seq_nr_last_acked;
2862306a36Sopenharmony_ci	u32		 	seq_nr_highest_sent;
2962306a36Sopenharmony_ci	unsigned int		privileged : 1,
3062306a36Sopenharmony_ci				seq_done : 1;
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* Sessions */
3462306a36Sopenharmony_cienum nfs4_slot_tbl_state {
3562306a36Sopenharmony_ci	NFS4_SLOT_TBL_DRAINING,
3662306a36Sopenharmony_ci};
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, BITS_PER_LONG)
3962306a36Sopenharmony_cistruct nfs4_slot_table {
4062306a36Sopenharmony_ci	struct nfs4_session *session;		/* Parent session */
4162306a36Sopenharmony_ci	struct nfs4_slot *slots;		/* seqid per slot */
4262306a36Sopenharmony_ci	unsigned long   used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
4362306a36Sopenharmony_ci	spinlock_t	slot_tbl_lock;
4462306a36Sopenharmony_ci	struct rpc_wait_queue	slot_tbl_waitq;	/* allocators may wait here */
4562306a36Sopenharmony_ci	wait_queue_head_t	slot_waitq;	/* Completion wait on slot */
4662306a36Sopenharmony_ci	u32		max_slots;		/* # slots in table */
4762306a36Sopenharmony_ci	u32		max_slotid;		/* Max allowed slotid value */
4862306a36Sopenharmony_ci	u32		highest_used_slotid;	/* sent to server on each SEQ.
4962306a36Sopenharmony_ci						 * op for dynamic resizing */
5062306a36Sopenharmony_ci	u32		target_highest_slotid;	/* Server max_slot target */
5162306a36Sopenharmony_ci	u32		server_highest_slotid;	/* Server highest slotid */
5262306a36Sopenharmony_ci	s32		d_target_highest_slotid; /* Derivative */
5362306a36Sopenharmony_ci	s32		d2_target_highest_slotid; /* 2nd derivative */
5462306a36Sopenharmony_ci	unsigned long	generation;		/* Generation counter for
5562306a36Sopenharmony_ci						   target_highest_slotid */
5662306a36Sopenharmony_ci	struct completion complete;
5762306a36Sopenharmony_ci	unsigned long	slot_tbl_state;
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/*
6162306a36Sopenharmony_ci * Session related parameters
6262306a36Sopenharmony_ci */
6362306a36Sopenharmony_cistruct nfs4_session {
6462306a36Sopenharmony_ci	struct nfs4_sessionid		sess_id;
6562306a36Sopenharmony_ci	u32				flags;
6662306a36Sopenharmony_ci	unsigned long			session_state;
6762306a36Sopenharmony_ci	u32				hash_alg;
6862306a36Sopenharmony_ci	u32				ssv_len;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* The fore and back channel */
7162306a36Sopenharmony_ci	struct nfs4_channel_attrs	fc_attrs;
7262306a36Sopenharmony_ci	struct nfs4_slot_table		fc_slot_table;
7362306a36Sopenharmony_ci	struct nfs4_channel_attrs	bc_attrs;
7462306a36Sopenharmony_ci	struct nfs4_slot_table		bc_slot_table;
7562306a36Sopenharmony_ci	struct nfs_client		*clp;
7662306a36Sopenharmony_ci};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cienum nfs4_session_state {
7962306a36Sopenharmony_ci	NFS4_SESSION_INITING,
8062306a36Sopenharmony_ci	NFS4_SESSION_ESTABLISHED,
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciextern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
8462306a36Sopenharmony_ci		unsigned int max_reqs, const char *queue);
8562306a36Sopenharmony_ciextern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
8662306a36Sopenharmony_ciextern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
8762306a36Sopenharmony_ciextern struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid);
8862306a36Sopenharmony_ciextern int nfs4_slot_wait_on_seqid(struct nfs4_slot_table *tbl,
8962306a36Sopenharmony_ci		u32 slotid, u32 seq_nr,
9062306a36Sopenharmony_ci		unsigned long timeout);
9162306a36Sopenharmony_ciextern bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
9262306a36Sopenharmony_ciextern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
9362306a36Sopenharmony_ciextern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);
9462306a36Sopenharmony_cibool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl,
9562306a36Sopenharmony_ci		struct nfs4_slot *slot);
9662306a36Sopenharmony_civoid nfs41_wake_slot_table(struct nfs4_slot_table *tbl);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic inline bool nfs4_slot_tbl_draining(struct nfs4_slot_table *tbl)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	return !!test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state);
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic inline bool nfs4_test_locked_slot(const struct nfs4_slot_table *tbl,
10462306a36Sopenharmony_ci		u32 slotid)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	return !!test_bit(slotid, tbl->used_slots);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic inline struct nfs4_session *nfs4_get_session(const struct nfs_client *clp)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	return clp->cl_session;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
11562306a36Sopenharmony_ciextern void nfs41_set_target_slotid(struct nfs4_slot_table *tbl,
11662306a36Sopenharmony_ci		u32 target_highest_slotid);
11762306a36Sopenharmony_ciextern void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
11862306a36Sopenharmony_ci		struct nfs4_slot *slot,
11962306a36Sopenharmony_ci		struct nfs4_sequence_res *res);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ciextern int nfs4_setup_session_slot_tables(struct nfs4_session *ses);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciextern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
12462306a36Sopenharmony_ciextern void nfs4_destroy_session(struct nfs4_session *session);
12562306a36Sopenharmony_ciextern int nfs4_init_session(struct nfs_client *clp);
12662306a36Sopenharmony_ciextern int nfs4_init_ds_session(struct nfs_client *, unsigned long);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/*
12962306a36Sopenharmony_ci * Determine if sessions are in use.
13062306a36Sopenharmony_ci */
13162306a36Sopenharmony_cistatic inline int nfs4_has_session(const struct nfs_client *clp)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	if (clp->cl_session)
13462306a36Sopenharmony_ci		return 1;
13562306a36Sopenharmony_ci	return 0;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic inline int nfs4_has_persistent_session(const struct nfs_client *clp)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	if (nfs4_has_session(clp))
14162306a36Sopenharmony_ci		return (clp->cl_session->flags & SESSION4_PERSIST);
14262306a36Sopenharmony_ci	return 0;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic inline void nfs4_copy_sessionid(struct nfs4_sessionid *dst,
14662306a36Sopenharmony_ci		const struct nfs4_sessionid *src)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	memcpy(dst->data, src->data, NFS4_MAX_SESSIONID_LEN);
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci#ifdef CONFIG_CRC32
15262306a36Sopenharmony_ci/*
15362306a36Sopenharmony_ci * nfs_session_id_hash - calculate the crc32 hash for the session id
15462306a36Sopenharmony_ci * @session - pointer to session
15562306a36Sopenharmony_ci */
15662306a36Sopenharmony_ci#define nfs_session_id_hash(sess_id) \
15762306a36Sopenharmony_ci	(~crc32_le(0xFFFFFFFF, &(sess_id)->data[0], sizeof((sess_id)->data)))
15862306a36Sopenharmony_ci#else
15962306a36Sopenharmony_ci#define nfs_session_id_hash(session) (0)
16062306a36Sopenharmony_ci#endif
16162306a36Sopenharmony_ci#else /* defined(CONFIG_NFS_V4_1) */
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistatic inline int nfs4_init_session(struct nfs_client *clp)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	return 0;
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci/*
16962306a36Sopenharmony_ci * Determine if sessions are in use.
17062306a36Sopenharmony_ci */
17162306a36Sopenharmony_cistatic inline int nfs4_has_session(const struct nfs_client *clp)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	return 0;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic inline int nfs4_has_persistent_session(const struct nfs_client *clp)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	return 0;
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci#define nfs_session_id_hash(session) (0)
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci#endif /* defined(CONFIG_NFS_V4_1) */
18462306a36Sopenharmony_ci#endif /* IS_ENABLED(CONFIG_NFS_V4) */
18562306a36Sopenharmony_ci#endif /* __LINUX_FS_NFS_NFS4SESSION_H */
186