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