nfsclstate.h revision 325407
1/*-
2 * Copyright (c) 2009 Rick Macklem, University of Guelph
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: stable/10/sys/fs/nfs/nfsclstate.h 325407 2017-11-04 21:30:27Z rmacklem $
27 */
28
29#ifndef _NFS_NFSCLSTATE_H_
30#define	_NFS_NFSCLSTATE_H_
31
32/*
33 * Definitions for NFS V4 client state handling.
34 */
35LIST_HEAD(nfsclopenhead, nfsclopen);
36LIST_HEAD(nfscllockownerhead, nfscllockowner);
37SLIST_HEAD(nfscllockownerfhhead, nfscllockownerfh);
38LIST_HEAD(nfscllockhead, nfscllock);
39LIST_HEAD(nfsclhead, nfsclclient);
40LIST_HEAD(nfsclownerhead, nfsclowner);
41TAILQ_HEAD(nfscldeleghead, nfscldeleg);
42LIST_HEAD(nfscldeleghash, nfscldeleg);
43TAILQ_HEAD(nfscllayouthead, nfscllayout);
44LIST_HEAD(nfscllayouthash, nfscllayout);
45LIST_HEAD(nfsclflayouthead, nfsclflayout);
46LIST_HEAD(nfscldevinfohead, nfscldevinfo);
47LIST_HEAD(nfsclrecalllayouthead, nfsclrecalllayout);
48#define	NFSCLDELEGHASHSIZE	256
49#define	NFSCLDELEGHASH(c, f, l)							\
50	(&((c)->nfsc_deleghash[ncl_hash((f), (l)) % NFSCLDELEGHASHSIZE]))
51#define	NFSCLLAYOUTHASHSIZE	256
52#define	NFSCLLAYOUTHASH(c, f, l)						\
53	(&((c)->nfsc_layouthash[ncl_hash((f), (l)) % NFSCLLAYOUTHASHSIZE]))
54
55/* Structure for NFSv4.1 session stuff. */
56struct nfsclsession {
57	struct mtx	nfsess_mtx;
58	struct nfsslot	nfsess_cbslots[NFSV4_CBSLOTS];
59	nfsquad_t	nfsess_clientid;
60	SVCXPRT		*nfsess_xprt;		/* For backchannel callback */
61	uint32_t	nfsess_slotseq[64];	/* Max for 64bit nm_slots */
62	uint64_t	nfsess_slots;
63	uint32_t	nfsess_sequenceid;
64	uint32_t	nfsess_maxcache;	/* Max size for cached reply. */
65	uint16_t	nfsess_foreslots;
66	uint16_t	nfsess_backslots;
67	uint8_t		nfsess_sessionid[NFSX_V4SESSIONID];
68	uint8_t		nfsess_defunct;		/* Non-zero for old sessions */
69};
70
71/*
72 * This structure holds the session, clientid and related information
73 * needed for an NFSv4.1 Meta Data Server (MDS) or Data Server (DS).
74 * It is malloc'd to the correct length.
75 */
76struct nfsclds {
77	TAILQ_ENTRY(nfsclds)	nfsclds_list;
78	struct nfsclsession	nfsclds_sess;
79	struct mtx		nfsclds_mtx;
80	struct nfssockreq	*nfsclds_sockp;
81	time_t			nfsclds_expire;
82	uint16_t		nfsclds_flags;
83	uint16_t		nfsclds_servownlen;
84	uint8_t			nfsclds_verf[NFSX_VERF];
85	uint8_t			nfsclds_serverown[0];
86};
87
88/*
89 * Flags for nfsclds_flags.
90 */
91#define	NFSCLDS_HASWRITEVERF	0x0001
92#define	NFSCLDS_MDS		0x0002
93#define	NFSCLDS_DS		0x0004
94#define	NFSCLDS_CLOSED		0x0008
95
96struct nfsclclient {
97	LIST_ENTRY(nfsclclient) nfsc_list;
98	struct nfsclownerhead	nfsc_owner;
99	struct nfscldeleghead	nfsc_deleg;
100	struct nfscldeleghash	nfsc_deleghash[NFSCLDELEGHASHSIZE];
101	struct nfscllayouthead	nfsc_layout;
102	struct nfscllayouthash	nfsc_layouthash[NFSCLLAYOUTHASHSIZE];
103	struct nfscldevinfohead	nfsc_devinfo;
104	struct nfsv4lock	nfsc_lock;
105	struct proc		*nfsc_renewthread;
106	struct nfsmount		*nfsc_nmp;
107	time_t			nfsc_expire;
108	u_int32_t		nfsc_clientidrev;
109	u_int32_t		nfsc_rev;
110	u_int32_t		nfsc_renew;
111	u_int32_t		nfsc_cbident;
112	u_int16_t		nfsc_flags;
113	u_int16_t		nfsc_idlen;
114	u_int8_t		nfsc_id[1];	/* Malloc'd to correct length */
115};
116
117/*
118 * Bits for nfsc_flags.
119 */
120#define	NFSCLFLAGS_INITED	0x0001
121#define	NFSCLFLAGS_HASCLIENTID	0x0002
122#define	NFSCLFLAGS_RECOVER	0x0004
123#define	NFSCLFLAGS_UMOUNT	0x0008
124#define	NFSCLFLAGS_HASTHREAD	0x0010
125#define	NFSCLFLAGS_AFINET6	0x0020
126#define	NFSCLFLAGS_EXPIREIT	0x0040
127#define	NFSCLFLAGS_FIRSTDELEG	0x0080
128#define	NFSCLFLAGS_GOTDELEG	0x0100
129#define	NFSCLFLAGS_RECVRINPROG	0x0200
130
131struct nfsclowner {
132	LIST_ENTRY(nfsclowner)	nfsow_list;
133	struct nfsclopenhead	nfsow_open;
134	struct nfsclclient	*nfsow_clp;
135	u_int32_t		nfsow_seqid;
136	u_int32_t		nfsow_defunct;
137	struct nfsv4lock	nfsow_rwlock;
138	u_int8_t		nfsow_owner[NFSV4CL_LOCKNAMELEN];
139};
140
141/*
142 * MALLOC'd to the correct length to accommodate the file handle.
143 */
144struct nfscldeleg {
145	TAILQ_ENTRY(nfscldeleg)	nfsdl_list;
146	LIST_ENTRY(nfscldeleg)	nfsdl_hash;
147	struct nfsclownerhead	nfsdl_owner;	/* locally issued state */
148	struct nfscllockownerhead nfsdl_lock;
149	nfsv4stateid_t		nfsdl_stateid;
150	struct acl_entry	nfsdl_ace;	/* Delegation ace */
151	struct nfsclclient	*nfsdl_clp;
152	struct nfsv4lock	nfsdl_rwlock;	/* for active I/O ops */
153	struct nfscred		nfsdl_cred;	/* Cred. used for Open */
154	time_t			nfsdl_timestamp; /* used for stale cleanup */
155	u_int64_t		nfsdl_sizelimit; /* Limit for file growth */
156	u_int64_t		nfsdl_size;	/* saved copy of file size */
157	u_int64_t		nfsdl_change;	/* and change attribute */
158	struct timespec		nfsdl_modtime;	/* local modify time */
159	u_int16_t		nfsdl_fhlen;
160	u_int8_t		nfsdl_flags;
161	u_int8_t		nfsdl_fh[1];	/* must be last */
162};
163
164/*
165 * nfsdl_flags bits.
166 */
167#define	NFSCLDL_READ		0x01
168#define	NFSCLDL_WRITE		0x02
169#define	NFSCLDL_RECALL		0x04
170#define	NFSCLDL_NEEDRECLAIM	0x08
171#define	NFSCLDL_ZAPPED		0x10
172#define	NFSCLDL_MODTIMESET	0x20
173#define	NFSCLDL_DELEGRET	0x40
174
175/*
176 * MALLOC'd to the correct length to accommodate the file handle.
177 */
178struct nfsclopen {
179	LIST_ENTRY(nfsclopen)	nfso_list;
180	struct nfscllockownerhead nfso_lock;
181	nfsv4stateid_t		nfso_stateid;
182	struct nfsclowner	*nfso_own;
183	struct nfscred		nfso_cred;	/* Cred. used for Open */
184	u_int32_t		nfso_mode;
185	u_int32_t		nfso_opencnt;
186	u_int16_t		nfso_fhlen;
187	u_int8_t		nfso_posixlock;	/* 1 for POSIX type locking */
188	u_int8_t		nfso_fh[1];	/* must be last */
189};
190
191/*
192 * Return values for nfscl_open(). NFSCLOPEN_OK must == 0.
193 */
194#define	NFSCLOPEN_OK		0
195#define	NFSCLOPEN_DOOPEN	1
196#define	NFSCLOPEN_DOOPENDOWNGRADE 2
197#define	NFSCLOPEN_SETCRED	3
198
199struct nfscllockowner {
200	LIST_ENTRY(nfscllockowner) nfsl_list;
201	struct nfscllockhead	nfsl_lock;
202	struct nfsclopen	*nfsl_open;
203	NFSPROC_T		*nfsl_inprog;
204	nfsv4stateid_t		nfsl_stateid;
205	int			nfsl_lockflags;
206	u_int32_t		nfsl_seqid;
207	struct nfsv4lock	nfsl_rwlock;
208	u_int8_t		nfsl_owner[NFSV4CL_LOCKNAMELEN];
209	u_int8_t		nfsl_openowner[NFSV4CL_LOCKNAMELEN];
210};
211
212/*
213 * Byte range entry for the above lock owner.
214 */
215struct nfscllock {
216	LIST_ENTRY(nfscllock)	nfslo_list;
217	u_int64_t		nfslo_first;
218	u_int64_t		nfslo_end;
219	short			nfslo_type;
220};
221
222/* This structure is used to collect a list of lockowners to free up. */
223struct nfscllockownerfh {
224	SLIST_ENTRY(nfscllockownerfh)	nfslfh_list;
225	struct nfscllockownerhead	nfslfh_lock;
226	int				nfslfh_len;
227	uint8_t				nfslfh_fh[NFSX_V4FHMAX];
228};
229
230/*
231 * MALLOC'd to the correct length to accommodate the file handle.
232 */
233struct nfscllayout {
234	TAILQ_ENTRY(nfscllayout)	nfsly_list;
235	LIST_ENTRY(nfscllayout)		nfsly_hash;
236	nfsv4stateid_t			nfsly_stateid;
237	struct nfsv4lock		nfsly_lock;
238	uint64_t			nfsly_filesid[2];
239	uint64_t			nfsly_lastbyte;
240	struct nfsclflayouthead		nfsly_flayread;
241	struct nfsclflayouthead		nfsly_flayrw;
242	struct nfsclrecalllayouthead	nfsly_recall;
243	time_t				nfsly_timestamp;
244	struct nfsclclient		*nfsly_clp;
245	uint16_t			nfsly_flags;
246	uint16_t			nfsly_fhlen;
247	uint8_t				nfsly_fh[1];
248};
249
250/*
251 * Flags for nfsly_flags.
252 */
253#define	NFSLY_FILES		0x0001
254#define	NFSLY_BLOCK		0x0002
255#define	NFSLY_OBJECT		0x0004
256#define	NFSLY_RECALL		0x0008
257#define	NFSLY_RECALLFILE	0x0010
258#define	NFSLY_RECALLFSID	0x0020
259#define	NFSLY_RECALLALL		0x0040
260#define	NFSLY_RETONCLOSE	0x0080
261#define	NFSLY_WRITTEN		0x0100	/* Has been used to write to a DS. */
262
263/*
264 * MALLOC'd to the correct length to accommodate the file handle list.
265 * These hang off of nfsly_flayread and nfsly_flayrw, sorted in increasing
266 * offset order.
267 * The nfsly_flayread list holds the ones with iomode == NFSLAYOUTIOMODE_READ,
268 * whereas the nfsly_flayrw holds the ones with iomode == NFSLAYOUTIOMODE_RW.
269 */
270struct nfsclflayout {
271	LIST_ENTRY(nfsclflayout)	nfsfl_list;
272	uint8_t				nfsfl_dev[NFSX_V4DEVICEID];
273	uint64_t			nfsfl_off;
274	uint64_t			nfsfl_end;
275	uint64_t			nfsfl_patoff;
276	struct nfscldevinfo		*nfsfl_devp;
277	uint32_t			nfsfl_iomode;
278	uint32_t			nfsfl_util;
279	uint32_t			nfsfl_stripe1;
280	uint16_t			nfsfl_flags;
281	uint16_t			nfsfl_fhcnt;
282	struct nfsfh			*nfsfl_fh[1];	/* FH list for DS */
283};
284
285/*
286 * Flags for nfsfl_flags.
287 */
288#define	NFSFL_RECALL	0x0001		/* File layout has been recalled */
289
290/*
291 * Structure that is used to store a LAYOUTRECALL.
292 */
293struct nfsclrecalllayout {
294	LIST_ENTRY(nfsclrecalllayout)	nfsrecly_list;
295	uint64_t			nfsrecly_off;
296	uint64_t			nfsrecly_len;
297	int				nfsrecly_recalltype;
298	uint32_t			nfsrecly_iomode;
299	uint32_t			nfsrecly_stateseqid;
300};
301
302/*
303 * Stores the NFSv4.1 Device Info. Malloc'd to the correct length to
304 * store the list of network connections and list of indices.
305 * nfsdi_data[] is allocated the following way:
306 * - nfsdi_addrcnt * struct nfsclds
307 * - stripe indices, each stored as one byte, since there can be many
308 *   of them. (This implies a limit of 256 on nfsdi_addrcnt, since the
309 *   indices select which address.)
310 */
311struct nfscldevinfo {
312	LIST_ENTRY(nfscldevinfo)	nfsdi_list;
313	uint8_t				nfsdi_deviceid[NFSX_V4DEVICEID];
314	struct nfsclclient		*nfsdi_clp;
315	uint32_t			nfsdi_refcnt;
316	uint32_t			nfsdi_layoutrefs;
317	uint16_t			nfsdi_stripecnt;
318	uint16_t			nfsdi_addrcnt;
319	struct nfsclds			*nfsdi_data[0];
320};
321
322/* These inline functions return values from nfsdi_data[]. */
323/*
324 * Return a pointer to the address at "pos".
325 */
326static __inline struct nfsclds **
327nfsfldi_addr(struct nfscldevinfo *ndi, int pos)
328{
329
330	if (pos >= ndi->nfsdi_addrcnt)
331		return (NULL);
332	return (&ndi->nfsdi_data[pos]);
333}
334
335/*
336 * Return the Nth ("pos") stripe index.
337 */
338static __inline int
339nfsfldi_stripeindex(struct nfscldevinfo *ndi, int pos)
340{
341	uint8_t *valp;
342
343	if (pos >= ndi->nfsdi_stripecnt)
344		return (-1);
345	valp = (uint8_t *)&ndi->nfsdi_data[ndi->nfsdi_addrcnt];
346	valp += pos;
347	return ((int)*valp);
348}
349
350/*
351 * Set the Nth ("pos") stripe index to "val".
352 */
353static __inline void
354nfsfldi_setstripeindex(struct nfscldevinfo *ndi, int pos, uint8_t val)
355{
356	uint8_t *valp;
357
358	if (pos >= ndi->nfsdi_stripecnt)
359		return;
360	valp = (uint8_t *)&ndi->nfsdi_data[ndi->nfsdi_addrcnt];
361	valp += pos;
362	*valp = val;
363}
364
365/*
366 * Macro for incrementing the seqid#.
367 */
368#define	NFSCL_INCRSEQID(s, n)	do { 					\
369	    if (((n)->nd_flag & ND_INCRSEQID))				\
370		(s)++; 							\
371	} while (0)
372
373#endif	/* _NFS_NFSCLSTATE_H_ */
374