1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 #ifndef APPLEKEXT 34 #include <fs/nfs/nfsport.h> 35 36 struct nfsrv_stablefirst nfsrv_stablefirst; 37 int nfsrv_issuedelegs = 0; 38 int nfsrv_dolocallocks = 0; 39 struct nfsv4lock nfsv4rootfs_lock; 40 41 extern int newnfs_numnfsd; 42 extern struct nfsstatsv1 nfsstatsv1; 43 extern int nfsrv_lease; 44 extern struct timeval nfsboottime; 45 extern u_int32_t newnfs_true, newnfs_false; 46 NFSV4ROOTLOCKMUTEX; 47 NFSSTATESPINLOCK; 48 49 SYSCTL_DECL(_vfs_nfsd); 50 int nfsrv_statehashsize = NFSSTATEHASHSIZE; 51 SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN, 52 &nfsrv_statehashsize, 0, 53 "Size of state hash table set via loader.conf"); 54 55 int nfsrv_clienthashsize = NFSCLIENTHASHSIZE; 56 SYSCTL_INT(_vfs_nfsd, OID_AUTO, clienthashsize, CTLFLAG_RDTUN, 57 &nfsrv_clienthashsize, 0, 58 "Size of client hash table set via loader.conf"); 59 60 int nfsrv_lockhashsize = NFSLOCKHASHSIZE; 61 SYSCTL_INT(_vfs_nfsd, OID_AUTO, fhhashsize, CTLFLAG_RDTUN, 62 &nfsrv_lockhashsize, 0, 63 "Size of file handle hash table set via loader.conf"); 64 65 int nfsrv_sessionhashsize = NFSSESSIONHASHSIZE; 66 SYSCTL_INT(_vfs_nfsd, OID_AUTO, sessionhashsize, CTLFLAG_RDTUN, 67 &nfsrv_sessionhashsize, 0, 68 "Size of session hash table set via loader.conf"); 69 70 static int nfsrv_v4statelimit = NFSRV_V4STATELIMIT; 71 SYSCTL_INT(_vfs_nfsd, OID_AUTO, v4statelimit, CTLFLAG_RWTUN, 72 &nfsrv_v4statelimit, 0, 73 "High water limit for NFSv4 opens+locks+delegations"); 74 75 static int nfsrv_writedelegifpos = 0; 76 SYSCTL_INT(_vfs_nfsd, OID_AUTO, writedelegifpos, CTLFLAG_RW, 77 &nfsrv_writedelegifpos, 0, 78 "Issue a write delegation for read opens if possible"); 79 80 static int nfsrv_allowreadforwriteopen = 1; 81 SYSCTL_INT(_vfs_nfsd, OID_AUTO, allowreadforwriteopen, CTLFLAG_RW, 82 &nfsrv_allowreadforwriteopen, 0, 83 "Allow Reads to be done with Write Access StateIDs"); 84 85 /* 86 * Hash lists for nfs V4. 87 */ 88 struct nfsclienthashhead *nfsclienthash; 89 struct nfslockhashhead *nfslockhash; 90 struct nfssessionhash *nfssessionhash; 91 #endif /* !APPLEKEXT */ 92 93 static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 0; 94 static time_t nfsrvboottime; 95 static int nfsrv_returnoldstateid = 0, nfsrv_clients = 0; 96 static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER; 97 static int nfsrv_nogsscallback = 0; 98 static volatile int nfsrv_writedelegcnt = 0; 99 100 /* local functions */ 101 static void nfsrv_dumpaclient(struct nfsclient *clp, 102 struct nfsd_dumpclients *dumpp); 103 static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, 104 NFSPROC_T *p); 105 static int nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, 106 NFSPROC_T *p); 107 static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, 108 NFSPROC_T *p); 109 static void nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, 110 int cansleep, NFSPROC_T *p); 111 static void nfsrv_freenfslock(struct nfslock *lop); 112 static void nfsrv_freenfslockfile(struct nfslockfile *lfp); 113 static void nfsrv_freedeleg(struct nfsstate *); 114 static int nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, 115 u_int32_t flags, struct nfsstate **stpp); 116 static void nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, 117 struct nfsstate **stpp); 118 static int nfsrv_getlockfh(vnode_t vp, u_short flags, 119 struct nfslockfile *new_lfp, fhandle_t *nfhp, NFSPROC_T *p); 120 static int nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, 121 struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit); 122 static void nfsrv_insertlock(struct nfslock *new_lop, 123 struct nfslock *insert_lop, struct nfsstate *stp, struct nfslockfile *lfp); 124 static void nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, 125 struct nfslock **other_lopp, struct nfslockfile *lfp); 126 static int nfsrv_getipnumber(u_char *cp); 127 static int nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 128 nfsv4stateid_t *stateidp, int specialid); 129 static int nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp, 130 u_int32_t flags); 131 static int nfsrv_docallback(struct nfsclient *clp, int procnum, 132 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, 133 struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p); 134 static int nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp, 135 uint32_t callback, int op, const char *optag, struct nfsdsession **sepp); 136 static u_int32_t nfsrv_nextclientindex(void); 137 static u_int32_t nfsrv_nextstateindex(struct nfsclient *clp); 138 static void nfsrv_markstable(struct nfsclient *clp); 139 static int nfsrv_checkstable(struct nfsclient *clp); 140 static int nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, struct 141 vnode *vp, NFSPROC_T *p); 142 static int nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, 143 NFSPROC_T *p, vnode_t vp); 144 static int nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 145 struct nfsclient *clp, int *haslockp, NFSPROC_T *p); 146 static int nfsrv_notsamecredname(struct nfsrv_descript *nd, 147 struct nfsclient *clp); 148 static time_t nfsrv_leaseexpiry(void); 149 static void nfsrv_delaydelegtimeout(struct nfsstate *stp); 150 static int nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 151 struct nfsstate *stp, struct nfsrvcache *op); 152 static int nfsrv_nootherstate(struct nfsstate *stp); 153 static int nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, 154 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p); 155 static void nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, 156 uint64_t init_first, uint64_t init_end, NFSPROC_T *p); 157 static int nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, 158 int oldflags, uint64_t first, uint64_t end, struct nfslockconflict *cfp, 159 NFSPROC_T *p); 160 static void nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, 161 NFSPROC_T *p); 162 static void nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, 163 uint64_t first, uint64_t end); 164 static void nfsrv_locklf(struct nfslockfile *lfp); 165 static void nfsrv_unlocklf(struct nfslockfile *lfp); 166 static struct nfsdsession *nfsrv_findsession(uint8_t *sessionid); 167 static int nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid); 168 static int nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp, 169 int dont_replycache, struct nfsdsession **sepp); 170 static int nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp); 171 172 /* 173 * Scan the client list for a match and either return the current one, 174 * create a new entry or return an error. 175 * If returning a non-error, the clp structure must either be linked into 176 * the client list or free'd. 177 */ 178 APPLESTATIC int 179 nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, 180 nfsquad_t *clientidp, nfsquad_t *confirmp, NFSPROC_T *p) 181 { 182 struct nfsclient *clp = NULL, *new_clp = *new_clpp; 183 int i, error = 0; 184 struct nfsstate *stp, *tstp; 185 struct sockaddr_in *sad, *rad; 186 int zapit = 0, gotit, hasstate = 0, igotlock; 187 static u_int64_t confirm_index = 0; 188 189 /* 190 * Check for state resource limit exceeded. 191 */ 192 if (nfsrv_openpluslock > nfsrv_v4statelimit) { 193 error = NFSERR_RESOURCE; 194 goto out; 195 } 196 197 if (nfsrv_issuedelegs == 0 || 198 ((nd->nd_flag & ND_GSS) != 0 && nfsrv_nogsscallback != 0)) 199 /* 200 * Don't do callbacks when delegations are disabled or 201 * for AUTH_GSS unless enabled via nfsrv_nogsscallback. 202 * If establishing a callback connection is attempted 203 * when a firewall is blocking the callback path, the 204 * server may wait too long for the connect attempt to 205 * succeed during the Open. Some clients, such as Linux, 206 * may timeout and give up on the Open before the server 207 * replies. Also, since AUTH_GSS callbacks are not 208 * yet interoperability tested, they might cause the 209 * server to crap out, if they get past the Init call to 210 * the client. 211 */ 212 new_clp->lc_program = 0; 213 214 /* Lock out other nfsd threads */ 215 NFSLOCKV4ROOTMUTEX(); 216 nfsv4_relref(&nfsv4rootfs_lock); 217 do { 218 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 219 NFSV4ROOTLOCKMUTEXPTR, NULL); 220 } while (!igotlock); 221 NFSUNLOCKV4ROOTMUTEX(); 222 223 /* 224 * Search for a match in the client list. 225 */ 226 gotit = i = 0; 227 while (i < nfsrv_clienthashsize && !gotit) { 228 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 229 if (new_clp->lc_idlen == clp->lc_idlen && 230 !NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) { 231 gotit = 1; 232 break; 233 } 234 } 235 if (gotit == 0) 236 i++; 237 } 238 if (!gotit || 239 (clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_ADMINREVOKED))) { 240 if ((nd->nd_flag & ND_NFSV41) != 0 && confirmp->lval[1] != 0) { 241 /* 242 * For NFSv4.1, if confirmp->lval[1] is non-zero, the 243 * client is trying to update a confirmed clientid. 244 */ 245 NFSLOCKV4ROOTMUTEX(); 246 nfsv4_unlock(&nfsv4rootfs_lock, 1); 247 NFSUNLOCKV4ROOTMUTEX(); 248 confirmp->lval[1] = 0; 249 error = NFSERR_NOENT; 250 goto out; 251 } 252 /* 253 * Get rid of the old one. 254 */ 255 if (i != nfsrv_clienthashsize) { 256 LIST_REMOVE(clp, lc_hash); 257 nfsrv_cleanclient(clp, p); 258 nfsrv_freedeleglist(&clp->lc_deleg); 259 nfsrv_freedeleglist(&clp->lc_olddeleg); 260 zapit = 1; 261 } 262 /* 263 * Add it after assigning a client id to it. 264 */ 265 new_clp->lc_flags |= LCL_NEEDSCONFIRM; 266 if ((nd->nd_flag & ND_NFSV41) != 0) 267 new_clp->lc_confirm.lval[0] = confirmp->lval[0] = 268 ++confirm_index; 269 else 270 confirmp->qval = new_clp->lc_confirm.qval = 271 ++confirm_index; 272 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 273 (u_int32_t)nfsrvboottime; 274 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 275 nfsrv_nextclientindex(); 276 new_clp->lc_stateindex = 0; 277 new_clp->lc_statemaxindex = 0; 278 new_clp->lc_cbref = 0; 279 new_clp->lc_expiry = nfsrv_leaseexpiry(); 280 LIST_INIT(&new_clp->lc_open); 281 LIST_INIT(&new_clp->lc_deleg); 282 LIST_INIT(&new_clp->lc_olddeleg); 283 LIST_INIT(&new_clp->lc_session); 284 for (i = 0; i < nfsrv_statehashsize; i++) 285 LIST_INIT(&new_clp->lc_stateid[i]); 286 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 287 lc_hash); 288 nfsstatsv1.srvclients++; 289 nfsrv_openpluslock++; 290 nfsrv_clients++; 291 NFSLOCKV4ROOTMUTEX(); 292 nfsv4_unlock(&nfsv4rootfs_lock, 1); 293 NFSUNLOCKV4ROOTMUTEX(); 294 if (zapit) 295 nfsrv_zapclient(clp, p); 296 *new_clpp = NULL; 297 goto out; 298 } 299 300 /* 301 * Now, handle the cases where the id is already issued. 302 */ 303 if (nfsrv_notsamecredname(nd, clp)) { 304 /* 305 * Check to see if there is expired state that should go away. 306 */ 307 if (clp->lc_expiry < NFSD_MONOSEC && 308 (!LIST_EMPTY(&clp->lc_open) || !LIST_EMPTY(&clp->lc_deleg))) { 309 nfsrv_cleanclient(clp, p); 310 nfsrv_freedeleglist(&clp->lc_deleg); 311 } 312 313 /* 314 * If there is outstanding state, then reply NFSERR_CLIDINUSE per 315 * RFC3530 Sec. 8.1.2 last para. 316 */ 317 if (!LIST_EMPTY(&clp->lc_deleg)) { 318 hasstate = 1; 319 } else if (LIST_EMPTY(&clp->lc_open)) { 320 hasstate = 0; 321 } else { 322 hasstate = 0; 323 /* Look for an Open on the OpenOwner */ 324 LIST_FOREACH(stp, &clp->lc_open, ls_list) { 325 if (!LIST_EMPTY(&stp->ls_open)) { 326 hasstate = 1; 327 break; 328 } 329 } 330 } 331 if (hasstate) { 332 /* 333 * If the uid doesn't match, return NFSERR_CLIDINUSE after 334 * filling out the correct ipaddr and portnum. 335 */ 336 sad = NFSSOCKADDR(new_clp->lc_req.nr_nam, struct sockaddr_in *); 337 rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 338 sad->sin_addr.s_addr = rad->sin_addr.s_addr; 339 sad->sin_port = rad->sin_port; 340 NFSLOCKV4ROOTMUTEX(); 341 nfsv4_unlock(&nfsv4rootfs_lock, 1); 342 NFSUNLOCKV4ROOTMUTEX(); 343 error = NFSERR_CLIDINUSE; 344 goto out; 345 } 346 } 347 348 if (NFSBCMP(new_clp->lc_verf, clp->lc_verf, NFSX_VERF)) { 349 /* 350 * If the verifier has changed, the client has rebooted 351 * and a new client id is issued. The old state info 352 * can be thrown away once the SETCLIENTID_CONFIRM occurs. 353 */ 354 LIST_REMOVE(clp, lc_hash); 355 new_clp->lc_flags |= LCL_NEEDSCONFIRM; 356 if ((nd->nd_flag & ND_NFSV41) != 0) 357 new_clp->lc_confirm.lval[0] = confirmp->lval[0] = 358 ++confirm_index; 359 else 360 confirmp->qval = new_clp->lc_confirm.qval = 361 ++confirm_index; 362 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 363 nfsrvboottime; 364 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 365 nfsrv_nextclientindex(); 366 new_clp->lc_stateindex = 0; 367 new_clp->lc_statemaxindex = 0; 368 new_clp->lc_cbref = 0; 369 new_clp->lc_expiry = nfsrv_leaseexpiry(); 370 371 /* 372 * Save the state until confirmed. 373 */ 374 LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list); 375 LIST_FOREACH(tstp, &new_clp->lc_open, ls_list) 376 tstp->ls_clp = new_clp; 377 LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list); 378 LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list) 379 tstp->ls_clp = new_clp; 380 LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, 381 ls_list); 382 LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list) 383 tstp->ls_clp = new_clp; 384 for (i = 0; i < nfsrv_statehashsize; i++) { 385 LIST_NEWHEAD(&new_clp->lc_stateid[i], 386 &clp->lc_stateid[i], ls_hash); 387 LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) 388 tstp->ls_clp = new_clp; 389 } 390 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 391 lc_hash); 392 nfsstatsv1.srvclients++; 393 nfsrv_openpluslock++; 394 nfsrv_clients++; 395 NFSLOCKV4ROOTMUTEX(); 396 nfsv4_unlock(&nfsv4rootfs_lock, 1); 397 NFSUNLOCKV4ROOTMUTEX(); 398 399 /* 400 * Must wait until any outstanding callback on the old clp 401 * completes. 402 */ 403 NFSLOCKSTATE(); 404 while (clp->lc_cbref) { 405 clp->lc_flags |= LCL_WAKEUPWANTED; 406 (void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1, 407 "nfsd clp", 10 * hz); 408 } 409 NFSUNLOCKSTATE(); 410 nfsrv_zapclient(clp, p); 411 *new_clpp = NULL; 412 goto out; 413 } 414 415 /* For NFSv4.1, mark that we found a confirmed clientid. */ 416 if ((nd->nd_flag & ND_NFSV41) != 0) { 417 clientidp->lval[0] = clp->lc_clientid.lval[0]; 418 clientidp->lval[1] = clp->lc_clientid.lval[1]; 419 confirmp->lval[0] = 0; /* Ignored by client */ 420 confirmp->lval[1] = 1; 421 } else { 422 /* 423 * id and verifier match, so update the net address info 424 * and get rid of any existing callback authentication 425 * handle, so a new one will be acquired. 426 */ 427 LIST_REMOVE(clp, lc_hash); 428 new_clp->lc_flags |= (LCL_NEEDSCONFIRM | LCL_DONTCLEAN); 429 new_clp->lc_expiry = nfsrv_leaseexpiry(); 430 confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; 431 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 432 clp->lc_clientid.lval[0]; 433 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 434 clp->lc_clientid.lval[1]; 435 new_clp->lc_delegtime = clp->lc_delegtime; 436 new_clp->lc_stateindex = clp->lc_stateindex; 437 new_clp->lc_statemaxindex = clp->lc_statemaxindex; 438 new_clp->lc_cbref = 0; 439 LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list); 440 LIST_FOREACH(tstp, &new_clp->lc_open, ls_list) 441 tstp->ls_clp = new_clp; 442 LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list); 443 LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list) 444 tstp->ls_clp = new_clp; 445 LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, ls_list); 446 LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list) 447 tstp->ls_clp = new_clp; 448 for (i = 0; i < nfsrv_statehashsize; i++) { 449 LIST_NEWHEAD(&new_clp->lc_stateid[i], 450 &clp->lc_stateid[i], ls_hash); 451 LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) 452 tstp->ls_clp = new_clp; 453 } 454 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 455 lc_hash); 456 nfsstatsv1.srvclients++; 457 nfsrv_openpluslock++; 458 nfsrv_clients++; 459 } 460 NFSLOCKV4ROOTMUTEX(); 461 nfsv4_unlock(&nfsv4rootfs_lock, 1); 462 NFSUNLOCKV4ROOTMUTEX(); 463 464 if ((nd->nd_flag & ND_NFSV41) == 0) { 465 /* 466 * Must wait until any outstanding callback on the old clp 467 * completes. 468 */ 469 NFSLOCKSTATE(); 470 while (clp->lc_cbref) { 471 clp->lc_flags |= LCL_WAKEUPWANTED; 472 (void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1, 473 "nfsdclp", 10 * hz); 474 } 475 NFSUNLOCKSTATE(); 476 nfsrv_zapclient(clp, p); 477 *new_clpp = NULL; 478 } 479 480 out: 481 NFSEXITCODE2(error, nd); 482 return (error); 483 } 484 485 /* 486 * Check to see if the client id exists and optionally confirm it. 487 */ 488 APPLESTATIC int 489 nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, 490 struct nfsdsession *nsep, nfsquad_t confirm, uint32_t cbprogram, 491 struct nfsrv_descript *nd, NFSPROC_T *p) 492 { 493 struct nfsclient *clp; 494 struct nfsstate *stp; 495 int i; 496 struct nfsclienthashhead *hp; 497 int error = 0, igotlock, doneok; 498 struct nfssessionhash *shp; 499 struct nfsdsession *sep; 500 uint64_t sessid[2]; 501 static uint64_t next_sess = 0; 502 503 if (clpp) 504 *clpp = NULL; 505 if ((nd == NULL || (nd->nd_flag & ND_NFSV41) == 0 || 506 opflags != CLOPS_RENEW) && nfsrvboottime != clientid.lval[0]) { 507 error = NFSERR_STALECLIENTID; 508 goto out; 509 } 510 511 /* 512 * If called with opflags == CLOPS_RENEW, the State Lock is 513 * already held. Otherwise, we need to get either that or, 514 * for the case of Confirm, lock out the nfsd threads. 515 */ 516 if (opflags & CLOPS_CONFIRM) { 517 NFSLOCKV4ROOTMUTEX(); 518 nfsv4_relref(&nfsv4rootfs_lock); 519 do { 520 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 521 NFSV4ROOTLOCKMUTEXPTR, NULL); 522 } while (!igotlock); 523 /* 524 * Create a new sessionid here, since we need to do it where 525 * there is a mutex held to serialize update of next_sess. 526 */ 527 if ((nd->nd_flag & ND_NFSV41) != 0) { 528 sessid[0] = ++next_sess; 529 sessid[1] = clientid.qval; 530 } 531 NFSUNLOCKV4ROOTMUTEX(); 532 } else if (opflags != CLOPS_RENEW) { 533 NFSLOCKSTATE(); 534 } 535 536 /* For NFSv4.1, the clp is acquired from the associated session. */ 537 if (nd != NULL && (nd->nd_flag & ND_NFSV41) != 0 && 538 opflags == CLOPS_RENEW) { 539 clp = NULL; 540 if ((nd->nd_flag & ND_HASSEQUENCE) != 0) { 541 shp = NFSSESSIONHASH(nd->nd_sessionid); 542 NFSLOCKSESSION(shp); 543 sep = nfsrv_findsession(nd->nd_sessionid); 544 if (sep != NULL) 545 clp = sep->sess_clp; 546 NFSUNLOCKSESSION(shp); 547 } 548 } else { 549 hp = NFSCLIENTHASH(clientid); 550 LIST_FOREACH(clp, hp, lc_hash) { 551 if (clp->lc_clientid.lval[1] == clientid.lval[1]) 552 break; 553 } 554 } 555 if (clp == NULL) { 556 if (opflags & CLOPS_CONFIRM) 557 error = NFSERR_STALECLIENTID; 558 else 559 error = NFSERR_EXPIRED; 560 } else if (clp->lc_flags & LCL_ADMINREVOKED) { 561 /* 562 * If marked admin revoked, just return the error. 563 */ 564 error = NFSERR_ADMINREVOKED; 565 } 566 if (error) { 567 if (opflags & CLOPS_CONFIRM) { 568 NFSLOCKV4ROOTMUTEX(); 569 nfsv4_unlock(&nfsv4rootfs_lock, 1); 570 NFSUNLOCKV4ROOTMUTEX(); 571 } else if (opflags != CLOPS_RENEW) { 572 NFSUNLOCKSTATE(); 573 } 574 goto out; 575 } 576 577 /* 578 * Perform any operations specified by the opflags. 579 */ 580 if (opflags & CLOPS_CONFIRM) { 581 if (((nd->nd_flag & ND_NFSV41) != 0 && 582 clp->lc_confirm.lval[0] != confirm.lval[0]) || 583 ((nd->nd_flag & ND_NFSV41) == 0 && 584 clp->lc_confirm.qval != confirm.qval)) 585 error = NFSERR_STALECLIENTID; 586 else if (nfsrv_notsamecredname(nd, clp)) 587 error = NFSERR_CLIDINUSE; 588 589 if (!error) { 590 if ((clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_DONTCLEAN)) == 591 LCL_NEEDSCONFIRM) { 592 /* 593 * Hang onto the delegations (as old delegations) 594 * for an Open with CLAIM_DELEGATE_PREV unless in 595 * grace, but get rid of the rest of the state. 596 */ 597 nfsrv_cleanclient(clp, p); 598 nfsrv_freedeleglist(&clp->lc_olddeleg); 599 if (nfsrv_checkgrace(nd, clp, 0)) { 600 /* In grace, so just delete delegations */ 601 nfsrv_freedeleglist(&clp->lc_deleg); 602 } else { 603 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) 604 stp->ls_flags |= NFSLCK_OLDDELEG; 605 clp->lc_delegtime = NFSD_MONOSEC + 606 nfsrv_lease + NFSRV_LEASEDELTA; 607 LIST_NEWHEAD(&clp->lc_olddeleg, &clp->lc_deleg, 608 ls_list); 609 } 610 if ((nd->nd_flag & ND_NFSV41) != 0) 611 clp->lc_program = cbprogram; 612 } 613 clp->lc_flags &= ~(LCL_NEEDSCONFIRM | LCL_DONTCLEAN); 614 if (clp->lc_program) 615 clp->lc_flags |= LCL_NEEDSCBNULL; 616 /* For NFSv4.1, link the session onto the client. */ 617 if (nsep != NULL) { 618 /* Hold a reference on the xprt for a backchannel. */ 619 if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) 620 != 0 && clp->lc_req.nr_client == NULL) { 621 clp->lc_req.nr_client = (struct __rpc_client *) 622 clnt_bck_create(nd->nd_xprt->xp_socket, 623 cbprogram, NFSV4_CBVERS); 624 if (clp->lc_req.nr_client != NULL) { 625 SVC_ACQUIRE(nd->nd_xprt); 626 nd->nd_xprt->xp_p2 = 627 clp->lc_req.nr_client->cl_private; 628 /* Disable idle timeout. */ 629 nd->nd_xprt->xp_idletimeout = 0; 630 nsep->sess_cbsess.nfsess_xprt = nd->nd_xprt; 631 } else 632 nsep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN; 633 } 634 NFSBCOPY(sessid, nsep->sess_sessionid, 635 NFSX_V4SESSIONID); 636 NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid, 637 NFSX_V4SESSIONID); 638 shp = NFSSESSIONHASH(nsep->sess_sessionid); 639 NFSLOCKSTATE(); 640 NFSLOCKSESSION(shp); 641 LIST_INSERT_HEAD(&shp->list, nsep, sess_hash); 642 LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list); 643 nsep->sess_clp = clp; 644 NFSUNLOCKSESSION(shp); 645 NFSUNLOCKSTATE(); 646 } 647 } 648 } else if (clp->lc_flags & LCL_NEEDSCONFIRM) { 649 error = NFSERR_EXPIRED; 650 } 651 652 /* 653 * If called by the Renew Op, we must check the principal. 654 */ 655 if (!error && (opflags & CLOPS_RENEWOP)) { 656 if (nfsrv_notsamecredname(nd, clp)) { 657 doneok = 0; 658 for (i = 0; i < nfsrv_statehashsize && doneok == 0; i++) { 659 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 660 if ((stp->ls_flags & NFSLCK_OPEN) && 661 stp->ls_uid == nd->nd_cred->cr_uid) { 662 doneok = 1; 663 break; 664 } 665 } 666 } 667 if (!doneok) 668 error = NFSERR_ACCES; 669 } 670 if (!error && (clp->lc_flags & LCL_CBDOWN)) 671 error = NFSERR_CBPATHDOWN; 672 } 673 if ((!error || error == NFSERR_CBPATHDOWN) && 674 (opflags & CLOPS_RENEW)) { 675 clp->lc_expiry = nfsrv_leaseexpiry(); 676 } 677 if (opflags & CLOPS_CONFIRM) { 678 NFSLOCKV4ROOTMUTEX(); 679 nfsv4_unlock(&nfsv4rootfs_lock, 1); 680 NFSUNLOCKV4ROOTMUTEX(); 681 } else if (opflags != CLOPS_RENEW) { 682 NFSUNLOCKSTATE(); 683 } 684 if (clpp) 685 *clpp = clp; 686 687 out: 688 NFSEXITCODE2(error, nd); 689 return (error); 690 } 691 692 /* 693 * Perform the NFSv4.1 destroy clientid. 694 */ 695 int 696 nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p) 697 { 698 struct nfsclient *clp; 699 struct nfsclienthashhead *hp; 700 int error = 0, i, igotlock; 701 702 if (nfsrvboottime != clientid.lval[0]) { 703 error = NFSERR_STALECLIENTID; 704 goto out; 705 } 706 707 /* Lock out other nfsd threads */ 708 NFSLOCKV4ROOTMUTEX(); 709 nfsv4_relref(&nfsv4rootfs_lock); 710 do { 711 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 712 NFSV4ROOTLOCKMUTEXPTR, NULL); 713 } while (igotlock == 0); 714 NFSUNLOCKV4ROOTMUTEX(); 715 716 hp = NFSCLIENTHASH(clientid); 717 LIST_FOREACH(clp, hp, lc_hash) { 718 if (clp->lc_clientid.lval[1] == clientid.lval[1]) 719 break; 720 } 721 if (clp == NULL) { 722 NFSLOCKV4ROOTMUTEX(); 723 nfsv4_unlock(&nfsv4rootfs_lock, 1); 724 NFSUNLOCKV4ROOTMUTEX(); 725 /* Just return ok, since it is gone. */ 726 goto out; 727 } 728 729 /* Scan for state on the clientid. */ 730 for (i = 0; i < nfsrv_statehashsize; i++) 731 if (!LIST_EMPTY(&clp->lc_stateid[i])) { 732 NFSLOCKV4ROOTMUTEX(); 733 nfsv4_unlock(&nfsv4rootfs_lock, 1); 734 NFSUNLOCKV4ROOTMUTEX(); 735 error = NFSERR_CLIENTIDBUSY; 736 goto out; 737 } 738 if (!LIST_EMPTY(&clp->lc_session) || !LIST_EMPTY(&clp->lc_deleg)) { 739 NFSLOCKV4ROOTMUTEX(); 740 nfsv4_unlock(&nfsv4rootfs_lock, 1); 741 NFSUNLOCKV4ROOTMUTEX(); 742 error = NFSERR_CLIENTIDBUSY; 743 goto out; 744 } 745 746 /* Destroy the clientid and return ok. */ 747 nfsrv_cleanclient(clp, p); 748 nfsrv_freedeleglist(&clp->lc_deleg); 749 nfsrv_freedeleglist(&clp->lc_olddeleg); 750 LIST_REMOVE(clp, lc_hash); 751 NFSLOCKV4ROOTMUTEX(); 752 nfsv4_unlock(&nfsv4rootfs_lock, 1); 753 NFSUNLOCKV4ROOTMUTEX(); 754 nfsrv_zapclient(clp, p); 755 out: 756 NFSEXITCODE2(error, nd); 757 return (error); 758 } 759 760 /* 761 * Called from the new nfssvc syscall to admin revoke a clientid. 762 * Returns 0 for success, error otherwise. 763 */ 764 APPLESTATIC int 765 nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p) 766 { 767 struct nfsclient *clp = NULL; 768 int i, error = 0; 769 int gotit, igotlock; 770 771 /* 772 * First, lock out the nfsd so that state won't change while the 773 * revocation record is being written to the stable storage restart 774 * file. 775 */ 776 NFSLOCKV4ROOTMUTEX(); 777 do { 778 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 779 NFSV4ROOTLOCKMUTEXPTR, NULL); 780 } while (!igotlock); 781 NFSUNLOCKV4ROOTMUTEX(); 782 783 /* 784 * Search for a match in the client list. 785 */ 786 gotit = i = 0; 787 while (i < nfsrv_clienthashsize && !gotit) { 788 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 789 if (revokep->nclid_idlen == clp->lc_idlen && 790 !NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) { 791 gotit = 1; 792 break; 793 } 794 } 795 i++; 796 } 797 if (!gotit) { 798 NFSLOCKV4ROOTMUTEX(); 799 nfsv4_unlock(&nfsv4rootfs_lock, 0); 800 NFSUNLOCKV4ROOTMUTEX(); 801 error = EPERM; 802 goto out; 803 } 804 805 /* 806 * Now, write out the revocation record 807 */ 808 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 809 nfsrv_backupstable(); 810 811 /* 812 * and clear out the state, marking the clientid revoked. 813 */ 814 clp->lc_flags &= ~LCL_CALLBACKSON; 815 clp->lc_flags |= LCL_ADMINREVOKED; 816 nfsrv_cleanclient(clp, p); 817 nfsrv_freedeleglist(&clp->lc_deleg); 818 nfsrv_freedeleglist(&clp->lc_olddeleg); 819 NFSLOCKV4ROOTMUTEX(); 820 nfsv4_unlock(&nfsv4rootfs_lock, 0); 821 NFSUNLOCKV4ROOTMUTEX(); 822 823 out: 824 NFSEXITCODE(error); 825 return (error); 826 } 827 828 /* 829 * Dump out stats for all clients. Called from nfssvc(2), that is used 830 * nfsstatsv1. 831 */ 832 APPLESTATIC void 833 nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt) 834 { 835 struct nfsclient *clp; 836 int i = 0, cnt = 0; 837 838 /* 839 * First, get a reference on the nfsv4rootfs_lock so that an 840 * exclusive lock cannot be acquired while dumping the clients. 841 */ 842 NFSLOCKV4ROOTMUTEX(); 843 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 844 NFSUNLOCKV4ROOTMUTEX(); 845 NFSLOCKSTATE(); 846 /* 847 * Rattle through the client lists until done. 848 */ 849 while (i < nfsrv_clienthashsize && cnt < maxcnt) { 850 clp = LIST_FIRST(&nfsclienthash[i]); 851 while (clp != LIST_END(&nfsclienthash[i]) && cnt < maxcnt) { 852 nfsrv_dumpaclient(clp, &dumpp[cnt]); 853 cnt++; 854 clp = LIST_NEXT(clp, lc_hash); 855 } 856 i++; 857 } 858 if (cnt < maxcnt) 859 dumpp[cnt].ndcl_clid.nclid_idlen = 0; 860 NFSUNLOCKSTATE(); 861 NFSLOCKV4ROOTMUTEX(); 862 nfsv4_relref(&nfsv4rootfs_lock); 863 NFSUNLOCKV4ROOTMUTEX(); 864 } 865 866 /* 867 * Dump stats for a client. Must be called with the NFSSTATELOCK and spl'd. 868 */ 869 static void 870 nfsrv_dumpaclient(struct nfsclient *clp, struct nfsd_dumpclients *dumpp) 871 { 872 struct nfsstate *stp, *openstp, *lckownstp; 873 struct nfslock *lop; 874 struct sockaddr *sad; 875 struct sockaddr_in *rad; 876 struct sockaddr_in6 *rad6; 877 878 dumpp->ndcl_nopenowners = dumpp->ndcl_nlockowners = 0; 879 dumpp->ndcl_nopens = dumpp->ndcl_nlocks = 0; 880 dumpp->ndcl_ndelegs = dumpp->ndcl_nolddelegs = 0; 881 dumpp->ndcl_flags = clp->lc_flags; 882 dumpp->ndcl_clid.nclid_idlen = clp->lc_idlen; 883 NFSBCOPY(clp->lc_id, dumpp->ndcl_clid.nclid_id, clp->lc_idlen); 884 sad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr *); 885 dumpp->ndcl_addrfam = sad->sa_family; 886 if (sad->sa_family == AF_INET) { 887 rad = (struct sockaddr_in *)sad; 888 dumpp->ndcl_cbaddr.sin_addr = rad->sin_addr; 889 } else { 890 rad6 = (struct sockaddr_in6 *)sad; 891 dumpp->ndcl_cbaddr.sin6_addr = rad6->sin6_addr; 892 } 893 894 /* 895 * Now, scan the state lists and total up the opens and locks. 896 */ 897 LIST_FOREACH(stp, &clp->lc_open, ls_list) { 898 dumpp->ndcl_nopenowners++; 899 LIST_FOREACH(openstp, &stp->ls_open, ls_list) { 900 dumpp->ndcl_nopens++; 901 LIST_FOREACH(lckownstp, &openstp->ls_open, ls_list) { 902 dumpp->ndcl_nlockowners++; 903 LIST_FOREACH(lop, &lckownstp->ls_lock, lo_lckowner) { 904 dumpp->ndcl_nlocks++; 905 } 906 } 907 } 908 } 909 910 /* 911 * and the delegation lists. 912 */ 913 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) { 914 dumpp->ndcl_ndelegs++; 915 } 916 LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) { 917 dumpp->ndcl_nolddelegs++; 918 } 919 } 920 921 /* 922 * Dump out lock stats for a file. 923 */ 924 APPLESTATIC void 925 nfsrv_dumplocks(vnode_t vp, struct nfsd_dumplocks *ldumpp, int maxcnt, 926 NFSPROC_T *p) 927 { 928 struct nfsstate *stp; 929 struct nfslock *lop; 930 int cnt = 0; 931 struct nfslockfile *lfp; 932 struct sockaddr *sad; 933 struct sockaddr_in *rad; 934 struct sockaddr_in6 *rad6; 935 int ret; 936 fhandle_t nfh; 937 938 ret = nfsrv_getlockfh(vp, 0, NULL, &nfh, p); 939 /* 940 * First, get a reference on the nfsv4rootfs_lock so that an 941 * exclusive lock on it cannot be acquired while dumping the locks. 942 */ 943 NFSLOCKV4ROOTMUTEX(); 944 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 945 NFSUNLOCKV4ROOTMUTEX(); 946 NFSLOCKSTATE(); 947 if (!ret) 948 ret = nfsrv_getlockfile(0, NULL, &lfp, &nfh, 0); 949 if (ret) { 950 ldumpp[0].ndlck_clid.nclid_idlen = 0; 951 NFSUNLOCKSTATE(); 952 NFSLOCKV4ROOTMUTEX(); 953 nfsv4_relref(&nfsv4rootfs_lock); 954 NFSUNLOCKV4ROOTMUTEX(); 955 return; 956 } 957 958 /* 959 * For each open share on file, dump it out. 960 */ 961 stp = LIST_FIRST(&lfp->lf_open); 962 while (stp != LIST_END(&lfp->lf_open) && cnt < maxcnt) { 963 ldumpp[cnt].ndlck_flags = stp->ls_flags; 964 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 965 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 966 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 967 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 968 ldumpp[cnt].ndlck_owner.nclid_idlen = 969 stp->ls_openowner->ls_ownerlen; 970 NFSBCOPY(stp->ls_openowner->ls_owner, 971 ldumpp[cnt].ndlck_owner.nclid_id, 972 stp->ls_openowner->ls_ownerlen); 973 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 974 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 975 stp->ls_clp->lc_idlen); 976 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 977 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 978 if (sad->sa_family == AF_INET) { 979 rad = (struct sockaddr_in *)sad; 980 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 981 } else { 982 rad6 = (struct sockaddr_in6 *)sad; 983 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 984 } 985 stp = LIST_NEXT(stp, ls_file); 986 cnt++; 987 } 988 989 /* 990 * and all locks. 991 */ 992 lop = LIST_FIRST(&lfp->lf_lock); 993 while (lop != LIST_END(&lfp->lf_lock) && cnt < maxcnt) { 994 stp = lop->lo_stp; 995 ldumpp[cnt].ndlck_flags = lop->lo_flags; 996 ldumpp[cnt].ndlck_first = lop->lo_first; 997 ldumpp[cnt].ndlck_end = lop->lo_end; 998 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 999 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 1000 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 1001 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 1002 ldumpp[cnt].ndlck_owner.nclid_idlen = stp->ls_ownerlen; 1003 NFSBCOPY(stp->ls_owner, ldumpp[cnt].ndlck_owner.nclid_id, 1004 stp->ls_ownerlen); 1005 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 1006 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 1007 stp->ls_clp->lc_idlen); 1008 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 1009 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 1010 if (sad->sa_family == AF_INET) { 1011 rad = (struct sockaddr_in *)sad; 1012 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 1013 } else { 1014 rad6 = (struct sockaddr_in6 *)sad; 1015 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 1016 } 1017 lop = LIST_NEXT(lop, lo_lckfile); 1018 cnt++; 1019 } 1020 1021 /* 1022 * and the delegations. 1023 */ 1024 stp = LIST_FIRST(&lfp->lf_deleg); 1025 while (stp != LIST_END(&lfp->lf_deleg) && cnt < maxcnt) { 1026 ldumpp[cnt].ndlck_flags = stp->ls_flags; 1027 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 1028 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 1029 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 1030 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 1031 ldumpp[cnt].ndlck_owner.nclid_idlen = 0; 1032 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 1033 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 1034 stp->ls_clp->lc_idlen); 1035 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 1036 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 1037 if (sad->sa_family == AF_INET) { 1038 rad = (struct sockaddr_in *)sad; 1039 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 1040 } else { 1041 rad6 = (struct sockaddr_in6 *)sad; 1042 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 1043 } 1044 stp = LIST_NEXT(stp, ls_file); 1045 cnt++; 1046 } 1047 1048 /* 1049 * If list isn't full, mark end of list by setting the client name 1050 * to zero length. 1051 */ 1052 if (cnt < maxcnt) 1053 ldumpp[cnt].ndlck_clid.nclid_idlen = 0; 1054 NFSUNLOCKSTATE(); 1055 NFSLOCKV4ROOTMUTEX(); 1056 nfsv4_relref(&nfsv4rootfs_lock); 1057 NFSUNLOCKV4ROOTMUTEX(); 1058 } 1059 1060 /* 1061 * Server timer routine. It can scan any linked list, so long 1062 * as it holds the spin/mutex lock and there is no exclusive lock on 1063 * nfsv4rootfs_lock. 1064 * (For OpenBSD, a kthread is ok. For FreeBSD, I think it is ok 1065 * to do this from a callout, since the spin locks work. For 1066 * Darwin, I'm not sure what will work correctly yet.) 1067 * Should be called once per second. 1068 */ 1069 APPLESTATIC void 1070 nfsrv_servertimer(void) 1071 { 1072 struct nfsclient *clp, *nclp; 1073 struct nfsstate *stp, *nstp; 1074 int got_ref, i; 1075 1076 /* 1077 * Make sure nfsboottime is set. This is used by V3 as well 1078 * as V4. Note that nfsboottime is not nfsrvboottime, which is 1079 * only used by the V4 server for leases. 1080 */ 1081 if (nfsboottime.tv_sec == 0) 1082 NFSSETBOOTTIME(nfsboottime); 1083 1084 /* 1085 * If server hasn't started yet, just return. 1086 */ 1087 NFSLOCKSTATE(); 1088 if (nfsrv_stablefirst.nsf_eograce == 0) { 1089 NFSUNLOCKSTATE(); 1090 return; 1091 } 1092 if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) { 1093 if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) && 1094 NFSD_MONOSEC > nfsrv_stablefirst.nsf_eograce) 1095 nfsrv_stablefirst.nsf_flags |= 1096 (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); 1097 NFSUNLOCKSTATE(); 1098 return; 1099 } 1100 1101 /* 1102 * Try and get a reference count on the nfsv4rootfs_lock so that 1103 * no nfsd thread can acquire an exclusive lock on it before this 1104 * call is done. If it is already exclusively locked, just return. 1105 */ 1106 NFSLOCKV4ROOTMUTEX(); 1107 got_ref = nfsv4_getref_nonblock(&nfsv4rootfs_lock); 1108 NFSUNLOCKV4ROOTMUTEX(); 1109 if (got_ref == 0) { 1110 NFSUNLOCKSTATE(); 1111 return; 1112 } 1113 1114 /* 1115 * For each client... 1116 */ 1117 for (i = 0; i < nfsrv_clienthashsize; i++) { 1118 clp = LIST_FIRST(&nfsclienthash[i]); 1119 while (clp != LIST_END(&nfsclienthash[i])) { 1120 nclp = LIST_NEXT(clp, lc_hash); 1121 if (!(clp->lc_flags & LCL_EXPIREIT)) { 1122 if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC 1123 && ((LIST_EMPTY(&clp->lc_deleg) 1124 && LIST_EMPTY(&clp->lc_open)) || 1125 nfsrv_clients > nfsrv_clienthighwater)) || 1126 (clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC || 1127 (clp->lc_expiry < NFSD_MONOSEC && 1128 (nfsrv_openpluslock * 10 / 9) > nfsrv_v4statelimit)) { 1129 /* 1130 * Lease has expired several nfsrv_lease times ago: 1131 * PLUS 1132 * - no state is associated with it 1133 * OR 1134 * - above high water mark for number of clients 1135 * (nfsrv_clienthighwater should be large enough 1136 * that this only occurs when clients fail to 1137 * use the same nfs_client_id4.id. Maybe somewhat 1138 * higher that the maximum number of clients that 1139 * will mount this server?) 1140 * OR 1141 * Lease has expired a very long time ago 1142 * OR 1143 * Lease has expired PLUS the number of opens + locks 1144 * has exceeded 90% of capacity 1145 * 1146 * --> Mark for expiry. The actual expiry will be done 1147 * by an nfsd sometime soon. 1148 */ 1149 clp->lc_flags |= LCL_EXPIREIT; 1150 nfsrv_stablefirst.nsf_flags |= 1151 (NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT); 1152 } else { 1153 /* 1154 * If there are no opens, increment no open tick cnt 1155 * If time exceeds NFSNOOPEN, mark it to be thrown away 1156 * otherwise, if there is an open, reset no open time 1157 * Hopefully, this will avoid excessive re-creation 1158 * of open owners and subsequent open confirms. 1159 */ 1160 stp = LIST_FIRST(&clp->lc_open); 1161 while (stp != LIST_END(&clp->lc_open)) { 1162 nstp = LIST_NEXT(stp, ls_list); 1163 if (LIST_EMPTY(&stp->ls_open)) { 1164 stp->ls_noopens++; 1165 if (stp->ls_noopens > NFSNOOPEN || 1166 (nfsrv_openpluslock * 2) > 1167 nfsrv_v4statelimit) 1168 nfsrv_stablefirst.nsf_flags |= 1169 NFSNSF_NOOPENS; 1170 } else { 1171 stp->ls_noopens = 0; 1172 } 1173 stp = nstp; 1174 } 1175 } 1176 } 1177 clp = nclp; 1178 } 1179 } 1180 NFSUNLOCKSTATE(); 1181 NFSLOCKV4ROOTMUTEX(); 1182 nfsv4_relref(&nfsv4rootfs_lock); 1183 NFSUNLOCKV4ROOTMUTEX(); 1184 } 1185 1186 /* 1187 * The following set of functions free up the various data structures. 1188 */ 1189 /* 1190 * Clear out all open/lock state related to this nfsclient. 1191 * Caller must hold an exclusive lock on nfsv4rootfs_lock, so that 1192 * there are no other active nfsd threads. 1193 */ 1194 APPLESTATIC void 1195 nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p) 1196 { 1197 struct nfsstate *stp, *nstp; 1198 struct nfsdsession *sep, *nsep; 1199 1200 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) 1201 nfsrv_freeopenowner(stp, 1, p); 1202 if ((clp->lc_flags & LCL_ADMINREVOKED) == 0) 1203 LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) 1204 (void)nfsrv_freesession(sep, NULL); 1205 } 1206 1207 /* 1208 * Free a client that has been cleaned. It should also already have been 1209 * removed from the lists. 1210 * (Just to be safe w.r.t. newnfs_disconnect(), call this function when 1211 * softclock interrupts are enabled.) 1212 */ 1213 APPLESTATIC void 1214 nfsrv_zapclient(struct nfsclient *clp, NFSPROC_T *p) 1215 { 1216 1217 #ifdef notyet 1218 if ((clp->lc_flags & (LCL_GSS | LCL_CALLBACKSON)) == 1219 (LCL_GSS | LCL_CALLBACKSON) && 1220 (clp->lc_hand.nfsh_flag & NFSG_COMPLETE) && 1221 clp->lc_handlelen > 0) { 1222 clp->lc_hand.nfsh_flag &= ~NFSG_COMPLETE; 1223 clp->lc_hand.nfsh_flag |= NFSG_DESTROYED; 1224 (void) nfsrv_docallback(clp, NFSV4PROC_CBNULL, 1225 NULL, 0, NULL, NULL, NULL, p); 1226 } 1227 #endif 1228 newnfs_disconnect(&clp->lc_req); 1229 free(clp->lc_req.nr_nam, M_SONAME); 1230 NFSFREEMUTEX(&clp->lc_req.nr_mtx); 1231 free(clp->lc_stateid, M_NFSDCLIENT); 1232 free(clp, M_NFSDCLIENT); 1233 NFSLOCKSTATE(); 1234 nfsstatsv1.srvclients--; 1235 nfsrv_openpluslock--; 1236 nfsrv_clients--; 1237 NFSUNLOCKSTATE(); 1238 } 1239 1240 /* 1241 * Free a list of delegation state structures. 1242 * (This function will also free all nfslockfile structures that no 1243 * longer have associated state.) 1244 */ 1245 APPLESTATIC void 1246 nfsrv_freedeleglist(struct nfsstatehead *sthp) 1247 { 1248 struct nfsstate *stp, *nstp; 1249 1250 LIST_FOREACH_SAFE(stp, sthp, ls_list, nstp) { 1251 nfsrv_freedeleg(stp); 1252 } 1253 LIST_INIT(sthp); 1254 } 1255 1256 /* 1257 * Free up a delegation. 1258 */ 1259 static void 1260 nfsrv_freedeleg(struct nfsstate *stp) 1261 { 1262 struct nfslockfile *lfp; 1263 1264 LIST_REMOVE(stp, ls_hash); 1265 LIST_REMOVE(stp, ls_list); 1266 LIST_REMOVE(stp, ls_file); 1267 if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0) 1268 nfsrv_writedelegcnt--; 1269 lfp = stp->ls_lfp; 1270 if (LIST_EMPTY(&lfp->lf_open) && 1271 LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) && 1272 LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && 1273 lfp->lf_usecount == 0 && 1274 nfsv4_testlock(&lfp->lf_locallock_lck) == 0) 1275 nfsrv_freenfslockfile(lfp); 1276 free(stp, M_NFSDSTATE); 1277 nfsstatsv1.srvdelegates--; 1278 nfsrv_openpluslock--; 1279 nfsrv_delegatecnt--; 1280 } 1281 1282 /* 1283 * This function frees an open owner and all associated opens. 1284 */ 1285 static void 1286 nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p) 1287 { 1288 struct nfsstate *nstp, *tstp; 1289 1290 LIST_REMOVE(stp, ls_list); 1291 /* 1292 * Now, free all associated opens. 1293 */ 1294 nstp = LIST_FIRST(&stp->ls_open); 1295 while (nstp != LIST_END(&stp->ls_open)) { 1296 tstp = nstp; 1297 nstp = LIST_NEXT(nstp, ls_list); 1298 (void) nfsrv_freeopen(tstp, NULL, cansleep, p); 1299 } 1300 if (stp->ls_op) 1301 nfsrvd_derefcache(stp->ls_op); 1302 free(stp, M_NFSDSTATE); 1303 nfsstatsv1.srvopenowners--; 1304 nfsrv_openpluslock--; 1305 } 1306 1307 /* 1308 * This function frees an open (nfsstate open structure) with all associated 1309 * lock_owners and locks. It also frees the nfslockfile structure iff there 1310 * are no other opens on the file. 1311 * Returns 1 if it free'd the nfslockfile, 0 otherwise. 1312 */ 1313 static int 1314 nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p) 1315 { 1316 struct nfsstate *nstp, *tstp; 1317 struct nfslockfile *lfp; 1318 int ret; 1319 1320 LIST_REMOVE(stp, ls_hash); 1321 LIST_REMOVE(stp, ls_list); 1322 LIST_REMOVE(stp, ls_file); 1323 1324 lfp = stp->ls_lfp; 1325 /* 1326 * Now, free all lockowners associated with this open. 1327 */ 1328 LIST_FOREACH_SAFE(tstp, &stp->ls_open, ls_list, nstp) 1329 nfsrv_freelockowner(tstp, vp, cansleep, p); 1330 1331 /* 1332 * The nfslockfile is freed here if there are no locks 1333 * associated with the open. 1334 * If there are locks associated with the open, the 1335 * nfslockfile structure can be freed via nfsrv_freelockowner(). 1336 * Acquire the state mutex to avoid races with calls to 1337 * nfsrv_getlockfile(). 1338 */ 1339 if (cansleep != 0) 1340 NFSLOCKSTATE(); 1341 if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) && 1342 LIST_EMPTY(&lfp->lf_deleg) && LIST_EMPTY(&lfp->lf_lock) && 1343 LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && 1344 lfp->lf_usecount == 0 && 1345 (cansleep != 0 || nfsv4_testlock(&lfp->lf_locallock_lck) == 0)) { 1346 nfsrv_freenfslockfile(lfp); 1347 ret = 1; 1348 } else 1349 ret = 0; 1350 if (cansleep != 0) 1351 NFSUNLOCKSTATE(); 1352 free(stp, M_NFSDSTATE); 1353 nfsstatsv1.srvopens--; 1354 nfsrv_openpluslock--; 1355 return (ret); 1356 } 1357 1358 /* 1359 * Frees a lockowner and all associated locks. 1360 */ 1361 static void 1362 nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, 1363 NFSPROC_T *p) 1364 { 1365 1366 LIST_REMOVE(stp, ls_hash); 1367 LIST_REMOVE(stp, ls_list); 1368 nfsrv_freeallnfslocks(stp, vp, cansleep, p); 1369 if (stp->ls_op) 1370 nfsrvd_derefcache(stp->ls_op); 1371 free(stp, M_NFSDSTATE); 1372 nfsstatsv1.srvlockowners--; 1373 nfsrv_openpluslock--; 1374 } 1375 1376 /* 1377 * Free all the nfs locks on a lockowner. 1378 */ 1379 static void 1380 nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep, 1381 NFSPROC_T *p) 1382 { 1383 struct nfslock *lop, *nlop; 1384 struct nfsrollback *rlp, *nrlp; 1385 struct nfslockfile *lfp = NULL; 1386 int gottvp = 0; 1387 vnode_t tvp = NULL; 1388 uint64_t first, end; 1389 1390 if (vp != NULL) 1391 ASSERT_VOP_UNLOCKED(vp, "nfsrv_freeallnfslocks: vnode locked"); 1392 lop = LIST_FIRST(&stp->ls_lock); 1393 while (lop != LIST_END(&stp->ls_lock)) { 1394 nlop = LIST_NEXT(lop, lo_lckowner); 1395 /* 1396 * Since all locks should be for the same file, lfp should 1397 * not change. 1398 */ 1399 if (lfp == NULL) 1400 lfp = lop->lo_lfp; 1401 else if (lfp != lop->lo_lfp) 1402 panic("allnfslocks"); 1403 /* 1404 * If vp is NULL and cansleep != 0, a vnode must be acquired 1405 * from the file handle. This only occurs when called from 1406 * nfsrv_cleanclient(). 1407 */ 1408 if (gottvp == 0) { 1409 if (nfsrv_dolocallocks == 0) 1410 tvp = NULL; 1411 else if (vp == NULL && cansleep != 0) { 1412 tvp = nfsvno_getvp(&lfp->lf_fh); 1413 NFSVOPUNLOCK(tvp, 0); 1414 } else 1415 tvp = vp; 1416 gottvp = 1; 1417 } 1418 1419 if (tvp != NULL) { 1420 if (cansleep == 0) 1421 panic("allnfs2"); 1422 first = lop->lo_first; 1423 end = lop->lo_end; 1424 nfsrv_freenfslock(lop); 1425 nfsrv_localunlock(tvp, lfp, first, end, p); 1426 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, 1427 nrlp) 1428 free(rlp, M_NFSDROLLBACK); 1429 LIST_INIT(&lfp->lf_rollback); 1430 } else 1431 nfsrv_freenfslock(lop); 1432 lop = nlop; 1433 } 1434 if (vp == NULL && tvp != NULL) 1435 vrele(tvp); 1436 } 1437 1438 /* 1439 * Free an nfslock structure. 1440 */ 1441 static void 1442 nfsrv_freenfslock(struct nfslock *lop) 1443 { 1444 1445 if (lop->lo_lckfile.le_prev != NULL) { 1446 LIST_REMOVE(lop, lo_lckfile); 1447 nfsstatsv1.srvlocks--; 1448 nfsrv_openpluslock--; 1449 } 1450 LIST_REMOVE(lop, lo_lckowner); 1451 free(lop, M_NFSDLOCK); 1452 } 1453 1454 /* 1455 * This function frees an nfslockfile structure. 1456 */ 1457 static void 1458 nfsrv_freenfslockfile(struct nfslockfile *lfp) 1459 { 1460 1461 LIST_REMOVE(lfp, lf_hash); 1462 free(lfp, M_NFSDLOCKFILE); 1463 } 1464 1465 /* 1466 * This function looks up an nfsstate structure via stateid. 1467 */ 1468 static int 1469 nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32_t flags, 1470 struct nfsstate **stpp) 1471 { 1472 struct nfsstate *stp; 1473 struct nfsstatehead *hp; 1474 int error = 0; 1475 1476 *stpp = NULL; 1477 hp = NFSSTATEHASH(clp, *stateidp); 1478 LIST_FOREACH(stp, hp, ls_hash) { 1479 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other, 1480 NFSX_STATEIDOTHER)) 1481 break; 1482 } 1483 1484 /* 1485 * If no state id in list, return NFSERR_BADSTATEID. 1486 */ 1487 if (stp == LIST_END(hp)) { 1488 error = NFSERR_BADSTATEID; 1489 goto out; 1490 } 1491 *stpp = stp; 1492 1493 out: 1494 NFSEXITCODE(error); 1495 return (error); 1496 } 1497 1498 /* 1499 * This function gets an nfsstate structure via owner string. 1500 */ 1501 static void 1502 nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, 1503 struct nfsstate **stpp) 1504 { 1505 struct nfsstate *stp; 1506 1507 *stpp = NULL; 1508 LIST_FOREACH(stp, hp, ls_list) { 1509 if (new_stp->ls_ownerlen == stp->ls_ownerlen && 1510 !NFSBCMP(new_stp->ls_owner,stp->ls_owner,stp->ls_ownerlen)) { 1511 *stpp = stp; 1512 return; 1513 } 1514 } 1515 } 1516 1517 /* 1518 * Lock control function called to update lock status. 1519 * Returns 0 upon success, -1 if there is no lock and the flags indicate 1520 * that one isn't to be created and an NFSERR_xxx for other errors. 1521 * The structures new_stp and new_lop are passed in as pointers that should 1522 * be set to NULL if the structure is used and shouldn't be free'd. 1523 * For the NFSLCK_TEST and NFSLCK_CHECK cases, the structures are 1524 * never used and can safely be allocated on the stack. For all other 1525 * cases, *new_stpp and *new_lopp should be malloc'd before the call, 1526 * in case they are used. 1527 */ 1528 APPLESTATIC int 1529 nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp, 1530 struct nfslock **new_lopp, struct nfslockconflict *cfp, 1531 nfsquad_t clientid, nfsv4stateid_t *stateidp, 1532 __unused struct nfsexstuff *exp, 1533 struct nfsrv_descript *nd, NFSPROC_T *p) 1534 { 1535 struct nfslock *lop; 1536 struct nfsstate *new_stp = *new_stpp; 1537 struct nfslock *new_lop = *new_lopp; 1538 struct nfsstate *tstp, *mystp, *nstp; 1539 int specialid = 0; 1540 struct nfslockfile *lfp; 1541 struct nfslock *other_lop = NULL; 1542 struct nfsstate *stp, *lckstp = NULL; 1543 struct nfsclient *clp = NULL; 1544 u_int32_t bits; 1545 int error = 0, haslock = 0, ret, reterr; 1546 int getlckret, delegation = 0, filestruct_locked, vnode_unlocked = 0; 1547 fhandle_t nfh; 1548 uint64_t first, end; 1549 uint32_t lock_flags; 1550 1551 if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_SETATTR)) { 1552 /* 1553 * Note the special cases of "all 1s" or "all 0s" stateids and 1554 * let reads with all 1s go ahead. 1555 */ 1556 if (new_stp->ls_stateid.seqid == 0x0 && 1557 new_stp->ls_stateid.other[0] == 0x0 && 1558 new_stp->ls_stateid.other[1] == 0x0 && 1559 new_stp->ls_stateid.other[2] == 0x0) 1560 specialid = 1; 1561 else if (new_stp->ls_stateid.seqid == 0xffffffff && 1562 new_stp->ls_stateid.other[0] == 0xffffffff && 1563 new_stp->ls_stateid.other[1] == 0xffffffff && 1564 new_stp->ls_stateid.other[2] == 0xffffffff) 1565 specialid = 2; 1566 } 1567 1568 /* 1569 * Check for restart conditions (client and server). 1570 */ 1571 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 1572 &new_stp->ls_stateid, specialid); 1573 if (error) 1574 goto out; 1575 1576 /* 1577 * Check for state resource limit exceeded. 1578 */ 1579 if ((new_stp->ls_flags & NFSLCK_LOCK) && 1580 nfsrv_openpluslock > nfsrv_v4statelimit) { 1581 error = NFSERR_RESOURCE; 1582 goto out; 1583 } 1584 1585 /* 1586 * For the lock case, get another nfslock structure, 1587 * just in case we need it. 1588 * Malloc now, before we start sifting through the linked lists, 1589 * in case we have to wait for memory. 1590 */ 1591 tryagain: 1592 if (new_stp->ls_flags & NFSLCK_LOCK) 1593 other_lop = malloc(sizeof (struct nfslock), 1594 M_NFSDLOCK, M_WAITOK); 1595 filestruct_locked = 0; 1596 reterr = 0; 1597 lfp = NULL; 1598 1599 /* 1600 * Get the lockfile structure for CFH now, so we can do a sanity 1601 * check against the stateid, before incrementing the seqid#, since 1602 * we want to return NFSERR_BADSTATEID on failure and the seqid# 1603 * shouldn't be incremented for this case. 1604 * If nfsrv_getlockfile() returns -1, it means "not found", which 1605 * will be handled later. 1606 * If we are doing Lock/LockU and local locking is enabled, sleep 1607 * lock the nfslockfile structure. 1608 */ 1609 getlckret = nfsrv_getlockfh(vp, new_stp->ls_flags, NULL, &nfh, p); 1610 NFSLOCKSTATE(); 1611 if (getlckret == 0) { 1612 if ((new_stp->ls_flags & (NFSLCK_LOCK | NFSLCK_UNLOCK)) != 0 && 1613 nfsrv_dolocallocks != 0 && nd->nd_repstat == 0) { 1614 getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, 1615 &lfp, &nfh, 1); 1616 if (getlckret == 0) 1617 filestruct_locked = 1; 1618 } else 1619 getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, 1620 &lfp, &nfh, 0); 1621 } 1622 if (getlckret != 0 && getlckret != -1) 1623 reterr = getlckret; 1624 1625 if (filestruct_locked != 0) { 1626 LIST_INIT(&lfp->lf_rollback); 1627 if ((new_stp->ls_flags & NFSLCK_LOCK)) { 1628 /* 1629 * For local locking, do the advisory locking now, so 1630 * that any conflict can be detected. A failure later 1631 * can be rolled back locally. If an error is returned, 1632 * struct nfslockfile has been unlocked and any local 1633 * locking rolled back. 1634 */ 1635 NFSUNLOCKSTATE(); 1636 if (vnode_unlocked == 0) { 1637 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl1"); 1638 vnode_unlocked = 1; 1639 NFSVOPUNLOCK(vp, 0); 1640 } 1641 reterr = nfsrv_locallock(vp, lfp, 1642 (new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)), 1643 new_lop->lo_first, new_lop->lo_end, cfp, p); 1644 NFSLOCKSTATE(); 1645 } 1646 } 1647 1648 if (specialid == 0) { 1649 if (new_stp->ls_flags & NFSLCK_TEST) { 1650 /* 1651 * RFC 3530 does not list LockT as an op that renews a 1652 * lease, but the consensus seems to be that it is ok 1653 * for a server to do so. 1654 */ 1655 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 1656 (nfsquad_t)((u_quad_t)0), 0, nd, p); 1657 1658 /* 1659 * Since NFSERR_EXPIRED, NFSERR_ADMINREVOKED are not valid 1660 * error returns for LockT, just go ahead and test for a lock, 1661 * since there are no locks for this client, but other locks 1662 * can conflict. (ie. same client will always be false) 1663 */ 1664 if (error == NFSERR_EXPIRED || error == NFSERR_ADMINREVOKED) 1665 error = 0; 1666 lckstp = new_stp; 1667 } else { 1668 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 1669 (nfsquad_t)((u_quad_t)0), 0, nd, p); 1670 if (error == 0) 1671 /* 1672 * Look up the stateid 1673 */ 1674 error = nfsrv_getstate(clp, &new_stp->ls_stateid, 1675 new_stp->ls_flags, &stp); 1676 /* 1677 * do some sanity checks for an unconfirmed open or a 1678 * stateid that refers to the wrong file, for an open stateid 1679 */ 1680 if (error == 0 && (stp->ls_flags & NFSLCK_OPEN) && 1681 ((stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM) || 1682 (getlckret == 0 && stp->ls_lfp != lfp))){ 1683 /* 1684 * NFSLCK_SETATTR should return OK rather than NFSERR_BADSTATEID 1685 * The only exception is using SETATTR with SIZE. 1686 * */ 1687 if ((new_stp->ls_flags & 1688 (NFSLCK_SETATTR | NFSLCK_CHECK)) != NFSLCK_SETATTR) 1689 error = NFSERR_BADSTATEID; 1690 } 1691 1692 if (error == 0 && 1693 (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) && 1694 getlckret == 0 && stp->ls_lfp != lfp) 1695 error = NFSERR_BADSTATEID; 1696 1697 /* 1698 * If the lockowner stateid doesn't refer to the same file, 1699 * I believe that is considered ok, since some clients will 1700 * only create a single lockowner and use that for all locks 1701 * on all files. 1702 * For now, log it as a diagnostic, instead of considering it 1703 * a BadStateid. 1704 */ 1705 if (error == 0 && (stp->ls_flags & 1706 (NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 && 1707 getlckret == 0 && stp->ls_lfp != lfp) { 1708 #ifdef DIAGNOSTIC 1709 printf("Got a lock statid for different file open\n"); 1710 #endif 1711 /* 1712 error = NFSERR_BADSTATEID; 1713 */ 1714 } 1715 1716 if (error == 0) { 1717 if (new_stp->ls_flags & NFSLCK_OPENTOLOCK) { 1718 /* 1719 * If haslock set, we've already checked the seqid. 1720 */ 1721 if (!haslock) { 1722 if (stp->ls_flags & NFSLCK_OPEN) 1723 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 1724 stp->ls_openowner, new_stp->ls_op); 1725 else 1726 error = NFSERR_BADSTATEID; 1727 } 1728 if (!error) 1729 nfsrv_getowner(&stp->ls_open, new_stp, &lckstp); 1730 if (lckstp) 1731 /* 1732 * I believe this should be an error, but it 1733 * isn't obvious what NFSERR_xxx would be 1734 * appropriate, so I'll use NFSERR_INVAL for now. 1735 */ 1736 error = NFSERR_INVAL; 1737 else 1738 lckstp = new_stp; 1739 } else if (new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK)) { 1740 /* 1741 * If haslock set, ditto above. 1742 */ 1743 if (!haslock) { 1744 if (stp->ls_flags & NFSLCK_OPEN) 1745 error = NFSERR_BADSTATEID; 1746 else 1747 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 1748 stp, new_stp->ls_op); 1749 } 1750 lckstp = stp; 1751 } else { 1752 lckstp = stp; 1753 } 1754 } 1755 /* 1756 * If the seqid part of the stateid isn't the same, return 1757 * NFSERR_OLDSTATEID for cases other than I/O Ops. 1758 * For I/O Ops, only return NFSERR_OLDSTATEID if 1759 * nfsrv_returnoldstateid is set. (The consensus on the email 1760 * list was that most clients would prefer to not receive 1761 * NFSERR_OLDSTATEID for I/O Ops, but the RFC suggests that that 1762 * is what will happen, so I use the nfsrv_returnoldstateid to 1763 * allow for either server configuration.) 1764 */ 1765 if (!error && stp->ls_stateid.seqid!=new_stp->ls_stateid.seqid && 1766 (((nd->nd_flag & ND_NFSV41) == 0 && 1767 (!(new_stp->ls_flags & NFSLCK_CHECK) || 1768 nfsrv_returnoldstateid)) || 1769 ((nd->nd_flag & ND_NFSV41) != 0 && 1770 new_stp->ls_stateid.seqid != 0))) 1771 error = NFSERR_OLDSTATEID; 1772 } 1773 } 1774 1775 /* 1776 * Now we can check for grace. 1777 */ 1778 if (!error) 1779 error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags); 1780 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error && 1781 nfsrv_checkstable(clp)) 1782 error = NFSERR_NOGRACE; 1783 /* 1784 * If we successfully Reclaimed state, note that. 1785 */ 1786 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error) 1787 nfsrv_markstable(clp); 1788 1789 /* 1790 * At this point, either error == NFSERR_BADSTATEID or the 1791 * seqid# has been updated, so we can return any error. 1792 * If error == 0, there may be an error in: 1793 * nd_repstat - Set by the calling function. 1794 * reterr - Set above, if getting the nfslockfile structure 1795 * or acquiring the local lock failed. 1796 * (If both of these are set, nd_repstat should probably be 1797 * returned, since that error was detected before this 1798 * function call.) 1799 */ 1800 if (error != 0 || nd->nd_repstat != 0 || reterr != 0) { 1801 if (error == 0) { 1802 if (nd->nd_repstat != 0) 1803 error = nd->nd_repstat; 1804 else 1805 error = reterr; 1806 } 1807 if (filestruct_locked != 0) { 1808 /* Roll back local locks. */ 1809 NFSUNLOCKSTATE(); 1810 if (vnode_unlocked == 0) { 1811 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl2"); 1812 vnode_unlocked = 1; 1813 NFSVOPUNLOCK(vp, 0); 1814 } 1815 nfsrv_locallock_rollback(vp, lfp, p); 1816 NFSLOCKSTATE(); 1817 nfsrv_unlocklf(lfp); 1818 } 1819 NFSUNLOCKSTATE(); 1820 goto out; 1821 } 1822 1823 /* 1824 * Check the nfsrv_getlockfile return. 1825 * Returned -1 if no structure found. 1826 */ 1827 if (getlckret == -1) { 1828 error = NFSERR_EXPIRED; 1829 /* 1830 * Called from lockt, so no lock is OK. 1831 */ 1832 if (new_stp->ls_flags & NFSLCK_TEST) { 1833 error = 0; 1834 } else if (new_stp->ls_flags & 1835 (NFSLCK_CHECK | NFSLCK_SETATTR)) { 1836 /* 1837 * Called to check for a lock, OK if the stateid is all 1838 * 1s or all 0s, but there should be an nfsstate 1839 * otherwise. 1840 * (ie. If there is no open, I'll assume no share 1841 * deny bits.) 1842 */ 1843 if (specialid) 1844 error = 0; 1845 else 1846 error = NFSERR_BADSTATEID; 1847 } 1848 NFSUNLOCKSTATE(); 1849 goto out; 1850 } 1851 1852 /* 1853 * For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict. 1854 * For NFSLCK_CHECK, allow a read if write access is granted, 1855 * but check for a deny. For NFSLCK_LOCK, require correct access, 1856 * which implies a conflicting deny can't exist. 1857 */ 1858 if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_LOCK)) { 1859 /* 1860 * Four kinds of state id: 1861 * - specialid (all 0s or all 1s), only for NFSLCK_CHECK 1862 * - stateid for an open 1863 * - stateid for a delegation 1864 * - stateid for a lock owner 1865 */ 1866 if (!specialid) { 1867 if (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { 1868 delegation = 1; 1869 mystp = stp; 1870 nfsrv_delaydelegtimeout(stp); 1871 } else if (stp->ls_flags & NFSLCK_OPEN) { 1872 mystp = stp; 1873 } else { 1874 mystp = stp->ls_openstp; 1875 } 1876 /* 1877 * If locking or checking, require correct access 1878 * bit set. 1879 */ 1880 if (((new_stp->ls_flags & NFSLCK_LOCK) && 1881 !((new_lop->lo_flags >> NFSLCK_LOCKSHIFT) & 1882 mystp->ls_flags & NFSLCK_ACCESSBITS)) || 1883 ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_READACCESS)) == 1884 (NFSLCK_CHECK | NFSLCK_READACCESS) && 1885 !(mystp->ls_flags & NFSLCK_READACCESS) && 1886 nfsrv_allowreadforwriteopen == 0) || 1887 ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) == 1888 (NFSLCK_CHECK | NFSLCK_WRITEACCESS) && 1889 !(mystp->ls_flags & NFSLCK_WRITEACCESS))) { 1890 if (filestruct_locked != 0) { 1891 /* Roll back local locks. */ 1892 NFSUNLOCKSTATE(); 1893 if (vnode_unlocked == 0) { 1894 ASSERT_VOP_ELOCKED(vp, 1895 "nfsrv_lockctrl3"); 1896 vnode_unlocked = 1; 1897 NFSVOPUNLOCK(vp, 0); 1898 } 1899 nfsrv_locallock_rollback(vp, lfp, p); 1900 NFSLOCKSTATE(); 1901 nfsrv_unlocklf(lfp); 1902 } 1903 NFSUNLOCKSTATE(); 1904 error = NFSERR_OPENMODE; 1905 goto out; 1906 } 1907 } else 1908 mystp = NULL; 1909 if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) { 1910 /* 1911 * Check for a conflicting deny bit. 1912 */ 1913 LIST_FOREACH(tstp, &lfp->lf_open, ls_file) { 1914 if (tstp != mystp) { 1915 bits = tstp->ls_flags; 1916 bits >>= NFSLCK_SHIFT; 1917 if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) { 1918 KASSERT(vnode_unlocked == 0, 1919 ("nfsrv_lockctrl: vnode unlocked1")); 1920 ret = nfsrv_clientconflict(tstp->ls_clp, &haslock, 1921 vp, p); 1922 if (ret == 1) { 1923 /* 1924 * nfsrv_clientconflict unlocks state 1925 * when it returns non-zero. 1926 */ 1927 lckstp = NULL; 1928 goto tryagain; 1929 } 1930 if (ret == 0) 1931 NFSUNLOCKSTATE(); 1932 if (ret == 2) 1933 error = NFSERR_PERM; 1934 else 1935 error = NFSERR_OPENMODE; 1936 goto out; 1937 } 1938 } 1939 } 1940 1941 /* We're outta here */ 1942 NFSUNLOCKSTATE(); 1943 goto out; 1944 } 1945 } 1946 1947 /* 1948 * For setattr, just get rid of all the Delegations for other clients. 1949 */ 1950 if (new_stp->ls_flags & NFSLCK_SETATTR) { 1951 KASSERT(vnode_unlocked == 0, 1952 ("nfsrv_lockctrl: vnode unlocked2")); 1953 ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p); 1954 if (ret) { 1955 /* 1956 * nfsrv_cleandeleg() unlocks state when it 1957 * returns non-zero. 1958 */ 1959 if (ret == -1) { 1960 lckstp = NULL; 1961 goto tryagain; 1962 } 1963 error = ret; 1964 goto out; 1965 } 1966 if (!(new_stp->ls_flags & NFSLCK_CHECK) || 1967 (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) && 1968 LIST_EMPTY(&lfp->lf_deleg))) { 1969 NFSUNLOCKSTATE(); 1970 goto out; 1971 } 1972 } 1973 1974 /* 1975 * Check for a conflicting delegation. If one is found, call 1976 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 1977 * been set yet, it will get the lock. Otherwise, it will recall 1978 * the delegation. Then, we try try again... 1979 * I currently believe the conflict algorithm to be: 1980 * For Lock Ops (Lock/LockT/LockU) 1981 * - there is a conflict iff a different client has a write delegation 1982 * For Reading (Read Op) 1983 * - there is a conflict iff a different client has a write delegation 1984 * (the specialids are always a different client) 1985 * For Writing (Write/Setattr of size) 1986 * - there is a conflict if a different client has any delegation 1987 * - there is a conflict if the same client has a read delegation 1988 * (I don't understand why this isn't allowed, but that seems to be 1989 * the current consensus?) 1990 */ 1991 tstp = LIST_FIRST(&lfp->lf_deleg); 1992 while (tstp != LIST_END(&lfp->lf_deleg)) { 1993 nstp = LIST_NEXT(tstp, ls_file); 1994 if ((((new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK|NFSLCK_TEST))|| 1995 ((new_stp->ls_flags & NFSLCK_CHECK) && 1996 (new_lop->lo_flags & NFSLCK_READ))) && 1997 clp != tstp->ls_clp && 1998 (tstp->ls_flags & NFSLCK_DELEGWRITE)) || 1999 ((new_stp->ls_flags & NFSLCK_CHECK) && 2000 (new_lop->lo_flags & NFSLCK_WRITE) && 2001 (clp != tstp->ls_clp || 2002 (tstp->ls_flags & NFSLCK_DELEGREAD)))) { 2003 ret = 0; 2004 if (filestruct_locked != 0) { 2005 /* Roll back local locks. */ 2006 NFSUNLOCKSTATE(); 2007 if (vnode_unlocked == 0) { 2008 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl4"); 2009 NFSVOPUNLOCK(vp, 0); 2010 } 2011 nfsrv_locallock_rollback(vp, lfp, p); 2012 NFSLOCKSTATE(); 2013 nfsrv_unlocklf(lfp); 2014 NFSUNLOCKSTATE(); 2015 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 2016 vnode_unlocked = 0; 2017 if ((vp->v_iflag & VI_DOOMED) != 0) 2018 ret = NFSERR_SERVERFAULT; 2019 NFSLOCKSTATE(); 2020 } 2021 if (ret == 0) 2022 ret = nfsrv_delegconflict(tstp, &haslock, p, vp); 2023 if (ret) { 2024 /* 2025 * nfsrv_delegconflict unlocks state when it 2026 * returns non-zero, which it always does. 2027 */ 2028 if (other_lop) { 2029 free(other_lop, M_NFSDLOCK); 2030 other_lop = NULL; 2031 } 2032 if (ret == -1) { 2033 lckstp = NULL; 2034 goto tryagain; 2035 } 2036 error = ret; 2037 goto out; 2038 } 2039 /* Never gets here. */ 2040 } 2041 tstp = nstp; 2042 } 2043 2044 /* 2045 * Handle the unlock case by calling nfsrv_updatelock(). 2046 * (Should I have done some access checking above for unlock? For now, 2047 * just let it happen.) 2048 */ 2049 if (new_stp->ls_flags & NFSLCK_UNLOCK) { 2050 first = new_lop->lo_first; 2051 end = new_lop->lo_end; 2052 nfsrv_updatelock(stp, new_lopp, &other_lop, lfp); 2053 stateidp->seqid = ++(stp->ls_stateid.seqid); 2054 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0) 2055 stateidp->seqid = stp->ls_stateid.seqid = 1; 2056 stateidp->other[0] = stp->ls_stateid.other[0]; 2057 stateidp->other[1] = stp->ls_stateid.other[1]; 2058 stateidp->other[2] = stp->ls_stateid.other[2]; 2059 if (filestruct_locked != 0) { 2060 NFSUNLOCKSTATE(); 2061 if (vnode_unlocked == 0) { 2062 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl5"); 2063 vnode_unlocked = 1; 2064 NFSVOPUNLOCK(vp, 0); 2065 } 2066 /* Update the local locks. */ 2067 nfsrv_localunlock(vp, lfp, first, end, p); 2068 NFSLOCKSTATE(); 2069 nfsrv_unlocklf(lfp); 2070 } 2071 NFSUNLOCKSTATE(); 2072 goto out; 2073 } 2074 2075 /* 2076 * Search for a conflicting lock. A lock conflicts if: 2077 * - the lock range overlaps and 2078 * - at least one lock is a write lock and 2079 * - it is not owned by the same lock owner 2080 */ 2081 if (!delegation) { 2082 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { 2083 if (new_lop->lo_end > lop->lo_first && 2084 new_lop->lo_first < lop->lo_end && 2085 (new_lop->lo_flags == NFSLCK_WRITE || 2086 lop->lo_flags == NFSLCK_WRITE) && 2087 lckstp != lop->lo_stp && 2088 (clp != lop->lo_stp->ls_clp || 2089 lckstp->ls_ownerlen != lop->lo_stp->ls_ownerlen || 2090 NFSBCMP(lckstp->ls_owner, lop->lo_stp->ls_owner, 2091 lckstp->ls_ownerlen))) { 2092 if (other_lop) { 2093 free(other_lop, M_NFSDLOCK); 2094 other_lop = NULL; 2095 } 2096 if (vnode_unlocked != 0) 2097 ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock, 2098 NULL, p); 2099 else 2100 ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock, 2101 vp, p); 2102 if (ret == 1) { 2103 if (filestruct_locked != 0) { 2104 if (vnode_unlocked == 0) { 2105 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl6"); 2106 NFSVOPUNLOCK(vp, 0); 2107 } 2108 /* Roll back local locks. */ 2109 nfsrv_locallock_rollback(vp, lfp, p); 2110 NFSLOCKSTATE(); 2111 nfsrv_unlocklf(lfp); 2112 NFSUNLOCKSTATE(); 2113 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 2114 vnode_unlocked = 0; 2115 if ((vp->v_iflag & VI_DOOMED) != 0) { 2116 error = NFSERR_SERVERFAULT; 2117 goto out; 2118 } 2119 } 2120 /* 2121 * nfsrv_clientconflict() unlocks state when it 2122 * returns non-zero. 2123 */ 2124 lckstp = NULL; 2125 goto tryagain; 2126 } 2127 /* 2128 * Found a conflicting lock, so record the conflict and 2129 * return the error. 2130 */ 2131 if (cfp != NULL && ret == 0) { 2132 cfp->cl_clientid.lval[0]=lop->lo_stp->ls_stateid.other[0]; 2133 cfp->cl_clientid.lval[1]=lop->lo_stp->ls_stateid.other[1]; 2134 cfp->cl_first = lop->lo_first; 2135 cfp->cl_end = lop->lo_end; 2136 cfp->cl_flags = lop->lo_flags; 2137 cfp->cl_ownerlen = lop->lo_stp->ls_ownerlen; 2138 NFSBCOPY(lop->lo_stp->ls_owner, cfp->cl_owner, 2139 cfp->cl_ownerlen); 2140 } 2141 if (ret == 2) 2142 error = NFSERR_PERM; 2143 else if (new_stp->ls_flags & NFSLCK_RECLAIM) 2144 error = NFSERR_RECLAIMCONFLICT; 2145 else if (new_stp->ls_flags & NFSLCK_CHECK) 2146 error = NFSERR_LOCKED; 2147 else 2148 error = NFSERR_DENIED; 2149 if (filestruct_locked != 0 && ret == 0) { 2150 /* Roll back local locks. */ 2151 NFSUNLOCKSTATE(); 2152 if (vnode_unlocked == 0) { 2153 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl7"); 2154 vnode_unlocked = 1; 2155 NFSVOPUNLOCK(vp, 0); 2156 } 2157 nfsrv_locallock_rollback(vp, lfp, p); 2158 NFSLOCKSTATE(); 2159 nfsrv_unlocklf(lfp); 2160 } 2161 if (ret == 0) 2162 NFSUNLOCKSTATE(); 2163 goto out; 2164 } 2165 } 2166 } 2167 2168 /* 2169 * We only get here if there was no lock that conflicted. 2170 */ 2171 if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) { 2172 NFSUNLOCKSTATE(); 2173 goto out; 2174 } 2175 2176 /* 2177 * We only get here when we are creating or modifying a lock. 2178 * There are two variants: 2179 * - exist_lock_owner where lock_owner exists 2180 * - open_to_lock_owner with new lock_owner 2181 */ 2182 first = new_lop->lo_first; 2183 end = new_lop->lo_end; 2184 lock_flags = new_lop->lo_flags; 2185 if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) { 2186 nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp); 2187 stateidp->seqid = ++(lckstp->ls_stateid.seqid); 2188 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0) 2189 stateidp->seqid = lckstp->ls_stateid.seqid = 1; 2190 stateidp->other[0] = lckstp->ls_stateid.other[0]; 2191 stateidp->other[1] = lckstp->ls_stateid.other[1]; 2192 stateidp->other[2] = lckstp->ls_stateid.other[2]; 2193 } else { 2194 /* 2195 * The new open_to_lock_owner case. 2196 * Link the new nfsstate into the lists. 2197 */ 2198 new_stp->ls_seq = new_stp->ls_opentolockseq; 2199 nfsrvd_refcache(new_stp->ls_op); 2200 stateidp->seqid = new_stp->ls_stateid.seqid = 1; 2201 stateidp->other[0] = new_stp->ls_stateid.other[0] = 2202 clp->lc_clientid.lval[0]; 2203 stateidp->other[1] = new_stp->ls_stateid.other[1] = 2204 clp->lc_clientid.lval[1]; 2205 stateidp->other[2] = new_stp->ls_stateid.other[2] = 2206 nfsrv_nextstateindex(clp); 2207 new_stp->ls_clp = clp; 2208 LIST_INIT(&new_stp->ls_lock); 2209 new_stp->ls_openstp = stp; 2210 new_stp->ls_lfp = lfp; 2211 nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp, 2212 lfp); 2213 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid), 2214 new_stp, ls_hash); 2215 LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list); 2216 *new_lopp = NULL; 2217 *new_stpp = NULL; 2218 nfsstatsv1.srvlockowners++; 2219 nfsrv_openpluslock++; 2220 } 2221 if (filestruct_locked != 0) { 2222 NFSUNLOCKSTATE(); 2223 nfsrv_locallock_commit(lfp, lock_flags, first, end); 2224 NFSLOCKSTATE(); 2225 nfsrv_unlocklf(lfp); 2226 } 2227 NFSUNLOCKSTATE(); 2228 2229 out: 2230 if (haslock) { 2231 NFSLOCKV4ROOTMUTEX(); 2232 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2233 NFSUNLOCKV4ROOTMUTEX(); 2234 } 2235 if (vnode_unlocked != 0) { 2236 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 2237 if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0) 2238 error = NFSERR_SERVERFAULT; 2239 } 2240 if (other_lop) 2241 free(other_lop, M_NFSDLOCK); 2242 NFSEXITCODE2(error, nd); 2243 return (error); 2244 } 2245 2246 /* 2247 * Check for state errors for Open. 2248 * repstat is passed back out as an error if more critical errors 2249 * are not detected. 2250 */ 2251 APPLESTATIC int 2252 nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp, 2253 struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd, 2254 NFSPROC_T *p, int repstat) 2255 { 2256 struct nfsstate *stp, *nstp; 2257 struct nfsclient *clp; 2258 struct nfsstate *ownerstp; 2259 struct nfslockfile *lfp, *new_lfp; 2260 int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0; 2261 2262 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 2263 readonly = 1; 2264 /* 2265 * Check for restart conditions (client and server). 2266 */ 2267 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2268 &new_stp->ls_stateid, 0); 2269 if (error) 2270 goto out; 2271 2272 /* 2273 * Check for state resource limit exceeded. 2274 * Technically this should be SMP protected, but the worst 2275 * case error is "out by one or two" on the count when it 2276 * returns NFSERR_RESOURCE and the limit is just a rather 2277 * arbitrary high water mark, so no harm is done. 2278 */ 2279 if (nfsrv_openpluslock > nfsrv_v4statelimit) { 2280 error = NFSERR_RESOURCE; 2281 goto out; 2282 } 2283 2284 tryagain: 2285 new_lfp = malloc(sizeof (struct nfslockfile), 2286 M_NFSDLOCKFILE, M_WAITOK); 2287 if (vp) 2288 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp, 2289 NULL, p); 2290 NFSLOCKSTATE(); 2291 /* 2292 * Get the nfsclient structure. 2293 */ 2294 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 2295 (nfsquad_t)((u_quad_t)0), 0, nd, p); 2296 2297 /* 2298 * Look up the open owner. See if it needs confirmation and 2299 * check the seq#, as required. 2300 */ 2301 if (!error) 2302 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp); 2303 2304 if (!error && ownerstp) { 2305 error = nfsrv_checkseqid(nd, new_stp->ls_seq, ownerstp, 2306 new_stp->ls_op); 2307 /* 2308 * If the OpenOwner hasn't been confirmed, assume the 2309 * old one was a replay and this one is ok. 2310 * See: RFC3530 Sec. 14.2.18. 2311 */ 2312 if (error == NFSERR_BADSEQID && 2313 (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM)) 2314 error = 0; 2315 } 2316 2317 /* 2318 * Check for grace. 2319 */ 2320 if (!error) 2321 error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags); 2322 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error && 2323 nfsrv_checkstable(clp)) 2324 error = NFSERR_NOGRACE; 2325 2326 /* 2327 * If none of the above errors occurred, let repstat be 2328 * returned. 2329 */ 2330 if (repstat && !error) 2331 error = repstat; 2332 if (error) { 2333 NFSUNLOCKSTATE(); 2334 if (haslock) { 2335 NFSLOCKV4ROOTMUTEX(); 2336 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2337 NFSUNLOCKV4ROOTMUTEX(); 2338 } 2339 free(new_lfp, M_NFSDLOCKFILE); 2340 goto out; 2341 } 2342 2343 /* 2344 * If vp == NULL, the file doesn't exist yet, so return ok. 2345 * (This always happens on the first pass, so haslock must be 0.) 2346 */ 2347 if (vp == NULL) { 2348 NFSUNLOCKSTATE(); 2349 free(new_lfp, M_NFSDLOCKFILE); 2350 goto out; 2351 } 2352 2353 /* 2354 * Get the structure for the underlying file. 2355 */ 2356 if (getfhret) 2357 error = getfhret; 2358 else 2359 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, 2360 NULL, 0); 2361 if (new_lfp) 2362 free(new_lfp, M_NFSDLOCKFILE); 2363 if (error) { 2364 NFSUNLOCKSTATE(); 2365 if (haslock) { 2366 NFSLOCKV4ROOTMUTEX(); 2367 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2368 NFSUNLOCKV4ROOTMUTEX(); 2369 } 2370 goto out; 2371 } 2372 2373 /* 2374 * Search for a conflicting open/share. 2375 */ 2376 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2377 /* 2378 * For Delegate_Cur, search for the matching Delegation, 2379 * which indicates no conflict. 2380 * An old delegation should have been recovered by the 2381 * client doing a Claim_DELEGATE_Prev, so I won't let 2382 * it match and return NFSERR_EXPIRED. Should I let it 2383 * match? 2384 */ 2385 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2386 if (!(stp->ls_flags & NFSLCK_OLDDELEG) && 2387 (((nd->nd_flag & ND_NFSV41) != 0 && 2388 stateidp->seqid == 0) || 2389 stateidp->seqid == stp->ls_stateid.seqid) && 2390 !NFSBCMP(stateidp->other, stp->ls_stateid.other, 2391 NFSX_STATEIDOTHER)) 2392 break; 2393 } 2394 if (stp == LIST_END(&lfp->lf_deleg) || 2395 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) && 2396 (stp->ls_flags & NFSLCK_DELEGREAD))) { 2397 NFSUNLOCKSTATE(); 2398 if (haslock) { 2399 NFSLOCKV4ROOTMUTEX(); 2400 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2401 NFSUNLOCKV4ROOTMUTEX(); 2402 } 2403 error = NFSERR_EXPIRED; 2404 goto out; 2405 } 2406 } 2407 2408 /* 2409 * Check for access/deny bit conflicts. I check for the same 2410 * owner as well, in case the client didn't bother. 2411 */ 2412 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 2413 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR) && 2414 (((new_stp->ls_flags & NFSLCK_ACCESSBITS) & 2415 ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))|| 2416 ((stp->ls_flags & NFSLCK_ACCESSBITS) & 2417 ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS)))){ 2418 ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p); 2419 if (ret == 1) { 2420 /* 2421 * nfsrv_clientconflict() unlocks 2422 * state when it returns non-zero. 2423 */ 2424 goto tryagain; 2425 } 2426 if (ret == 2) 2427 error = NFSERR_PERM; 2428 else if (new_stp->ls_flags & NFSLCK_RECLAIM) 2429 error = NFSERR_RECLAIMCONFLICT; 2430 else 2431 error = NFSERR_SHAREDENIED; 2432 if (ret == 0) 2433 NFSUNLOCKSTATE(); 2434 if (haslock) { 2435 NFSLOCKV4ROOTMUTEX(); 2436 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2437 NFSUNLOCKV4ROOTMUTEX(); 2438 } 2439 goto out; 2440 } 2441 } 2442 2443 /* 2444 * Check for a conflicting delegation. If one is found, call 2445 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2446 * been set yet, it will get the lock. Otherwise, it will recall 2447 * the delegation. Then, we try try again... 2448 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there 2449 * isn't a conflict.) 2450 * I currently believe the conflict algorithm to be: 2451 * For Open with Read Access and Deny None 2452 * - there is a conflict iff a different client has a write delegation 2453 * For Open with other Write Access or any Deny except None 2454 * - there is a conflict if a different client has any delegation 2455 * - there is a conflict if the same client has a read delegation 2456 * (The current consensus is that this last case should be 2457 * considered a conflict since the client with a read delegation 2458 * could have done an Open with ReadAccess and WriteDeny 2459 * locally and then not have checked for the WriteDeny.) 2460 * Don't check for a Reclaim, since that will be dealt with 2461 * by nfsrv_openctrl(). 2462 */ 2463 if (!(new_stp->ls_flags & 2464 (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR | NFSLCK_RECLAIM))) { 2465 stp = LIST_FIRST(&lfp->lf_deleg); 2466 while (stp != LIST_END(&lfp->lf_deleg)) { 2467 nstp = LIST_NEXT(stp, ls_file); 2468 if ((readonly && stp->ls_clp != clp && 2469 (stp->ls_flags & NFSLCK_DELEGWRITE)) || 2470 (!readonly && (stp->ls_clp != clp || 2471 (stp->ls_flags & NFSLCK_DELEGREAD)))) { 2472 ret = nfsrv_delegconflict(stp, &haslock, p, vp); 2473 if (ret) { 2474 /* 2475 * nfsrv_delegconflict() unlocks state 2476 * when it returns non-zero. 2477 */ 2478 if (ret == -1) 2479 goto tryagain; 2480 error = ret; 2481 goto out; 2482 } 2483 } 2484 stp = nstp; 2485 } 2486 } 2487 NFSUNLOCKSTATE(); 2488 if (haslock) { 2489 NFSLOCKV4ROOTMUTEX(); 2490 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2491 NFSUNLOCKV4ROOTMUTEX(); 2492 } 2493 2494 out: 2495 NFSEXITCODE2(error, nd); 2496 return (error); 2497 } 2498 2499 /* 2500 * Open control function to create/update open state for an open. 2501 */ 2502 APPLESTATIC int 2503 nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp, 2504 struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp, 2505 nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp, 2506 NFSPROC_T *p, u_quad_t filerev) 2507 { 2508 struct nfsstate *new_stp = *new_stpp; 2509 struct nfsstate *stp, *nstp; 2510 struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg; 2511 struct nfslockfile *lfp, *new_lfp; 2512 struct nfsclient *clp; 2513 int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1; 2514 int readonly = 0, cbret = 1, getfhret = 0; 2515 int gotstate = 0, len = 0; 2516 u_char *clidp = NULL; 2517 2518 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 2519 readonly = 1; 2520 /* 2521 * Check for restart conditions (client and server). 2522 * (Paranoia, should have been detected by nfsrv_opencheck().) 2523 * If an error does show up, return NFSERR_EXPIRED, since the 2524 * the seqid# has already been incremented. 2525 */ 2526 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2527 &new_stp->ls_stateid, 0); 2528 if (error) { 2529 printf("Nfsd: openctrl unexpected restart err=%d\n", 2530 error); 2531 error = NFSERR_EXPIRED; 2532 goto out; 2533 } 2534 2535 clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK); 2536 tryagain: 2537 new_lfp = malloc(sizeof (struct nfslockfile), 2538 M_NFSDLOCKFILE, M_WAITOK); 2539 new_open = malloc(sizeof (struct nfsstate), 2540 M_NFSDSTATE, M_WAITOK); 2541 new_deleg = malloc(sizeof (struct nfsstate), 2542 M_NFSDSTATE, M_WAITOK); 2543 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp, 2544 NULL, p); 2545 NFSLOCKSTATE(); 2546 /* 2547 * Get the client structure. Since the linked lists could be changed 2548 * by other nfsd processes if this process does a tsleep(), one of 2549 * two things must be done. 2550 * 1 - don't tsleep() 2551 * or 2552 * 2 - get the nfsv4_lock() { indicated by haslock == 1 } 2553 * before using the lists, since this lock stops the other 2554 * nfsd. This should only be used for rare cases, since it 2555 * essentially single threads the nfsd. 2556 * At this time, it is only done for cases where the stable 2557 * storage file must be written prior to completion of state 2558 * expiration. 2559 */ 2560 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 2561 (nfsquad_t)((u_quad_t)0), 0, nd, p); 2562 if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) && 2563 clp->lc_program) { 2564 /* 2565 * This happens on the first open for a client 2566 * that supports callbacks. 2567 */ 2568 NFSUNLOCKSTATE(); 2569 /* 2570 * Although nfsrv_docallback() will sleep, clp won't 2571 * go away, since they are only removed when the 2572 * nfsv4_lock() has blocked the nfsd threads. The 2573 * fields in clp can change, but having multiple 2574 * threads do this Null callback RPC should be 2575 * harmless. 2576 */ 2577 cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL, 2578 NULL, 0, NULL, NULL, NULL, p); 2579 NFSLOCKSTATE(); 2580 clp->lc_flags &= ~LCL_NEEDSCBNULL; 2581 if (!cbret) 2582 clp->lc_flags |= LCL_CALLBACKSON; 2583 } 2584 2585 /* 2586 * Look up the open owner. See if it needs confirmation and 2587 * check the seq#, as required. 2588 */ 2589 if (!error) 2590 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp); 2591 2592 if (error) { 2593 NFSUNLOCKSTATE(); 2594 printf("Nfsd: openctrl unexpected state err=%d\n", 2595 error); 2596 free(new_lfp, M_NFSDLOCKFILE); 2597 free(new_open, M_NFSDSTATE); 2598 free(new_deleg, M_NFSDSTATE); 2599 if (haslock) { 2600 NFSLOCKV4ROOTMUTEX(); 2601 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2602 NFSUNLOCKV4ROOTMUTEX(); 2603 } 2604 error = NFSERR_EXPIRED; 2605 goto out; 2606 } 2607 2608 if (new_stp->ls_flags & NFSLCK_RECLAIM) 2609 nfsrv_markstable(clp); 2610 2611 /* 2612 * Get the structure for the underlying file. 2613 */ 2614 if (getfhret) 2615 error = getfhret; 2616 else 2617 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, 2618 NULL, 0); 2619 if (new_lfp) 2620 free(new_lfp, M_NFSDLOCKFILE); 2621 if (error) { 2622 NFSUNLOCKSTATE(); 2623 printf("Nfsd openctrl unexpected getlockfile err=%d\n", 2624 error); 2625 free(new_open, M_NFSDSTATE); 2626 free(new_deleg, M_NFSDSTATE); 2627 if (haslock) { 2628 NFSLOCKV4ROOTMUTEX(); 2629 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2630 NFSUNLOCKV4ROOTMUTEX(); 2631 } 2632 goto out; 2633 } 2634 2635 /* 2636 * Search for a conflicting open/share. 2637 */ 2638 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2639 /* 2640 * For Delegate_Cur, search for the matching Delegation, 2641 * which indicates no conflict. 2642 * An old delegation should have been recovered by the 2643 * client doing a Claim_DELEGATE_Prev, so I won't let 2644 * it match and return NFSERR_EXPIRED. Should I let it 2645 * match? 2646 */ 2647 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2648 if (!(stp->ls_flags & NFSLCK_OLDDELEG) && 2649 (((nd->nd_flag & ND_NFSV41) != 0 && 2650 stateidp->seqid == 0) || 2651 stateidp->seqid == stp->ls_stateid.seqid) && 2652 !NFSBCMP(stateidp->other, stp->ls_stateid.other, 2653 NFSX_STATEIDOTHER)) 2654 break; 2655 } 2656 if (stp == LIST_END(&lfp->lf_deleg) || 2657 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) && 2658 (stp->ls_flags & NFSLCK_DELEGREAD))) { 2659 NFSUNLOCKSTATE(); 2660 printf("Nfsd openctrl unexpected expiry\n"); 2661 free(new_open, M_NFSDSTATE); 2662 free(new_deleg, M_NFSDSTATE); 2663 if (haslock) { 2664 NFSLOCKV4ROOTMUTEX(); 2665 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2666 NFSUNLOCKV4ROOTMUTEX(); 2667 } 2668 error = NFSERR_EXPIRED; 2669 goto out; 2670 } 2671 2672 /* 2673 * Don't issue a Delegation, since one already exists and 2674 * delay delegation timeout, as required. 2675 */ 2676 delegate = 0; 2677 nfsrv_delaydelegtimeout(stp); 2678 } 2679 2680 /* 2681 * Check for access/deny bit conflicts. I also check for the 2682 * same owner, since the client might not have bothered to check. 2683 * Also, note an open for the same file and owner, if found, 2684 * which is all we do here for Delegate_Cur, since conflict 2685 * checking is already done. 2686 */ 2687 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 2688 if (ownerstp && stp->ls_openowner == ownerstp) 2689 openstp = stp; 2690 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) { 2691 /* 2692 * If another client has the file open, the only 2693 * delegation that can be issued is a Read delegation 2694 * and only if it is a Read open with Deny none. 2695 */ 2696 if (clp != stp->ls_clp) { 2697 if ((stp->ls_flags & NFSLCK_SHAREBITS) == 2698 NFSLCK_READACCESS) 2699 writedeleg = 0; 2700 else 2701 delegate = 0; 2702 } 2703 if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) & 2704 ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))|| 2705 ((stp->ls_flags & NFSLCK_ACCESSBITS) & 2706 ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){ 2707 ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p); 2708 if (ret == 1) { 2709 /* 2710 * nfsrv_clientconflict() unlocks state 2711 * when it returns non-zero. 2712 */ 2713 free(new_open, M_NFSDSTATE); 2714 free(new_deleg, M_NFSDSTATE); 2715 openstp = NULL; 2716 goto tryagain; 2717 } 2718 if (ret == 2) 2719 error = NFSERR_PERM; 2720 else if (new_stp->ls_flags & NFSLCK_RECLAIM) 2721 error = NFSERR_RECLAIMCONFLICT; 2722 else 2723 error = NFSERR_SHAREDENIED; 2724 if (ret == 0) 2725 NFSUNLOCKSTATE(); 2726 if (haslock) { 2727 NFSLOCKV4ROOTMUTEX(); 2728 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2729 NFSUNLOCKV4ROOTMUTEX(); 2730 } 2731 free(new_open, M_NFSDSTATE); 2732 free(new_deleg, M_NFSDSTATE); 2733 printf("nfsd openctrl unexpected client cnfl\n"); 2734 goto out; 2735 } 2736 } 2737 } 2738 2739 /* 2740 * Check for a conflicting delegation. If one is found, call 2741 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2742 * been set yet, it will get the lock. Otherwise, it will recall 2743 * the delegation. Then, we try try again... 2744 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there 2745 * isn't a conflict.) 2746 * I currently believe the conflict algorithm to be: 2747 * For Open with Read Access and Deny None 2748 * - there is a conflict iff a different client has a write delegation 2749 * For Open with other Write Access or any Deny except None 2750 * - there is a conflict if a different client has any delegation 2751 * - there is a conflict if the same client has a read delegation 2752 * (The current consensus is that this last case should be 2753 * considered a conflict since the client with a read delegation 2754 * could have done an Open with ReadAccess and WriteDeny 2755 * locally and then not have checked for the WriteDeny.) 2756 */ 2757 if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) { 2758 stp = LIST_FIRST(&lfp->lf_deleg); 2759 while (stp != LIST_END(&lfp->lf_deleg)) { 2760 nstp = LIST_NEXT(stp, ls_file); 2761 if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD)) 2762 writedeleg = 0; 2763 else 2764 delegate = 0; 2765 if ((readonly && stp->ls_clp != clp && 2766 (stp->ls_flags & NFSLCK_DELEGWRITE)) || 2767 (!readonly && (stp->ls_clp != clp || 2768 (stp->ls_flags & NFSLCK_DELEGREAD)))) { 2769 if (new_stp->ls_flags & NFSLCK_RECLAIM) { 2770 delegate = 2; 2771 } else { 2772 ret = nfsrv_delegconflict(stp, &haslock, p, vp); 2773 if (ret) { 2774 /* 2775 * nfsrv_delegconflict() unlocks state 2776 * when it returns non-zero. 2777 */ 2778 printf("Nfsd openctrl unexpected deleg cnfl\n"); 2779 free(new_open, M_NFSDSTATE); 2780 free(new_deleg, M_NFSDSTATE); 2781 if (ret == -1) { 2782 openstp = NULL; 2783 goto tryagain; 2784 } 2785 error = ret; 2786 goto out; 2787 } 2788 } 2789 } 2790 stp = nstp; 2791 } 2792 } 2793 2794 /* 2795 * We only get here if there was no open that conflicted. 2796 * If an open for the owner exists, or in the access/deny bits. 2797 * Otherwise it is a new open. If the open_owner hasn't been 2798 * confirmed, replace the open with the new one needing confirmation, 2799 * otherwise add the open. 2800 */ 2801 if (new_stp->ls_flags & NFSLCK_DELEGPREV) { 2802 /* 2803 * Handle NFSLCK_DELEGPREV by searching the old delegations for 2804 * a match. If found, just move the old delegation to the current 2805 * delegation list and issue open. If not found, return 2806 * NFSERR_EXPIRED. 2807 */ 2808 LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) { 2809 if (stp->ls_lfp == lfp) { 2810 /* Found it */ 2811 if (stp->ls_clp != clp) 2812 panic("olddeleg clp"); 2813 LIST_REMOVE(stp, ls_list); 2814 LIST_REMOVE(stp, ls_hash); 2815 stp->ls_flags &= ~NFSLCK_OLDDELEG; 2816 stp->ls_stateid.seqid = delegstateidp->seqid = 1; 2817 stp->ls_stateid.other[0] = delegstateidp->other[0] = 2818 clp->lc_clientid.lval[0]; 2819 stp->ls_stateid.other[1] = delegstateidp->other[1] = 2820 clp->lc_clientid.lval[1]; 2821 stp->ls_stateid.other[2] = delegstateidp->other[2] = 2822 nfsrv_nextstateindex(clp); 2823 stp->ls_compref = nd->nd_compref; 2824 LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list); 2825 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2826 stp->ls_stateid), stp, ls_hash); 2827 if (stp->ls_flags & NFSLCK_DELEGWRITE) 2828 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2829 else 2830 *rflagsp |= NFSV4OPEN_READDELEGATE; 2831 clp->lc_delegtime = NFSD_MONOSEC + 2832 nfsrv_lease + NFSRV_LEASEDELTA; 2833 2834 /* 2835 * Now, do the associated open. 2836 */ 2837 new_open->ls_stateid.seqid = 1; 2838 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2839 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2840 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2841 new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)| 2842 NFSLCK_OPEN; 2843 if (stp->ls_flags & NFSLCK_DELEGWRITE) 2844 new_open->ls_flags |= (NFSLCK_READACCESS | 2845 NFSLCK_WRITEACCESS); 2846 else 2847 new_open->ls_flags |= NFSLCK_READACCESS; 2848 new_open->ls_uid = new_stp->ls_uid; 2849 new_open->ls_lfp = lfp; 2850 new_open->ls_clp = clp; 2851 LIST_INIT(&new_open->ls_open); 2852 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2853 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2854 new_open, ls_hash); 2855 /* 2856 * and handle the open owner 2857 */ 2858 if (ownerstp) { 2859 new_open->ls_openowner = ownerstp; 2860 LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list); 2861 } else { 2862 new_open->ls_openowner = new_stp; 2863 new_stp->ls_flags = 0; 2864 nfsrvd_refcache(new_stp->ls_op); 2865 new_stp->ls_noopens = 0; 2866 LIST_INIT(&new_stp->ls_open); 2867 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 2868 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 2869 *new_stpp = NULL; 2870 nfsstatsv1.srvopenowners++; 2871 nfsrv_openpluslock++; 2872 } 2873 openstp = new_open; 2874 new_open = NULL; 2875 nfsstatsv1.srvopens++; 2876 nfsrv_openpluslock++; 2877 break; 2878 } 2879 } 2880 if (stp == LIST_END(&clp->lc_olddeleg)) 2881 error = NFSERR_EXPIRED; 2882 } else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { 2883 /* 2884 * Scan to see that no delegation for this client and file 2885 * doesn't already exist. 2886 * There also shouldn't yet be an Open for this file and 2887 * openowner. 2888 */ 2889 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2890 if (stp->ls_clp == clp) 2891 break; 2892 } 2893 if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) { 2894 /* 2895 * This is the Claim_Previous case with a delegation 2896 * type != Delegate_None. 2897 */ 2898 /* 2899 * First, add the delegation. (Although we must issue the 2900 * delegation, we can also ask for an immediate return.) 2901 */ 2902 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 2903 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] = 2904 clp->lc_clientid.lval[0]; 2905 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] = 2906 clp->lc_clientid.lval[1]; 2907 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] = 2908 nfsrv_nextstateindex(clp); 2909 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) { 2910 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 2911 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 2912 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2913 nfsrv_writedelegcnt++; 2914 } else { 2915 new_deleg->ls_flags = (NFSLCK_DELEGREAD | 2916 NFSLCK_READACCESS); 2917 *rflagsp |= NFSV4OPEN_READDELEGATE; 2918 } 2919 new_deleg->ls_uid = new_stp->ls_uid; 2920 new_deleg->ls_lfp = lfp; 2921 new_deleg->ls_clp = clp; 2922 new_deleg->ls_filerev = filerev; 2923 new_deleg->ls_compref = nd->nd_compref; 2924 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 2925 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2926 new_deleg->ls_stateid), new_deleg, ls_hash); 2927 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 2928 new_deleg = NULL; 2929 if (delegate == 2 || nfsrv_issuedelegs == 0 || 2930 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 2931 LCL_CALLBACKSON || 2932 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) || 2933 !NFSVNO_DELEGOK(vp)) 2934 *rflagsp |= NFSV4OPEN_RECALL; 2935 nfsstatsv1.srvdelegates++; 2936 nfsrv_openpluslock++; 2937 nfsrv_delegatecnt++; 2938 2939 /* 2940 * Now, do the associated open. 2941 */ 2942 new_open->ls_stateid.seqid = 1; 2943 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2944 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2945 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2946 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) | 2947 NFSLCK_OPEN; 2948 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) 2949 new_open->ls_flags |= (NFSLCK_READACCESS | 2950 NFSLCK_WRITEACCESS); 2951 else 2952 new_open->ls_flags |= NFSLCK_READACCESS; 2953 new_open->ls_uid = new_stp->ls_uid; 2954 new_open->ls_lfp = lfp; 2955 new_open->ls_clp = clp; 2956 LIST_INIT(&new_open->ls_open); 2957 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2958 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2959 new_open, ls_hash); 2960 /* 2961 * and handle the open owner 2962 */ 2963 if (ownerstp) { 2964 new_open->ls_openowner = ownerstp; 2965 LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); 2966 } else { 2967 new_open->ls_openowner = new_stp; 2968 new_stp->ls_flags = 0; 2969 nfsrvd_refcache(new_stp->ls_op); 2970 new_stp->ls_noopens = 0; 2971 LIST_INIT(&new_stp->ls_open); 2972 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 2973 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 2974 *new_stpp = NULL; 2975 nfsstatsv1.srvopenowners++; 2976 nfsrv_openpluslock++; 2977 } 2978 openstp = new_open; 2979 new_open = NULL; 2980 nfsstatsv1.srvopens++; 2981 nfsrv_openpluslock++; 2982 } else { 2983 error = NFSERR_RECLAIMCONFLICT; 2984 } 2985 } else if (ownerstp) { 2986 if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) { 2987 /* Replace the open */ 2988 if (ownerstp->ls_op) 2989 nfsrvd_derefcache(ownerstp->ls_op); 2990 ownerstp->ls_op = new_stp->ls_op; 2991 nfsrvd_refcache(ownerstp->ls_op); 2992 ownerstp->ls_seq = new_stp->ls_seq; 2993 *rflagsp |= NFSV4OPEN_RESULTCONFIRM; 2994 stp = LIST_FIRST(&ownerstp->ls_open); 2995 stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) | 2996 NFSLCK_OPEN; 2997 stp->ls_stateid.seqid = 1; 2998 stp->ls_uid = new_stp->ls_uid; 2999 if (lfp != stp->ls_lfp) { 3000 LIST_REMOVE(stp, ls_file); 3001 LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file); 3002 stp->ls_lfp = lfp; 3003 } 3004 openstp = stp; 3005 } else if (openstp) { 3006 openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS); 3007 openstp->ls_stateid.seqid++; 3008 if ((nd->nd_flag & ND_NFSV41) != 0 && 3009 openstp->ls_stateid.seqid == 0) 3010 openstp->ls_stateid.seqid = 1; 3011 3012 /* 3013 * This is where we can choose to issue a delegation. 3014 */ 3015 if (delegate == 0 || writedeleg == 0 || 3016 NFSVNO_EXRDONLY(exp) || (readonly != 0 && 3017 nfsrv_writedelegifpos == 0) || 3018 !NFSVNO_DELEGOK(vp) || 3019 (new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 || 3020 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 3021 LCL_CALLBACKSON) 3022 *rflagsp |= NFSV4OPEN_WDCONTENTION; 3023 else if (nfsrv_issuedelegs == 0 || 3024 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt)) 3025 *rflagsp |= NFSV4OPEN_WDRESOURCE; 3026 else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0) 3027 *rflagsp |= NFSV4OPEN_WDNOTWANTED; 3028 else { 3029 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 3030 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] 3031 = clp->lc_clientid.lval[0]; 3032 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] 3033 = clp->lc_clientid.lval[1]; 3034 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] 3035 = nfsrv_nextstateindex(clp); 3036 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 3037 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 3038 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3039 new_deleg->ls_uid = new_stp->ls_uid; 3040 new_deleg->ls_lfp = lfp; 3041 new_deleg->ls_clp = clp; 3042 new_deleg->ls_filerev = filerev; 3043 new_deleg->ls_compref = nd->nd_compref; 3044 nfsrv_writedelegcnt++; 3045 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 3046 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3047 new_deleg->ls_stateid), new_deleg, ls_hash); 3048 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 3049 new_deleg = NULL; 3050 nfsstatsv1.srvdelegates++; 3051 nfsrv_openpluslock++; 3052 nfsrv_delegatecnt++; 3053 } 3054 } else { 3055 new_open->ls_stateid.seqid = 1; 3056 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 3057 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 3058 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 3059 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)| 3060 NFSLCK_OPEN; 3061 new_open->ls_uid = new_stp->ls_uid; 3062 new_open->ls_openowner = ownerstp; 3063 new_open->ls_lfp = lfp; 3064 new_open->ls_clp = clp; 3065 LIST_INIT(&new_open->ls_open); 3066 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 3067 LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); 3068 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 3069 new_open, ls_hash); 3070 openstp = new_open; 3071 new_open = NULL; 3072 nfsstatsv1.srvopens++; 3073 nfsrv_openpluslock++; 3074 3075 /* 3076 * This is where we can choose to issue a delegation. 3077 */ 3078 if (delegate == 0 || (writedeleg == 0 && readonly == 0) || 3079 !NFSVNO_DELEGOK(vp) || 3080 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 3081 LCL_CALLBACKSON) 3082 *rflagsp |= NFSV4OPEN_WDCONTENTION; 3083 else if (nfsrv_issuedelegs == 0 || 3084 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt)) 3085 *rflagsp |= NFSV4OPEN_WDRESOURCE; 3086 else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0) 3087 *rflagsp |= NFSV4OPEN_WDNOTWANTED; 3088 else { 3089 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 3090 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] 3091 = clp->lc_clientid.lval[0]; 3092 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] 3093 = clp->lc_clientid.lval[1]; 3094 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] 3095 = nfsrv_nextstateindex(clp); 3096 if (writedeleg && !NFSVNO_EXRDONLY(exp) && 3097 (nfsrv_writedelegifpos || !readonly) && 3098 (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) { 3099 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 3100 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 3101 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3102 nfsrv_writedelegcnt++; 3103 } else { 3104 new_deleg->ls_flags = (NFSLCK_DELEGREAD | 3105 NFSLCK_READACCESS); 3106 *rflagsp |= NFSV4OPEN_READDELEGATE; 3107 } 3108 new_deleg->ls_uid = new_stp->ls_uid; 3109 new_deleg->ls_lfp = lfp; 3110 new_deleg->ls_clp = clp; 3111 new_deleg->ls_filerev = filerev; 3112 new_deleg->ls_compref = nd->nd_compref; 3113 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 3114 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3115 new_deleg->ls_stateid), new_deleg, ls_hash); 3116 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 3117 new_deleg = NULL; 3118 nfsstatsv1.srvdelegates++; 3119 nfsrv_openpluslock++; 3120 nfsrv_delegatecnt++; 3121 } 3122 } 3123 } else { 3124 /* 3125 * New owner case. Start the open_owner sequence with a 3126 * Needs confirmation (unless a reclaim) and hang the 3127 * new open off it. 3128 */ 3129 new_open->ls_stateid.seqid = 1; 3130 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 3131 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 3132 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 3133 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) | 3134 NFSLCK_OPEN; 3135 new_open->ls_uid = new_stp->ls_uid; 3136 LIST_INIT(&new_open->ls_open); 3137 new_open->ls_openowner = new_stp; 3138 new_open->ls_lfp = lfp; 3139 new_open->ls_clp = clp; 3140 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 3141 if (new_stp->ls_flags & NFSLCK_RECLAIM) { 3142 new_stp->ls_flags = 0; 3143 } else if ((nd->nd_flag & ND_NFSV41) != 0) { 3144 /* NFSv4.1 never needs confirmation. */ 3145 new_stp->ls_flags = 0; 3146 3147 /* 3148 * This is where we can choose to issue a delegation. 3149 */ 3150 if (delegate && nfsrv_issuedelegs && 3151 (writedeleg || readonly) && 3152 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) == 3153 LCL_CALLBACKSON && 3154 !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) && 3155 NFSVNO_DELEGOK(vp) && 3156 ((nd->nd_flag & ND_NFSV41) == 0 || 3157 (new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) { 3158 new_deleg->ls_stateid.seqid = 3159 delegstateidp->seqid = 1; 3160 new_deleg->ls_stateid.other[0] = 3161 delegstateidp->other[0] 3162 = clp->lc_clientid.lval[0]; 3163 new_deleg->ls_stateid.other[1] = 3164 delegstateidp->other[1] 3165 = clp->lc_clientid.lval[1]; 3166 new_deleg->ls_stateid.other[2] = 3167 delegstateidp->other[2] 3168 = nfsrv_nextstateindex(clp); 3169 if (writedeleg && !NFSVNO_EXRDONLY(exp) && 3170 (nfsrv_writedelegifpos || !readonly) && 3171 ((nd->nd_flag & ND_NFSV41) == 0 || 3172 (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 3173 0)) { 3174 new_deleg->ls_flags = 3175 (NFSLCK_DELEGWRITE | 3176 NFSLCK_READACCESS | 3177 NFSLCK_WRITEACCESS); 3178 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3179 nfsrv_writedelegcnt++; 3180 } else { 3181 new_deleg->ls_flags = 3182 (NFSLCK_DELEGREAD | 3183 NFSLCK_READACCESS); 3184 *rflagsp |= NFSV4OPEN_READDELEGATE; 3185 } 3186 new_deleg->ls_uid = new_stp->ls_uid; 3187 new_deleg->ls_lfp = lfp; 3188 new_deleg->ls_clp = clp; 3189 new_deleg->ls_filerev = filerev; 3190 new_deleg->ls_compref = nd->nd_compref; 3191 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, 3192 ls_file); 3193 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3194 new_deleg->ls_stateid), new_deleg, ls_hash); 3195 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, 3196 ls_list); 3197 new_deleg = NULL; 3198 nfsstatsv1.srvdelegates++; 3199 nfsrv_openpluslock++; 3200 nfsrv_delegatecnt++; 3201 } 3202 /* 3203 * Since NFSv4.1 never does an OpenConfirm, the first 3204 * open state will be acquired here. 3205 */ 3206 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { 3207 clp->lc_flags |= LCL_STAMPEDSTABLE; 3208 len = clp->lc_idlen; 3209 NFSBCOPY(clp->lc_id, clidp, len); 3210 gotstate = 1; 3211 } 3212 } else { 3213 *rflagsp |= NFSV4OPEN_RESULTCONFIRM; 3214 new_stp->ls_flags = NFSLCK_NEEDSCONFIRM; 3215 } 3216 nfsrvd_refcache(new_stp->ls_op); 3217 new_stp->ls_noopens = 0; 3218 LIST_INIT(&new_stp->ls_open); 3219 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 3220 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 3221 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 3222 new_open, ls_hash); 3223 openstp = new_open; 3224 new_open = NULL; 3225 *new_stpp = NULL; 3226 nfsstatsv1.srvopens++; 3227 nfsrv_openpluslock++; 3228 nfsstatsv1.srvopenowners++; 3229 nfsrv_openpluslock++; 3230 } 3231 if (!error) { 3232 stateidp->seqid = openstp->ls_stateid.seqid; 3233 stateidp->other[0] = openstp->ls_stateid.other[0]; 3234 stateidp->other[1] = openstp->ls_stateid.other[1]; 3235 stateidp->other[2] = openstp->ls_stateid.other[2]; 3236 } 3237 NFSUNLOCKSTATE(); 3238 if (haslock) { 3239 NFSLOCKV4ROOTMUTEX(); 3240 nfsv4_unlock(&nfsv4rootfs_lock, 1); 3241 NFSUNLOCKV4ROOTMUTEX(); 3242 } 3243 if (new_open) 3244 free(new_open, M_NFSDSTATE); 3245 if (new_deleg) 3246 free(new_deleg, M_NFSDSTATE); 3247 3248 /* 3249 * If the NFSv4.1 client just acquired its first open, write a timestamp 3250 * to the stable storage file. 3251 */ 3252 if (gotstate != 0) { 3253 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p); 3254 nfsrv_backupstable(); 3255 } 3256 3257 out: 3258 free(clidp, M_TEMP); 3259 NFSEXITCODE2(error, nd); 3260 return (error); 3261 } 3262 3263 /* 3264 * Open update. Does the confirm, downgrade and close. 3265 */ 3266 APPLESTATIC int 3267 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid, 3268 nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p) 3269 { 3270 struct nfsstate *stp; 3271 struct nfsclient *clp; 3272 struct nfslockfile *lfp; 3273 u_int32_t bits; 3274 int error = 0, gotstate = 0, len = 0; 3275 u_char *clidp = NULL; 3276 3277 /* 3278 * Check for restart conditions (client and server). 3279 */ 3280 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 3281 &new_stp->ls_stateid, 0); 3282 if (error) 3283 goto out; 3284 3285 clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK); 3286 NFSLOCKSTATE(); 3287 /* 3288 * Get the open structure via clientid and stateid. 3289 */ 3290 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3291 (nfsquad_t)((u_quad_t)0), 0, nd, p); 3292 if (!error) 3293 error = nfsrv_getstate(clp, &new_stp->ls_stateid, 3294 new_stp->ls_flags, &stp); 3295 3296 /* 3297 * Sanity check the open. 3298 */ 3299 if (!error && (!(stp->ls_flags & NFSLCK_OPEN) || 3300 (!(new_stp->ls_flags & NFSLCK_CONFIRM) && 3301 (stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) || 3302 ((new_stp->ls_flags & NFSLCK_CONFIRM) && 3303 (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))))) 3304 error = NFSERR_BADSTATEID; 3305 3306 if (!error) 3307 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 3308 stp->ls_openowner, new_stp->ls_op); 3309 if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid && 3310 (((nd->nd_flag & ND_NFSV41) == 0 && 3311 !(new_stp->ls_flags & NFSLCK_CONFIRM)) || 3312 ((nd->nd_flag & ND_NFSV41) != 0 && 3313 new_stp->ls_stateid.seqid != 0))) 3314 error = NFSERR_OLDSTATEID; 3315 if (!error && vnode_vtype(vp) != VREG) { 3316 if (vnode_vtype(vp) == VDIR) 3317 error = NFSERR_ISDIR; 3318 else 3319 error = NFSERR_INVAL; 3320 } 3321 3322 if (error) { 3323 /* 3324 * If a client tries to confirm an Open with a bad 3325 * seqid# and there are no byte range locks or other Opens 3326 * on the openowner, just throw it away, so the next use of the 3327 * openowner will start a fresh seq#. 3328 */ 3329 if (error == NFSERR_BADSEQID && 3330 (new_stp->ls_flags & NFSLCK_CONFIRM) && 3331 nfsrv_nootherstate(stp)) 3332 nfsrv_freeopenowner(stp->ls_openowner, 0, p); 3333 NFSUNLOCKSTATE(); 3334 goto out; 3335 } 3336 3337 /* 3338 * Set the return stateid. 3339 */ 3340 stateidp->seqid = stp->ls_stateid.seqid + 1; 3341 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0) 3342 stateidp->seqid = 1; 3343 stateidp->other[0] = stp->ls_stateid.other[0]; 3344 stateidp->other[1] = stp->ls_stateid.other[1]; 3345 stateidp->other[2] = stp->ls_stateid.other[2]; 3346 /* 3347 * Now, handle the three cases. 3348 */ 3349 if (new_stp->ls_flags & NFSLCK_CONFIRM) { 3350 /* 3351 * If the open doesn't need confirmation, it seems to me that 3352 * there is a client error, but I'll just log it and keep going? 3353 */ 3354 if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) 3355 printf("Nfsv4d: stray open confirm\n"); 3356 stp->ls_openowner->ls_flags = 0; 3357 stp->ls_stateid.seqid++; 3358 if ((nd->nd_flag & ND_NFSV41) != 0 && 3359 stp->ls_stateid.seqid == 0) 3360 stp->ls_stateid.seqid = 1; 3361 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { 3362 clp->lc_flags |= LCL_STAMPEDSTABLE; 3363 len = clp->lc_idlen; 3364 NFSBCOPY(clp->lc_id, clidp, len); 3365 gotstate = 1; 3366 } 3367 NFSUNLOCKSTATE(); 3368 } else if (new_stp->ls_flags & NFSLCK_CLOSE) { 3369 lfp = stp->ls_lfp; 3370 if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) { 3371 /* Get the lf lock */ 3372 nfsrv_locklf(lfp); 3373 NFSUNLOCKSTATE(); 3374 ASSERT_VOP_ELOCKED(vp, "nfsrv_openupdate"); 3375 NFSVOPUNLOCK(vp, 0); 3376 if (nfsrv_freeopen(stp, vp, 1, p) == 0) { 3377 NFSLOCKSTATE(); 3378 nfsrv_unlocklf(lfp); 3379 NFSUNLOCKSTATE(); 3380 } 3381 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 3382 } else { 3383 (void) nfsrv_freeopen(stp, NULL, 0, p); 3384 NFSUNLOCKSTATE(); 3385 } 3386 } else { 3387 /* 3388 * Update the share bits, making sure that the new set are a 3389 * subset of the old ones. 3390 */ 3391 bits = (new_stp->ls_flags & NFSLCK_SHAREBITS); 3392 if (~(stp->ls_flags) & bits) { 3393 NFSUNLOCKSTATE(); 3394 error = NFSERR_INVAL; 3395 goto out; 3396 } 3397 stp->ls_flags = (bits | NFSLCK_OPEN); 3398 stp->ls_stateid.seqid++; 3399 if ((nd->nd_flag & ND_NFSV41) != 0 && 3400 stp->ls_stateid.seqid == 0) 3401 stp->ls_stateid.seqid = 1; 3402 NFSUNLOCKSTATE(); 3403 } 3404 3405 /* 3406 * If the client just confirmed its first open, write a timestamp 3407 * to the stable storage file. 3408 */ 3409 if (gotstate != 0) { 3410 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p); 3411 nfsrv_backupstable(); 3412 } 3413 3414 out: 3415 free(clidp, M_TEMP); 3416 NFSEXITCODE2(error, nd); 3417 return (error); 3418 } 3419 3420 /* 3421 * Delegation update. Does the purge and return. 3422 */ 3423 APPLESTATIC int 3424 nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid, 3425 nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred, 3426 NFSPROC_T *p) 3427 { 3428 struct nfsstate *stp; 3429 struct nfsclient *clp; 3430 int error = 0; 3431 fhandle_t fh; 3432 3433 /* 3434 * Do a sanity check against the file handle for DelegReturn. 3435 */ 3436 if (vp) { 3437 error = nfsvno_getfh(vp, &fh, p); 3438 if (error) 3439 goto out; 3440 } 3441 /* 3442 * Check for restart conditions (client and server). 3443 */ 3444 if (op == NFSV4OP_DELEGRETURN) 3445 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN, 3446 stateidp, 0); 3447 else 3448 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE, 3449 stateidp, 0); 3450 3451 NFSLOCKSTATE(); 3452 /* 3453 * Get the open structure via clientid and stateid. 3454 */ 3455 if (!error) 3456 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3457 (nfsquad_t)((u_quad_t)0), 0, nd, p); 3458 if (error) { 3459 if (error == NFSERR_CBPATHDOWN) 3460 error = 0; 3461 if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN) 3462 error = NFSERR_STALESTATEID; 3463 } 3464 if (!error && op == NFSV4OP_DELEGRETURN) { 3465 error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp); 3466 if (!error && stp->ls_stateid.seqid != stateidp->seqid && 3467 ((nd->nd_flag & ND_NFSV41) == 0 || stateidp->seqid != 0)) 3468 error = NFSERR_OLDSTATEID; 3469 } 3470 /* 3471 * NFSERR_EXPIRED means that the state has gone away, 3472 * so Delegations have been purged. Just return ok. 3473 */ 3474 if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) { 3475 NFSUNLOCKSTATE(); 3476 error = 0; 3477 goto out; 3478 } 3479 if (error) { 3480 NFSUNLOCKSTATE(); 3481 goto out; 3482 } 3483 3484 if (op == NFSV4OP_DELEGRETURN) { 3485 if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh, 3486 sizeof (fhandle_t))) { 3487 NFSUNLOCKSTATE(); 3488 error = NFSERR_BADSTATEID; 3489 goto out; 3490 } 3491 nfsrv_freedeleg(stp); 3492 } else { 3493 nfsrv_freedeleglist(&clp->lc_olddeleg); 3494 } 3495 NFSUNLOCKSTATE(); 3496 error = 0; 3497 3498 out: 3499 NFSEXITCODE(error); 3500 return (error); 3501 } 3502 3503 /* 3504 * Release lock owner. 3505 */ 3506 APPLESTATIC int 3507 nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid, 3508 NFSPROC_T *p) 3509 { 3510 struct nfsstate *stp, *nstp, *openstp, *ownstp; 3511 struct nfsclient *clp; 3512 int error = 0; 3513 3514 /* 3515 * Check for restart conditions (client and server). 3516 */ 3517 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 3518 &new_stp->ls_stateid, 0); 3519 if (error) 3520 goto out; 3521 3522 NFSLOCKSTATE(); 3523 /* 3524 * Get the lock owner by name. 3525 */ 3526 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3527 (nfsquad_t)((u_quad_t)0), 0, NULL, p); 3528 if (error) { 3529 NFSUNLOCKSTATE(); 3530 goto out; 3531 } 3532 LIST_FOREACH(ownstp, &clp->lc_open, ls_list) { 3533 LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) { 3534 stp = LIST_FIRST(&openstp->ls_open); 3535 while (stp != LIST_END(&openstp->ls_open)) { 3536 nstp = LIST_NEXT(stp, ls_list); 3537 /* 3538 * If the owner matches, check for locks and 3539 * then free or return an error. 3540 */ 3541 if (stp->ls_ownerlen == new_stp->ls_ownerlen && 3542 !NFSBCMP(stp->ls_owner, new_stp->ls_owner, 3543 stp->ls_ownerlen)){ 3544 if (LIST_EMPTY(&stp->ls_lock)) { 3545 nfsrv_freelockowner(stp, NULL, 0, p); 3546 } else { 3547 NFSUNLOCKSTATE(); 3548 error = NFSERR_LOCKSHELD; 3549 goto out; 3550 } 3551 } 3552 stp = nstp; 3553 } 3554 } 3555 } 3556 NFSUNLOCKSTATE(); 3557 3558 out: 3559 NFSEXITCODE(error); 3560 return (error); 3561 } 3562 3563 /* 3564 * Get the file handle for a lock structure. 3565 */ 3566 static int 3567 nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile *new_lfp, 3568 fhandle_t *nfhp, NFSPROC_T *p) 3569 { 3570 fhandle_t *fhp = NULL; 3571 int error; 3572 3573 /* 3574 * For lock, use the new nfslock structure, otherwise just 3575 * a fhandle_t on the stack. 3576 */ 3577 if (flags & NFSLCK_OPEN) { 3578 KASSERT(new_lfp != NULL, ("nfsrv_getlockfh: new_lfp NULL")); 3579 fhp = &new_lfp->lf_fh; 3580 } else if (nfhp) { 3581 fhp = nfhp; 3582 } else { 3583 panic("nfsrv_getlockfh"); 3584 } 3585 error = nfsvno_getfh(vp, fhp, p); 3586 NFSEXITCODE(error); 3587 return (error); 3588 } 3589 3590 /* 3591 * Get an nfs lock structure. Allocate one, as required, and return a 3592 * pointer to it. 3593 * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock. 3594 */ 3595 static int 3596 nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, 3597 struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit) 3598 { 3599 struct nfslockfile *lfp; 3600 fhandle_t *fhp = NULL, *tfhp; 3601 struct nfslockhashhead *hp; 3602 struct nfslockfile *new_lfp = NULL; 3603 3604 /* 3605 * For lock, use the new nfslock structure, otherwise just 3606 * a fhandle_t on the stack. 3607 */ 3608 if (flags & NFSLCK_OPEN) { 3609 new_lfp = *new_lfpp; 3610 fhp = &new_lfp->lf_fh; 3611 } else if (nfhp) { 3612 fhp = nfhp; 3613 } else { 3614 panic("nfsrv_getlockfile"); 3615 } 3616 3617 hp = NFSLOCKHASH(fhp); 3618 LIST_FOREACH(lfp, hp, lf_hash) { 3619 tfhp = &lfp->lf_fh; 3620 if (NFSVNO_CMPFH(fhp, tfhp)) { 3621 if (lockit) 3622 nfsrv_locklf(lfp); 3623 *lfpp = lfp; 3624 return (0); 3625 } 3626 } 3627 if (!(flags & NFSLCK_OPEN)) 3628 return (-1); 3629 3630 /* 3631 * No match, so chain the new one into the list. 3632 */ 3633 LIST_INIT(&new_lfp->lf_open); 3634 LIST_INIT(&new_lfp->lf_lock); 3635 LIST_INIT(&new_lfp->lf_deleg); 3636 LIST_INIT(&new_lfp->lf_locallock); 3637 LIST_INIT(&new_lfp->lf_rollback); 3638 new_lfp->lf_locallock_lck.nfslock_usecnt = 0; 3639 new_lfp->lf_locallock_lck.nfslock_lock = 0; 3640 new_lfp->lf_usecount = 0; 3641 LIST_INSERT_HEAD(hp, new_lfp, lf_hash); 3642 *lfpp = new_lfp; 3643 *new_lfpp = NULL; 3644 return (0); 3645 } 3646 3647 /* 3648 * This function adds a nfslock lock structure to the list for the associated 3649 * nfsstate and nfslockfile structures. It will be inserted after the 3650 * entry pointed at by insert_lop. 3651 */ 3652 static void 3653 nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop, 3654 struct nfsstate *stp, struct nfslockfile *lfp) 3655 { 3656 struct nfslock *lop, *nlop; 3657 3658 new_lop->lo_stp = stp; 3659 new_lop->lo_lfp = lfp; 3660 3661 if (stp != NULL) { 3662 /* Insert in increasing lo_first order */ 3663 lop = LIST_FIRST(&lfp->lf_lock); 3664 if (lop == LIST_END(&lfp->lf_lock) || 3665 new_lop->lo_first <= lop->lo_first) { 3666 LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile); 3667 } else { 3668 nlop = LIST_NEXT(lop, lo_lckfile); 3669 while (nlop != LIST_END(&lfp->lf_lock) && 3670 nlop->lo_first < new_lop->lo_first) { 3671 lop = nlop; 3672 nlop = LIST_NEXT(lop, lo_lckfile); 3673 } 3674 LIST_INSERT_AFTER(lop, new_lop, lo_lckfile); 3675 } 3676 } else { 3677 new_lop->lo_lckfile.le_prev = NULL; /* list not used */ 3678 } 3679 3680 /* 3681 * Insert after insert_lop, which is overloaded as stp or lfp for 3682 * an empty list. 3683 */ 3684 if (stp == NULL && (struct nfslockfile *)insert_lop == lfp) 3685 LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner); 3686 else if ((struct nfsstate *)insert_lop == stp) 3687 LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner); 3688 else 3689 LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner); 3690 if (stp != NULL) { 3691 nfsstatsv1.srvlocks++; 3692 nfsrv_openpluslock++; 3693 } 3694 } 3695 3696 /* 3697 * This function updates the locking for a lock owner and given file. It 3698 * maintains a list of lock ranges ordered on increasing file offset that 3699 * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style). 3700 * It always adds new_lop to the list and sometimes uses the one pointed 3701 * at by other_lopp. 3702 */ 3703 static void 3704 nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, 3705 struct nfslock **other_lopp, struct nfslockfile *lfp) 3706 { 3707 struct nfslock *new_lop = *new_lopp; 3708 struct nfslock *lop, *tlop, *ilop; 3709 struct nfslock *other_lop = *other_lopp; 3710 int unlock = 0, myfile = 0; 3711 u_int64_t tmp; 3712 3713 /* 3714 * Work down the list until the lock is merged. 3715 */ 3716 if (new_lop->lo_flags & NFSLCK_UNLOCK) 3717 unlock = 1; 3718 if (stp != NULL) { 3719 ilop = (struct nfslock *)stp; 3720 lop = LIST_FIRST(&stp->ls_lock); 3721 } else { 3722 ilop = (struct nfslock *)lfp; 3723 lop = LIST_FIRST(&lfp->lf_locallock); 3724 } 3725 while (lop != NULL) { 3726 /* 3727 * Only check locks for this file that aren't before the start of 3728 * new lock's range. 3729 */ 3730 if (lop->lo_lfp == lfp) { 3731 myfile = 1; 3732 if (lop->lo_end >= new_lop->lo_first) { 3733 if (new_lop->lo_end < lop->lo_first) { 3734 /* 3735 * If the new lock ends before the start of the 3736 * current lock's range, no merge, just insert 3737 * the new lock. 3738 */ 3739 break; 3740 } 3741 if (new_lop->lo_flags == lop->lo_flags || 3742 (new_lop->lo_first <= lop->lo_first && 3743 new_lop->lo_end >= lop->lo_end)) { 3744 /* 3745 * This lock can be absorbed by the new lock/unlock. 3746 * This happens when it covers the entire range 3747 * of the old lock or is contiguous 3748 * with the old lock and is of the same type or an 3749 * unlock. 3750 */ 3751 if (lop->lo_first < new_lop->lo_first) 3752 new_lop->lo_first = lop->lo_first; 3753 if (lop->lo_end > new_lop->lo_end) 3754 new_lop->lo_end = lop->lo_end; 3755 tlop = lop; 3756 lop = LIST_NEXT(lop, lo_lckowner); 3757 nfsrv_freenfslock(tlop); 3758 continue; 3759 } 3760 3761 /* 3762 * All these cases are for contiguous locks that are not the 3763 * same type, so they can't be merged. 3764 */ 3765 if (new_lop->lo_first <= lop->lo_first) { 3766 /* 3767 * This case is where the new lock overlaps with the 3768 * first part of the old lock. Move the start of the 3769 * old lock to just past the end of the new lock. The 3770 * new lock will be inserted in front of the old, since 3771 * ilop hasn't been updated. (We are done now.) 3772 */ 3773 lop->lo_first = new_lop->lo_end; 3774 break; 3775 } 3776 if (new_lop->lo_end >= lop->lo_end) { 3777 /* 3778 * This case is where the new lock overlaps with the 3779 * end of the old lock's range. Move the old lock's 3780 * end to just before the new lock's first and insert 3781 * the new lock after the old lock. 3782 * Might not be done yet, since the new lock could 3783 * overlap further locks with higher ranges. 3784 */ 3785 lop->lo_end = new_lop->lo_first; 3786 ilop = lop; 3787 lop = LIST_NEXT(lop, lo_lckowner); 3788 continue; 3789 } 3790 /* 3791 * The final case is where the new lock's range is in the 3792 * middle of the current lock's and splits the current lock 3793 * up. Use *other_lopp to handle the second part of the 3794 * split old lock range. (We are done now.) 3795 * For unlock, we use new_lop as other_lop and tmp, since 3796 * other_lop and new_lop are the same for this case. 3797 * We noted the unlock case above, so we don't need 3798 * new_lop->lo_flags any longer. 3799 */ 3800 tmp = new_lop->lo_first; 3801 if (other_lop == NULL) { 3802 if (!unlock) 3803 panic("nfsd srv update unlock"); 3804 other_lop = new_lop; 3805 *new_lopp = NULL; 3806 } 3807 other_lop->lo_first = new_lop->lo_end; 3808 other_lop->lo_end = lop->lo_end; 3809 other_lop->lo_flags = lop->lo_flags; 3810 other_lop->lo_stp = stp; 3811 other_lop->lo_lfp = lfp; 3812 lop->lo_end = tmp; 3813 nfsrv_insertlock(other_lop, lop, stp, lfp); 3814 *other_lopp = NULL; 3815 ilop = lop; 3816 break; 3817 } 3818 } 3819 ilop = lop; 3820 lop = LIST_NEXT(lop, lo_lckowner); 3821 if (myfile && (lop == NULL || lop->lo_lfp != lfp)) 3822 break; 3823 } 3824 3825 /* 3826 * Insert the new lock in the list at the appropriate place. 3827 */ 3828 if (!unlock) { 3829 nfsrv_insertlock(new_lop, ilop, stp, lfp); 3830 *new_lopp = NULL; 3831 } 3832 } 3833 3834 /* 3835 * This function handles sequencing of locks, etc. 3836 * It returns an error that indicates what the caller should do. 3837 */ 3838 static int 3839 nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 3840 struct nfsstate *stp, struct nfsrvcache *op) 3841 { 3842 int error = 0; 3843 3844 if ((nd->nd_flag & ND_NFSV41) != 0) 3845 /* NFSv4.1 ignores the open_seqid and lock_seqid. */ 3846 goto out; 3847 if (op != nd->nd_rp) 3848 panic("nfsrvstate checkseqid"); 3849 if (!(op->rc_flag & RC_INPROG)) 3850 panic("nfsrvstate not inprog"); 3851 if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) { 3852 printf("refcnt=%d\n", stp->ls_op->rc_refcnt); 3853 panic("nfsrvstate op refcnt"); 3854 } 3855 if ((stp->ls_seq + 1) == seqid) { 3856 if (stp->ls_op) 3857 nfsrvd_derefcache(stp->ls_op); 3858 stp->ls_op = op; 3859 nfsrvd_refcache(op); 3860 stp->ls_seq = seqid; 3861 goto out; 3862 } else if (stp->ls_seq == seqid && stp->ls_op && 3863 op->rc_xid == stp->ls_op->rc_xid && 3864 op->rc_refcnt == 0 && 3865 op->rc_reqlen == stp->ls_op->rc_reqlen && 3866 op->rc_cksum == stp->ls_op->rc_cksum) { 3867 if (stp->ls_op->rc_flag & RC_INPROG) { 3868 error = NFSERR_DONTREPLY; 3869 goto out; 3870 } 3871 nd->nd_rp = stp->ls_op; 3872 nd->nd_rp->rc_flag |= RC_INPROG; 3873 nfsrvd_delcache(op); 3874 error = NFSERR_REPLYFROMCACHE; 3875 goto out; 3876 } 3877 error = NFSERR_BADSEQID; 3878 3879 out: 3880 NFSEXITCODE2(error, nd); 3881 return (error); 3882 } 3883 3884 /* 3885 * Get the client ip address for callbacks. If the strings can't be parsed, 3886 * just set lc_program to 0 to indicate no callbacks are possible. 3887 * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set 3888 * the address to the client's transport address. This won't be used 3889 * for callbacks, but can be printed out by nfsstats for info.) 3890 * Return error if the xdr can't be parsed, 0 otherwise. 3891 */ 3892 APPLESTATIC int 3893 nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp) 3894 { 3895 u_int32_t *tl; 3896 u_char *cp, *cp2; 3897 int i, j; 3898 struct sockaddr_in *rad, *sad; 3899 u_char protocol[5], addr[24]; 3900 int error = 0, cantparse = 0; 3901 union { 3902 in_addr_t ival; 3903 u_char cval[4]; 3904 } ip; 3905 union { 3906 in_port_t sval; 3907 u_char cval[2]; 3908 } port; 3909 3910 rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 3911 rad->sin_family = AF_INET; 3912 rad->sin_len = sizeof (struct sockaddr_in); 3913 rad->sin_addr.s_addr = 0; 3914 rad->sin_port = 0; 3915 clp->lc_req.nr_client = NULL; 3916 clp->lc_req.nr_lock = 0; 3917 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3918 i = fxdr_unsigned(int, *tl); 3919 if (i >= 3 && i <= 4) { 3920 error = nfsrv_mtostr(nd, protocol, i); 3921 if (error) 3922 goto nfsmout; 3923 if (!strcmp(protocol, "tcp")) { 3924 clp->lc_flags |= LCL_TCPCALLBACK; 3925 clp->lc_req.nr_sotype = SOCK_STREAM; 3926 clp->lc_req.nr_soproto = IPPROTO_TCP; 3927 } else if (!strcmp(protocol, "udp")) { 3928 clp->lc_req.nr_sotype = SOCK_DGRAM; 3929 clp->lc_req.nr_soproto = IPPROTO_UDP; 3930 } else { 3931 cantparse = 1; 3932 } 3933 } else { 3934 cantparse = 1; 3935 if (i > 0) { 3936 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 3937 if (error) 3938 goto nfsmout; 3939 } 3940 } 3941 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3942 i = fxdr_unsigned(int, *tl); 3943 if (i < 0) { 3944 error = NFSERR_BADXDR; 3945 goto nfsmout; 3946 } else if (i == 0) { 3947 cantparse = 1; 3948 } else if (!cantparse && i <= 23 && i >= 11) { 3949 error = nfsrv_mtostr(nd, addr, i); 3950 if (error) 3951 goto nfsmout; 3952 3953 /* 3954 * Parse out the address fields. We expect 6 decimal numbers 3955 * separated by '.'s. 3956 */ 3957 cp = addr; 3958 i = 0; 3959 while (*cp && i < 6) { 3960 cp2 = cp; 3961 while (*cp2 && *cp2 != '.') 3962 cp2++; 3963 if (*cp2) 3964 *cp2++ = '\0'; 3965 else if (i != 5) { 3966 cantparse = 1; 3967 break; 3968 } 3969 j = nfsrv_getipnumber(cp); 3970 if (j >= 0) { 3971 if (i < 4) 3972 ip.cval[3 - i] = j; 3973 else 3974 port.cval[5 - i] = j; 3975 } else { 3976 cantparse = 1; 3977 break; 3978 } 3979 cp = cp2; 3980 i++; 3981 } 3982 if (!cantparse) { 3983 if (ip.ival != 0x0) { 3984 rad->sin_addr.s_addr = htonl(ip.ival); 3985 rad->sin_port = htons(port.sval); 3986 } else { 3987 cantparse = 1; 3988 } 3989 } 3990 } else { 3991 cantparse = 1; 3992 if (i > 0) { 3993 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 3994 if (error) 3995 goto nfsmout; 3996 } 3997 } 3998 if (cantparse) { 3999 sad = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); 4000 if (sad->sin_family == AF_INET) { 4001 rad->sin_addr.s_addr = sad->sin_addr.s_addr; 4002 rad->sin_port = 0x0; 4003 } 4004 clp->lc_program = 0; 4005 } 4006 nfsmout: 4007 NFSEXITCODE2(error, nd); 4008 return (error); 4009 } 4010 4011 /* 4012 * Turn a string of up to three decimal digits into a number. Return -1 upon 4013 * error. 4014 */ 4015 static int 4016 nfsrv_getipnumber(u_char *cp) 4017 { 4018 int i = 0, j = 0; 4019 4020 while (*cp) { 4021 if (j > 2 || *cp < '0' || *cp > '9') 4022 return (-1); 4023 i *= 10; 4024 i += (*cp - '0'); 4025 cp++; 4026 j++; 4027 } 4028 if (i < 256) 4029 return (i); 4030 return (-1); 4031 } 4032 4033 /* 4034 * This function checks for restart conditions. 4035 */ 4036 static int 4037 nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 4038 nfsv4stateid_t *stateidp, int specialid) 4039 { 4040 int ret = 0; 4041 4042 /* 4043 * First check for a server restart. Open, LockT, ReleaseLockOwner 4044 * and DelegPurge have a clientid, the rest a stateid. 4045 */ 4046 if (flags & 4047 (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { 4048 if (clientid.lval[0] != nfsrvboottime) { 4049 ret = NFSERR_STALECLIENTID; 4050 goto out; 4051 } 4052 } else if (stateidp->other[0] != nfsrvboottime && 4053 specialid == 0) { 4054 ret = NFSERR_STALESTATEID; 4055 goto out; 4056 } 4057 4058 /* 4059 * Read, Write, Setattr and LockT can return NFSERR_GRACE and do 4060 * not use a lock/open owner seqid#, so the check can be done now. 4061 * (The others will be checked, as required, later.) 4062 */ 4063 if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST))) 4064 goto out; 4065 4066 NFSLOCKSTATE(); 4067 ret = nfsrv_checkgrace(NULL, NULL, flags); 4068 NFSUNLOCKSTATE(); 4069 4070 out: 4071 NFSEXITCODE(ret); 4072 return (ret); 4073 } 4074 4075 /* 4076 * Check for grace. 4077 */ 4078 static int 4079 nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp, 4080 u_int32_t flags) 4081 { 4082 int error = 0; 4083 4084 if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) { 4085 if (flags & NFSLCK_RECLAIM) { 4086 error = NFSERR_NOGRACE; 4087 goto out; 4088 } 4089 } else { 4090 if (!(flags & NFSLCK_RECLAIM)) { 4091 error = NFSERR_GRACE; 4092 goto out; 4093 } 4094 if (nd != NULL && clp != NULL && 4095 (nd->nd_flag & ND_NFSV41) != 0 && 4096 (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) { 4097 error = NFSERR_NOGRACE; 4098 goto out; 4099 } 4100 4101 /* 4102 * If grace is almost over and we are still getting Reclaims, 4103 * extend grace a bit. 4104 */ 4105 if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > 4106 nfsrv_stablefirst.nsf_eograce) 4107 nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC + 4108 NFSRV_LEASEDELTA; 4109 } 4110 4111 out: 4112 NFSEXITCODE(error); 4113 return (error); 4114 } 4115 4116 /* 4117 * Do a server callback. 4118 */ 4119 static int 4120 nfsrv_docallback(struct nfsclient *clp, int procnum, 4121 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, 4122 struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p) 4123 { 4124 mbuf_t m; 4125 u_int32_t *tl; 4126 struct nfsrv_descript nfsd, *nd = &nfsd; 4127 struct ucred *cred; 4128 int error = 0; 4129 u_int32_t callback; 4130 struct nfsdsession *sep = NULL; 4131 4132 cred = newnfs_getcred(); 4133 NFSLOCKSTATE(); /* mostly for lc_cbref++ */ 4134 if (clp->lc_flags & LCL_NEEDSCONFIRM) { 4135 NFSUNLOCKSTATE(); 4136 panic("docallb"); 4137 } 4138 clp->lc_cbref++; 4139 4140 /* 4141 * Fill the callback program# and version into the request 4142 * structure for newnfs_connect() to use. 4143 */ 4144 clp->lc_req.nr_prog = clp->lc_program; 4145 #ifdef notnow 4146 if ((clp->lc_flags & LCL_NFSV41) != 0) 4147 clp->lc_req.nr_vers = NFSV41_CBVERS; 4148 else 4149 #endif 4150 clp->lc_req.nr_vers = NFSV4_CBVERS; 4151 4152 /* 4153 * First, fill in some of the fields of nd and cr. 4154 */ 4155 nd->nd_flag = ND_NFSV4; 4156 if (clp->lc_flags & LCL_GSS) 4157 nd->nd_flag |= ND_KERBV; 4158 if ((clp->lc_flags & LCL_NFSV41) != 0) 4159 nd->nd_flag |= ND_NFSV41; 4160 nd->nd_repstat = 0; 4161 cred->cr_uid = clp->lc_uid; 4162 cred->cr_gid = clp->lc_gid; 4163 callback = clp->lc_callback; 4164 NFSUNLOCKSTATE(); 4165 cred->cr_ngroups = 1; 4166 4167 /* 4168 * Get the first mbuf for the request. 4169 */ 4170 MGET(m, M_WAITOK, MT_DATA); 4171 mbuf_setlen(m, 0); 4172 nd->nd_mreq = nd->nd_mb = m; 4173 nd->nd_bpos = NFSMTOD(m, caddr_t); 4174 4175 /* 4176 * and build the callback request. 4177 */ 4178 if (procnum == NFSV4OP_CBGETATTR) { 4179 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4180 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR, 4181 "CB Getattr", &sep); 4182 if (error != 0) { 4183 mbuf_freem(nd->nd_mreq); 4184 goto errout; 4185 } 4186 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 4187 (void)nfsrv_putattrbit(nd, attrbitp); 4188 } else if (procnum == NFSV4OP_CBRECALL) { 4189 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4190 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL, 4191 "CB Recall", &sep); 4192 if (error != 0) { 4193 mbuf_freem(nd->nd_mreq); 4194 goto errout; 4195 } 4196 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID); 4197 *tl++ = txdr_unsigned(stateidp->seqid); 4198 NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl, 4199 NFSX_STATEIDOTHER); 4200 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4201 if (trunc) 4202 *tl = newnfs_true; 4203 else 4204 *tl = newnfs_false; 4205 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 4206 } else if (procnum == NFSV4PROC_CBNULL) { 4207 nd->nd_procnum = NFSV4PROC_CBNULL; 4208 if ((clp->lc_flags & LCL_NFSV41) != 0) { 4209 error = nfsv4_getcbsession(clp, &sep); 4210 if (error != 0) { 4211 mbuf_freem(nd->nd_mreq); 4212 goto errout; 4213 } 4214 } 4215 } else { 4216 error = NFSERR_SERVERFAULT; 4217 mbuf_freem(nd->nd_mreq); 4218 goto errout; 4219 } 4220 4221 /* 4222 * Call newnfs_connect(), as required, and then newnfs_request(). 4223 */ 4224 (void) newnfs_sndlock(&clp->lc_req.nr_lock); 4225 if (clp->lc_req.nr_client == NULL) { 4226 if ((clp->lc_flags & LCL_NFSV41) != 0) 4227 error = ECONNREFUSED; 4228 else if (nd->nd_procnum == NFSV4PROC_CBNULL) 4229 error = newnfs_connect(NULL, &clp->lc_req, cred, 4230 NULL, 1); 4231 else 4232 error = newnfs_connect(NULL, &clp->lc_req, cred, 4233 NULL, 3); 4234 } 4235 newnfs_sndunlock(&clp->lc_req.nr_lock); 4236 if (!error) { 4237 if ((nd->nd_flag & ND_NFSV41) != 0) { 4238 KASSERT(sep != NULL, ("sep NULL")); 4239 if (sep->sess_cbsess.nfsess_xprt != NULL) 4240 error = newnfs_request(nd, NULL, clp, 4241 &clp->lc_req, NULL, NULL, cred, 4242 clp->lc_program, clp->lc_req.nr_vers, NULL, 4243 1, NULL, &sep->sess_cbsess); 4244 else { 4245 /* 4246 * This should probably never occur, but if a 4247 * client somehow does an RPC without a 4248 * SequenceID Op that causes a callback just 4249 * after the nfsd threads have been terminated 4250 * and restared we could conceivably get here 4251 * without a backchannel xprt. 4252 */ 4253 printf("nfsrv_docallback: no xprt\n"); 4254 error = ECONNREFUSED; 4255 } 4256 nfsrv_freesession(sep, NULL); 4257 } else 4258 error = newnfs_request(nd, NULL, clp, &clp->lc_req, 4259 NULL, NULL, cred, clp->lc_program, 4260 clp->lc_req.nr_vers, NULL, 1, NULL, NULL); 4261 } 4262 errout: 4263 NFSFREECRED(cred); 4264 4265 /* 4266 * If error is set here, the Callback path isn't working 4267 * properly, so twiddle the appropriate LCL_ flags. 4268 * (nd_repstat != 0 indicates the Callback path is working, 4269 * but the callback failed on the client.) 4270 */ 4271 if (error) { 4272 /* 4273 * Mark the callback pathway down, which disabled issuing 4274 * of delegations and gets Renew to return NFSERR_CBPATHDOWN. 4275 */ 4276 NFSLOCKSTATE(); 4277 clp->lc_flags |= LCL_CBDOWN; 4278 NFSUNLOCKSTATE(); 4279 } else { 4280 /* 4281 * Callback worked. If the callback path was down, disable 4282 * callbacks, so no more delegations will be issued. (This 4283 * is done on the assumption that the callback pathway is 4284 * flakey.) 4285 */ 4286 NFSLOCKSTATE(); 4287 if (clp->lc_flags & LCL_CBDOWN) 4288 clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON); 4289 NFSUNLOCKSTATE(); 4290 if (nd->nd_repstat) 4291 error = nd->nd_repstat; 4292 else if (error == 0 && procnum == NFSV4OP_CBGETATTR) 4293 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, 4294 NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 4295 p, NULL); 4296 mbuf_freem(nd->nd_mrep); 4297 } 4298 NFSLOCKSTATE(); 4299 clp->lc_cbref--; 4300 if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) { 4301 clp->lc_flags &= ~LCL_WAKEUPWANTED; 4302 wakeup(clp); 4303 } 4304 NFSUNLOCKSTATE(); 4305 4306 NFSEXITCODE(error); 4307 return (error); 4308 } 4309 4310 /* 4311 * Set up the compound RPC for the callback. 4312 */ 4313 static int 4314 nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp, 4315 uint32_t callback, int op, const char *optag, struct nfsdsession **sepp) 4316 { 4317 uint32_t *tl; 4318 int error, len; 4319 4320 len = strlen(optag); 4321 (void)nfsm_strtom(nd, optag, len); 4322 NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED); 4323 if ((nd->nd_flag & ND_NFSV41) != 0) { 4324 *tl++ = txdr_unsigned(NFSV41_MINORVERSION); 4325 *tl++ = txdr_unsigned(callback); 4326 *tl++ = txdr_unsigned(2); 4327 *tl = txdr_unsigned(NFSV4OP_CBSEQUENCE); 4328 error = nfsv4_setcbsequence(nd, clp, 1, sepp); 4329 if (error != 0) 4330 return (error); 4331 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 4332 *tl = txdr_unsigned(op); 4333 } else { 4334 *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 4335 *tl++ = txdr_unsigned(callback); 4336 *tl++ = txdr_unsigned(1); 4337 *tl = txdr_unsigned(op); 4338 } 4339 return (0); 4340 } 4341 4342 /* 4343 * Return the next index# for a clientid. Mostly just increment and return 4344 * the next one, but... if the 32bit unsigned does actually wrap around, 4345 * it should be rebooted. 4346 * At an average rate of one new client per second, it will wrap around in 4347 * approximately 136 years. (I think the server will have been shut 4348 * down or rebooted before then.) 4349 */ 4350 static u_int32_t 4351 nfsrv_nextclientindex(void) 4352 { 4353 static u_int32_t client_index = 0; 4354 4355 client_index++; 4356 if (client_index != 0) 4357 return (client_index); 4358 4359 printf("%s: out of clientids\n", __func__); 4360 return (client_index); 4361 } 4362 4363 /* 4364 * Return the next index# for a stateid. Mostly just increment and return 4365 * the next one, but... if the 32bit unsigned does actually wrap around 4366 * (will a BSD server stay up that long?), find 4367 * new start and end values. 4368 */ 4369 static u_int32_t 4370 nfsrv_nextstateindex(struct nfsclient *clp) 4371 { 4372 struct nfsstate *stp; 4373 int i; 4374 u_int32_t canuse, min_index, max_index; 4375 4376 if (!(clp->lc_flags & LCL_INDEXNOTOK)) { 4377 clp->lc_stateindex++; 4378 if (clp->lc_stateindex != clp->lc_statemaxindex) 4379 return (clp->lc_stateindex); 4380 } 4381 4382 /* 4383 * Yuck, we've hit the end. 4384 * Look for a new min and max. 4385 */ 4386 min_index = 0; 4387 max_index = 0xffffffff; 4388 for (i = 0; i < nfsrv_statehashsize; i++) { 4389 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 4390 if (stp->ls_stateid.other[2] > 0x80000000) { 4391 if (stp->ls_stateid.other[2] < max_index) 4392 max_index = stp->ls_stateid.other[2]; 4393 } else { 4394 if (stp->ls_stateid.other[2] > min_index) 4395 min_index = stp->ls_stateid.other[2]; 4396 } 4397 } 4398 } 4399 4400 /* 4401 * Yikes, highly unlikely, but I'll handle it anyhow. 4402 */ 4403 if (min_index == 0x80000000 && max_index == 0x80000001) { 4404 canuse = 0; 4405 /* 4406 * Loop around until we find an unused entry. Return that 4407 * and set LCL_INDEXNOTOK, so the search will continue next time. 4408 * (This is one of those rare cases where a goto is the 4409 * cleanest way to code the loop.) 4410 */ 4411 tryagain: 4412 for (i = 0; i < nfsrv_statehashsize; i++) { 4413 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 4414 if (stp->ls_stateid.other[2] == canuse) { 4415 canuse++; 4416 goto tryagain; 4417 } 4418 } 4419 } 4420 clp->lc_flags |= LCL_INDEXNOTOK; 4421 return (canuse); 4422 } 4423 4424 /* 4425 * Ok to start again from min + 1. 4426 */ 4427 clp->lc_stateindex = min_index + 1; 4428 clp->lc_statemaxindex = max_index; 4429 clp->lc_flags &= ~LCL_INDEXNOTOK; 4430 return (clp->lc_stateindex); 4431 } 4432 4433 /* 4434 * The following functions handle the stable storage file that deals with 4435 * the edge conditions described in RFC3530 Sec. 8.6.3. 4436 * The file is as follows: 4437 * - a single record at the beginning that has the lease time of the 4438 * previous server instance (before the last reboot) and the nfsrvboottime 4439 * values for the previous server boots. 4440 * These previous boot times are used to ensure that the current 4441 * nfsrvboottime does not, somehow, get set to a previous one. 4442 * (This is important so that Stale ClientIDs and StateIDs can 4443 * be recognized.) 4444 * The number of previous nfsvrboottime values precedes the list. 4445 * - followed by some number of appended records with: 4446 * - client id string 4447 * - flag that indicates it is a record revoking state via lease 4448 * expiration or similar 4449 * OR has successfully acquired state. 4450 * These structures vary in length, with the client string at the end, up 4451 * to NFSV4_OPAQUELIMIT in size. 4452 * 4453 * At the end of the grace period, the file is truncated, the first 4454 * record is rewritten with updated information and any acquired state 4455 * records for successful reclaims of state are written. 4456 * 4457 * Subsequent records are appended when the first state is issued to 4458 * a client and when state is revoked for a client. 4459 * 4460 * When reading the file in, state issued records that come later in 4461 * the file override older ones, since the append log is in cronological order. 4462 * If, for some reason, the file can't be read, the grace period is 4463 * immediately terminated and all reclaims get NFSERR_NOGRACE. 4464 */ 4465 4466 /* 4467 * Read in the stable storage file. Called by nfssvc() before the nfsd 4468 * processes start servicing requests. 4469 */ 4470 APPLESTATIC void 4471 nfsrv_setupstable(NFSPROC_T *p) 4472 { 4473 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4474 struct nfsrv_stable *sp, *nsp; 4475 struct nfst_rec *tsp; 4476 int error, i, tryagain; 4477 off_t off = 0; 4478 ssize_t aresid, len; 4479 4480 /* 4481 * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without 4482 * a reboot, so state has not been lost. 4483 */ 4484 if (sf->nsf_flags & NFSNSF_UPDATEDONE) 4485 return; 4486 /* 4487 * Set Grace over just until the file reads successfully. 4488 */ 4489 nfsrvboottime = time_second; 4490 LIST_INIT(&sf->nsf_head); 4491 sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); 4492 sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA; 4493 if (sf->nsf_fp == NULL) 4494 return; 4495 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4496 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE, 4497 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4498 if (error || aresid || sf->nsf_numboots == 0 || 4499 sf->nsf_numboots > NFSNSF_MAXNUMBOOTS) 4500 return; 4501 4502 /* 4503 * Now, read in the boottimes. 4504 */ 4505 sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) * 4506 sizeof (time_t), M_TEMP, M_WAITOK); 4507 off = sizeof (struct nfsf_rec); 4508 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4509 (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off, 4510 UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4511 if (error || aresid) { 4512 free(sf->nsf_bootvals, M_TEMP); 4513 sf->nsf_bootvals = NULL; 4514 return; 4515 } 4516 4517 /* 4518 * Make sure this nfsrvboottime is different from all recorded 4519 * previous ones. 4520 */ 4521 do { 4522 tryagain = 0; 4523 for (i = 0; i < sf->nsf_numboots; i++) { 4524 if (nfsrvboottime == sf->nsf_bootvals[i]) { 4525 nfsrvboottime++; 4526 tryagain = 1; 4527 break; 4528 } 4529 } 4530 } while (tryagain); 4531 4532 sf->nsf_flags |= NFSNSF_OK; 4533 off += (sf->nsf_numboots * sizeof (time_t)); 4534 4535 /* 4536 * Read through the file, building a list of records for grace 4537 * checking. 4538 * Each record is between sizeof (struct nfst_rec) and 4539 * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1 4540 * and is actually sizeof (struct nfst_rec) + nst_len - 1. 4541 */ 4542 tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4543 NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK); 4544 do { 4545 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4546 (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1, 4547 off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4548 len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid; 4549 if (error || (len > 0 && (len < sizeof (struct nfst_rec) || 4550 len < (sizeof (struct nfst_rec) + tsp->len - 1)))) { 4551 /* 4552 * Yuck, the file has been corrupted, so just return 4553 * after clearing out any restart state, so the grace period 4554 * is over. 4555 */ 4556 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4557 LIST_REMOVE(sp, nst_list); 4558 free(sp, M_TEMP); 4559 } 4560 free(tsp, M_TEMP); 4561 sf->nsf_flags &= ~NFSNSF_OK; 4562 free(sf->nsf_bootvals, M_TEMP); 4563 sf->nsf_bootvals = NULL; 4564 return; 4565 } 4566 if (len > 0) { 4567 off += sizeof (struct nfst_rec) + tsp->len - 1; 4568 /* 4569 * Search the list for a matching client. 4570 */ 4571 LIST_FOREACH(sp, &sf->nsf_head, nst_list) { 4572 if (tsp->len == sp->nst_len && 4573 !NFSBCMP(tsp->client, sp->nst_client, tsp->len)) 4574 break; 4575 } 4576 if (sp == LIST_END(&sf->nsf_head)) { 4577 sp = (struct nfsrv_stable *)malloc(tsp->len + 4578 sizeof (struct nfsrv_stable) - 1, M_TEMP, 4579 M_WAITOK); 4580 NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec, 4581 sizeof (struct nfst_rec) + tsp->len - 1); 4582 LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list); 4583 } else { 4584 if (tsp->flag == NFSNST_REVOKE) 4585 sp->nst_flag |= NFSNST_REVOKE; 4586 else 4587 /* 4588 * A subsequent timestamp indicates the client 4589 * did a setclientid/confirm and any previous 4590 * revoke is no longer relevant. 4591 */ 4592 sp->nst_flag &= ~NFSNST_REVOKE; 4593 } 4594 } 4595 } while (len > 0); 4596 free(tsp, M_TEMP); 4597 sf->nsf_flags = NFSNSF_OK; 4598 sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease + 4599 NFSRV_LEASEDELTA; 4600 } 4601 4602 /* 4603 * Update the stable storage file, now that the grace period is over. 4604 */ 4605 APPLESTATIC void 4606 nfsrv_updatestable(NFSPROC_T *p) 4607 { 4608 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4609 struct nfsrv_stable *sp, *nsp; 4610 int i; 4611 struct nfsvattr nva; 4612 vnode_t vp; 4613 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) 4614 mount_t mp = NULL; 4615 #endif 4616 int error; 4617 4618 if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE)) 4619 return; 4620 sf->nsf_flags |= NFSNSF_UPDATEDONE; 4621 /* 4622 * Ok, we need to rewrite the stable storage file. 4623 * - truncate to 0 length 4624 * - write the new first structure 4625 * - loop through the data structures, writing out any that 4626 * have timestamps older than the old boot 4627 */ 4628 if (sf->nsf_bootvals) { 4629 sf->nsf_numboots++; 4630 for (i = sf->nsf_numboots - 2; i >= 0; i--) 4631 sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i]; 4632 } else { 4633 sf->nsf_numboots = 1; 4634 sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t), 4635 M_TEMP, M_WAITOK); 4636 } 4637 sf->nsf_bootvals[0] = nfsrvboottime; 4638 sf->nsf_lease = nfsrv_lease; 4639 NFSVNO_ATTRINIT(&nva); 4640 NFSVNO_SETATTRVAL(&nva, size, 0); 4641 vp = NFSFPVNODE(sf->nsf_fp); 4642 vn_start_write(vp, &mp, V_WAIT); 4643 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { 4644 error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p, 4645 NULL); 4646 NFSVOPUNLOCK(vp, 0); 4647 } else 4648 error = EPERM; 4649 vn_finished_write(mp); 4650 if (!error) 4651 error = NFSD_RDWR(UIO_WRITE, vp, 4652 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0, 4653 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4654 if (!error) 4655 error = NFSD_RDWR(UIO_WRITE, vp, 4656 (caddr_t)sf->nsf_bootvals, 4657 sf->nsf_numboots * sizeof (time_t), 4658 (off_t)(sizeof (struct nfsf_rec)), 4659 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4660 free(sf->nsf_bootvals, M_TEMP); 4661 sf->nsf_bootvals = NULL; 4662 if (error) { 4663 sf->nsf_flags &= ~NFSNSF_OK; 4664 printf("EEK! Can't write NfsV4 stable storage file\n"); 4665 return; 4666 } 4667 sf->nsf_flags |= NFSNSF_OK; 4668 4669 /* 4670 * Loop through the list and write out timestamp records for 4671 * any clients that successfully reclaimed state. 4672 */ 4673 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4674 if (sp->nst_flag & NFSNST_GOTSTATE) { 4675 nfsrv_writestable(sp->nst_client, sp->nst_len, 4676 NFSNST_NEWSTATE, p); 4677 sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE; 4678 } 4679 LIST_REMOVE(sp, nst_list); 4680 free(sp, M_TEMP); 4681 } 4682 nfsrv_backupstable(); 4683 } 4684 4685 /* 4686 * Append a record to the stable storage file. 4687 */ 4688 APPLESTATIC void 4689 nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p) 4690 { 4691 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4692 struct nfst_rec *sp; 4693 int error; 4694 4695 if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL) 4696 return; 4697 sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4698 len - 1, M_TEMP, M_WAITOK); 4699 sp->len = len; 4700 NFSBCOPY(client, sp->client, len); 4701 sp->flag = flag; 4702 error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp), 4703 (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0, 4704 UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p); 4705 free(sp, M_TEMP); 4706 if (error) { 4707 sf->nsf_flags &= ~NFSNSF_OK; 4708 printf("EEK! Can't write NfsV4 stable storage file\n"); 4709 } 4710 } 4711 4712 /* 4713 * This function is called during the grace period to mark a client 4714 * that successfully reclaimed state. 4715 */ 4716 static void 4717 nfsrv_markstable(struct nfsclient *clp) 4718 { 4719 struct nfsrv_stable *sp; 4720 4721 /* 4722 * First find the client structure. 4723 */ 4724 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4725 if (sp->nst_len == clp->lc_idlen && 4726 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4727 break; 4728 } 4729 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) 4730 return; 4731 4732 /* 4733 * Now, just mark it and set the nfsclient back pointer. 4734 */ 4735 sp->nst_flag |= NFSNST_GOTSTATE; 4736 sp->nst_clp = clp; 4737 } 4738 4739 /* 4740 * This function is called for a reclaim, to see if it gets grace. 4741 * It returns 0 if a reclaim is allowed, 1 otherwise. 4742 */ 4743 static int 4744 nfsrv_checkstable(struct nfsclient *clp) 4745 { 4746 struct nfsrv_stable *sp; 4747 4748 /* 4749 * First, find the entry for the client. 4750 */ 4751 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4752 if (sp->nst_len == clp->lc_idlen && 4753 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4754 break; 4755 } 4756 4757 /* 4758 * If not in the list, state was revoked or no state was issued 4759 * since the previous reboot, a reclaim is denied. 4760 */ 4761 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) || 4762 (sp->nst_flag & NFSNST_REVOKE) || 4763 !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK)) 4764 return (1); 4765 return (0); 4766 } 4767 4768 /* 4769 * Test for and try to clear out a conflicting client. This is called by 4770 * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients 4771 * a found. 4772 * The trick here is that it can't revoke a conflicting client with an 4773 * expired lease unless it holds the v4root lock, so... 4774 * If no v4root lock, get the lock and return 1 to indicate "try again". 4775 * Return 0 to indicate the conflict can't be revoked and 1 to indicate 4776 * the revocation worked and the conflicting client is "bye, bye", so it 4777 * can be tried again. 4778 * Return 2 to indicate that the vnode is VI_DOOMED after NFSVOPLOCK(). 4779 * Unlocks State before a non-zero value is returned. 4780 */ 4781 static int 4782 nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp, 4783 NFSPROC_T *p) 4784 { 4785 int gotlock, lktype = 0; 4786 4787 /* 4788 * If lease hasn't expired, we can't fix it. 4789 */ 4790 if (clp->lc_expiry >= NFSD_MONOSEC || 4791 !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) 4792 return (0); 4793 if (*haslockp == 0) { 4794 NFSUNLOCKSTATE(); 4795 if (vp != NULL) { 4796 lktype = NFSVOPISLOCKED(vp); 4797 NFSVOPUNLOCK(vp, 0); 4798 } 4799 NFSLOCKV4ROOTMUTEX(); 4800 nfsv4_relref(&nfsv4rootfs_lock); 4801 do { 4802 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4803 NFSV4ROOTLOCKMUTEXPTR, NULL); 4804 } while (!gotlock); 4805 NFSUNLOCKV4ROOTMUTEX(); 4806 *haslockp = 1; 4807 if (vp != NULL) { 4808 NFSVOPLOCK(vp, lktype | LK_RETRY); 4809 if ((vp->v_iflag & VI_DOOMED) != 0) 4810 return (2); 4811 } 4812 return (1); 4813 } 4814 NFSUNLOCKSTATE(); 4815 4816 /* 4817 * Ok, we can expire the conflicting client. 4818 */ 4819 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 4820 nfsrv_backupstable(); 4821 nfsrv_cleanclient(clp, p); 4822 nfsrv_freedeleglist(&clp->lc_deleg); 4823 nfsrv_freedeleglist(&clp->lc_olddeleg); 4824 LIST_REMOVE(clp, lc_hash); 4825 nfsrv_zapclient(clp, p); 4826 return (1); 4827 } 4828 4829 /* 4830 * Resolve a delegation conflict. 4831 * Returns 0 to indicate the conflict was resolved without sleeping. 4832 * Return -1 to indicate that the caller should check for conflicts again. 4833 * Return > 0 for an error that should be returned, normally NFSERR_DELAY. 4834 * 4835 * Also, manipulate the nfsv4root_lock, as required. It isn't changed 4836 * for a return of 0, since there was no sleep and it could be required 4837 * later. It is released for a return of NFSERR_DELAY, since the caller 4838 * will return that error. It is released when a sleep was done waiting 4839 * for the delegation to be returned or expire (so that other nfsds can 4840 * handle ops). Then, it must be acquired for the write to stable storage. 4841 * (This function is somewhat similar to nfsrv_clientconflict(), but 4842 * the semantics differ in a couple of subtle ways. The return of 0 4843 * indicates the conflict was resolved without sleeping here, not 4844 * that the conflict can't be resolved and the handling of nfsv4root_lock 4845 * differs, as noted above.) 4846 * Unlocks State before returning a non-zero value. 4847 */ 4848 static int 4849 nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p, 4850 vnode_t vp) 4851 { 4852 struct nfsclient *clp = stp->ls_clp; 4853 int gotlock, error, lktype = 0, retrycnt, zapped_clp; 4854 nfsv4stateid_t tstateid; 4855 fhandle_t tfh; 4856 4857 /* 4858 * If the conflict is with an old delegation... 4859 */ 4860 if (stp->ls_flags & NFSLCK_OLDDELEG) { 4861 /* 4862 * You can delete it, if it has expired. 4863 */ 4864 if (clp->lc_delegtime < NFSD_MONOSEC) { 4865 nfsrv_freedeleg(stp); 4866 NFSUNLOCKSTATE(); 4867 error = -1; 4868 goto out; 4869 } 4870 NFSUNLOCKSTATE(); 4871 /* 4872 * During this delay, the old delegation could expire or it 4873 * could be recovered by the client via an Open with 4874 * CLAIM_DELEGATE_PREV. 4875 * Release the nfsv4root_lock, if held. 4876 */ 4877 if (*haslockp) { 4878 *haslockp = 0; 4879 NFSLOCKV4ROOTMUTEX(); 4880 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4881 NFSUNLOCKV4ROOTMUTEX(); 4882 } 4883 error = NFSERR_DELAY; 4884 goto out; 4885 } 4886 4887 /* 4888 * It's a current delegation, so: 4889 * - check to see if the delegation has expired 4890 * - if so, get the v4root lock and then expire it 4891 */ 4892 if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) { 4893 /* 4894 * - do a recall callback, since not yet done 4895 * For now, never allow truncate to be set. To use 4896 * truncate safely, it must be guaranteed that the 4897 * Remove, Rename or Setattr with size of 0 will 4898 * succeed and that would require major changes to 4899 * the VFS/Vnode OPs. 4900 * Set the expiry time large enough so that it won't expire 4901 * until after the callback, then set it correctly, once 4902 * the callback is done. (The delegation will now time 4903 * out whether or not the Recall worked ok. The timeout 4904 * will be extended when ops are done on the delegation 4905 * stateid, up to the timelimit.) 4906 */ 4907 stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) + 4908 NFSRV_LEASEDELTA; 4909 stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) + 4910 NFSRV_LEASEDELTA; 4911 stp->ls_flags |= NFSLCK_DELEGRECALL; 4912 4913 /* 4914 * Loop NFSRV_CBRETRYCNT times while the CBRecall replies 4915 * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done 4916 * in order to try and avoid a race that could happen 4917 * when a CBRecall request passed the Open reply with 4918 * the delegation in it when transitting the network. 4919 * Since nfsrv_docallback will sleep, don't use stp after 4920 * the call. 4921 */ 4922 NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid, 4923 sizeof (tstateid)); 4924 NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh, 4925 sizeof (tfh)); 4926 NFSUNLOCKSTATE(); 4927 if (*haslockp) { 4928 *haslockp = 0; 4929 NFSLOCKV4ROOTMUTEX(); 4930 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4931 NFSUNLOCKV4ROOTMUTEX(); 4932 } 4933 retrycnt = 0; 4934 do { 4935 error = nfsrv_docallback(clp, NFSV4OP_CBRECALL, 4936 &tstateid, 0, &tfh, NULL, NULL, p); 4937 retrycnt++; 4938 } while ((error == NFSERR_BADSTATEID || 4939 error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT); 4940 error = NFSERR_DELAY; 4941 goto out; 4942 } 4943 4944 if (clp->lc_expiry >= NFSD_MONOSEC && 4945 stp->ls_delegtime >= NFSD_MONOSEC) { 4946 NFSUNLOCKSTATE(); 4947 /* 4948 * A recall has been done, but it has not yet expired. 4949 * So, RETURN_DELAY. 4950 */ 4951 if (*haslockp) { 4952 *haslockp = 0; 4953 NFSLOCKV4ROOTMUTEX(); 4954 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4955 NFSUNLOCKV4ROOTMUTEX(); 4956 } 4957 error = NFSERR_DELAY; 4958 goto out; 4959 } 4960 4961 /* 4962 * If we don't yet have the lock, just get it and then return, 4963 * since we need that before deleting expired state, such as 4964 * this delegation. 4965 * When getting the lock, unlock the vnode, so other nfsds that 4966 * are in progress, won't get stuck waiting for the vnode lock. 4967 */ 4968 if (*haslockp == 0) { 4969 NFSUNLOCKSTATE(); 4970 if (vp != NULL) { 4971 lktype = NFSVOPISLOCKED(vp); 4972 NFSVOPUNLOCK(vp, 0); 4973 } 4974 NFSLOCKV4ROOTMUTEX(); 4975 nfsv4_relref(&nfsv4rootfs_lock); 4976 do { 4977 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4978 NFSV4ROOTLOCKMUTEXPTR, NULL); 4979 } while (!gotlock); 4980 NFSUNLOCKV4ROOTMUTEX(); 4981 *haslockp = 1; 4982 if (vp != NULL) { 4983 NFSVOPLOCK(vp, lktype | LK_RETRY); 4984 if ((vp->v_iflag & VI_DOOMED) != 0) { 4985 *haslockp = 0; 4986 NFSLOCKV4ROOTMUTEX(); 4987 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4988 NFSUNLOCKV4ROOTMUTEX(); 4989 error = NFSERR_PERM; 4990 goto out; 4991 } 4992 } 4993 error = -1; 4994 goto out; 4995 } 4996 4997 NFSUNLOCKSTATE(); 4998 /* 4999 * Ok, we can delete the expired delegation. 5000 * First, write the Revoke record to stable storage and then 5001 * clear out the conflict. 5002 * Since all other nfsd threads are now blocked, we can safely 5003 * sleep without the state changing. 5004 */ 5005 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 5006 nfsrv_backupstable(); 5007 if (clp->lc_expiry < NFSD_MONOSEC) { 5008 nfsrv_cleanclient(clp, p); 5009 nfsrv_freedeleglist(&clp->lc_deleg); 5010 nfsrv_freedeleglist(&clp->lc_olddeleg); 5011 LIST_REMOVE(clp, lc_hash); 5012 zapped_clp = 1; 5013 } else { 5014 nfsrv_freedeleg(stp); 5015 zapped_clp = 0; 5016 } 5017 if (zapped_clp) 5018 nfsrv_zapclient(clp, p); 5019 error = -1; 5020 5021 out: 5022 NFSEXITCODE(error); 5023 return (error); 5024 } 5025 5026 /* 5027 * Check for a remove allowed, if remove is set to 1 and get rid of 5028 * delegations. 5029 */ 5030 APPLESTATIC int 5031 nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p) 5032 { 5033 struct nfsstate *stp; 5034 struct nfslockfile *lfp; 5035 int error, haslock = 0; 5036 fhandle_t nfh; 5037 5038 /* 5039 * First, get the lock file structure. 5040 * (A return of -1 means no associated state, so remove ok.) 5041 */ 5042 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 5043 tryagain: 5044 NFSLOCKSTATE(); 5045 if (!error) 5046 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 5047 if (error) { 5048 NFSUNLOCKSTATE(); 5049 if (haslock) { 5050 NFSLOCKV4ROOTMUTEX(); 5051 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5052 NFSUNLOCKV4ROOTMUTEX(); 5053 } 5054 if (error == -1) 5055 error = 0; 5056 goto out; 5057 } 5058 5059 /* 5060 * Now, we must Recall any delegations. 5061 */ 5062 error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p); 5063 if (error) { 5064 /* 5065 * nfsrv_cleandeleg() unlocks state for non-zero 5066 * return. 5067 */ 5068 if (error == -1) 5069 goto tryagain; 5070 if (haslock) { 5071 NFSLOCKV4ROOTMUTEX(); 5072 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5073 NFSUNLOCKV4ROOTMUTEX(); 5074 } 5075 goto out; 5076 } 5077 5078 /* 5079 * Now, look for a conflicting open share. 5080 */ 5081 if (remove) { 5082 /* 5083 * If the entry in the directory was the last reference to the 5084 * corresponding filesystem object, the object can be destroyed 5085 * */ 5086 if(lfp->lf_usecount>1) 5087 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 5088 if (stp->ls_flags & NFSLCK_WRITEDENY) { 5089 error = NFSERR_FILEOPEN; 5090 break; 5091 } 5092 } 5093 } 5094 5095 NFSUNLOCKSTATE(); 5096 if (haslock) { 5097 NFSLOCKV4ROOTMUTEX(); 5098 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5099 NFSUNLOCKV4ROOTMUTEX(); 5100 } 5101 5102 out: 5103 NFSEXITCODE(error); 5104 return (error); 5105 } 5106 5107 /* 5108 * Clear out all delegations for the file referred to by lfp. 5109 * May return NFSERR_DELAY, if there will be a delay waiting for 5110 * delegations to expire. 5111 * Returns -1 to indicate it slept while recalling a delegation. 5112 * This function has the side effect of deleting the nfslockfile structure, 5113 * if it no longer has associated state and didn't have to sleep. 5114 * Unlocks State before a non-zero value is returned. 5115 */ 5116 static int 5117 nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 5118 struct nfsclient *clp, int *haslockp, NFSPROC_T *p) 5119 { 5120 struct nfsstate *stp, *nstp; 5121 int ret = 0; 5122 5123 stp = LIST_FIRST(&lfp->lf_deleg); 5124 while (stp != LIST_END(&lfp->lf_deleg)) { 5125 nstp = LIST_NEXT(stp, ls_file); 5126 if (stp->ls_clp != clp) { 5127 ret = nfsrv_delegconflict(stp, haslockp, p, vp); 5128 if (ret) { 5129 /* 5130 * nfsrv_delegconflict() unlocks state 5131 * when it returns non-zero. 5132 */ 5133 goto out; 5134 } 5135 } 5136 stp = nstp; 5137 } 5138 out: 5139 NFSEXITCODE(ret); 5140 return (ret); 5141 } 5142 5143 /* 5144 * There are certain operations that, when being done outside of NFSv4, 5145 * require that any NFSv4 delegation for the file be recalled. 5146 * This function is to be called for those cases: 5147 * VOP_RENAME() - When a delegation is being recalled for any reason, 5148 * the client may have to do Opens against the server, using the file's 5149 * final component name. If the file has been renamed on the server, 5150 * that component name will be incorrect and the Open will fail. 5151 * VOP_REMOVE() - Theoretically, a client could Open a file after it has 5152 * been removed on the server, if there is a delegation issued to 5153 * that client for the file. I say "theoretically" since clients 5154 * normally do an Access Op before the Open and that Access Op will 5155 * fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so 5156 * they will detect the file's removal in the same manner. (There is 5157 * one case where RFC3530 allows a client to do an Open without first 5158 * doing an Access Op, which is passage of a check against the ACE 5159 * returned with a Write delegation, but current practice is to ignore 5160 * the ACE and always do an Access Op.) 5161 * Since the functions can only be called with an unlocked vnode, this 5162 * can't be done at this time. 5163 * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range 5164 * locks locally in the client, which are not visible to the server. To 5165 * deal with this, issuing of delegations for a vnode must be disabled 5166 * and all delegations for the vnode recalled. This is done via the 5167 * second function, using the VV_DISABLEDELEG vflag on the vnode. 5168 */ 5169 APPLESTATIC void 5170 nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p) 5171 { 5172 time_t starttime; 5173 int error; 5174 5175 /* 5176 * First, check to see if the server is currently running and it has 5177 * been called for a regular file when issuing delegations. 5178 */ 5179 if (newnfs_numnfsd == 0 || vp->v_type != VREG || 5180 nfsrv_issuedelegs == 0) 5181 return; 5182 5183 KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp)); 5184 /* 5185 * First, get a reference on the nfsv4rootfs_lock so that an 5186 * exclusive lock cannot be acquired by another thread. 5187 */ 5188 NFSLOCKV4ROOTMUTEX(); 5189 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 5190 NFSUNLOCKV4ROOTMUTEX(); 5191 5192 /* 5193 * Now, call nfsrv_checkremove() in a loop while it returns 5194 * NFSERR_DELAY. Return upon any other error or when timed out. 5195 */ 5196 starttime = NFSD_MONOSEC; 5197 do { 5198 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { 5199 error = nfsrv_checkremove(vp, 0, p); 5200 NFSVOPUNLOCK(vp, 0); 5201 } else 5202 error = EPERM; 5203 if (error == NFSERR_DELAY) { 5204 if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO) 5205 break; 5206 /* Sleep for a short period of time */ 5207 (void) nfs_catnap(PZERO, 0, "nfsremove"); 5208 } 5209 } while (error == NFSERR_DELAY); 5210 NFSLOCKV4ROOTMUTEX(); 5211 nfsv4_relref(&nfsv4rootfs_lock); 5212 NFSUNLOCKV4ROOTMUTEX(); 5213 } 5214 5215 APPLESTATIC void 5216 nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p) 5217 { 5218 5219 #ifdef VV_DISABLEDELEG 5220 /* 5221 * First, flag issuance of delegations disabled. 5222 */ 5223 atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG); 5224 #endif 5225 5226 /* 5227 * Then call nfsd_recalldelegation() to get rid of all extant 5228 * delegations. 5229 */ 5230 nfsd_recalldelegation(vp, p); 5231 } 5232 5233 /* 5234 * Check for conflicting locks, etc. and then get rid of delegations. 5235 * (At one point I thought that I should get rid of delegations for any 5236 * Setattr, since it could potentially disallow the I/O op (read or write) 5237 * allowed by the delegation. However, Setattr Ops that aren't changing 5238 * the size get a stateid of all 0s, so you can't tell if it is a delegation 5239 * for the same client or a different one, so I decided to only get rid 5240 * of delegations for other clients when the size is being changed.) 5241 * In general, a Setattr can disable NFS I/O Ops that are outstanding, such 5242 * as Write backs, even if there is no delegation, so it really isn't any 5243 * different?) 5244 */ 5245 APPLESTATIC int 5246 nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd, 5247 nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp, 5248 struct nfsexstuff *exp, NFSPROC_T *p) 5249 { 5250 struct nfsstate st, *stp = &st; 5251 struct nfslock lo, *lop = &lo; 5252 int error = 0; 5253 nfsquad_t clientid; 5254 5255 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) { 5256 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 5257 lop->lo_first = nvap->na_size; 5258 } else { 5259 stp->ls_flags = 0; 5260 lop->lo_first = 0; 5261 } 5262 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) || 5263 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) || 5264 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) || 5265 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL)) 5266 stp->ls_flags |= NFSLCK_SETATTR; 5267 if (stp->ls_flags == 0) 5268 goto out; 5269 lop->lo_end = NFS64BITSSET; 5270 lop->lo_flags = NFSLCK_WRITE; 5271 stp->ls_ownerlen = 0; 5272 stp->ls_op = NULL; 5273 stp->ls_uid = nd->nd_cred->cr_uid; 5274 stp->ls_stateid.seqid = stateidp->seqid; 5275 clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0]; 5276 clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1]; 5277 stp->ls_stateid.other[2] = stateidp->other[2]; 5278 error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 5279 stateidp, exp, nd, p); 5280 5281 out: 5282 NFSEXITCODE2(error, nd); 5283 return (error); 5284 } 5285 5286 /* 5287 * Check for a write delegation and do a CBGETATTR if there is one, updating 5288 * the attributes, as required. 5289 * Should I return an error if I can't get the attributes? (For now, I'll 5290 * just return ok. 5291 */ 5292 APPLESTATIC int 5293 nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp, 5294 struct nfsvattr *nvap, nfsattrbit_t *attrbitp, struct ucred *cred, 5295 NFSPROC_T *p) 5296 { 5297 struct nfsstate *stp; 5298 struct nfslockfile *lfp; 5299 struct nfsclient *clp; 5300 struct nfsvattr nva; 5301 fhandle_t nfh; 5302 int error = 0; 5303 nfsattrbit_t cbbits; 5304 u_quad_t delegfilerev; 5305 5306 NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits); 5307 if (!NFSNONZERO_ATTRBIT(&cbbits)) 5308 goto out; 5309 if (nfsrv_writedelegcnt == 0) 5310 goto out; 5311 5312 /* 5313 * Get the lock file structure. 5314 * (A return of -1 means no associated state, so return ok.) 5315 */ 5316 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 5317 NFSLOCKSTATE(); 5318 if (!error) 5319 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 5320 if (error) { 5321 NFSUNLOCKSTATE(); 5322 if (error == -1) 5323 error = 0; 5324 goto out; 5325 } 5326 5327 /* 5328 * Now, look for a write delegation. 5329 */ 5330 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 5331 if (stp->ls_flags & NFSLCK_DELEGWRITE) 5332 break; 5333 } 5334 if (stp == LIST_END(&lfp->lf_deleg)) { 5335 NFSUNLOCKSTATE(); 5336 goto out; 5337 } 5338 clp = stp->ls_clp; 5339 delegfilerev = stp->ls_filerev; 5340 5341 /* 5342 * If the Write delegation was issued as a part of this Compound RPC 5343 * or if we have an Implied Clientid (used in a previous Op in this 5344 * compound) and it is the client the delegation was issued to, 5345 * just return ok. 5346 * I also assume that it is from the same client iff the network 5347 * host IP address is the same as the callback address. (Not 5348 * exactly correct by the RFC, but avoids a lot of Getattr 5349 * callbacks.) 5350 */ 5351 if (nd->nd_compref == stp->ls_compref || 5352 ((nd->nd_flag & ND_IMPLIEDCLID) && 5353 clp->lc_clientid.qval == nd->nd_clientid.qval) || 5354 nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) { 5355 NFSUNLOCKSTATE(); 5356 goto out; 5357 } 5358 5359 /* 5360 * We are now done with the delegation state structure, 5361 * so the statelock can be released and we can now tsleep(). 5362 */ 5363 5364 /* 5365 * Now, we must do the CB Getattr callback, to see if Change or Size 5366 * has changed. 5367 */ 5368 if (clp->lc_expiry >= NFSD_MONOSEC) { 5369 NFSUNLOCKSTATE(); 5370 NFSVNO_ATTRINIT(&nva); 5371 nva.na_filerev = NFS64BITSSET; 5372 error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL, 5373 0, &nfh, &nva, &cbbits, p); 5374 if (!error) { 5375 if ((nva.na_filerev != NFS64BITSSET && 5376 nva.na_filerev > delegfilerev) || 5377 (NFSVNO_ISSETSIZE(&nva) && 5378 nva.na_size != nvap->na_size)) { 5379 error = nfsvno_updfilerev(vp, nvap, cred, p); 5380 if (NFSVNO_ISSETSIZE(&nva)) 5381 nvap->na_size = nva.na_size; 5382 } 5383 } else 5384 error = 0; /* Ignore callback errors for now. */ 5385 } else { 5386 NFSUNLOCKSTATE(); 5387 } 5388 5389 out: 5390 NFSEXITCODE2(error, nd); 5391 return (error); 5392 } 5393 5394 /* 5395 * This function looks for openowners that haven't had any opens for 5396 * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS 5397 * is set. 5398 */ 5399 APPLESTATIC void 5400 nfsrv_throwawayopens(NFSPROC_T *p) 5401 { 5402 struct nfsclient *clp, *nclp; 5403 struct nfsstate *stp, *nstp; 5404 int i; 5405 5406 NFSLOCKSTATE(); 5407 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS; 5408 /* 5409 * For each client... 5410 */ 5411 for (i = 0; i < nfsrv_clienthashsize; i++) { 5412 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 5413 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { 5414 if (LIST_EMPTY(&stp->ls_open) && 5415 (stp->ls_noopens > NFSNOOPEN || 5416 (nfsrv_openpluslock * 2) > 5417 nfsrv_v4statelimit)) 5418 nfsrv_freeopenowner(stp, 0, p); 5419 } 5420 } 5421 } 5422 NFSUNLOCKSTATE(); 5423 } 5424 5425 /* 5426 * This function checks to see if the credentials are the same. 5427 * Returns 1 for not same, 0 otherwise. 5428 */ 5429 static int 5430 nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp) 5431 { 5432 5433 if (nd->nd_flag & ND_GSS) { 5434 if (!(clp->lc_flags & LCL_GSS)) 5435 return (1); 5436 if (clp->lc_flags & LCL_NAME) { 5437 if (nd->nd_princlen != clp->lc_namelen || 5438 NFSBCMP(nd->nd_principal, clp->lc_name, 5439 clp->lc_namelen)) 5440 return (1); 5441 else 5442 return (0); 5443 } 5444 if (nd->nd_cred->cr_uid == clp->lc_uid) 5445 return (0); 5446 else 5447 return (1); 5448 } else if (clp->lc_flags & LCL_GSS) 5449 return (1); 5450 /* 5451 * For AUTH_SYS, allow the same uid or root. (This is underspecified 5452 * in RFC3530, which talks about principals, but doesn't say anything 5453 * about uids for AUTH_SYS.) 5454 */ 5455 if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0) 5456 return (0); 5457 else 5458 return (1); 5459 } 5460 5461 /* 5462 * Calculate the lease expiry time. 5463 */ 5464 static time_t 5465 nfsrv_leaseexpiry(void) 5466 { 5467 5468 if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC) 5469 return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA)); 5470 return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA); 5471 } 5472 5473 /* 5474 * Delay the delegation timeout as far as ls_delegtimelimit, as required. 5475 */ 5476 static void 5477 nfsrv_delaydelegtimeout(struct nfsstate *stp) 5478 { 5479 5480 if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0) 5481 return; 5482 5483 if ((stp->ls_delegtime + 15) > NFSD_MONOSEC && 5484 stp->ls_delegtime < stp->ls_delegtimelimit) { 5485 stp->ls_delegtime += nfsrv_lease; 5486 if (stp->ls_delegtime > stp->ls_delegtimelimit) 5487 stp->ls_delegtime = stp->ls_delegtimelimit; 5488 } 5489 } 5490 5491 /* 5492 * This function checks to see if there is any other state associated 5493 * with the openowner for this Open. 5494 * It returns 1 if there is no other state, 0 otherwise. 5495 */ 5496 static int 5497 nfsrv_nootherstate(struct nfsstate *stp) 5498 { 5499 struct nfsstate *tstp; 5500 5501 LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) { 5502 if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock)) 5503 return (0); 5504 } 5505 return (1); 5506 } 5507 5508 /* 5509 * Create a list of lock deltas (changes to local byte range locking 5510 * that can be rolled back using the list) and apply the changes via 5511 * nfsvno_advlock(). Optionally, lock the list. It is expected that either 5512 * the rollback or update function will be called after this. 5513 * It returns an error (and rolls back, as required), if any nfsvno_advlock() 5514 * call fails. If it returns an error, it will unlock the list. 5515 */ 5516 static int 5517 nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, 5518 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5519 { 5520 struct nfslock *lop, *nlop; 5521 int error = 0; 5522 5523 /* Loop through the list of locks. */ 5524 lop = LIST_FIRST(&lfp->lf_locallock); 5525 while (first < end && lop != NULL) { 5526 nlop = LIST_NEXT(lop, lo_lckowner); 5527 if (first >= lop->lo_end) { 5528 /* not there yet */ 5529 lop = nlop; 5530 } else if (first < lop->lo_first) { 5531 /* new one starts before entry in list */ 5532 if (end <= lop->lo_first) { 5533 /* no overlap between old and new */ 5534 error = nfsrv_dolocal(vp, lfp, flags, 5535 NFSLCK_UNLOCK, first, end, cfp, p); 5536 if (error != 0) 5537 break; 5538 first = end; 5539 } else { 5540 /* handle fragment overlapped with new one */ 5541 error = nfsrv_dolocal(vp, lfp, flags, 5542 NFSLCK_UNLOCK, first, lop->lo_first, cfp, 5543 p); 5544 if (error != 0) 5545 break; 5546 first = lop->lo_first; 5547 } 5548 } else { 5549 /* new one overlaps this entry in list */ 5550 if (end <= lop->lo_end) { 5551 /* overlaps all of new one */ 5552 error = nfsrv_dolocal(vp, lfp, flags, 5553 lop->lo_flags, first, end, cfp, p); 5554 if (error != 0) 5555 break; 5556 first = end; 5557 } else { 5558 /* handle fragment overlapped with new one */ 5559 error = nfsrv_dolocal(vp, lfp, flags, 5560 lop->lo_flags, first, lop->lo_end, cfp, p); 5561 if (error != 0) 5562 break; 5563 first = lop->lo_end; 5564 lop = nlop; 5565 } 5566 } 5567 } 5568 if (first < end && error == 0) 5569 /* handle fragment past end of list */ 5570 error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first, 5571 end, cfp, p); 5572 5573 NFSEXITCODE(error); 5574 return (error); 5575 } 5576 5577 /* 5578 * Local lock unlock. Unlock all byte ranges that are no longer locked 5579 * by NFSv4. To do this, unlock any subranges of first-->end that 5580 * do not overlap with the byte ranges of any lock in the lfp->lf_lock 5581 * list. This list has all locks for the file held by other 5582 * <clientid, lockowner> tuples. The list is ordered by increasing 5583 * lo_first value, but may have entries that overlap each other, for 5584 * the case of read locks. 5585 */ 5586 static void 5587 nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first, 5588 uint64_t init_end, NFSPROC_T *p) 5589 { 5590 struct nfslock *lop; 5591 uint64_t first, end, prevfirst; 5592 5593 first = init_first; 5594 end = init_end; 5595 while (first < init_end) { 5596 /* Loop through all nfs locks, adjusting first and end */ 5597 prevfirst = 0; 5598 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { 5599 KASSERT(prevfirst <= lop->lo_first, 5600 ("nfsv4 locks out of order")); 5601 KASSERT(lop->lo_first < lop->lo_end, 5602 ("nfsv4 bogus lock")); 5603 prevfirst = lop->lo_first; 5604 if (first >= lop->lo_first && 5605 first < lop->lo_end) 5606 /* 5607 * Overlaps with initial part, so trim 5608 * off that initial part by moving first past 5609 * it. 5610 */ 5611 first = lop->lo_end; 5612 else if (end > lop->lo_first && 5613 lop->lo_first > first) { 5614 /* 5615 * This lock defines the end of the 5616 * segment to unlock, so set end to the 5617 * start of it and break out of the loop. 5618 */ 5619 end = lop->lo_first; 5620 break; 5621 } 5622 if (first >= end) 5623 /* 5624 * There is no segment left to do, so 5625 * break out of this loop and then exit 5626 * the outer while() since first will be set 5627 * to end, which must equal init_end here. 5628 */ 5629 break; 5630 } 5631 if (first < end) { 5632 /* Unlock this segment */ 5633 (void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK, 5634 NFSLCK_READ, first, end, NULL, p); 5635 nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK, 5636 first, end); 5637 } 5638 /* 5639 * Now move past this segment and look for any further 5640 * segment in the range, if there is one. 5641 */ 5642 first = end; 5643 end = init_end; 5644 } 5645 } 5646 5647 /* 5648 * Do the local lock operation and update the rollback list, as required. 5649 * Perform the rollback and return the error if nfsvno_advlock() fails. 5650 */ 5651 static int 5652 nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags, 5653 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5654 { 5655 struct nfsrollback *rlp; 5656 int error = 0, ltype, oldltype; 5657 5658 if (flags & NFSLCK_WRITE) 5659 ltype = F_WRLCK; 5660 else if (flags & NFSLCK_READ) 5661 ltype = F_RDLCK; 5662 else 5663 ltype = F_UNLCK; 5664 if (oldflags & NFSLCK_WRITE) 5665 oldltype = F_WRLCK; 5666 else if (oldflags & NFSLCK_READ) 5667 oldltype = F_RDLCK; 5668 else 5669 oldltype = F_UNLCK; 5670 if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK)) 5671 /* nothing to do */ 5672 goto out; 5673 error = nfsvno_advlock(vp, ltype, first, end, p); 5674 if (error != 0) { 5675 if (cfp != NULL) { 5676 cfp->cl_clientid.lval[0] = 0; 5677 cfp->cl_clientid.lval[1] = 0; 5678 cfp->cl_first = 0; 5679 cfp->cl_end = NFS64BITSSET; 5680 cfp->cl_flags = NFSLCK_WRITE; 5681 cfp->cl_ownerlen = 5; 5682 NFSBCOPY("LOCAL", cfp->cl_owner, 5); 5683 } 5684 nfsrv_locallock_rollback(vp, lfp, p); 5685 } else if (ltype != F_UNLCK) { 5686 rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK, 5687 M_WAITOK); 5688 rlp->rlck_first = first; 5689 rlp->rlck_end = end; 5690 rlp->rlck_type = oldltype; 5691 LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list); 5692 } 5693 5694 out: 5695 NFSEXITCODE(error); 5696 return (error); 5697 } 5698 5699 /* 5700 * Roll back local lock changes and free up the rollback list. 5701 */ 5702 static void 5703 nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p) 5704 { 5705 struct nfsrollback *rlp, *nrlp; 5706 5707 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) { 5708 (void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first, 5709 rlp->rlck_end, p); 5710 free(rlp, M_NFSDROLLBACK); 5711 } 5712 LIST_INIT(&lfp->lf_rollback); 5713 } 5714 5715 /* 5716 * Update local lock list and delete rollback list (ie now committed to the 5717 * local locks). Most of the work is done by the internal function. 5718 */ 5719 static void 5720 nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first, 5721 uint64_t end) 5722 { 5723 struct nfsrollback *rlp, *nrlp; 5724 struct nfslock *new_lop, *other_lop; 5725 5726 new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK); 5727 if (flags & (NFSLCK_READ | NFSLCK_WRITE)) 5728 other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, 5729 M_WAITOK); 5730 else 5731 other_lop = NULL; 5732 new_lop->lo_flags = flags; 5733 new_lop->lo_first = first; 5734 new_lop->lo_end = end; 5735 nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp); 5736 if (new_lop != NULL) 5737 free(new_lop, M_NFSDLOCK); 5738 if (other_lop != NULL) 5739 free(other_lop, M_NFSDLOCK); 5740 5741 /* and get rid of the rollback list */ 5742 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) 5743 free(rlp, M_NFSDROLLBACK); 5744 LIST_INIT(&lfp->lf_rollback); 5745 } 5746 5747 /* 5748 * Lock the struct nfslockfile for local lock updating. 5749 */ 5750 static void 5751 nfsrv_locklf(struct nfslockfile *lfp) 5752 { 5753 int gotlock; 5754 5755 /* lf_usecount ensures *lfp won't be free'd */ 5756 lfp->lf_usecount++; 5757 do { 5758 gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL, 5759 NFSSTATEMUTEXPTR, NULL); 5760 } while (gotlock == 0); 5761 lfp->lf_usecount--; 5762 } 5763 5764 /* 5765 * Unlock the struct nfslockfile after local lock updating. 5766 */ 5767 static void 5768 nfsrv_unlocklf(struct nfslockfile *lfp) 5769 { 5770 5771 nfsv4_unlock(&lfp->lf_locallock_lck, 0); 5772 } 5773 5774 /* 5775 * Clear out all state for the NFSv4 server. 5776 * Must be called by a thread that can sleep when no nfsds are running. 5777 */ 5778 void 5779 nfsrv_throwawayallstate(NFSPROC_T *p) 5780 { 5781 struct nfsclient *clp, *nclp; 5782 struct nfslockfile *lfp, *nlfp; 5783 int i; 5784 5785 /* 5786 * For each client, clean out the state and then free the structure. 5787 */ 5788 for (i = 0; i < nfsrv_clienthashsize; i++) { 5789 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 5790 nfsrv_cleanclient(clp, p); 5791 nfsrv_freedeleglist(&clp->lc_deleg); 5792 nfsrv_freedeleglist(&clp->lc_olddeleg); 5793 free(clp->lc_stateid, M_NFSDCLIENT); 5794 free(clp, M_NFSDCLIENT); 5795 } 5796 } 5797 5798 /* 5799 * Also, free up any remaining lock file structures. 5800 */ 5801 for (i = 0; i < nfsrv_lockhashsize; i++) { 5802 LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) 5803 nfsrv_freenfslockfile(lfp); 5804 } 5805 } 5806 5807 /* 5808 * Check the sequence# for the session and slot provided as an argument. 5809 * Also, renew the lease if the session will return NFS_OK. 5810 */ 5811 int 5812 nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid, 5813 uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this, 5814 uint32_t *sflagsp, NFSPROC_T *p) 5815 { 5816 struct nfsdsession *sep; 5817 struct nfssessionhash *shp; 5818 int error; 5819 SVCXPRT *savxprt; 5820 5821 shp = NFSSESSIONHASH(nd->nd_sessionid); 5822 NFSLOCKSESSION(shp); 5823 sep = nfsrv_findsession(nd->nd_sessionid); 5824 if (sep == NULL) { 5825 NFSUNLOCKSESSION(shp); 5826 return (NFSERR_BADSESSION); 5827 } 5828 error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp, 5829 sep->sess_slots, NULL, NFSV4_SLOTS - 1); 5830 if (error != 0) { 5831 NFSUNLOCKSESSION(shp); 5832 return (error); 5833 } 5834 if (cache_this != 0) 5835 nd->nd_flag |= ND_SAVEREPLY; 5836 /* Renew the lease. */ 5837 sep->sess_clp->lc_expiry = nfsrv_leaseexpiry(); 5838 nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval; 5839 nd->nd_flag |= ND_IMPLIEDCLID; 5840 5841 /* 5842 * If this session handles the backchannel, save the nd_xprt for this 5843 * RPC, since this is the one being used. 5844 */ 5845 if (sep->sess_clp->lc_req.nr_client != NULL && 5846 (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) { 5847 savxprt = sep->sess_cbsess.nfsess_xprt; 5848 SVC_ACQUIRE(nd->nd_xprt); 5849 nd->nd_xprt->xp_p2 = 5850 sep->sess_clp->lc_req.nr_client->cl_private; 5851 nd->nd_xprt->xp_idletimeout = 0; /* Disable timeout. */ 5852 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt; 5853 if (savxprt != NULL) 5854 SVC_RELEASE(savxprt); 5855 } 5856 5857 *sflagsp = 0; 5858 if (sep->sess_clp->lc_req.nr_client == NULL) 5859 *sflagsp |= NFSV4SEQ_CBPATHDOWN; 5860 NFSUNLOCKSESSION(shp); 5861 if (error == NFSERR_EXPIRED) { 5862 *sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED; 5863 error = 0; 5864 } else if (error == NFSERR_ADMINREVOKED) { 5865 *sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED; 5866 error = 0; 5867 } 5868 *highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1; 5869 return (0); 5870 } 5871 5872 /* 5873 * Check/set reclaim complete for this session/clientid. 5874 */ 5875 int 5876 nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd) 5877 { 5878 struct nfsdsession *sep; 5879 struct nfssessionhash *shp; 5880 int error = 0; 5881 5882 shp = NFSSESSIONHASH(nd->nd_sessionid); 5883 NFSLOCKSTATE(); 5884 NFSLOCKSESSION(shp); 5885 sep = nfsrv_findsession(nd->nd_sessionid); 5886 if (sep == NULL) { 5887 NFSUNLOCKSESSION(shp); 5888 NFSUNLOCKSTATE(); 5889 return (NFSERR_BADSESSION); 5890 } 5891 5892 /* Check to see if reclaim complete has already happened. */ 5893 if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) 5894 error = NFSERR_COMPLETEALREADY; 5895 else 5896 sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE; 5897 NFSUNLOCKSESSION(shp); 5898 NFSUNLOCKSTATE(); 5899 return (error); 5900 } 5901 5902 /* 5903 * Cache the reply in a session slot. 5904 */ 5905 void 5906 nfsrv_cache_session(uint8_t *sessionid, uint32_t slotid, int repstat, 5907 struct mbuf **m) 5908 { 5909 struct nfsdsession *sep; 5910 struct nfssessionhash *shp; 5911 5912 shp = NFSSESSIONHASH(sessionid); 5913 NFSLOCKSESSION(shp); 5914 sep = nfsrv_findsession(sessionid); 5915 if (sep == NULL) { 5916 NFSUNLOCKSESSION(shp); 5917 printf("nfsrv_cache_session: no session\n"); 5918 m_freem(*m); 5919 return; 5920 } 5921 nfsv4_seqsess_cacherep(slotid, sep->sess_slots, repstat, m); 5922 NFSUNLOCKSESSION(shp); 5923 } 5924 5925 /* 5926 * Search for a session that matches the sessionid. 5927 */ 5928 static struct nfsdsession * 5929 nfsrv_findsession(uint8_t *sessionid) 5930 { 5931 struct nfsdsession *sep; 5932 struct nfssessionhash *shp; 5933 5934 shp = NFSSESSIONHASH(sessionid); 5935 LIST_FOREACH(sep, &shp->list, sess_hash) { 5936 if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID)) 5937 break; 5938 } 5939 return (sep); 5940 } 5941 5942 /* 5943 * Destroy a session. 5944 */ 5945 int 5946 nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid) 5947 { 5948 int error, samesess; 5949 5950 samesess = 0; 5951 if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID)) { 5952 samesess = 1; 5953 if ((nd->nd_flag & ND_LASTOP) == 0) 5954 return (NFSERR_BADSESSION); 5955 } 5956 error = nfsrv_freesession(NULL, sessionid); 5957 if (error == 0 && samesess != 0) 5958 nd->nd_flag &= ~ND_HASSEQUENCE; 5959 return (error); 5960 } 5961 5962 /* 5963 * Free up a session structure. 5964 */ 5965 static int 5966 nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid) 5967 { 5968 struct nfssessionhash *shp; 5969 int i; 5970 5971 NFSLOCKSTATE(); 5972 if (sep == NULL) { 5973 shp = NFSSESSIONHASH(sessionid); 5974 NFSLOCKSESSION(shp); 5975 sep = nfsrv_findsession(sessionid); 5976 } else { 5977 shp = NFSSESSIONHASH(sep->sess_sessionid); 5978 NFSLOCKSESSION(shp); 5979 } 5980 if (sep != NULL) { 5981 sep->sess_refcnt--; 5982 if (sep->sess_refcnt > 0) { 5983 NFSUNLOCKSESSION(shp); 5984 NFSUNLOCKSTATE(); 5985 return (0); 5986 } 5987 LIST_REMOVE(sep, sess_hash); 5988 LIST_REMOVE(sep, sess_list); 5989 } 5990 NFSUNLOCKSESSION(shp); 5991 NFSUNLOCKSTATE(); 5992 if (sep == NULL) 5993 return (NFSERR_BADSESSION); 5994 for (i = 0; i < NFSV4_SLOTS; i++) 5995 if (sep->sess_slots[i].nfssl_reply != NULL) 5996 m_freem(sep->sess_slots[i].nfssl_reply); 5997 if (sep->sess_cbsess.nfsess_xprt != NULL) 5998 SVC_RELEASE(sep->sess_cbsess.nfsess_xprt); 5999 free(sep, M_NFSDSESSION); 6000 return (0); 6001 } 6002 6003 /* 6004 * Free a stateid. 6005 * RFC5661 says that it should fail when there are associated opens, locks 6006 * or delegations. Since stateids represent opens, I don't see how you can 6007 * free an open stateid (it will be free'd when closed), so this function 6008 * only works for lock stateids (freeing the lock_owner) or delegations. 6009 */ 6010 int 6011 nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, 6012 NFSPROC_T *p) 6013 { 6014 struct nfsclient *clp; 6015 struct nfsstate *stp; 6016 int error; 6017 6018 NFSLOCKSTATE(); 6019 /* 6020 * Look up the stateid 6021 */ 6022 error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp, 6023 NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); 6024 if (error == 0) { 6025 /* First, check for a delegation. */ 6026 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) { 6027 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other, 6028 NFSX_STATEIDOTHER)) 6029 break; 6030 } 6031 if (stp != NULL) { 6032 nfsrv_freedeleg(stp); 6033 NFSUNLOCKSTATE(); 6034 return (error); 6035 } 6036 } 6037 /* Not a delegation, try for a lock_owner. */ 6038 if (error == 0) 6039 error = nfsrv_getstate(clp, stateidp, 0, &stp); 6040 if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD | 6041 NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0)) 6042 /* Not a lock_owner stateid. */ 6043 error = NFSERR_LOCKSHELD; 6044 if (error == 0 && !LIST_EMPTY(&stp->ls_lock)) 6045 error = NFSERR_LOCKSHELD; 6046 if (error == 0) 6047 nfsrv_freelockowner(stp, NULL, 0, p); 6048 NFSUNLOCKSTATE(); 6049 return (error); 6050 } 6051 6052 /* 6053 * Generate the xdr for an NFSv4.1 CBSequence Operation. 6054 */ 6055 static int 6056 nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp, 6057 int dont_replycache, struct nfsdsession **sepp) 6058 { 6059 struct nfsdsession *sep; 6060 uint32_t *tl, slotseq = 0; 6061 int maxslot, slotpos; 6062 uint8_t sessionid[NFSX_V4SESSIONID]; 6063 int error; 6064 6065 error = nfsv4_getcbsession(clp, sepp); 6066 if (error != 0) 6067 return (error); 6068 sep = *sepp; 6069 (void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot, 6070 &slotseq, sessionid); 6071 KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot")); 6072 6073 /* Build the Sequence arguments. */ 6074 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED); 6075 bcopy(sessionid, tl, NFSX_V4SESSIONID); 6076 tl += NFSX_V4SESSIONID / NFSX_UNSIGNED; 6077 nd->nd_slotseq = tl; 6078 *tl++ = txdr_unsigned(slotseq); 6079 *tl++ = txdr_unsigned(slotpos); 6080 *tl++ = txdr_unsigned(maxslot); 6081 if (dont_replycache == 0) 6082 *tl++ = newnfs_true; 6083 else 6084 *tl++ = newnfs_false; 6085 *tl = 0; /* No referring call list, for now. */ 6086 nd->nd_flag |= ND_HASSEQUENCE; 6087 return (0); 6088 } 6089 6090 /* 6091 * Get a session for the callback. 6092 */ 6093 static int 6094 nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp) 6095 { 6096 struct nfsdsession *sep; 6097 6098 NFSLOCKSTATE(); 6099 LIST_FOREACH(sep, &clp->lc_session, sess_list) { 6100 if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) 6101 break; 6102 } 6103 if (sep == NULL) { 6104 NFSUNLOCKSTATE(); 6105 return (NFSERR_BADSESSION); 6106 } 6107 sep->sess_refcnt++; 6108 *sepp = sep; 6109 NFSUNLOCKSTATE(); 6110 return (0); 6111 } 6112 6113 /* 6114 * Free up all backchannel xprts. This needs to be done when the nfsd threads 6115 * exit, since those transports will all be going away. 6116 * This is only called after all the nfsd threads are done performing RPCs, 6117 * so locking shouldn't be an issue. 6118 */ 6119 APPLESTATIC void 6120 nfsrv_freeallbackchannel_xprts(void) 6121 { 6122 struct nfsdsession *sep; 6123 struct nfsclient *clp; 6124 SVCXPRT *xprt; 6125 int i; 6126 6127 for (i = 0; i < nfsrv_clienthashsize; i++) { 6128 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 6129 LIST_FOREACH(sep, &clp->lc_session, sess_list) { 6130 xprt = sep->sess_cbsess.nfsess_xprt; 6131 sep->sess_cbsess.nfsess_xprt = NULL; 6132 if (xprt != NULL) 6133 SVC_RELEASE(xprt); 6134 } 6135 } 6136 } 6137 } 6138 6139