Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/fs/nfs/nfs_commonport.c
39483 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1989, 1993
5
* The Regents of the University of California. All rights reserved.
6
*
7
* This code is derived from software contributed to Berkeley by
8
* Rick Macklem at The University of Guelph.
9
*
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
12
* are met:
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. Neither the name of the University nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
21
*
22
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
* SUCH DAMAGE.
33
*
34
*/
35
36
#include <sys/cdefs.h>
37
/*
38
* Functions that need to be different for different versions of BSD
39
* kernel should be kept here, along with any global storage specific
40
* to this BSD variant.
41
*/
42
#include <fs/nfs/nfsport.h>
43
#include <sys/smp.h>
44
#include <sys/sysctl.h>
45
#include <sys/taskqueue.h>
46
#include <rpc/rpc_com.h>
47
#include <vm/vm.h>
48
#include <vm/vm_object.h>
49
#include <vm/vm_page.h>
50
#include <vm/vm_param.h>
51
#include <vm/vm_map.h>
52
#include <vm/vm_kern.h>
53
#include <vm/vm_extern.h>
54
#include <vm/uma.h>
55
56
extern int nfscl_ticks;
57
extern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *,
58
struct thread *);
59
extern int nfsrv_useacl;
60
int newnfs_numnfsd = 0;
61
struct nfsstatsv1 nfsstatsv1;
62
int nfs_numnfscbd = 0;
63
int nfscl_debuglevel = 0;
64
char nfsv4_callbackaddr[INET6_ADDRSTRLEN];
65
int nfsrv_lughashsize = 100;
66
struct mtx nfsrv_dslock_mtx;
67
struct nfsdevicehead nfsrv_devidhead;
68
volatile int nfsrv_devidcnt = 0;
69
void (*ncl_call_invalcaches)(struct vnode *) = NULL;
70
vop_advlock_t *nfs_advlock_p = NULL;
71
vop_reclaim_t *nfs_reclaim_p = NULL;
72
uint32_t nfs_srvmaxio = NFS_SRVMAXIO;
73
74
NFSD_VNET_DEFINE(struct nfsstatsv1 *, nfsstatsv1_p);
75
76
NFSD_VNET_DECLARE(struct nfssockreq, nfsrv_nfsuserdsock);
77
NFSD_VNET_DECLARE(nfsuserd_state, nfsrv_nfsuserd);
78
79
int nfs_pnfsio(task_fn_t *, void *);
80
81
static int nfs_realign_test;
82
static int nfs_realign_count;
83
static struct ext_nfsstats oldnfsstats;
84
static struct nfsstatsov1 nfsstatsov1;
85
86
SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
87
"NFS filesystem");
88
SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test,
89
0, "Number of realign tests done");
90
SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count,
91
0, "Number of mbuf realignments done");
92
SYSCTL_STRING(_vfs_nfs, OID_AUTO, callback_addr, CTLFLAG_RW,
93
nfsv4_callbackaddr, sizeof(nfsv4_callbackaddr),
94
"NFSv4 callback addr for server to use");
95
SYSCTL_INT(_vfs_nfs, OID_AUTO, debuglevel, CTLFLAG_RW, &nfscl_debuglevel,
96
0, "Debug level for NFS client");
97
SYSCTL_INT(_vfs_nfs, OID_AUTO, userhashsize, CTLFLAG_RDTUN, &nfsrv_lughashsize,
98
0, "Size of hash tables for uid/name mapping");
99
int nfs_pnfsiothreads = -1;
100
SYSCTL_INT(_vfs_nfs, OID_AUTO, pnfsiothreads, CTLFLAG_RW, &nfs_pnfsiothreads,
101
0, "Number of pNFS mirror I/O threads");
102
103
/*
104
* Defines for malloc
105
* (Here for FreeBSD, since they allocate storage.)
106
*/
107
MALLOC_DEFINE(M_NEWNFSRVCACHE, "NFSD srvcache", "NFSD Server Request Cache");
108
MALLOC_DEFINE(M_NEWNFSDCLIENT, "NFSD V4client", "NFSD V4 Client Id");
109
MALLOC_DEFINE(M_NEWNFSDSTATE, "NFSD V4state",
110
"NFSD V4 State (Openowner, Open, Lockowner, Delegation");
111
MALLOC_DEFINE(M_NEWNFSDLOCK, "NFSD V4lock", "NFSD V4 byte range lock");
112
MALLOC_DEFINE(M_NEWNFSDLOCKFILE, "NFSD lckfile", "NFSD Open/Lock file");
113
MALLOC_DEFINE(M_NEWNFSSTRING, "NFSD string", "NFSD V4 long string");
114
MALLOC_DEFINE(M_NEWNFSUSERGROUP, "NFSD usrgroup", "NFSD V4 User/group map");
115
MALLOC_DEFINE(M_NEWNFSDREQ, "NFS req", "NFS request header");
116
MALLOC_DEFINE(M_NEWNFSFH, "NFS fh", "NFS file handle");
117
MALLOC_DEFINE(M_NEWNFSCLOWNER, "NFSCL owner", "NFSCL Open Owner");
118
MALLOC_DEFINE(M_NEWNFSCLOPEN, "NFSCL open", "NFSCL Open");
119
MALLOC_DEFINE(M_NEWNFSCLDELEG, "NFSCL deleg", "NFSCL Delegation");
120
MALLOC_DEFINE(M_NEWNFSCLCLIENT, "NFSCL client", "NFSCL Client");
121
MALLOC_DEFINE(M_NEWNFSCLLOCKOWNER, "NFSCL lckown", "NFSCL Lock Owner");
122
MALLOC_DEFINE(M_NEWNFSCLLOCK, "NFSCL lck", "NFSCL Lock");
123
MALLOC_DEFINE(M_NEWNFSV4NODE, "NEWNFSnode", "NFS vnode");
124
MALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL diroff",
125
"NFS directory offset data");
126
MALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback",
127
"NFS local lock rollback");
128
MALLOC_DEFINE(M_NEWNFSLAYOUT, "NFSCL layout", "NFSv4.1 Layout");
129
MALLOC_DEFINE(M_NEWNFSFLAYOUT, "NFSCL flayout", "NFSv4.1 File Layout");
130
MALLOC_DEFINE(M_NEWNFSDEVINFO, "NFSCL devinfo", "NFSv4.1 Device Info");
131
MALLOC_DEFINE(M_NEWNFSSOCKREQ, "NFSCL sockreq", "NFS Sock Req");
132
MALLOC_DEFINE(M_NEWNFSCLDS, "NFSCL session", "NFSv4.1 Session");
133
MALLOC_DEFINE(M_NEWNFSLAYRECALL, "NFSCL layrecall", "NFSv4.1 Layout Recall");
134
MALLOC_DEFINE(M_NEWNFSDSESSION, "NFSD session", "NFSD Session for a client");
135
136
/*
137
* Definition of mutex locks.
138
* newnfsd_mtx is used in nfsrvd_nfsd() to protect the nfs socket list
139
* and assorted other nfsd structures.
140
*/
141
struct mtx newnfsd_mtx;
142
struct mtx nfs_sockl_mutex;
143
struct mtx nfs_state_mutex;
144
struct mtx nfs_nameid_mutex;
145
struct mtx nfs_req_mutex;
146
struct mtx nfs_slock_mutex;
147
struct mtx nfs_clstate_mutex;
148
149
/* local functions */
150
static int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *);
151
152
#ifdef __NO_STRICT_ALIGNMENT
153
/*
154
* These architectures don't need re-alignment, so just return.
155
*/
156
int
157
newnfs_realign(struct mbuf **pm, int how)
158
{
159
160
return (0);
161
}
162
#else /* !__NO_STRICT_ALIGNMENT */
163
/*
164
* newnfs_realign:
165
*
166
* Check for badly aligned mbuf data and realign by copying the unaligned
167
* portion of the data into a new mbuf chain and freeing the portions
168
* of the old chain that were replaced.
169
*
170
* We cannot simply realign the data within the existing mbuf chain
171
* because the underlying buffers may contain other rpc commands and
172
* we cannot afford to overwrite them.
173
*
174
* We would prefer to avoid this situation entirely. The situation does
175
* not occur with NFS/UDP and is supposed to only occasionally occur
176
* with TCP. Use vfs.nfs.realign_count and realign_test to check this.
177
*
178
*/
179
int
180
newnfs_realign(struct mbuf **pm, int how)
181
{
182
struct mbuf *m, *n;
183
int off, space;
184
185
++nfs_realign_test;
186
while ((m = *pm) != NULL) {
187
if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
188
/*
189
* NB: we can't depend on m_pkthdr.len to help us
190
* decide what to do here. May not be worth doing
191
* the m_length calculation as m_copyback will
192
* expand the mbuf chain below as needed.
193
*/
194
space = m_length(m, NULL);
195
if (space >= MINCLSIZE) {
196
/* NB: m_copyback handles space > MCLBYTES */
197
n = m_getcl(how, MT_DATA, 0);
198
} else
199
n = m_get(how, MT_DATA);
200
if (n == NULL)
201
return (ENOMEM);
202
/*
203
* Align the remainder of the mbuf chain.
204
*/
205
n->m_len = 0;
206
off = 0;
207
while (m != NULL) {
208
m_copyback(n, off, m->m_len, mtod(m, caddr_t));
209
off += m->m_len;
210
m = m->m_next;
211
}
212
m_freem(*pm);
213
*pm = n;
214
++nfs_realign_count;
215
break;
216
}
217
pm = &m->m_next;
218
}
219
220
return (0);
221
}
222
#endif /* __NO_STRICT_ALIGNMENT */
223
224
#ifdef notdef
225
static void
226
nfsrv_object_create(struct vnode *vp, struct thread *td)
227
{
228
229
if (vp == NULL || vp->v_type != VREG)
230
return;
231
(void) vfs_object_create(vp, td, td->td_ucred);
232
}
233
#endif
234
235
/*
236
* Look up a file name. Basically just initialize stuff and call namei().
237
*/
238
int
239
nfsrv_lookupfilename(struct nameidata *ndp, char *fname, NFSPROC_T *p __unused)
240
{
241
int error;
242
243
NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, fname);
244
error = namei(ndp);
245
if (!error) {
246
NDFREE_PNBUF(ndp);
247
}
248
return (error);
249
}
250
251
/*
252
* Copy NFS uid, gids to the cred structure.
253
*/
254
void
255
newnfs_copycred(struct nfscred *nfscr, struct ucred *cr)
256
{
257
258
KASSERT(nfscr->nfsc_ngroups >= 0,
259
("newnfs_copycred: negative nfsc_ngroups"));
260
cr->cr_uid = nfscr->nfsc_uid;
261
crsetgroups_and_egid(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups,
262
GID_NOGROUP);
263
}
264
265
/*
266
* Map args from nfsmsleep() to msleep().
267
*/
268
int
269
nfsmsleep(void *chan, void *mutex, int prio, const char *wmesg,
270
struct timespec *ts)
271
{
272
u_int64_t nsecval;
273
int error, timeo;
274
275
if (ts) {
276
timeo = hz * ts->tv_sec;
277
nsecval = (u_int64_t)ts->tv_nsec;
278
nsecval = ((nsecval * ((u_int64_t)hz)) + 500000000) /
279
1000000000;
280
timeo += (int)nsecval;
281
} else {
282
timeo = 0;
283
}
284
error = msleep(chan, (struct mtx *)mutex, prio, wmesg, timeo);
285
return (error);
286
}
287
288
/*
289
* Get the file system info for the server. For now, just assume FFS.
290
*/
291
void
292
nfsvno_getfs(struct nfsfsinfo *sip, int isdgram)
293
{
294
int pref;
295
296
/*
297
* XXX
298
* There should be file system VFS OP(s) to get this information.
299
* For now, assume ufs.
300
*/
301
if (isdgram)
302
pref = NFS_MAXDGRAMDATA;
303
else
304
pref = nfs_srvmaxio;
305
sip->fs_rtmax = nfs_srvmaxio;
306
sip->fs_rtpref = pref;
307
sip->fs_rtmult = NFS_FABLKSIZE;
308
sip->fs_wtmax = nfs_srvmaxio;
309
sip->fs_wtpref = pref;
310
sip->fs_wtmult = NFS_FABLKSIZE;
311
sip->fs_dtpref = pref;
312
sip->fs_maxfilesize = 0xffffffffffffffffull;
313
sip->fs_timedelta.tv_sec = 0;
314
sip->fs_timedelta.tv_nsec = 1;
315
sip->fs_properties = (NFSV3FSINFO_LINK |
316
NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
317
NFSV3FSINFO_CANSETTIME);
318
}
319
320
/*
321
* Do the pathconf vnode op.
322
*/
323
int
324
nfsvno_pathconf(struct vnode *vp, int flag, long *retf,
325
struct ucred *cred, struct thread *p)
326
{
327
int error;
328
329
error = VOP_PATHCONF(vp, flag, retf);
330
if (error == EOPNOTSUPP || error == EINVAL) {
331
/*
332
* Some file systems return EINVAL for name arguments not
333
* supported and some return EOPNOTSUPP for this case.
334
* So the NFSv3 Pathconf RPC doesn't fail for these cases,
335
* just fake them.
336
*/
337
switch (flag) {
338
case _PC_LINK_MAX:
339
*retf = NFS_LINK_MAX;
340
break;
341
case _PC_NAME_MAX:
342
*retf = NAME_MAX;
343
break;
344
case _PC_CHOWN_RESTRICTED:
345
*retf = 1;
346
break;
347
case _PC_NO_TRUNC:
348
*retf = 1;
349
break;
350
default:
351
/*
352
* Only happens if a _PC_xxx is added to the server,
353
* but this isn't updated.
354
*/
355
*retf = 0;
356
printf("nfsrvd pathconf flag=%d not supp\n", flag);
357
}
358
error = 0;
359
}
360
NFSEXITCODE(error);
361
return (error);
362
}
363
364
/* Fake nfsrv_atroot. Just return 0 */
365
int
366
nfsrv_atroot(struct vnode *vp, uint64_t *retp)
367
{
368
369
return (0);
370
}
371
372
/*
373
* Set the credentials to refer to root.
374
*/
375
void
376
newnfs_setroot(struct ucred *cred)
377
{
378
379
cred->cr_uid = 0;
380
cred->cr_gid = 0;
381
cred->cr_ngroups = 0;
382
}
383
384
/*
385
* Get the client credential. Used for Renew and recovery.
386
*/
387
struct ucred *
388
newnfs_getcred(void)
389
{
390
struct ucred *cred;
391
struct thread *td = curthread;
392
393
cred = crdup(td->td_ucred);
394
newnfs_setroot(cred);
395
return (cred);
396
}
397
398
/*
399
* Sleep for a short period of time unless errval == NFSERR_GRACE, where
400
* the sleep should be for 5 seconds.
401
* Since lbolt doesn't exist in FreeBSD-CURRENT, just use a timeout on
402
* an event that never gets a wakeup. Only return EINTR or 0.
403
*/
404
int
405
nfs_catnap(int prio, int errval, const char *wmesg)
406
{
407
static int non_event;
408
int ret;
409
410
if (errval == NFSERR_GRACE)
411
ret = tsleep(&non_event, prio, wmesg, 5 * hz);
412
else
413
ret = tsleep(&non_event, prio, wmesg, 1);
414
if (ret != EINTR)
415
ret = 0;
416
return (ret);
417
}
418
419
/*
420
* Get referral. For now, just fail.
421
*/
422
struct nfsreferral *
423
nfsv4root_getreferral(struct vnode *vp, struct vnode *dvp, u_int32_t fileno)
424
{
425
426
return (NULL);
427
}
428
429
static int
430
nfssvc_nfscommon(struct thread *td, struct nfssvc_args *uap)
431
{
432
int error;
433
434
NFSD_CURVNET_SET(NFSD_TD_TO_VNET(td));
435
error = nfssvc_call(td, uap, td->td_ucred);
436
NFSD_CURVNET_RESTORE();
437
NFSEXITCODE(error);
438
return (error);
439
}
440
441
static int
442
nfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
443
{
444
int error = EINVAL, i, j;
445
struct nfsd_idargs nid;
446
struct nfsd_oidargs onid;
447
struct {
448
int vers; /* Just the first field of nfsstats. */
449
} nfsstatver;
450
451
if (uap->flag & NFSSVC_IDNAME) {
452
if ((uap->flag & NFSSVC_NEWSTRUCT) != 0)
453
error = copyin(uap->argp, &nid, sizeof(nid));
454
else {
455
error = copyin(uap->argp, &onid, sizeof(onid));
456
if (error == 0) {
457
nid.nid_flag = onid.nid_flag;
458
nid.nid_uid = onid.nid_uid;
459
nid.nid_gid = onid.nid_gid;
460
nid.nid_usermax = onid.nid_usermax;
461
nid.nid_usertimeout = onid.nid_usertimeout;
462
nid.nid_name = onid.nid_name;
463
nid.nid_namelen = onid.nid_namelen;
464
nid.nid_ngroup = 0;
465
nid.nid_grps = NULL;
466
}
467
}
468
if (error)
469
goto out;
470
error = nfssvc_idname(&nid);
471
goto out;
472
} else if (uap->flag & NFSSVC_GETSTATS) {
473
if ((uap->flag & NFSSVC_NEWSTRUCT) == 0) {
474
/* Copy fields to the old ext_nfsstat structure. */
475
oldnfsstats.attrcache_hits =
476
NFSD_VNET(nfsstatsv1_p)->attrcache_hits;
477
oldnfsstats.attrcache_misses =
478
NFSD_VNET(nfsstatsv1_p)->attrcache_misses;
479
oldnfsstats.lookupcache_hits =
480
NFSD_VNET(nfsstatsv1_p)->lookupcache_hits;
481
oldnfsstats.lookupcache_misses =
482
NFSD_VNET(nfsstatsv1_p)->lookupcache_misses;
483
oldnfsstats.direofcache_hits =
484
NFSD_VNET(nfsstatsv1_p)->direofcache_hits;
485
oldnfsstats.direofcache_misses =
486
NFSD_VNET(nfsstatsv1_p)->direofcache_misses;
487
oldnfsstats.accesscache_hits =
488
NFSD_VNET(nfsstatsv1_p)->accesscache_hits;
489
oldnfsstats.accesscache_misses =
490
NFSD_VNET(nfsstatsv1_p)->accesscache_misses;
491
oldnfsstats.biocache_reads =
492
NFSD_VNET(nfsstatsv1_p)->biocache_reads;
493
oldnfsstats.read_bios =
494
NFSD_VNET(nfsstatsv1_p)->read_bios;
495
oldnfsstats.read_physios =
496
NFSD_VNET(nfsstatsv1_p)->read_physios;
497
oldnfsstats.biocache_writes =
498
NFSD_VNET(nfsstatsv1_p)->biocache_writes;
499
oldnfsstats.write_bios =
500
NFSD_VNET(nfsstatsv1_p)->write_bios;
501
oldnfsstats.write_physios =
502
NFSD_VNET(nfsstatsv1_p)->write_physios;
503
oldnfsstats.biocache_readlinks =
504
NFSD_VNET(nfsstatsv1_p)->biocache_readlinks;
505
oldnfsstats.readlink_bios =
506
NFSD_VNET(nfsstatsv1_p)->readlink_bios;
507
oldnfsstats.biocache_readdirs =
508
NFSD_VNET(nfsstatsv1_p)->biocache_readdirs;
509
oldnfsstats.readdir_bios =
510
NFSD_VNET(nfsstatsv1_p)->readdir_bios;
511
for (i = 0; i < NFSV4_NPROCS; i++)
512
oldnfsstats.rpccnt[i] =
513
NFSD_VNET(nfsstatsv1_p)->rpccnt[i];
514
oldnfsstats.rpcretries =
515
NFSD_VNET(nfsstatsv1_p)->rpcretries;
516
for (i = 0; i < NFSV4OP_NOPS; i++)
517
oldnfsstats.srvrpccnt[i] =
518
NFSD_VNET(nfsstatsv1_p)->srvrpccnt[i];
519
for (i = NFSV42_NOPS, j = NFSV4OP_NOPS;
520
i < NFSV42_NOPS + NFSV4OP_FAKENOPS; i++, j++)
521
oldnfsstats.srvrpccnt[j] =
522
NFSD_VNET(nfsstatsv1_p)->srvrpccnt[i];
523
oldnfsstats.reserved_0 = 0;
524
oldnfsstats.reserved_1 = 0;
525
oldnfsstats.rpcrequests =
526
NFSD_VNET(nfsstatsv1_p)->rpcrequests;
527
oldnfsstats.rpctimeouts =
528
NFSD_VNET(nfsstatsv1_p)->rpctimeouts;
529
oldnfsstats.rpcunexpected =
530
NFSD_VNET(nfsstatsv1_p)->rpcunexpected;
531
oldnfsstats.rpcinvalid =
532
NFSD_VNET(nfsstatsv1_p)->rpcinvalid;
533
oldnfsstats.srvcache_inproghits =
534
NFSD_VNET(nfsstatsv1_p)->srvcache_inproghits;
535
oldnfsstats.reserved_2 = 0;
536
oldnfsstats.srvcache_nonidemdonehits =
537
NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits;
538
oldnfsstats.srvcache_misses =
539
NFSD_VNET(nfsstatsv1_p)->srvcache_misses;
540
oldnfsstats.srvcache_tcppeak =
541
NFSD_VNET(nfsstatsv1_p)->srvcache_tcppeak;
542
oldnfsstats.srvcache_size =
543
NFSD_VNET(nfsstatsv1_p)->srvcache_size;
544
oldnfsstats.srvclients =
545
NFSD_VNET(nfsstatsv1_p)->srvclients;
546
oldnfsstats.srvopenowners =
547
NFSD_VNET(nfsstatsv1_p)->srvopenowners;
548
oldnfsstats.srvopens =
549
NFSD_VNET(nfsstatsv1_p)->srvopens;
550
oldnfsstats.srvlockowners =
551
NFSD_VNET(nfsstatsv1_p)->srvlockowners;
552
oldnfsstats.srvlocks =
553
NFSD_VNET(nfsstatsv1_p)->srvlocks;
554
oldnfsstats.srvdelegates =
555
NFSD_VNET(nfsstatsv1_p)->srvdelegates;
556
for (i = 0; i < NFSV4OP_CBNOPS; i++)
557
oldnfsstats.cbrpccnt[i] =
558
NFSD_VNET(nfsstatsv1_p)->cbrpccnt[i];
559
oldnfsstats.clopenowners =
560
NFSD_VNET(nfsstatsv1_p)->clopenowners;
561
oldnfsstats.clopens = NFSD_VNET(nfsstatsv1_p)->clopens;
562
oldnfsstats.cllockowners =
563
NFSD_VNET(nfsstatsv1_p)->cllockowners;
564
oldnfsstats.cllocks = NFSD_VNET(nfsstatsv1_p)->cllocks;
565
oldnfsstats.cldelegates =
566
NFSD_VNET(nfsstatsv1_p)->cldelegates;
567
oldnfsstats.cllocalopenowners =
568
NFSD_VNET(nfsstatsv1_p)->cllocalopenowners;
569
oldnfsstats.cllocalopens =
570
NFSD_VNET(nfsstatsv1_p)->cllocalopens;
571
oldnfsstats.cllocallockowners =
572
NFSD_VNET(nfsstatsv1_p)->cllocallockowners;
573
oldnfsstats.cllocallocks =
574
NFSD_VNET(nfsstatsv1_p)->cllocallocks;
575
error = copyout(&oldnfsstats, uap->argp,
576
sizeof (oldnfsstats));
577
} else {
578
error = copyin(uap->argp, &nfsstatver,
579
sizeof(nfsstatver));
580
if (error == 0) {
581
if (nfsstatver.vers == NFSSTATS_OV1) {
582
/* Copy nfsstatsv1 to nfsstatsov1. */
583
nfsstatsov1.attrcache_hits =
584
NFSD_VNET(nfsstatsv1_p)->attrcache_hits;
585
nfsstatsov1.attrcache_misses =
586
NFSD_VNET(nfsstatsv1_p)->attrcache_misses;
587
nfsstatsov1.lookupcache_hits =
588
NFSD_VNET(nfsstatsv1_p)->lookupcache_hits;
589
nfsstatsov1.lookupcache_misses =
590
NFSD_VNET(nfsstatsv1_p)->lookupcache_misses;
591
nfsstatsov1.direofcache_hits =
592
NFSD_VNET(nfsstatsv1_p)->direofcache_hits;
593
nfsstatsov1.direofcache_misses =
594
NFSD_VNET(nfsstatsv1_p)->direofcache_misses;
595
nfsstatsov1.accesscache_hits =
596
NFSD_VNET(nfsstatsv1_p)->accesscache_hits;
597
nfsstatsov1.accesscache_misses =
598
NFSD_VNET(nfsstatsv1_p)->accesscache_misses;
599
nfsstatsov1.biocache_reads =
600
NFSD_VNET(nfsstatsv1_p)->biocache_reads;
601
nfsstatsov1.read_bios =
602
NFSD_VNET(nfsstatsv1_p)->read_bios;
603
nfsstatsov1.read_physios =
604
NFSD_VNET(nfsstatsv1_p)->read_physios;
605
nfsstatsov1.biocache_writes =
606
NFSD_VNET(nfsstatsv1_p)->biocache_writes;
607
nfsstatsov1.write_bios =
608
NFSD_VNET(nfsstatsv1_p)->write_bios;
609
nfsstatsov1.write_physios =
610
NFSD_VNET(nfsstatsv1_p)->write_physios;
611
nfsstatsov1.biocache_readlinks =
612
NFSD_VNET(nfsstatsv1_p)->biocache_readlinks;
613
nfsstatsov1.readlink_bios =
614
NFSD_VNET(nfsstatsv1_p)->readlink_bios;
615
nfsstatsov1.biocache_readdirs =
616
NFSD_VNET(nfsstatsv1_p)->biocache_readdirs;
617
nfsstatsov1.readdir_bios =
618
NFSD_VNET(nfsstatsv1_p)->readdir_bios;
619
for (i = 0; i < NFSV42_OLDNPROCS; i++)
620
nfsstatsov1.rpccnt[i] =
621
NFSD_VNET(nfsstatsv1_p)->rpccnt[i];
622
nfsstatsov1.rpcretries =
623
NFSD_VNET(nfsstatsv1_p)->rpcretries;
624
for (i = 0; i < NFSV42_PURENOPS; i++)
625
nfsstatsov1.srvrpccnt[i] =
626
NFSD_VNET(nfsstatsv1_p)->srvrpccnt[i];
627
for (i = NFSV42_NOPS,
628
j = NFSV42_PURENOPS;
629
i < NFSV42_NOPS + NFSV4OP_FAKENOPS;
630
i++, j++)
631
nfsstatsov1.srvrpccnt[j] =
632
NFSD_VNET(nfsstatsv1_p)->srvrpccnt[i];
633
nfsstatsov1.reserved_0 = 0;
634
nfsstatsov1.reserved_1 = 0;
635
nfsstatsov1.rpcrequests =
636
NFSD_VNET(nfsstatsv1_p)->rpcrequests;
637
nfsstatsov1.rpctimeouts =
638
NFSD_VNET(nfsstatsv1_p)->rpctimeouts;
639
nfsstatsov1.rpcunexpected =
640
NFSD_VNET(nfsstatsv1_p)->rpcunexpected;
641
nfsstatsov1.rpcinvalid =
642
NFSD_VNET(nfsstatsv1_p)->rpcinvalid;
643
nfsstatsov1.srvcache_inproghits =
644
NFSD_VNET(nfsstatsv1_p)->srvcache_inproghits;
645
nfsstatsov1.reserved_2 = 0;
646
nfsstatsov1.srvcache_nonidemdonehits =
647
NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits;
648
nfsstatsov1.srvcache_misses =
649
NFSD_VNET(nfsstatsv1_p)->srvcache_misses;
650
nfsstatsov1.srvcache_tcppeak =
651
NFSD_VNET(nfsstatsv1_p)->srvcache_tcppeak;
652
nfsstatsov1.srvcache_size =
653
NFSD_VNET(nfsstatsv1_p)->srvcache_size;
654
nfsstatsov1.srvclients =
655
NFSD_VNET(nfsstatsv1_p)->srvclients;
656
nfsstatsov1.srvopenowners =
657
NFSD_VNET(nfsstatsv1_p)->srvopenowners;
658
nfsstatsov1.srvopens =
659
NFSD_VNET(nfsstatsv1_p)->srvopens;
660
nfsstatsov1.srvlockowners =
661
NFSD_VNET(nfsstatsv1_p)->srvlockowners;
662
nfsstatsov1.srvlocks =
663
NFSD_VNET(nfsstatsv1_p)->srvlocks;
664
nfsstatsov1.srvdelegates =
665
NFSD_VNET(nfsstatsv1_p)->srvdelegates;
666
for (i = 0; i < NFSV42_CBNOPS; i++)
667
nfsstatsov1.cbrpccnt[i] =
668
NFSD_VNET(nfsstatsv1_p)->cbrpccnt[i];
669
nfsstatsov1.clopenowners =
670
NFSD_VNET(nfsstatsv1_p)->clopenowners;
671
nfsstatsov1.clopens =
672
NFSD_VNET(nfsstatsv1_p)->clopens;
673
nfsstatsov1.cllockowners =
674
NFSD_VNET(nfsstatsv1_p)->cllockowners;
675
nfsstatsov1.cllocks =
676
NFSD_VNET(nfsstatsv1_p)->cllocks;
677
nfsstatsov1.cldelegates =
678
NFSD_VNET(nfsstatsv1_p)->cldelegates;
679
nfsstatsov1.cllocalopenowners =
680
NFSD_VNET(nfsstatsv1_p)->cllocalopenowners;
681
nfsstatsov1.cllocalopens =
682
NFSD_VNET(nfsstatsv1_p)->cllocalopens;
683
nfsstatsov1.cllocallockowners =
684
NFSD_VNET(nfsstatsv1_p)->cllocallockowners;
685
nfsstatsov1.cllocallocks =
686
NFSD_VNET(nfsstatsv1_p)->cllocallocks;
687
nfsstatsov1.srvstartcnt =
688
NFSD_VNET(nfsstatsv1_p)->srvstartcnt;
689
nfsstatsov1.srvdonecnt =
690
NFSD_VNET(nfsstatsv1_p)->srvdonecnt;
691
for (i = NFSV42_NOPS,
692
j = NFSV42_PURENOPS;
693
i < NFSV42_NOPS + NFSV4OP_FAKENOPS;
694
i++, j++) {
695
nfsstatsov1.srvbytes[j] =
696
NFSD_VNET(nfsstatsv1_p)->srvbytes[i];
697
nfsstatsov1.srvops[j] =
698
NFSD_VNET(nfsstatsv1_p)->srvops[i];
699
nfsstatsov1.srvduration[j] =
700
NFSD_VNET(nfsstatsv1_p)->srvduration[i];
701
}
702
nfsstatsov1.busyfrom =
703
NFSD_VNET(nfsstatsv1_p)->busyfrom;
704
nfsstatsov1.busyfrom =
705
NFSD_VNET(nfsstatsv1_p)->busyfrom;
706
error = copyout(&nfsstatsov1, uap->argp,
707
sizeof(nfsstatsov1));
708
} else if (nfsstatver.vers != NFSSTATS_V1)
709
error = EPERM;
710
else
711
error = copyout(NFSD_VNET(nfsstatsv1_p),
712
uap->argp, sizeof(nfsstatsv1));
713
}
714
}
715
if (error == 0) {
716
if ((uap->flag & NFSSVC_ZEROCLTSTATS) != 0) {
717
NFSD_VNET(nfsstatsv1_p)->attrcache_hits = 0;
718
NFSD_VNET(nfsstatsv1_p)->attrcache_misses = 0;
719
NFSD_VNET(nfsstatsv1_p)->lookupcache_hits = 0;
720
NFSD_VNET(nfsstatsv1_p)->lookupcache_misses = 0;
721
NFSD_VNET(nfsstatsv1_p)->direofcache_hits = 0;
722
NFSD_VNET(nfsstatsv1_p)->direofcache_misses = 0;
723
NFSD_VNET(nfsstatsv1_p)->accesscache_hits = 0;
724
NFSD_VNET(nfsstatsv1_p)->accesscache_misses = 0;
725
NFSD_VNET(nfsstatsv1_p)->biocache_reads = 0;
726
NFSD_VNET(nfsstatsv1_p)->read_bios = 0;
727
NFSD_VNET(nfsstatsv1_p)->read_physios = 0;
728
NFSD_VNET(nfsstatsv1_p)->biocache_writes = 0;
729
NFSD_VNET(nfsstatsv1_p)->write_bios = 0;
730
NFSD_VNET(nfsstatsv1_p)->write_physios = 0;
731
NFSD_VNET(nfsstatsv1_p)->biocache_readlinks = 0;
732
NFSD_VNET(nfsstatsv1_p)->readlink_bios = 0;
733
NFSD_VNET(nfsstatsv1_p)->biocache_readdirs = 0;
734
NFSD_VNET(nfsstatsv1_p)->readdir_bios = 0;
735
NFSD_VNET(nfsstatsv1_p)->rpcretries = 0;
736
NFSD_VNET(nfsstatsv1_p)->rpcrequests = 0;
737
NFSD_VNET(nfsstatsv1_p)->rpctimeouts = 0;
738
NFSD_VNET(nfsstatsv1_p)->rpcunexpected = 0;
739
NFSD_VNET(nfsstatsv1_p)->rpcinvalid = 0;
740
bzero(NFSD_VNET(nfsstatsv1_p)->rpccnt,
741
sizeof(NFSD_VNET(nfsstatsv1_p)->rpccnt));
742
}
743
if ((uap->flag & NFSSVC_ZEROSRVSTATS) != 0) {
744
NFSD_VNET(nfsstatsv1_p)->srvcache_inproghits = 0;
745
NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits = 0;
746
NFSD_VNET(nfsstatsv1_p)->srvcache_misses = 0;
747
NFSD_VNET(nfsstatsv1_p)->srvcache_tcppeak = 0;
748
bzero(NFSD_VNET(nfsstatsv1_p)->srvrpccnt,
749
sizeof(NFSD_VNET(nfsstatsv1_p)->srvrpccnt));
750
bzero(NFSD_VNET(nfsstatsv1_p)->cbrpccnt,
751
sizeof(NFSD_VNET(nfsstatsv1_p)->cbrpccnt));
752
}
753
}
754
goto out;
755
} else if (uap->flag & NFSSVC_NFSUSERDPORT) {
756
u_short sockport;
757
struct nfsuserd_args nargs;
758
759
if ((uap->flag & NFSSVC_NEWSTRUCT) == 0) {
760
error = copyin(uap->argp, (caddr_t)&sockport,
761
sizeof (u_short));
762
if (error == 0) {
763
nargs.nuserd_family = AF_INET;
764
nargs.nuserd_port = sockport;
765
}
766
} else {
767
/*
768
* New nfsuserd_args structure, which indicates
769
* which IP version to use along with the port#.
770
*/
771
error = copyin(uap->argp, &nargs, sizeof(nargs));
772
}
773
if (!error)
774
error = nfsrv_nfsuserdport(&nargs, p);
775
} else if (uap->flag & NFSSVC_NFSUSERDDELPORT) {
776
nfsrv_nfsuserddelport();
777
error = 0;
778
}
779
780
out:
781
NFSEXITCODE(error);
782
return (error);
783
}
784
785
/*
786
* called by all three modevent routines, so that it gets things
787
* initialized soon enough.
788
*/
789
void
790
newnfs_portinit(void)
791
{
792
static int inited = 0;
793
794
if (inited)
795
return;
796
inited = 1;
797
/* Initialize SMP locks used by both client and server. */
798
mtx_init(&newnfsd_mtx, "newnfsd_mtx", NULL, MTX_DEF);
799
mtx_init(&nfs_state_mutex, "nfs_state_mutex", NULL, MTX_DEF);
800
mtx_init(&nfs_clstate_mutex, "nfs_clstate_mutex", NULL, MTX_DEF);
801
}
802
803
/*
804
* Determine if the file system supports NFSv4 ACLs.
805
* Return 1 if it does, 0 otherwise.
806
*/
807
int
808
nfs_supportsnfsv4acls(struct vnode *vp)
809
{
810
int error;
811
long retval;
812
813
ASSERT_VOP_LOCKED(vp, "nfs supports nfsv4acls");
814
815
if (nfsrv_useacl == 0)
816
return (0);
817
error = VOP_PATHCONF(vp, _PC_ACL_NFS4, &retval);
818
if (error == 0 && retval != 0)
819
return (1);
820
return (0);
821
}
822
823
/*
824
* These are the first fields of all the context structures passed into
825
* nfs_pnfsio().
826
*/
827
struct pnfsio {
828
int done;
829
int inprog;
830
struct task tsk;
831
};
832
833
/*
834
* Do a mirror I/O on a pNFS thread.
835
*/
836
int
837
nfs_pnfsio(task_fn_t *func, void *context)
838
{
839
struct pnfsio *pio;
840
int ret;
841
static struct taskqueue *pnfsioq = NULL;
842
843
pio = (struct pnfsio *)context;
844
if (pnfsioq == NULL) {
845
if (nfs_pnfsiothreads == 0)
846
return (EPERM);
847
if (nfs_pnfsiothreads < 0)
848
nfs_pnfsiothreads = mp_ncpus * 4;
849
pnfsioq = taskqueue_create("pnfsioq", M_WAITOK,
850
taskqueue_thread_enqueue, &pnfsioq);
851
if (pnfsioq == NULL)
852
return (ENOMEM);
853
ret = taskqueue_start_threads(&pnfsioq, nfs_pnfsiothreads,
854
0, "pnfsiot");
855
if (ret != 0) {
856
taskqueue_free(pnfsioq);
857
pnfsioq = NULL;
858
return (ret);
859
}
860
}
861
pio->inprog = 1;
862
TASK_INIT(&pio->tsk, 0, func, context);
863
ret = taskqueue_enqueue(pnfsioq, &pio->tsk);
864
if (ret != 0)
865
pio->inprog = 0;
866
return (ret);
867
}
868
869
/*
870
* Initialize everything that needs to be initialized for a vnet.
871
*/
872
static void
873
nfs_vnetinit(const void *unused __unused)
874
{
875
876
if (IS_DEFAULT_VNET(curvnet))
877
NFSD_VNET(nfsstatsv1_p) = &nfsstatsv1;
878
else
879
NFSD_VNET(nfsstatsv1_p) = malloc(sizeof(struct nfsstatsv1),
880
M_TEMP, M_WAITOK | M_ZERO);
881
mtx_init(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx, "nfsuserd",
882
NULL, MTX_DEF);
883
}
884
VNET_SYSINIT(nfs_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_FIRST,
885
nfs_vnetinit, NULL);
886
887
static void
888
nfs_cleanup(void *unused __unused)
889
{
890
891
mtx_destroy(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx);
892
if (!IS_DEFAULT_VNET(curvnet)) {
893
free(NFSD_VNET(nfsstatsv1_p), M_TEMP);
894
NFSD_VNET(nfsstatsv1_p) = NULL;
895
}
896
/* Clean out the name<-->id cache. */
897
nfsrv_cleanusergroup();
898
}
899
VNET_SYSUNINIT(nfs_cleanup, SI_SUB_VNET_DONE, SI_ORDER_FIRST,
900
nfs_cleanup, NULL);
901
902
extern int (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *);
903
904
/*
905
* Called once to initialize data structures...
906
*/
907
static int
908
nfscommon_modevent(module_t mod, int type, void *data)
909
{
910
int error = 0;
911
static int loaded = 0;
912
913
switch (type) {
914
case MOD_LOAD:
915
if (loaded)
916
goto out;
917
newnfs_portinit();
918
mtx_init(&nfs_nameid_mutex, "nfs_nameid_mutex", NULL, MTX_DEF);
919
mtx_init(&nfs_sockl_mutex, "nfs_sockl_mutex", NULL, MTX_DEF);
920
mtx_init(&nfs_slock_mutex, "nfs_slock_mutex", NULL, MTX_DEF);
921
mtx_init(&nfs_req_mutex, "nfs_req_mutex", NULL, MTX_DEF);
922
mtx_init(&nfsrv_dslock_mtx, "nfs4ds", NULL, MTX_DEF);
923
TAILQ_INIT(&nfsrv_devidhead);
924
newnfs_init();
925
nfsd_call_nfscommon = nfssvc_nfscommon;
926
loaded = 1;
927
break;
928
929
case MOD_UNLOAD:
930
if (newnfs_numnfsd != 0 ||
931
NFSD_VNET(nfsrv_nfsuserd) != NOTRUNNING ||
932
nfs_numnfscbd != 0) {
933
error = EBUSY;
934
break;
935
}
936
937
nfsd_call_nfscommon = NULL;
938
/* and get rid of the mutexes */
939
mtx_destroy(&nfs_nameid_mutex);
940
mtx_destroy(&newnfsd_mtx);
941
mtx_destroy(&nfs_state_mutex);
942
mtx_destroy(&nfs_clstate_mutex);
943
mtx_destroy(&nfs_sockl_mutex);
944
mtx_destroy(&nfs_slock_mutex);
945
mtx_destroy(&nfs_req_mutex);
946
mtx_destroy(&nfsrv_dslock_mtx);
947
loaded = 0;
948
break;
949
default:
950
error = EOPNOTSUPP;
951
break;
952
}
953
954
out:
955
NFSEXITCODE(error);
956
return error;
957
}
958
static moduledata_t nfscommon_mod = {
959
"nfscommon",
960
nfscommon_modevent,
961
NULL,
962
};
963
DECLARE_MODULE(nfscommon, nfscommon_mod, SI_SUB_VFS, SI_ORDER_ANY);
964
965
/* So that loader and kldload(2) can find us, wherever we are.. */
966
MODULE_VERSION(nfscommon, 1);
967
MODULE_DEPEND(nfscommon, nfssvc, 1, 1, 1);
968
MODULE_DEPEND(nfscommon, krpc, 1, 1, 1);
969
970