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