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