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