summaryrefslogtreecommitdiff
path: root/fs/nfsd/netns.h
blob: 26f7b34d1a03057df52ffa66ccc83d2d14016f81 (plain) (blame)
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * per net namespace data structures for nfsd
 *
 * Copyright (C) 2012, Jeff Layton <jlayton@redhat.com>
 */

#ifndef __NFSD_NETNS_H__
#define __NFSD_NETNS_H__

#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <linux/filelock.h>
#include <linux/nfs4.h>
#include <linux/percpu_counter.h>
#include <linux/percpu-refcount.h>
#include <linux/siphash.h>
#include <linux/sunrpc/stats.h>

/* Hash tables for nfs4_clientid state */
#define CLIENT_HASH_BITS                 4
#define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
#define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)

#define SESSION_HASH_SIZE	512

struct cld_net;
struct nfsd4_client_tracking_ops;

enum {
	/* cache misses due only to checksum comparison failures */
	NFSD_STATS_PAYLOAD_MISSES,
	/* amount of memory (in bytes) currently consumed by the DRC */
	NFSD_STATS_DRC_MEM_USAGE,
	NFSD_STATS_RC_HITS,		/* repcache hits */
	NFSD_STATS_RC_MISSES,		/* repcache misses */
	NFSD_STATS_RC_NOCACHE,		/* uncached reqs */
	NFSD_STATS_FH_STALE,		/* FH stale error */
	NFSD_STATS_IO_READ,		/* bytes returned to read requests */
	NFSD_STATS_IO_WRITE,		/* bytes passed in write requests */
#ifdef CONFIG_NFSD_V4
	NFSD_STATS_FIRST_NFS4_OP,	/* count of individual nfsv4 operations */
	NFSD_STATS_LAST_NFS4_OP = NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP,
#define NFSD_STATS_NFS4_OP(op)	(NFSD_STATS_FIRST_NFS4_OP + (op))
	NFSD_STATS_WDELEG_GETATTR,	/* count of getattr conflict with wdeleg */
#endif
	NFSD_STATS_COUNTERS_NUM
};

/*
 * Represents a nfsd "container". With respect to nfsv4 state tracking, the
 * fields of interest are the *_id_hashtbls and the *_name_tree. These track
 * the nfs4_client objects by either short or long form clientid.
 *
 * Each nfsd_net runs a nfs4_laundromat workqueue job when necessary to clean
 * up expired clients and delegations within the container.
 */
struct nfsd_net {
	struct cld_net *cld_net;

	struct cache_detail *svc_expkey_cache;
	struct cache_detail *svc_export_cache;

	struct cache_detail *idtoname_cache;
	struct cache_detail *nametoid_cache;

	struct lock_manager nfsd4_manager;
	bool grace_ended;
	time64_t boot_time;

	struct dentry *nfsd_client_dir;

	/*
	 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
	 * used in reboot/reset lease grace period processing
	 *
	 * conf_id_hashtbl[], and conf_name_tree hold confirmed
	 * setclientid_confirmed info.
	 *
	 * unconf_str_hastbl[] and unconf_name_tree hold unconfirmed
	 * setclientid info.
	 */
	struct list_head *reclaim_str_hashtbl;
	int reclaim_str_hashtbl_size;
	struct list_head *conf_id_hashtbl;
	struct rb_root conf_name_tree;
	struct list_head *unconf_id_hashtbl;
	struct rb_root unconf_name_tree;
	struct list_head *sessionid_hashtbl;
	/*
	 * client_lru holds client queue ordered by nfs4_client.cl_time
	 * for lease renewal.
	 *
	 * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
	 * for last close replay.
	 *
	 * All of the above fields are protected by the client_mutex.
	 */
	struct list_head client_lru;
	struct list_head close_lru;
	struct list_head del_recall_lru;

	/* protected by blocked_locks_lock */
	struct list_head blocked_locks_lru;

	struct delayed_work laundromat_work;

