Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/fs/nfsserver/nfs_nfsdstate.c
106924 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2009 Rick Macklem, University of Guelph
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*
28
*/
29
30
#include <sys/cdefs.h>
31
#include "opt_inet.h"
32
#include "opt_inet6.h"
33
#include <sys/extattr.h>
34
#include <fs/nfs/nfsport.h>
35
36
int nfsrv_issuedelegs = 0;
37
int nfsrv_dolocallocks = 0;
38
struct nfsv4lock nfsv4rootfs_lock;
39
time_t nfsdev_time = 0;
40
int nfsrv_layouthashsize;
41
volatile int nfsrv_layoutcnt = 0;
42
43
NFSD_VNET_DEFINE(struct nfsrv_stablefirst, nfsrv_stablefirst);
44
45
NFSD_VNET_DECLARE(int, nfsrv_numnfsd);
46
NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
47
48
extern uint32_t nfs_srvmaxio;
49
extern int nfsrv_lease;
50
extern struct timeval nfsboottime;
51
extern u_int32_t newnfs_true, newnfs_false;
52
extern struct mtx nfsrv_dslock_mtx;
53
extern struct mtx nfsrv_recalllock_mtx;
54
extern struct mtx nfsrv_dontlistlock_mtx;
55
extern int nfsd_debuglevel;
56
extern u_int nfsrv_dsdirsize;
57
extern struct nfsdevicehead nfsrv_devidhead;
58
extern int nfsrv_doflexfile;
59
extern int nfsrv_maxpnfsmirror;
60
NFSV4ROOTLOCKMUTEX;
61
NFSSTATESPINLOCK;
62
extern struct nfsdontlisthead nfsrv_dontlisthead;
63
extern volatile int nfsrv_devidcnt;
64
extern struct nfslayouthead nfsrv_recalllisthead;
65
extern char *nfsrv_zeropnfsdat;
66
67
SYSCTL_DECL(_vfs_nfsd);
68
int nfsrv_statehashsize = NFSSTATEHASHSIZE;
69
SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN,
70
&nfsrv_statehashsize, 0,
71
"Size of state hash table set via loader.conf");
72
73
int nfsrv_clienthashsize = NFSCLIENTHASHSIZE;
74
SYSCTL_INT(_vfs_nfsd, OID_AUTO, clienthashsize, CTLFLAG_RDTUN,
75
&nfsrv_clienthashsize, 0,
76
"Size of client hash table set via loader.conf");
77
78
int nfsrv_lockhashsize = NFSLOCKHASHSIZE;
79
SYSCTL_INT(_vfs_nfsd, OID_AUTO, fhhashsize, CTLFLAG_RDTUN,
80
&nfsrv_lockhashsize, 0,
81
"Size of file handle hash table set via loader.conf");
82
83
int nfsrv_sessionhashsize = NFSSESSIONHASHSIZE;
84
SYSCTL_INT(_vfs_nfsd, OID_AUTO, sessionhashsize, CTLFLAG_RDTUN,
85
&nfsrv_sessionhashsize, 0,
86
"Size of session hash table set via loader.conf");
87
88
int nfsrv_layouthighwater = NFSLAYOUTHIGHWATER;
89
SYSCTL_INT(_vfs_nfsd, OID_AUTO, layouthighwater, CTLFLAG_RDTUN,
90
&nfsrv_layouthighwater, 0,
91
"High water mark for number of layouts set via loader.conf");
92
93
static int nfsrv_v4statelimit = NFSRV_V4STATELIMIT;
94
SYSCTL_INT(_vfs_nfsd, OID_AUTO, v4statelimit, CTLFLAG_RWTUN,
95
&nfsrv_v4statelimit, 0,
96
"High water limit for NFSv4 opens+locks+delegations");
97
98
static int nfsrv_writedelegifpos = 0;
99
SYSCTL_INT(_vfs_nfsd, OID_AUTO, writedelegifpos, CTLFLAG_RW,
100
&nfsrv_writedelegifpos, 0,
101
"Issue a write delegation for read opens if possible");
102
103
static int nfsrv_allowreadforwriteopen = 1;
104
SYSCTL_INT(_vfs_nfsd, OID_AUTO, allowreadforwriteopen, CTLFLAG_RW,
105
&nfsrv_allowreadforwriteopen, 0,
106
"Allow Reads to be done with Write Access StateIDs");
107
108
int nfsrv_pnfsatime = 0;
109
SYSCTL_INT(_vfs_nfsd, OID_AUTO, pnfsstrictatime, CTLFLAG_RW,
110
&nfsrv_pnfsatime, 0,
111
"For pNFS service, do Getattr ops to keep atime up-to-date");
112
113
int nfsrv_flexlinuxhack = 0;
114
SYSCTL_INT(_vfs_nfsd, OID_AUTO, flexlinuxhack, CTLFLAG_RW,
115
&nfsrv_flexlinuxhack, 0,
116
"For Linux clients, hack around Flex File Layout bug");
117
118
NFSD_VNET_DEFINE_STATIC(bool, nfsd_disable_grace) = false;
119
SYSCTL_BOOL(_vfs_nfsd, OID_AUTO, testing_disable_grace,
120
CTLFLAG_NFSD_VNET | CTLFLAG_RW, &NFSD_VNET_NAME(nfsd_disable_grace),
121
0, "Disable grace for testing");
122
123
/*
124
* Hash lists for nfs V4.
125
*/
126
NFSD_VNET_DEFINE(struct nfsclienthashhead *, nfsclienthash);
127
NFSD_VNET_DEFINE(struct nfslockhashhead *, nfslockhash);
128
NFSD_VNET_DEFINE(struct nfssessionhash *, nfssessionhash);
129
130
struct nfslayouthash *nfslayouthash;
131
volatile int nfsrv_dontlistlen = 0;
132
133
static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 0;
134
static int nfsrv_returnoldstateid = 0, nfsrv_clients = 0;
135
static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER;
136
static int nfsrv_nogsscallback = 0;
137
static volatile int nfsrv_writedelegcnt = 0;
138
static int nfsrv_faildscnt;
139
140
NFSD_VNET_DEFINE_STATIC(time_t, nfsrvboottime);
141
142
/* local functions */
143
static void nfsrv_dumpaclient(struct nfsclient *clp,
144
struct nfsd_dumpclients *dumpp);
145
static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep,
146
NFSPROC_T *p);
147
static void nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep,
148
NFSPROC_T *p);
149
static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep,
150
NFSPROC_T *p);
151
static void nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp,
152
int cansleep, NFSPROC_T *p);
153
static void nfsrv_freenfslock(struct nfslock *lop);
154
static void nfsrv_freenfslockfile(struct nfslockfile *lfp);
155
static void nfsrv_freedeleg(struct nfsstate *);
156
static int nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp,
157
u_int32_t flags, struct nfsstate **stpp);
158
static void nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp,
159
struct nfsstate **stpp);
160
static int nfsrv_getlockfh(vnode_t vp, u_short flags,
161
struct nfslockfile *new_lfp, fhandle_t *nfhp, NFSPROC_T *p);
162
static int nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp,
163
struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit);
164
static void nfsrv_insertlock(struct nfslock *new_lop,
165
struct nfslock *insert_lop, struct nfsstate *stp, struct nfslockfile *lfp);
166
static void nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp,
167
struct nfslock **other_lopp, struct nfslockfile *lfp);
168
static int nfsrv_getipnumber(u_char *cp);
169
static int nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
170
nfsv4stateid_t *stateidp, int specialid);
171
static int nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
172
u_int32_t flags);
173
static int nfsrv_docallback(struct nfsclient *clp, int procnum,
174
nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp,
175
struct nfsvattr *nap, nfsattrbit_t *attrbitp, int laytype, NFSPROC_T *p);
176
static int nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
177
uint32_t callback, int op, const char *optag, struct nfsdsession **sepp,
178
int *slotposp);
179
static u_int32_t nfsrv_nextclientindex(void);
180
static u_int32_t nfsrv_nextstateindex(struct nfsclient *clp);
181
static void nfsrv_markstable(struct nfsclient *clp);
182
static void nfsrv_markreclaim(struct nfsclient *clp);
183
static int nfsrv_checkstable(struct nfsclient *clp);
184
static int nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, struct
185
vnode *vp, NFSPROC_T *p);
186
static int nfsrv_delegconflict(struct nfsstate *stp, int *haslockp,
187
NFSPROC_T *p, vnode_t vp);
188
static int nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
189
struct nfsclient *clp, int *haslockp, NFSPROC_T *p);
190
static int nfsrv_notsamecredname(int op, struct nfsrv_descript *nd,
191
struct nfsclient *clp);
192
static time_t nfsrv_leaseexpiry(void);
193
static void nfsrv_delaydelegtimeout(struct nfsstate *stp);
194
static int nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
195
struct nfsstate *stp, struct nfsrvcache *op);
196
static int nfsrv_nootherstate(struct nfsstate *stp);
197
static int nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
198
uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p);
199
static void nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp,
200
uint64_t init_first, uint64_t init_end, NFSPROC_T *p);
201
static int nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags,
202
int oldflags, uint64_t first, uint64_t end, struct nfslockconflict *cfp,
203
NFSPROC_T *p);
204
static void nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp,
205
NFSPROC_T *p);
206
static void nfsrv_locallock_commit(struct nfslockfile *lfp, int flags,
207
uint64_t first, uint64_t end);
208
static void nfsrv_locklf(struct nfslockfile *lfp);
209
static void nfsrv_unlocklf(struct nfslockfile *lfp);
210
static struct nfsdsession *nfsrv_findsession(uint8_t *sessionid);
211
static int nfsrv_freesession(struct nfsrv_descript *nd, struct nfsdsession *sep,
212
uint8_t *sessionid, bool locked, SVCXPRT **old_xprtp);
213
static int nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
214
int dont_replycache, struct nfsdsession **sepp, int *slotposp);
215
static int nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp);
216
static int nfsrv_addlayout(struct nfsrv_descript *nd, struct nfslayout **lypp,
217
nfsv4stateid_t *stateidp, char *layp, int *layoutlenp, NFSPROC_T *p);
218
static void nfsrv_freelayout(struct nfslayouthead *lhp, struct nfslayout *lyp);
219
static void nfsrv_freelayoutlist(nfsquad_t clientid);
220
static void nfsrv_freelayouts(nfsquad_t *clid, fsid_t *fs, int laytype,
221
int iomode);
222
static void nfsrv_freealllayouts(void);
223
static void nfsrv_freedevid(struct nfsdevice *ds);
224
static int nfsrv_setdsserver(char *dspathp, char *mdspathp, NFSPROC_T *p,
225
struct nfsdevice **dsp);
226
static void nfsrv_deleteds(struct nfsdevice *fndds);
227
static void nfsrv_allocdevid(struct nfsdevice *ds, char *addr, char *dnshost);
228
static void nfsrv_freealldevids(void);
229
static void nfsrv_flexlayouterr(struct nfsrv_descript *nd, uint32_t *layp,
230
int maxcnt, NFSPROC_T *p);
231
static int nfsrv_recalllayout(nfsquad_t clid, nfsv4stateid_t *stateidp,
232
fhandle_t *fhp, struct nfslayout *lyp, int changed, int laytype,
233
NFSPROC_T *p);
234
static int nfsrv_findlayout(nfsquad_t *clientidp, fhandle_t *fhp, int laytype,
235
NFSPROC_T *, struct nfslayout **lypp);
236
static int nfsrv_fndclid(nfsquad_t *clidvec, nfsquad_t clid, int clidcnt);
237
static struct nfslayout *nfsrv_filelayout(struct nfsrv_descript *nd, int iomode,
238
fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs);
239
static struct nfslayout *nfsrv_flexlayout(struct nfsrv_descript *nd, int iomode,
240
int mirrorcnt, fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs);
241
static int nfsrv_dontlayout(fhandle_t *fhp);
242
static int nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf,
243
vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p,
244
vnode_t *tvpp);
245
static struct nfsdevice *nfsrv_findmirroredds(struct nfsmount *nmp);
246
static int nfsrv_checkmachcred(int op, struct nfsrv_descript *nd,
247
struct nfsclient *clp);
248
static void nfsrv_issuedelegation(struct vnode *vp, struct nfsclient *clp,
249
struct nfsrv_descript *nd, int delegate, int writedeleg, int readonly,
250
u_quad_t filerev, uint64_t rdonly, struct nfsstate **new_delegp,
251
struct nfsstate *new_stp, struct nfslockfile *lfp, uint32_t *rflagsp,
252
nfsv4stateid_t *delegstateidp);
253
static void nfsrv_clientlock(bool mlocked);
254
static void nfsrv_clientunlock(bool mlocked);
255
256
/*
257
* Lock the client structure, either with the mutex or the exclusive nfsd lock.
258
*/
259
static void
260
nfsrv_clientlock(bool mlocked)
261
{
262
int igotlock;
263
264
if (mlocked) {
265
NFSLOCKSTATE();
266
} else {
267
NFSLOCKV4ROOTMUTEX();
268
nfsv4_relref(&nfsv4rootfs_lock);
269
do {
270
igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
271
NFSV4ROOTLOCKMUTEXPTR, NULL);
272
} while (!igotlock);
273
NFSUNLOCKV4ROOTMUTEX();
274
}
275
}
276
277
/*
278
* Unlock the client structure.
279
*/
280
static void
281
nfsrv_clientunlock(bool mlocked)
282
{
283
284
if (mlocked) {
285
NFSUNLOCKSTATE();
286
} else {
287
NFSLOCKV4ROOTMUTEX();
288
nfsv4_unlock(&nfsv4rootfs_lock, 1);
289
NFSUNLOCKV4ROOTMUTEX();
290
}
291
}
292
293
/*
294
* Scan the client list for a match and either return the current one,
295
* create a new entry or return an error.
296
* If returning a non-error, the clp structure must either be linked into
297
* the client list or free'd.
298
*/
299
int
300
nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
301
nfsquad_t *clientidp, nfsquad_t *confirmp, NFSPROC_T *p)
302
{
303
struct nfsclient *clp = NULL, *new_clp = *new_clpp;
304
int i, error = 0, ret;
305
struct nfsstate *stp, *tstp;
306
#ifdef INET
307
struct sockaddr_in *sin, *rin;
308
#endif
309
#ifdef INET6
310
struct sockaddr_in6 *sin6, *rin6;
311
#endif
312
struct nfsdsession *sep, *nsep;
313
SVCXPRT *old_xprt;
314
struct nfssessionhead old_sess;
315
int zapit = 0, gotit, hasstate = 0;
316
bool mlocked;
317
static u_int64_t confirm_index = 0;
318
319
/*
320
* Check for state resource limit exceeded.
321
*/
322
if (nfsrv_openpluslock > nfsrv_v4statelimit) {
323
error = NFSERR_RESOURCE;
324
goto out;
325
}
326
327
if (nfsrv_issuedelegs == 0 ||
328
((nd->nd_flag & ND_GSS) != 0 && nfsrv_nogsscallback != 0))
329
/*
330
* Don't do callbacks when delegations are disabled or
331
* for AUTH_GSS unless enabled via nfsrv_nogsscallback.
332
* If establishing a callback connection is attempted
333
* when a firewall is blocking the callback path, the
334
* server may wait too long for the connect attempt to
335
* succeed during the Open. Some clients, such as Linux,
336
* may timeout and give up on the Open before the server
337
* replies. Also, since AUTH_GSS callbacks are not
338
* yet interoperability tested, they might cause the
339
* server to crap out, if they get past the Init call to
340
* the client.
341
*/
342
new_clp->lc_program = 0;
343
344
mlocked = true;
345
if (nfsrv_dolocallocks != 0)
346
mlocked = false;
347
/* Lock out other nfsd threads */
348
nfsrv_clientlock(mlocked);
349
350
/*
351
* Search for a match in the client list.
352
*/
353
gotit = i = 0;
354
while (i < nfsrv_clienthashsize && !gotit) {
355
LIST_FOREACH(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash) {
356
if (new_clp->lc_idlen == clp->lc_idlen &&
357
!NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) {
358
gotit = 1;
359
break;
360
}
361
}
362
if (gotit == 0)
363
i++;
364
}
365
old_xprt = NULL;
366
if (!gotit ||
367
(clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_ADMINREVOKED))) {
368
if ((nd->nd_flag & ND_NFSV41) != 0 && confirmp->lval[1] != 0) {
369
/*
370
* For NFSv4.1, if confirmp->lval[1] is non-zero, the
371
* client is trying to update a confirmed clientid.
372
*/
373
nfsrv_clientunlock(mlocked);
374
confirmp->lval[1] = 0;
375
error = NFSERR_NOENT;
376
goto out;
377
}
378
/*
379
* Get rid of the old one.
380
*/
381
if (i != nfsrv_clienthashsize) {
382
LIST_REMOVE(clp, lc_hash);
383
if (mlocked)
384
nfsrv_cleanclient(clp, p, true, &old_xprt);
385
else
386
nfsrv_cleanclient(clp, p, false, NULL);
387
nfsrv_freedeleglist(&clp->lc_deleg);
388
nfsrv_freedeleglist(&clp->lc_olddeleg);
389
zapit = 1;
390
}
391
/*
392
* Add it after assigning a client id to it.
393
*/
394
new_clp->lc_flags |= LCL_NEEDSCONFIRM;
395
if ((nd->nd_flag & ND_NFSV41) != 0) {
396
confirmp->lval[0] = ++confirm_index;
397
new_clp->lc_confirm.lval[0] = confirmp->lval[0] - 1;
398
} else
399
confirmp->qval = new_clp->lc_confirm.qval =
400
++confirm_index;
401
clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
402
NFSD_VNET(nfsrvboottime);
403
clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
404
nfsrv_nextclientindex();
405
new_clp->lc_stateindex = 0;
406
new_clp->lc_statemaxindex = 0;
407
new_clp->lc_prevsess = 0;
408
new_clp->lc_cbref = 0;
409
new_clp->lc_expiry = nfsrv_leaseexpiry();
410
LIST_INIT(&new_clp->lc_open);
411
LIST_INIT(&new_clp->lc_deleg);
412
LIST_INIT(&new_clp->lc_olddeleg);
413
LIST_INIT(&new_clp->lc_session);
414
for (i = 0; i < nfsrv_statehashsize; i++)
415
LIST_INIT(&new_clp->lc_stateid[i]);
416
LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
417
lc_hash);
418
NFSD_VNET(nfsstatsv1_p)->srvclients++;
419
nfsrv_openpluslock++;
420
nfsrv_clients++;
421
nfsrv_clientunlock(mlocked);
422
if (zapit != 0) {
423
if (old_xprt != NULL)
424
SVC_RELEASE(old_xprt);
425
nfsrv_zapclient(clp, p);
426
}
427
*new_clpp = NULL;
428
goto out;
429
}
430
431
/*
432
* Now, handle the cases where the id is already issued.
433
*/
434
if (nfsrv_notsamecredname(NFSV4OP_EXCHANGEID, nd, clp)) {
435
/*
436
* Check to see if there is expired state that should go away.
437
*/
438
if (clp->lc_expiry < NFSD_MONOSEC &&
439
(!LIST_EMPTY(&clp->lc_open) || !LIST_EMPTY(&clp->lc_deleg))) {
440
if (mlocked)
441
nfsrv_cleanclient(clp, p, true, &old_xprt);
442
else
443
nfsrv_cleanclient(clp, p, false, NULL);
444
nfsrv_freedeleglist(&clp->lc_deleg);
445
}
446
447
/*
448
* If there is outstanding state, then reply NFSERR_CLIDINUSE per
449
* RFC3530 Sec. 8.1.2 last para.
450
*/
451
if (!LIST_EMPTY(&clp->lc_deleg)) {
452
hasstate = 1;
453
} else if (LIST_EMPTY(&clp->lc_open)) {
454
hasstate = 0;
455
} else {
456
hasstate = 0;
457
/* Look for an Open on the OpenOwner */
458
LIST_FOREACH(stp, &clp->lc_open, ls_list) {
459
if (!LIST_EMPTY(&stp->ls_open)) {
460
hasstate = 1;
461
break;
462
}
463
}
464
}
465
if (hasstate) {
466
/*
467
* If the uid doesn't match, return NFSERR_CLIDINUSE after
468
* filling out the correct ipaddr and portnum.
469
*/
470
switch (clp->lc_req.nr_nam->sa_family) {
471
#ifdef INET
472
case AF_INET:
473
sin = (struct sockaddr_in *)new_clp->lc_req.nr_nam;
474
rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
475
sin->sin_addr.s_addr = rin->sin_addr.s_addr;
476
sin->sin_port = rin->sin_port;
477
break;
478
#endif
479
#ifdef INET6
480
case AF_INET6:
481
sin6 = (struct sockaddr_in6 *)new_clp->lc_req.nr_nam;
482
rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
483
sin6->sin6_addr = rin6->sin6_addr;
484
sin6->sin6_port = rin6->sin6_port;
485
break;
486
#endif
487
}
488
nfsrv_clientunlock(mlocked);
489
if (old_xprt != NULL)
490
SVC_RELEASE(old_xprt);
491
error = NFSERR_CLIDINUSE;
492
goto out;
493
}
494
}
495
496
if (NFSBCMP(new_clp->lc_verf, clp->lc_verf, NFSX_VERF)) {
497
/*
498
* If the verifier has changed, the client has rebooted
499
* and a new client id is issued. The old state info
500
* can be thrown away once the SetClientID_Confirm or
501
* Create_Session that confirms the clientid occurs.
502
*/
503
LIST_REMOVE(clp, lc_hash);
504
505
LIST_NEWHEAD(&old_sess, &clp->lc_session, sess_list);
506
507
new_clp->lc_flags |= LCL_NEEDSCONFIRM;
508
if ((nd->nd_flag & ND_NFSV41) != 0) {
509
confirmp->lval[0] = ++confirm_index;
510
new_clp->lc_confirm.lval[0] = confirmp->lval[0] - 1;
511
} else
512
confirmp->qval = new_clp->lc_confirm.qval =
513
++confirm_index;
514
clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
515
NFSD_VNET(nfsrvboottime);
516
clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
517
nfsrv_nextclientindex();
518
new_clp->lc_stateindex = 0;
519
new_clp->lc_statemaxindex = 0;
520
new_clp->lc_prevsess = 0;
521
new_clp->lc_cbref = 0;
522
new_clp->lc_expiry = nfsrv_leaseexpiry();
523
524
/*
525
* Save the state until confirmed.
526
*/
527
LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list);
528
LIST_FOREACH(tstp, &new_clp->lc_open, ls_list)
529
tstp->ls_clp = new_clp;
530
LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list);
531
LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list)
532
tstp->ls_clp = new_clp;
533
LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg,
534
ls_list);
535
LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list)
536
tstp->ls_clp = new_clp;
537
for (i = 0; i < nfsrv_statehashsize; i++) {
538
LIST_NEWHEAD(&new_clp->lc_stateid[i],
539
&clp->lc_stateid[i], ls_hash);
540
LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash)
541
tstp->ls_clp = new_clp;
542
}
543
LIST_INIT(&new_clp->lc_session);
544
LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
545
lc_hash);
546
NFSD_VNET(nfsstatsv1_p)->srvclients++;
547
nfsrv_openpluslock++;
548
nfsrv_clients++;
549
if (!mlocked) {
550
nfsrv_clientunlock(mlocked);
551
NFSLOCKSTATE();
552
}
553
554
/*
555
* Must wait until any outstanding callback on the old clp
556
* completes.
557
*/
558
while (clp->lc_cbref) {
559
clp->lc_flags |= LCL_WAKEUPWANTED;
560
(void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PVFS,
561
"nfsd clp", 10 * hz);
562
}
563
NFSUNLOCKSTATE();
564
if (old_xprt != NULL)
565
SVC_RELEASE(old_xprt);
566
/* Get rid of all sessions on this clientid. */
567
LIST_FOREACH_SAFE(sep, &old_sess, sess_list, nsep) {
568
ret = nfsrv_freesession(NULL, sep, NULL, false, NULL);
569
if (ret != 0)
570
printf("nfsrv_setclient: verifier changed free"
571
" session failed=%d\n", ret);
572
}
573
574
nfsrv_zapclient(clp, p);
575
*new_clpp = NULL;
576
goto out;
577
}
578
579
/* For NFSv4.1, mark that we found a confirmed clientid. */
580
if ((nd->nd_flag & ND_NFSV41) != 0) {
581
clientidp->lval[0] = clp->lc_clientid.lval[0];
582
clientidp->lval[1] = clp->lc_clientid.lval[1];
583
confirmp->lval[0] = 0; /* Ignored by client */
584
confirmp->lval[1] = 1;
585
} else {
586
/*
587
* id and verifier match, so update the net address info
588
* and get rid of any existing callback authentication
589
* handle, so a new one will be acquired.
590
*/
591
LIST_REMOVE(clp, lc_hash);
592
new_clp->lc_flags |= (LCL_NEEDSCONFIRM | LCL_DONTCLEAN);
593
new_clp->lc_expiry = nfsrv_leaseexpiry();
594
confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index;
595
clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
596
clp->lc_clientid.lval[0];
597
clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
598
clp->lc_clientid.lval[1];
599
new_clp->lc_delegtime = clp->lc_delegtime;
600
new_clp->lc_stateindex = clp->lc_stateindex;
601
new_clp->lc_statemaxindex = clp->lc_statemaxindex;
602
new_clp->lc_cbref = 0;
603
LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list);
604
LIST_FOREACH(tstp, &new_clp->lc_open, ls_list)
605
tstp->ls_clp = new_clp;
606
LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list);
607
LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list)
608
tstp->ls_clp = new_clp;
609
LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, ls_list);
610
LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list)
611
tstp->ls_clp = new_clp;
612
for (i = 0; i < nfsrv_statehashsize; i++) {
613
LIST_NEWHEAD(&new_clp->lc_stateid[i],
614
&clp->lc_stateid[i], ls_hash);
615
LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash)
616
tstp->ls_clp = new_clp;
617
}
618
LIST_INIT(&new_clp->lc_session);
619
LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
620
lc_hash);
621
NFSD_VNET(nfsstatsv1_p)->srvclients++;
622
nfsrv_openpluslock++;
623
nfsrv_clients++;
624
}
625
if (!mlocked)
626
nfsrv_clientunlock(mlocked);
627
628
if ((nd->nd_flag & ND_NFSV41) == 0) {
629
/*
630
* Must wait until any outstanding callback on the old clp
631
* completes.
632
*/
633
if (!mlocked)
634
NFSLOCKSTATE();
635
while (clp->lc_cbref) {
636
clp->lc_flags |= LCL_WAKEUPWANTED;
637
(void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PVFS,
638
"nfsdclp", 10 * hz);
639
}
640
NFSUNLOCKSTATE();
641
if (old_xprt != NULL)
642
SVC_RELEASE(old_xprt);
643
nfsrv_zapclient(clp, p);
644
*new_clpp = NULL;
645
} else {
646
if (mlocked)
647
NFSUNLOCKSTATE();
648
if (old_xprt != NULL)
649
SVC_RELEASE(old_xprt);
650
}
651
652
out:
653
NFSEXITCODE2(error, nd);
654
return (error);
655
}
656
657
/*
658
* Check to see if the client id exists and optionally confirm it.
659
*/
660
int
661
nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
662
struct nfsdsession *nsep, nfsquad_t confirm, uint32_t cbprogram,
663
struct nfsrv_descript *nd, NFSPROC_T *p)
664
{
665
struct nfsclient *clp;
666
struct nfsstate *stp;
667
int i;
668
struct nfsclienthashhead *hp;
669
int error = 0, doneok, igotlock;
670
struct nfssessionhash *shp;
671
struct nfsdsession *sep;
672
uint64_t sessid[2];
673
CLIENT *client;
674
SVCXPRT *old_xprt;
675
bool mlocked, sess_replay;
676
static uint64_t next_sess = 0;
677
678
if (clpp)
679
*clpp = NULL;
680
if ((nd == NULL || (nd->nd_flag & ND_NFSV41) == 0 ||
681
opflags != CLOPS_RENEW) && NFSD_VNET(nfsrvboottime) !=
682
clientid.lval[0]) {
683
error = NFSERR_STALECLIENTID;
684
goto out;
685
}
686
687
/*
688
* If called with opflags == CLOPS_RENEW, the State Lock is
689
* already held. Otherwise, we need to get either that or,
690
* for the case of Confirm, lock out the nfsd threads.
691
*/
692
client = NULL;
693
old_xprt = NULL;
694
mlocked = true;
695
if (nfsrv_dolocallocks != 0)
696
mlocked = false;
697
if (opflags & CLOPS_CONFIRM) {
698
if (nsep != NULL &&
699
(nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0)
700
client = (struct __rpc_client *)
701
clnt_bck_create(nd->nd_xprt->xp_socket,
702
cbprogram, NFSV4_CBVERS);
703
if (mlocked) {
704
nfsrv_clientlock(mlocked);
705
} else {
706
NFSLOCKV4ROOTMUTEX();
707
nfsv4_relref(&nfsv4rootfs_lock);
708
do {
709
igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1,
710
NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
711
} while (!igotlock);
712
}
713
/*
714
* Create a new sessionid here, since we need to do it where
715
* there is a mutex held to serialize update of next_sess.
716
*/
717
if ((nd->nd_flag & ND_NFSV41) != 0) {
718
sessid[0] = ++next_sess;
719
sessid[1] = clientid.qval;
720
}
721
if (!mlocked)
722
NFSUNLOCKV4ROOTMUTEX();
723
} else if (opflags != CLOPS_RENEW) {
724
NFSLOCKSTATE();
725
}
726
727
/* For NFSv4.1, the clp is acquired from the associated session. */
728
if (nd != NULL && (nd->nd_flag & ND_NFSV41) != 0 &&
729
opflags == CLOPS_RENEW) {
730
clp = NULL;
731
if ((nd->nd_flag & ND_HASSEQUENCE) != 0) {
732
shp = NFSSESSIONHASH(nd->nd_sessionid);
733
NFSLOCKSESSION(shp);
734
sep = nfsrv_findsession(nd->nd_sessionid);
735
if (sep != NULL)
736
clp = sep->sess_clp;
737
NFSUNLOCKSESSION(shp);
738
}
739
} else {
740
hp = NFSCLIENTHASH(clientid);
741
LIST_FOREACH(clp, hp, lc_hash) {
742
if (clp->lc_clientid.lval[1] == clientid.lval[1])
743
break;
744
}
745
}
746
if (clp == NULL) {
747
if (opflags & CLOPS_CONFIRM)
748
error = NFSERR_STALECLIENTID;
749
else
750
error = NFSERR_EXPIRED;
751
} else if (clp->lc_flags & LCL_ADMINREVOKED) {
752
/*
753
* If marked admin revoked, just return the error.
754
*/
755
error = NFSERR_ADMINREVOKED;
756
}
757
if (error) {
758
if (opflags & CLOPS_CONFIRM) {
759
nfsrv_clientunlock(mlocked);
760
if (client != NULL)
761
CLNT_RELEASE(client);
762
} else if (opflags != CLOPS_RENEW) {
763
NFSUNLOCKSTATE();
764
}
765
goto out;
766
}
767
768
/*
769
* Perform any operations specified by the opflags.
770
*/
771
if (opflags & CLOPS_CONFIRM) {
772
sess_replay = false;
773
if ((nd->nd_flag & ND_NFSV41) != 0) {
774
/*
775
* For the case where lc_confirm.lval[0] == confirm.lval[0],
776
* use the new session, but with the previous sessionid.
777
* This is not exactly what the RFC describes, but should
778
* result in the same reply as the previous CreateSession.
779
*/
780
if (clp->lc_confirm.lval[0] + 1 == confirm.lval[0]) {
781
clp->lc_confirm.lval[0] = confirm.lval[0];
782
clp->lc_prevsess = sessid[0];
783
} else if (clp->lc_confirm.lval[0] == confirm.lval[0]) {
784
if (clp->lc_prevsess == 0)
785
error = NFSERR_SEQMISORDERED;
786
else
787
sessid[0] = clp->lc_prevsess;
788
sess_replay = true;
789
} else
790
error = NFSERR_SEQMISORDERED;
791
} else if ((nd->nd_flag & ND_NFSV41) == 0 &&
792
clp->lc_confirm.qval != confirm.qval)
793
error = NFSERR_STALECLIENTID;
794
if (error == 0 && nfsrv_notsamecredname(NFSV4OP_CREATESESSION,
795
nd, clp))
796
error = NFSERR_CLIDINUSE;
797
798
if (!error) {
799
if ((clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_DONTCLEAN)) ==
800
LCL_NEEDSCONFIRM) {
801
/*
802
* Hang onto the delegations (as old delegations)
803
* for an Open with CLAIM_DELEGATE_PREV unless in
804
* grace, but get rid of the rest of the state.
805
*/
806
if (mlocked)
807
nfsrv_cleanclient(clp, p, true, &old_xprt);
808
else
809
nfsrv_cleanclient(clp, p, false, NULL);
810
nfsrv_freedeleglist(&clp->lc_olddeleg);
811
if (nfsrv_checkgrace(nd, clp, 0)) {
812
/* In grace, so just delete delegations */
813
nfsrv_freedeleglist(&clp->lc_deleg);
814
} else {
815
LIST_FOREACH(stp, &clp->lc_deleg, ls_list)
816
stp->ls_flags |= NFSLCK_OLDDELEG;
817
clp->lc_delegtime = NFSD_MONOSEC +
818
nfsrv_lease + NFSRV_LEASEDELTA;
819
LIST_NEWHEAD(&clp->lc_olddeleg, &clp->lc_deleg,
820
ls_list);
821
}
822
if ((nd->nd_flag & ND_NFSV41) != 0)
823
clp->lc_program = cbprogram;
824
}
825
clp->lc_flags &= ~(LCL_NEEDSCONFIRM | LCL_DONTCLEAN);
826
if (clp->lc_program)
827
clp->lc_flags |= LCL_NEEDSCBNULL;
828
/* For NFSv4.1, link the session onto the client. */
829
if (nsep != NULL) {
830
/* Hold a reference on the xprt for a backchannel. */
831
if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN)
832
!= 0 && !sess_replay) {
833
if (clp->lc_req.nr_client == NULL) {
834
clp->lc_req.nr_client = client;
835
client = NULL;
836
}
837
if (clp->lc_req.nr_client != NULL) {
838
SVC_ACQUIRE(nd->nd_xprt);
839
CLNT_ACQUIRE(clp->lc_req.nr_client);
840
nd->nd_xprt->xp_p2 = clp->lc_req.nr_client;
841
/* Disable idle timeout. */
842
nd->nd_xprt->xp_idletimeout = 0;
843
nsep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
844
} else
845
nsep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN;
846
}
847
NFSBCOPY(sessid, nsep->sess_sessionid,
848
NFSX_V4SESSIONID);
849
NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid,
850
NFSX_V4SESSIONID);
851
if (!sess_replay) {
852
shp = NFSSESSIONHASH(nsep->sess_sessionid);
853
if (!mlocked)
854
NFSLOCKSTATE();
855
NFSLOCKSESSION(shp);
856
LIST_INSERT_HEAD(&shp->list, nsep, sess_hash);
857
LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list);
858
nsep->sess_clp = clp;
859
NFSUNLOCKSESSION(shp);
860
if (!mlocked)
861
NFSUNLOCKSTATE();
862
}
863
}
864
}
865
} else if (clp->lc_flags & LCL_NEEDSCONFIRM) {
866
error = NFSERR_EXPIRED;
867
}
868
869
/*
870
* If called by the Renew Op, we must check the principal.
871
*/
872
if (!error && (opflags & CLOPS_RENEWOP)) {
873
if (nfsrv_notsamecredname(0, nd, clp)) {
874
doneok = 0;
875
for (i = 0; i < nfsrv_statehashsize && doneok == 0; i++) {
876
LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
877
if ((stp->ls_flags & NFSLCK_OPEN) &&
878
stp->ls_uid == nd->nd_cred->cr_uid) {
879
doneok = 1;
880
break;
881
}
882
}
883
}
884
if (!doneok)
885
error = NFSERR_ACCES;
886
}
887
if (!error && (clp->lc_flags & LCL_CBDOWN))
888
error = NFSERR_CBPATHDOWN;
889
}
890
if ((!error || error == NFSERR_CBPATHDOWN) &&
891
(opflags & CLOPS_RENEW)) {
892
clp->lc_expiry = nfsrv_leaseexpiry();
893
}
894
if (opflags & CLOPS_CONFIRM) {
895
nfsrv_clientunlock(mlocked);
896
if (client != NULL)
897
CLNT_RELEASE(client);
898
if (old_xprt != NULL)
899
SVC_RELEASE(old_xprt);
900
} else if (opflags != CLOPS_RENEW) {
901
NFSUNLOCKSTATE();
902
}
903
if (clpp)
904
*clpp = clp;
905
906
out:
907
NFSEXITCODE2(error, nd);
908
return (error);
909
}
910
911
/*
912
* Perform the NFSv4.1 destroy clientid.
913
*/
914
int
915
nfsrv_destroyclient(struct nfsrv_descript *nd, nfsquad_t clientid, NFSPROC_T *p)
916
{
917
struct nfsclient *clp;
918
struct nfsclienthashhead *hp;
919
SVCXPRT *old_xprt;
920
int error = 0, i;
921
bool mlocked;
922
923
if (NFSD_VNET(nfsrvboottime) != clientid.lval[0]) {
924
error = NFSERR_STALECLIENTID;
925
goto out;
926
}
927
928
mlocked = true;
929
if (nfsrv_dolocallocks != 0)
930
mlocked = false;
931
/* Lock out other nfsd threads */
932
nfsrv_clientlock(mlocked);
933
934
hp = NFSCLIENTHASH(clientid);
935
LIST_FOREACH(clp, hp, lc_hash) {
936
if (clp->lc_clientid.lval[1] == clientid.lval[1])
937
break;
938
}
939
if (clp == NULL) {
940
nfsrv_clientunlock(mlocked);
941
/* Just return ok, since it is gone. */
942
goto out;
943
}
944
945
/* Check for the SP4_MACH_CRED case. */
946
error = nfsrv_checkmachcred(NFSV4OP_DESTROYCLIENTID, nd, clp);
947
if (error != 0) {
948
nfsrv_clientunlock(mlocked);
949
goto out;
950
}
951
952
/*
953
* Free up all layouts on the clientid. Should the client return the
954
* layouts?
955
*/
956
nfsrv_freelayoutlist(clientid);
957
958
/* Scan for state on the clientid. */
959
for (i = 0; i < nfsrv_statehashsize; i++)
960
if (!LIST_EMPTY(&clp->lc_stateid[i])) {
961
nfsrv_clientunlock(mlocked);
962
error = NFSERR_CLIENTIDBUSY;
963
goto out;
964
}
965
if (!LIST_EMPTY(&clp->lc_session) || !LIST_EMPTY(&clp->lc_deleg)) {
966
nfsrv_clientunlock(mlocked);
967
error = NFSERR_CLIENTIDBUSY;
968
goto out;
969
}
970
971
/* Destroy the clientid and return ok. */
972
old_xprt = NULL;
973
if (mlocked)
974
nfsrv_cleanclient(clp, p, true, &old_xprt);
975
else
976
nfsrv_cleanclient(clp, p, false, NULL);
977
nfsrv_freedeleglist(&clp->lc_deleg);
978
nfsrv_freedeleglist(&clp->lc_olddeleg);
979
LIST_REMOVE(clp, lc_hash);
980
nfsrv_clientunlock(mlocked);
981
if (old_xprt != NULL)
982
SVC_RELEASE(old_xprt);
983
nfsrv_zapclient(clp, p);
984
out:
985
NFSEXITCODE2(error, nd);
986
return (error);
987
}
988
989
/*
990
* Called from the new nfssvc syscall to admin revoke a clientid.
991
* Returns 0 for success, error otherwise.
992
*/
993
int
994
nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p)
995
{
996
struct nfsclient *clp = NULL;
997
int i, error = 0;
998
int gotit, igotlock;
999
1000
/*
1001
* First, lock out the nfsd so that state won't change while the
1002
* revocation record is being written to the stable storage restart
1003
* file.
1004
*/
1005
NFSLOCKV4ROOTMUTEX();
1006
do {
1007
igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
1008
NFSV4ROOTLOCKMUTEXPTR, NULL);
1009
} while (!igotlock);
1010
NFSUNLOCKV4ROOTMUTEX();
1011
1012
/*
1013
* Search for a match in the client list.
1014
*/
1015
gotit = i = 0;
1016
while (i < nfsrv_clienthashsize && !gotit) {
1017
LIST_FOREACH(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash) {
1018
if (revokep->nclid_idlen == clp->lc_idlen &&
1019
!NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) {
1020
gotit = 1;
1021
break;
1022
}
1023
}
1024
i++;
1025
}
1026
if (!gotit) {
1027
NFSLOCKV4ROOTMUTEX();
1028
nfsv4_unlock(&nfsv4rootfs_lock, 0);
1029
NFSUNLOCKV4ROOTMUTEX();
1030
error = EPERM;
1031
goto out;
1032
}
1033
1034
/*
1035
* Now, write out the revocation record
1036
*/
1037
nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
1038
nfsrv_backupstable();
1039
1040
/*
1041
* and clear out the state, marking the clientid revoked.
1042
*/
1043
clp->lc_flags &= ~LCL_CALLBACKSON;
1044
clp->lc_flags |= LCL_ADMINREVOKED;
1045
nfsrv_cleanclient(clp, p, false, NULL);
1046
nfsrv_freedeleglist(&clp->lc_deleg);
1047
nfsrv_freedeleglist(&clp->lc_olddeleg);
1048
NFSLOCKV4ROOTMUTEX();
1049
nfsv4_unlock(&nfsv4rootfs_lock, 0);
1050
NFSUNLOCKV4ROOTMUTEX();
1051
1052
out:
1053
NFSEXITCODE(error);
1054
return (error);
1055
}
1056
1057
/*
1058
* Dump out stats for all clients. Called from nfssvc(2), that is used
1059
* nfsstatsv1.
1060
*/
1061
void
1062
nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt)
1063
{
1064
struct nfsclient *clp;
1065
int i = 0, cnt = 0;
1066
1067
/*
1068
* First, get a reference on the nfsv4rootfs_lock so that an
1069
* exclusive lock cannot be acquired while dumping the clients.
1070
*/
1071
NFSLOCKV4ROOTMUTEX();
1072
nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
1073
NFSUNLOCKV4ROOTMUTEX();
1074
NFSLOCKSTATE();
1075
/*
1076
* Rattle through the client lists until done.
1077
*/
1078
while (i < nfsrv_clienthashsize && cnt < maxcnt) {
1079
clp = LIST_FIRST(&NFSD_VNET(nfsclienthash)[i]);
1080
while (clp != LIST_END(&NFSD_VNET(nfsclienthash)[i]) && cnt <
1081
maxcnt) {
1082
nfsrv_dumpaclient(clp, &dumpp[cnt]);
1083
cnt++;
1084
clp = LIST_NEXT(clp, lc_hash);
1085
}
1086
i++;
1087
}
1088
if (cnt < maxcnt)
1089
dumpp[cnt].ndcl_clid.nclid_idlen = 0;
1090
NFSUNLOCKSTATE();
1091
NFSLOCKV4ROOTMUTEX();
1092
nfsv4_relref(&nfsv4rootfs_lock);
1093
NFSUNLOCKV4ROOTMUTEX();
1094
}
1095
1096
/*
1097
* Dump stats for a client. Must be called with the NFSSTATELOCK and spl'd.
1098
*/
1099
static void
1100
nfsrv_dumpaclient(struct nfsclient *clp, struct nfsd_dumpclients *dumpp)
1101
{
1102
struct nfsstate *stp, *openstp, *lckownstp;
1103
struct nfslock *lop;
1104
sa_family_t af;
1105
#ifdef INET
1106
struct sockaddr_in *rin;
1107
#endif
1108
#ifdef INET6
1109
struct sockaddr_in6 *rin6;
1110
#endif
1111
1112
dumpp->ndcl_nopenowners = dumpp->ndcl_nlockowners = 0;
1113
dumpp->ndcl_nopens = dumpp->ndcl_nlocks = 0;
1114
dumpp->ndcl_ndelegs = dumpp->ndcl_nolddelegs = 0;
1115
dumpp->ndcl_flags = clp->lc_flags;
1116
dumpp->ndcl_clid.nclid_idlen = clp->lc_idlen;
1117
NFSBCOPY(clp->lc_id, dumpp->ndcl_clid.nclid_id, clp->lc_idlen);
1118
af = clp->lc_req.nr_nam->sa_family;
1119
dumpp->ndcl_addrfam = af;
1120
switch (af) {
1121
#ifdef INET
1122
case AF_INET:
1123
rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
1124
dumpp->ndcl_cbaddr.sin_addr = rin->sin_addr;
1125
break;
1126
#endif
1127
#ifdef INET6
1128
case AF_INET6:
1129
rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
1130
dumpp->ndcl_cbaddr.sin6_addr = rin6->sin6_addr;
1131
break;
1132
#endif
1133
}
1134
1135
/*
1136
* Now, scan the state lists and total up the opens and locks.
1137
*/
1138
LIST_FOREACH(stp, &clp->lc_open, ls_list) {
1139
dumpp->ndcl_nopenowners++;
1140
LIST_FOREACH(openstp, &stp->ls_open, ls_list) {
1141
dumpp->ndcl_nopens++;
1142
LIST_FOREACH(lckownstp, &openstp->ls_open, ls_list) {
1143
dumpp->ndcl_nlockowners++;
1144
LIST_FOREACH(lop, &lckownstp->ls_lock, lo_lckowner) {
1145
dumpp->ndcl_nlocks++;
1146
}
1147
}
1148
}
1149
}
1150
1151
/*
1152
* and the delegation lists.
1153
*/
1154
LIST_FOREACH(stp, &clp->lc_deleg, ls_list) {
1155
dumpp->ndcl_ndelegs++;
1156
}
1157
LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) {
1158
dumpp->ndcl_nolddelegs++;
1159
}
1160
}
1161
1162
/*
1163
* Dump out lock stats for a file.
1164
*/
1165
void
1166
nfsrv_dumplocks(vnode_t vp, struct nfsd_dumplocks *ldumpp, int maxcnt,
1167
NFSPROC_T *p)
1168
{
1169
struct nfsstate *stp;
1170
struct nfslock *lop;
1171
int cnt = 0;
1172
struct nfslockfile *lfp;
1173
sa_family_t af;
1174
#ifdef INET
1175
struct sockaddr_in *rin;
1176
#endif
1177
#ifdef INET6
1178
struct sockaddr_in6 *rin6;
1179
#endif
1180
int ret;
1181
fhandle_t nfh;
1182
1183
ret = nfsrv_getlockfh(vp, 0, NULL, &nfh, p);
1184
/*
1185
* First, get a reference on the nfsv4rootfs_lock so that an
1186
* exclusive lock on it cannot be acquired while dumping the locks.
1187
*/
1188
NFSLOCKV4ROOTMUTEX();
1189
nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
1190
NFSUNLOCKV4ROOTMUTEX();
1191
NFSLOCKSTATE();
1192
if (!ret)
1193
ret = nfsrv_getlockfile(0, NULL, &lfp, &nfh, 0);
1194
if (ret) {
1195
ldumpp[0].ndlck_clid.nclid_idlen = 0;
1196
NFSUNLOCKSTATE();
1197
NFSLOCKV4ROOTMUTEX();
1198
nfsv4_relref(&nfsv4rootfs_lock);
1199
NFSUNLOCKV4ROOTMUTEX();
1200
return;
1201
}
1202
1203
/*
1204
* For each open share on file, dump it out.
1205
*/
1206
stp = LIST_FIRST(&lfp->lf_open);
1207
while (stp != LIST_END(&lfp->lf_open) && cnt < maxcnt) {
1208
ldumpp[cnt].ndlck_flags = stp->ls_flags;
1209
ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
1210
ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
1211
ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
1212
ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
1213
ldumpp[cnt].ndlck_owner.nclid_idlen =
1214
stp->ls_openowner->ls_ownerlen;
1215
NFSBCOPY(stp->ls_openowner->ls_owner,
1216
ldumpp[cnt].ndlck_owner.nclid_id,
1217
stp->ls_openowner->ls_ownerlen);
1218
ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
1219
NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
1220
stp->ls_clp->lc_idlen);
1221
af = stp->ls_clp->lc_req.nr_nam->sa_family;
1222
ldumpp[cnt].ndlck_addrfam = af;
1223
switch (af) {
1224
#ifdef INET
1225
case AF_INET:
1226
rin = (struct sockaddr_in *)stp->ls_clp->lc_req.nr_nam;
1227
ldumpp[cnt].ndlck_cbaddr.sin_addr = rin->sin_addr;
1228
break;
1229
#endif
1230
#ifdef INET6
1231
case AF_INET6:
1232
rin6 = (struct sockaddr_in6 *)
1233
stp->ls_clp->lc_req.nr_nam;
1234
ldumpp[cnt].ndlck_cbaddr.sin6_addr = rin6->sin6_addr;
1235
break;
1236
#endif
1237
}
1238
stp = LIST_NEXT(stp, ls_file);
1239
cnt++;
1240
}
1241
1242
/*
1243
* and all locks.
1244
*/
1245
lop = LIST_FIRST(&lfp->lf_lock);
1246
while (lop != LIST_END(&lfp->lf_lock) && cnt < maxcnt) {
1247
stp = lop->lo_stp;
1248
ldumpp[cnt].ndlck_flags = lop->lo_flags;
1249
ldumpp[cnt].ndlck_first = lop->lo_first;
1250
ldumpp[cnt].ndlck_end = lop->lo_end;
1251
ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
1252
ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
1253
ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
1254
ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
1255
ldumpp[cnt].ndlck_owner.nclid_idlen = stp->ls_ownerlen;
1256
NFSBCOPY(stp->ls_owner, ldumpp[cnt].ndlck_owner.nclid_id,
1257
stp->ls_ownerlen);
1258
ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
1259
NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
1260
stp->ls_clp->lc_idlen);
1261
af = stp->ls_clp->lc_req.nr_nam->sa_family;
1262
ldumpp[cnt].ndlck_addrfam = af;
1263
switch (af) {
1264
#ifdef INET
1265
case AF_INET:
1266
rin = (struct sockaddr_in *)stp->ls_clp->lc_req.nr_nam;
1267
ldumpp[cnt].ndlck_cbaddr.sin_addr = rin->sin_addr;
1268
break;
1269
#endif
1270
#ifdef INET6
1271
case AF_INET6:
1272
rin6 = (struct sockaddr_in6 *)
1273
stp->ls_clp->lc_req.nr_nam;
1274
ldumpp[cnt].ndlck_cbaddr.sin6_addr = rin6->sin6_addr;
1275
break;
1276
#endif
1277
}
1278
lop = LIST_NEXT(lop, lo_lckfile);
1279
cnt++;
1280
}
1281
1282
/*
1283
* and the delegations.
1284
*/
1285
stp = LIST_FIRST(&lfp->lf_deleg);
1286
while (stp != LIST_END(&lfp->lf_deleg) && cnt < maxcnt) {
1287
ldumpp[cnt].ndlck_flags = stp->ls_flags;
1288
ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
1289
ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
1290
ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
1291
ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
1292
ldumpp[cnt].ndlck_owner.nclid_idlen = 0;
1293
ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
1294
NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
1295
stp->ls_clp->lc_idlen);
1296
af = stp->ls_clp->lc_req.nr_nam->sa_family;
1297
ldumpp[cnt].ndlck_addrfam = af;
1298
switch (af) {
1299
#ifdef INET
1300
case AF_INET:
1301
rin = (struct sockaddr_in *)stp->ls_clp->lc_req.nr_nam;
1302
ldumpp[cnt].ndlck_cbaddr.sin_addr = rin->sin_addr;
1303
break;
1304
#endif
1305
#ifdef INET6
1306
case AF_INET6:
1307
rin6 = (struct sockaddr_in6 *)
1308
stp->ls_clp->lc_req.nr_nam;
1309
ldumpp[cnt].ndlck_cbaddr.sin6_addr = rin6->sin6_addr;
1310
break;
1311
#endif
1312
}
1313
stp = LIST_NEXT(stp, ls_file);
1314
cnt++;
1315
}
1316
1317
/*
1318
* If list isn't full, mark end of list by setting the client name
1319
* to zero length.
1320
*/
1321
if (cnt < maxcnt)
1322
ldumpp[cnt].ndlck_clid.nclid_idlen = 0;
1323
NFSUNLOCKSTATE();
1324
NFSLOCKV4ROOTMUTEX();
1325
nfsv4_relref(&nfsv4rootfs_lock);
1326
NFSUNLOCKV4ROOTMUTEX();
1327
}
1328
1329
/*
1330
* Server timer routine. It can scan any linked list, so long
1331
* as it holds the spin/mutex lock and there is no exclusive lock on
1332
* nfsv4rootfs_lock.
1333
* (For OpenBSD, a kthread is ok. For FreeBSD, I think it is ok
1334
* to do this from a callout, since the spin locks work. For
1335
* Darwin, I'm not sure what will work correctly yet.)
1336
* Should be called once per second.
1337
*/
1338
void
1339
nfsrv_servertimer(void *arg __unused)
1340
{
1341
struct nfsclient *clp, *nclp;
1342
struct nfsstate *stp, *nstp;
1343
int got_ref, i;
1344
1345
/*
1346
* Make sure nfsboottime is set. This is used by V3 as well
1347
* as V4. Note that nfsboottime is not nfsrvboottime, which is
1348
* only used by the V4 server for leases.
1349
*/
1350
if (nfsboottime.tv_sec == 0)
1351
NFSSETBOOTTIME(nfsboottime);
1352
1353
/*
1354
* If server hasn't started yet, just return.
1355
*/
1356
NFSLOCKSTATE();
1357
if (NFSD_VNET(nfsrv_stablefirst).nsf_eograce == 0) {
1358
NFSUNLOCKSTATE();
1359
return;
1360
}
1361
if (!(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_UPDATEDONE)) {
1362
if (!(NFSD_VNET(nfsrv_stablefirst).nsf_flags &
1363
NFSNSF_GRACEOVER) &&
1364
NFSD_MONOSEC > NFSD_VNET(nfsrv_stablefirst).nsf_eograce)
1365
NFSD_VNET(nfsrv_stablefirst).nsf_flags |=
1366
(NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
1367
NFSUNLOCKSTATE();
1368
return;
1369
}
1370
1371
/*
1372
* Try and get a reference count on the nfsv4rootfs_lock so that
1373
* no nfsd thread can acquire an exclusive lock on it before this
1374
* call is done. If it is already exclusively locked, just return.
1375
*/
1376
NFSLOCKV4ROOTMUTEX();
1377
got_ref = nfsv4_getref_nonblock(&nfsv4rootfs_lock);
1378
NFSUNLOCKV4ROOTMUTEX();
1379
if (got_ref == 0) {
1380
NFSUNLOCKSTATE();
1381
return;
1382
}
1383
1384
/*
1385
* For each client...
1386
*/
1387
for (i = 0; i < nfsrv_clienthashsize; i++) {
1388
clp = LIST_FIRST(&NFSD_VNET(nfsclienthash)[i]);
1389
while (clp != LIST_END(&NFSD_VNET(nfsclienthash)[i])) {
1390
nclp = LIST_NEXT(clp, lc_hash);
1391
if (!(clp->lc_flags & LCL_EXPIREIT)) {
1392
if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC
1393
&& ((LIST_EMPTY(&clp->lc_deleg)
1394
&& LIST_EMPTY(&clp->lc_open)) ||
1395
nfsrv_clients > nfsrv_clienthighwater)) ||
1396
(clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC ||
1397
(clp->lc_expiry < NFSD_MONOSEC &&
1398
(nfsrv_openpluslock * 10 / 9) > nfsrv_v4statelimit)) {
1399
/*
1400
* Lease has expired several nfsrv_lease times ago:
1401
* PLUS
1402
* - no state is associated with it
1403
* OR
1404
* - above high water mark for number of clients
1405
* (nfsrv_clienthighwater should be large enough
1406
* that this only occurs when clients fail to
1407
* use the same nfs_client_id4.id. Maybe somewhat
1408
* higher that the maximum number of clients that
1409
* will mount this server?)
1410
* OR
1411
* Lease has expired a very long time ago
1412
* OR
1413
* Lease has expired PLUS the number of opens + locks
1414
* has exceeded 90% of capacity
1415
*
1416
* --> Mark for expiry. The actual expiry will be done
1417
* by an nfsd sometime soon.
1418
*/
1419
clp->lc_flags |= LCL_EXPIREIT;
1420
NFSD_VNET(nfsrv_stablefirst).nsf_flags |=
1421
(NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT);
1422
} else {
1423
/*
1424
* If there are no opens, increment no open tick cnt
1425
* If time exceeds NFSNOOPEN, mark it to be thrown away
1426
* otherwise, if there is an open, reset no open time
1427
* Hopefully, this will avoid excessive re-creation
1428
* of open owners and subsequent open confirms.
1429
*/
1430
stp = LIST_FIRST(&clp->lc_open);
1431
while (stp != LIST_END(&clp->lc_open)) {
1432
nstp = LIST_NEXT(stp, ls_list);
1433
if (LIST_EMPTY(&stp->ls_open)) {
1434
stp->ls_noopens++;
1435
if (stp->ls_noopens > NFSNOOPEN ||
1436
(nfsrv_openpluslock * 2) >
1437
nfsrv_v4statelimit)
1438
NFSD_VNET(nfsrv_stablefirst).nsf_flags |=
1439
NFSNSF_NOOPENS;
1440
} else {
1441
stp->ls_noopens = 0;
1442
}
1443
stp = nstp;
1444
}
1445
}
1446
}
1447
clp = nclp;
1448
}
1449
}
1450
NFSUNLOCKSTATE();
1451
NFSLOCKV4ROOTMUTEX();
1452
nfsv4_relref(&nfsv4rootfs_lock);
1453
NFSUNLOCKV4ROOTMUTEX();
1454
}
1455
1456
/*
1457
* The following set of functions free up the various data structures.
1458
*/
1459
/*
1460
* Clear out all open/lock state related to this nfsclient.
1461
* Caller must hold an exclusive lock on nfsv4rootfs_lock, so that
1462
* there are no other active nfsd threads.
1463
*/
1464
void
1465
nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p, bool locked,
1466
SVCXPRT **old_xprtp)
1467
{
1468
struct nfsstate *stp, *nstp;
1469
struct nfsdsession *sep, *nsep;
1470
1471
LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) {
1472
if (locked)
1473
nfsrv_freeopenowner(stp, 0, p);
1474
else
1475
nfsrv_freeopenowner(stp, 1, p);
1476
}
1477
if ((clp->lc_flags & LCL_ADMINREVOKED) == 0)
1478
LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep)
1479
(void)nfsrv_freesession(NULL, sep, NULL, locked,
1480
old_xprtp);
1481
}
1482
1483
/*
1484
* Free a client that has been cleaned. It should also already have been
1485
* removed from the lists.
1486
* (Just to be safe w.r.t. newnfs_disconnect(), call this function when
1487
* softclock interrupts are enabled.)
1488
*/
1489
void
1490
nfsrv_zapclient(struct nfsclient *clp, NFSPROC_T *p)
1491
{
1492
1493
#ifdef notyet
1494
if ((clp->lc_flags & (LCL_GSS | LCL_CALLBACKSON)) ==
1495
(LCL_GSS | LCL_CALLBACKSON) &&
1496
(clp->lc_hand.nfsh_flag & NFSG_COMPLETE) &&
1497
clp->lc_handlelen > 0) {
1498
clp->lc_hand.nfsh_flag &= ~NFSG_COMPLETE;
1499
clp->lc_hand.nfsh_flag |= NFSG_DESTROYED;
1500
(void) nfsrv_docallback(clp, NFSV4PROC_CBNULL,
1501
NULL, 0, NULL, NULL, NULL, 0, p);
1502
}
1503
#endif
1504
newnfs_disconnect(NULL, &clp->lc_req);
1505
free(clp->lc_req.nr_nam, M_SONAME);
1506
NFSFREEMUTEX(&clp->lc_req.nr_mtx);
1507
free(clp->lc_stateid, M_NFSDCLIENT);
1508
free(clp, M_NFSDCLIENT);
1509
NFSLOCKSTATE();
1510
NFSD_VNET(nfsstatsv1_p)->srvclients--;
1511
nfsrv_openpluslock--;
1512
nfsrv_clients--;
1513
NFSUNLOCKSTATE();
1514
}
1515
1516
/*
1517
* Free a list of delegation state structures.
1518
* (This function will also free all nfslockfile structures that no
1519
* longer have associated state.)
1520
*/
1521
void
1522
nfsrv_freedeleglist(struct nfsstatehead *sthp)
1523
{
1524
struct nfsstate *stp, *nstp;
1525
1526
LIST_FOREACH_SAFE(stp, sthp, ls_list, nstp) {
1527
nfsrv_freedeleg(stp);
1528
}
1529
LIST_INIT(sthp);
1530
}
1531
1532
/*
1533
* Free up a delegation.
1534
*/
1535
static void
1536
nfsrv_freedeleg(struct nfsstate *stp)
1537
{
1538
struct nfslockfile *lfp;
1539
1540
LIST_REMOVE(stp, ls_hash);
1541
LIST_REMOVE(stp, ls_list);
1542
LIST_REMOVE(stp, ls_file);
1543
if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0)
1544
nfsrv_writedelegcnt--;
1545
lfp = stp->ls_lfp;
1546
if (LIST_EMPTY(&lfp->lf_open) &&
1547
LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) &&
1548
LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) &&
1549
lfp->lf_usecount == 0 &&
1550
nfsv4_testlock(&lfp->lf_locallock_lck) == 0)
1551
nfsrv_freenfslockfile(lfp);
1552
free(stp, M_NFSDSTATE);
1553
NFSD_VNET(nfsstatsv1_p)->srvdelegates--;
1554
nfsrv_openpluslock--;
1555
nfsrv_delegatecnt--;
1556
}
1557
1558
/*
1559
* This function frees an open owner and all associated opens.
1560
*/
1561
static void
1562
nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p)
1563
{
1564
struct nfsstate *nstp, *tstp;
1565
1566
LIST_REMOVE(stp, ls_list);
1567
/*
1568
* Now, free all associated opens.
1569
*/
1570
nstp = LIST_FIRST(&stp->ls_open);
1571
while (nstp != LIST_END(&stp->ls_open)) {
1572
tstp = nstp;
1573
nstp = LIST_NEXT(nstp, ls_list);
1574
nfsrv_freeopen(tstp, NULL, cansleep, p);
1575
}
1576
if (stp->ls_op)
1577
nfsrvd_derefcache(stp->ls_op);
1578
free(stp, M_NFSDSTATE);
1579
NFSD_VNET(nfsstatsv1_p)->srvopenowners--;
1580
nfsrv_openpluslock--;
1581
}
1582
1583
/*
1584
* This function frees an open (nfsstate open structure) with all associated
1585
* lock_owners and locks. It also frees the nfslockfile structure iff there
1586
* are no other opens on the file.
1587
* Returns 1 if it free'd the nfslockfile, 0 otherwise.
1588
*/
1589
static void
1590
nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p)
1591
{
1592
struct nfsstate *nstp, *tstp;
1593
struct nfslockfile *lfp;
1594
1595
LIST_REMOVE(stp, ls_hash);
1596
LIST_REMOVE(stp, ls_list);
1597
LIST_REMOVE(stp, ls_file);
1598
1599
lfp = stp->ls_lfp;
1600
/*
1601
* Now, free all lockowners associated with this open.
1602
* Note that, if vp != NULL, nfsrv_freelockowner() will
1603
* not call nfsrv_freeallnfslocks(), so it needs to be called, below.
1604
*/
1605
LIST_FOREACH_SAFE(tstp, &stp->ls_open, ls_list, nstp)
1606
nfsrv_freelockowner(tstp, vp, cansleep, p);
1607
1608
if (vp != NULL) {
1609
KASSERT(cansleep != 0, ("nfsrv_freeopen: cansleep == 0"));
1610
mtx_assert(NFSSTATEMUTEXPTR, MA_OWNED);
1611
/*
1612
* Only called with vp != NULL for Close when
1613
* vfs.nfsd.enable_locallocks != 0.
1614
* Lock the lfp so that it will not go away and do the
1615
* nfsrv_freeallnfslocks() call that was not done by
1616
* nfsrv_freelockowner().
1617
*/
1618
nfsrv_locklf(lfp);
1619
NFSUNLOCKSTATE();
1620
NFSVOPUNLOCK(vp);
1621
nfsrv_freeallnfslocks(stp, vp, cansleep, p);
1622
NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
1623
NFSLOCKSTATE();
1624
nfsrv_unlocklf(lfp);
1625
}
1626
1627
/*
1628
* The nfslockfile is freed here if there are no locks
1629
* associated with the open.
1630
* If there are locks associated with the open, the
1631
* nfslockfile structure can be freed via nfsrv_freelockowner().
1632
*/
1633
if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) &&
1634
LIST_EMPTY(&lfp->lf_deleg) && LIST_EMPTY(&lfp->lf_lock) &&
1635
LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) &&
1636
lfp->lf_usecount == 0 &&
1637
nfsv4_testlock(&lfp->lf_locallock_lck) == 0)
1638
nfsrv_freenfslockfile(lfp);
1639
free(stp, M_NFSDSTATE);
1640
NFSD_VNET(nfsstatsv1_p)->srvopens--;
1641
nfsrv_openpluslock--;
1642
}
1643
1644
/*
1645
* Frees a lockowner and all associated locks.
1646
*/
1647
static void
1648
nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep,
1649
NFSPROC_T *p)
1650
{
1651
1652
LIST_REMOVE(stp, ls_hash);
1653
LIST_REMOVE(stp, ls_list);
1654
if (vp == NULL)
1655
nfsrv_freeallnfslocks(stp, vp, cansleep, p);
1656
if (stp->ls_op)
1657
nfsrvd_derefcache(stp->ls_op);
1658
free(stp, M_NFSDSTATE);
1659
NFSD_VNET(nfsstatsv1_p)->srvlockowners--;
1660
nfsrv_openpluslock--;
1661
}
1662
1663
/*
1664
* Free all the nfs locks on a lockowner.
1665
*/
1666
static void
1667
nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep,
1668
NFSPROC_T *p)
1669
{
1670
struct nfslock *lop, *nlop;
1671
struct nfsrollback *rlp, *nrlp;
1672
struct nfslockfile *lfp = NULL;
1673
int gottvp = 0;
1674
vnode_t tvp = NULL;
1675
uint64_t first, end;
1676
1677
if (vp != NULL)
1678
ASSERT_VOP_UNLOCKED(vp, "nfsrv_freeallnfslocks: vnode locked");
1679
lop = LIST_FIRST(&stp->ls_lock);
1680
while (lop != LIST_END(&stp->ls_lock)) {
1681
nlop = LIST_NEXT(lop, lo_lckowner);
1682
/*
1683
* Since all locks should be for the same file, lfp should
1684
* not change.
1685
*/
1686
if (lfp == NULL)
1687
lfp = lop->lo_lfp;
1688
else if (lfp != lop->lo_lfp)
1689
panic("allnfslocks");
1690
/*
1691
* If vp is NULL and cansleep != 0, a vnode must be acquired
1692
* from the file handle. This only occurs when called from
1693
* nfsrv_cleanclient().
1694
*/
1695
if (gottvp == 0) {
1696
if (nfsrv_dolocallocks == 0)
1697
tvp = NULL;
1698
else if (vp == NULL && cansleep != 0) {
1699
tvp = nfsvno_getvp(&lfp->lf_fh);
1700
if (tvp != NULL)
1701
NFSVOPUNLOCK(tvp);
1702
} else
1703
tvp = vp;
1704
gottvp = 1;
1705
}
1706
1707
if (tvp != NULL) {
1708
if (cansleep == 0)
1709
panic("allnfs2");
1710
first = lop->lo_first;
1711
end = lop->lo_end;
1712
nfsrv_freenfslock(lop);
1713
nfsrv_localunlock(tvp, lfp, first, end, p);
1714
LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list,
1715
nrlp)
1716
free(rlp, M_NFSDROLLBACK);
1717
LIST_INIT(&lfp->lf_rollback);
1718
} else
1719
nfsrv_freenfslock(lop);
1720
lop = nlop;
1721
}
1722
if (vp == NULL && tvp != NULL)
1723
vrele(tvp);
1724
}
1725
1726
/*
1727
* Free an nfslock structure.
1728
*/
1729
static void
1730
nfsrv_freenfslock(struct nfslock *lop)
1731
{
1732
1733
if (lop->lo_lckfile.le_prev != NULL) {
1734
LIST_REMOVE(lop, lo_lckfile);
1735
NFSD_VNET(nfsstatsv1_p)->srvlocks--;
1736
nfsrv_openpluslock--;
1737
}
1738
LIST_REMOVE(lop, lo_lckowner);
1739
free(lop, M_NFSDLOCK);
1740
}
1741
1742
/*
1743
* This function frees an nfslockfile structure.
1744
*/
1745
static void
1746
nfsrv_freenfslockfile(struct nfslockfile *lfp)
1747
{
1748
1749
LIST_REMOVE(lfp, lf_hash);
1750
free(lfp, M_NFSDLOCKFILE);
1751
}
1752
1753
/*
1754
* This function looks up an nfsstate structure via stateid.
1755
*/
1756
static int
1757
nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32_t flags,
1758
struct nfsstate **stpp)
1759
{
1760
struct nfsstate *stp;
1761
struct nfsstatehead *hp;
1762
int error = 0;
1763
1764
*stpp = NULL;
1765
hp = NFSSTATEHASH(clp, *stateidp);
1766
LIST_FOREACH(stp, hp, ls_hash) {
1767
if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
1768
NFSX_STATEIDOTHER))
1769
break;
1770
}
1771
1772
/*
1773
* If no state id in list, return NFSERR_BADSTATEID.
1774
*/
1775
if (stp == LIST_END(hp)) {
1776
error = NFSERR_BADSTATEID;
1777
goto out;
1778
}
1779
*stpp = stp;
1780
1781
out:
1782
NFSEXITCODE(error);
1783
return (error);
1784
}
1785
1786
/*
1787
* This function gets an nfsstate structure via owner string.
1788
*/
1789
static void
1790
nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp,
1791
struct nfsstate **stpp)
1792
{
1793
struct nfsstate *stp;
1794
1795
*stpp = NULL;
1796
LIST_FOREACH(stp, hp, ls_list) {
1797
if (new_stp->ls_ownerlen == stp->ls_ownerlen &&
1798
!NFSBCMP(new_stp->ls_owner,stp->ls_owner,stp->ls_ownerlen)) {
1799
*stpp = stp;
1800
return;
1801
}
1802
}
1803
}
1804
1805
/*
1806
* Lock control function called to update lock status.
1807
* Returns 0 upon success, -1 if there is no lock and the flags indicate
1808
* that one isn't to be created and an NFSERR_xxx for other errors.
1809
* The structures new_stp and new_lop are passed in as pointers that should
1810
* be set to NULL if the structure is used and shouldn't be free'd.
1811
* For the NFSLCK_TEST and NFSLCK_CHECK cases, the structures are
1812
* never used and can safely be allocated on the stack. For all other
1813
* cases, *new_stpp and *new_lopp should be malloc'd before the call,
1814
* in case they are used.
1815
*/
1816
int
1817
nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp,
1818
struct nfslock **new_lopp, struct nfslockconflict *cfp,
1819
nfsquad_t clientid, nfsv4stateid_t *stateidp,
1820
__unused struct nfsexstuff *exp,
1821
struct nfsrv_descript *nd, NFSPROC_T *p)
1822
{
1823
struct nfslock *lop;
1824
struct nfsstate *new_stp = *new_stpp;
1825
struct nfslock *new_lop = *new_lopp;
1826
struct nfsstate *tstp, *mystp, *nstp;
1827
int specialid = 0;
1828
struct nfslockfile *lfp;
1829
struct nfslock *other_lop = NULL;
1830
struct nfsstate *stp, *lckstp = NULL;
1831
struct nfsclient *clp = NULL;
1832
u_int32_t bits;
1833
int error = 0, haslock = 0, ret, reterr;
1834
int getlckret, delegation = 0, filestruct_locked, vnode_unlocked = 0;
1835
fhandle_t nfh;
1836
uint64_t first, end;
1837
uint32_t lock_flags;
1838
1839
if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_SETATTR)) {
1840
/*
1841
* Note the special cases of "all 1s" or "all 0s" stateids and
1842
* let reads with all 1s go ahead.
1843
*/
1844
if (new_stp->ls_stateid.seqid == 0x0 &&
1845
new_stp->ls_stateid.other[0] == 0x0 &&
1846
new_stp->ls_stateid.other[1] == 0x0 &&
1847
new_stp->ls_stateid.other[2] == 0x0)
1848
specialid = 1;
1849
else if (new_stp->ls_stateid.seqid == 0xffffffff &&
1850
new_stp->ls_stateid.other[0] == 0xffffffff &&
1851
new_stp->ls_stateid.other[1] == 0xffffffff &&
1852
new_stp->ls_stateid.other[2] == 0xffffffff)
1853
specialid = 2;
1854
}
1855
1856
/*
1857
* Check for restart conditions (client and server).
1858
*/
1859
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
1860
&new_stp->ls_stateid, specialid);
1861
if (error)
1862
goto out;
1863
1864
/*
1865
* Check for state resource limit exceeded.
1866
*/
1867
if ((new_stp->ls_flags & NFSLCK_LOCK) &&
1868
nfsrv_openpluslock > nfsrv_v4statelimit) {
1869
error = NFSERR_RESOURCE;
1870
goto out;
1871
}
1872
1873
/*
1874
* For the lock case, get another nfslock structure,
1875
* just in case we need it.
1876
* Malloc now, before we start sifting through the linked lists,
1877
* in case we have to wait for memory.
1878
*/
1879
tryagain:
1880
if (new_stp->ls_flags & NFSLCK_LOCK)
1881
other_lop = malloc(sizeof (struct nfslock),
1882
M_NFSDLOCK, M_WAITOK);
1883
filestruct_locked = 0;
1884
reterr = 0;
1885
lfp = NULL;
1886
1887
/*
1888
* Get the lockfile structure for CFH now, so we can do a sanity
1889
* check against the stateid, before incrementing the seqid#, since
1890
* we want to return NFSERR_BADSTATEID on failure and the seqid#
1891
* shouldn't be incremented for this case.
1892
* If nfsrv_getlockfile() returns -1, it means "not found", which
1893
* will be handled later.
1894
* If we are doing Lock/LockU and local locking is enabled, sleep
1895
* lock the nfslockfile structure.
1896
*/
1897
getlckret = nfsrv_getlockfh(vp, new_stp->ls_flags, NULL, &nfh, p);
1898
NFSLOCKSTATE();
1899
if (getlckret == 0) {
1900
if ((new_stp->ls_flags & (NFSLCK_LOCK | NFSLCK_UNLOCK)) != 0 &&
1901
nfsrv_dolocallocks != 0 && nd->nd_repstat == 0) {
1902
getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL,
1903
&lfp, &nfh, 1);
1904
if (getlckret == 0)
1905
filestruct_locked = 1;
1906
} else
1907
getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL,
1908
&lfp, &nfh, 0);
1909
}
1910
if (getlckret != 0 && getlckret != -1)
1911
reterr = getlckret;
1912
1913
if (filestruct_locked != 0) {
1914
LIST_INIT(&lfp->lf_rollback);
1915
if ((new_stp->ls_flags & NFSLCK_LOCK)) {
1916
/*
1917
* For local locking, do the advisory locking now, so
1918
* that any conflict can be detected. A failure later
1919
* can be rolled back locally. If an error is returned,
1920
* struct nfslockfile has been unlocked and any local
1921
* locking rolled back.
1922
*/
1923
NFSUNLOCKSTATE();
1924
if (vnode_unlocked == 0) {
1925
ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl1");
1926
vnode_unlocked = 1;
1927
NFSVOPUNLOCK(vp);
1928
}
1929
reterr = nfsrv_locallock(vp, lfp,
1930
(new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)),
1931
new_lop->lo_first, new_lop->lo_end, cfp, p);
1932
NFSLOCKSTATE();
1933
}
1934
}
1935
1936
if (specialid == 0) {
1937
if (new_stp->ls_flags & NFSLCK_TEST) {
1938
/*
1939
* RFC 3530 does not list LockT as an op that renews a
1940
* lease, but the consensus seems to be that it is ok
1941
* for a server to do so.
1942
*/
1943
error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
1944
(nfsquad_t)((u_quad_t)0), 0, nd, p);
1945
1946
/*
1947
* Since NFSERR_EXPIRED, NFSERR_ADMINREVOKED are not valid
1948
* error returns for LockT, just go ahead and test for a lock,
1949
* since there are no locks for this client, but other locks
1950
* can conflict. (ie. same client will always be false)
1951
*/
1952
if (error == NFSERR_EXPIRED || error == NFSERR_ADMINREVOKED)
1953
error = 0;
1954
lckstp = new_stp;
1955
} else {
1956
error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
1957
(nfsquad_t)((u_quad_t)0), 0, nd, p);
1958
if (error == 0)
1959
/*
1960
* Look up the stateid
1961
*/
1962
error = nfsrv_getstate(clp, &new_stp->ls_stateid,
1963
new_stp->ls_flags, &stp);
1964
/*
1965
* do some sanity checks for an unconfirmed open or a
1966
* stateid that refers to the wrong file, for an open stateid
1967
*/
1968
if (error == 0 && (stp->ls_flags & NFSLCK_OPEN) &&
1969
((stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM) ||
1970
(getlckret == 0 && stp->ls_lfp != lfp))){
1971
/*
1972
* NFSLCK_SETATTR should return OK rather than NFSERR_BADSTATEID
1973
* The only exception is using SETATTR with SIZE.
1974
* */
1975
if ((new_stp->ls_flags &
1976
(NFSLCK_SETATTR | NFSLCK_CHECK)) != NFSLCK_SETATTR)
1977
error = NFSERR_BADSTATEID;
1978
}
1979
1980
/*
1981
* Sanity check the stateid for the Lock/LockU cases.
1982
*/
1983
if (error == 0 && (new_stp->ls_flags & NFSLCK_LOCK) != 0 &&
1984
(((new_stp->ls_flags & NFSLCK_OPENTOLOCK) != 0 &&
1985
(stp->ls_flags & NFSLCK_OPEN) == 0) ||
1986
((new_stp->ls_flags & NFSLCK_OPENTOLOCK) == 0 &&
1987
(stp->ls_flags & NFSLCK_LOCK) == 0)))
1988
error = NFSERR_BADSTATEID;
1989
if (error == 0 && (new_stp->ls_flags & NFSLCK_UNLOCK) != 0 &&
1990
(stp->ls_flags & NFSLCK_LOCK) == 0)
1991
error = NFSERR_BADSTATEID;
1992
1993
/* Sanity check the delegation stateid. */
1994
if (error == 0 &&
1995
(stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) &&
1996
getlckret == 0 && stp->ls_lfp != lfp)
1997
error = NFSERR_BADSTATEID;
1998
1999
/*
2000
* If the lockowner stateid doesn't refer to the same file,
2001
* I believe that is considered ok, since some clients will
2002
* only create a single lockowner and use that for all locks
2003
* on all files.
2004
* For now, log it as a diagnostic, instead of considering it
2005
* a BadStateid.
2006
*/
2007
if (error == 0 && (stp->ls_flags &
2008
(NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 &&
2009
getlckret == 0 && stp->ls_lfp != lfp) {
2010
#ifdef DIAGNOSTIC
2011
printf("Got a lock statid for different file open\n");
2012
#endif
2013
/*
2014
error = NFSERR_BADSTATEID;
2015
*/
2016
}
2017
2018
if (error == 0) {
2019
if (new_stp->ls_flags & NFSLCK_OPENTOLOCK) {
2020
/*
2021
* If haslock set, we've already checked the seqid.
2022
*/
2023
if (!haslock) {
2024
if (stp->ls_flags & NFSLCK_OPEN)
2025
error = nfsrv_checkseqid(nd, new_stp->ls_seq,
2026
stp->ls_openowner, new_stp->ls_op);
2027
else
2028
error = NFSERR_BADSTATEID;
2029
}
2030
if (!error)
2031
nfsrv_getowner(&stp->ls_open, new_stp, &lckstp);
2032
if (lckstp) {
2033
/*
2034
* For NFSv4.1 and NFSv4.2 allow an
2035
* open_to_lock_owner when the lock_owner already
2036
* exists. Just clear NFSLCK_OPENTOLOCK so that
2037
* a new lock_owner will not be created.
2038
* RFC7530 states that the error for NFSv4.0
2039
* is NFS4ERR_BAD_SEQID.
2040
*/
2041
if ((nd->nd_flag & ND_NFSV41) != 0)
2042
new_stp->ls_flags &= ~NFSLCK_OPENTOLOCK;
2043
else
2044
error = NFSERR_BADSEQID;
2045
} else
2046
lckstp = new_stp;
2047
} else if (new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK)) {
2048
/*
2049
* If haslock set, ditto above.
2050
*/
2051
if (!haslock) {
2052
if (stp->ls_flags & NFSLCK_OPEN)
2053
error = NFSERR_BADSTATEID;
2054
else
2055
error = nfsrv_checkseqid(nd, new_stp->ls_seq,
2056
stp, new_stp->ls_op);
2057
}
2058
lckstp = stp;
2059
} else {
2060
lckstp = stp;
2061
}
2062
}
2063
/*
2064
* If the seqid part of the stateid isn't the same, return
2065
* NFSERR_OLDSTATEID for cases other than I/O Ops.
2066
* For I/O Ops, only return NFSERR_OLDSTATEID if
2067
* nfsrv_returnoldstateid is set. (The consensus on the email
2068
* list was that most clients would prefer to not receive
2069
* NFSERR_OLDSTATEID for I/O Ops, but the RFC suggests that that
2070
* is what will happen, so I use the nfsrv_returnoldstateid to
2071
* allow for either server configuration.)
2072
*/
2073
if (!error && stp->ls_stateid.seqid!=new_stp->ls_stateid.seqid &&
2074
(((nd->nd_flag & ND_NFSV41) == 0 &&
2075
(!(new_stp->ls_flags & NFSLCK_CHECK) ||
2076
nfsrv_returnoldstateid)) ||
2077
((nd->nd_flag & ND_NFSV41) != 0 &&
2078
new_stp->ls_stateid.seqid != 0)))
2079
error = NFSERR_OLDSTATEID;
2080
}
2081
}
2082
2083
/*
2084
* Now we can check for grace.
2085
*/
2086
if (!error)
2087
error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
2088
if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
2089
nfsrv_checkstable(clp))
2090
error = NFSERR_NOGRACE;
2091
/*
2092
* If we successfully Reclaimed state, note that.
2093
*/
2094
if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error)
2095
nfsrv_markstable(clp);
2096
2097
/*
2098
* At this point, either error == NFSERR_BADSTATEID or the
2099
* seqid# has been updated, so we can return any error.
2100
* If error == 0, there may be an error in:
2101
* nd_repstat - Set by the calling function.
2102
* reterr - Set above, if getting the nfslockfile structure
2103
* or acquiring the local lock failed.
2104
* (If both of these are set, nd_repstat should probably be
2105
* returned, since that error was detected before this
2106
* function call.)
2107
*/
2108
if (error != 0 || nd->nd_repstat != 0 || reterr != 0) {
2109
if (error == 0) {
2110
if (nd->nd_repstat != 0)
2111
error = nd->nd_repstat;
2112
else
2113
error = reterr;
2114
}
2115
if (filestruct_locked != 0) {
2116
/* Roll back local locks. */
2117
NFSUNLOCKSTATE();
2118
if (vnode_unlocked == 0) {
2119
ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl2");
2120
vnode_unlocked = 1;
2121
NFSVOPUNLOCK(vp);
2122
}
2123
nfsrv_locallock_rollback(vp, lfp, p);
2124
NFSLOCKSTATE();
2125
nfsrv_unlocklf(lfp);
2126
}
2127
NFSUNLOCKSTATE();
2128
goto out;
2129
}
2130
2131
/*
2132
* Check the nfsrv_getlockfile return.
2133
* Returned -1 if no structure found.
2134
*/
2135
if (getlckret == -1) {
2136
error = NFSERR_EXPIRED;
2137
/*
2138
* Called from lockt, so no lock is OK.
2139
*/
2140
if (new_stp->ls_flags & NFSLCK_TEST) {
2141
error = 0;
2142
} else if (new_stp->ls_flags &
2143
(NFSLCK_CHECK | NFSLCK_SETATTR)) {
2144
/*
2145
* Called to check for a lock, OK if the stateid is all
2146
* 1s or all 0s, but there should be an nfsstate
2147
* otherwise.
2148
* (ie. If there is no open, I'll assume no share
2149
* deny bits.)
2150
*/
2151
if (specialid)
2152
error = 0;
2153
else
2154
error = NFSERR_BADSTATEID;
2155
}
2156
NFSUNLOCKSTATE();
2157
goto out;
2158
}
2159
2160
/*
2161
* For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict.
2162
* For NFSLCK_CHECK, allow a read if write access is granted,
2163
* but check for a deny. For NFSLCK_LOCK, require correct access,
2164
* which implies a conflicting deny can't exist.
2165
*/
2166
if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_LOCK)) {
2167
/*
2168
* Four kinds of state id:
2169
* - specialid (all 0s or all 1s), only for NFSLCK_CHECK
2170
* - stateid for an open
2171
* - stateid for a delegation
2172
* - stateid for a lock owner
2173
*/
2174
if (!specialid) {
2175
if (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
2176
delegation = 1;
2177
mystp = stp;
2178
nfsrv_delaydelegtimeout(stp);
2179
} else if (stp->ls_flags & NFSLCK_OPEN) {
2180
mystp = stp;
2181
} else {
2182
mystp = stp->ls_openstp;
2183
}
2184
/*
2185
* If locking or checking, require correct access
2186
* bit set.
2187
*/
2188
if (((new_stp->ls_flags & NFSLCK_LOCK) &&
2189
!((new_lop->lo_flags >> NFSLCK_LOCKSHIFT) &
2190
mystp->ls_flags & NFSLCK_ACCESSBITS)) ||
2191
((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_READACCESS)) ==
2192
(NFSLCK_CHECK | NFSLCK_READACCESS) &&
2193
!(mystp->ls_flags & NFSLCK_READACCESS) &&
2194
nfsrv_allowreadforwriteopen == 0) ||
2195
((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) ==
2196
(NFSLCK_CHECK | NFSLCK_WRITEACCESS) &&
2197
!(mystp->ls_flags & NFSLCK_WRITEACCESS))) {
2198
if (filestruct_locked != 0) {
2199
/* Roll back local locks. */
2200
NFSUNLOCKSTATE();
2201
if (vnode_unlocked == 0) {
2202
ASSERT_VOP_ELOCKED(vp,
2203
"nfsrv_lockctrl3");
2204
vnode_unlocked = 1;
2205
NFSVOPUNLOCK(vp);
2206
}
2207
nfsrv_locallock_rollback(vp, lfp, p);
2208
NFSLOCKSTATE();
2209
nfsrv_unlocklf(lfp);
2210
}
2211
NFSUNLOCKSTATE();
2212
error = NFSERR_OPENMODE;
2213
goto out;
2214
}
2215
} else
2216
mystp = NULL;
2217
if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) {
2218
/*
2219
* Check for a conflicting deny bit.
2220
*/
2221
LIST_FOREACH(tstp, &lfp->lf_open, ls_file) {
2222
if (tstp != mystp) {
2223
bits = tstp->ls_flags;
2224
bits >>= NFSLCK_SHIFT;
2225
if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) {
2226
KASSERT(vnode_unlocked == 0,
2227
("nfsrv_lockctrl: vnode unlocked1"));
2228
ret = nfsrv_clientconflict(tstp->ls_clp, &haslock,
2229
vp, p);
2230
if (ret == 1) {
2231
/*
2232
* nfsrv_clientconflict unlocks state
2233
* when it returns non-zero.
2234
*/
2235
lckstp = NULL;
2236
goto tryagain;
2237
}
2238
if (ret == 0)
2239
NFSUNLOCKSTATE();
2240
if (ret == 2)
2241
error = NFSERR_PERM;
2242
else
2243
error = NFSERR_OPENMODE;
2244
goto out;
2245
}
2246
}
2247
}
2248
2249
/* We're outta here */
2250
NFSUNLOCKSTATE();
2251
goto out;
2252
}
2253
}
2254
2255
/*
2256
* For setattr, just get rid of all the Delegations for other clients.
2257
*/
2258
if (new_stp->ls_flags & NFSLCK_SETATTR) {
2259
KASSERT(vnode_unlocked == 0,
2260
("nfsrv_lockctrl: vnode unlocked2"));
2261
ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
2262
if (ret) {
2263
/*
2264
* nfsrv_cleandeleg() unlocks state when it
2265
* returns non-zero.
2266
*/
2267
if (ret == -1) {
2268
lckstp = NULL;
2269
goto tryagain;
2270
}
2271
error = ret;
2272
goto out;
2273
}
2274
if (!(new_stp->ls_flags & NFSLCK_CHECK) ||
2275
(LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) &&
2276
LIST_EMPTY(&lfp->lf_deleg))) {
2277
NFSUNLOCKSTATE();
2278
goto out;
2279
}
2280
}
2281
2282
/*
2283
* Check for a conflicting delegation. If one is found, call
2284
* nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2285
* been set yet, it will get the lock. Otherwise, it will recall
2286
* the delegation. Then, we try try again...
2287
* I currently believe the conflict algorithm to be:
2288
* For Lock Ops (Lock/LockT/LockU)
2289
* - there is a conflict iff a different client has a write delegation
2290
* For Reading (Read Op)
2291
* - there is a conflict iff a different client has a write delegation
2292
* (the specialids are always a different client)
2293
* For Writing (Write/Setattr of size)
2294
* - there is a conflict if a different client has any delegation
2295
* - there is a conflict if the same client has a read delegation
2296
* (I don't understand why this isn't allowed, but that seems to be
2297
* the current consensus?)
2298
*/
2299
tstp = LIST_FIRST(&lfp->lf_deleg);
2300
while (tstp != LIST_END(&lfp->lf_deleg)) {
2301
nstp = LIST_NEXT(tstp, ls_file);
2302
if ((((new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK|NFSLCK_TEST))||
2303
((new_stp->ls_flags & NFSLCK_CHECK) &&
2304
(new_lop->lo_flags & NFSLCK_READ))) &&
2305
clp != tstp->ls_clp &&
2306
(tstp->ls_flags & NFSLCK_DELEGWRITE)) ||
2307
((new_stp->ls_flags & NFSLCK_CHECK) &&
2308
(new_lop->lo_flags & NFSLCK_WRITE) &&
2309
(clp != tstp->ls_clp ||
2310
(tstp->ls_flags & NFSLCK_DELEGREAD)))) {
2311
ret = 0;
2312
if (filestruct_locked != 0) {
2313
/* Roll back local locks. */
2314
NFSUNLOCKSTATE();
2315
if (vnode_unlocked == 0) {
2316
ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl4");
2317
NFSVOPUNLOCK(vp);
2318
}
2319
nfsrv_locallock_rollback(vp, lfp, p);
2320
NFSLOCKSTATE();
2321
nfsrv_unlocklf(lfp);
2322
NFSUNLOCKSTATE();
2323
NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2324
vnode_unlocked = 0;
2325
if (VN_IS_DOOMED(vp))
2326
ret = NFSERR_SERVERFAULT;
2327
NFSLOCKSTATE();
2328
}
2329
if (ret == 0)
2330
ret = nfsrv_delegconflict(tstp, &haslock, p, vp);
2331
if (ret) {
2332
/*
2333
* nfsrv_delegconflict unlocks state when it
2334
* returns non-zero, which it always does.
2335
*/
2336
if (other_lop) {
2337
free(other_lop, M_NFSDLOCK);
2338
other_lop = NULL;
2339
}
2340
if (ret == -1) {
2341
lckstp = NULL;
2342
goto tryagain;
2343
}
2344
error = ret;
2345
goto out;
2346
}
2347
/* Never gets here. */
2348
}
2349
tstp = nstp;
2350
}
2351
2352
/*
2353
* Handle the unlock case by calling nfsrv_updatelock().
2354
* (Should I have done some access checking above for unlock? For now,
2355
* just let it happen.)
2356
*/
2357
if (new_stp->ls_flags & NFSLCK_UNLOCK) {
2358
first = new_lop->lo_first;
2359
end = new_lop->lo_end;
2360
nfsrv_updatelock(stp, new_lopp, &other_lop, lfp);
2361
stateidp->seqid = ++(stp->ls_stateid.seqid);
2362
if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2363
stateidp->seqid = stp->ls_stateid.seqid = 1;
2364
stateidp->other[0] = stp->ls_stateid.other[0];
2365
stateidp->other[1] = stp->ls_stateid.other[1];
2366
stateidp->other[2] = stp->ls_stateid.other[2];
2367
if (filestruct_locked != 0) {
2368
NFSUNLOCKSTATE();
2369
if (vnode_unlocked == 0) {
2370
ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl5");
2371
vnode_unlocked = 1;
2372
NFSVOPUNLOCK(vp);
2373
}
2374
/* Update the local locks. */
2375
nfsrv_localunlock(vp, lfp, first, end, p);
2376
NFSLOCKSTATE();
2377
nfsrv_unlocklf(lfp);
2378
}
2379
NFSUNLOCKSTATE();
2380
goto out;
2381
}
2382
2383
/*
2384
* Search for a conflicting lock. A lock conflicts if:
2385
* - the lock range overlaps and
2386
* - at least one lock is a write lock and
2387
* - it is not owned by the same lock owner
2388
*/
2389
if (!delegation) {
2390
LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
2391
if (new_lop->lo_end > lop->lo_first &&
2392
new_lop->lo_first < lop->lo_end &&
2393
(new_lop->lo_flags == NFSLCK_WRITE ||
2394
lop->lo_flags == NFSLCK_WRITE) &&
2395
lckstp != lop->lo_stp &&
2396
(clp != lop->lo_stp->ls_clp ||
2397
lckstp->ls_ownerlen != lop->lo_stp->ls_ownerlen ||
2398
NFSBCMP(lckstp->ls_owner, lop->lo_stp->ls_owner,
2399
lckstp->ls_ownerlen))) {
2400
if (other_lop) {
2401
free(other_lop, M_NFSDLOCK);
2402
other_lop = NULL;
2403
}
2404
if (vnode_unlocked != 0)
2405
ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
2406
NULL, p);
2407
else
2408
ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
2409
vp, p);
2410
if (ret == 1) {
2411
if (filestruct_locked != 0) {
2412
if (vnode_unlocked == 0) {
2413
ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl6");
2414
NFSVOPUNLOCK(vp);
2415
}
2416
/* Roll back local locks. */
2417
nfsrv_locallock_rollback(vp, lfp, p);
2418
NFSLOCKSTATE();
2419
nfsrv_unlocklf(lfp);
2420
NFSUNLOCKSTATE();
2421
NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2422
vnode_unlocked = 0;
2423
if (VN_IS_DOOMED(vp)) {
2424
error = NFSERR_SERVERFAULT;
2425
goto out;
2426
}
2427
}
2428
/*
2429
* nfsrv_clientconflict() unlocks state when it
2430
* returns non-zero.
2431
*/
2432
lckstp = NULL;
2433
goto tryagain;
2434
}
2435
/*
2436
* Found a conflicting lock, so record the conflict and
2437
* return the error.
2438
*/
2439
if (cfp != NULL && ret == 0) {
2440
cfp->cl_clientid.lval[0]=lop->lo_stp->ls_stateid.other[0];
2441
cfp->cl_clientid.lval[1]=lop->lo_stp->ls_stateid.other[1];
2442
cfp->cl_first = lop->lo_first;
2443
cfp->cl_end = lop->lo_end;
2444
cfp->cl_flags = lop->lo_flags;
2445
cfp->cl_ownerlen = lop->lo_stp->ls_ownerlen;
2446
NFSBCOPY(lop->lo_stp->ls_owner, cfp->cl_owner,
2447
cfp->cl_ownerlen);
2448
}
2449
if (ret == 2)
2450
error = NFSERR_PERM;
2451
else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2452
error = NFSERR_RECLAIMCONFLICT;
2453
else if (new_stp->ls_flags & NFSLCK_CHECK)
2454
error = NFSERR_LOCKED;
2455
else
2456
error = NFSERR_DENIED;
2457
if (filestruct_locked != 0 && ret == 0) {
2458
/* Roll back local locks. */
2459
NFSUNLOCKSTATE();
2460
if (vnode_unlocked == 0) {
2461
ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl7");
2462
vnode_unlocked = 1;
2463
NFSVOPUNLOCK(vp);
2464
}
2465
nfsrv_locallock_rollback(vp, lfp, p);
2466
NFSLOCKSTATE();
2467
nfsrv_unlocklf(lfp);
2468
}
2469
if (ret == 0)
2470
NFSUNLOCKSTATE();
2471
goto out;
2472
}
2473
}
2474
}
2475
2476
/*
2477
* We only get here if there was no lock that conflicted.
2478
*/
2479
if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) {
2480
NFSUNLOCKSTATE();
2481
goto out;
2482
}
2483
2484
/*
2485
* We only get here when we are creating or modifying a lock.
2486
* There are two variants:
2487
* - exist_lock_owner where lock_owner exists
2488
* - open_to_lock_owner with new lock_owner
2489
*/
2490
first = new_lop->lo_first;
2491
end = new_lop->lo_end;
2492
lock_flags = new_lop->lo_flags;
2493
if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) {
2494
nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp);
2495
stateidp->seqid = ++(lckstp->ls_stateid.seqid);
2496
if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2497
stateidp->seqid = lckstp->ls_stateid.seqid = 1;
2498
stateidp->other[0] = lckstp->ls_stateid.other[0];
2499
stateidp->other[1] = lckstp->ls_stateid.other[1];
2500
stateidp->other[2] = lckstp->ls_stateid.other[2];
2501
} else {
2502
/*
2503
* The new open_to_lock_owner case.
2504
* Link the new nfsstate into the lists.
2505
*/
2506
new_stp->ls_seq = new_stp->ls_opentolockseq;
2507
nfsrvd_refcache(new_stp->ls_op);
2508
stateidp->seqid = new_stp->ls_stateid.seqid = 1;
2509
stateidp->other[0] = new_stp->ls_stateid.other[0] =
2510
clp->lc_clientid.lval[0];
2511
stateidp->other[1] = new_stp->ls_stateid.other[1] =
2512
clp->lc_clientid.lval[1];
2513
stateidp->other[2] = new_stp->ls_stateid.other[2] =
2514
nfsrv_nextstateindex(clp);
2515
new_stp->ls_clp = clp;
2516
LIST_INIT(&new_stp->ls_lock);
2517
new_stp->ls_openstp = stp;
2518
new_stp->ls_lfp = lfp;
2519
nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp,
2520
lfp);
2521
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid),
2522
new_stp, ls_hash);
2523
LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list);
2524
*new_lopp = NULL;
2525
*new_stpp = NULL;
2526
NFSD_VNET(nfsstatsv1_p)->srvlockowners++;
2527
nfsrv_openpluslock++;
2528
}
2529
if (filestruct_locked != 0) {
2530
NFSUNLOCKSTATE();
2531
nfsrv_locallock_commit(lfp, lock_flags, first, end);
2532
NFSLOCKSTATE();
2533
nfsrv_unlocklf(lfp);
2534
}
2535
NFSUNLOCKSTATE();
2536
2537
out:
2538
if (haslock) {
2539
NFSLOCKV4ROOTMUTEX();
2540
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2541
NFSUNLOCKV4ROOTMUTEX();
2542
}
2543
if (vnode_unlocked != 0) {
2544
NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2545
if (error == 0 && VN_IS_DOOMED(vp))
2546
error = NFSERR_SERVERFAULT;
2547
}
2548
if (other_lop)
2549
free(other_lop, M_NFSDLOCK);
2550
NFSEXITCODE2(error, nd);
2551
return (error);
2552
}
2553
2554
/*
2555
* Check for state errors for Open.
2556
* repstat is passed back out as an error if more critical errors
2557
* are not detected.
2558
*/
2559
int
2560
nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
2561
struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd,
2562
NFSPROC_T *p, int repstat)
2563
{
2564
struct nfsstate *stp, *nstp;
2565
struct nfsclient *clp;
2566
struct nfsstate *ownerstp;
2567
struct nfslockfile *lfp, *new_lfp;
2568
int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0;
2569
2570
if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2571
readonly = 1;
2572
/*
2573
* Check for restart conditions (client and server).
2574
*/
2575
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2576
&new_stp->ls_stateid, 0);
2577
if (error)
2578
goto out;
2579
2580
/*
2581
* Check for state resource limit exceeded.
2582
* Technically this should be SMP protected, but the worst
2583
* case error is "out by one or two" on the count when it
2584
* returns NFSERR_RESOURCE and the limit is just a rather
2585
* arbitrary high water mark, so no harm is done.
2586
*/
2587
if (nfsrv_openpluslock > nfsrv_v4statelimit) {
2588
error = NFSERR_RESOURCE;
2589
goto out;
2590
}
2591
2592
tryagain:
2593
new_lfp = malloc(sizeof (struct nfslockfile),
2594
M_NFSDLOCKFILE, M_WAITOK);
2595
if (vp)
2596
getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2597
NULL, p);
2598
NFSLOCKSTATE();
2599
/*
2600
* Get the nfsclient structure.
2601
*/
2602
error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2603
(nfsquad_t)((u_quad_t)0), 0, nd, p);
2604
2605
/*
2606
* Look up the open owner. See if it needs confirmation and
2607
* check the seq#, as required.
2608
*/
2609
if (!error)
2610
nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2611
2612
if (!error && ownerstp) {
2613
error = nfsrv_checkseqid(nd, new_stp->ls_seq, ownerstp,
2614
new_stp->ls_op);
2615
/*
2616
* If the OpenOwner hasn't been confirmed, assume the
2617
* old one was a replay and this one is ok.
2618
* See: RFC3530 Sec. 14.2.18.
2619
*/
2620
if (error == NFSERR_BADSEQID &&
2621
(ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM))
2622
error = 0;
2623
}
2624
2625
/*
2626
* Check for grace.
2627
*/
2628
if (!error)
2629
error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
2630
if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
2631
nfsrv_checkstable(clp))
2632
error = NFSERR_NOGRACE;
2633
2634
/*
2635
* If none of the above errors occurred, let repstat be
2636
* returned.
2637
*/
2638
if (repstat && !error)
2639
error = repstat;
2640
if (error) {
2641
NFSUNLOCKSTATE();
2642
if (haslock) {
2643
NFSLOCKV4ROOTMUTEX();
2644
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2645
NFSUNLOCKV4ROOTMUTEX();
2646
}
2647
free(new_lfp, M_NFSDLOCKFILE);
2648
goto out;
2649
}
2650
2651
/*
2652
* If vp == NULL, the file doesn't exist yet, so return ok.
2653
* (This always happens on the first pass, so haslock must be 0.)
2654
*/
2655
if (vp == NULL) {
2656
NFSUNLOCKSTATE();
2657
free(new_lfp, M_NFSDLOCKFILE);
2658
goto out;
2659
}
2660
2661
/*
2662
* Get the structure for the underlying file.
2663
*/
2664
if (getfhret)
2665
error = getfhret;
2666
else
2667
error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2668
NULL, 0);
2669
if (new_lfp)
2670
free(new_lfp, M_NFSDLOCKFILE);
2671
if (error) {
2672
NFSUNLOCKSTATE();
2673
if (haslock) {
2674
NFSLOCKV4ROOTMUTEX();
2675
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2676
NFSUNLOCKV4ROOTMUTEX();
2677
}
2678
goto out;
2679
}
2680
2681
/*
2682
* Search for a conflicting open/share.
2683
*/
2684
if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2685
/*
2686
* For Delegate_Cur, search for the matching Delegation,
2687
* which indicates no conflict.
2688
* An old delegation should have been recovered by the
2689
* client doing a Claim_DELEGATE_Prev, so I won't let
2690
* it match and return NFSERR_EXPIRED. Should I let it
2691
* match?
2692
*/
2693
LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2694
if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2695
(((nd->nd_flag & ND_NFSV41) != 0 &&
2696
stateidp->seqid == 0) ||
2697
stateidp->seqid == stp->ls_stateid.seqid) &&
2698
!NFSBCMP(stateidp->other, stp->ls_stateid.other,
2699
NFSX_STATEIDOTHER))
2700
break;
2701
}
2702
if (stp == LIST_END(&lfp->lf_deleg) ||
2703
((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2704
(stp->ls_flags & NFSLCK_DELEGREAD))) {
2705
NFSUNLOCKSTATE();
2706
if (haslock) {
2707
NFSLOCKV4ROOTMUTEX();
2708
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2709
NFSUNLOCKV4ROOTMUTEX();
2710
}
2711
error = NFSERR_EXPIRED;
2712
goto out;
2713
}
2714
}
2715
2716
/*
2717
* Check for access/deny bit conflicts. I check for the same
2718
* owner as well, in case the client didn't bother.
2719
*/
2720
LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2721
if (!(new_stp->ls_flags & NFSLCK_DELEGCUR) &&
2722
(((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2723
((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2724
((stp->ls_flags & NFSLCK_ACCESSBITS) &
2725
((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS)))){
2726
ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2727
if (ret == 1) {
2728
/*
2729
* nfsrv_clientconflict() unlocks
2730
* state when it returns non-zero.
2731
*/
2732
goto tryagain;
2733
}
2734
if (ret == 2)
2735
error = NFSERR_PERM;
2736
else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2737
error = NFSERR_RECLAIMCONFLICT;
2738
else
2739
error = NFSERR_SHAREDENIED;
2740
if (ret == 0)
2741
NFSUNLOCKSTATE();
2742
if (haslock) {
2743
NFSLOCKV4ROOTMUTEX();
2744
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2745
NFSUNLOCKV4ROOTMUTEX();
2746
}
2747
goto out;
2748
}
2749
}
2750
2751
/*
2752
* Check for a conflicting delegation. If one is found, call
2753
* nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2754
* been set yet, it will get the lock. Otherwise, it will recall
2755
* the delegation. Then, we try try again...
2756
* (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2757
* isn't a conflict.)
2758
* I currently believe the conflict algorithm to be:
2759
* For Open with Read Access and Deny None
2760
* - there is a conflict iff a different client has a write delegation
2761
* For Open with other Write Access or any Deny except None
2762
* - there is a conflict if a different client has any delegation
2763
* - there is a conflict if the same client has a read delegation
2764
* (The current consensus is that this last case should be
2765
* considered a conflict since the client with a read delegation
2766
* could have done an Open with ReadAccess and WriteDeny
2767
* locally and then not have checked for the WriteDeny.)
2768
* The exception is a NFSv4.1/4.2 client that has requested
2769
* an atomic upgrade to a write delegation.
2770
* Don't check for a Reclaim, since that will be dealt with
2771
* by nfsrv_openctrl().
2772
*/
2773
if (!(new_stp->ls_flags &
2774
(NFSLCK_DELEGPREV | NFSLCK_DELEGCUR | NFSLCK_RECLAIM))) {
2775
stp = LIST_FIRST(&lfp->lf_deleg);
2776
while (stp != LIST_END(&lfp->lf_deleg)) {
2777
nstp = LIST_NEXT(stp, ls_file);
2778
if ((readonly && stp->ls_clp != clp &&
2779
(stp->ls_flags & NFSLCK_DELEGWRITE) != 0) ||
2780
(!readonly && (stp->ls_clp != clp ||
2781
((stp->ls_flags & NFSLCK_DELEGREAD) != 0 &&
2782
(new_stp->ls_flags & NFSLCK_WANTWDELEG) == 0)))) {
2783
ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2784
if (ret) {
2785
/*
2786
* nfsrv_delegconflict() unlocks state
2787
* when it returns non-zero.
2788
*/
2789
if (ret == -1)
2790
goto tryagain;
2791
error = ret;
2792
goto out;
2793
}
2794
}
2795
stp = nstp;
2796
}
2797
}
2798
NFSUNLOCKSTATE();
2799
if (haslock) {
2800
NFSLOCKV4ROOTMUTEX();
2801
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2802
NFSUNLOCKV4ROOTMUTEX();
2803
}
2804
2805
out:
2806
NFSEXITCODE2(error, nd);
2807
return (error);
2808
}
2809
2810
/*
2811
* Open control function to create/update open state for an open.
2812
*/
2813
int
2814
nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
2815
struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp,
2816
nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp,
2817
NFSPROC_T *p, u_quad_t filerev)
2818
{
2819
struct nfsstate *new_stp = *new_stpp;
2820
struct nfsstate *stp, *nstp;
2821
struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg;
2822
struct nfslockfile *lfp, *new_lfp;
2823
struct nfsclient *clp;
2824
int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1;
2825
int readonly = 0, cbret = 1, getfhret = 0;
2826
int gotstate = 0, len = 0;
2827
u_char *clidp = NULL;
2828
2829
if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2830
readonly = 1;
2831
/*
2832
* Check for restart conditions (client and server).
2833
* (Paranoia, should have been detected by nfsrv_opencheck().)
2834
* If an error does show up, return NFSERR_EXPIRED, since the
2835
* the seqid# has already been incremented.
2836
*/
2837
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2838
&new_stp->ls_stateid, 0);
2839
if (error) {
2840
printf("Nfsd: openctrl unexpected restart err=%d\n",
2841
error);
2842
error = NFSERR_EXPIRED;
2843
goto out;
2844
}
2845
2846
clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
2847
tryagain:
2848
new_lfp = malloc(sizeof (struct nfslockfile),
2849
M_NFSDLOCKFILE, M_WAITOK);
2850
new_open = malloc(sizeof (struct nfsstate),
2851
M_NFSDSTATE, M_WAITOK);
2852
new_deleg = malloc(sizeof (struct nfsstate),
2853
M_NFSDSTATE, M_WAITOK);
2854
getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2855
NULL, p);
2856
NFSLOCKSTATE();
2857
/*
2858
* Get the client structure. Since the linked lists could be changed
2859
* by other nfsd processes if this process does a tsleep(), one of
2860
* two things must be done.
2861
* 1 - don't tsleep()
2862
* or
2863
* 2 - get the nfsv4_lock() { indicated by haslock == 1 }
2864
* before using the lists, since this lock stops the other
2865
* nfsd. This should only be used for rare cases, since it
2866
* essentially single threads the nfsd.
2867
* At this time, it is only done for cases where the stable
2868
* storage file must be written prior to completion of state
2869
* expiration.
2870
*/
2871
error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2872
(nfsquad_t)((u_quad_t)0), 0, nd, p);
2873
if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) &&
2874
clp->lc_program) {
2875
/*
2876
* This happens on the first open for a client
2877
* that supports callbacks.
2878
*/
2879
NFSUNLOCKSTATE();
2880
/*
2881
* Although nfsrv_docallback() will sleep, clp won't
2882
* go away, since they are only removed when the
2883
* nfsv4_lock() has blocked the nfsd threads. The
2884
* fields in clp can change, but having multiple
2885
* threads do this Null callback RPC should be
2886
* harmless.
2887
*/
2888
cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL,
2889
NULL, 0, NULL, NULL, NULL, 0, p);
2890
NFSLOCKSTATE();
2891
clp->lc_flags &= ~LCL_NEEDSCBNULL;
2892
if (!cbret)
2893
clp->lc_flags |= LCL_CALLBACKSON;
2894
}
2895
2896
/*
2897
* Look up the open owner. See if it needs confirmation and
2898
* check the seq#, as required.
2899
*/
2900
if (!error)
2901
nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2902
2903
if (error) {
2904
NFSUNLOCKSTATE();
2905
printf("Nfsd: openctrl unexpected state err=%d\n",
2906
error);
2907
free(new_lfp, M_NFSDLOCKFILE);
2908
free(new_open, M_NFSDSTATE);
2909
free(new_deleg, M_NFSDSTATE);
2910
if (haslock) {
2911
NFSLOCKV4ROOTMUTEX();
2912
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2913
NFSUNLOCKV4ROOTMUTEX();
2914
}
2915
error = NFSERR_EXPIRED;
2916
goto out;
2917
}
2918
2919
if (new_stp->ls_flags & NFSLCK_RECLAIM)
2920
nfsrv_markstable(clp);
2921
2922
/*
2923
* Get the structure for the underlying file.
2924
*/
2925
if (getfhret)
2926
error = getfhret;
2927
else
2928
error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2929
NULL, 0);
2930
if (new_lfp)
2931
free(new_lfp, M_NFSDLOCKFILE);
2932
if (error) {
2933
NFSUNLOCKSTATE();
2934
printf("Nfsd openctrl unexpected getlockfile err=%d\n",
2935
error);
2936
free(new_open, M_NFSDSTATE);
2937
free(new_deleg, M_NFSDSTATE);
2938
if (haslock) {
2939
NFSLOCKV4ROOTMUTEX();
2940
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2941
NFSUNLOCKV4ROOTMUTEX();
2942
}
2943
goto out;
2944
}
2945
2946
/*
2947
* Search for a conflicting open/share.
2948
*/
2949
if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2950
/*
2951
* For Delegate_Cur, search for the matching Delegation,
2952
* which indicates no conflict.
2953
* An old delegation should have been recovered by the
2954
* client doing a Claim_DELEGATE_Prev, so I won't let
2955
* it match and return NFSERR_EXPIRED. Should I let it
2956
* match?
2957
*/
2958
LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2959
if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2960
(((nd->nd_flag & ND_NFSV41) != 0 &&
2961
stateidp->seqid == 0) ||
2962
stateidp->seqid == stp->ls_stateid.seqid) &&
2963
!NFSBCMP(stateidp->other, stp->ls_stateid.other,
2964
NFSX_STATEIDOTHER))
2965
break;
2966
}
2967
if (stp == LIST_END(&lfp->lf_deleg) ||
2968
((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2969
(stp->ls_flags & NFSLCK_DELEGREAD))) {
2970
NFSUNLOCKSTATE();
2971
printf("Nfsd openctrl unexpected expiry\n");
2972
free(new_open, M_NFSDSTATE);
2973
free(new_deleg, M_NFSDSTATE);
2974
if (haslock) {
2975
NFSLOCKV4ROOTMUTEX();
2976
nfsv4_unlock(&nfsv4rootfs_lock, 1);
2977
NFSUNLOCKV4ROOTMUTEX();
2978
}
2979
error = NFSERR_EXPIRED;
2980
goto out;
2981
}
2982
2983
/*
2984
* Don't issue a Delegation, since one already exists and
2985
* delay delegation timeout, as required.
2986
*/
2987
delegate = 0;
2988
nfsrv_delaydelegtimeout(stp);
2989
}
2990
2991
/*
2992
* Check for access/deny bit conflicts. I also check for the
2993
* same owner, since the client might not have bothered to check.
2994
* Also, note an open for the same file and owner, if found,
2995
* which is all we do here for Delegate_Cur, since conflict
2996
* checking is already done.
2997
*/
2998
LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2999
if (ownerstp && stp->ls_openowner == ownerstp)
3000
openstp = stp;
3001
if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) {
3002
/*
3003
* If another client has the file open, the only
3004
* delegation that can be issued is a Read delegation
3005
* and only if it is a Read open with Deny none.
3006
*/
3007
if (clp != stp->ls_clp) {
3008
if ((stp->ls_flags & NFSLCK_SHAREBITS) ==
3009
NFSLCK_READACCESS)
3010
writedeleg = 0;
3011
else
3012
delegate = 0;
3013
}
3014
if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
3015
((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
3016
((stp->ls_flags & NFSLCK_ACCESSBITS) &
3017
((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){
3018
ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
3019
if (ret == 1) {
3020
/*
3021
* nfsrv_clientconflict() unlocks state
3022
* when it returns non-zero.
3023
*/
3024
free(new_open, M_NFSDSTATE);
3025
free(new_deleg, M_NFSDSTATE);
3026
openstp = NULL;
3027
goto tryagain;
3028
}
3029
if (ret == 2)
3030
error = NFSERR_PERM;
3031
else if (new_stp->ls_flags & NFSLCK_RECLAIM)
3032
error = NFSERR_RECLAIMCONFLICT;
3033
else
3034
error = NFSERR_SHAREDENIED;
3035
if (ret == 0)
3036
NFSUNLOCKSTATE();
3037
if (haslock) {
3038
NFSLOCKV4ROOTMUTEX();
3039
nfsv4_unlock(&nfsv4rootfs_lock, 1);
3040
NFSUNLOCKV4ROOTMUTEX();
3041
}
3042
free(new_open, M_NFSDSTATE);
3043
free(new_deleg, M_NFSDSTATE);
3044
printf("nfsd openctrl unexpected client cnfl\n");
3045
goto out;
3046
}
3047
}
3048
}
3049
3050
/*
3051
* Check for a conflicting delegation. If one is found, call
3052
* nfsrv_delegconflict() to handle it. If the v4root lock hasn't
3053
* been set yet, it will get the lock. Otherwise, it will recall
3054
* the delegation. Then, we try try again...
3055
* (If NFSLCK_DELEGCUR is set, it has a delegation, so there
3056
* isn't a conflict.)
3057
* I currently believe the conflict algorithm to be:
3058
* For Open with Read Access and Deny None
3059
* - there is a conflict iff a different client has a write delegation
3060
* For Open with other Write Access or any Deny except None
3061
* - there is a conflict if a different client has any delegation
3062
* - there is a conflict if the same client has a read delegation
3063
* (The current consensus is that this last case should be
3064
* considered a conflict since the client with a read delegation
3065
* could have done an Open with ReadAccess and WriteDeny
3066
* locally and then not have checked for the WriteDeny.)
3067
* The exception is a NFSv4.1/4.2 client that has requested
3068
* an atomic upgrade to a write delegation.
3069
*/
3070
if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) {
3071
stp = LIST_FIRST(&lfp->lf_deleg);
3072
while (stp != LIST_END(&lfp->lf_deleg)) {
3073
nstp = LIST_NEXT(stp, ls_file);
3074
if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD))
3075
writedeleg = 0;
3076
else if (stp->ls_clp != clp ||
3077
(stp->ls_flags & NFSLCK_DELEGWRITE) != 0 ||
3078
(new_stp->ls_flags & NFSLCK_WANTWDELEG) == 0)
3079
delegate = 0;
3080
if ((readonly && stp->ls_clp != clp &&
3081
(stp->ls_flags & NFSLCK_DELEGWRITE) != 0) ||
3082
(!readonly && (stp->ls_clp != clp ||
3083
((stp->ls_flags & NFSLCK_DELEGREAD) != 0 &&
3084
(new_stp->ls_flags & NFSLCK_WANTWDELEG) == 0)))) {
3085
if (new_stp->ls_flags & NFSLCK_RECLAIM) {
3086
delegate = 2;
3087
} else {
3088
ret = nfsrv_delegconflict(stp, &haslock, p, vp);
3089
if (ret) {
3090
/*
3091
* nfsrv_delegconflict() unlocks state
3092
* when it returns non-zero.
3093
*/
3094
printf("Nfsd openctrl unexpected deleg cnfl\n");
3095
free(new_open, M_NFSDSTATE);
3096
free(new_deleg, M_NFSDSTATE);
3097
if (ret == -1) {
3098
openstp = NULL;
3099
goto tryagain;
3100
}
3101
error = ret;
3102
goto out;
3103
}
3104
}
3105
}
3106
stp = nstp;
3107
}
3108
}
3109
3110
/*
3111
* We only get here if there was no open that conflicted.
3112
* If an open for the owner exists, or in the access/deny bits.
3113
* Otherwise it is a new open. If the open_owner hasn't been
3114
* confirmed, replace the open with the new one needing confirmation,
3115
* otherwise add the open.
3116
*/
3117
if (new_stp->ls_flags & NFSLCK_DELEGPREV) {
3118
/*
3119
* Handle NFSLCK_DELEGPREV by searching the old delegations for
3120
* a match. If found, just move the old delegation to the current
3121
* delegation list and issue open. If not found, return
3122
* NFSERR_EXPIRED.
3123
*/
3124
LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) {
3125
if (stp->ls_lfp == lfp) {
3126
/* Found it */
3127
if (stp->ls_clp != clp)
3128
panic("olddeleg clp");
3129
LIST_REMOVE(stp, ls_list);
3130
LIST_REMOVE(stp, ls_hash);
3131
stp->ls_flags &= ~NFSLCK_OLDDELEG;
3132
stp->ls_stateid.seqid = delegstateidp->seqid = 1;
3133
stp->ls_stateid.other[0] = delegstateidp->other[0] =
3134
clp->lc_clientid.lval[0];
3135
stp->ls_stateid.other[1] = delegstateidp->other[1] =
3136
clp->lc_clientid.lval[1];
3137
stp->ls_stateid.other[2] = delegstateidp->other[2] =
3138
nfsrv_nextstateindex(clp);
3139
stp->ls_compref = nd->nd_compref;
3140
LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list);
3141
LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3142
stp->ls_stateid), stp, ls_hash);
3143
if (stp->ls_flags & NFSLCK_DELEGWRITE)
3144
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3145
else
3146
*rflagsp |= NFSV4OPEN_READDELEGATE;
3147
clp->lc_delegtime = NFSD_MONOSEC +
3148
nfsrv_lease + NFSRV_LEASEDELTA;
3149
3150
/*
3151
* Now, do the associated open.
3152
*/
3153
new_open->ls_stateid.seqid = 1;
3154
new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3155
new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3156
new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3157
new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)|
3158
NFSLCK_OPEN;
3159
if (stp->ls_flags & NFSLCK_DELEGWRITE)
3160
new_open->ls_flags |= (NFSLCK_READACCESS |
3161
NFSLCK_WRITEACCESS);
3162
else
3163
new_open->ls_flags |= NFSLCK_READACCESS;
3164
new_open->ls_uid = new_stp->ls_uid;
3165
new_open->ls_lfp = lfp;
3166
new_open->ls_clp = clp;
3167
LIST_INIT(&new_open->ls_open);
3168
LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3169
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3170
new_open, ls_hash);
3171
/*
3172
* and handle the open owner
3173
*/
3174
if (ownerstp) {
3175
new_open->ls_openowner = ownerstp;
3176
LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list);
3177
} else {
3178
new_open->ls_openowner = new_stp;
3179
new_stp->ls_flags = 0;
3180
nfsrvd_refcache(new_stp->ls_op);
3181
new_stp->ls_noopens = 0;
3182
LIST_INIT(&new_stp->ls_open);
3183
LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3184
LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3185
*new_stpp = NULL;
3186
NFSD_VNET(nfsstatsv1_p)->srvopenowners++;
3187
nfsrv_openpluslock++;
3188
}
3189
openstp = new_open;
3190
new_open = NULL;
3191
NFSD_VNET(nfsstatsv1_p)->srvopens++;
3192
nfsrv_openpluslock++;
3193
break;
3194
}
3195
}
3196
if (stp == LIST_END(&clp->lc_olddeleg))
3197
error = NFSERR_EXPIRED;
3198
} else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
3199
/*
3200
* Scan to see that no delegation for this client and file
3201
* doesn't already exist.
3202
* There also shouldn't yet be an Open for this file and
3203
* openowner.
3204
*/
3205
LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
3206
if (stp->ls_clp == clp)
3207
break;
3208
}
3209
if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) {
3210
/*
3211
* This is the Claim_Previous case with a delegation
3212
* type != Delegate_None.
3213
*/
3214
/*
3215
* First, add the delegation. (Although we must issue the
3216
* delegation, we can also ask for an immediate return.)
3217
*/
3218
new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
3219
new_deleg->ls_stateid.other[0] = delegstateidp->other[0] =
3220
clp->lc_clientid.lval[0];
3221
new_deleg->ls_stateid.other[1] = delegstateidp->other[1] =
3222
clp->lc_clientid.lval[1];
3223
new_deleg->ls_stateid.other[2] = delegstateidp->other[2] =
3224
nfsrv_nextstateindex(clp);
3225
if (new_stp->ls_flags & NFSLCK_DELEGWRITE) {
3226
new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
3227
NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
3228
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3229
nfsrv_writedelegcnt++;
3230
} else {
3231
new_deleg->ls_flags = (NFSLCK_DELEGREAD |
3232
NFSLCK_READACCESS);
3233
*rflagsp |= NFSV4OPEN_READDELEGATE;
3234
}
3235
new_deleg->ls_uid = new_stp->ls_uid;
3236
new_deleg->ls_lfp = lfp;
3237
new_deleg->ls_clp = clp;
3238
new_deleg->ls_filerev = filerev;
3239
new_deleg->ls_compref = nd->nd_compref;
3240
new_deleg->ls_lastrecall = 0;
3241
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
3242
LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3243
new_deleg->ls_stateid), new_deleg, ls_hash);
3244
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
3245
new_deleg = NULL;
3246
if (delegate == 2 || nfsrv_issuedelegs == 0 ||
3247
(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3248
LCL_CALLBACKSON ||
3249
NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) ||
3250
!NFSVNO_DELEGOK(vp))
3251
*rflagsp |= NFSV4OPEN_RECALL;
3252
NFSD_VNET(nfsstatsv1_p)->srvdelegates++;
3253
nfsrv_openpluslock++;
3254
nfsrv_delegatecnt++;
3255
3256
/*
3257
* Now, do the associated open.
3258
*/
3259
new_open->ls_stateid.seqid = 1;
3260
new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3261
new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3262
new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3263
new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) |
3264
NFSLCK_OPEN;
3265
if (new_stp->ls_flags & NFSLCK_DELEGWRITE)
3266
new_open->ls_flags |= (NFSLCK_READACCESS |
3267
NFSLCK_WRITEACCESS);
3268
else
3269
new_open->ls_flags |= NFSLCK_READACCESS;
3270
new_open->ls_uid = new_stp->ls_uid;
3271
new_open->ls_lfp = lfp;
3272
new_open->ls_clp = clp;
3273
LIST_INIT(&new_open->ls_open);
3274
LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3275
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3276
new_open, ls_hash);
3277
/*
3278
* and handle the open owner
3279
*/
3280
if (ownerstp) {
3281
new_open->ls_openowner = ownerstp;
3282
LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
3283
} else {
3284
new_open->ls_openowner = new_stp;
3285
new_stp->ls_flags = 0;
3286
nfsrvd_refcache(new_stp->ls_op);
3287
new_stp->ls_noopens = 0;
3288
LIST_INIT(&new_stp->ls_open);
3289
LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3290
LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3291
*new_stpp = NULL;
3292
NFSD_VNET(nfsstatsv1_p)->srvopenowners++;
3293
nfsrv_openpluslock++;
3294
}
3295
openstp = new_open;
3296
new_open = NULL;
3297
NFSD_VNET(nfsstatsv1_p)->srvopens++;
3298
nfsrv_openpluslock++;
3299
} else {
3300
error = NFSERR_RECLAIMCONFLICT;
3301
}
3302
} else if (ownerstp) {
3303
if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) {
3304
/* Replace the open */
3305
if (ownerstp->ls_op)
3306
nfsrvd_derefcache(ownerstp->ls_op);
3307
ownerstp->ls_op = new_stp->ls_op;
3308
nfsrvd_refcache(ownerstp->ls_op);
3309
ownerstp->ls_seq = new_stp->ls_seq;
3310
*rflagsp |= NFSV4OPEN_RESULTCONFIRM;
3311
stp = LIST_FIRST(&ownerstp->ls_open);
3312
stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
3313
NFSLCK_OPEN;
3314
stp->ls_stateid.seqid = 1;
3315
stp->ls_uid = new_stp->ls_uid;
3316
if (lfp != stp->ls_lfp) {
3317
LIST_REMOVE(stp, ls_file);
3318
LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file);
3319
stp->ls_lfp = lfp;
3320
}
3321
openstp = stp;
3322
} else if (openstp) {
3323
openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS);
3324
openstp->ls_stateid.seqid++;
3325
if ((nd->nd_flag & ND_NFSV41) != 0 &&
3326
openstp->ls_stateid.seqid == 0)
3327
openstp->ls_stateid.seqid = 1;
3328
3329
/*
3330
* This is where we can choose to issue a delegation.
3331
*/
3332
nfsrv_issuedelegation(vp, clp, nd, delegate, writedeleg,
3333
readonly, filerev, NFSVNO_EXRDONLY(exp), &new_deleg,
3334
new_stp, lfp, rflagsp, delegstateidp);
3335
} else {
3336
new_open->ls_stateid.seqid = 1;
3337
new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3338
new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3339
new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3340
new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)|
3341
NFSLCK_OPEN;
3342
new_open->ls_uid = new_stp->ls_uid;
3343
new_open->ls_openowner = ownerstp;
3344
new_open->ls_lfp = lfp;
3345
new_open->ls_clp = clp;
3346
LIST_INIT(&new_open->ls_open);
3347
LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3348
LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
3349
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3350
new_open, ls_hash);
3351
openstp = new_open;
3352
new_open = NULL;
3353
NFSD_VNET(nfsstatsv1_p)->srvopens++;
3354
nfsrv_openpluslock++;
3355
3356
/*
3357
* This is where we can choose to issue a delegation.
3358
*/
3359
nfsrv_issuedelegation(vp, clp, nd, delegate, writedeleg,
3360
readonly, filerev, NFSVNO_EXRDONLY(exp), &new_deleg,
3361
new_stp, lfp, rflagsp, delegstateidp);
3362
}
3363
} else {
3364
/*
3365
* New owner case. Start the open_owner sequence with a
3366
* Needs confirmation (unless a reclaim) and hang the
3367
* new open off it.
3368
*/
3369
new_open->ls_stateid.seqid = 1;
3370
new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3371
new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3372
new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3373
new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
3374
NFSLCK_OPEN;
3375
new_open->ls_uid = new_stp->ls_uid;
3376
LIST_INIT(&new_open->ls_open);
3377
new_open->ls_openowner = new_stp;
3378
new_open->ls_lfp = lfp;
3379
new_open->ls_clp = clp;
3380
LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3381
if (new_stp->ls_flags & NFSLCK_RECLAIM) {
3382
new_stp->ls_flags = 0;
3383
} else if ((nd->nd_flag & ND_NFSV41) != 0) {
3384
/*
3385
* This is where we can choose to issue a delegation.
3386
*/
3387
nfsrv_issuedelegation(vp, clp, nd, delegate, writedeleg,
3388
readonly, filerev, NFSVNO_EXRDONLY(exp), &new_deleg,
3389
new_stp, lfp, rflagsp, delegstateidp);
3390
/* NFSv4.1 never needs confirmation. */
3391
new_stp->ls_flags = 0;
3392
3393
/*
3394
* Since NFSv4.1 never does an OpenConfirm, the first
3395
* open state will be acquired here.
3396
*/
3397
if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3398
clp->lc_flags |= LCL_STAMPEDSTABLE;
3399
len = clp->lc_idlen;
3400
NFSBCOPY(clp->lc_id, clidp, len);
3401
gotstate = 1;
3402
}
3403
} else {
3404
*rflagsp |= NFSV4OPEN_RESULTCONFIRM;
3405
new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
3406
}
3407
nfsrvd_refcache(new_stp->ls_op);
3408
new_stp->ls_noopens = 0;
3409
LIST_INIT(&new_stp->ls_open);
3410
LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3411
LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3412
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3413
new_open, ls_hash);
3414
openstp = new_open;
3415
new_open = NULL;
3416
*new_stpp = NULL;
3417
NFSD_VNET(nfsstatsv1_p)->srvopens++;
3418
nfsrv_openpluslock++;
3419
NFSD_VNET(nfsstatsv1_p)->srvopenowners++;
3420
nfsrv_openpluslock++;
3421
}
3422
if (!error) {
3423
stateidp->seqid = openstp->ls_stateid.seqid;
3424
stateidp->other[0] = openstp->ls_stateid.other[0];
3425
stateidp->other[1] = openstp->ls_stateid.other[1];
3426
stateidp->other[2] = openstp->ls_stateid.other[2];
3427
}
3428
NFSUNLOCKSTATE();
3429
if (haslock) {
3430
NFSLOCKV4ROOTMUTEX();
3431
nfsv4_unlock(&nfsv4rootfs_lock, 1);
3432
NFSUNLOCKV4ROOTMUTEX();
3433
}
3434
if (new_open)
3435
free(new_open, M_NFSDSTATE);
3436
if (new_deleg)
3437
free(new_deleg, M_NFSDSTATE);
3438
3439
/*
3440
* If the NFSv4.1 client just acquired its first open, write a timestamp
3441
* to the stable storage file.
3442
*/
3443
if (gotstate != 0) {
3444
nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
3445
nfsrv_backupstable();
3446
}
3447
3448
out:
3449
free(clidp, M_TEMP);
3450
NFSEXITCODE2(error, nd);
3451
return (error);
3452
}
3453
3454
/*
3455
* Open update. Does the confirm, downgrade and close.
3456
*/
3457
int
3458
nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
3459
nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p,
3460
int *retwriteaccessp)
3461
{
3462
struct nfsstate *stp;
3463
struct nfsclient *clp;
3464
u_int32_t bits;
3465
int error = 0, gotstate = 0, len = 0;
3466
u_char *clidp = NULL;
3467
3468
/*
3469
* Check for restart conditions (client and server).
3470
*/
3471
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3472
&new_stp->ls_stateid, 0);
3473
if (error)
3474
goto out;
3475
3476
clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
3477
NFSLOCKSTATE();
3478
/*
3479
* Get the open structure via clientid and stateid.
3480
*/
3481
error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3482
(nfsquad_t)((u_quad_t)0), 0, nd, p);
3483
if (!error)
3484
error = nfsrv_getstate(clp, &new_stp->ls_stateid,
3485
new_stp->ls_flags, &stp);
3486
3487
/*
3488
* Sanity check the open.
3489
*/
3490
if (!error && (!(stp->ls_flags & NFSLCK_OPEN) ||
3491
(!(new_stp->ls_flags & NFSLCK_CONFIRM) &&
3492
(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) ||
3493
((new_stp->ls_flags & NFSLCK_CONFIRM) &&
3494
(!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)))))
3495
error = NFSERR_BADSTATEID;
3496
3497
if (!error)
3498
error = nfsrv_checkseqid(nd, new_stp->ls_seq,
3499
stp->ls_openowner, new_stp->ls_op);
3500
if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid &&
3501
(((nd->nd_flag & ND_NFSV41) == 0 &&
3502
!(new_stp->ls_flags & NFSLCK_CONFIRM)) ||
3503
((nd->nd_flag & ND_NFSV41) != 0 &&
3504
new_stp->ls_stateid.seqid != 0)))
3505
error = NFSERR_OLDSTATEID;
3506
if (!error && vp->v_type != VREG) {
3507
if (vp->v_type == VDIR)
3508
error = NFSERR_ISDIR;
3509
else
3510
error = NFSERR_INVAL;
3511
}
3512
3513
if (error) {
3514
/*
3515
* If a client tries to confirm an Open with a bad
3516
* seqid# and there are no byte range locks or other Opens
3517
* on the openowner, just throw it away, so the next use of the
3518
* openowner will start a fresh seq#.
3519
*/
3520
if (error == NFSERR_BADSEQID &&
3521
(new_stp->ls_flags & NFSLCK_CONFIRM) &&
3522
nfsrv_nootherstate(stp))
3523
nfsrv_freeopenowner(stp->ls_openowner, 0, p);
3524
NFSUNLOCKSTATE();
3525
goto out;
3526
}
3527
3528
/*
3529
* Set the return stateid.
3530
*/
3531
stateidp->seqid = stp->ls_stateid.seqid + 1;
3532
if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
3533
stateidp->seqid = 1;
3534
stateidp->other[0] = stp->ls_stateid.other[0];
3535
stateidp->other[1] = stp->ls_stateid.other[1];
3536
stateidp->other[2] = stp->ls_stateid.other[2];
3537
/*
3538
* Now, handle the three cases.
3539
*/
3540
if (new_stp->ls_flags & NFSLCK_CONFIRM) {
3541
/*
3542
* If the open doesn't need confirmation, it seems to me that
3543
* there is a client error, but I'll just log it and keep going?
3544
*/
3545
if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))
3546
printf("Nfsv4d: stray open confirm\n");
3547
stp->ls_openowner->ls_flags = 0;
3548
stp->ls_stateid.seqid++;
3549
if ((nd->nd_flag & ND_NFSV41) != 0 &&
3550
stp->ls_stateid.seqid == 0)
3551
stp->ls_stateid.seqid = 1;
3552
if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3553
clp->lc_flags |= LCL_STAMPEDSTABLE;
3554
len = clp->lc_idlen;
3555
NFSBCOPY(clp->lc_id, clidp, len);
3556
gotstate = 1;
3557
}
3558
} else if (new_stp->ls_flags & NFSLCK_CLOSE) {
3559
if (retwriteaccessp != NULL) {
3560
if ((stp->ls_flags & NFSLCK_WRITEACCESS) != 0)
3561
*retwriteaccessp = 1;
3562
else
3563
*retwriteaccessp = 0;
3564
}
3565
if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) {
3566
ASSERT_VOP_ELOCKED(vp, "nfsrv_openupdate");
3567
nfsrv_freeopen(stp, vp, 1, p);
3568
} else {
3569
nfsrv_freeopen(stp, NULL, 0, p);
3570
}
3571
} else {
3572
/*
3573
* Update the share bits, making sure that the new set are a
3574
* subset of the old ones.
3575
*/
3576
bits = (new_stp->ls_flags & NFSLCK_SHAREBITS);
3577
if (~(stp->ls_flags) & bits) {
3578
NFSUNLOCKSTATE();
3579
error = NFSERR_INVAL;
3580
goto out;
3581
}
3582
stp->ls_flags = (bits | NFSLCK_OPEN);
3583
stp->ls_stateid.seqid++;
3584
if ((nd->nd_flag & ND_NFSV41) != 0 &&
3585
stp->ls_stateid.seqid == 0)
3586
stp->ls_stateid.seqid = 1;
3587
}
3588
NFSUNLOCKSTATE();
3589
3590
/*
3591
* If the client just confirmed its first open, write a timestamp
3592
* to the stable storage file.
3593
*/
3594
if (gotstate != 0) {
3595
nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
3596
nfsrv_backupstable();
3597
}
3598
3599
out:
3600
free(clidp, M_TEMP);
3601
NFSEXITCODE2(error, nd);
3602
return (error);
3603
}
3604
3605
/*
3606
* Delegation update. Does the purge and return.
3607
*/
3608
int
3609
nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid,
3610
nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred,
3611
NFSPROC_T *p, int *retwriteaccessp)
3612
{
3613
struct nfsstate *stp;
3614
struct nfsclient *clp;
3615
int error = 0;
3616
fhandle_t fh;
3617
3618
/*
3619
* Do a sanity check against the file handle for DelegReturn.
3620
*/
3621
if (vp) {
3622
error = nfsvno_getfh(vp, &fh, p);
3623
if (error)
3624
goto out;
3625
}
3626
/*
3627
* Check for restart conditions (client and server).
3628
*/
3629
if (op == NFSV4OP_DELEGRETURN)
3630
error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN,
3631
stateidp, 0);
3632
else
3633
error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE,
3634
stateidp, 0);
3635
3636
NFSLOCKSTATE();
3637
/*
3638
* Get the open structure via clientid and stateid.
3639
*/
3640
if (!error)
3641
error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3642
(nfsquad_t)((u_quad_t)0), 0, nd, p);
3643
if (error) {
3644
if (error == NFSERR_CBPATHDOWN)
3645
error = 0;
3646
if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN)
3647
error = NFSERR_STALESTATEID;
3648
}
3649
if (!error && op == NFSV4OP_DELEGRETURN) {
3650
error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp);
3651
if (!error && stp->ls_stateid.seqid != stateidp->seqid &&
3652
((nd->nd_flag & ND_NFSV41) == 0 || stateidp->seqid != 0))
3653
error = NFSERR_OLDSTATEID;
3654
}
3655
/*
3656
* NFSERR_EXPIRED means that the state has gone away,
3657
* so Delegations have been purged. Just return ok.
3658
*/
3659
if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) {
3660
NFSUNLOCKSTATE();
3661
error = 0;
3662
goto out;
3663
}
3664
if (error) {
3665
NFSUNLOCKSTATE();
3666
goto out;
3667
}
3668
3669
if (op == NFSV4OP_DELEGRETURN) {
3670
if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh,
3671
sizeof (fhandle_t))) {
3672
NFSUNLOCKSTATE();
3673
error = NFSERR_BADSTATEID;
3674
goto out;
3675
}
3676
if (retwriteaccessp != NULL) {
3677
if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0)
3678
*retwriteaccessp = 1;
3679
else
3680
*retwriteaccessp = 0;
3681
}
3682
nfsrv_freedeleg(stp);
3683
} else {
3684
nfsrv_freedeleglist(&clp->lc_olddeleg);
3685
}
3686
NFSUNLOCKSTATE();
3687
error = 0;
3688
3689
out:
3690
NFSEXITCODE(error);
3691
return (error);
3692
}
3693
3694
/*
3695
* Release lock owner.
3696
*/
3697
int
3698
nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
3699
NFSPROC_T *p)
3700
{
3701
struct nfsstate *stp, *nstp, *openstp, *ownstp;
3702
struct nfsclient *clp;
3703
int error = 0;
3704
3705
/*
3706
* Check for restart conditions (client and server).
3707
*/
3708
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3709
&new_stp->ls_stateid, 0);
3710
if (error)
3711
goto out;
3712
3713
NFSLOCKSTATE();
3714
/*
3715
* Get the lock owner by name.
3716
*/
3717
error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3718
(nfsquad_t)((u_quad_t)0), 0, NULL, p);
3719
if (error) {
3720
NFSUNLOCKSTATE();
3721
goto out;
3722
}
3723
LIST_FOREACH(ownstp, &clp->lc_open, ls_list) {
3724
LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) {
3725
stp = LIST_FIRST(&openstp->ls_open);
3726
while (stp != LIST_END(&openstp->ls_open)) {
3727
nstp = LIST_NEXT(stp, ls_list);
3728
/*
3729
* If the owner matches, check for locks and
3730
* then free or return an error.
3731
*/
3732
if (stp->ls_ownerlen == new_stp->ls_ownerlen &&
3733
!NFSBCMP(stp->ls_owner, new_stp->ls_owner,
3734
stp->ls_ownerlen)){
3735
if (LIST_EMPTY(&stp->ls_lock)) {
3736
nfsrv_freelockowner(stp, NULL, 0, p);
3737
} else {
3738
NFSUNLOCKSTATE();
3739
error = NFSERR_LOCKSHELD;
3740
goto out;
3741
}
3742
}
3743
stp = nstp;
3744
}
3745
}
3746
}
3747
NFSUNLOCKSTATE();
3748
3749
out:
3750
NFSEXITCODE(error);
3751
return (error);
3752
}
3753
3754
/*
3755
* Get the file handle for a lock structure.
3756
*/
3757
static int
3758
nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile *new_lfp,
3759
fhandle_t *nfhp, NFSPROC_T *p)
3760
{
3761
fhandle_t *fhp = NULL;
3762
int error;
3763
3764
/*
3765
* For lock, use the new nfslock structure, otherwise just
3766
* a fhandle_t on the stack.
3767
*/
3768
if (flags & NFSLCK_OPEN) {
3769
KASSERT(new_lfp != NULL, ("nfsrv_getlockfh: new_lfp NULL"));
3770
fhp = &new_lfp->lf_fh;
3771
} else if (nfhp) {
3772
fhp = nfhp;
3773
} else {
3774
panic("nfsrv_getlockfh");
3775
}
3776
error = nfsvno_getfh(vp, fhp, p);
3777
NFSEXITCODE(error);
3778
return (error);
3779
}
3780
3781
/*
3782
* Get an nfs lock structure. Allocate one, as required, and return a
3783
* pointer to it.
3784
* Returns an NFSERR_xxx upon failure or -1 to indicate no current lock.
3785
*/
3786
static int
3787
nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp,
3788
struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit)
3789
{
3790
struct nfslockfile *lfp;
3791
fhandle_t *fhp = NULL, *tfhp;
3792
struct nfslockhashhead *hp;
3793
struct nfslockfile *new_lfp = NULL;
3794
3795
/*
3796
* For lock, use the new nfslock structure, otherwise just
3797
* a fhandle_t on the stack.
3798
*/
3799
if (flags & NFSLCK_OPEN) {
3800
new_lfp = *new_lfpp;
3801
fhp = &new_lfp->lf_fh;
3802
} else if (nfhp) {
3803
fhp = nfhp;
3804
} else {
3805
panic("nfsrv_getlockfile");
3806
}
3807
3808
hp = NFSLOCKHASH(fhp);
3809
LIST_FOREACH(lfp, hp, lf_hash) {
3810
tfhp = &lfp->lf_fh;
3811
if (NFSVNO_CMPFH(fhp, tfhp)) {
3812
if (lockit)
3813
nfsrv_locklf(lfp);
3814
*lfpp = lfp;
3815
return (0);
3816
}
3817
}
3818
if (!(flags & NFSLCK_OPEN))
3819
return (-1);
3820
3821
/*
3822
* No match, so chain the new one into the list.
3823
*/
3824
LIST_INIT(&new_lfp->lf_open);
3825
LIST_INIT(&new_lfp->lf_lock);
3826
LIST_INIT(&new_lfp->lf_deleg);
3827
LIST_INIT(&new_lfp->lf_locallock);
3828
LIST_INIT(&new_lfp->lf_rollback);
3829
new_lfp->lf_locallock_lck.nfslock_usecnt = 0;
3830
new_lfp->lf_locallock_lck.nfslock_lock = 0;
3831
new_lfp->lf_usecount = 0;
3832
LIST_INSERT_HEAD(hp, new_lfp, lf_hash);
3833
*lfpp = new_lfp;
3834
*new_lfpp = NULL;
3835
return (0);
3836
}
3837
3838
/*
3839
* This function adds a nfslock lock structure to the list for the associated
3840
* nfsstate and nfslockfile structures. It will be inserted after the
3841
* entry pointed at by insert_lop.
3842
*/
3843
static void
3844
nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop,
3845
struct nfsstate *stp, struct nfslockfile *lfp)
3846
{
3847
struct nfslock *lop, *nlop;
3848
3849
new_lop->lo_stp = stp;
3850
new_lop->lo_lfp = lfp;
3851
3852
if (stp != NULL) {
3853
/* Insert in increasing lo_first order */
3854
lop = LIST_FIRST(&lfp->lf_lock);
3855
if (lop == LIST_END(&lfp->lf_lock) ||
3856
new_lop->lo_first <= lop->lo_first) {
3857
LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile);
3858
} else {
3859
nlop = LIST_NEXT(lop, lo_lckfile);
3860
while (nlop != LIST_END(&lfp->lf_lock) &&
3861
nlop->lo_first < new_lop->lo_first) {
3862
lop = nlop;
3863
nlop = LIST_NEXT(lop, lo_lckfile);
3864
}
3865
LIST_INSERT_AFTER(lop, new_lop, lo_lckfile);
3866
}
3867
} else {
3868
new_lop->lo_lckfile.le_prev = NULL; /* list not used */
3869
}
3870
3871
/*
3872
* Insert after insert_lop, which is overloaded as stp or lfp for
3873
* an empty list.
3874
*/
3875
if (stp == NULL && (struct nfslockfile *)insert_lop == lfp)
3876
LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner);
3877
else if ((struct nfsstate *)insert_lop == stp)
3878
LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner);
3879
else
3880
LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner);
3881
if (stp != NULL) {
3882
NFSD_VNET(nfsstatsv1_p)->srvlocks++;
3883
nfsrv_openpluslock++;
3884
}
3885
}
3886
3887
/*
3888
* This function updates the locking for a lock owner and given file. It
3889
* maintains a list of lock ranges ordered on increasing file offset that
3890
* are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style).
3891
* It always adds new_lop to the list and sometimes uses the one pointed
3892
* at by other_lopp.
3893
*/
3894
static void
3895
nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp,
3896
struct nfslock **other_lopp, struct nfslockfile *lfp)
3897
{
3898
struct nfslock *new_lop = *new_lopp;
3899
struct nfslock *lop, *tlop, *ilop;
3900
struct nfslock *other_lop = *other_lopp;
3901
int unlock = 0, myfile = 0;
3902
u_int64_t tmp;
3903
3904
/*
3905
* Work down the list until the lock is merged.
3906
*/
3907
if (new_lop->lo_flags & NFSLCK_UNLOCK)
3908
unlock = 1;
3909
if (stp != NULL) {
3910
ilop = (struct nfslock *)stp;
3911
lop = LIST_FIRST(&stp->ls_lock);
3912
} else {
3913
ilop = (struct nfslock *)lfp;
3914
lop = LIST_FIRST(&lfp->lf_locallock);
3915
}
3916
while (lop != NULL) {
3917
/*
3918
* Only check locks for this file that aren't before the start of
3919
* new lock's range.
3920
*/
3921
if (lop->lo_lfp == lfp) {
3922
myfile = 1;
3923
if (lop->lo_end >= new_lop->lo_first) {
3924
if (new_lop->lo_end < lop->lo_first) {
3925
/*
3926
* If the new lock ends before the start of the
3927
* current lock's range, no merge, just insert
3928
* the new lock.
3929
*/
3930
break;
3931
}
3932
if (new_lop->lo_flags == lop->lo_flags ||
3933
(new_lop->lo_first <= lop->lo_first &&
3934
new_lop->lo_end >= lop->lo_end)) {
3935
/*
3936
* This lock can be absorbed by the new lock/unlock.
3937
* This happens when it covers the entire range
3938
* of the old lock or is contiguous
3939
* with the old lock and is of the same type or an
3940
* unlock.
3941
*/
3942
if (lop->lo_first < new_lop->lo_first)
3943
new_lop->lo_first = lop->lo_first;
3944
if (lop->lo_end > new_lop->lo_end)
3945
new_lop->lo_end = lop->lo_end;
3946
tlop = lop;
3947
lop = LIST_NEXT(lop, lo_lckowner);
3948
nfsrv_freenfslock(tlop);
3949
continue;
3950
}
3951
3952
/*
3953
* All these cases are for contiguous locks that are not the
3954
* same type, so they can't be merged.
3955
*/
3956
if (new_lop->lo_first <= lop->lo_first) {
3957
/*
3958
* This case is where the new lock overlaps with the
3959
* first part of the old lock. Move the start of the
3960
* old lock to just past the end of the new lock. The
3961
* new lock will be inserted in front of the old, since
3962
* ilop hasn't been updated. (We are done now.)
3963
*/
3964
lop->lo_first = new_lop->lo_end;
3965
break;
3966
}
3967
if (new_lop->lo_end >= lop->lo_end) {
3968
/*
3969
* This case is where the new lock overlaps with the
3970
* end of the old lock's range. Move the old lock's
3971
* end to just before the new lock's first and insert
3972
* the new lock after the old lock.
3973
* Might not be done yet, since the new lock could
3974
* overlap further locks with higher ranges.
3975
*/
3976
lop->lo_end = new_lop->lo_first;
3977
ilop = lop;
3978
lop = LIST_NEXT(lop, lo_lckowner);
3979
continue;
3980
}
3981
/*
3982
* The final case is where the new lock's range is in the
3983
* middle of the current lock's and splits the current lock
3984
* up. Use *other_lopp to handle the second part of the
3985
* split old lock range. (We are done now.)
3986
* For unlock, we use new_lop as other_lop and tmp, since
3987
* other_lop and new_lop are the same for this case.
3988
* We noted the unlock case above, so we don't need
3989
* new_lop->lo_flags any longer.
3990
*/
3991
tmp = new_lop->lo_first;
3992
if (other_lop == NULL) {
3993
if (!unlock)
3994
panic("nfsd srv update unlock");
3995
other_lop = new_lop;
3996
*new_lopp = NULL;
3997
}
3998
other_lop->lo_first = new_lop->lo_end;
3999
other_lop->lo_end = lop->lo_end;
4000
other_lop->lo_flags = lop->lo_flags;
4001
other_lop->lo_stp = stp;
4002
other_lop->lo_lfp = lfp;
4003
lop->lo_end = tmp;
4004
nfsrv_insertlock(other_lop, lop, stp, lfp);
4005
*other_lopp = NULL;
4006
ilop = lop;
4007
break;
4008
}
4009
}
4010
ilop = lop;
4011
lop = LIST_NEXT(lop, lo_lckowner);
4012
if (myfile && (lop == NULL || lop->lo_lfp != lfp))
4013
break;
4014
}
4015
4016
/*
4017
* Insert the new lock in the list at the appropriate place.
4018
*/
4019
if (!unlock) {
4020
nfsrv_insertlock(new_lop, ilop, stp, lfp);
4021
*new_lopp = NULL;
4022
}
4023
}
4024
4025
/*
4026
* This function handles sequencing of locks, etc.
4027
* It returns an error that indicates what the caller should do.
4028
*/
4029
static int
4030
nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
4031
struct nfsstate *stp, struct nfsrvcache *op)
4032
{
4033
int error = 0;
4034
4035
if ((nd->nd_flag & ND_NFSV41) != 0)
4036
/* NFSv4.1 ignores the open_seqid and lock_seqid. */
4037
goto out;
4038
if (op != nd->nd_rp)
4039
panic("nfsrvstate checkseqid");
4040
if (!(op->rc_flag & RC_INPROG))
4041
panic("nfsrvstate not inprog");
4042
if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) {
4043
printf("refcnt=%d\n", stp->ls_op->rc_refcnt);
4044
panic("nfsrvstate op refcnt");
4045
}
4046
4047
/* If ND_ERELOOKUP is set, the seqid has already been handled. */
4048
if ((nd->nd_flag & ND_ERELOOKUP) != 0)
4049
goto out;
4050
4051
if ((stp->ls_seq + 1) == seqid) {
4052
if (stp->ls_op)
4053
nfsrvd_derefcache(stp->ls_op);
4054
stp->ls_op = op;
4055
nfsrvd_refcache(op);
4056
stp->ls_seq = seqid;
4057
goto out;
4058
} else if (stp->ls_seq == seqid && stp->ls_op &&
4059
op->rc_xid == stp->ls_op->rc_xid &&
4060
op->rc_refcnt == 0 &&
4061
op->rc_reqlen == stp->ls_op->rc_reqlen &&
4062
op->rc_cksum == stp->ls_op->rc_cksum) {
4063
if (stp->ls_op->rc_flag & RC_INPROG) {
4064
error = NFSERR_DONTREPLY;
4065
goto out;
4066
}
4067
nd->nd_rp = stp->ls_op;
4068
nd->nd_rp->rc_flag |= RC_INPROG;
4069
nfsrvd_delcache(op);
4070
error = NFSERR_REPLYFROMCACHE;
4071
goto out;
4072
}
4073
error = NFSERR_BADSEQID;
4074
4075
out:
4076
NFSEXITCODE2(error, nd);
4077
return (error);
4078
}
4079
4080
/*
4081
* Get the client ip address for callbacks. If the strings can't be parsed,
4082
* just set lc_program to 0 to indicate no callbacks are possible.
4083
* (For cases where the address can't be parsed or is 0.0.0.0.0.0, set
4084
* the address to the client's transport address. This won't be used
4085
* for callbacks, but can be printed out by nfsstats for info.)
4086
* Return error if the xdr can't be parsed, 0 otherwise.
4087
*/
4088
int
4089
nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp)
4090
{
4091
u_int32_t *tl;
4092
u_char *cp, *cp2;
4093
int i, j, maxalen = 0, minalen = 0;
4094
sa_family_t af;
4095
#ifdef INET
4096
struct sockaddr_in *rin = NULL, *sin;
4097
#endif
4098
#ifdef INET6
4099
struct sockaddr_in6 *rin6 = NULL, *sin6;
4100
#endif
4101
u_char *addr;
4102
int error = 0, cantparse = 0;
4103
union {
4104
in_addr_t ival;
4105
u_char cval[4];
4106
} ip;
4107
union {
4108
in_port_t sval;
4109
u_char cval[2];
4110
} port;
4111
4112
/* 8 is the maximum length of the port# string. */
4113
addr = malloc(INET6_ADDRSTRLEN + 8, M_TEMP, M_WAITOK);
4114
clp->lc_req.nr_client = NULL;
4115
clp->lc_req.nr_lock = 0;
4116
af = AF_UNSPEC;
4117
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4118
i = fxdr_unsigned(int, *tl);
4119
if (i >= 3 && i <= 4) {
4120
error = nfsrv_mtostr(nd, addr, i);
4121
if (error)
4122
goto nfsmout;
4123
#ifdef INET
4124
if (!strcmp(addr, "tcp")) {
4125
clp->lc_flags |= LCL_TCPCALLBACK;
4126
clp->lc_req.nr_sotype = SOCK_STREAM;
4127
clp->lc_req.nr_soproto = IPPROTO_TCP;
4128
af = AF_INET;
4129
} else if (!strcmp(addr, "udp")) {
4130
clp->lc_req.nr_sotype = SOCK_DGRAM;
4131
clp->lc_req.nr_soproto = IPPROTO_UDP;
4132
af = AF_INET;
4133
}
4134
#endif
4135
#ifdef INET6
4136
if (af == AF_UNSPEC) {
4137
if (!strcmp(addr, "tcp6")) {
4138
clp->lc_flags |= LCL_TCPCALLBACK;
4139
clp->lc_req.nr_sotype = SOCK_STREAM;
4140
clp->lc_req.nr_soproto = IPPROTO_TCP;
4141
af = AF_INET6;
4142
} else if (!strcmp(addr, "udp6")) {
4143
clp->lc_req.nr_sotype = SOCK_DGRAM;
4144
clp->lc_req.nr_soproto = IPPROTO_UDP;
4145
af = AF_INET6;
4146
}
4147
}
4148
#endif
4149
if (af == AF_UNSPEC) {
4150
cantparse = 1;
4151
}
4152
} else {
4153
cantparse = 1;
4154
if (i > 0) {
4155
error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
4156
if (error)
4157
goto nfsmout;
4158
}
4159
}
4160
/*
4161
* The caller has allocated clp->lc_req.nr_nam to be large enough
4162
* for either AF_INET or AF_INET6 and zeroed out the contents.
4163
* maxalen is set to the maximum length of the host IP address string
4164
* plus 8 for the maximum length of the port#.
4165
* minalen is set to the minimum length of the host IP address string
4166
* plus 4 for the minimum length of the port#.
4167
* These lengths do not include NULL termination,
4168
* so INET[6]_ADDRSTRLEN - 1 is used in the calculations.
4169
*/
4170
switch (af) {
4171
#ifdef INET
4172
case AF_INET:
4173
rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4174
rin->sin_family = AF_INET;
4175
rin->sin_len = sizeof(struct sockaddr_in);
4176
maxalen = INET_ADDRSTRLEN - 1 + 8;
4177
minalen = 7 + 4;
4178
break;
4179
#endif
4180
#ifdef INET6
4181
case AF_INET6:
4182
rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4183
rin6->sin6_family = AF_INET6;
4184
rin6->sin6_len = sizeof(struct sockaddr_in6);
4185
maxalen = INET6_ADDRSTRLEN - 1 + 8;
4186
minalen = 3 + 4;
4187
break;
4188
#endif
4189
}
4190
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4191
i = fxdr_unsigned(int, *tl);
4192
if (i < 0) {
4193
error = NFSERR_BADXDR;
4194
goto nfsmout;
4195
} else if (i == 0) {
4196
cantparse = 1;
4197
} else if (!cantparse && i <= maxalen && i >= minalen) {
4198
error = nfsrv_mtostr(nd, addr, i);
4199
if (error)
4200
goto nfsmout;
4201
4202
/*
4203
* Parse out the address fields. We expect 6 decimal numbers
4204
* separated by '.'s for AF_INET and two decimal numbers
4205
* preceded by '.'s for AF_INET6.
4206
*/
4207
cp = NULL;
4208
switch (af) {
4209
#ifdef INET6
4210
/*
4211
* For AF_INET6, first parse the host address.
4212
*/
4213
case AF_INET6:
4214
cp = strchr(addr, '.');
4215
if (cp != NULL) {
4216
*cp++ = '\0';
4217
if (inet_pton(af, addr, &rin6->sin6_addr) == 1)
4218
i = 4;
4219
else {
4220
cp = NULL;
4221
cantparse = 1;
4222
}
4223
}
4224
break;
4225
#endif
4226
#ifdef INET
4227
case AF_INET:
4228
cp = addr;
4229
i = 0;
4230
break;
4231
#endif
4232
}
4233
while (cp != NULL && *cp && i < 6) {
4234
cp2 = cp;
4235
while (*cp2 && *cp2 != '.')
4236
cp2++;
4237
if (*cp2)
4238
*cp2++ = '\0';
4239
else if (i != 5) {
4240
cantparse = 1;
4241
break;
4242
}
4243
j = nfsrv_getipnumber(cp);
4244
if (j >= 0) {
4245
if (i < 4)
4246
ip.cval[3 - i] = j;
4247
else
4248
port.cval[5 - i] = j;
4249
} else {
4250
cantparse = 1;
4251
break;
4252
}
4253
cp = cp2;
4254
i++;
4255
}
4256
if (!cantparse) {
4257
/*
4258
* The host address INADDR_ANY is (mis)used to indicate
4259
* "there is no valid callback address".
4260
*/
4261
switch (af) {
4262
#ifdef INET6
4263
case AF_INET6:
4264
if (!IN6_ARE_ADDR_EQUAL(&rin6->sin6_addr,
4265
&in6addr_any))
4266
rin6->sin6_port = htons(port.sval);
4267
else
4268
cantparse = 1;
4269
break;
4270
#endif
4271
#ifdef INET
4272
case AF_INET:
4273
if (ip.ival != INADDR_ANY) {
4274
rin->sin_addr.s_addr = htonl(ip.ival);
4275
rin->sin_port = htons(port.sval);
4276
} else {
4277
cantparse = 1;
4278
}
4279
break;
4280
#endif
4281
}
4282
}
4283
} else {
4284
cantparse = 1;
4285
if (i > 0) {
4286
error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
4287
if (error)
4288
goto nfsmout;
4289
}
4290
}
4291
if (cantparse) {
4292
switch (nd->nd_nam->sa_family) {
4293
#ifdef INET
4294
case AF_INET:
4295
sin = (struct sockaddr_in *)nd->nd_nam;
4296
rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4297
rin->sin_family = AF_INET;
4298
rin->sin_len = sizeof(struct sockaddr_in);
4299
rin->sin_addr.s_addr = sin->sin_addr.s_addr;
4300
rin->sin_port = 0x0;
4301
break;
4302
#endif
4303
#ifdef INET6
4304
case AF_INET6:
4305
sin6 = (struct sockaddr_in6 *)nd->nd_nam;
4306
rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4307
rin6->sin6_family = AF_INET6;
4308
rin6->sin6_len = sizeof(struct sockaddr_in6);
4309
rin6->sin6_addr = sin6->sin6_addr;
4310
rin6->sin6_port = 0x0;
4311
break;
4312
#endif
4313
}
4314
clp->lc_program = 0;
4315
}
4316
nfsmout:
4317
free(addr, M_TEMP);
4318
NFSEXITCODE2(error, nd);
4319
return (error);
4320
}
4321
4322
/*
4323
* Turn a string of up to three decimal digits into a number. Return -1 upon
4324
* error.
4325
*/
4326
static int
4327
nfsrv_getipnumber(u_char *cp)
4328
{
4329
int i = 0, j = 0;
4330
4331
while (*cp) {
4332
if (j > 2 || *cp < '0' || *cp > '9')
4333
return (-1);
4334
i *= 10;
4335
i += (*cp - '0');
4336
cp++;
4337
j++;
4338
}
4339
if (i < 256)
4340
return (i);
4341
return (-1);
4342
}
4343
4344
/*
4345
* This function checks for restart conditions.
4346
*/
4347
static int
4348
nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
4349
nfsv4stateid_t *stateidp, int specialid)
4350
{
4351
int ret = 0;
4352
4353
/*
4354
* First check for a server restart. Open, LockT, ReleaseLockOwner
4355
* and DelegPurge have a clientid, the rest a stateid.
4356
*/
4357
if (flags &
4358
(NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) {
4359
if (clientid.lval[0] != NFSD_VNET(nfsrvboottime)) {
4360
ret = NFSERR_STALECLIENTID;
4361
goto out;
4362
}
4363
} else if (stateidp->other[0] != NFSD_VNET(nfsrvboottime) &&
4364
specialid == 0) {
4365
ret = NFSERR_STALESTATEID;
4366
goto out;
4367
}
4368
4369
/*
4370
* Read, Write, Setattr and LockT can return NFSERR_GRACE and do
4371
* not use a lock/open owner seqid#, so the check can be done now.
4372
* (The others will be checked, as required, later.)
4373
*/
4374
if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST)))
4375
goto out;
4376
4377
NFSLOCKSTATE();
4378
ret = nfsrv_checkgrace(NULL, NULL, flags);
4379
NFSUNLOCKSTATE();
4380
4381
out:
4382
NFSEXITCODE(ret);
4383
return (ret);
4384
}
4385
4386
/*
4387
* Check for grace.
4388
*/
4389
static int
4390
nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
4391
u_int32_t flags)
4392
{
4393
int error = 0, notreclaimed;
4394
struct nfsrv_stable *sp;
4395
4396
if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags & (NFSNSF_UPDATEDONE |
4397
NFSNSF_GRACEOVER)) == 0) {
4398
/*
4399
* First, check to see if all of the clients have done a
4400
* ReclaimComplete. If so, grace can end now.
4401
*/
4402
notreclaimed = 0;
4403
if (!NFSD_VNET(nfsd_disable_grace)) {
4404
LIST_FOREACH(sp, &NFSD_VNET(nfsrv_stablefirst).nsf_head,
4405
nst_list) {
4406
if ((sp->nst_flag & NFSNST_RECLAIMED) == 0) {
4407
notreclaimed = 1;
4408
break;
4409
}
4410
}
4411
}
4412
if (notreclaimed == 0)
4413
NFSD_VNET(nfsrv_stablefirst).nsf_flags |=
4414
(NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
4415
}
4416
4417
if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_GRACEOVER) != 0) {
4418
if (flags & NFSLCK_RECLAIM) {
4419
error = NFSERR_NOGRACE;
4420
goto out;
4421
}
4422
} else {
4423
if (!(flags & NFSLCK_RECLAIM)) {
4424
error = NFSERR_GRACE;
4425
goto out;
4426
}
4427
if (nd != NULL && clp != NULL &&
4428
(nd->nd_flag & ND_NFSV41) != 0 &&
4429
(clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) {
4430
error = NFSERR_NOGRACE;
4431
goto out;
4432
}
4433
4434
/*
4435
* If grace is almost over and we are still getting Reclaims,
4436
* extend grace a bit.
4437
*/
4438
if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) >
4439
NFSD_VNET(nfsrv_stablefirst).nsf_eograce)
4440
NFSD_VNET(nfsrv_stablefirst).nsf_eograce =
4441
NFSD_MONOSEC + NFSRV_LEASEDELTA;
4442
}
4443
4444
out:
4445
NFSEXITCODE(error);
4446
return (error);
4447
}
4448
4449
/*
4450
* Do a server callback.
4451
* The "trunc" argument is slightly overloaded and refers to different
4452
* boolean arguments for CBRECALL and CBLAYOUTRECALL.
4453
*/
4454
static int
4455
nfsrv_docallback(struct nfsclient *clp, int procnum, nfsv4stateid_t *stateidp,
4456
int trunc, fhandle_t *fhp, struct nfsvattr *nap, nfsattrbit_t *attrbitp,
4457
int laytype, NFSPROC_T *p)
4458
{
4459
struct mbuf *m;
4460
u_int32_t *tl;
4461
struct nfsrv_descript *nd;
4462
struct ucred *cred;
4463
int error = 0, slotpos;
4464
u_int32_t callback;
4465
struct nfsdsession *sep = NULL;
4466
uint64_t tval;
4467
bool dotls;
4468
4469
nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
4470
cred = newnfs_getcred();
4471
NFSLOCKSTATE(); /* mostly for lc_cbref++ */
4472
if (clp->lc_flags & LCL_NEEDSCONFIRM) {
4473
NFSUNLOCKSTATE();
4474
panic("docallb");
4475
}
4476
clp->lc_cbref++;
4477
4478
/*
4479
* Fill the callback program# and version into the request
4480
* structure for newnfs_connect() to use.
4481
*/
4482
clp->lc_req.nr_prog = clp->lc_program;
4483
#ifdef notnow
4484
if ((clp->lc_flags & LCL_NFSV41) != 0)
4485
clp->lc_req.nr_vers = NFSV41_CBVERS;
4486
else
4487
#endif
4488
clp->lc_req.nr_vers = NFSV4_CBVERS;
4489
4490
/*
4491
* First, fill in some of the fields of nd and cr.
4492
*/
4493
nd->nd_flag = ND_NFSV4;
4494
if (clp->lc_flags & LCL_GSS)
4495
nd->nd_flag |= ND_KERBV;
4496
if ((clp->lc_flags & LCL_NFSV41) != 0)
4497
nd->nd_flag |= ND_NFSV41;
4498
if ((clp->lc_flags & LCL_NFSV42) != 0)
4499
nd->nd_flag |= ND_NFSV42;
4500
nd->nd_repstat = 0;
4501
cred->cr_uid = clp->lc_uid;
4502
cred->cr_gid = clp->lc_gid;
4503
callback = clp->lc_callback;
4504
NFSUNLOCKSTATE();
4505
cred->cr_ngroups = 1;
4506
4507
/*
4508
* Get the first mbuf for the request.
4509
*/
4510
MGET(m, M_WAITOK, MT_DATA);
4511
m->m_len = 0;
4512
nd->nd_mreq = nd->nd_mb = m;
4513
nd->nd_bpos = mtod(m, caddr_t);
4514
4515
/*
4516
* and build the callback request.
4517
*/
4518
if (procnum == NFSV4OP_CBGETATTR) {
4519
nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4520
error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR,
4521
"CB Getattr", &sep, &slotpos);
4522
if (error != 0) {
4523
m_freem(nd->nd_mreq);
4524
goto errout;
4525
}
4526
(void)nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4527
(void)nfsrv_putattrbit(nd, attrbitp);
4528
} else if (procnum == NFSV4OP_CBRECALL) {
4529
nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4530
error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL,
4531
"CB Recall", &sep, &slotpos);
4532
if (error != 0) {
4533
m_freem(nd->nd_mreq);
4534
goto errout;
4535
}
4536
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
4537
*tl++ = txdr_unsigned(stateidp->seqid);
4538
NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl,
4539
NFSX_STATEIDOTHER);
4540
tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4541
if (trunc)
4542
*tl = newnfs_true;
4543
else
4544
*tl = newnfs_false;
4545
(void)nfsm_fhtom(NULL, nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4546
} else if (procnum == NFSV4OP_CBLAYOUTRECALL) {
4547
NFSD_DEBUG(4, "docallback layout recall\n");
4548
nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4549
error = nfsrv_cbcallargs(nd, clp, callback,
4550
NFSV4OP_CBLAYOUTRECALL, "CB Reclayout", &sep, &slotpos);
4551
NFSD_DEBUG(4, "aft cbcallargs=%d\n", error);
4552
if (error != 0) {
4553
m_freem(nd->nd_mreq);
4554
goto errout;
4555
}
4556
NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
4557
*tl++ = txdr_unsigned(laytype);
4558
*tl++ = txdr_unsigned(NFSLAYOUTIOMODE_ANY);
4559
if (trunc)
4560
*tl++ = newnfs_true;
4561
else
4562
*tl++ = newnfs_false;
4563
*tl = txdr_unsigned(NFSV4LAYOUTRET_FILE);
4564
(void)nfsm_fhtom(NULL, nd, (uint8_t *)fhp, NFSX_MYFH, 0);
4565
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER + NFSX_STATEID);
4566
tval = 0;
4567
txdr_hyper(tval, tl); tl += 2;
4568
tval = UINT64_MAX;
4569
txdr_hyper(tval, tl); tl += 2;
4570
*tl++ = txdr_unsigned(stateidp->seqid);
4571
NFSBCOPY(stateidp->other, tl, NFSX_STATEIDOTHER);
4572
tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4573
NFSD_DEBUG(4, "aft args\n");
4574
} else if (procnum == NFSV4PROC_CBNULL) {
4575
nd->nd_procnum = NFSV4PROC_CBNULL;
4576
if ((clp->lc_flags & LCL_NFSV41) != 0) {
4577
error = nfsv4_getcbsession(clp, &sep);
4578
if (error != 0) {
4579
m_freem(nd->nd_mreq);
4580
goto errout;
4581
}
4582
}
4583
} else {
4584
error = NFSERR_SERVERFAULT;
4585
m_freem(nd->nd_mreq);
4586
goto errout;
4587
}
4588
4589
/*
4590
* Call newnfs_connect(), as required, and then newnfs_request().
4591
*/
4592
dotls = false;
4593
if ((clp->lc_flags & LCL_TLSCB) != 0)
4594
dotls = true;
4595
(void) newnfs_sndlock(&clp->lc_req.nr_lock);
4596
if (clp->lc_req.nr_client == NULL) {
4597
if ((clp->lc_flags & LCL_NFSV41) != 0) {
4598
error = ECONNREFUSED;
4599
if (procnum != NFSV4PROC_CBNULL)
4600
nfsv4_freeslot(&sep->sess_cbsess, slotpos,
4601
true);
4602
nfsrv_freesession(NULL, sep, NULL, false, NULL);
4603
} else if (nd->nd_procnum == NFSV4PROC_CBNULL)
4604
error = newnfs_connect(NULL, &clp->lc_req, cred,
4605
NULL, 1, dotls, &clp->lc_req.nr_client);
4606
else
4607
error = newnfs_connect(NULL, &clp->lc_req, cred,
4608
NULL, 3, dotls, &clp->lc_req.nr_client);
4609
}
4610
newnfs_sndunlock(&clp->lc_req.nr_lock);
4611
NFSD_DEBUG(4, "aft sndunlock=%d\n", error);
4612
if (!error) {
4613
if ((nd->nd_flag & ND_NFSV41) != 0) {
4614
KASSERT(sep != NULL, ("sep NULL"));
4615
if (sep->sess_cbsess.nfsess_xprt != NULL)
4616
error = newnfs_request(nd, NULL, clp,
4617
&clp->lc_req, NULL, NULL, cred,
4618
clp->lc_program, clp->lc_req.nr_vers, NULL,
4619
1, NULL, &sep->sess_cbsess);
4620
else {
4621
/*
4622
* This should probably never occur, but if a
4623
* client somehow does an RPC without a
4624
* SequenceID Op that causes a callback just
4625
* after the nfsd threads have been terminated
4626
* and restarted we could conceivably get here
4627
* without a backchannel xprt.
4628
*/
4629
printf("nfsrv_docallback: no xprt\n");
4630
error = ECONNREFUSED;
4631
}
4632
NFSD_DEBUG(4, "aft newnfs_request=%d\n", error);
4633
if (error != 0 && procnum != NFSV4PROC_CBNULL) {
4634
/*
4635
* It is likely that the callback was never
4636
* processed by the client and, as such,
4637
* the sequence# for the session slot needs
4638
* to be backed up by one to avoid a
4639
* NFSERR_SEQMISORDERED error reply.
4640
* For the unlikely case where the callback
4641
* was processed by the client, this will
4642
* make the next callback on the slot
4643
* appear to be a retry.
4644
* Since callbacks never specify that the
4645
* reply be cached, this "apparent retry"
4646
* should not be a problem.
4647
*/
4648
nfsv4_freeslot(&sep->sess_cbsess, slotpos,
4649
true);
4650
}
4651
nfsrv_freesession(NULL, sep, NULL, false, NULL);
4652
} else
4653
error = newnfs_request(nd, NULL, clp, &clp->lc_req,
4654
NULL, NULL, cred, clp->lc_program,
4655
clp->lc_req.nr_vers, NULL, 1, NULL, NULL);
4656
}
4657
errout:
4658
NFSFREECRED(cred);
4659
4660
/*
4661
* If error is set here, the Callback path isn't working
4662
* properly, so twiddle the appropriate LCL_ flags.
4663
* (nd_repstat != 0 indicates the Callback path is working,
4664
* but the callback failed on the client.)
4665
*/
4666
if (error) {
4667
/*
4668
* Mark the callback pathway down, which disabled issuing
4669
* of delegations and gets Renew to return NFSERR_CBPATHDOWN.
4670
*/
4671
NFSLOCKSTATE();
4672
clp->lc_flags |= LCL_CBDOWN;
4673
NFSUNLOCKSTATE();
4674
} else {
4675
/*
4676
* Callback worked. If the callback path was down, disable
4677
* callbacks, so no more delegations will be issued. (This
4678
* is done on the assumption that the callback pathway is
4679
* flakey.)
4680
*/
4681
NFSLOCKSTATE();
4682
if (clp->lc_flags & LCL_CBDOWN)
4683
clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON);
4684
NFSUNLOCKSTATE();
4685
if (nd->nd_repstat) {
4686
error = nd->nd_repstat;
4687
NFSD_DEBUG(1, "nfsrv_docallback op=%d err=%d\n",
4688
procnum, error);
4689
} else if (error == 0 && procnum == NFSV4OP_CBGETATTR)
4690
error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
4691
NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL,
4692
NULL, NULL, NULL, p, NULL);
4693
m_freem(nd->nd_mrep);
4694
}
4695
NFSLOCKSTATE();
4696
clp->lc_cbref--;
4697
if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) {
4698
clp->lc_flags &= ~LCL_WAKEUPWANTED;
4699
wakeup(clp);
4700
}
4701
NFSUNLOCKSTATE();
4702
4703
free(nd, M_TEMP);
4704
NFSEXITCODE(error);
4705
return (error);
4706
}
4707
4708
/*
4709
* Set up the compound RPC for the callback.
4710
*/
4711
static int
4712
nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
4713
uint32_t callback, int op, const char *optag, struct nfsdsession **sepp,
4714
int *slotposp)
4715
{
4716
uint32_t *tl;
4717
int error, len;
4718
4719
len = strlen(optag);
4720
(void)nfsm_strtom(nd, optag, len);
4721
NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4722
if ((nd->nd_flag & ND_NFSV41) != 0) {
4723
if ((nd->nd_flag & ND_NFSV42) != 0)
4724
*tl++ = txdr_unsigned(NFSV42_MINORVERSION);
4725
else
4726
*tl++ = txdr_unsigned(NFSV41_MINORVERSION);
4727
*tl++ = txdr_unsigned(callback);
4728
*tl++ = txdr_unsigned(2);
4729
*tl = txdr_unsigned(NFSV4OP_CBSEQUENCE);
4730
error = nfsv4_setcbsequence(nd, clp, 1, sepp, slotposp);
4731
if (error != 0)
4732
return (error);
4733
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
4734
*tl = txdr_unsigned(op);
4735
} else {
4736
*tl++ = txdr_unsigned(NFSV4_MINORVERSION);
4737
*tl++ = txdr_unsigned(callback);
4738
*tl++ = txdr_unsigned(1);
4739
*tl = txdr_unsigned(op);
4740
}
4741
return (0);
4742
}
4743
4744
/*
4745
* Return the next index# for a clientid. Mostly just increment and return
4746
* the next one, but... if the 32bit unsigned does actually wrap around,
4747
* it should be rebooted.
4748
* At an average rate of one new client per second, it will wrap around in
4749
* approximately 136 years. (I think the server will have been shut
4750
* down or rebooted before then.)
4751
*/
4752
static u_int32_t
4753
nfsrv_nextclientindex(void)
4754
{
4755
static u_int32_t client_index = 0;
4756
4757
client_index++;
4758
if (client_index != 0)
4759
return (client_index);
4760
4761
printf("%s: out of clientids\n", __func__);
4762
return (client_index);
4763
}
4764
4765
/*
4766
* Return the next index# for a stateid. Mostly just increment and return
4767
* the next one, but... if the 32bit unsigned does actually wrap around
4768
* (will a BSD server stay up that long?), find
4769
* new start and end values.
4770
*/
4771
static u_int32_t
4772
nfsrv_nextstateindex(struct nfsclient *clp)
4773
{
4774
struct nfsstate *stp;
4775
int i;
4776
u_int32_t canuse, min_index, max_index;
4777
4778
if (!(clp->lc_flags & LCL_INDEXNOTOK)) {
4779
clp->lc_stateindex++;
4780
if (clp->lc_stateindex != clp->lc_statemaxindex)
4781
return (clp->lc_stateindex);
4782
}
4783
4784
/*
4785
* Yuck, we've hit the end.
4786
* Look for a new min and max.
4787
*/
4788
min_index = 0;
4789
max_index = 0xffffffff;
4790
for (i = 0; i < nfsrv_statehashsize; i++) {
4791
LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4792
if (stp->ls_stateid.other[2] > 0x80000000) {
4793
if (stp->ls_stateid.other[2] < max_index)
4794
max_index = stp->ls_stateid.other[2];
4795
} else {
4796
if (stp->ls_stateid.other[2] > min_index)
4797
min_index = stp->ls_stateid.other[2];
4798
}
4799
}
4800
}
4801
4802
/*
4803
* Yikes, highly unlikely, but I'll handle it anyhow.
4804
*/
4805
if (min_index == 0x80000000 && max_index == 0x80000001) {
4806
canuse = 0;
4807
/*
4808
* Loop around until we find an unused entry. Return that
4809
* and set LCL_INDEXNOTOK, so the search will continue next time.
4810
* (This is one of those rare cases where a goto is the
4811
* cleanest way to code the loop.)
4812
*/
4813
tryagain:
4814
for (i = 0; i < nfsrv_statehashsize; i++) {
4815
LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4816
if (stp->ls_stateid.other[2] == canuse) {
4817
canuse++;
4818
goto tryagain;
4819
}
4820
}
4821
}
4822
clp->lc_flags |= LCL_INDEXNOTOK;
4823
return (canuse);
4824
}
4825
4826
/*
4827
* Ok to start again from min + 1.
4828
*/
4829
clp->lc_stateindex = min_index + 1;
4830
clp->lc_statemaxindex = max_index;
4831
clp->lc_flags &= ~LCL_INDEXNOTOK;
4832
return (clp->lc_stateindex);
4833
}
4834
4835
/*
4836
* The following functions handle the stable storage file that deals with
4837
* the edge conditions described in RFC3530 Sec. 8.6.3.
4838
* The file is as follows:
4839
* - a single record at the beginning that has the lease time of the
4840
* previous server instance (before the last reboot) and the nfsrvboottime
4841
* values for the previous server boots.
4842
* These previous boot times are used to ensure that the current
4843
* nfsrvboottime does not, somehow, get set to a previous one.
4844
* (This is important so that Stale ClientIDs and StateIDs can
4845
* be recognized.)
4846
* The number of previous nfsvrboottime values precedes the list.
4847
* - followed by some number of appended records with:
4848
* - client id string
4849
* - flag that indicates it is a record revoking state via lease
4850
* expiration or similar
4851
* OR has successfully acquired state.
4852
* These structures vary in length, with the client string at the end, up
4853
* to NFSV4_OPAQUELIMIT in size.
4854
*
4855
* At the end of the grace period, the file is truncated, the first
4856
* record is rewritten with updated information and any acquired state
4857
* records for successful reclaims of state are written.
4858
*
4859
* Subsequent records are appended when the first state is issued to
4860
* a client and when state is revoked for a client.
4861
*
4862
* When reading the file in, state issued records that come later in
4863
* the file override older ones, since the append log is in cronological order.
4864
* If, for some reason, the file can't be read, the grace period is
4865
* immediately terminated and all reclaims get NFSERR_NOGRACE.
4866
*/
4867
4868
/*
4869
* Read in the stable storage file. Called by nfssvc() before the nfsd
4870
* processes start servicing requests.
4871
*/
4872
void
4873
nfsrv_setupstable(NFSPROC_T *p)
4874
{
4875
struct nfsrv_stablefirst *sf = &NFSD_VNET(nfsrv_stablefirst);
4876
struct nfsrv_stable *sp, *nsp;
4877
struct nfst_rec *tsp;
4878
int error, i, tryagain;
4879
off_t off = 0;
4880
ssize_t aresid, len;
4881
4882
/*
4883
* If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without
4884
* a reboot, so state has not been lost.
4885
*/
4886
if (sf->nsf_flags & NFSNSF_UPDATEDONE)
4887
return;
4888
/*
4889
* Set Grace over just until the file reads successfully.
4890
*/
4891
NFSD_VNET(nfsrvboottime) = time_second;
4892
LIST_INIT(&sf->nsf_head);
4893
sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
4894
sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA;
4895
if (sf->nsf_fp == NULL)
4896
return;
4897
error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4898
(caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE,
4899
0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4900
if (error || aresid || sf->nsf_numboots == 0 ||
4901
sf->nsf_numboots > NFSNSF_MAXNUMBOOTS)
4902
return;
4903
4904
/*
4905
* Now, read in the boottimes.
4906
*/
4907
sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) *
4908
sizeof(time_t), M_TEMP, M_WAITOK);
4909
off = sizeof (struct nfsf_rec);
4910
error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4911
(caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off,
4912
UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4913
if (error || aresid) {
4914
free(sf->nsf_bootvals, M_TEMP);
4915
sf->nsf_bootvals = NULL;
4916
return;
4917
}
4918
4919
/*
4920
* Make sure this nfsrvboottime is different from all recorded
4921
* previous ones.
4922
*/
4923
do {
4924
tryagain = 0;
4925
for (i = 0; i < sf->nsf_numboots; i++) {
4926
if (NFSD_VNET(nfsrvboottime) == sf->nsf_bootvals[i]) {
4927
NFSD_VNET(nfsrvboottime)++;
4928
tryagain = 1;
4929
break;
4930
}
4931
}
4932
} while (tryagain);
4933
4934
sf->nsf_flags |= NFSNSF_OK;
4935
off += (sf->nsf_numboots * sizeof (time_t));
4936
4937
/*
4938
* Read through the file, building a list of records for grace
4939
* checking.
4940
* Each record is between sizeof (struct nfst_rec) and
4941
* sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1
4942
* and is actually sizeof (struct nfst_rec) + nst_len - 1.
4943
*/
4944
tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
4945
NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK);
4946
do {
4947
error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4948
(caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1,
4949
off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4950
len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid;
4951
if (error || (len > 0 && (len < sizeof (struct nfst_rec) ||
4952
len < (sizeof (struct nfst_rec) + tsp->len - 1)))) {
4953
/*
4954
* Yuck, the file has been corrupted, so just return
4955
* after clearing out any restart state, so the grace period
4956
* is over.
4957
*/
4958
LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
4959
LIST_REMOVE(sp, nst_list);
4960
free(sp, M_TEMP);
4961
}
4962
free(tsp, M_TEMP);
4963
sf->nsf_flags &= ~NFSNSF_OK;
4964
free(sf->nsf_bootvals, M_TEMP);
4965
sf->nsf_bootvals = NULL;
4966
return;
4967
}
4968
if (len > 0) {
4969
off += sizeof (struct nfst_rec) + tsp->len - 1;
4970
/*
4971
* Search the list for a matching client.
4972
*/
4973
LIST_FOREACH(sp, &sf->nsf_head, nst_list) {
4974
if (tsp->len == sp->nst_len &&
4975
!NFSBCMP(tsp->client, sp->nst_client, tsp->len))
4976
break;
4977
}
4978
if (sp == LIST_END(&sf->nsf_head)) {
4979
sp = (struct nfsrv_stable *)malloc(tsp->len +
4980
sizeof (struct nfsrv_stable) - 1, M_TEMP,
4981
M_WAITOK);
4982
NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec,
4983
sizeof (struct nfst_rec) + tsp->len - 1);
4984
LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list);
4985
} else {
4986
if (tsp->flag == NFSNST_REVOKE)
4987
sp->nst_flag |= NFSNST_REVOKE;
4988
else
4989
/*
4990
* A subsequent timestamp indicates the client
4991
* did a setclientid/confirm and any previous
4992
* revoke is no longer relevant.
4993
*/
4994
sp->nst_flag &= ~NFSNST_REVOKE;
4995
}
4996
}
4997
} while (len > 0);
4998
free(tsp, M_TEMP);
4999
sf->nsf_flags = NFSNSF_OK;
5000
sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease +
5001
NFSRV_LEASEDELTA;
5002
}
5003
5004
/*
5005
* Update the stable storage file, now that the grace period is over.
5006
*/
5007
void
5008
nfsrv_updatestable(NFSPROC_T *p)
5009
{
5010
struct nfsrv_stablefirst *sf = &NFSD_VNET(nfsrv_stablefirst);
5011
struct nfsrv_stable *sp, *nsp;
5012
int i;
5013
struct nfsvattr nva;
5014
vnode_t vp;
5015
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000)
5016
mount_t mp = NULL;
5017
#endif
5018
int error;
5019
5020
if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE))
5021
return;
5022
sf->nsf_flags |= NFSNSF_UPDATEDONE;
5023
/*
5024
* Ok, we need to rewrite the stable storage file.
5025
* - truncate to 0 length
5026
* - write the new first structure
5027
* - loop through the data structures, writing out any that
5028
* have timestamps older than the old boot
5029
*/
5030
if (sf->nsf_bootvals) {
5031
sf->nsf_numboots++;
5032
for (i = sf->nsf_numboots - 2; i >= 0; i--)
5033
sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i];
5034
} else {
5035
sf->nsf_numboots = 1;
5036
sf->nsf_bootvals = (time_t *)malloc(sizeof(time_t),
5037
M_TEMP, M_WAITOK);
5038
}
5039
sf->nsf_bootvals[0] = NFSD_VNET(nfsrvboottime);
5040
sf->nsf_lease = nfsrv_lease;
5041
NFSVNO_ATTRINIT(&nva);
5042
NFSVNO_SETATTRVAL(&nva, size, 0);
5043
vp = NFSFPVNODE(sf->nsf_fp);
5044
vn_start_write(vp, &mp, V_WAIT);
5045
if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
5046
error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p,
5047
NULL);
5048
NFSVOPUNLOCK(vp);
5049
} else
5050
error = EPERM;
5051
vn_finished_write(mp);
5052
if (!error)
5053
error = NFSD_RDWR(UIO_WRITE, vp,
5054
(caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0,
5055
UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
5056
if (!error)
5057
error = NFSD_RDWR(UIO_WRITE, vp,
5058
(caddr_t)sf->nsf_bootvals,
5059
sf->nsf_numboots * sizeof (time_t),
5060
(off_t)(sizeof (struct nfsf_rec)),
5061
UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
5062
free(sf->nsf_bootvals, M_TEMP);
5063
sf->nsf_bootvals = NULL;
5064
if (error) {
5065
sf->nsf_flags &= ~NFSNSF_OK;
5066
printf("EEK! Can't write NfsV4 stable storage file\n");
5067
return;
5068
}
5069
sf->nsf_flags |= NFSNSF_OK;
5070
5071
/*
5072
* Loop through the list and write out timestamp records for
5073
* any clients that successfully reclaimed state.
5074
*/
5075
LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
5076
if (sp->nst_flag & NFSNST_GOTSTATE) {
5077
nfsrv_writestable(sp->nst_client, sp->nst_len,
5078
NFSNST_NEWSTATE, p);
5079
sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE;
5080
}
5081
LIST_REMOVE(sp, nst_list);
5082
free(sp, M_TEMP);
5083
}
5084
nfsrv_backupstable();
5085
}
5086
5087
/*
5088
* Append a record to the stable storage file.
5089
*/
5090
void
5091
nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p)
5092
{
5093
struct nfsrv_stablefirst *sf = &NFSD_VNET(nfsrv_stablefirst);
5094
struct nfst_rec *sp;
5095
int error;
5096
5097
if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL)
5098
return;
5099
sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
5100
len - 1, M_TEMP, M_WAITOK);
5101
sp->len = len;
5102
NFSBCOPY(client, sp->client, len);
5103
sp->flag = flag;
5104
error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp),
5105
(caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0,
5106
UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p);
5107
free(sp, M_TEMP);
5108
if (error) {
5109
sf->nsf_flags &= ~NFSNSF_OK;
5110
printf("EEK! Can't write NfsV4 stable storage file\n");
5111
}
5112
}
5113
5114
/*
5115
* This function is called during the grace period to mark a client
5116
* that successfully reclaimed state.
5117
*/
5118
static void
5119
nfsrv_markstable(struct nfsclient *clp)
5120
{
5121
struct nfsrv_stable *sp;
5122
5123
/*
5124
* First find the client structure.
5125
*/
5126
LIST_FOREACH(sp, &NFSD_VNET(nfsrv_stablefirst).nsf_head, nst_list) {
5127
if (sp->nst_len == clp->lc_idlen &&
5128
!NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
5129
break;
5130
}
5131
if (sp == LIST_END(&NFSD_VNET(nfsrv_stablefirst).nsf_head))
5132
return;
5133
5134
/*
5135
* Now, just mark it and set the nfsclient back pointer.
5136
*/
5137
sp->nst_flag |= NFSNST_GOTSTATE;
5138
sp->nst_clp = clp;
5139
}
5140
5141
/*
5142
* This function is called when a NFSv4.1 client does a ReclaimComplete.
5143
* Very similar to nfsrv_markstable(), except for the flag being set.
5144
*/
5145
static void
5146
nfsrv_markreclaim(struct nfsclient *clp)
5147
{
5148
struct nfsrv_stable *sp;
5149
5150
/*
5151
* First find the client structure.
5152
*/
5153
LIST_FOREACH(sp, &NFSD_VNET(nfsrv_stablefirst).nsf_head, nst_list) {
5154
if (sp->nst_len == clp->lc_idlen &&
5155
!NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
5156
break;
5157
}
5158
if (sp == LIST_END(&NFSD_VNET(nfsrv_stablefirst).nsf_head))
5159
return;
5160
5161
/*
5162
* Now, just set the flag.
5163
*/
5164
sp->nst_flag |= NFSNST_RECLAIMED;
5165
5166
/*
5167
* Free up any old delegations.
5168
*/
5169
nfsrv_freedeleglist(&clp->lc_olddeleg);
5170
}
5171
5172
/*
5173
* This function is called for a reclaim, to see if it gets grace.
5174
* It returns 0 if a reclaim is allowed, 1 otherwise.
5175
*/
5176
static int
5177
nfsrv_checkstable(struct nfsclient *clp)
5178
{
5179
struct nfsrv_stable *sp;
5180
5181
/*
5182
* First, find the entry for the client.
5183
*/
5184
LIST_FOREACH(sp, &NFSD_VNET(nfsrv_stablefirst).nsf_head, nst_list) {
5185
if (sp->nst_len == clp->lc_idlen &&
5186
!NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
5187
break;
5188
}
5189
5190
/*
5191
* If not in the list, state was revoked or no state was issued
5192
* since the previous reboot, a reclaim is denied.
5193
*/
5194
if (sp == LIST_END(&NFSD_VNET(nfsrv_stablefirst).nsf_head) ||
5195
(sp->nst_flag & NFSNST_REVOKE) ||
5196
!(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_OK))
5197
return (1);
5198
return (0);
5199
}
5200
5201
/*
5202
* Test for and try to clear out a conflicting client. This is called by
5203
* nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients
5204
* a found.
5205
* The trick here is that it can't revoke a conflicting client with an
5206
* expired lease unless it holds the v4root lock, so...
5207
* If no v4root lock, get the lock and return 1 to indicate "try again".
5208
* Return 0 to indicate the conflict can't be revoked and 1 to indicate
5209
* the revocation worked and the conflicting client is "bye, bye", so it
5210
* can be tried again.
5211
* Return 2 to indicate that the vnode is VIRF_DOOMED after NFSVOPLOCK().
5212
* Unlocks State before a non-zero value is returned.
5213
*/
5214
static int
5215
nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
5216
NFSPROC_T *p)
5217
{
5218
int gotlock, lktype = 0;
5219
5220
/*
5221
* If lease hasn't expired, we can't fix it.
5222
*/
5223
if (clp->lc_expiry >= NFSD_MONOSEC ||
5224
!(NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_UPDATEDONE))
5225
return (0);
5226
if (*haslockp == 0) {
5227
NFSUNLOCKSTATE();
5228
if (vp != NULL) {
5229
lktype = NFSVOPISLOCKED(vp);
5230
NFSVOPUNLOCK(vp);
5231
}
5232
NFSLOCKV4ROOTMUTEX();
5233
nfsv4_relref(&nfsv4rootfs_lock);
5234
do {
5235
gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
5236
NFSV4ROOTLOCKMUTEXPTR, NULL);
5237
} while (!gotlock);
5238
NFSUNLOCKV4ROOTMUTEX();
5239
*haslockp = 1;
5240
if (vp != NULL) {
5241
NFSVOPLOCK(vp, lktype | LK_RETRY);
5242
if (VN_IS_DOOMED(vp))
5243
return (2);
5244
}
5245
return (1);
5246
}
5247
NFSUNLOCKSTATE();
5248
5249
/*
5250
* Ok, we can expire the conflicting client.
5251
*/
5252
nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
5253
nfsrv_backupstable();
5254
nfsrv_cleanclient(clp, p, false, NULL);
5255
nfsrv_freedeleglist(&clp->lc_deleg);
5256
nfsrv_freedeleglist(&clp->lc_olddeleg);
5257
LIST_REMOVE(clp, lc_hash);
5258
nfsrv_zapclient(clp, p);
5259
return (1);
5260
}
5261
5262
/*
5263
* Resolve a delegation conflict.
5264
* Returns 0 to indicate the conflict was resolved without sleeping.
5265
* Return -1 to indicate that the caller should check for conflicts again.
5266
* Return > 0 for an error that should be returned, normally NFSERR_DELAY.
5267
*
5268
* Also, manipulate the nfsv4root_lock, as required. It isn't changed
5269
* for a return of 0, since there was no sleep and it could be required
5270
* later. It is released for a return of NFSERR_DELAY, since the caller
5271
* will return that error. It is released when a sleep was done waiting
5272
* for the delegation to be returned or expire (so that other nfsds can
5273
* handle ops). Then, it must be acquired for the write to stable storage.
5274
* (This function is somewhat similar to nfsrv_clientconflict(), but
5275
* the semantics differ in a couple of subtle ways. The return of 0
5276
* indicates the conflict was resolved without sleeping here, not
5277
* that the conflict can't be resolved and the handling of nfsv4root_lock
5278
* differs, as noted above.)
5279
* Unlocks State before returning a non-zero value.
5280
*/
5281
static int
5282
nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
5283
vnode_t vp)
5284
{
5285
struct nfsclient *clp = stp->ls_clp;
5286
int gotlock, error, lktype = 0, retrycnt, zapped_clp;
5287
nfsv4stateid_t tstateid;
5288
fhandle_t tfh;
5289
5290
/*
5291
* If the conflict is with an old delegation...
5292
*/
5293
if (stp->ls_flags & NFSLCK_OLDDELEG) {
5294
/*
5295
* You can delete it, if it has expired.
5296
*/
5297
if (clp->lc_delegtime < NFSD_MONOSEC) {
5298
nfsrv_freedeleg(stp);
5299
NFSUNLOCKSTATE();
5300
error = -1;
5301
goto out;
5302
}
5303
NFSUNLOCKSTATE();
5304
/*
5305
* During this delay, the old delegation could expire or it
5306
* could be recovered by the client via an Open with
5307
* CLAIM_DELEGATE_PREV.
5308
* Release the nfsv4root_lock, if held.
5309
*/
5310
if (*haslockp) {
5311
*haslockp = 0;
5312
NFSLOCKV4ROOTMUTEX();
5313
nfsv4_unlock(&nfsv4rootfs_lock, 1);
5314
NFSUNLOCKV4ROOTMUTEX();
5315
}
5316
error = NFSERR_DELAY;
5317
goto out;
5318
}
5319
5320
/*
5321
* It's a current delegation, so:
5322
* - check to see if the delegation has expired
5323
* - if so, get the v4root lock and then expire it
5324
*/
5325
if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0 || (stp->ls_lastrecall <
5326
NFSD_MONOSEC && clp->lc_expiry >= NFSD_MONOSEC &&
5327
stp->ls_delegtime >= NFSD_MONOSEC)) {
5328
/*
5329
* - do a recall callback, since not yet done
5330
* For now, never allow truncate to be set. To use
5331
* truncate safely, it must be guaranteed that the
5332
* Remove, Rename or Setattr with size of 0 will
5333
* succeed and that would require major changes to
5334
* the VFS/Vnode OPs.
5335
* Set the expiry time large enough so that it won't expire
5336
* until after the callback, then set it correctly, once
5337
* the callback is done. (The delegation will now time
5338
* out whether or not the Recall worked ok. The timeout
5339
* will be extended when ops are done on the delegation
5340
* stateid, up to the timelimit.)
5341
*/
5342
if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0) {
5343
stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) +
5344
NFSRV_LEASEDELTA;
5345
stp->ls_delegtimelimit = NFSD_MONOSEC + (6 *
5346
nfsrv_lease) + NFSRV_LEASEDELTA;
5347
stp->ls_flags |= NFSLCK_DELEGRECALL;
5348
}
5349
stp->ls_lastrecall = time_uptime + 1;
5350
5351
/*
5352
* Loop NFSRV_CBRETRYCNT times while the CBRecall replies
5353
* NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done
5354
* in order to try and avoid a race that could happen
5355
* when a CBRecall request passed the Open reply with
5356
* the delegation in it when transitting the network.
5357
* Since nfsrv_docallback will sleep, don't use stp after
5358
* the call.
5359
*/
5360
NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid,
5361
sizeof (tstateid));
5362
NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh,
5363
sizeof (tfh));
5364
NFSUNLOCKSTATE();
5365
if (*haslockp) {
5366
*haslockp = 0;
5367
NFSLOCKV4ROOTMUTEX();
5368
nfsv4_unlock(&nfsv4rootfs_lock, 1);
5369
NFSUNLOCKV4ROOTMUTEX();
5370
}
5371
retrycnt = 0;
5372
do {
5373
error = nfsrv_docallback(clp, NFSV4OP_CBRECALL,
5374
&tstateid, 0, &tfh, NULL, NULL, 0, p);
5375
retrycnt++;
5376
} while ((error == NFSERR_BADSTATEID ||
5377
error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT);
5378
error = NFSERR_DELAY;
5379
goto out;
5380
}
5381
5382
if (clp->lc_expiry >= NFSD_MONOSEC &&
5383
stp->ls_delegtime >= NFSD_MONOSEC) {
5384
NFSUNLOCKSTATE();
5385
/*
5386
* A recall has been done, but it has not yet expired.
5387
* So, RETURN_DELAY.
5388
*/
5389
if (*haslockp) {
5390
*haslockp = 0;
5391
NFSLOCKV4ROOTMUTEX();
5392
nfsv4_unlock(&nfsv4rootfs_lock, 1);
5393
NFSUNLOCKV4ROOTMUTEX();
5394
}
5395
error = NFSERR_DELAY;
5396
goto out;
5397
}
5398
5399
/*
5400
* If we don't yet have the lock, just get it and then return,
5401
* since we need that before deleting expired state, such as
5402
* this delegation.
5403
* When getting the lock, unlock the vnode, so other nfsds that
5404
* are in progress, won't get stuck waiting for the vnode lock.
5405
*/
5406
if (*haslockp == 0) {
5407
NFSUNLOCKSTATE();
5408
if (vp != NULL) {
5409
lktype = NFSVOPISLOCKED(vp);
5410
NFSVOPUNLOCK(vp);
5411
}
5412
NFSLOCKV4ROOTMUTEX();
5413
nfsv4_relref(&nfsv4rootfs_lock);
5414
do {
5415
gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
5416
NFSV4ROOTLOCKMUTEXPTR, NULL);
5417
} while (!gotlock);
5418
NFSUNLOCKV4ROOTMUTEX();
5419
*haslockp = 1;
5420
if (vp != NULL) {
5421
NFSVOPLOCK(vp, lktype | LK_RETRY);
5422
if (VN_IS_DOOMED(vp)) {
5423
*haslockp = 0;
5424
NFSLOCKV4ROOTMUTEX();
5425
nfsv4_unlock(&nfsv4rootfs_lock, 1);
5426
NFSUNLOCKV4ROOTMUTEX();
5427
error = NFSERR_PERM;
5428
goto out;
5429
}
5430
}
5431
error = -1;
5432
goto out;
5433
}
5434
5435
NFSUNLOCKSTATE();
5436
/*
5437
* Ok, we can delete the expired delegation.
5438
* First, write the Revoke record to stable storage and then
5439
* clear out the conflict.
5440
* Since all other nfsd threads are now blocked, we can safely
5441
* sleep without the state changing.
5442
*/
5443
nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
5444
nfsrv_backupstable();
5445
if (clp->lc_expiry < NFSD_MONOSEC) {
5446
nfsrv_cleanclient(clp, p, false, NULL);
5447
nfsrv_freedeleglist(&clp->lc_deleg);
5448
nfsrv_freedeleglist(&clp->lc_olddeleg);
5449
LIST_REMOVE(clp, lc_hash);
5450
zapped_clp = 1;
5451
} else {
5452
nfsrv_freedeleg(stp);
5453
zapped_clp = 0;
5454
}
5455
if (zapped_clp)
5456
nfsrv_zapclient(clp, p);
5457
error = -1;
5458
5459
out:
5460
NFSEXITCODE(error);
5461
return (error);
5462
}
5463
5464
/*
5465
* Check for a remove allowed, if remove is set to 1 and get rid of
5466
* delegations.
5467
*/
5468
int
5469
nfsrv_checkremove(vnode_t vp, int remove, struct nfsrv_descript *nd,
5470
nfsquad_t clientid, NFSPROC_T *p)
5471
{
5472
struct nfsclient *clp;
5473
struct nfsstate *stp;
5474
struct nfslockfile *lfp;
5475
int error, haslock = 0;
5476
fhandle_t nfh;
5477
5478
clp = NULL;
5479
/*
5480
* First, get the lock file structure.
5481
* (A return of -1 means no associated state, so remove ok.)
5482
*/
5483
error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5484
tryagain:
5485
NFSLOCKSTATE();
5486
if (error == 0 && clientid.qval != 0)
5487
error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
5488
(nfsquad_t)((u_quad_t)0), 0, nd, p);
5489
if (!error)
5490
error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5491
if (error) {
5492
NFSUNLOCKSTATE();
5493
if (haslock) {
5494
NFSLOCKV4ROOTMUTEX();
5495
nfsv4_unlock(&nfsv4rootfs_lock, 1);
5496
NFSUNLOCKV4ROOTMUTEX();
5497
}
5498
if (error == -1)
5499
error = 0;
5500
goto out;
5501
}
5502
5503
/*
5504
* Now, we must Recall any delegations.
5505
*/
5506
error = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
5507
if (error) {
5508
/*
5509
* nfsrv_cleandeleg() unlocks state for non-zero
5510
* return.
5511
*/
5512
if (error == -1)
5513
goto tryagain;
5514
if (haslock) {
5515
NFSLOCKV4ROOTMUTEX();
5516
nfsv4_unlock(&nfsv4rootfs_lock, 1);
5517
NFSUNLOCKV4ROOTMUTEX();
5518
}
5519
goto out;
5520
}
5521
5522
/*
5523
* Now, look for a conflicting open share.
5524
*/
5525
if (remove) {
5526
/*
5527
* If the entry in the directory was the last reference to the
5528
* corresponding filesystem object, the object can be destroyed
5529
* */
5530
if(lfp->lf_usecount>1)
5531
LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
5532
if (stp->ls_flags & NFSLCK_WRITEDENY) {
5533
error = NFSERR_FILEOPEN;
5534
break;
5535
}
5536
}
5537
}
5538
5539
NFSUNLOCKSTATE();
5540
if (haslock) {
5541
NFSLOCKV4ROOTMUTEX();
5542
nfsv4_unlock(&nfsv4rootfs_lock, 1);
5543
NFSUNLOCKV4ROOTMUTEX();
5544
}
5545
5546
out:
5547
NFSEXITCODE(error);
5548
return (error);
5549
}
5550
5551
/*
5552
* Clear out all delegations for the file referred to by lfp.
5553
* May return NFSERR_DELAY, if there will be a delay waiting for
5554
* delegations to expire.
5555
* Returns -1 to indicate it slept while recalling a delegation.
5556
* This function has the side effect of deleting the nfslockfile structure,
5557
* if it no longer has associated state and didn't have to sleep.
5558
* Unlocks State before a non-zero value is returned.
5559
*/
5560
static int
5561
nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
5562
struct nfsclient *clp, int *haslockp, NFSPROC_T *p)
5563
{
5564
struct nfsstate *stp, *nstp;
5565
int ret = 0;
5566
5567
stp = LIST_FIRST(&lfp->lf_deleg);
5568
while (stp != LIST_END(&lfp->lf_deleg)) {
5569
nstp = LIST_NEXT(stp, ls_file);
5570
if (stp->ls_clp != clp) {
5571
ret = nfsrv_delegconflict(stp, haslockp, p, vp);
5572
if (ret) {
5573
/*
5574
* nfsrv_delegconflict() unlocks state
5575
* when it returns non-zero.
5576
*/
5577
goto out;
5578
}
5579
}
5580
stp = nstp;
5581
}
5582
out:
5583
NFSEXITCODE(ret);
5584
return (ret);
5585
}
5586
5587
/*
5588
* There are certain operations that, when being done outside of NFSv4,
5589
* require that any NFSv4 delegation for the file be recalled.
5590
* This function is to be called for those cases:
5591
* VOP_RENAME() - When a delegation is being recalled for any reason,
5592
* the client may have to do Opens against the server, using the file's
5593
* final component name. If the file has been renamed on the server,
5594
* that component name will be incorrect and the Open will fail.
5595
* VOP_REMOVE() - Theoretically, a client could Open a file after it has
5596
* been removed on the server, if there is a delegation issued to
5597
* that client for the file. I say "theoretically" since clients
5598
* normally do an Access Op before the Open and that Access Op will
5599
* fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so
5600
* they will detect the file's removal in the same manner. (There is
5601
* one case where RFC3530 allows a client to do an Open without first
5602
* doing an Access Op, which is passage of a check against the ACE
5603
* returned with a Write delegation, but current practice is to ignore
5604
* the ACE and always do an Access Op.)
5605
* Since the functions can only be called with an unlocked vnode, this
5606
* can't be done at this time.
5607
* VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range
5608
* locks locally in the client, which are not visible to the server. To
5609
* deal with this, issuing of delegations for a vnode must be disabled
5610
* and all delegations for the vnode recalled. This is done via the
5611
* second function, using the VV_DISABLEDELEG vflag on the vnode.
5612
*/
5613
void
5614
nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
5615
{
5616
time_t starttime;
5617
int error;
5618
5619
/*
5620
* First, check to see if the server is currently running and it has
5621
* been called for a regular file when issuing delegations.
5622
*/
5623
if (NFSD_VNET(nfsrv_numnfsd) == 0 || vp->v_type != VREG ||
5624
nfsrv_issuedelegs == 0)
5625
return;
5626
5627
KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp));
5628
/*
5629
* First, get a reference on the nfsv4rootfs_lock so that an
5630
* exclusive lock cannot be acquired by another thread.
5631
*/
5632
NFSLOCKV4ROOTMUTEX();
5633
nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
5634
NFSUNLOCKV4ROOTMUTEX();
5635
5636
/*
5637
* Now, call nfsrv_checkremove() in a loop while it returns
5638
* NFSERR_DELAY. Return upon any other error or when timed out.
5639
*/
5640
starttime = NFSD_MONOSEC;
5641
do {
5642
if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
5643
error = nfsrv_checkremove(vp, 0, NULL,
5644
(nfsquad_t)((u_quad_t)0), p);
5645
NFSVOPUNLOCK(vp);
5646
} else
5647
error = EPERM;
5648
if (error == NFSERR_DELAY) {
5649
if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO)
5650
break;
5651
/* Sleep for a short period of time */
5652
(void) nfs_catnap(PZERO, 0, "nfsremove");
5653
}
5654
} while (error == NFSERR_DELAY);
5655
NFSLOCKV4ROOTMUTEX();
5656
nfsv4_relref(&nfsv4rootfs_lock);
5657
NFSUNLOCKV4ROOTMUTEX();
5658
}
5659
5660
void
5661
nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p)
5662
{
5663
5664
#ifdef VV_DISABLEDELEG
5665
/*
5666
* First, flag issuance of delegations disabled.
5667
*/
5668
atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG);
5669
#endif
5670
5671
/*
5672
* Then call nfsd_recalldelegation() to get rid of all extant
5673
* delegations.
5674
*/
5675
nfsd_recalldelegation(vp, p);
5676
}
5677
5678
/*
5679
* Check for conflicting locks, etc. and then get rid of delegations.
5680
* (At one point I thought that I should get rid of delegations for any
5681
* Setattr, since it could potentially disallow the I/O op (read or write)
5682
* allowed by the delegation. However, Setattr Ops that aren't changing
5683
* the size get a stateid of all 0s, so you can't tell if it is a delegation
5684
* for the same client or a different one, so I decided to only get rid
5685
* of delegations for other clients when the size is being changed.)
5686
* In general, a Setattr can disable NFS I/O Ops that are outstanding, such
5687
* as Write backs, even if there is no delegation, so it really isn't any
5688
* different?)
5689
*/
5690
int
5691
nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd,
5692
nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp,
5693
struct nfsexstuff *exp, NFSPROC_T *p)
5694
{
5695
struct nfsstate st, *stp = &st;
5696
struct nfslock lo, *lop = &lo;
5697
int error = 0;
5698
nfsquad_t clientid;
5699
5700
if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) {
5701
stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5702
lop->lo_first = nvap->na_size;
5703
} else {
5704
stp->ls_flags = 0;
5705
lop->lo_first = 0;
5706
}
5707
if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) ||
5708
NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) ||
5709
NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) ||
5710
NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL))
5711
stp->ls_flags |= NFSLCK_SETATTR;
5712
if (stp->ls_flags == 0)
5713
goto out;
5714
lop->lo_end = NFS64BITSSET;
5715
lop->lo_flags = NFSLCK_WRITE;
5716
stp->ls_ownerlen = 0;
5717
stp->ls_op = NULL;
5718
stp->ls_uid = nd->nd_cred->cr_uid;
5719
stp->ls_stateid.seqid = stateidp->seqid;
5720
clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0];
5721
clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1];
5722
stp->ls_stateid.other[2] = stateidp->other[2];
5723
error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
5724
stateidp, exp, nd, p);
5725
5726
out:
5727
NFSEXITCODE2(error, nd);
5728
return (error);
5729
}
5730
5731
/*
5732
* Check for a write delegation and do a CBGETATTR if there is one, updating
5733
* the attributes, as required.
5734
* Should I return an error if I can't get the attributes? (For now, I'll
5735
* just return ok.
5736
*/
5737
int
5738
nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
5739
struct nfsvattr *nvap, nfsattrbit_t *attrbitp, NFSPROC_T *p)
5740
{
5741
struct nfsstate *stp;
5742
struct nfslockfile *lfp;
5743
struct nfsclient *clp;
5744
struct nfsvattr nva;
5745
fhandle_t nfh;
5746
int error = 0;
5747
nfsattrbit_t cbbits;
5748
u_quad_t delegfilerev;
5749
5750
NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits);
5751
if (!NFSNONZERO_ATTRBIT(&cbbits))
5752
goto out;
5753
if (nfsrv_writedelegcnt == 0)
5754
goto out;
5755
5756
/*
5757
* Get the lock file structure.
5758
* (A return of -1 means no associated state, so return ok.)
5759
*/
5760
error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5761
NFSLOCKSTATE();
5762
if (!error)
5763
error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5764
if (error) {
5765
NFSUNLOCKSTATE();
5766
if (error == -1)
5767
error = 0;
5768
goto out;
5769
}
5770
5771
/*
5772
* Now, look for a write delegation.
5773
*/
5774
LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
5775
if (stp->ls_flags & NFSLCK_DELEGWRITE)
5776
break;
5777
}
5778
if (stp == LIST_END(&lfp->lf_deleg)) {
5779
NFSUNLOCKSTATE();
5780
goto out;
5781
}
5782
clp = stp->ls_clp;
5783
5784
/* If the clientid is not confirmed, ignore the delegation. */
5785
if (clp->lc_flags & LCL_NEEDSCONFIRM) {
5786
NFSUNLOCKSTATE();
5787
goto out;
5788
}
5789
5790
delegfilerev = stp->ls_filerev;
5791
/*
5792
* If the Write delegation was issued as a part of this Compound RPC
5793
* or if we have an Implied Clientid (used in a previous Op in this
5794
* compound) and it is the client the delegation was issued to,
5795
* just return ok.
5796
* I also assume that it is from the same client iff the network
5797
* host IP address is the same as the callback address. (Not
5798
* exactly correct by the RFC, but avoids a lot of Getattr
5799
* callbacks.)
5800
*/
5801
if (nd->nd_compref == stp->ls_compref ||
5802
((nd->nd_flag & ND_IMPLIEDCLID) &&
5803
clp->lc_clientid.qval == nd->nd_clientid.qval) ||
5804
nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) {
5805
NFSUNLOCKSTATE();
5806
goto out;
5807
}
5808
5809
/*
5810
* We are now done with the delegation state structure,
5811
* so the statelock can be released and we can now tsleep().
5812
*/
5813
5814
/*
5815
* Now, we must do the CB Getattr callback, to see if Change or Size
5816
* has changed.
5817
*/
5818
if (clp->lc_expiry >= NFSD_MONOSEC) {
5819
NFSUNLOCKSTATE();
5820
NFSVNO_ATTRINIT(&nva);
5821
nva.na_filerev = NFS64BITSSET;
5822
error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL,
5823
0, &nfh, &nva, &cbbits, 0, p);
5824
if (!error) {
5825
if ((nva.na_filerev != NFS64BITSSET &&
5826
nva.na_filerev > delegfilerev) ||
5827
(NFSVNO_ISSETSIZE(&nva) &&
5828
nva.na_size != nvap->na_size)) {
5829
error = nfsvno_updfilerev(vp, nvap, nd, p);
5830
if (NFSVNO_ISSETSIZE(&nva))
5831
nvap->na_size = nva.na_size;
5832
}
5833
} else
5834
error = 0; /* Ignore callback errors for now. */
5835
} else {
5836
NFSUNLOCKSTATE();
5837
}
5838
5839
out:
5840
NFSEXITCODE2(error, nd);
5841
return (error);
5842
}
5843
5844
/*
5845
* This function looks for openowners that haven't had any opens for
5846
* a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS
5847
* is set.
5848
*/
5849
void
5850
nfsrv_throwawayopens(NFSPROC_T *p)
5851
{
5852
struct nfsclient *clp, *nclp;
5853
struct nfsstate *stp, *nstp;
5854
int i;
5855
5856
NFSLOCKSTATE();
5857
NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NOOPENS;
5858
/*
5859
* For each client...
5860
*/
5861
for (i = 0; i < nfsrv_clienthashsize; i++) {
5862
LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash,
5863
nclp) {
5864
LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) {
5865
if (LIST_EMPTY(&stp->ls_open) &&
5866
(stp->ls_noopens > NFSNOOPEN ||
5867
(nfsrv_openpluslock * 2) >
5868
nfsrv_v4statelimit))
5869
nfsrv_freeopenowner(stp, 0, p);
5870
}
5871
}
5872
}
5873
NFSUNLOCKSTATE();
5874
}
5875
5876
/*
5877
* This function checks to see if the credentials are the same.
5878
* The check for same credentials is needed for state management operations
5879
* for NFSv4.0 or NFSv4.1/4.2 when SP4_MACH_CRED is configured via
5880
* ExchangeID.
5881
* Returns 1 for not same, 0 otherwise.
5882
*/
5883
static int
5884
nfsrv_notsamecredname(int op, struct nfsrv_descript *nd, struct nfsclient *clp)
5885
{
5886
5887
/* Check for the SP4_MACH_CRED case. */
5888
if (op != 0 && nfsrv_checkmachcred(op, nd, clp) != 0)
5889
return (1);
5890
5891
/* For NFSv4.1/4.2, SP4_NONE always allows this. */
5892
if ((nd->nd_flag & ND_NFSV41) != 0)
5893
return (0);
5894
5895
if (nd->nd_flag & ND_GSS) {
5896
if (!(clp->lc_flags & LCL_GSS))
5897
return (1);
5898
if (clp->lc_flags & LCL_NAME) {
5899
if (nd->nd_princlen != clp->lc_namelen ||
5900
NFSBCMP(nd->nd_principal, clp->lc_name,
5901
clp->lc_namelen))
5902
return (1);
5903
else
5904
return (0);
5905
}
5906
if (nd->nd_cred->cr_uid == clp->lc_uid)
5907
return (0);
5908
else
5909
return (1);
5910
} else if (clp->lc_flags & LCL_GSS)
5911
return (1);
5912
/*
5913
* For AUTH_SYS, allow the same uid or root. (This is underspecified
5914
* in RFC3530, which talks about principals, but doesn't say anything
5915
* about uids for AUTH_SYS.)
5916
*/
5917
if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0)
5918
return (0);
5919
else
5920
return (1);
5921
}
5922
5923
/*
5924
* Calculate the lease expiry time.
5925
*/
5926
static time_t
5927
nfsrv_leaseexpiry(void)
5928
{
5929
5930
if (NFSD_VNET(nfsrv_stablefirst).nsf_eograce > NFSD_MONOSEC)
5931
return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA));
5932
return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA);
5933
}
5934
5935
/*
5936
* Delay the delegation timeout as far as ls_delegtimelimit, as required.
5937
*/
5938
static void
5939
nfsrv_delaydelegtimeout(struct nfsstate *stp)
5940
{
5941
5942
if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0)
5943
return;
5944
5945
if ((stp->ls_delegtime + 15) > NFSD_MONOSEC &&
5946
stp->ls_delegtime < stp->ls_delegtimelimit) {
5947
stp->ls_delegtime += nfsrv_lease;
5948
if (stp->ls_delegtime > stp->ls_delegtimelimit)
5949
stp->ls_delegtime = stp->ls_delegtimelimit;
5950
}
5951
}
5952
5953
/*
5954
* This function checks to see if there is any other state associated
5955
* with the openowner for this Open.
5956
* It returns 1 if there is no other state, 0 otherwise.
5957
*/
5958
static int
5959
nfsrv_nootherstate(struct nfsstate *stp)
5960
{
5961
struct nfsstate *tstp;
5962
5963
LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) {
5964
if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock))
5965
return (0);
5966
}
5967
return (1);
5968
}
5969
5970
/*
5971
* Create a list of lock deltas (changes to local byte range locking
5972
* that can be rolled back using the list) and apply the changes via
5973
* nfsvno_advlock(). Optionally, lock the list. It is expected that either
5974
* the rollback or update function will be called after this.
5975
* It returns an error (and rolls back, as required), if any nfsvno_advlock()
5976
* call fails. If it returns an error, it will unlock the list.
5977
*/
5978
static int
5979
nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
5980
uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
5981
{
5982
struct nfslock *lop, *nlop;
5983
int error = 0;
5984
5985
/* Loop through the list of locks. */
5986
lop = LIST_FIRST(&lfp->lf_locallock);
5987
while (first < end && lop != NULL) {
5988
nlop = LIST_NEXT(lop, lo_lckowner);
5989
if (first >= lop->lo_end) {
5990
/* not there yet */
5991
lop = nlop;
5992
} else if (first < lop->lo_first) {
5993
/* new one starts before entry in list */
5994
if (end <= lop->lo_first) {
5995
/* no overlap between old and new */
5996
error = nfsrv_dolocal(vp, lfp, flags,
5997
NFSLCK_UNLOCK, first, end, cfp, p);
5998
if (error != 0)
5999
break;
6000
first = end;
6001
} else {
6002
/* handle fragment overlapped with new one */
6003
error = nfsrv_dolocal(vp, lfp, flags,
6004
NFSLCK_UNLOCK, first, lop->lo_first, cfp,
6005
p);
6006
if (error != 0)
6007
break;
6008
first = lop->lo_first;
6009
}
6010
} else {
6011
/* new one overlaps this entry in list */
6012
if (end <= lop->lo_end) {
6013
/* overlaps all of new one */
6014
error = nfsrv_dolocal(vp, lfp, flags,
6015
lop->lo_flags, first, end, cfp, p);
6016
if (error != 0)
6017
break;
6018
first = end;
6019
} else {
6020
/* handle fragment overlapped with new one */
6021
error = nfsrv_dolocal(vp, lfp, flags,
6022
lop->lo_flags, first, lop->lo_end, cfp, p);
6023
if (error != 0)
6024
break;
6025
first = lop->lo_end;
6026
lop = nlop;
6027
}
6028
}
6029
}
6030
if (first < end && error == 0)
6031
/* handle fragment past end of list */
6032
error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first,
6033
end, cfp, p);
6034
6035
NFSEXITCODE(error);
6036
return (error);
6037
}
6038
6039
/*
6040
* Local lock unlock. Unlock all byte ranges that are no longer locked
6041
* by NFSv4. To do this, unlock any subranges of first-->end that
6042
* do not overlap with the byte ranges of any lock in the lfp->lf_lock
6043
* list. This list has all locks for the file held by other
6044
* <clientid, lockowner> tuples. The list is ordered by increasing
6045
* lo_first value, but may have entries that overlap each other, for
6046
* the case of read locks.
6047
*/
6048
static void
6049
nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first,
6050
uint64_t init_end, NFSPROC_T *p)
6051
{
6052
struct nfslock *lop;
6053
uint64_t first, end, prevfirst __unused;
6054
6055
first = init_first;
6056
end = init_end;
6057
while (first < init_end) {
6058
/* Loop through all nfs locks, adjusting first and end */
6059
prevfirst = 0;
6060
LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
6061
KASSERT(prevfirst <= lop->lo_first,
6062
("nfsv4 locks out of order"));
6063
KASSERT(lop->lo_first < lop->lo_end,
6064
("nfsv4 bogus lock"));
6065
prevfirst = lop->lo_first;
6066
if (first >= lop->lo_first &&
6067
first < lop->lo_end)
6068
/*
6069
* Overlaps with initial part, so trim
6070
* off that initial part by moving first past
6071
* it.
6072
*/
6073
first = lop->lo_end;
6074
else if (end > lop->lo_first &&
6075
lop->lo_first > first) {
6076
/*
6077
* This lock defines the end of the
6078
* segment to unlock, so set end to the
6079
* start of it and break out of the loop.
6080
*/
6081
end = lop->lo_first;
6082
break;
6083
}
6084
if (first >= end)
6085
/*
6086
* There is no segment left to do, so
6087
* break out of this loop and then exit
6088
* the outer while() since first will be set
6089
* to end, which must equal init_end here.
6090
*/
6091
break;
6092
}
6093
if (first < end) {
6094
/* Unlock this segment */
6095
(void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK,
6096
NFSLCK_READ, first, end, NULL, p);
6097
nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK,
6098
first, end);
6099
}
6100
/*
6101
* Now move past this segment and look for any further
6102
* segment in the range, if there is one.
6103
*/
6104
first = end;
6105
end = init_end;
6106
}
6107
}
6108
6109
/*
6110
* Do the local lock operation and update the rollback list, as required.
6111
* Perform the rollback and return the error if nfsvno_advlock() fails.
6112
*/
6113
static int
6114
nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags,
6115
uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
6116
{
6117
struct nfsrollback *rlp;
6118
int error = 0, ltype, oldltype;
6119
6120
if (flags & NFSLCK_WRITE)
6121
ltype = F_WRLCK;
6122
else if (flags & NFSLCK_READ)
6123
ltype = F_RDLCK;
6124
else
6125
ltype = F_UNLCK;
6126
if (oldflags & NFSLCK_WRITE)
6127
oldltype = F_WRLCK;
6128
else if (oldflags & NFSLCK_READ)
6129
oldltype = F_RDLCK;
6130
else
6131
oldltype = F_UNLCK;
6132
if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK))
6133
/* nothing to do */
6134
goto out;
6135
error = nfsvno_advlock(vp, ltype, first, end, p);
6136
if (error != 0) {
6137
if (cfp != NULL) {
6138
cfp->cl_clientid.lval[0] = 0;
6139
cfp->cl_clientid.lval[1] = 0;
6140
cfp->cl_first = 0;
6141
cfp->cl_end = NFS64BITSSET;
6142
cfp->cl_flags = NFSLCK_WRITE;
6143
cfp->cl_ownerlen = 5;
6144
NFSBCOPY("LOCAL", cfp->cl_owner, 5);
6145
}
6146
nfsrv_locallock_rollback(vp, lfp, p);
6147
} else if (ltype != F_UNLCK) {
6148
rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK,
6149
M_WAITOK);
6150
rlp->rlck_first = first;
6151
rlp->rlck_end = end;
6152
rlp->rlck_type = oldltype;
6153
LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list);
6154
}
6155
6156
out:
6157
NFSEXITCODE(error);
6158
return (error);
6159
}
6160
6161
/*
6162
* Roll back local lock changes and free up the rollback list.
6163
*/
6164
static void
6165
nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p)
6166
{
6167
struct nfsrollback *rlp, *nrlp;
6168
6169
LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) {
6170
(void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first,
6171
rlp->rlck_end, p);
6172
free(rlp, M_NFSDROLLBACK);
6173
}
6174
LIST_INIT(&lfp->lf_rollback);
6175
}
6176
6177
/*
6178
* Update local lock list and delete rollback list (ie now committed to the
6179
* local locks). Most of the work is done by the internal function.
6180
*/
6181
static void
6182
nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first,
6183
uint64_t end)
6184
{
6185
struct nfsrollback *rlp, *nrlp;
6186
struct nfslock *new_lop, *other_lop;
6187
6188
new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK);
6189
if (flags & (NFSLCK_READ | NFSLCK_WRITE))
6190
other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK,
6191
M_WAITOK);
6192
else
6193
other_lop = NULL;
6194
new_lop->lo_flags = flags;
6195
new_lop->lo_first = first;
6196
new_lop->lo_end = end;
6197
nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp);
6198
if (new_lop != NULL)
6199
free(new_lop, M_NFSDLOCK);
6200
if (other_lop != NULL)
6201
free(other_lop, M_NFSDLOCK);
6202
6203
/* and get rid of the rollback list */
6204
LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp)
6205
free(rlp, M_NFSDROLLBACK);
6206
LIST_INIT(&lfp->lf_rollback);
6207
}
6208
6209
/*
6210
* Lock the struct nfslockfile for local lock updating.
6211
*/
6212
static void
6213
nfsrv_locklf(struct nfslockfile *lfp)
6214
{
6215
int gotlock;
6216
6217
/* lf_usecount ensures *lfp won't be free'd */
6218
lfp->lf_usecount++;
6219
do {
6220
gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL,
6221
NFSSTATEMUTEXPTR, NULL);
6222
} while (gotlock == 0);
6223
lfp->lf_usecount--;
6224
}
6225
6226
/*
6227
* Unlock the struct nfslockfile after local lock updating.
6228
*/
6229
static void
6230
nfsrv_unlocklf(struct nfslockfile *lfp)
6231
{
6232
6233
nfsv4_unlock(&lfp->lf_locallock_lck, 0);
6234
}
6235
6236
/*
6237
* Clear out all state for the NFSv4 server.
6238
* Must be called by a thread that can sleep when no nfsds are running.
6239
*/
6240
void
6241
nfsrv_throwawayallstate(NFSPROC_T *p)
6242
{
6243
struct nfsclient *clp, *nclp;
6244
struct nfslockfile *lfp, *nlfp;
6245
int i;
6246
6247
/*
6248
* For each client, clean out the state and then free the structure.
6249
*/
6250
for (i = 0; i < nfsrv_clienthashsize; i++) {
6251
LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash,
6252
nclp) {
6253
nfsrv_cleanclient(clp, p, false, NULL);
6254
nfsrv_freedeleglist(&clp->lc_deleg);
6255
nfsrv_freedeleglist(&clp->lc_olddeleg);
6256
free(clp->lc_stateid, M_NFSDCLIENT);
6257
free(clp, M_NFSDCLIENT);
6258
}
6259
}
6260
6261
/*
6262
* Also, free up any remaining lock file structures.
6263
*/
6264
for (i = 0; i < nfsrv_lockhashsize; i++) {
6265
LIST_FOREACH_SAFE(lfp, &NFSD_VNET(nfslockhash)[i], lf_hash,
6266
nlfp) {
6267
printf("nfsd unload: fnd a lock file struct\n");
6268
nfsrv_freenfslockfile(lfp);
6269
}
6270
}
6271
6272
/* And get rid of the deviceid structures and layouts. */
6273
nfsrv_freealllayoutsanddevids();
6274
}
6275
6276
/*
6277
* Check the sequence# for the session and slot provided as an argument.
6278
* Also, renew the lease if the session will return NFS_OK.
6279
*/
6280
int
6281
nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid,
6282
uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this,
6283
uint32_t *sflagsp, NFSPROC_T *p)
6284
{
6285
struct nfsdsession *sep;
6286
struct nfssessionhash *shp;
6287
int error;
6288
6289
shp = NFSSESSIONHASH(nd->nd_sessionid);
6290
NFSLOCKSESSION(shp);
6291
sep = nfsrv_findsession(nd->nd_sessionid);
6292
if (sep == NULL) {
6293
NFSUNLOCKSESSION(shp);
6294
return (NFSERR_BADSESSION);
6295
}
6296
error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp,
6297
sep->sess_slots, NULL, NFSV4_SLOTS - 1);
6298
if (error != 0) {
6299
NFSUNLOCKSESSION(shp);
6300
return (error);
6301
}
6302
if (cache_this != 0)
6303
nd->nd_flag |= ND_SAVEREPLY;
6304
/* Renew the lease. */
6305
sep->sess_clp->lc_expiry = nfsrv_leaseexpiry();
6306
nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
6307
nd->nd_flag |= ND_IMPLIEDCLID;
6308
6309
/* Handle the SP4_MECH_CRED case for NFSv4.1/4.2. */
6310
if ((sep->sess_clp->lc_flags & LCL_MACHCRED) != 0 &&
6311
(nd->nd_flag & (ND_GSSINTEGRITY | ND_GSSPRIVACY)) != 0 &&
6312
nd->nd_princlen == sep->sess_clp->lc_namelen &&
6313
!NFSBCMP(sep->sess_clp->lc_name, nd->nd_principal,
6314
nd->nd_princlen)) {
6315
nd->nd_flag |= ND_MACHCRED;
6316
NFSSET_OPBIT(&nd->nd_allowops, &sep->sess_clp->lc_allowops);
6317
}
6318
6319
/* Save maximum request and reply sizes. */
6320
nd->nd_maxreq = sep->sess_maxreq;
6321
nd->nd_maxresp = sep->sess_maxresp;
6322
6323
*sflagsp = 0;
6324
if (sep->sess_clp->lc_req.nr_client == NULL ||
6325
(sep->sess_clp->lc_flags & LCL_CBDOWN) != 0)
6326
*sflagsp |= NFSV4SEQ_CBPATHDOWN;
6327
NFSUNLOCKSESSION(shp);
6328
if (error == NFSERR_EXPIRED) {
6329
*sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED;
6330
error = 0;
6331
} else if (error == NFSERR_ADMINREVOKED) {
6332
*sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED;
6333
error = 0;
6334
}
6335
*highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1;
6336
return (0);
6337
}
6338
6339
/*
6340
* Check/set reclaim complete for this session/clientid.
6341
*/
6342
int
6343
nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd, int onefs)
6344
{
6345
struct nfsdsession *sep;
6346
struct nfssessionhash *shp;
6347
int error = 0;
6348
6349
shp = NFSSESSIONHASH(nd->nd_sessionid);
6350
NFSLOCKSTATE();
6351
NFSLOCKSESSION(shp);
6352
sep = nfsrv_findsession(nd->nd_sessionid);
6353
if (sep == NULL) {
6354
NFSUNLOCKSESSION(shp);
6355
NFSUNLOCKSTATE();
6356
return (NFSERR_BADSESSION);
6357
}
6358
6359
if (onefs != 0)
6360
sep->sess_clp->lc_flags |= LCL_RECLAIMONEFS;
6361
/* Check to see if reclaim complete has already happened. */
6362
else if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)
6363
error = NFSERR_COMPLETEALREADY;
6364
else {
6365
sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE;
6366
nfsrv_markreclaim(sep->sess_clp);
6367
}
6368
NFSUNLOCKSESSION(shp);
6369
NFSUNLOCKSTATE();
6370
return (error);
6371
}
6372
6373
/*
6374
* Cache the reply in a session slot.
6375
*/
6376
void
6377
nfsrv_cache_session(struct nfsrv_descript *nd, struct mbuf **m)
6378
{
6379
struct nfsdsession *sep;
6380
struct nfssessionhash *shp;
6381
char *buf, *cp;
6382
#ifdef INET
6383
struct sockaddr_in *sin;
6384
#endif
6385
#ifdef INET6
6386
struct sockaddr_in6 *sin6;
6387
#endif
6388
6389
shp = NFSSESSIONHASH(nd->nd_sessionid);
6390
NFSLOCKSESSION(shp);
6391
sep = nfsrv_findsession(nd->nd_sessionid);
6392
if (sep == NULL) {
6393
NFSUNLOCKSESSION(shp);
6394
if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags &
6395
NFSNSF_GRACEOVER) != 0) {
6396
buf = malloc(INET6_ADDRSTRLEN, M_TEMP, M_WAITOK);
6397
switch (nd->nd_nam->sa_family) {
6398
#ifdef INET
6399
case AF_INET:
6400
sin = (struct sockaddr_in *)nd->nd_nam;
6401
cp = inet_ntop(sin->sin_family,
6402
&sin->sin_addr.s_addr, buf,
6403
INET6_ADDRSTRLEN);
6404
break;
6405
#endif
6406
#ifdef INET6
6407
case AF_INET6:
6408
sin6 = (struct sockaddr_in6 *)nd->nd_nam;
6409
cp = inet_ntop(sin6->sin6_family,
6410
&sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
6411
break;
6412
#endif
6413
default:
6414
cp = NULL;
6415
}
6416
if (cp != NULL)
6417
printf("nfsrv_cache_session: no session "
6418
"IPaddr=%s, check NFS clients for unique "
6419
"/etc/hostid's\n", cp);
6420
else
6421
printf("nfsrv_cache_session: no session, "
6422
"check NFS clients for unique "
6423
"/etc/hostid's\n");
6424
free(buf, M_TEMP);
6425
}
6426
m_freem(*m);
6427
return;
6428
}
6429
nfsv4_seqsess_cacherep(nd->nd_slotid, sep->sess_slots, nd->nd_repstat,
6430
m);
6431
NFSUNLOCKSESSION(shp);
6432
}
6433
6434
/*
6435
* Search for a session that matches the sessionid.
6436
*/
6437
static struct nfsdsession *
6438
nfsrv_findsession(uint8_t *sessionid)
6439
{
6440
struct nfsdsession *sep;
6441
struct nfssessionhash *shp;
6442
6443
shp = NFSSESSIONHASH(sessionid);
6444
LIST_FOREACH(sep, &shp->list, sess_hash) {
6445
if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID))
6446
break;
6447
}
6448
return (sep);
6449
}
6450
6451
/*
6452
* Destroy a session.
6453
*/
6454
int
6455
nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid)
6456
{
6457
int error, igotlock, samesess;
6458
6459
samesess = 0;
6460
if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID) &&
6461
(nd->nd_flag & ND_HASSEQUENCE) != 0) {
6462
samesess = 1;
6463
if ((nd->nd_flag & ND_LASTOP) == 0)
6464
return (NFSERR_BADSESSION);
6465
}
6466
6467
/* Lock out other nfsd threads */
6468
NFSLOCKV4ROOTMUTEX();
6469
nfsv4_relref(&nfsv4rootfs_lock);
6470
do {
6471
igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
6472
NFSV4ROOTLOCKMUTEXPTR, NULL);
6473
} while (igotlock == 0);
6474
NFSUNLOCKV4ROOTMUTEX();
6475
6476
error = nfsrv_freesession(nd, NULL, sessionid, false, NULL);
6477
if (error == 0 && samesess != 0)
6478
nd->nd_flag &= ~ND_HASSEQUENCE;
6479
6480
NFSLOCKV4ROOTMUTEX();
6481
nfsv4_unlock(&nfsv4rootfs_lock, 1);
6482
NFSUNLOCKV4ROOTMUTEX();
6483
return (error);
6484
}
6485
6486
/*
6487
* Bind a connection to a session.
6488
* For now, only certain variants are supported, since the current session
6489
* structure can only handle a single backchannel entry, which will be
6490
* applied to all connections if it is set.
6491
*/
6492
int
6493
nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp)
6494
{
6495
struct nfssessionhash *shp;
6496
struct nfsdsession *sep;
6497
struct nfsclient *clp;
6498
SVCXPRT *savxprt;
6499
int error;
6500
6501
error = 0;
6502
savxprt = NULL;
6503
shp = NFSSESSIONHASH(sessionid);
6504
NFSLOCKSTATE();
6505
NFSLOCKSESSION(shp);
6506
sep = nfsrv_findsession(sessionid);
6507
if (sep != NULL) {
6508
clp = sep->sess_clp;
6509
error = nfsrv_checkmachcred(NFSV4OP_BINDCONNTOSESS, nd, clp);
6510
if (error != 0)
6511
goto out;
6512
if (*foreaftp == NFSCDFC4_BACK ||
6513
*foreaftp == NFSCDFC4_BACK_OR_BOTH ||
6514
*foreaftp == NFSCDFC4_FORE_OR_BOTH) {
6515
/* Try to set up a backchannel. */
6516
if (clp->lc_req.nr_client == NULL) {
6517
NFSD_DEBUG(2, "nfsrv_bindconnsess: acquire "
6518
"backchannel\n");
6519
clp->lc_req.nr_client = (struct __rpc_client *)
6520
clnt_bck_create(nd->nd_xprt->xp_socket,
6521
sep->sess_cbprogram, NFSV4_CBVERS);
6522
}
6523
if (clp->lc_req.nr_client != NULL) {
6524
NFSD_DEBUG(2, "nfsrv_bindconnsess: set up "
6525
"backchannel\n");
6526
savxprt = sep->sess_cbsess.nfsess_xprt;
6527
SVC_ACQUIRE(nd->nd_xprt);
6528
CLNT_ACQUIRE(clp->lc_req.nr_client);
6529
nd->nd_xprt->xp_p2 = clp->lc_req.nr_client;
6530
/* Disable idle timeout. */
6531
nd->nd_xprt->xp_idletimeout = 0;
6532
sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
6533
sep->sess_crflags |= NFSV4CRSESS_CONNBACKCHAN;
6534
clp->lc_flags |= LCL_DONEBINDCONN |
6535
LCL_NEEDSCBNULL;
6536
clp->lc_flags &= ~LCL_CBDOWN;
6537
if (*foreaftp == NFSCDFS4_BACK)
6538
*foreaftp = NFSCDFS4_BACK;
6539
else
6540
*foreaftp = NFSCDFS4_BOTH;
6541
} else if (*foreaftp != NFSCDFC4_BACK) {
6542
NFSD_DEBUG(2, "nfsrv_bindconnsess: can't set "
6543
"up backchannel\n");
6544
sep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN;
6545
clp->lc_flags |= LCL_DONEBINDCONN;
6546
*foreaftp = NFSCDFS4_FORE;
6547
} else {
6548
error = NFSERR_NOTSUPP;
6549
printf("nfsrv_bindconnsess: Can't add "
6550
"backchannel\n");
6551
}
6552
} else {
6553
NFSD_DEBUG(2, "nfsrv_bindconnsess: Set forechannel\n");
6554
clp->lc_flags |= LCL_DONEBINDCONN;
6555
*foreaftp = NFSCDFS4_FORE;
6556
}
6557
} else
6558
error = NFSERR_BADSESSION;
6559
out:
6560
NFSUNLOCKSESSION(shp);
6561
NFSUNLOCKSTATE();
6562
if (savxprt != NULL)
6563
SVC_RELEASE(savxprt);
6564
return (error);
6565
}
6566
6567
/*
6568
* Free up a session structure.
6569
*/
6570
static int
6571
nfsrv_freesession(struct nfsrv_descript *nd, struct nfsdsession *sep,
6572
uint8_t *sessionid, bool locked, SVCXPRT **old_xprtp)
6573
{
6574
struct nfssessionhash *shp;
6575
int i;
6576
6577
if (!locked)
6578
NFSLOCKSTATE();
6579
if (sep == NULL) {
6580
shp = NFSSESSIONHASH(sessionid);
6581
NFSLOCKSESSION(shp);
6582
sep = nfsrv_findsession(sessionid);
6583
} else {
6584
shp = NFSSESSIONHASH(sep->sess_sessionid);
6585
NFSLOCKSESSION(shp);
6586
}
6587
if (sep != NULL) {
6588
/* Check for the SP4_MACH_CRED case. */
6589
if (nd != NULL && nfsrv_checkmachcred(NFSV4OP_DESTROYSESSION,
6590
nd, sep->sess_clp) != 0) {
6591
NFSUNLOCKSESSION(shp);
6592
if (!locked)
6593
NFSUNLOCKSTATE();
6594
return (NFSERR_AUTHERR | AUTH_TOOWEAK);
6595
}
6596
6597
sep->sess_refcnt--;
6598
if (sep->sess_refcnt > 0) {
6599
NFSUNLOCKSESSION(shp);
6600
if (!locked)
6601
NFSUNLOCKSTATE();
6602
return (NFSERR_BACKCHANBUSY);
6603
}
6604
LIST_REMOVE(sep, sess_hash);
6605
LIST_REMOVE(sep, sess_list);
6606
}
6607
NFSUNLOCKSESSION(shp);
6608
if (!locked)
6609
NFSUNLOCKSTATE();
6610
if (sep == NULL)
6611
return (NFSERR_BADSESSION);
6612
for (i = 0; i < NFSV4_SLOTS; i++)
6613
if (sep->sess_slots[i].nfssl_reply != NULL)
6614
m_freem(sep->sess_slots[i].nfssl_reply);
6615
if (!locked) {
6616
if (sep->sess_cbsess.nfsess_xprt != NULL)
6617
SVC_RELEASE(sep->sess_cbsess.nfsess_xprt);
6618
if (old_xprtp != NULL)
6619
*old_xprtp = NULL;
6620
} else if (old_xprtp != NULL)
6621
*old_xprtp = sep->sess_cbsess.nfsess_xprt;
6622
free(sep, M_NFSDSESSION);
6623
return (0);
6624
}
6625
6626
/*
6627
* Free a stateid.
6628
* RFC5661 says that it should fail when there are associated opens, locks
6629
* or delegations. Since stateids represent opens, I don't see how you can
6630
* free an open stateid (it will be free'd when closed), so this function
6631
* only works for lock stateids (freeing the lock_owner) or delegations.
6632
*/
6633
int
6634
nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
6635
NFSPROC_T *p)
6636
{
6637
struct nfsclient *clp;
6638
struct nfsstate *stp;
6639
int error;
6640
6641
NFSLOCKSTATE();
6642
/*
6643
* Look up the stateid
6644
*/
6645
error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
6646
NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
6647
if (error == 0) {
6648
/* First, check for a delegation. */
6649
LIST_FOREACH(stp, &clp->lc_deleg, ls_list) {
6650
if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
6651
NFSX_STATEIDOTHER))
6652
break;
6653
}
6654
if (stp != NULL) {
6655
nfsrv_freedeleg(stp);
6656
NFSUNLOCKSTATE();
6657
return (error);
6658
}
6659
}
6660
/* Not a delegation, try for a lock_owner. */
6661
if (error == 0)
6662
error = nfsrv_getstate(clp, stateidp, 0, &stp);
6663
if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD |
6664
NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0))
6665
/* Not a lock_owner stateid. */
6666
error = NFSERR_LOCKSHELD;
6667
if (error == 0 && !LIST_EMPTY(&stp->ls_lock))
6668
error = NFSERR_LOCKSHELD;
6669
if (error == 0)
6670
nfsrv_freelockowner(stp, NULL, 0, p);
6671
NFSUNLOCKSTATE();
6672
return (error);
6673
}
6674
6675
/*
6676
* Test a stateid.
6677
*/
6678
int
6679
nfsrv_teststateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
6680
NFSPROC_T *p)
6681
{
6682
struct nfsclient *clp;
6683
struct nfsstate *stp;
6684
int error;
6685
6686
NFSLOCKSTATE();
6687
/*
6688
* Look up the stateid
6689
*/
6690
error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
6691
NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
6692
if (error == 0)
6693
error = nfsrv_getstate(clp, stateidp, 0, &stp);
6694
if (error == 0 && stateidp->seqid != 0 &&
6695
SEQ_LT(stateidp->seqid, stp->ls_stateid.seqid))
6696
error = NFSERR_OLDSTATEID;
6697
NFSUNLOCKSTATE();
6698
return (error);
6699
}
6700
6701
/*
6702
* Generate the xdr for an NFSv4.1 CBSequence Operation.
6703
*/
6704
static int
6705
nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
6706
int dont_replycache, struct nfsdsession **sepp, int *slotposp)
6707
{
6708
struct nfsdsession *sep;
6709
uint32_t *tl, slotseq = 0;
6710
int maxslot;
6711
uint8_t sessionid[NFSX_V4SESSIONID];
6712
int error;
6713
6714
error = nfsv4_getcbsession(clp, sepp);
6715
if (error != 0)
6716
return (error);
6717
sep = *sepp;
6718
nfsv4_sequencelookup(NULL, &sep->sess_cbsess, slotposp, &maxslot,
6719
&slotseq, sessionid, true);
6720
KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot"));
6721
6722
/* Build the Sequence arguments. */
6723
NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED);
6724
bcopy(sessionid, tl, NFSX_V4SESSIONID);
6725
tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
6726
nd->nd_slotseq = tl;
6727
nd->nd_slotid = *slotposp;
6728
nd->nd_flag |= ND_HASSLOTID;
6729
*tl++ = txdr_unsigned(slotseq);
6730
*tl++ = txdr_unsigned(*slotposp);
6731
*tl++ = txdr_unsigned(maxslot);
6732
if (dont_replycache == 0)
6733
*tl++ = newnfs_true;
6734
else
6735
*tl++ = newnfs_false;
6736
*tl = 0; /* No referring call list, for now. */
6737
nd->nd_flag |= ND_HASSEQUENCE;
6738
return (0);
6739
}
6740
6741
/*
6742
* Get a session for the callback.
6743
*/
6744
static int
6745
nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp)
6746
{
6747
struct nfsdsession *sep;
6748
6749
NFSLOCKSTATE();
6750
LIST_FOREACH(sep, &clp->lc_session, sess_list) {
6751
if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0)
6752
break;
6753
}
6754
if (sep == NULL) {
6755
NFSUNLOCKSTATE();
6756
return (NFSERR_BADSESSION);
6757
}
6758
sep->sess_refcnt++;
6759
*sepp = sep;
6760
NFSUNLOCKSTATE();
6761
return (0);
6762
}
6763
6764
/*
6765
* Free up all backchannel xprts. This needs to be done when the nfsd threads
6766
* exit, since those transports will all be going away.
6767
* This is only called after all the nfsd threads are done performing RPCs,
6768
* so locking shouldn't be an issue.
6769
*/
6770
void
6771
nfsrv_freeallbackchannel_xprts(void)
6772
{
6773
struct nfsdsession *sep;
6774
struct nfsclient *clp;
6775
SVCXPRT *xprt;
6776
int i;
6777
6778
for (i = 0; i < nfsrv_clienthashsize; i++) {
6779
LIST_FOREACH(clp, &NFSD_VNET(nfsclienthash)[i], lc_hash) {
6780
LIST_FOREACH(sep, &clp->lc_session, sess_list) {
6781
xprt = sep->sess_cbsess.nfsess_xprt;
6782
sep->sess_cbsess.nfsess_xprt = NULL;
6783
if (xprt != NULL)
6784
SVC_RELEASE(xprt);
6785
}
6786
}
6787
}
6788
}
6789
6790
/*
6791
* Do a layout commit. Actually just call nfsrv_updatemdsattr().
6792
* I have no idea if the rest of these arguments will ever be useful?
6793
*/
6794
int
6795
nfsrv_layoutcommit(struct nfsrv_descript *nd, vnode_t vp, int layouttype,
6796
int hasnewoff, uint64_t newoff, uint64_t offset, uint64_t len,
6797
int hasnewmtime, struct timespec *newmtimep, int reclaim,
6798
nfsv4stateid_t *stateidp, int maxcnt, char *layp, int *hasnewsizep,
6799
uint64_t *newsizep, struct ucred *cred, NFSPROC_T *p)
6800
{
6801
struct nfsvattr na;
6802
int error;
6803
6804
error = nfsrv_updatemdsattr(vp, &na, p);
6805
if (error == 0) {
6806
*hasnewsizep = 1;
6807
*newsizep = na.na_size;
6808
}
6809
return (error);
6810
}
6811
6812
/*
6813
* Try and get a layout.
6814
*/
6815
int
6816
nfsrv_layoutget(struct nfsrv_descript *nd, vnode_t vp, struct nfsexstuff *exp,
6817
int layouttype, int *iomode, uint64_t *offset, uint64_t *len,
6818
uint64_t minlen, nfsv4stateid_t *stateidp, int maxcnt, int *retonclose,
6819
int *layoutlenp, char *layp, struct ucred *cred, NFSPROC_T *p)
6820
{
6821
struct nfslayouthash *lhyp;
6822
struct nfslayout *lyp;
6823
char *devid;
6824
fhandle_t fh, *dsfhp;
6825
int error, mirrorcnt;
6826
6827
if (nfsrv_devidcnt == 0)
6828
return (NFSERR_UNKNLAYOUTTYPE);
6829
6830
if (*offset != 0)
6831
printf("nfsrv_layoutget: off=%ju len=%ju\n", (uintmax_t)*offset,
6832
(uintmax_t)*len);
6833
error = nfsvno_getfh(vp, &fh, p);
6834
NFSD_DEBUG(4, "layoutget getfh=%d\n", error);
6835
if (error != 0)
6836
return (error);
6837
6838
/*
6839
* For now, all layouts are for entire files.
6840
* Only issue Read/Write layouts if requested for a non-readonly fs.
6841
*/
6842
if (NFSVNO_EXRDONLY(exp)) {
6843
if (*iomode == NFSLAYOUTIOMODE_RW)
6844
return (NFSERR_LAYOUTTRYLATER);
6845
*iomode = NFSLAYOUTIOMODE_READ;
6846
}
6847
if (*iomode != NFSLAYOUTIOMODE_RW)
6848
*iomode = NFSLAYOUTIOMODE_READ;
6849
6850
/*
6851
* Check to see if a write layout can be issued for this file.
6852
* This is used during mirror recovery to avoid RW layouts being
6853
* issued for a file while it is being copied to the recovered
6854
* mirror.
6855
*/
6856
if (*iomode == NFSLAYOUTIOMODE_RW && nfsrv_dontlayout(&fh) != 0)
6857
return (NFSERR_LAYOUTTRYLATER);
6858
6859
*retonclose = 0;
6860
*offset = 0;
6861
*len = UINT64_MAX;
6862
6863
/* First, see if a layout already exists and return if found. */
6864
lhyp = NFSLAYOUTHASH(&fh);
6865
NFSLOCKLAYOUT(lhyp);
6866
error = nfsrv_findlayout(&nd->nd_clientid, &fh, layouttype, p, &lyp);
6867
NFSD_DEBUG(4, "layoutget findlay=%d\n", error);
6868
/*
6869
* Not sure if the seqid must be the same, so I won't check it.
6870
*/
6871
if (error == 0 && (stateidp->other[0] != lyp->lay_stateid.other[0] ||
6872
stateidp->other[1] != lyp->lay_stateid.other[1] ||
6873
stateidp->other[2] != lyp->lay_stateid.other[2])) {
6874
if ((lyp->lay_flags & NFSLAY_CALLB) == 0) {
6875
NFSUNLOCKLAYOUT(lhyp);
6876
NFSD_DEBUG(1, "ret bad stateid\n");
6877
return (NFSERR_BADSTATEID);
6878
}
6879
/*
6880
* I believe we get here because there is a race between
6881
* the client processing the CBLAYOUTRECALL and the layout
6882
* being deleted here on the server.
6883
* The client has now done a LayoutGet with a non-layout
6884
* stateid, as it would when there is no layout.
6885
* As such, free this layout and set error == NFSERR_BADSTATEID
6886
* so the code below will create a new layout structure as
6887
* would happen if no layout was found.
6888
* "lyp" will be set before being used below, but set it NULL
6889
* as a safety belt.
6890
*/
6891
nfsrv_freelayout(&lhyp->list, lyp);
6892
lyp = NULL;
6893
error = NFSERR_BADSTATEID;
6894
}
6895
if (error == 0) {
6896
if (lyp->lay_layoutlen > maxcnt) {
6897
NFSUNLOCKLAYOUT(lhyp);
6898
NFSD_DEBUG(1, "ret layout too small\n");
6899
return (NFSERR_TOOSMALL);
6900
}
6901
if (*iomode == NFSLAYOUTIOMODE_RW) {
6902
if ((lyp->lay_flags & NFSLAY_NOSPC) != 0) {
6903
NFSUNLOCKLAYOUT(lhyp);
6904
NFSD_DEBUG(1, "ret layout nospace\n");
6905
return (NFSERR_NOSPC);
6906
}
6907
lyp->lay_flags |= NFSLAY_RW;
6908
} else
6909
lyp->lay_flags |= NFSLAY_READ;
6910
NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen);
6911
*layoutlenp = lyp->lay_layoutlen;
6912
if (++lyp->lay_stateid.seqid == 0)
6913
lyp->lay_stateid.seqid = 1;
6914
stateidp->seqid = lyp->lay_stateid.seqid;
6915
NFSUNLOCKLAYOUT(lhyp);
6916
NFSD_DEBUG(4, "ret fnd layout\n");
6917
return (0);
6918
}
6919
NFSUNLOCKLAYOUT(lhyp);
6920
6921
/* Find the device id and file handle. */
6922
dsfhp = malloc(sizeof(fhandle_t) * NFSDEV_MAXMIRRORS, M_TEMP, M_WAITOK);
6923
devid = malloc(NFSX_V4DEVICEID * NFSDEV_MAXMIRRORS, M_TEMP, M_WAITOK);
6924
error = nfsrv_dsgetdevandfh(vp, p, &mirrorcnt, dsfhp, devid);
6925
NFSD_DEBUG(4, "layoutget devandfh=%d\n", error);
6926
if (error == 0) {
6927
if (layouttype == NFSLAYOUT_NFSV4_1_FILES) {
6928
if (NFSX_V4FILELAYOUT > maxcnt)
6929
error = NFSERR_TOOSMALL;
6930
else
6931
lyp = nfsrv_filelayout(nd, *iomode, &fh, dsfhp,
6932
devid, vp->v_mount->mnt_stat.f_fsid);
6933
} else {
6934
if (NFSX_V4FLEXLAYOUT(mirrorcnt) > maxcnt)
6935
error = NFSERR_TOOSMALL;
6936
else
6937
lyp = nfsrv_flexlayout(nd, *iomode, mirrorcnt,
6938
&fh, dsfhp, devid,
6939
vp->v_mount->mnt_stat.f_fsid);
6940
}
6941
}
6942
free(dsfhp, M_TEMP);
6943
free(devid, M_TEMP);
6944
if (error != 0)
6945
return (error);
6946
6947
/*
6948
* Now, add this layout to the list.
6949
*/
6950
error = nfsrv_addlayout(nd, &lyp, stateidp, layp, layoutlenp, p);
6951
NFSD_DEBUG(4, "layoutget addl=%d\n", error);
6952
/*
6953
* The lyp will be set to NULL by nfsrv_addlayout() if it
6954
* linked the new structure into the lists.
6955
*/
6956
free(lyp, M_NFSDSTATE);
6957
return (error);
6958
}
6959
6960
/*
6961
* Generate a File Layout.
6962
*/
6963
static struct nfslayout *
6964
nfsrv_filelayout(struct nfsrv_descript *nd, int iomode, fhandle_t *fhp,
6965
fhandle_t *dsfhp, char *devid, fsid_t fs)
6966
{
6967
uint32_t *tl;
6968
struct nfslayout *lyp;
6969
uint64_t pattern_offset;
6970
6971
lyp = malloc(sizeof(struct nfslayout) + NFSX_V4FILELAYOUT, M_NFSDSTATE,
6972
M_WAITOK | M_ZERO);
6973
lyp->lay_type = NFSLAYOUT_NFSV4_1_FILES;
6974
if (iomode == NFSLAYOUTIOMODE_RW)
6975
lyp->lay_flags = NFSLAY_RW;
6976
else
6977
lyp->lay_flags = NFSLAY_READ;
6978
NFSBCOPY(fhp, &lyp->lay_fh, sizeof(*fhp));
6979
lyp->lay_clientid.qval = nd->nd_clientid.qval;
6980
lyp->lay_fsid = fs;
6981
NFSBCOPY(devid, lyp->lay_deviceid, NFSX_V4DEVICEID);
6982
6983
/* Fill in the xdr for the files layout. */
6984
tl = (uint32_t *)lyp->lay_xdr;
6985
NFSBCOPY(devid, tl, NFSX_V4DEVICEID); /* Device ID. */
6986
tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
6987
6988
/* Set the stripe size to the maximum I/O size. */
6989
*tl++ = txdr_unsigned(nfs_srvmaxio & NFSFLAYUTIL_STRIPE_MASK);
6990
*tl++ = 0; /* 1st stripe index. */
6991
pattern_offset = 0;
6992
txdr_hyper(pattern_offset, tl); tl += 2; /* Pattern offset. */
6993
*tl++ = txdr_unsigned(1); /* 1 file handle. */
6994
*tl++ = txdr_unsigned(NFSX_V4PNFSFH);
6995
NFSBCOPY(dsfhp, tl, sizeof(*dsfhp));
6996
lyp->lay_layoutlen = NFSX_V4FILELAYOUT;
6997
return (lyp);
6998
}
6999
7000
#define FLEX_OWNERID "999"
7001
#define FLEX_UID0 "0"
7002
/*
7003
* Generate a Flex File Layout.
7004
* The FLEX_OWNERID can be any string of 3 decimal digits. Although this
7005
* string goes on the wire, it isn't supposed to be used by the client,
7006
* since this server uses tight coupling.
7007
* Although not recommended by the spec., if vfs.nfsd.flexlinuxhack=1 use
7008
* a string of "0". This works around the Linux Flex File Layout driver bug
7009
* which uses the synthetic uid/gid strings for the "tightly coupled" case.
7010
*/
7011
static struct nfslayout *
7012
nfsrv_flexlayout(struct nfsrv_descript *nd, int iomode, int mirrorcnt,
7013
fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs)
7014
{
7015
uint32_t *tl;
7016
struct nfslayout *lyp;
7017
uint64_t lenval;
7018
int i;
7019
7020
lyp = malloc(sizeof(struct nfslayout) + NFSX_V4FLEXLAYOUT(mirrorcnt),
7021
M_NFSDSTATE, M_WAITOK | M_ZERO);
7022
lyp->lay_type = NFSLAYOUT_FLEXFILE;
7023
if (iomode == NFSLAYOUTIOMODE_RW)
7024
lyp->lay_flags = NFSLAY_RW;
7025
else
7026
lyp->lay_flags = NFSLAY_READ;
7027
NFSBCOPY(fhp, &lyp->lay_fh, sizeof(*fhp));
7028
lyp->lay_clientid.qval = nd->nd_clientid.qval;
7029
lyp->lay_fsid = fs;
7030
lyp->lay_mirrorcnt = mirrorcnt;
7031
NFSBCOPY(devid, lyp->lay_deviceid, NFSX_V4DEVICEID);
7032
7033
/* Fill in the xdr for the files layout. */
7034
tl = (uint32_t *)lyp->lay_xdr;
7035
lenval = 0;
7036
txdr_hyper(lenval, tl); tl += 2; /* Stripe unit. */
7037
*tl++ = txdr_unsigned(mirrorcnt); /* # of mirrors. */
7038
for (i = 0; i < mirrorcnt; i++) {
7039
*tl++ = txdr_unsigned(1); /* One stripe. */
7040
NFSBCOPY(devid, tl, NFSX_V4DEVICEID); /* Device ID. */
7041
tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
7042
devid += NFSX_V4DEVICEID;
7043
*tl++ = txdr_unsigned(1); /* Efficiency. */
7044
*tl++ = 0; /* Proxy Stateid. */
7045
*tl++ = 0x55555555;
7046
*tl++ = 0x55555555;
7047
*tl++ = 0x55555555;
7048
*tl++ = txdr_unsigned(1); /* 1 file handle. */
7049
*tl++ = txdr_unsigned(NFSX_V4PNFSFH);
7050
NFSBCOPY(dsfhp, tl, sizeof(*dsfhp));
7051
tl += (NFSM_RNDUP(NFSX_V4PNFSFH) / NFSX_UNSIGNED);
7052
dsfhp++;
7053
if (nfsrv_flexlinuxhack != 0) {
7054
*tl++ = txdr_unsigned(strlen(FLEX_UID0));
7055
*tl = 0; /* 0 pad string. */
7056
NFSBCOPY(FLEX_UID0, tl++, strlen(FLEX_UID0));
7057
*tl++ = txdr_unsigned(strlen(FLEX_UID0));
7058
*tl = 0; /* 0 pad string. */
7059
NFSBCOPY(FLEX_UID0, tl++, strlen(FLEX_UID0));
7060
} else {
7061
*tl++ = txdr_unsigned(strlen(FLEX_OWNERID));
7062
NFSBCOPY(FLEX_OWNERID, tl++, NFSX_UNSIGNED);
7063
*tl++ = txdr_unsigned(strlen(FLEX_OWNERID));
7064
NFSBCOPY(FLEX_OWNERID, tl++, NFSX_UNSIGNED);
7065
}
7066
}
7067
*tl++ = txdr_unsigned(0); /* ff_flags. */
7068
*tl = txdr_unsigned(60); /* Status interval hint. */
7069
lyp->lay_layoutlen = NFSX_V4FLEXLAYOUT(mirrorcnt);
7070
return (lyp);
7071
}
7072
7073
/*
7074
* Parse and process Flex File errors returned via LayoutReturn.
7075
*/
7076
static void
7077
nfsrv_flexlayouterr(struct nfsrv_descript *nd, uint32_t *layp, int maxcnt,
7078
NFSPROC_T *p)
7079
{
7080
uint32_t *tl;
7081
int cnt, errcnt, i, j, opnum, stat;
7082
char devid[NFSX_V4DEVICEID];
7083
7084
tl = layp;
7085
maxcnt -= NFSX_UNSIGNED;
7086
if (maxcnt > 0)
7087
cnt = fxdr_unsigned(int, *tl++);
7088
else
7089
cnt = 0;
7090
NFSD_DEBUG(4, "flexlayouterr cnt=%d\n", cnt);
7091
for (i = 0; i < cnt; i++) {
7092
maxcnt -= NFSX_STATEID + 2 * NFSX_HYPER +
7093
NFSX_UNSIGNED;
7094
if (maxcnt <= 0)
7095
break;
7096
/* Skip offset, length and stateid for now. */
7097
tl += (4 + NFSX_STATEID / NFSX_UNSIGNED);
7098
errcnt = fxdr_unsigned(int, *tl++);
7099
NFSD_DEBUG(4, "flexlayouterr errcnt=%d\n", errcnt);
7100
for (j = 0; j < errcnt; j++) {
7101
maxcnt -= NFSX_V4DEVICEID + 2 * NFSX_UNSIGNED;
7102
if (maxcnt < 0)
7103
break;
7104
NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
7105
tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
7106
stat = fxdr_unsigned(int, *tl++);
7107
opnum = fxdr_unsigned(int, *tl++);
7108
NFSD_DEBUG(4, "flexlayouterr op=%d stat=%d\n", opnum,
7109
stat);
7110
/*
7111
* Except for NFSERR_ACCES, NFSERR_STALE and
7112
* NFSERR_NOSPC errors, disable the mirror.
7113
*/
7114
if (stat != NFSERR_ACCES && stat != NFSERR_STALE &&
7115
stat != NFSERR_NOSPC)
7116
nfsrv_delds(devid, p);
7117
7118
/* For NFSERR_NOSPC, mark all devids and layouts. */
7119
if (stat == NFSERR_NOSPC)
7120
nfsrv_marknospc(devid, true);
7121
}
7122
}
7123
}
7124
7125
/*
7126
* This function removes all flex file layouts which has a mirror with
7127
* a device id that matches the argument.
7128
* Called when the DS represented by the device id has failed.
7129
*/
7130
void
7131
nfsrv_flexmirrordel(char *devid, NFSPROC_T *p)
7132
{
7133
uint32_t *tl;
7134
struct nfslayout *lyp, *nlyp;
7135
struct nfslayouthash *lhyp;
7136
struct nfslayouthead loclyp;
7137
int i, j;
7138
7139
NFSD_DEBUG(4, "flexmirrordel\n");
7140
/* Move all layouts found onto a local list. */
7141
TAILQ_INIT(&loclyp);
7142
for (i = 0; i < nfsrv_layouthashsize; i++) {
7143
lhyp = &nfslayouthash[i];
7144
NFSLOCKLAYOUT(lhyp);
7145
TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
7146
if (lyp->lay_type == NFSLAYOUT_FLEXFILE &&
7147
lyp->lay_mirrorcnt > 1) {
7148
NFSD_DEBUG(4, "possible match\n");
7149
tl = lyp->lay_xdr;
7150
tl += 3;
7151
for (j = 0; j < lyp->lay_mirrorcnt; j++) {
7152
tl++;
7153
if (NFSBCMP(devid, tl, NFSX_V4DEVICEID)
7154
== 0) {
7155
/* Found one. */
7156
NFSD_DEBUG(4, "fnd one\n");
7157
TAILQ_REMOVE(&lhyp->list, lyp,
7158
lay_list);
7159
TAILQ_INSERT_HEAD(&loclyp, lyp,
7160
lay_list);
7161
break;
7162
}
7163
tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED +
7164
NFSM_RNDUP(NFSX_V4PNFSFH) /
7165
NFSX_UNSIGNED + 11 * NFSX_UNSIGNED);
7166
}
7167
}
7168
}
7169
NFSUNLOCKLAYOUT(lhyp);
7170
}
7171
7172
/* Now, try to do a Layout recall for each one found. */
7173
TAILQ_FOREACH_SAFE(lyp, &loclyp, lay_list, nlyp) {
7174
NFSD_DEBUG(4, "do layout recall\n");
7175
/*
7176
* The layout stateid.seqid needs to be incremented
7177
* before doing a LAYOUT_RECALL callback.
7178
*/
7179
if (++lyp->lay_stateid.seqid == 0)
7180
lyp->lay_stateid.seqid = 1;
7181
nfsrv_recalllayout(lyp->lay_clientid, &lyp->lay_stateid,
7182
&lyp->lay_fh, lyp, 1, lyp->lay_type, p);
7183
nfsrv_freelayout(&loclyp, lyp);
7184
}
7185
}
7186
7187
/*
7188
* Do a recall callback to the client for this layout.
7189
*/
7190
static int
7191
nfsrv_recalllayout(nfsquad_t clid, nfsv4stateid_t *stateidp, fhandle_t *fhp,
7192
struct nfslayout *lyp, int changed, int laytype, NFSPROC_T *p)
7193
{
7194
struct nfsclient *clp;
7195
int error;
7196
7197
NFSD_DEBUG(4, "nfsrv_recalllayout\n");
7198
error = nfsrv_getclient(clid, 0, &clp, NULL, (nfsquad_t)((u_quad_t)0),
7199
0, NULL, p);
7200
NFSD_DEBUG(4, "aft nfsrv_getclient=%d\n", error);
7201
if (error != 0) {
7202
printf("nfsrv_recalllayout: getclient err=%d\n", error);
7203
return (error);
7204
}
7205
if ((clp->lc_flags & LCL_NFSV41) != 0) {
7206
error = nfsrv_docallback(clp, NFSV4OP_CBLAYOUTRECALL,
7207
stateidp, changed, fhp, NULL, NULL, laytype, p);
7208
/* If lyp != NULL, handle an error return here. */
7209
if (error != 0 && lyp != NULL) {
7210
NFSDRECALLLOCK();
7211
/*
7212
* Mark it returned, since no layout recall
7213
* has been done.
7214
* All errors seem to be non-recoverable, although
7215
* NFSERR_NOMATCHLAYOUT is a normal event.
7216
*/
7217
if ((lyp->lay_flags & NFSLAY_RECALL) != 0) {
7218
lyp->lay_flags |= NFSLAY_RETURNED;
7219
wakeup(lyp);
7220
}
7221
NFSDRECALLUNLOCK();
7222
if (error != NFSERR_NOMATCHLAYOUT)
7223
printf("nfsrv_recalllayout: err=%d\n", error);
7224
}
7225
} else
7226
printf("nfsrv_recalllayout: clp not NFSv4.1\n");
7227
return (error);
7228
}
7229
7230
/*
7231
* Find a layout to recall when we exceed our high water mark.
7232
*/
7233
void
7234
nfsrv_recalloldlayout(NFSPROC_T *p)
7235
{
7236
struct nfslayouthash *lhyp;
7237
struct nfslayout *lyp;
7238
nfsquad_t clientid;
7239
nfsv4stateid_t stateid;
7240
fhandle_t fh;
7241
int error, laytype = 0, ret;
7242
7243
lhyp = &nfslayouthash[arc4random() % nfsrv_layouthashsize];
7244
NFSLOCKLAYOUT(lhyp);
7245
TAILQ_FOREACH_REVERSE(lyp, &lhyp->list, nfslayouthead, lay_list) {
7246
if ((lyp->lay_flags & NFSLAY_CALLB) == 0) {
7247
lyp->lay_flags |= NFSLAY_CALLB;
7248
/*
7249
* The layout stateid.seqid needs to be incremented
7250
* before doing a LAYOUT_RECALL callback.
7251
*/
7252
if (++lyp->lay_stateid.seqid == 0)
7253
lyp->lay_stateid.seqid = 1;
7254
clientid = lyp->lay_clientid;
7255
stateid = lyp->lay_stateid;
7256
NFSBCOPY(&lyp->lay_fh, &fh, sizeof(fh));
7257
laytype = lyp->lay_type;
7258
break;
7259
}
7260
}
7261
NFSUNLOCKLAYOUT(lhyp);
7262
if (lyp != NULL) {
7263
error = nfsrv_recalllayout(clientid, &stateid, &fh, NULL, 0,
7264
laytype, p);
7265
if (error != 0 && error != NFSERR_NOMATCHLAYOUT)
7266
NFSD_DEBUG(4, "recallold=%d\n", error);
7267
if (error != 0) {
7268
NFSLOCKLAYOUT(lhyp);
7269
/*
7270
* Since the hash list was unlocked, we need to
7271
* find it again.
7272
*/
7273
ret = nfsrv_findlayout(&clientid, &fh, laytype, p,
7274
&lyp);
7275
if (ret == 0 &&
7276
(lyp->lay_flags & NFSLAY_CALLB) != 0 &&
7277
lyp->lay_stateid.other[0] == stateid.other[0] &&
7278
lyp->lay_stateid.other[1] == stateid.other[1] &&
7279
lyp->lay_stateid.other[2] == stateid.other[2]) {
7280
/*
7281
* The client no longer knows this layout, so
7282
* it can be free'd now.
7283
*/
7284
if (error == NFSERR_NOMATCHLAYOUT)
7285
nfsrv_freelayout(&lhyp->list, lyp);
7286
else {
7287
/*
7288
* Leave it to be tried later by
7289
* clearing NFSLAY_CALLB and moving
7290
* it to the head of the list, so it
7291
* won't be tried again for a while.
7292
*/
7293
lyp->lay_flags &= ~NFSLAY_CALLB;
7294
TAILQ_REMOVE(&lhyp->list, lyp,
7295
lay_list);
7296
TAILQ_INSERT_HEAD(&lhyp->list, lyp,
7297
lay_list);
7298
}
7299
}
7300
NFSUNLOCKLAYOUT(lhyp);
7301
}
7302
}
7303
}
7304
7305
/*
7306
* Try and return layout(s).
7307
*/
7308
int
7309
nfsrv_layoutreturn(struct nfsrv_descript *nd, vnode_t vp,
7310
int layouttype, int iomode, uint64_t offset, uint64_t len, int reclaim,
7311
int kind, nfsv4stateid_t *stateidp, int maxcnt, uint32_t *layp, int *fndp,
7312
struct ucred *cred, NFSPROC_T *p)
7313
{
7314
struct nfsvattr na;
7315
struct nfslayouthash *lhyp;
7316
struct nfslayout *lyp;
7317
fhandle_t fh;
7318
int error = 0;
7319
7320
*fndp = 0;
7321
if (kind == NFSV4LAYOUTRET_FILE) {
7322
error = nfsvno_getfh(vp, &fh, p);
7323
if (error == 0) {
7324
error = nfsrv_updatemdsattr(vp, &na, p);
7325
if (error != 0)
7326
printf("nfsrv_layoutreturn: updatemdsattr"
7327
" failed=%d\n", error);
7328
}
7329
if (error == 0) {
7330
if (reclaim == newnfs_true) {
7331
error = nfsrv_checkgrace(NULL, NULL,
7332
NFSLCK_RECLAIM);
7333
if (error != NFSERR_NOGRACE)
7334
error = 0;
7335
return (error);
7336
}
7337
lhyp = NFSLAYOUTHASH(&fh);
7338
NFSDRECALLLOCK();
7339
NFSLOCKLAYOUT(lhyp);
7340
error = nfsrv_findlayout(&nd->nd_clientid, &fh,
7341
layouttype, p, &lyp);
7342
NFSD_DEBUG(4, "layoutret findlay=%d\n", error);
7343
if (error == 0 &&
7344
stateidp->other[0] == lyp->lay_stateid.other[0] &&
7345
stateidp->other[1] == lyp->lay_stateid.other[1] &&
7346
stateidp->other[2] == lyp->lay_stateid.other[2]) {
7347
NFSD_DEBUG(4, "nfsrv_layoutreturn: stateid %d"
7348
" %x %x %x laystateid %d %x %x %x"
7349
" off=%ju len=%ju flgs=0x%x\n",
7350
stateidp->seqid, stateidp->other[0],
7351
stateidp->other[1], stateidp->other[2],
7352
lyp->lay_stateid.seqid,
7353
lyp->lay_stateid.other[0],
7354
lyp->lay_stateid.other[1],
7355
lyp->lay_stateid.other[2],
7356
(uintmax_t)offset, (uintmax_t)len,
7357
lyp->lay_flags);
7358
if (++lyp->lay_stateid.seqid == 0)
7359
lyp->lay_stateid.seqid = 1;
7360
stateidp->seqid = lyp->lay_stateid.seqid;
7361
if (offset == 0 && len == UINT64_MAX) {
7362
if ((iomode & NFSLAYOUTIOMODE_READ) !=
7363
0)
7364
lyp->lay_flags &= ~NFSLAY_READ;
7365
if ((iomode & NFSLAYOUTIOMODE_RW) != 0)
7366
lyp->lay_flags &= ~NFSLAY_RW;
7367
if ((lyp->lay_flags & (NFSLAY_READ |
7368
NFSLAY_RW)) == 0)
7369
nfsrv_freelayout(&lhyp->list,
7370
lyp);
7371
else
7372
*fndp = 1;
7373
} else
7374
*fndp = 1;
7375
}
7376
NFSUNLOCKLAYOUT(lhyp);
7377
/* Search the nfsrv_recalllist for a match. */
7378
TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) {
7379
if (NFSBCMP(&lyp->lay_fh, &fh,
7380
sizeof(fh)) == 0 &&
7381
lyp->lay_clientid.qval ==
7382
nd->nd_clientid.qval &&
7383
stateidp->other[0] ==
7384
lyp->lay_stateid.other[0] &&
7385
stateidp->other[1] ==
7386
lyp->lay_stateid.other[1] &&
7387
stateidp->other[2] ==
7388
lyp->lay_stateid.other[2]) {
7389
lyp->lay_flags |= NFSLAY_RETURNED;
7390
wakeup(lyp);
7391
error = 0;
7392
}
7393
}
7394
NFSDRECALLUNLOCK();
7395
}
7396
if (layouttype == NFSLAYOUT_FLEXFILE && layp != NULL)
7397
nfsrv_flexlayouterr(nd, layp, maxcnt, p);
7398
} else if (kind == NFSV4LAYOUTRET_FSID)
7399
nfsrv_freelayouts(&nd->nd_clientid,
7400
&vp->v_mount->mnt_stat.f_fsid, layouttype, iomode);
7401
else if (kind == NFSV4LAYOUTRET_ALL)
7402
nfsrv_freelayouts(&nd->nd_clientid, NULL, layouttype, iomode);
7403
else
7404
error = NFSERR_INVAL;
7405
if (error == -1)
7406
error = 0;
7407
return (error);
7408
}
7409
7410
/*
7411
* Look for an existing layout.
7412
*/
7413
static int
7414
nfsrv_findlayout(nfsquad_t *clientidp, fhandle_t *fhp, int laytype,
7415
NFSPROC_T *p, struct nfslayout **lypp)
7416
{
7417
struct nfslayouthash *lhyp;
7418
struct nfslayout *lyp;
7419
int ret;
7420
7421
*lypp = NULL;
7422
ret = 0;
7423
lhyp = NFSLAYOUTHASH(fhp);
7424
TAILQ_FOREACH(lyp, &lhyp->list, lay_list) {
7425
if (NFSBCMP(&lyp->lay_fh, fhp, sizeof(*fhp)) == 0 &&
7426
lyp->lay_clientid.qval == clientidp->qval &&
7427
lyp->lay_type == laytype)
7428
break;
7429
}
7430
if (lyp != NULL)
7431
*lypp = lyp;
7432
else
7433
ret = -1;
7434
return (ret);
7435
}
7436
7437
/*
7438
* Add the new layout, as required.
7439
*/
7440
static int
7441
nfsrv_addlayout(struct nfsrv_descript *nd, struct nfslayout **lypp,
7442
nfsv4stateid_t *stateidp, char *layp, int *layoutlenp, NFSPROC_T *p)
7443
{
7444
struct nfsclient *clp;
7445
struct nfslayouthash *lhyp;
7446
struct nfslayout *lyp, *nlyp;
7447
fhandle_t *fhp;
7448
int error;
7449
7450
KASSERT((nd->nd_flag & ND_IMPLIEDCLID) != 0,
7451
("nfsrv_layoutget: no nd_clientid\n"));
7452
lyp = *lypp;
7453
fhp = &lyp->lay_fh;
7454
NFSLOCKSTATE();
7455
error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
7456
NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
7457
if (error != 0) {
7458
NFSUNLOCKSTATE();
7459
return (error);
7460
}
7461
lyp->lay_stateid.seqid = stateidp->seqid = 1;
7462
lyp->lay_stateid.other[0] = stateidp->other[0] =
7463
clp->lc_clientid.lval[0];
7464
lyp->lay_stateid.other[1] = stateidp->other[1] =
7465
clp->lc_clientid.lval[1];
7466
lyp->lay_stateid.other[2] = stateidp->other[2] =
7467
nfsrv_nextstateindex(clp);
7468
NFSUNLOCKSTATE();
7469
7470
lhyp = NFSLAYOUTHASH(fhp);
7471
NFSLOCKLAYOUT(lhyp);
7472
TAILQ_FOREACH(nlyp, &lhyp->list, lay_list) {
7473
if (NFSBCMP(&nlyp->lay_fh, fhp, sizeof(*fhp)) == 0 &&
7474
nlyp->lay_clientid.qval == nd->nd_clientid.qval)
7475
break;
7476
}
7477
if (nlyp != NULL) {
7478
/* A layout already exists, so use it. */
7479
nlyp->lay_flags |= (lyp->lay_flags & (NFSLAY_READ | NFSLAY_RW));
7480
NFSBCOPY(nlyp->lay_xdr, layp, nlyp->lay_layoutlen);
7481
*layoutlenp = nlyp->lay_layoutlen;
7482
if (++nlyp->lay_stateid.seqid == 0)
7483
nlyp->lay_stateid.seqid = 1;
7484
stateidp->seqid = nlyp->lay_stateid.seqid;
7485
stateidp->other[0] = nlyp->lay_stateid.other[0];
7486
stateidp->other[1] = nlyp->lay_stateid.other[1];
7487
stateidp->other[2] = nlyp->lay_stateid.other[2];
7488
NFSUNLOCKLAYOUT(lhyp);
7489
return (0);
7490
}
7491
7492
/* Insert the new layout in the lists. */
7493
*lypp = NULL;
7494
atomic_add_int(&nfsrv_layoutcnt, 1);
7495
NFSD_VNET(nfsstatsv1_p)->srvlayouts++;
7496
NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen);
7497
*layoutlenp = lyp->lay_layoutlen;
7498
TAILQ_INSERT_HEAD(&lhyp->list, lyp, lay_list);
7499
NFSUNLOCKLAYOUT(lhyp);
7500
return (0);
7501
}
7502
7503
/*
7504
* Get the devinfo for a deviceid.
7505
*/
7506
int
7507
nfsrv_getdevinfo(char *devid, int layouttype, uint32_t *maxcnt,
7508
uint32_t *notify, int *devaddrlen, char **devaddr)
7509
{
7510
struct nfsdevice *ds;
7511
7512
if ((layouttype != NFSLAYOUT_NFSV4_1_FILES && layouttype !=
7513
NFSLAYOUT_FLEXFILE) ||
7514
(nfsrv_maxpnfsmirror > 1 && layouttype == NFSLAYOUT_NFSV4_1_FILES))
7515
return (NFSERR_UNKNLAYOUTTYPE);
7516
7517
/*
7518
* Now, search for the device id. Note that the structures won't go
7519
* away, but the order changes in the list. As such, the lock only
7520
* needs to be held during the search through the list.
7521
*/
7522
NFSDDSLOCK();
7523
TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
7524
if (NFSBCMP(devid, ds->nfsdev_deviceid, NFSX_V4DEVICEID) == 0 &&
7525
ds->nfsdev_nmp != NULL)
7526
break;
7527
}
7528
NFSDDSUNLOCK();
7529
if (ds == NULL)
7530
return (NFSERR_NOENT);
7531
7532
/* If the correct nfsdev_XXXXaddrlen is > 0, we have the device info. */
7533
*devaddrlen = 0;
7534
if (layouttype == NFSLAYOUT_NFSV4_1_FILES) {
7535
*devaddrlen = ds->nfsdev_fileaddrlen;
7536
*devaddr = ds->nfsdev_fileaddr;
7537
} else if (layouttype == NFSLAYOUT_FLEXFILE) {
7538
*devaddrlen = ds->nfsdev_flexaddrlen;
7539
*devaddr = ds->nfsdev_flexaddr;
7540
}
7541
if (*devaddrlen == 0)
7542
return (NFSERR_UNKNLAYOUTTYPE);
7543
7544
/*
7545
* The XDR overhead is 3 unsigned values: layout_type,
7546
* length_of_address and notify bitmap.
7547
* If the notify array is changed to not all zeros, the
7548
* count of unsigned values must be increased.
7549
*/
7550
if (*maxcnt > 0 && *maxcnt < NFSM_RNDUP(*devaddrlen) +
7551
3 * NFSX_UNSIGNED) {
7552
*maxcnt = NFSM_RNDUP(*devaddrlen) + 3 * NFSX_UNSIGNED;
7553
return (NFSERR_TOOSMALL);
7554
}
7555
return (0);
7556
}
7557
7558
/*
7559
* Free a list of layout state structures.
7560
*/
7561
static void
7562
nfsrv_freelayoutlist(nfsquad_t clientid)
7563
{
7564
struct nfslayouthash *lhyp;
7565
struct nfslayout *lyp, *nlyp;
7566
int i;
7567
7568
for (i = 0; i < nfsrv_layouthashsize; i++) {
7569
lhyp = &nfslayouthash[i];
7570
NFSLOCKLAYOUT(lhyp);
7571
TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
7572
if (lyp->lay_clientid.qval == clientid.qval)
7573
nfsrv_freelayout(&lhyp->list, lyp);
7574
}
7575
NFSUNLOCKLAYOUT(lhyp);
7576
}
7577
}
7578
7579
/*
7580
* Free up a layout.
7581
*/
7582
static void
7583
nfsrv_freelayout(struct nfslayouthead *lhp, struct nfslayout *lyp)
7584
{
7585
7586
NFSD_DEBUG(4, "Freelayout=%p\n", lyp);
7587
atomic_add_int(&nfsrv_layoutcnt, -1);
7588
NFSD_VNET(nfsstatsv1_p)->srvlayouts--;
7589
TAILQ_REMOVE(lhp, lyp, lay_list);
7590
free(lyp, M_NFSDSTATE);
7591
}
7592
7593
/*
7594
* Free up a device id.
7595
*/
7596
void
7597
nfsrv_freeonedevid(struct nfsdevice *ds)
7598
{
7599
int i;
7600
7601
atomic_add_int(&nfsrv_devidcnt, -1);
7602
vrele(ds->nfsdev_dvp);
7603
for (i = 0; i < nfsrv_dsdirsize; i++)
7604
if (ds->nfsdev_dsdir[i] != NULL)
7605
vrele(ds->nfsdev_dsdir[i]);
7606
free(ds->nfsdev_fileaddr, M_NFSDSTATE);
7607
free(ds->nfsdev_flexaddr, M_NFSDSTATE);
7608
free(ds->nfsdev_host, M_NFSDSTATE);
7609
free(ds, M_NFSDSTATE);
7610
}
7611
7612
/*
7613
* Free up a device id and its mirrors.
7614
*/
7615
static void
7616
nfsrv_freedevid(struct nfsdevice *ds)
7617
{
7618
7619
TAILQ_REMOVE(&nfsrv_devidhead, ds, nfsdev_list);
7620
nfsrv_freeonedevid(ds);
7621
}
7622
7623
/*
7624
* Free all layouts and device ids.
7625
* Done when the nfsd threads are shut down since there may be a new
7626
* modified device id list created when the nfsd is restarted.
7627
*/
7628
void
7629
nfsrv_freealllayoutsanddevids(void)
7630
{
7631
struct nfsdontlist *mrp, *nmrp;
7632
struct nfslayout *lyp, *nlyp;
7633
7634
/* Get rid of the deviceid structures. */
7635
nfsrv_freealldevids();
7636
TAILQ_INIT(&nfsrv_devidhead);
7637
nfsrv_devidcnt = 0;
7638
7639
/* Get rid of all layouts. */
7640
nfsrv_freealllayouts();
7641
7642
/* Get rid of any nfsdontlist entries. */
7643
LIST_FOREACH_SAFE(mrp, &nfsrv_dontlisthead, nfsmr_list, nmrp)
7644
free(mrp, M_NFSDSTATE);
7645
LIST_INIT(&nfsrv_dontlisthead);
7646
nfsrv_dontlistlen = 0;
7647
7648
/* Free layouts in the recall list. */
7649
TAILQ_FOREACH_SAFE(lyp, &nfsrv_recalllisthead, lay_list, nlyp)
7650
nfsrv_freelayout(&nfsrv_recalllisthead, lyp);
7651
TAILQ_INIT(&nfsrv_recalllisthead);
7652
}
7653
7654
/*
7655
* Free layouts that match the arguments.
7656
*/
7657
static void
7658
nfsrv_freelayouts(nfsquad_t *clid, fsid_t *fs, int laytype, int iomode)
7659
{
7660
struct nfslayouthash *lhyp;
7661
struct nfslayout *lyp, *nlyp;
7662
int i;
7663
7664
for (i = 0; i < nfsrv_layouthashsize; i++) {
7665
lhyp = &nfslayouthash[i];
7666
NFSLOCKLAYOUT(lhyp);
7667
TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
7668
if (clid->qval != lyp->lay_clientid.qval)
7669
continue;
7670
if (fs != NULL && fsidcmp(fs, &lyp->lay_fsid) != 0)
7671
continue;
7672
if (laytype != lyp->lay_type)
7673
continue;
7674
if ((iomode & NFSLAYOUTIOMODE_READ) != 0)
7675
lyp->lay_flags &= ~NFSLAY_READ;
7676
if ((iomode & NFSLAYOUTIOMODE_RW) != 0)
7677
lyp->lay_flags &= ~NFSLAY_RW;
7678
if ((lyp->lay_flags & (NFSLAY_READ | NFSLAY_RW)) == 0)
7679
nfsrv_freelayout(&lhyp->list, lyp);
7680
}
7681
NFSUNLOCKLAYOUT(lhyp);
7682
}
7683
}
7684
7685
/*
7686
* Free all layouts for the argument file.
7687
*/
7688
void
7689
nfsrv_freefilelayouts(fhandle_t *fhp)
7690
{
7691
struct nfslayouthash *lhyp;
7692
struct nfslayout *lyp, *nlyp;
7693
7694
lhyp = NFSLAYOUTHASH(fhp);
7695
NFSLOCKLAYOUT(lhyp);
7696
TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
7697
if (NFSBCMP(&lyp->lay_fh, fhp, sizeof(*fhp)) == 0)
7698
nfsrv_freelayout(&lhyp->list, lyp);
7699
}
7700
NFSUNLOCKLAYOUT(lhyp);
7701
}
7702
7703
/*
7704
* Free all layouts.
7705
*/
7706
static void
7707
nfsrv_freealllayouts(void)
7708
{
7709
struct nfslayouthash *lhyp;
7710
struct nfslayout *lyp, *nlyp;
7711
int i;
7712
7713
for (i = 0; i < nfsrv_layouthashsize; i++) {
7714
lhyp = &nfslayouthash[i];
7715
NFSLOCKLAYOUT(lhyp);
7716
TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp)
7717
nfsrv_freelayout(&lhyp->list, lyp);
7718
NFSUNLOCKLAYOUT(lhyp);
7719
}
7720
}
7721
7722
/*
7723
* Look up the mount path for the DS server.
7724
*/
7725
static int
7726
nfsrv_setdsserver(char *dspathp, char *mdspathp, NFSPROC_T *p,
7727
struct nfsdevice **dsp)
7728
{
7729
struct nameidata nd;
7730
struct nfsdevice *ds;
7731
struct mount *mp;
7732
int error, i;
7733
char *dsdirpath;
7734
size_t dsdirsize;
7735
7736
NFSD_DEBUG(4, "setdssrv path=%s\n", dspathp);
7737
*dsp = NULL;
7738
if (jailed(p->td_ucred)) {
7739
printf("A pNFS nfsd cannot run in a jail\n");
7740
return (EPERM);
7741
}
7742
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE,
7743
dspathp);
7744
error = namei(&nd);
7745
NFSD_DEBUG(4, "lookup=%d\n", error);
7746
if (error != 0)
7747
return (error);
7748
NDFREE_PNBUF(&nd);
7749
if (nd.ni_vp->v_type != VDIR) {
7750
vput(nd.ni_vp);
7751
NFSD_DEBUG(4, "dspath not dir\n");
7752
return (ENOTDIR);
7753
}
7754
if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) {
7755
vput(nd.ni_vp);
7756
NFSD_DEBUG(4, "dspath not an NFS mount\n");
7757
return (ENXIO);
7758
}
7759
7760
/*
7761
* Allocate a DS server structure with the NFS mounted directory
7762
* vnode reference counted, so that a non-forced dismount will
7763
* fail with EBUSY.
7764
* This structure is always linked into the list, even if an error
7765
* is being returned. The caller will free the entire list upon
7766
* an error return.
7767
*/
7768
*dsp = ds = malloc(sizeof(*ds) + nfsrv_dsdirsize * sizeof(vnode_t),
7769
M_NFSDSTATE, M_WAITOK | M_ZERO);
7770
ds->nfsdev_dvp = nd.ni_vp;
7771
ds->nfsdev_nmp = VFSTONFS(nd.ni_vp->v_mount);
7772
NFSVOPUNLOCK(nd.ni_vp);
7773
7774
dsdirsize = strlen(dspathp) + 16;
7775
dsdirpath = malloc(dsdirsize, M_TEMP, M_WAITOK);
7776
/* Now, create the DS directory structures. */
7777
for (i = 0; i < nfsrv_dsdirsize; i++) {
7778
snprintf(dsdirpath, dsdirsize, "%s/ds%d", dspathp, i);
7779
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
7780
UIO_SYSSPACE, dsdirpath);
7781
error = namei(&nd);
7782
NFSD_DEBUG(4, "dsdirpath=%s lookup=%d\n", dsdirpath, error);
7783
if (error != 0)
7784
break;
7785
NDFREE_PNBUF(&nd);
7786
if (nd.ni_vp->v_type != VDIR) {
7787
vput(nd.ni_vp);
7788
error = ENOTDIR;
7789
NFSD_DEBUG(4, "dsdirpath not a VDIR\n");
7790
break;
7791
}
7792
if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) {
7793
vput(nd.ni_vp);
7794
error = ENXIO;
7795
NFSD_DEBUG(4, "dsdirpath not an NFS mount\n");
7796
break;
7797
}
7798
ds->nfsdev_dsdir[i] = nd.ni_vp;
7799
NFSVOPUNLOCK(nd.ni_vp);
7800
}
7801
free(dsdirpath, M_TEMP);
7802
7803
if (strlen(mdspathp) > 0) {
7804
/*
7805
* This DS stores file for a specific MDS exported file
7806
* system.
7807
*/
7808
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
7809
UIO_SYSSPACE, mdspathp);
7810
error = namei(&nd);
7811
NFSD_DEBUG(4, "mds lookup=%d\n", error);
7812
if (error != 0)
7813
goto out;
7814
NDFREE_PNBUF(&nd);
7815
if (nd.ni_vp->v_type != VDIR) {
7816
vput(nd.ni_vp);
7817
error = ENOTDIR;
7818
NFSD_DEBUG(4, "mdspath not dir\n");
7819
goto out;
7820
}
7821
mp = nd.ni_vp->v_mount;
7822
if ((mp->mnt_flag & MNT_EXPORTED) == 0) {
7823
vput(nd.ni_vp);
7824
error = ENXIO;
7825
NFSD_DEBUG(4, "mdspath not an exported fs\n");
7826
goto out;
7827
}
7828
ds->nfsdev_mdsfsid = mp->mnt_stat.f_fsid;
7829
ds->nfsdev_mdsisset = 1;
7830
vput(nd.ni_vp);
7831
}
7832
7833
out:
7834
TAILQ_INSERT_TAIL(&nfsrv_devidhead, ds, nfsdev_list);
7835
atomic_add_int(&nfsrv_devidcnt, 1);
7836
return (error);
7837
}
7838
7839
/*
7840
* Look up the mount path for the DS server and delete it.
7841
*/
7842
int
7843
nfsrv_deldsserver(int op, char *dspathp, NFSPROC_T *p)
7844
{
7845
struct mount *mp;
7846
struct nfsmount *nmp;
7847
struct nfsdevice *ds;
7848
int error;
7849
7850
NFSD_DEBUG(4, "deldssrv path=%s\n", dspathp);
7851
/*
7852
* Search for the path in the mount list. Avoid looking the path
7853
* up, since this mount point may be hung, with associated locked
7854
* vnodes, etc.
7855
* Set NFSMNTP_CANCELRPCS so that any forced dismount will be blocked
7856
* until this completes.
7857
* As noted in the man page, this should be done before any forced
7858
* dismount on the mount point, but at least the handshake on
7859
* NFSMNTP_CANCELRPCS should make it safe.
7860
*/
7861
error = 0;
7862
ds = NULL;
7863
nmp = NULL;
7864
mtx_lock(&mountlist_mtx);
7865
TAILQ_FOREACH(mp, &mountlist, mnt_list) {
7866
if (strcmp(mp->mnt_stat.f_mntonname, dspathp) == 0 &&
7867
strcmp(mp->mnt_stat.f_fstypename, "nfs") == 0 &&
7868
mp->mnt_data != NULL) {
7869
nmp = VFSTONFS(mp);
7870
NFSLOCKMNT(nmp);
7871
if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM |
7872
NFSMNTP_CANCELRPCS)) == 0) {
7873
nmp->nm_privflag |= NFSMNTP_CANCELRPCS;
7874
NFSUNLOCKMNT(nmp);
7875
} else {
7876
NFSUNLOCKMNT(nmp);
7877
nmp = NULL;
7878
}
7879
break;
7880
}
7881
}
7882
mtx_unlock(&mountlist_mtx);
7883
7884
if (nmp != NULL) {
7885
ds = nfsrv_deldsnmp(op, nmp, p);
7886
NFSD_DEBUG(4, "deldsnmp=%p\n", ds);
7887
if (ds != NULL) {
7888
nfsrv_killrpcs(nmp);
7889
NFSD_DEBUG(4, "aft killrpcs\n");
7890
} else
7891
error = ENXIO;
7892
NFSLOCKMNT(nmp);
7893
nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS;
7894
wakeup(nmp);
7895
NFSUNLOCKMNT(nmp);
7896
} else
7897
error = EINVAL;
7898
return (error);
7899
}
7900
7901
/*
7902
* Search for and remove a DS entry which matches the "nmp" argument.
7903
* The nfsdevice structure pointer is returned so that the caller can
7904
* free it via nfsrv_freeonedevid().
7905
* For the forced case, do not try to do LayoutRecalls, since the server
7906
* must be shut down now anyhow.
7907
*/
7908
struct nfsdevice *
7909
nfsrv_deldsnmp(int op, struct nfsmount *nmp, NFSPROC_T *p)
7910
{
7911
struct nfsdevice *fndds;
7912
7913
NFSD_DEBUG(4, "deldsdvp\n");
7914
NFSDDSLOCK();
7915
if (op == PNFSDOP_FORCEDELDS)
7916
fndds = nfsv4_findmirror(nmp);
7917
else
7918
fndds = nfsrv_findmirroredds(nmp);
7919
if (fndds != NULL)
7920
nfsrv_deleteds(fndds);
7921
NFSDDSUNLOCK();
7922
if (fndds != NULL) {
7923
if (op != PNFSDOP_FORCEDELDS)
7924
nfsrv_flexmirrordel(fndds->nfsdev_deviceid, p);
7925
printf("pNFS server: mirror %s failed\n", fndds->nfsdev_host);
7926
}
7927
return (fndds);
7928
}
7929
7930
/*
7931
* Similar to nfsrv_deldsnmp(), except that the DS is indicated by deviceid.
7932
* This function also calls nfsrv_killrpcs() to unblock RPCs on the mount
7933
* point.
7934
* Also, returns an error instead of the nfsdevice found.
7935
*/
7936
int
7937
nfsrv_delds(char *devid, NFSPROC_T *p)
7938
{
7939
struct nfsdevice *ds, *fndds;
7940
struct nfsmount *nmp;
7941
int fndmirror;
7942
7943
NFSD_DEBUG(4, "delds\n");
7944
/*
7945
* Search the DS server list for a match with devid.
7946
* Remove the DS entry if found and there is a mirror.
7947
*/
7948
fndds = NULL;
7949
nmp = NULL;
7950
fndmirror = 0;
7951
NFSDDSLOCK();
7952
TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
7953
if (NFSBCMP(ds->nfsdev_deviceid, devid, NFSX_V4DEVICEID) == 0 &&
7954
ds->nfsdev_nmp != NULL) {
7955
NFSD_DEBUG(4, "fnd main ds\n");
7956
fndds = ds;
7957
break;
7958
}
7959
}
7960
if (fndds == NULL) {
7961
NFSDDSUNLOCK();
7962
return (ENXIO);
7963
}
7964
if (fndds->nfsdev_mdsisset == 0 && nfsrv_faildscnt > 0)
7965
fndmirror = 1;
7966
else if (fndds->nfsdev_mdsisset != 0) {
7967
/* For the fsid is set case, search for a mirror. */
7968
TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
7969
if (ds != fndds && ds->nfsdev_nmp != NULL &&
7970
ds->nfsdev_mdsisset != 0 &&
7971
fsidcmp(&ds->nfsdev_mdsfsid,
7972
&fndds->nfsdev_mdsfsid) == 0) {
7973
fndmirror = 1;
7974
break;
7975
}
7976
}
7977
}
7978
if (fndmirror != 0) {
7979
nmp = fndds->nfsdev_nmp;
7980
NFSLOCKMNT(nmp);
7981
if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM |
7982
NFSMNTP_CANCELRPCS)) == 0) {
7983
nmp->nm_privflag |= NFSMNTP_CANCELRPCS;
7984
NFSUNLOCKMNT(nmp);
7985
nfsrv_deleteds(fndds);
7986
} else {
7987
NFSUNLOCKMNT(nmp);
7988
nmp = NULL;
7989
}
7990
}
7991
NFSDDSUNLOCK();
7992
if (nmp != NULL) {
7993
nfsrv_flexmirrordel(fndds->nfsdev_deviceid, p);
7994
printf("pNFS server: mirror %s failed\n", fndds->nfsdev_host);
7995
nfsrv_killrpcs(nmp);
7996
NFSLOCKMNT(nmp);
7997
nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS;
7998
wakeup(nmp);
7999
NFSUNLOCKMNT(nmp);
8000
return (0);
8001
}
8002
return (ENXIO);
8003
}
8004
8005
/*
8006
* Mark a DS as disabled by setting nfsdev_nmp = NULL.
8007
*/
8008
static void
8009
nfsrv_deleteds(struct nfsdevice *fndds)
8010
{
8011
8012
NFSD_DEBUG(4, "deleteds: deleting a mirror\n");
8013
fndds->nfsdev_nmp = NULL;
8014
if (fndds->nfsdev_mdsisset == 0)
8015
nfsrv_faildscnt--;
8016
}
8017
8018
/*
8019
* Fill in the addr structures for the File and Flex File layouts.
8020
*/
8021
static void
8022
nfsrv_allocdevid(struct nfsdevice *ds, char *addr, char *dnshost)
8023
{
8024
uint32_t *tl;
8025
char *netprot;
8026
int addrlen;
8027
static uint64_t new_devid = 0;
8028
8029
if (strchr(addr, ':') != NULL)
8030
netprot = "tcp6";
8031
else
8032
netprot = "tcp";
8033
8034
/* Fill in the device id. */
8035
NFSBCOPY(&nfsdev_time, ds->nfsdev_deviceid, sizeof(nfsdev_time));
8036
new_devid++;
8037
NFSBCOPY(&new_devid, &ds->nfsdev_deviceid[sizeof(nfsdev_time)],
8038
sizeof(new_devid));
8039
8040
/*
8041
* Fill in the file addr (actually the nfsv4_file_layout_ds_addr4
8042
* as defined in RFC5661) in XDR.
8043
*/
8044
addrlen = NFSM_RNDUP(strlen(addr)) + NFSM_RNDUP(strlen(netprot)) +
8045
6 * NFSX_UNSIGNED;
8046
NFSD_DEBUG(4, "hn=%s addr=%s netprot=%s\n", dnshost, addr, netprot);
8047
ds->nfsdev_fileaddrlen = addrlen;
8048
tl = malloc(addrlen, M_NFSDSTATE, M_WAITOK | M_ZERO);
8049
ds->nfsdev_fileaddr = (char *)tl;
8050
*tl++ = txdr_unsigned(1); /* One stripe with index 0. */
8051
*tl++ = 0;
8052
*tl++ = txdr_unsigned(1); /* One multipath list */
8053
*tl++ = txdr_unsigned(1); /* with one entry in it. */
8054
/* The netaddr for this one entry. */
8055
*tl++ = txdr_unsigned(strlen(netprot));
8056
NFSBCOPY(netprot, tl, strlen(netprot));
8057
tl += (NFSM_RNDUP(strlen(netprot)) / NFSX_UNSIGNED);
8058
*tl++ = txdr_unsigned(strlen(addr));
8059
NFSBCOPY(addr, tl, strlen(addr));
8060
8061
/*
8062
* Fill in the flex file addr (actually the ff_device_addr4
8063
* as defined for Flexible File Layout) in XDR.
8064
*/
8065
addrlen = NFSM_RNDUP(strlen(addr)) + NFSM_RNDUP(strlen(netprot)) +
8066
14 * NFSX_UNSIGNED;
8067
ds->nfsdev_flexaddrlen = addrlen;
8068
tl = malloc(addrlen, M_NFSDSTATE, M_WAITOK | M_ZERO);
8069
ds->nfsdev_flexaddr = (char *)tl;
8070
*tl++ = txdr_unsigned(1); /* One multipath entry. */
8071
/* The netaddr for this one entry. */
8072
*tl++ = txdr_unsigned(strlen(netprot));
8073
NFSBCOPY(netprot, tl, strlen(netprot));
8074
tl += (NFSM_RNDUP(strlen(netprot)) / NFSX_UNSIGNED);
8075
*tl++ = txdr_unsigned(strlen(addr));
8076
NFSBCOPY(addr, tl, strlen(addr));
8077
tl += (NFSM_RNDUP(strlen(addr)) / NFSX_UNSIGNED);
8078
*tl++ = txdr_unsigned(2); /* Two NFS Versions. */
8079
*tl++ = txdr_unsigned(NFS_VER4); /* NFSv4. */
8080
*tl++ = txdr_unsigned(NFSV42_MINORVERSION); /* Minor version 2. */
8081
*tl++ = txdr_unsigned(nfs_srvmaxio); /* DS max rsize. */
8082
*tl++ = txdr_unsigned(nfs_srvmaxio); /* DS max wsize. */
8083
*tl++ = newnfs_true; /* Tightly coupled. */
8084
*tl++ = txdr_unsigned(NFS_VER4); /* NFSv4. */
8085
*tl++ = txdr_unsigned(NFSV41_MINORVERSION); /* Minor version 1. */
8086
*tl++ = txdr_unsigned(nfs_srvmaxio); /* DS max rsize. */
8087
*tl++ = txdr_unsigned(nfs_srvmaxio); /* DS max wsize. */
8088
*tl = newnfs_true; /* Tightly coupled. */
8089
8090
ds->nfsdev_hostnamelen = strlen(dnshost);
8091
ds->nfsdev_host = malloc(ds->nfsdev_hostnamelen + 1, M_NFSDSTATE,
8092
M_WAITOK);
8093
NFSBCOPY(dnshost, ds->nfsdev_host, ds->nfsdev_hostnamelen + 1);
8094
}
8095
8096
/*
8097
* Create the device id list.
8098
* Return 0 if the nfsd threads are to run and ENXIO if the "-p" argument
8099
* is misconfigured.
8100
*/
8101
int
8102
nfsrv_createdevids(struct nfsd_nfsd_args *args, NFSPROC_T *p)
8103
{
8104
struct nfsdevice *ds;
8105
char *addrp, *dnshostp, *dspathp, *mdspathp;
8106
int error, i;
8107
8108
addrp = args->addr;
8109
dnshostp = args->dnshost;
8110
dspathp = args->dspath;
8111
mdspathp = args->mdspath;
8112
nfsrv_maxpnfsmirror = args->mirrorcnt;
8113
if (addrp == NULL || dnshostp == NULL || dspathp == NULL ||
8114
mdspathp == NULL)
8115
return (0);
8116
8117
/*
8118
* Loop around for each nul-terminated string in args->addr,
8119
* args->dnshost, args->dnspath and args->mdspath.
8120
*/
8121
while (addrp < (args->addr + args->addrlen) &&
8122
dnshostp < (args->dnshost + args->dnshostlen) &&
8123
dspathp < (args->dspath + args->dspathlen) &&
8124
mdspathp < (args->mdspath + args->mdspathlen)) {
8125
error = nfsrv_setdsserver(dspathp, mdspathp, p, &ds);
8126
if (error != 0) {
8127
/* Free all DS servers. */
8128
nfsrv_freealldevids();
8129
nfsrv_devidcnt = 0;
8130
return (ENXIO);
8131
}
8132
nfsrv_allocdevid(ds, addrp, dnshostp);
8133
addrp += (strlen(addrp) + 1);
8134
dnshostp += (strlen(dnshostp) + 1);
8135
dspathp += (strlen(dspathp) + 1);
8136
mdspathp += (strlen(mdspathp) + 1);
8137
}
8138
if (nfsrv_devidcnt < nfsrv_maxpnfsmirror) {
8139
/* Free all DS servers. */
8140
nfsrv_freealldevids();
8141
nfsrv_devidcnt = 0;
8142
nfsrv_maxpnfsmirror = 1;
8143
return (ENXIO);
8144
}
8145
/* We can fail at most one less DS than the mirror level. */
8146
nfsrv_faildscnt = nfsrv_maxpnfsmirror - 1;
8147
8148
/*
8149
* Allocate the nfslayout hash table now, since this is a pNFS server.
8150
* Make it 1% of the high water mark and at least 100.
8151
*/
8152
if (nfslayouthash == NULL) {
8153
nfsrv_layouthashsize = nfsrv_layouthighwater / 100;
8154
if (nfsrv_layouthashsize < 100)
8155
nfsrv_layouthashsize = 100;
8156
nfslayouthash = mallocarray(nfsrv_layouthashsize,
8157
sizeof(struct nfslayouthash), M_NFSDSESSION, M_WAITOK |
8158
M_ZERO);
8159
for (i = 0; i < nfsrv_layouthashsize; i++) {
8160
mtx_init(&nfslayouthash[i].mtx, "nfslm", NULL, MTX_DEF);
8161
TAILQ_INIT(&nfslayouthash[i].list);
8162
}
8163
}
8164
return (0);
8165
}
8166
8167
/*
8168
* Free all device ids.
8169
*/
8170
static void
8171
nfsrv_freealldevids(void)
8172
{
8173
struct nfsdevice *ds, *nds;
8174
8175
TAILQ_FOREACH_SAFE(ds, &nfsrv_devidhead, nfsdev_list, nds)
8176
nfsrv_freedevid(ds);
8177
}
8178
8179
/*
8180
* Check to see if there is a Read/Write Layout plus either:
8181
* - A Write Delegation
8182
* or
8183
* - An Open with Write_access.
8184
* Return 1 if this is the case and 0 otherwise.
8185
* This function is used by nfsrv_proxyds() to decide if doing a Proxy
8186
* Getattr RPC to the Data Server (DS) is necessary.
8187
*/
8188
#define NFSCLIDVECSIZE 6
8189
int
8190
nfsrv_checkdsattr(vnode_t vp, NFSPROC_T *p)
8191
{
8192
fhandle_t fh, *tfhp;
8193
struct nfsstate *stp;
8194
struct nfslayout *lyp;
8195
struct nfslayouthash *lhyp;
8196
struct nfslockhashhead *hp;
8197
struct nfslockfile *lfp;
8198
nfsquad_t clid[NFSCLIDVECSIZE];
8199
int clidcnt, ret;
8200
8201
ret = nfsvno_getfh(vp, &fh, p);
8202
if (ret != 0)
8203
return (0);
8204
8205
/* First check for a Read/Write Layout. */
8206
clidcnt = 0;
8207
lhyp = NFSLAYOUTHASH(&fh);
8208
NFSLOCKLAYOUT(lhyp);
8209
TAILQ_FOREACH(lyp, &lhyp->list, lay_list) {
8210
if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 &&
8211
((lyp->lay_flags & NFSLAY_RW) != 0 ||
8212
((lyp->lay_flags & NFSLAY_READ) != 0 &&
8213
nfsrv_pnfsatime != 0))) {
8214
if (clidcnt < NFSCLIDVECSIZE)
8215
clid[clidcnt].qval = lyp->lay_clientid.qval;
8216
clidcnt++;
8217
}
8218
}
8219
NFSUNLOCKLAYOUT(lhyp);
8220
if (clidcnt == 0) {
8221
/* None found, so return 0. */
8222
return (0);
8223
}
8224
8225
/* Get the nfslockfile for this fh. */
8226
NFSLOCKSTATE();
8227
hp = NFSLOCKHASH(&fh);
8228
LIST_FOREACH(lfp, hp, lf_hash) {
8229
tfhp = &lfp->lf_fh;
8230
if (NFSVNO_CMPFH(&fh, tfhp))
8231
break;
8232
}
8233
if (lfp == NULL) {
8234
/* None found, so return 0. */
8235
NFSUNLOCKSTATE();
8236
return (0);
8237
}
8238
8239
/* Now, look for a Write delegation for this clientid. */
8240
LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
8241
if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0 &&
8242
nfsrv_fndclid(clid, stp->ls_clp->lc_clientid, clidcnt) != 0)
8243
break;
8244
}
8245
if (stp != NULL) {
8246
/* Found one, so return 1. */
8247
NFSUNLOCKSTATE();
8248
return (1);
8249
}
8250
8251
/* No Write delegation, so look for an Open with Write_access. */
8252
LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
8253
KASSERT((stp->ls_flags & NFSLCK_OPEN) != 0,
8254
("nfsrv_checkdsattr: Non-open in Open list\n"));
8255
if ((stp->ls_flags & NFSLCK_WRITEACCESS) != 0 &&
8256
nfsrv_fndclid(clid, stp->ls_clp->lc_clientid, clidcnt) != 0)
8257
break;
8258
}
8259
NFSUNLOCKSTATE();
8260
if (stp != NULL)
8261
return (1);
8262
return (0);
8263
}
8264
8265
/*
8266
* Look for a matching clientid in the vector. Return 1 if one might match.
8267
*/
8268
static int
8269
nfsrv_fndclid(nfsquad_t *clidvec, nfsquad_t clid, int clidcnt)
8270
{
8271
int i;
8272
8273
/* If too many for the vector, return 1 since there might be a match. */
8274
if (clidcnt > NFSCLIDVECSIZE)
8275
return (1);
8276
8277
for (i = 0; i < clidcnt; i++)
8278
if (clidvec[i].qval == clid.qval)
8279
return (1);
8280
return (0);
8281
}
8282
8283
/*
8284
* Check the don't list for "vp" and see if issuing an rw layout is allowed.
8285
* Return 1 if issuing an rw layout isn't allowed, 0 otherwise.
8286
*/
8287
static int
8288
nfsrv_dontlayout(fhandle_t *fhp)
8289
{
8290
struct nfsdontlist *mrp;
8291
int ret;
8292
8293
if (nfsrv_dontlistlen == 0)
8294
return (0);
8295
ret = 0;
8296
NFSDDONTLISTLOCK();
8297
LIST_FOREACH(mrp, &nfsrv_dontlisthead, nfsmr_list) {
8298
if (NFSBCMP(fhp, &mrp->nfsmr_fh, sizeof(*fhp)) == 0 &&
8299
(mrp->nfsmr_flags & NFSMR_DONTLAYOUT) != 0) {
8300
ret = 1;
8301
break;
8302
}
8303
}
8304
NFSDDONTLISTUNLOCK();
8305
return (ret);
8306
}
8307
8308
#define PNFSDS_COPYSIZ 65536
8309
/*
8310
* Create a new file on a DS and copy the contents of an extant DS file to it.
8311
* This can be used for recovery of a DS file onto a recovered DS.
8312
* The steps are:
8313
* - When called, the MDS file's vnode is locked, blocking LayoutGet operations.
8314
* - Disable issuing of read/write layouts for the file via the nfsdontlist,
8315
* so that they will be disabled after the MDS file's vnode is unlocked.
8316
* - Set up the nfsrv_recalllist so that recall of read/write layouts can
8317
* be done.
8318
* - Unlock the MDS file's vnode, so that the client(s) can perform proxied
8319
* writes, LayoutCommits and LayoutReturns for the file when completing the
8320
* LayoutReturn requested by the LayoutRecall callback.
8321
* - Issue a LayoutRecall callback for all read/write layouts and wait for
8322
* them to be returned. (If the LayoutRecall callback replies
8323
* NFSERR_NOMATCHLAYOUT, they are gone and no LayoutReturn is needed.)
8324
* - Exclusively lock the MDS file's vnode. This ensures that no proxied
8325
* writes are in progress or can occur during the DS file copy.
8326
* It also blocks Setattr operations.
8327
* - Create the file on the recovered mirror.
8328
* - Copy the file from the operational DS.
8329
* - Copy any ACL from the MDS file to the new DS file.
8330
* - Set the modify time of the new DS file to that of the MDS file.
8331
* - Update the extended attribute for the MDS file.
8332
* - Enable issuing of rw layouts by deleting the nfsdontlist entry.
8333
* - The caller will unlock the MDS file's vnode allowing operations
8334
* to continue normally, since it is now on the mirror again.
8335
*/
8336
int
8337
nfsrv_copymr(vnode_t vp, vnode_t fvp, vnode_t dvp, struct nfsdevice *ds,
8338
struct pnfsdsfile *pf, struct pnfsdsfile *wpf, int mirrorcnt,
8339
struct ucred *cred, NFSPROC_T *p)
8340
{
8341
struct nfsdontlist *mrp, *nmrp;
8342
struct nfslayouthash *lhyp;
8343
struct nfslayout *lyp, *nlyp;
8344
struct nfslayouthead thl;
8345
struct mount *mp, *tvmp;
8346
struct acl *aclp;
8347
struct vattr va;
8348
struct timespec mtime;
8349
fhandle_t fh;
8350
vnode_t tvp;
8351
off_t rdpos, wrpos;
8352
ssize_t aresid;
8353
char *dat;
8354
int didprintf, ret, retacl, xfer;
8355
8356
ASSERT_VOP_LOCKED(fvp, "nfsrv_copymr fvp");
8357
ASSERT_VOP_LOCKED(vp, "nfsrv_copymr vp");
8358
/*
8359
* Allocate a nfsdontlist entry and set the NFSMR_DONTLAYOUT flag
8360
* so that no more RW layouts will get issued.
8361
*/
8362
ret = nfsvno_getfh(vp, &fh, p);
8363
if (ret != 0) {
8364
NFSD_DEBUG(4, "nfsrv_copymr: getfh=%d\n", ret);
8365
return (ret);
8366
}
8367
nmrp = malloc(sizeof(*nmrp), M_NFSDSTATE, M_WAITOK);
8368
nmrp->nfsmr_flags = NFSMR_DONTLAYOUT;
8369
NFSBCOPY(&fh, &nmrp->nfsmr_fh, sizeof(fh));
8370
NFSDDONTLISTLOCK();
8371
LIST_FOREACH(mrp, &nfsrv_dontlisthead, nfsmr_list) {
8372
if (NFSBCMP(&fh, &mrp->nfsmr_fh, sizeof(fh)) == 0)
8373
break;
8374
}
8375
if (mrp == NULL) {
8376
LIST_INSERT_HEAD(&nfsrv_dontlisthead, nmrp, nfsmr_list);
8377
mrp = nmrp;
8378
nmrp = NULL;
8379
nfsrv_dontlistlen++;
8380
NFSD_DEBUG(4, "nfsrv_copymr: in dontlist\n");
8381
} else {
8382
NFSDDONTLISTUNLOCK();
8383
free(nmrp, M_NFSDSTATE);
8384
NFSD_DEBUG(4, "nfsrv_copymr: dup dontlist\n");
8385
return (ENXIO);
8386
}
8387
NFSDDONTLISTUNLOCK();
8388
8389
/*
8390
* Search for all RW layouts for this file. Move them to the
8391
* recall list, so they can be recalled and their return noted.
8392
*/
8393
lhyp = NFSLAYOUTHASH(&fh);
8394
NFSDRECALLLOCK();
8395
NFSLOCKLAYOUT(lhyp);
8396
TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
8397
if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 &&
8398
(lyp->lay_flags & NFSLAY_RW) != 0) {
8399
TAILQ_REMOVE(&lhyp->list, lyp, lay_list);
8400
TAILQ_INSERT_HEAD(&nfsrv_recalllisthead, lyp, lay_list);
8401
lyp->lay_trycnt = 0;
8402
}
8403
}
8404
NFSUNLOCKLAYOUT(lhyp);
8405
NFSDRECALLUNLOCK();
8406
8407
ret = 0;
8408
mp = tvmp = NULL;
8409
didprintf = 0;
8410
TAILQ_INIT(&thl);
8411
/* Unlock the MDS vp, so that a LayoutReturn can be done on it. */
8412
NFSVOPUNLOCK(vp);
8413
/* Now, do a recall for all layouts not yet recalled. */
8414
tryagain:
8415
NFSDRECALLLOCK();
8416
TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) {
8417
if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 &&
8418
(lyp->lay_flags & NFSLAY_RECALL) == 0) {
8419
lyp->lay_flags |= NFSLAY_RECALL;
8420
/*
8421
* The layout stateid.seqid needs to be incremented
8422
* before doing a LAYOUT_RECALL callback.
8423
*/
8424
if (++lyp->lay_stateid.seqid == 0)
8425
lyp->lay_stateid.seqid = 1;
8426
NFSDRECALLUNLOCK();
8427
nfsrv_recalllayout(lyp->lay_clientid, &lyp->lay_stateid,
8428
&lyp->lay_fh, lyp, 0, lyp->lay_type, p);
8429
NFSD_DEBUG(4, "nfsrv_copymr: recalled layout\n");
8430
goto tryagain;
8431
}
8432
}
8433
8434
/* Now wait for them to be returned. */
8435
tryagain2:
8436
TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) {
8437
if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0) {
8438
if ((lyp->lay_flags & NFSLAY_RETURNED) != 0) {
8439
TAILQ_REMOVE(&nfsrv_recalllisthead, lyp,
8440
lay_list);
8441
TAILQ_INSERT_HEAD(&thl, lyp, lay_list);
8442
NFSD_DEBUG(4,
8443
"nfsrv_copymr: layout returned\n");
8444
} else {
8445
lyp->lay_trycnt++;
8446
ret = mtx_sleep(lyp, NFSDRECALLMUTEXPTR,
8447
PVFS | PCATCH, "nfsmrl", hz);
8448
NFSD_DEBUG(4, "nfsrv_copymr: aft sleep=%d\n",
8449
ret);
8450
if (ret == EINTR || ret == ERESTART)
8451
break;
8452
if ((lyp->lay_flags & NFSLAY_RETURNED) == 0) {
8453
/*
8454
* Give up after 60sec and return
8455
* ENXIO, failing the copymr.
8456
* This layout will remain on the
8457
* recalllist. It can only be cleared
8458
* by restarting the nfsd.
8459
* This seems the safe way to handle
8460
* it, since it cannot be safely copied
8461
* with an outstanding RW layout.
8462
*/
8463
if (lyp->lay_trycnt >= 60) {
8464
ret = ENXIO;
8465
break;
8466
}
8467
if (didprintf == 0) {
8468
printf("nfsrv_copymr: layout "
8469
"not returned\n");
8470
didprintf = 1;
8471
}
8472
}
8473
}
8474
goto tryagain2;
8475
}
8476
}
8477
NFSDRECALLUNLOCK();
8478
/* We can now get rid of the layouts that have been returned. */
8479
TAILQ_FOREACH_SAFE(lyp, &thl, lay_list, nlyp)
8480
nfsrv_freelayout(&thl, lyp);
8481
8482
/*
8483
* Do the vn_start_write() calls here, before the MDS vnode is
8484
* locked and the tvp is created (locked) in the NFS file system
8485
* that dvp is in.
8486
* For tvmp, this probably isn't necessary, since it will be an
8487
* NFS mount and they are not suspendable at this time.
8488
*/
8489
if (ret == 0)
8490
ret = vn_start_write(vp, &mp, V_WAIT | V_PCATCH);
8491
if (ret == 0) {
8492
tvmp = dvp->v_mount;
8493
ret = vn_start_write(NULL, &tvmp, V_WAIT | V_PCATCH);
8494
}
8495
8496
/*
8497
* LK_EXCLUSIVE lock the MDS vnode, so that any
8498
* proxied writes through the MDS will be blocked until we have
8499
* completed the copy and update of the extended attributes.
8500
* This will also ensure that any attributes and ACL will not be
8501
* changed until the copy is complete.
8502
*/
8503
NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
8504
if (ret == 0 && VN_IS_DOOMED(vp)) {
8505
NFSD_DEBUG(4, "nfsrv_copymr: lk_exclusive doomed\n");
8506
ret = ESTALE;
8507
}
8508
8509
/* Create the data file on the recovered DS. */
8510
if (ret == 0)
8511
ret = nfsrv_createdsfile(vp, &fh, pf, dvp, ds, cred, p, &tvp);
8512
8513
/* Copy the DS file, if created successfully. */
8514
if (ret == 0) {
8515
/*
8516
* Get any NFSv4 ACL on the MDS file, so that it can be set
8517
* on the new DS file.
8518
*/
8519
aclp = acl_alloc(M_WAITOK | M_ZERO);
8520
retacl = VOP_GETACL(vp, ACL_TYPE_NFS4, aclp, cred, p);
8521
if (retacl != 0 && retacl != ENOATTR)
8522
NFSD_DEBUG(1, "nfsrv_copymr: vop_getacl=%d\n", retacl);
8523
dat = malloc(PNFSDS_COPYSIZ, M_TEMP, M_WAITOK);
8524
/* Malloc a block of 0s used to check for holes. */
8525
if (nfsrv_zeropnfsdat == NULL)
8526
nfsrv_zeropnfsdat = malloc(PNFSDS_COPYSIZ, M_TEMP,
8527
M_WAITOK | M_ZERO);
8528
rdpos = wrpos = 0;
8529
ret = VOP_GETATTR(fvp, &va, cred);
8530
aresid = 0;
8531
while (ret == 0 && aresid == 0) {
8532
ret = vn_rdwr(UIO_READ, fvp, dat, PNFSDS_COPYSIZ,
8533
rdpos, UIO_SYSSPACE, IO_NODELOCKED, cred, NULL,
8534
&aresid, p);
8535
xfer = PNFSDS_COPYSIZ - aresid;
8536
if (ret == 0 && xfer > 0) {
8537
rdpos += xfer;
8538
/*
8539
* Skip the write for holes, except for the
8540
* last block.
8541
*/
8542
if (xfer < PNFSDS_COPYSIZ || rdpos ==
8543
va.va_size || NFSBCMP(dat,
8544
nfsrv_zeropnfsdat, PNFSDS_COPYSIZ) != 0)
8545
ret = vn_rdwr(UIO_WRITE, tvp, dat, xfer,
8546
wrpos, UIO_SYSSPACE, IO_NODELOCKED,
8547
cred, NULL, NULL, p);
8548
if (ret == 0)
8549
wrpos += xfer;
8550
}
8551
}
8552
8553
/* If there is an ACL and the copy succeeded, set the ACL. */
8554
if (ret == 0 && retacl == 0) {
8555
ret = VOP_SETACL(tvp, ACL_TYPE_NFS4, aclp, cred, p);
8556
/*
8557
* Don't consider these as errors, since VOP_GETACL()
8558
* can return an ACL when they are not actually
8559
* supported. For example, for UFS, VOP_GETACL()
8560
* will return a trivial ACL based on the uid/gid/mode
8561
* when there is no ACL on the file.
8562
* This case should be recognized as a trivial ACL
8563
* by UFS's VOP_SETACL() and succeed, but...
8564
*/
8565
if (ret == ENOATTR || ret == EOPNOTSUPP || ret == EPERM)
8566
ret = 0;
8567
}
8568
8569
if (ret == 0)
8570
ret = VOP_FSYNC(tvp, MNT_WAIT, p);
8571
8572
/* Set the DS data file's modify time that of the MDS file. */
8573
if (ret == 0)
8574
ret = VOP_GETATTR(vp, &va, cred);
8575
if (ret == 0) {
8576
mtime = va.va_mtime;
8577
VATTR_NULL(&va);
8578
va.va_mtime = mtime;
8579
ret = VOP_SETATTR(tvp, &va, cred);
8580
}
8581
8582
vput(tvp);
8583
acl_free(aclp);
8584
free(dat, M_TEMP);
8585
}
8586
if (tvmp != NULL)
8587
vn_finished_write(tvmp);
8588
8589
/* Update the extended attributes for the newly created DS file. */
8590
if (ret == 0)
8591
ret = vn_extattr_set(vp, IO_NODELOCKED,
8592
EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile",
8593
sizeof(*wpf) * mirrorcnt, (char *)wpf, p);
8594
if (mp != NULL)
8595
vn_finished_write(mp);
8596
8597
/* Get rid of the dontlist entry, so that Layouts can be issued. */
8598
NFSDDONTLISTLOCK();
8599
LIST_REMOVE(mrp, nfsmr_list);
8600
NFSDDONTLISTUNLOCK();
8601
free(mrp, M_NFSDSTATE);
8602
return (ret);
8603
}
8604
8605
/*
8606
* Create a data storage file on the recovered DS.
8607
*/
8608
static int
8609
nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf,
8610
vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p,
8611
vnode_t *tvpp)
8612
{
8613
struct vattr va, nva;
8614
int error;
8615
8616
/* Make data file name based on FH. */
8617
error = VOP_GETATTR(vp, &va, cred);
8618
if (error == 0) {
8619
/* Set the attributes for "vp" to Setattr the DS vp. */
8620
VATTR_NULL(&nva);
8621
nva.va_uid = va.va_uid;
8622
nva.va_gid = va.va_gid;
8623
nva.va_mode = va.va_mode;
8624
nva.va_size = 0;
8625
VATTR_NULL(&va);
8626
va.va_type = VREG;
8627
va.va_mode = nva.va_mode;
8628
NFSD_DEBUG(4, "nfsrv_dscreatefile: dvp=%p pf=%p\n", dvp, pf);
8629
error = nfsrv_dscreate(dvp, &va, &nva, fhp, pf, NULL,
8630
pf->dsf_filename, cred, p, tvpp);
8631
}
8632
return (error);
8633
}
8634
8635
/*
8636
* Look up the MDS file shared locked, and then get the extended attribute
8637
* to find the extant DS file to be copied to the new mirror.
8638
* If successful, *vpp is set to the MDS file's vp and *nvpp is
8639
* set to a DS data file for the MDS file, both exclusively locked.
8640
* The "buf" argument has the pnfsdsfile structure from the MDS file
8641
* in it and buflen is set to its length.
8642
*/
8643
int
8644
nfsrv_mdscopymr(char *mdspathp, char *dspathp, char *curdspathp, char *buf,
8645
int *buflenp, char *fname, NFSPROC_T *p, struct vnode **vpp,
8646
struct vnode **nvpp, struct pnfsdsfile **pfp, struct nfsdevice **dsp,
8647
struct nfsdevice **fdsp)
8648
{
8649
struct nameidata nd;
8650
struct vnode *vp, *curvp;
8651
struct pnfsdsfile *pf;
8652
struct nfsmount *nmp, *curnmp;
8653
int dsdir, error, mirrorcnt, ippos;
8654
8655
vp = NULL;
8656
curvp = NULL;
8657
curnmp = NULL;
8658
*dsp = NULL;
8659
*fdsp = NULL;
8660
if (dspathp == NULL && curdspathp != NULL)
8661
return (EPERM);
8662
8663
/*
8664
* Look up the MDS file shared locked. The lock will be upgraded
8665
* to an exclusive lock after any rw layouts have been returned.
8666
*/
8667
NFSD_DEBUG(4, "mdsopen path=%s\n", mdspathp);
8668
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE,
8669
mdspathp);
8670
error = namei(&nd);
8671
NFSD_DEBUG(4, "lookup=%d\n", error);
8672
if (error != 0)
8673
return (error);
8674
NDFREE_PNBUF(&nd);
8675
if (nd.ni_vp->v_type != VREG) {
8676
vput(nd.ni_vp);
8677
NFSD_DEBUG(4, "mdspath not reg\n");
8678
return (EISDIR);
8679
}
8680
vp = nd.ni_vp;
8681
8682
if (curdspathp != NULL) {
8683
/*
8684
* Look up the current DS path and find the nfsdev structure for
8685
* it.
8686
*/
8687
NFSD_DEBUG(4, "curmdsdev path=%s\n", curdspathp);
8688
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
8689
UIO_SYSSPACE, curdspathp);
8690
error = namei(&nd);
8691
NFSD_DEBUG(4, "ds lookup=%d\n", error);
8692
if (error != 0) {
8693
vput(vp);
8694
return (error);
8695
}
8696
NDFREE_PNBUF(&nd);
8697
if (nd.ni_vp->v_type != VDIR) {
8698
vput(nd.ni_vp);
8699
vput(vp);
8700
NFSD_DEBUG(4, "curdspath not dir\n");
8701
return (ENOTDIR);
8702
}
8703
if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) {
8704
vput(nd.ni_vp);
8705
vput(vp);
8706
NFSD_DEBUG(4, "curdspath not an NFS mount\n");
8707
return (ENXIO);
8708
}
8709
curnmp = VFSTONFS(nd.ni_vp->v_mount);
8710
8711
/* Search the nfsdev list for a match. */
8712
NFSDDSLOCK();
8713
*fdsp = nfsv4_findmirror(curnmp);
8714
NFSDDSUNLOCK();
8715
if (*fdsp == NULL)
8716
curnmp = NULL;
8717
if (curnmp == NULL) {
8718
vput(nd.ni_vp);
8719
vput(vp);
8720
NFSD_DEBUG(4, "mdscopymr: no current ds\n");
8721
return (ENXIO);
8722
}
8723
curvp = nd.ni_vp;
8724
}
8725
8726
if (dspathp != NULL) {
8727
/* Look up the nfsdev path and find the nfsdev structure. */
8728
NFSD_DEBUG(4, "mdsdev path=%s\n", dspathp);
8729
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
8730
UIO_SYSSPACE, dspathp);
8731
error = namei(&nd);
8732
NFSD_DEBUG(4, "ds lookup=%d\n", error);
8733
if (error != 0) {
8734
vput(vp);
8735
if (curvp != NULL)
8736
vput(curvp);
8737
return (error);
8738
}
8739
NDFREE_PNBUF(&nd);
8740
if (nd.ni_vp->v_type != VDIR || nd.ni_vp == curvp) {
8741
vput(nd.ni_vp);
8742
vput(vp);
8743
if (curvp != NULL)
8744
vput(curvp);
8745
NFSD_DEBUG(4, "dspath not dir\n");
8746
if (nd.ni_vp == curvp)
8747
return (EPERM);
8748
return (ENOTDIR);
8749
}
8750
if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) {
8751
vput(nd.ni_vp);
8752
vput(vp);
8753
if (curvp != NULL)
8754
vput(curvp);
8755
NFSD_DEBUG(4, "dspath not an NFS mount\n");
8756
return (ENXIO);
8757
}
8758
nmp = VFSTONFS(nd.ni_vp->v_mount);
8759
8760
/*
8761
* Search the nfsdevice list for a match. If curnmp == NULL,
8762
* this is a recovery and there must be a mirror.
8763
*/
8764
NFSDDSLOCK();
8765
if (curnmp == NULL)
8766
*dsp = nfsrv_findmirroredds(nmp);
8767
else
8768
*dsp = nfsv4_findmirror(nmp);
8769
NFSDDSUNLOCK();
8770
if (*dsp == NULL) {
8771
vput(nd.ni_vp);
8772
vput(vp);
8773
if (curvp != NULL)
8774
vput(curvp);
8775
NFSD_DEBUG(4, "mdscopymr: no ds\n");
8776
return (ENXIO);
8777
}
8778
} else {
8779
nd.ni_vp = NULL;
8780
nmp = NULL;
8781
}
8782
8783
/*
8784
* Get a vp for an available DS data file using the extended
8785
* attribute on the MDS file.
8786
* If there is a valid entry for the new DS in the extended attribute
8787
* on the MDS file (as checked via the nmp argument),
8788
* nfsrv_dsgetsockmnt() returns EEXIST, so no copying will occur.
8789
*/
8790
error = nfsrv_dsgetsockmnt(vp, 0, buf, buflenp, &mirrorcnt, p,
8791
NULL, NULL, NULL, fname, nvpp, &nmp, curnmp, &ippos, &dsdir);
8792
if (curvp != NULL)
8793
vput(curvp);
8794
if (nd.ni_vp == NULL) {
8795
if (error == 0 && nmp != NULL) {
8796
/* Search the nfsdev list for a match. */
8797
NFSDDSLOCK();
8798
*dsp = nfsrv_findmirroredds(nmp);
8799
NFSDDSUNLOCK();
8800
}
8801
if (error == 0 && (nmp == NULL || *dsp == NULL)) {
8802
if (nvpp != NULL && *nvpp != NULL) {
8803
vput(*nvpp);
8804
*nvpp = NULL;
8805
}
8806
error = ENXIO;
8807
}
8808
} else
8809
vput(nd.ni_vp);
8810
8811
/*
8812
* When dspathp != NULL and curdspathp == NULL, this is a recovery
8813
* and is only allowed if there is a 0.0.0.0 IP address entry.
8814
* When curdspathp != NULL, the ippos will be set to that entry.
8815
*/
8816
if (error == 0 && dspathp != NULL && ippos == -1) {
8817
if (nvpp != NULL && *nvpp != NULL) {
8818
vput(*nvpp);
8819
*nvpp = NULL;
8820
}
8821
error = ENXIO;
8822
}
8823
if (error == 0) {
8824
*vpp = vp;
8825
8826
pf = (struct pnfsdsfile *)buf;
8827
if (ippos == -1) {
8828
/* If no zeroip pnfsdsfile, add one. */
8829
ippos = *buflenp / sizeof(*pf);
8830
*buflenp += sizeof(*pf);
8831
pf += ippos;
8832
pf->dsf_dir = dsdir;
8833
strlcpy(pf->dsf_filename, fname,
8834
sizeof(pf->dsf_filename));
8835
} else
8836
pf += ippos;
8837
*pfp = pf;
8838
} else
8839
vput(vp);
8840
return (error);
8841
}
8842
8843
/*
8844
* Search for a matching pnfsd mirror device structure, base on the nmp arg.
8845
* Return one if found, NULL otherwise.
8846
*/
8847
static struct nfsdevice *
8848
nfsrv_findmirroredds(struct nfsmount *nmp)
8849
{
8850
struct nfsdevice *ds, *fndds;
8851
int fndmirror;
8852
8853
mtx_assert(NFSDDSMUTEXPTR, MA_OWNED);
8854
/*
8855
* Search the DS server list for a match with nmp.
8856
* Remove the DS entry if found and there is a mirror.
8857
*/
8858
fndds = NULL;
8859
fndmirror = 0;
8860
if (nfsrv_devidcnt == 0)
8861
return (fndds);
8862
TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
8863
if (ds->nfsdev_nmp == nmp) {
8864
NFSD_DEBUG(4, "nfsrv_findmirroredds: fnd main ds\n");
8865
fndds = ds;
8866
break;
8867
}
8868
}
8869
if (fndds == NULL)
8870
return (fndds);
8871
if (fndds->nfsdev_mdsisset == 0 && nfsrv_faildscnt > 0)
8872
fndmirror = 1;
8873
else if (fndds->nfsdev_mdsisset != 0) {
8874
/* For the fsid is set case, search for a mirror. */
8875
TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
8876
if (ds != fndds && ds->nfsdev_nmp != NULL &&
8877
ds->nfsdev_mdsisset != 0 &&
8878
fsidcmp(&ds->nfsdev_mdsfsid,
8879
&fndds->nfsdev_mdsfsid) == 0) {
8880
fndmirror = 1;
8881
break;
8882
}
8883
}
8884
}
8885
if (fndmirror == 0) {
8886
NFSD_DEBUG(4, "nfsrv_findmirroredds: no mirror for DS\n");
8887
return (NULL);
8888
}
8889
return (fndds);
8890
}
8891
8892
/*
8893
* Mark the appropriate devid and all associated layout as "out of space".
8894
*/
8895
void
8896
nfsrv_marknospc(char *devid, bool setit)
8897
{
8898
struct nfsdevice *ds;
8899
struct nfslayout *lyp;
8900
struct nfslayouthash *lhyp;
8901
int i;
8902
8903
NFSDDSLOCK();
8904
TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
8905
if (NFSBCMP(ds->nfsdev_deviceid, devid, NFSX_V4DEVICEID) == 0) {
8906
NFSD_DEBUG(1, "nfsrv_marknospc: devid %d\n", setit);
8907
ds->nfsdev_nospc = setit;
8908
}
8909
}
8910
NFSDDSUNLOCK();
8911
8912
for (i = 0; i < nfsrv_layouthashsize; i++) {
8913
lhyp = &nfslayouthash[i];
8914
NFSLOCKLAYOUT(lhyp);
8915
TAILQ_FOREACH(lyp, &lhyp->list, lay_list) {
8916
if (NFSBCMP(lyp->lay_deviceid, devid,
8917
NFSX_V4DEVICEID) == 0) {
8918
NFSD_DEBUG(1, "nfsrv_marknospc: layout %d\n",
8919
setit);
8920
if (setit)
8921
lyp->lay_flags |= NFSLAY_NOSPC;
8922
else
8923
lyp->lay_flags &= ~NFSLAY_NOSPC;
8924
}
8925
}
8926
NFSUNLOCKLAYOUT(lhyp);
8927
}
8928
}
8929
8930
/*
8931
* Check to see if SP4_MACH_CRED is in use and, if it is, check that the
8932
* correct machine credential is being used.
8933
*/
8934
static int
8935
nfsrv_checkmachcred(int op, struct nfsrv_descript *nd, struct nfsclient *clp)
8936
{
8937
8938
if ((clp->lc_flags & LCL_MACHCRED) == 0 ||
8939
!NFSISSET_OPBIT(&clp->lc_mustops, op))
8940
return (0);
8941
KASSERT((nd->nd_flag & ND_NFSV41) != 0,
8942
("nfsrv_checkmachcred: MachCred for NFSv4.0"));
8943
if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_GSSPRIVACY)) != 0 &&
8944
nd->nd_princlen == clp->lc_namelen &&
8945
!NFSBCMP(nd->nd_principal, clp->lc_name, nd->nd_princlen))
8946
return (0);
8947
return (NFSERR_AUTHERR | AUTH_TOOWEAK);
8948
}
8949
8950
/*
8951
* Issue a delegation and, optionally set rflagsp for why not.
8952
*/
8953
static void
8954
nfsrv_issuedelegation(struct vnode *vp, struct nfsclient *clp,
8955
struct nfsrv_descript *nd, int delegate, int writedeleg, int readonly,
8956
u_quad_t filerev, uint64_t rdonly, struct nfsstate **new_delegp,
8957
struct nfsstate *new_stp, struct nfslockfile *lfp, uint32_t *rflagsp,
8958
nfsv4stateid_t *delegstateidp)
8959
{
8960
struct nfsstate *up_deleg, *new_deleg;
8961
8962
new_deleg = *new_delegp;
8963
up_deleg = LIST_FIRST(&lfp->lf_deleg);
8964
if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
8965
*rflagsp |= NFSV4OPEN_WDNOTWANTED;
8966
else if (nfsrv_issuedelegs == 0)
8967
*rflagsp |= NFSV4OPEN_WDSUPPFTYPE;
8968
else if (NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
8969
*rflagsp |= NFSV4OPEN_WDRESOURCE;
8970
else if (delegate == 0 || !NFSVNO_DELEGOK(vp) ||
8971
(writedeleg == 0 && (readonly == 0 ||
8972
(new_stp->ls_flags & NFSLCK_WANTWDELEG) != 0)) ||
8973
(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
8974
LCL_CALLBACKSON) {
8975
/* Is this a downgrade attempt? */
8976
if (up_deleg != NULL && up_deleg->ls_clp == clp &&
8977
(up_deleg->ls_flags & NFSLCK_DELEGWRITE) != 0 &&
8978
(new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0)
8979
*rflagsp |= NFSV4OPEN_WDNOTSUPPDOWNGRADE;
8980
else
8981
*rflagsp |= NFSV4OPEN_WDCONTENTION;
8982
} else if (up_deleg != NULL &&
8983
(up_deleg->ls_flags & NFSLCK_DELEGREAD) != 0 &&
8984
(new_stp->ls_flags & NFSLCK_WANTWDELEG) != 0) {
8985
/* This is an atomic upgrade. */
8986
up_deleg->ls_stateid.seqid++;
8987
delegstateidp->seqid = up_deleg->ls_stateid.seqid;
8988
delegstateidp->other[0] = up_deleg->ls_stateid.other[0];
8989
delegstateidp->other[1] = up_deleg->ls_stateid.other[1];
8990
delegstateidp->other[2] = up_deleg->ls_stateid.other[2];
8991
up_deleg->ls_flags = (NFSLCK_DELEGWRITE |
8992
NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
8993
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
8994
nfsrv_writedelegcnt++;
8995
} else {
8996
new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
8997
new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
8998
= clp->lc_clientid.lval[0];
8999
new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
9000
= clp->lc_clientid.lval[1];
9001
new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
9002
= nfsrv_nextstateindex(clp);
9003
if (writedeleg && !rdonly &&
9004
(nfsrv_writedelegifpos || !readonly) &&
9005
(new_stp->ls_flags & (NFSLCK_WANTRDELEG |
9006
NFSLCK_WANTWDELEG)) != NFSLCK_WANTRDELEG) {
9007
new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
9008
NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
9009
*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
9010
nfsrv_writedelegcnt++;
9011
} else {
9012
new_deleg->ls_flags = (NFSLCK_DELEGREAD |
9013
NFSLCK_READACCESS);
9014
*rflagsp |= NFSV4OPEN_READDELEGATE;
9015
}
9016
new_deleg->ls_uid = new_stp->ls_uid;
9017
new_deleg->ls_lfp = lfp;
9018
new_deleg->ls_clp = clp;
9019
new_deleg->ls_filerev = filerev;
9020
new_deleg->ls_compref = nd->nd_compref;
9021
new_deleg->ls_lastrecall = 0;
9022
LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
9023
LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_deleg->ls_stateid),
9024
new_deleg, ls_hash);
9025
LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
9026
*new_delegp = NULL;
9027
NFSD_VNET(nfsstatsv1_p)->srvdelegates++;
9028
nfsrv_openpluslock++;
9029
nfsrv_delegatecnt++;
9030
}
9031
}
9032
9033
/*
9034
* Find and remove any delegations for the fh.
9035
*/
9036
void
9037
nfsrv_removedeleg(fhandle_t *fhp, struct nfsrv_descript *nd, NFSPROC_T *p)
9038
{
9039
struct nfsclient *clp;
9040
struct nfsstate *stp, *nstp;
9041
struct nfslockfile *lfp;
9042
int error;
9043
9044
NFSLOCKSTATE();
9045
error = nfsrv_getclient(nd->nd_clientid, CLOPS_RENEW, &clp, NULL,
9046
(nfsquad_t)((u_quad_t)0), 0, nd, p);
9047
if (error == 0)
9048
error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, fhp, 0);
9049
/*
9050
* Now we must free any delegations.
9051
*/
9052
if (error == 0) {
9053
LIST_FOREACH_SAFE(stp, &lfp->lf_deleg, ls_file, nstp)
9054
nfsrv_freedeleg(stp);
9055
}
9056
NFSUNLOCKSTATE();
9057
}
9058
9059