hc
2024-03-22 ac5f19e89dcbd5c7428fcc78a0d407c887564466
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * fs/nfs/nfs4session.h
 *
 * Copyright (c) 2012 Trond Myklebust <Trond.Myklebust@netapp.com>
 *
 */
#ifndef __LINUX_FS_NFS_NFS4SESSION_H
#define __LINUX_FS_NFS_NFS4SESSION_H
 
/* maximum number of slots to use */
#define NFS4_DEF_SLOT_TABLE_SIZE (64U)
#define NFS4_DEF_CB_SLOT_TABLE_SIZE (16U)
#define NFS4_MAX_SLOT_TABLE (1024U)
#define NFS4_NO_SLOT ((u32)-1)
 
#if IS_ENABLED(CONFIG_NFS_V4)
 
/* Sessions slot seqid */
struct nfs4_slot {
   struct nfs4_slot_table    *table;
   struct nfs4_slot    *next;
   unsigned long        generation;
   u32            slot_nr;
   u32             seq_nr;
   u32             seq_nr_last_acked;
   u32             seq_nr_highest_sent;
   unsigned int        privileged : 1,
               seq_done : 1;
};
 
/* Sessions */
enum nfs4_slot_tbl_state {
   NFS4_SLOT_TBL_DRAINING,
};
 
#define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long))
struct nfs4_slot_table {
   struct nfs4_session *session;        /* Parent session */
   struct nfs4_slot *slots;        /* seqid per slot */
   unsigned long   used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
   spinlock_t    slot_tbl_lock;
   struct rpc_wait_queue    slot_tbl_waitq;    /* allocators may wait here */
   wait_queue_head_t    slot_waitq;    /* Completion wait on slot */
   u32        max_slots;        /* # slots in table */
   u32        max_slotid;        /* Max allowed slotid value */
   u32        highest_used_slotid;    /* sent to server on each SEQ.
                        * op for dynamic resizing */
   u32        target_highest_slotid;    /* Server max_slot target */
   u32        server_highest_slotid;    /* Server highest slotid */
   s32        d_target_highest_slotid; /* Derivative */
   s32        d2_target_highest_slotid; /* 2nd derivative */
   unsigned long    generation;        /* Generation counter for
                          target_highest_slotid */
   struct completion complete;
   unsigned long    slot_tbl_state;
};
 
/*
 * Session related parameters
 */
struct nfs4_session {
   struct nfs4_sessionid        sess_id;
   u32                flags;
   unsigned long            session_state;
   u32                hash_alg;
   u32                ssv_len;
 
   /* The fore and back channel */
   struct nfs4_channel_attrs    fc_attrs;
   struct nfs4_slot_table        fc_slot_table;
   struct nfs4_channel_attrs    bc_attrs;
   struct nfs4_slot_table        bc_slot_table;
   struct nfs_client        *clp;
};
 
enum nfs4_session_state {
   NFS4_SESSION_INITING,
   NFS4_SESSION_ESTABLISHED,
};
 
extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
       unsigned int max_reqs, const char *queue);
extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
extern struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid);
extern int nfs4_slot_wait_on_seqid(struct nfs4_slot_table *tbl,
       u32 slotid, u32 seq_nr,
       unsigned long timeout);
extern bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);
bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl,
       struct nfs4_slot *slot);
void nfs41_wake_slot_table(struct nfs4_slot_table *tbl);
 
static inline bool nfs4_slot_tbl_draining(struct nfs4_slot_table *tbl)
{
   return !!test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state);
}
 
static inline bool nfs4_test_locked_slot(const struct nfs4_slot_table *tbl,
       u32 slotid)
{
   return !!test_bit(slotid, tbl->used_slots);
}
 
static inline struct nfs4_session *nfs4_get_session(const struct nfs_client *clp)
{
   return clp->cl_session;
}
 
#if defined(CONFIG_NFS_V4_1)
extern void nfs41_set_target_slotid(struct nfs4_slot_table *tbl,
       u32 target_highest_slotid);
extern void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
       struct nfs4_slot *slot,
       struct nfs4_sequence_res *res);
 
extern int nfs4_setup_session_slot_tables(struct nfs4_session *ses);
 
extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
extern void nfs4_destroy_session(struct nfs4_session *session);
extern int nfs4_init_session(struct nfs_client *clp);
extern int nfs4_init_ds_session(struct nfs_client *, unsigned long);
 
/*
 * Determine if sessions are in use.
 */
static inline int nfs4_has_session(const struct nfs_client *clp)
{
   if (clp->cl_session)
       return 1;
   return 0;
}
 
static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
{
   if (nfs4_has_session(clp))
       return (clp->cl_session->flags & SESSION4_PERSIST);
   return 0;
}
 
static inline void nfs4_copy_sessionid(struct nfs4_sessionid *dst,
       const struct nfs4_sessionid *src)
{
   memcpy(dst->data, src->data, NFS4_MAX_SESSIONID_LEN);
}
 
#ifdef CONFIG_CRC32
/*
 * nfs_session_id_hash - calculate the crc32 hash for the session id
 * @session - pointer to session
 */
#define nfs_session_id_hash(sess_id) \
   (~crc32_le(0xFFFFFFFF, &(sess_id)->data[0], sizeof((sess_id)->data)))
#else
#define nfs_session_id_hash(session) (0)
#endif
#else /* defined(CONFIG_NFS_V4_1) */
 
static inline int nfs4_init_session(struct nfs_client *clp)
{
   return 0;
}
 
/*
 * Determine if sessions are in use.
 */
static inline int nfs4_has_session(const struct nfs_client *clp)
{
   return 0;
}
 
static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
{
   return 0;
}
 
#define nfs_session_id_hash(session) (0)
 
#endif /* defined(CONFIG_NFS_V4_1) */
#endif /* IS_ENABLED(CONFIG_NFS_V4) */
#endif /* __LINUX_FS_NFS_NFS4SESSION_H */