	/* client_lock protects the client lru list and session hash table */
	spinlock_t client_lock;

	/* protects blocked_locks_lru */
	spinlock_t blocked_locks_lock;

	struct file *rec_file;
	bool in_grace;
	const struct nfsd4_client_tracking_ops *client_tracking_ops;

	time64_t nfsd4_lease;
	time64_t nfsd4_grace;
	bool somebody_reclaimed;

	bool track_reclaim_completes;
	atomic_t nr_reclaim_complete;

	bool nfsd_net_up;
	bool lockd_up;

	seqlock_t writeverf_lock;
	unsigned char writeverf[8];

	/*
	 * Max number of connections this nfsd container will allow. Defaults
	 * to '0' which is means that it bases this on the number of threads.
	 */
	unsigned int max_connections;

	u32 clientid_base;
	u32 clientid_counter;
	u32 clverifier_counter;

	struct svc_info nfsd_info;
#define nfsd_serv nfsd_info.serv
	struct percpu_ref nfsd_serv_ref;
	struct completion nfsd_serv_confirm_done;
	struct completion nfsd_serv_free_done;

	/*
	 * clientid and stateid data for construction of net unique COPY
	 * stateids.
	 */
	u32		s2s_cp_cl_id;
	struct idr	s2s_cp_stateids;
	spinlock_t	s2s_cp_lock;
	atomic_t	pending_async_copies;

	/*
	 * Version information
	 */
	bool nfsd_versions[NFSD_MAXVERS + 1];
	bool nfsd4_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1];

	/*
	 * Duplicate reply cache
	 */
	struct nfsd_drc_bucket   *drc_hashtbl;

	/* max number of entries allowed in the cache */
	unsigned int             max_drc_entries;

	/* number of significant bits in the hash value */
	unsigned int             maskbits;
	unsigned int             drc_hashsize;

	/*
	 * Stats and other tracking of on the duplicate reply cache.
	 * The longest_chain* fields are modified with only the per-bucket
	 * cache lock, which isn't really safe and should be fixed if we want
	 * these statistics to be completely accurate.
	 */

	/* total number of entries */
	atomic_t                 num_drc_entries;

	/* Per-netns stats counters */
	struct percpu_counter    counter[NFSD_STATS_COUNTERS_NUM];

	/* sunrpc svc stats */
	struct svc_stat          nfsd_svcstats;

	/* longest hash chain seen */
	unsigned int             longest_chain;

	/* size of cache when we saw the longest hash chain */
	unsigned int             longest_chain_cachesize;

	struct shrinker		*nfsd_reply_cache_shrinker;

	/* tracking server-to-server copy mounts */
	spinlock_t              nfsd_ssc_lock;
	struct list_head        nfsd_ssc_mount_list;
	wait_queue_head_t       nfsd_ssc_waitq;

	/* utsname taken from the process that starts the server */
	char			nfsd_name[UNX_MAXNODENAME+1];

	struct nfsd_fcache_disposal *fcache_disposal;

	siphash_key_t		siphash_key;

	atomic_t		nfs4_client_count;
	int			nfs4_max_clients;

	atomic_t		nfsd_courtesy_clients;
	struct shrinker		*nfsd_client_shrinker;
	struct work_struct	nfsd_shrinker_work;

	/* last time an admin-revoke happened for NFSv4.0 */
	time64_t		nfs40_last_revoke;

#if IS_ENABLED(CONFIG_NFS_LOCALIO)
	/* Local clients to be invalidated when net is shut down */
	struct list_head	local_clients;
#endif
};

/* Simple check to find out if a given net was properly initialized */
#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)

extern bool nfsd_support_version(int vers);
extern unsigned int nfsd_net_id;

bool nfsd_serv_try_get(struct net *net);
void nfsd_serv_put(struct net *net);

void nfsd_copy_write_verifier(__be32 verf[2], struct nfsd_net *nn);
void nfsd_reset_write_verifier(struct nfsd_net *nn);
#endif /* __NFSD_NETNS_H__ */