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 int gotstate = 0, len = 0; 2505 u_char *clidp = NULL; 2506 2507 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 2508 readonly = 1; 2509 /* 2510 * Check for restart conditions (client and server). 2511 * (Paranoia, should have been detected by nfsrv_opencheck().) 2512 * If an error does show up, return NFSERR_EXPIRED, since the 2513 * the seqid# has already been incremented. 2514 */ 2515 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2516 &new_stp->ls_stateid, 0); 2517 if (error) { 2518 printf("Nfsd: openctrl unexpected restart err=%d\n", 2519 error); 2520 error = NFSERR_EXPIRED; 2521 goto out; 2522 } 2523 2524 clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK); 2525 tryagain: 2526 MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile), 2527 M_NFSDLOCKFILE, M_WAITOK); 2528 MALLOC(new_open, struct nfsstate *, sizeof (struct nfsstate), 2529 M_NFSDSTATE, M_WAITOK); 2530 MALLOC(new_deleg, struct nfsstate *, sizeof (struct nfsstate), 2531 M_NFSDSTATE, M_WAITOK); 2532 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp, 2533 NULL, p); 2534 NFSLOCKSTATE(); 2535 /* 2536 * Get the client structure. Since the linked lists could be changed 2537 * by other nfsd processes if this process does a tsleep(), one of 2538 * two things must be done. 2539 * 1 - don't tsleep() 2540 * or 2541 * 2 - get the nfsv4_lock() { indicated by haslock == 1 } 2542 * before using the lists, since this lock stops the other 2543 * nfsd. This should only be used for rare cases, since it 2544 * essentially single threads the nfsd. 2545 * At this time, it is only done for cases where the stable 2546 * storage file must be written prior to completion of state 2547 * expiration. 2548 */ 2549 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 2550 (nfsquad_t)((u_quad_t)0), 0, nd, p); 2551 if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) && 2552 clp->lc_program) { 2553 /* 2554 * This happens on the first open for a client 2555 * that supports callbacks. 2556 */ 2557 NFSUNLOCKSTATE(); 2558 /* 2559 * Although nfsrv_docallback() will sleep, clp won't 2560 * go away, since they are only removed when the 2561 * nfsv4_lock() has blocked the nfsd threads. The 2562 * fields in clp can change, but having multiple 2563 * threads do this Null callback RPC should be 2564 * harmless. 2565 */ 2566 cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL, 2567 NULL, 0, NULL, NULL, NULL, p); 2568 NFSLOCKSTATE(); 2569 clp->lc_flags &= ~LCL_NEEDSCBNULL; 2570 if (!cbret) 2571 clp->lc_flags |= LCL_CALLBACKSON; 2572 } 2573 2574 /* 2575 * Look up the open owner. See if it needs confirmation and 2576 * check the seq#, as required. 2577 */ 2578 if (!error) 2579 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp); 2580 2581 if (error) { 2582 NFSUNLOCKSTATE(); 2583 printf("Nfsd: openctrl unexpected state err=%d\n", 2584 error); 2585 free((caddr_t)new_lfp, M_NFSDLOCKFILE); 2586 free((caddr_t)new_open, M_NFSDSTATE); 2587 free((caddr_t)new_deleg, M_NFSDSTATE); 2588 if (haslock) { 2589 NFSLOCKV4ROOTMUTEX(); 2590 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2591 NFSUNLOCKV4ROOTMUTEX(); 2592 } 2593 error = NFSERR_EXPIRED; 2594 goto out; 2595 } 2596 2597 if (new_stp->ls_flags & NFSLCK_RECLAIM) 2598 nfsrv_markstable(clp); 2599 2600 /* 2601 * Get the structure for the underlying file. 2602 */ 2603 if (getfhret) 2604 error = getfhret; 2605 else 2606 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, 2607 NULL, 0); 2608 if (new_lfp) 2609 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE); 2610 if (error) { 2611 NFSUNLOCKSTATE(); 2612 printf("Nfsd openctrl unexpected getlockfile err=%d\n", 2613 error); 2614 free((caddr_t)new_open, M_NFSDSTATE); 2615 free((caddr_t)new_deleg, M_NFSDSTATE); 2616 if (haslock) { 2617 NFSLOCKV4ROOTMUTEX(); 2618 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2619 NFSUNLOCKV4ROOTMUTEX(); 2620 } 2621 goto out; 2622 } 2623 2624 /* 2625 * Search for a conflicting open/share. 2626 */ 2627 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2628 /* 2629 * For Delegate_Cur, search for the matching Delegation, 2630 * which indicates no conflict. 2631 * An old delegation should have been recovered by the 2632 * client doing a Claim_DELEGATE_Prev, so I won't let 2633 * it match and return NFSERR_EXPIRED. Should I let it 2634 * match? 2635 */ 2636 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2637 if (!(stp->ls_flags & NFSLCK_OLDDELEG) && 2638 (((nd->nd_flag & ND_NFSV41) != 0 && 2639 stateidp->seqid == 0) || 2640 stateidp->seqid == stp->ls_stateid.seqid) && 2641 !NFSBCMP(stateidp->other, stp->ls_stateid.other, 2642 NFSX_STATEIDOTHER)) 2643 break; 2644 } 2645 if (stp == LIST_END(&lfp->lf_deleg) || 2646 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) && 2647 (stp->ls_flags & NFSLCK_DELEGREAD))) { 2648 NFSUNLOCKSTATE(); 2649 printf("Nfsd openctrl unexpected expiry\n"); 2650 free((caddr_t)new_open, M_NFSDSTATE); 2651 free((caddr_t)new_deleg, M_NFSDSTATE); 2652 if (haslock) { 2653 NFSLOCKV4ROOTMUTEX(); 2654 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2655 NFSUNLOCKV4ROOTMUTEX(); 2656 } 2657 error = NFSERR_EXPIRED; 2658 goto out; 2659 } 2660 2661 /* 2662 * Don't issue a Delegation, since one already exists and 2663 * delay delegation timeout, as required. 2664 */ 2665 delegate = 0; 2666 nfsrv_delaydelegtimeout(stp); 2667 } 2668 2669 /* 2670 * Check for access/deny bit conflicts. I also check for the 2671 * same owner, since the client might not have bothered to check. 2672 * Also, note an open for the same file and owner, if found, 2673 * which is all we do here for Delegate_Cur, since conflict 2674 * checking is already done. 2675 */ 2676 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 2677 if (ownerstp && stp->ls_openowner == ownerstp) 2678 openstp = stp; 2679 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) { 2680 /* 2681 * If another client has the file open, the only 2682 * delegation that can be issued is a Read delegation 2683 * and only if it is a Read open with Deny none. 2684 */ 2685 if (clp != stp->ls_clp) { 2686 if ((stp->ls_flags & NFSLCK_SHAREBITS) == 2687 NFSLCK_READACCESS) 2688 writedeleg = 0; 2689 else 2690 delegate = 0; 2691 } 2692 if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) & 2693 ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))|| 2694 ((stp->ls_flags & NFSLCK_ACCESSBITS) & 2695 ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){ 2696 ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p); 2697 if (ret == 1) { 2698 /* 2699 * nfsrv_clientconflict() unlocks state 2700 * when it returns non-zero. 2701 */ 2702 free((caddr_t)new_open, M_NFSDSTATE); 2703 free((caddr_t)new_deleg, M_NFSDSTATE); 2704 openstp = NULL; 2705 goto tryagain; 2706 } 2707 if (ret == 2) 2708 error = NFSERR_PERM; 2709 else if (new_stp->ls_flags & NFSLCK_RECLAIM) 2710 error = NFSERR_RECLAIMCONFLICT; 2711 else 2712 error = NFSERR_SHAREDENIED; 2713 if (ret == 0) 2714 NFSUNLOCKSTATE(); 2715 if (haslock) { 2716 NFSLOCKV4ROOTMUTEX(); 2717 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2718 NFSUNLOCKV4ROOTMUTEX(); 2719 } 2720 free((caddr_t)new_open, M_NFSDSTATE); 2721 free((caddr_t)new_deleg, M_NFSDSTATE); 2722 printf("nfsd openctrl unexpected client cnfl\n"); 2723 goto out; 2724 } 2725 } 2726 } 2727 2728 /* 2729 * Check for a conflicting delegation. If one is found, call 2730 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2731 * been set yet, it will get the lock. Otherwise, it will recall 2732 * the delegation. Then, we try try again... 2733 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there 2734 * isn't a conflict.) 2735 * I currently believe the conflict algorithm to be: 2736 * For Open with Read Access and Deny None 2737 * - there is a conflict iff a different client has a write delegation 2738 * For Open with other Write Access or any Deny except None 2739 * - there is a conflict if a different client has any delegation 2740 * - there is a conflict if the same client has a read delegation 2741 * (The current consensus is that this last case should be 2742 * considered a conflict since the client with a read delegation 2743 * could have done an Open with ReadAccess and WriteDeny 2744 * locally and then not have checked for the WriteDeny.) 2745 */ 2746 if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) { 2747 stp = LIST_FIRST(&lfp->lf_deleg); 2748 while (stp != LIST_END(&lfp->lf_deleg)) { 2749 nstp = LIST_NEXT(stp, ls_file); 2750 if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD)) 2751 writedeleg = 0; 2752 else 2753 delegate = 0; 2754 if ((readonly && stp->ls_clp != clp && 2755 (stp->ls_flags & NFSLCK_DELEGWRITE)) || 2756 (!readonly && (stp->ls_clp != clp || 2757 (stp->ls_flags & NFSLCK_DELEGREAD)))) { 2758 if (new_stp->ls_flags & NFSLCK_RECLAIM) { 2759 delegate = 2; 2760 } else { 2761 ret = nfsrv_delegconflict(stp, &haslock, p, vp); 2762 if (ret) { 2763 /* 2764 * nfsrv_delegconflict() unlocks state 2765 * when it returns non-zero. 2766 */ 2767 printf("Nfsd openctrl unexpected deleg cnfl\n"); 2768 free((caddr_t)new_open, M_NFSDSTATE); 2769 free((caddr_t)new_deleg, M_NFSDSTATE); 2770 if (ret == -1) { 2771 openstp = NULL; 2772 goto tryagain; 2773 } 2774 error = ret; 2775 goto out; 2776 } 2777 } 2778 } 2779 stp = nstp; 2780 } 2781 } 2782 2783 /* 2784 * We only get here if there was no open that conflicted. 2785 * If an open for the owner exists, or in the access/deny bits. 2786 * Otherwise it is a new open. If the open_owner hasn't been 2787 * confirmed, replace the open with the new one needing confirmation, 2788 * otherwise add the open. 2789 */ 2790 if (new_stp->ls_flags & NFSLCK_DELEGPREV) { 2791 /* 2792 * Handle NFSLCK_DELEGPREV by searching the old delegations for 2793 * a match. If found, just move the old delegation to the current 2794 * delegation list and issue open. If not found, return 2795 * NFSERR_EXPIRED. 2796 */ 2797 LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) { 2798 if (stp->ls_lfp == lfp) { 2799 /* Found it */ 2800 if (stp->ls_clp != clp) 2801 panic("olddeleg clp"); 2802 LIST_REMOVE(stp, ls_list); 2803 LIST_REMOVE(stp, ls_hash); 2804 stp->ls_flags &= ~NFSLCK_OLDDELEG; 2805 stp->ls_stateid.seqid = delegstateidp->seqid = 1; 2806 stp->ls_stateid.other[0] = delegstateidp->other[0] = 2807 clp->lc_clientid.lval[0]; 2808 stp->ls_stateid.other[1] = delegstateidp->other[1] = 2809 clp->lc_clientid.lval[1]; 2810 stp->ls_stateid.other[2] = delegstateidp->other[2] = 2811 nfsrv_nextstateindex(clp); 2812 stp->ls_compref = nd->nd_compref; 2813 LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list); 2814 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2815 stp->ls_stateid), stp, ls_hash); 2816 if (stp->ls_flags & NFSLCK_DELEGWRITE) 2817 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2818 else 2819 *rflagsp |= NFSV4OPEN_READDELEGATE; 2820 clp->lc_delegtime = NFSD_MONOSEC + 2821 nfsrv_lease + NFSRV_LEASEDELTA; 2822 2823 /* 2824 * Now, do the associated open. 2825 */ 2826 new_open->ls_stateid.seqid = 1; 2827 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2828 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2829 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2830 new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)| 2831 NFSLCK_OPEN; 2832 if (stp->ls_flags & NFSLCK_DELEGWRITE) 2833 new_open->ls_flags |= (NFSLCK_READACCESS | 2834 NFSLCK_WRITEACCESS); 2835 else 2836 new_open->ls_flags |= NFSLCK_READACCESS; 2837 new_open->ls_uid = new_stp->ls_uid; 2838 new_open->ls_lfp = lfp; 2839 new_open->ls_clp = clp; 2840 LIST_INIT(&new_open->ls_open); 2841 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2842 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2843 new_open, ls_hash); 2844 /* 2845 * and handle the open owner 2846 */ 2847 if (ownerstp) { 2848 new_open->ls_openowner = ownerstp; 2849 LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list); 2850 } else { 2851 new_open->ls_openowner = new_stp; 2852 new_stp->ls_flags = 0; 2853 nfsrvd_refcache(new_stp->ls_op); 2854 new_stp->ls_noopens = 0; 2855 LIST_INIT(&new_stp->ls_open); 2856 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 2857 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 2858 *new_stpp = NULL; 2859 nfsstatsv1.srvopenowners++; 2860 nfsrv_openpluslock++; 2861 } 2862 openstp = new_open; 2863 new_open = NULL; 2864 nfsstatsv1.srvopens++; 2865 nfsrv_openpluslock++; 2866 break; 2867 } 2868 } 2869 if (stp == LIST_END(&clp->lc_olddeleg)) 2870 error = NFSERR_EXPIRED; 2871 } else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { 2872 /* 2873 * Scan to see that no delegation for this client and file 2874 * doesn't already exist. 2875 * There also shouldn't yet be an Open for this file and 2876 * openowner. 2877 */ 2878 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2879 if (stp->ls_clp == clp) 2880 break; 2881 } 2882 if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) { 2883 /* 2884 * This is the Claim_Previous case with a delegation 2885 * type != Delegate_None. 2886 */ 2887 /* 2888 * First, add the delegation. (Although we must issue the 2889 * delegation, we can also ask for an immediate return.) 2890 */ 2891 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 2892 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] = 2893 clp->lc_clientid.lval[0]; 2894 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] = 2895 clp->lc_clientid.lval[1]; 2896 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] = 2897 nfsrv_nextstateindex(clp); 2898 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) { 2899 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 2900 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 2901 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2902 } else { 2903 new_deleg->ls_flags = (NFSLCK_DELEGREAD | 2904 NFSLCK_READACCESS); 2905 *rflagsp |= NFSV4OPEN_READDELEGATE; 2906 } 2907 new_deleg->ls_uid = new_stp->ls_uid; 2908 new_deleg->ls_lfp = lfp; 2909 new_deleg->ls_clp = clp; 2910 new_deleg->ls_filerev = filerev; 2911 new_deleg->ls_compref = nd->nd_compref; 2912 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 2913 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2914 new_deleg->ls_stateid), new_deleg, ls_hash); 2915 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 2916 new_deleg = NULL; 2917 if (delegate == 2 || nfsrv_issuedelegs == 0 || 2918 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 2919 LCL_CALLBACKSON || 2920 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) || 2921 !NFSVNO_DELEGOK(vp)) 2922 *rflagsp |= NFSV4OPEN_RECALL; 2923 nfsstatsv1.srvdelegates++; 2924 nfsrv_openpluslock++; 2925 nfsrv_delegatecnt++; 2926 2927 /* 2928 * Now, do the associated open. 2929 */ 2930 new_open->ls_stateid.seqid = 1; 2931 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2932 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2933 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2934 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) | 2935 NFSLCK_OPEN; 2936 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) 2937 new_open->ls_flags |= (NFSLCK_READACCESS | 2938 NFSLCK_WRITEACCESS); 2939 else 2940 new_open->ls_flags |= NFSLCK_READACCESS; 2941 new_open->ls_uid = new_stp->ls_uid; 2942 new_open->ls_lfp = lfp; 2943 new_open->ls_clp = clp; 2944 LIST_INIT(&new_open->ls_open); 2945 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2946 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2947 new_open, ls_hash); 2948 /* 2949 * and handle the open owner 2950 */ 2951 if (ownerstp) { 2952 new_open->ls_openowner = ownerstp; 2953 LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); 2954 } else { 2955 new_open->ls_openowner = new_stp; 2956 new_stp->ls_flags = 0; 2957 nfsrvd_refcache(new_stp->ls_op); 2958 new_stp->ls_noopens = 0; 2959 LIST_INIT(&new_stp->ls_open); 2960 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 2961 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 2962 *new_stpp = NULL; 2963 nfsstatsv1.srvopenowners++; 2964 nfsrv_openpluslock++; 2965 } 2966 openstp = new_open; 2967 new_open = NULL; 2968 nfsstatsv1.srvopens++; 2969 nfsrv_openpluslock++; 2970 } else { 2971 error = NFSERR_RECLAIMCONFLICT; 2972 } 2973 } else if (ownerstp) { 2974 if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) { 2975 /* Replace the open */ 2976 if (ownerstp->ls_op) 2977 nfsrvd_derefcache(ownerstp->ls_op); 2978 ownerstp->ls_op = new_stp->ls_op; 2979 nfsrvd_refcache(ownerstp->ls_op); 2980 ownerstp->ls_seq = new_stp->ls_seq; 2981 *rflagsp |= NFSV4OPEN_RESULTCONFIRM; 2982 stp = LIST_FIRST(&ownerstp->ls_open); 2983 stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) | 2984 NFSLCK_OPEN; 2985 stp->ls_stateid.seqid = 1; 2986 stp->ls_uid = new_stp->ls_uid; 2987 if (lfp != stp->ls_lfp) { 2988 LIST_REMOVE(stp, ls_file); 2989 LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file); 2990 stp->ls_lfp = lfp; 2991 } 2992 openstp = stp; 2993 } else if (openstp) { 2994 openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS); 2995 openstp->ls_stateid.seqid++; 2996 if ((nd->nd_flag & ND_NFSV41) != 0 && 2997 openstp->ls_stateid.seqid == 0) 2998 openstp->ls_stateid.seqid = 1; 2999 3000 /* 3001 * This is where we can choose to issue a delegation. 3002 */ 3003 if (delegate == 0 || writedeleg == 0 || 3004 NFSVNO_EXRDONLY(exp) || (readonly != 0 && 3005 nfsrv_writedelegifpos == 0) || 3006 !NFSVNO_DELEGOK(vp) || 3007 (new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 || 3008 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 3009 LCL_CALLBACKSON) 3010 *rflagsp |= NFSV4OPEN_WDCONTENTION; 3011 else if (nfsrv_issuedelegs == 0 || 3012 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt)) 3013 *rflagsp |= NFSV4OPEN_WDRESOURCE; 3014 else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0) 3015 *rflagsp |= NFSV4OPEN_WDNOTWANTED; 3016 else { 3017 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 3018 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] 3019 = clp->lc_clientid.lval[0]; 3020 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] 3021 = clp->lc_clientid.lval[1]; 3022 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] 3023 = nfsrv_nextstateindex(clp); 3024 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 3025 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 3026 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3027 new_deleg->ls_uid = new_stp->ls_uid; 3028 new_deleg->ls_lfp = lfp; 3029 new_deleg->ls_clp = clp; 3030 new_deleg->ls_filerev = filerev; 3031 new_deleg->ls_compref = nd->nd_compref; 3032 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 3033 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3034 new_deleg->ls_stateid), new_deleg, ls_hash); 3035 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 3036 new_deleg = NULL; 3037 nfsstatsv1.srvdelegates++; 3038 nfsrv_openpluslock++; 3039 nfsrv_delegatecnt++; 3040 } 3041 } else { 3042 new_open->ls_stateid.seqid = 1; 3043 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 3044 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 3045 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 3046 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)| 3047 NFSLCK_OPEN; 3048 new_open->ls_uid = new_stp->ls_uid; 3049 new_open->ls_openowner = ownerstp; 3050 new_open->ls_lfp = lfp; 3051 new_open->ls_clp = clp; 3052 LIST_INIT(&new_open->ls_open); 3053 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 3054 LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); 3055 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 3056 new_open, ls_hash); 3057 openstp = new_open; 3058 new_open = NULL; 3059 nfsstatsv1.srvopens++; 3060 nfsrv_openpluslock++; 3061 3062 /* 3063 * This is where we can choose to issue a delegation. 3064 */ 3065 if (delegate == 0 || (writedeleg == 0 && readonly == 0) || 3066 !NFSVNO_DELEGOK(vp) || 3067 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 3068 LCL_CALLBACKSON) 3069 *rflagsp |= NFSV4OPEN_WDCONTENTION; 3070 else if (nfsrv_issuedelegs == 0 || 3071 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt)) 3072 *rflagsp |= NFSV4OPEN_WDRESOURCE; 3073 else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0) 3074 *rflagsp |= NFSV4OPEN_WDNOTWANTED; 3075 else { 3076 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 3077 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] 3078 = clp->lc_clientid.lval[0]; 3079 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] 3080 = clp->lc_clientid.lval[1]; 3081 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] 3082 = nfsrv_nextstateindex(clp); 3083 if (writedeleg && !NFSVNO_EXRDONLY(exp) && 3084 (nfsrv_writedelegifpos || !readonly) && 3085 (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) { 3086 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 3087 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 3088 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3089 } else { 3090 new_deleg->ls_flags = (NFSLCK_DELEGREAD | 3091 NFSLCK_READACCESS); 3092 *rflagsp |= NFSV4OPEN_READDELEGATE; 3093 } 3094 new_deleg->ls_uid = new_stp->ls_uid; 3095 new_deleg->ls_lfp = lfp; 3096 new_deleg->ls_clp = clp; 3097 new_deleg->ls_filerev = filerev; 3098 new_deleg->ls_compref = nd->nd_compref; 3099 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 3100 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3101 new_deleg->ls_stateid), new_deleg, ls_hash); 3102 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 3103 new_deleg = NULL; 3104 nfsstatsv1.srvdelegates++; 3105 nfsrv_openpluslock++; 3106 nfsrv_delegatecnt++; 3107 } 3108 } 3109 } else { 3110 /* 3111 * New owner case. Start the open_owner sequence with a 3112 * Needs confirmation (unless a reclaim) and hang the 3113 * new open off it. 3114 */ 3115 new_open->ls_stateid.seqid = 1; 3116 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 3117 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 3118 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 3119 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) | 3120 NFSLCK_OPEN; 3121 new_open->ls_uid = new_stp->ls_uid; 3122 LIST_INIT(&new_open->ls_open); 3123 new_open->ls_openowner = new_stp; 3124 new_open->ls_lfp = lfp; 3125 new_open->ls_clp = clp; 3126 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 3127 if (new_stp->ls_flags & NFSLCK_RECLAIM) { 3128 new_stp->ls_flags = 0; 3129 } else if ((nd->nd_flag & ND_NFSV41) != 0) { 3130 /* NFSv4.1 never needs confirmation. */ 3131 new_stp->ls_flags = 0; 3132 3133 /* 3134 * This is where we can choose to issue a delegation. 3135 */ 3136 if (delegate && nfsrv_issuedelegs && 3137 (writedeleg || readonly) && 3138 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) == 3139 LCL_CALLBACKSON && 3140 !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) && 3141 NFSVNO_DELEGOK(vp) && 3142 ((nd->nd_flag & ND_NFSV41) == 0 || 3143 (new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) { 3144 new_deleg->ls_stateid.seqid = 3145 delegstateidp->seqid = 1; 3146 new_deleg->ls_stateid.other[0] = 3147 delegstateidp->other[0] 3148 = clp->lc_clientid.lval[0]; 3149 new_deleg->ls_stateid.other[1] = 3150 delegstateidp->other[1] 3151 = clp->lc_clientid.lval[1]; 3152 new_deleg->ls_stateid.other[2] = 3153 delegstateidp->other[2] 3154 = nfsrv_nextstateindex(clp); 3155 if (writedeleg && !NFSVNO_EXRDONLY(exp) && 3156 (nfsrv_writedelegifpos || !readonly) && 3157 ((nd->nd_flag & ND_NFSV41) == 0 || 3158 (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 3159 0)) { 3160 new_deleg->ls_flags = 3161 (NFSLCK_DELEGWRITE | 3162 NFSLCK_READACCESS | 3163 NFSLCK_WRITEACCESS); 3164 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3165 } else { 3166 new_deleg->ls_flags = 3167 (NFSLCK_DELEGREAD | 3168 NFSLCK_READACCESS); 3169 *rflagsp |= NFSV4OPEN_READDELEGATE; 3170 } 3171 new_deleg->ls_uid = new_stp->ls_uid; 3172 new_deleg->ls_lfp = lfp; 3173 new_deleg->ls_clp = clp; 3174 new_deleg->ls_filerev = filerev; 3175 new_deleg->ls_compref = nd->nd_compref; 3176 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, 3177 ls_file); 3178 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3179 new_deleg->ls_stateid), new_deleg, ls_hash); 3180 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, 3181 ls_list); 3182 new_deleg = NULL; 3183 nfsstatsv1.srvdelegates++; 3184 nfsrv_openpluslock++; 3185 nfsrv_delegatecnt++; 3186 } 3187 /* 3188 * Since NFSv4.1 never does an OpenConfirm, the first 3189 * open state will be acquired here. 3190 */ 3191 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { 3192 clp->lc_flags |= LCL_STAMPEDSTABLE; 3193 len = clp->lc_idlen; 3194 NFSBCOPY(clp->lc_id, clidp, len); 3195 gotstate = 1; 3196 } 3197 } else { 3198 *rflagsp |= NFSV4OPEN_RESULTCONFIRM; 3199 new_stp->ls_flags = NFSLCK_NEEDSCONFIRM; 3200 } 3201 nfsrvd_refcache(new_stp->ls_op); 3202 new_stp->ls_noopens = 0; 3203 LIST_INIT(&new_stp->ls_open); 3204 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 3205 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 3206 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 3207 new_open, ls_hash); 3208 openstp = new_open; 3209 new_open = NULL; 3210 *new_stpp = NULL; 3211 nfsstatsv1.srvopens++; 3212 nfsrv_openpluslock++; 3213 nfsstatsv1.srvopenowners++; 3214 nfsrv_openpluslock++; 3215 } 3216 if (!error) { 3217 stateidp->seqid = openstp->ls_stateid.seqid; 3218 stateidp->other[0] = openstp->ls_stateid.other[0]; 3219 stateidp->other[1] = openstp->ls_stateid.other[1]; 3220 stateidp->other[2] = openstp->ls_stateid.other[2]; 3221 } 3222 NFSUNLOCKSTATE(); 3223 if (haslock) { 3224 NFSLOCKV4ROOTMUTEX(); 3225 nfsv4_unlock(&nfsv4rootfs_lock, 1); 3226 NFSUNLOCKV4ROOTMUTEX(); 3227 } 3228 if (new_open) 3229 FREE((caddr_t)new_open, M_NFSDSTATE); 3230 if (new_deleg) 3231 FREE((caddr_t)new_deleg, M_NFSDSTATE); 3232 3233 /* 3234 * If the NFSv4.1 client just acquired its first open, write a timestamp 3235 * to the stable storage file. 3236 */ 3237 if (gotstate != 0) { 3238 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p); 3239 nfsrv_backupstable(); 3240 } 3241 3242 out: 3243 free(clidp, M_TEMP); 3244 NFSEXITCODE2(error, nd); 3245 return (error); 3246 } 3247 3248 /* 3249 * Open update. Does the confirm, downgrade and close. 3250 */ 3251 APPLESTATIC int 3252 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid, 3253 nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p) 3254 { 3255 struct nfsstate *stp, *ownerstp; 3256 struct nfsclient *clp; 3257 struct nfslockfile *lfp; 3258 u_int32_t bits; 3259 int error = 0, gotstate = 0, len = 0; 3260 u_char *clidp = NULL; 3261 3262 /* 3263 * Check for restart conditions (client and server). 3264 */ 3265 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 3266 &new_stp->ls_stateid, 0); 3267 if (error) 3268 goto out; 3269 3270 clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK); 3271 NFSLOCKSTATE(); 3272 /* 3273 * Get the open structure via clientid and stateid. 3274 */ 3275 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3276 (nfsquad_t)((u_quad_t)0), 0, nd, p); 3277 if (!error) 3278 error = nfsrv_getstate(clp, &new_stp->ls_stateid, 3279 new_stp->ls_flags, &stp); 3280 3281 /* 3282 * Sanity check the open. 3283 */ 3284 if (!error && (!(stp->ls_flags & NFSLCK_OPEN) || 3285 (!(new_stp->ls_flags & NFSLCK_CONFIRM) && 3286 (stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) || 3287 ((new_stp->ls_flags & NFSLCK_CONFIRM) && 3288 (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))))) 3289 error = NFSERR_BADSTATEID; 3290 3291 if (!error) 3292 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 3293 stp->ls_openowner, new_stp->ls_op); 3294 if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid && 3295 (((nd->nd_flag & ND_NFSV41) == 0 && 3296 !(new_stp->ls_flags & NFSLCK_CONFIRM)) || 3297 ((nd->nd_flag & ND_NFSV41) != 0 && 3298 new_stp->ls_stateid.seqid != 0))) 3299 error = NFSERR_OLDSTATEID; 3300 if (!error && vnode_vtype(vp) != VREG) { 3301 if (vnode_vtype(vp) == VDIR) 3302 error = NFSERR_ISDIR; 3303 else 3304 error = NFSERR_INVAL; 3305 } 3306 3307 if (error) { 3308 /* 3309 * If a client tries to confirm an Open with a bad 3310 * seqid# and there are no byte range locks or other Opens 3311 * on the openowner, just throw it away, so the next use of the 3312 * openowner will start a fresh seq#. 3313 */ 3314 if (error == NFSERR_BADSEQID && 3315 (new_stp->ls_flags & NFSLCK_CONFIRM) && 3316 nfsrv_nootherstate(stp)) 3317 nfsrv_freeopenowner(stp->ls_openowner, 0, p); 3318 NFSUNLOCKSTATE(); 3319 goto out; 3320 } 3321 3322 /* 3323 * Set the return stateid. 3324 */ 3325 stateidp->seqid = stp->ls_stateid.seqid + 1; 3326 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0) 3327 stateidp->seqid = 1; 3328 stateidp->other[0] = stp->ls_stateid.other[0]; 3329 stateidp->other[1] = stp->ls_stateid.other[1]; 3330 stateidp->other[2] = stp->ls_stateid.other[2]; 3331 /* 3332 * Now, handle the three cases. 3333 */ 3334 if (new_stp->ls_flags & NFSLCK_CONFIRM) { 3335 /* 3336 * If the open doesn't need confirmation, it seems to me that 3337 * there is a client error, but I'll just log it and keep going? 3338 */ 3339 if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) 3340 printf("Nfsv4d: stray open confirm\n"); 3341 stp->ls_openowner->ls_flags = 0; 3342 stp->ls_stateid.seqid++; 3343 if ((nd->nd_flag & ND_NFSV41) != 0 && 3344 stp->ls_stateid.seqid == 0) 3345 stp->ls_stateid.seqid = 1; 3346 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { 3347 clp->lc_flags |= LCL_STAMPEDSTABLE; 3348 len = clp->lc_idlen; 3349 NFSBCOPY(clp->lc_id, clidp, len); 3350 gotstate = 1; 3351 } 3352 NFSUNLOCKSTATE(); 3353 } else if (new_stp->ls_flags & NFSLCK_CLOSE) { 3354 ownerstp = stp->ls_openowner; 3355 lfp = stp->ls_lfp; 3356 if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) { 3357 /* Get the lf lock */ 3358 nfsrv_locklf(lfp); 3359 NFSUNLOCKSTATE(); 3360 ASSERT_VOP_ELOCKED(vp, "nfsrv_openupdate"); 3361 NFSVOPUNLOCK(vp, 0); 3362 if (nfsrv_freeopen(stp, vp, 1, p) == 0) { 3363 NFSLOCKSTATE(); 3364 nfsrv_unlocklf(lfp); 3365 NFSUNLOCKSTATE(); 3366 } 3367 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 3368 } else { 3369 (void) nfsrv_freeopen(stp, NULL, 0, p); 3370 NFSUNLOCKSTATE(); 3371 } 3372 } else { 3373 /* 3374 * Update the share bits, making sure that the new set are a 3375 * subset of the old ones. 3376 */ 3377 bits = (new_stp->ls_flags & NFSLCK_SHAREBITS); 3378 if (~(stp->ls_flags) & bits) { 3379 NFSUNLOCKSTATE(); 3380 error = NFSERR_INVAL; 3381 goto out; 3382 } 3383 stp->ls_flags = (bits | NFSLCK_OPEN); 3384 stp->ls_stateid.seqid++; 3385 if ((nd->nd_flag & ND_NFSV41) != 0 && 3386 stp->ls_stateid.seqid == 0) 3387 stp->ls_stateid.seqid = 1; 3388 NFSUNLOCKSTATE(); 3389 } 3390 3391 /* 3392 * If the client just confirmed its first open, write a timestamp 3393 * to the stable storage file. 3394 */ 3395 if (gotstate != 0) { 3396 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p); 3397 nfsrv_backupstable(); 3398 } 3399 3400 out: 3401 free(clidp, M_TEMP); 3402 NFSEXITCODE2(error, nd); 3403 return (error); 3404 } 3405 3406 /* 3407 * Delegation update. Does the purge and return. 3408 */ 3409 APPLESTATIC int 3410 nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid, 3411 nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred, 3412 NFSPROC_T *p) 3413 { 3414 struct nfsstate *stp; 3415 struct nfsclient *clp; 3416 int error = 0; 3417 fhandle_t fh; 3418 3419 /* 3420 * Do a sanity check against the file handle for DelegReturn. 3421 */ 3422 if (vp) { 3423 error = nfsvno_getfh(vp, &fh, p); 3424 if (error) 3425 goto out; 3426 } 3427 /* 3428 * Check for restart conditions (client and server). 3429 */ 3430 if (op == NFSV4OP_DELEGRETURN) 3431 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN, 3432 stateidp, 0); 3433 else 3434 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE, 3435 stateidp, 0); 3436 3437 NFSLOCKSTATE(); 3438 /* 3439 * Get the open structure via clientid and stateid. 3440 */ 3441 if (!error) 3442 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3443 (nfsquad_t)((u_quad_t)0), 0, nd, p); 3444 if (error) { 3445 if (error == NFSERR_CBPATHDOWN) 3446 error = 0; 3447 if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN) 3448 error = NFSERR_STALESTATEID; 3449 } 3450 if (!error && op == NFSV4OP_DELEGRETURN) { 3451 error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp); 3452 if (!error && stp->ls_stateid.seqid != stateidp->seqid && 3453 ((nd->nd_flag & ND_NFSV41) == 0 || stateidp->seqid != 0)) 3454 error = NFSERR_OLDSTATEID; 3455 } 3456 /* 3457 * NFSERR_EXPIRED means that the state has gone away, 3458 * so Delegations have been purged. Just return ok. 3459 */ 3460 if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) { 3461 NFSUNLOCKSTATE(); 3462 error = 0; 3463 goto out; 3464 } 3465 if (error) { 3466 NFSUNLOCKSTATE(); 3467 goto out; 3468 } 3469 3470 if (op == NFSV4OP_DELEGRETURN) { 3471 if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh, 3472 sizeof (fhandle_t))) { 3473 NFSUNLOCKSTATE(); 3474 error = NFSERR_BADSTATEID; 3475 goto out; 3476 } 3477 nfsrv_freedeleg(stp); 3478 } else { 3479 nfsrv_freedeleglist(&clp->lc_olddeleg); 3480 } 3481 NFSUNLOCKSTATE(); 3482 error = 0; 3483 3484 out: 3485 NFSEXITCODE(error); 3486 return (error); 3487 } 3488 3489 /* 3490 * Release lock owner. 3491 */ 3492 APPLESTATIC int 3493 nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid, 3494 NFSPROC_T *p) 3495 { 3496 struct nfsstate *stp, *nstp, *openstp, *ownstp; 3497 struct nfsclient *clp; 3498 int error = 0; 3499 3500 /* 3501 * Check for restart conditions (client and server). 3502 */ 3503 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 3504 &new_stp->ls_stateid, 0); 3505 if (error) 3506 goto out; 3507 3508 NFSLOCKSTATE(); 3509 /* 3510 * Get the lock owner by name. 3511 */ 3512 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3513 (nfsquad_t)((u_quad_t)0), 0, NULL, p); 3514 if (error) { 3515 NFSUNLOCKSTATE(); 3516 goto out; 3517 } 3518 LIST_FOREACH(ownstp, &clp->lc_open, ls_list) { 3519 LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) { 3520 stp = LIST_FIRST(&openstp->ls_open); 3521 while (stp != LIST_END(&openstp->ls_open)) { 3522 nstp = LIST_NEXT(stp, ls_list); 3523 /* 3524 * If the owner matches, check for locks and 3525 * then free or return an error. 3526 */ 3527 if (stp->ls_ownerlen == new_stp->ls_ownerlen && 3528 !NFSBCMP(stp->ls_owner, new_stp->ls_owner, 3529 stp->ls_ownerlen)){ 3530 if (LIST_EMPTY(&stp->ls_lock)) { 3531 nfsrv_freelockowner(stp, NULL, 0, p); 3532 } else { 3533 NFSUNLOCKSTATE(); 3534 error = NFSERR_LOCKSHELD; 3535 goto out; 3536 } 3537 } 3538 stp = nstp; 3539 } 3540 } 3541 } 3542 NFSUNLOCKSTATE(); 3543 3544 out: 3545 NFSEXITCODE(error); 3546 return (error); 3547 } 3548 3549 /* 3550 * Get the file handle for a lock structure. 3551 */ 3552 static int 3553 nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile *new_lfp, 3554 fhandle_t *nfhp, NFSPROC_T *p) 3555 { 3556 fhandle_t *fhp = NULL; 3557 int error; 3558 3559 /* 3560 * For lock, use the new nfslock structure, otherwise just 3561 * a fhandle_t on the stack. 3562 */ 3563 if (flags & NFSLCK_OPEN) { 3564 KASSERT(new_lfp != NULL, ("nfsrv_getlockfh: new_lfp NULL")); 3565 fhp = &new_lfp->lf_fh; 3566 } else if (nfhp) { 3567 fhp = nfhp; 3568 } else { 3569 panic("nfsrv_getlockfh"); 3570 } 3571 error = nfsvno_getfh(vp, fhp, p); 3572 NFSEXITCODE(error); 3573 return (error); 3574 } 3575 3576 /* 3577 * Get an nfs lock structure. Allocate one, as required, and return a 3578 * pointer to it. 3579 * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock. 3580 */ 3581 static int 3582 nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, 3583 struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit) 3584 { 3585 struct nfslockfile *lfp; 3586 fhandle_t *fhp = NULL, *tfhp; 3587 struct nfslockhashhead *hp; 3588 struct nfslockfile *new_lfp = NULL; 3589 3590 /* 3591 * For lock, use the new nfslock structure, otherwise just 3592 * a fhandle_t on the stack. 3593 */ 3594 if (flags & NFSLCK_OPEN) { 3595 new_lfp = *new_lfpp; 3596 fhp = &new_lfp->lf_fh; 3597 } else if (nfhp) { 3598 fhp = nfhp; 3599 } else { 3600 panic("nfsrv_getlockfile"); 3601 } 3602 3603 hp = NFSLOCKHASH(fhp); 3604 LIST_FOREACH(lfp, hp, lf_hash) { 3605 tfhp = &lfp->lf_fh; 3606 if (NFSVNO_CMPFH(fhp, tfhp)) { 3607 if (lockit) 3608 nfsrv_locklf(lfp); 3609 *lfpp = lfp; 3610 return (0); 3611 } 3612 } 3613 if (!(flags & NFSLCK_OPEN)) 3614 return (-1); 3615 3616 /* 3617 * No match, so chain the new one into the list. 3618 */ 3619 LIST_INIT(&new_lfp->lf_open); 3620 LIST_INIT(&new_lfp->lf_lock); 3621 LIST_INIT(&new_lfp->lf_deleg); 3622 LIST_INIT(&new_lfp->lf_locallock); 3623 LIST_INIT(&new_lfp->lf_rollback); 3624 new_lfp->lf_locallock_lck.nfslock_usecnt = 0; 3625 new_lfp->lf_locallock_lck.nfslock_lock = 0; 3626 new_lfp->lf_usecount = 0; 3627 LIST_INSERT_HEAD(hp, new_lfp, lf_hash); 3628 *lfpp = new_lfp; 3629 *new_lfpp = NULL; 3630 return (0); 3631 } 3632 3633 /* 3634 * This function adds a nfslock lock structure to the list for the associated 3635 * nfsstate and nfslockfile structures. It will be inserted after the 3636 * entry pointed at by insert_lop. 3637 */ 3638 static void 3639 nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop, 3640 struct nfsstate *stp, struct nfslockfile *lfp) 3641 { 3642 struct nfslock *lop, *nlop; 3643 3644 new_lop->lo_stp = stp; 3645 new_lop->lo_lfp = lfp; 3646 3647 if (stp != NULL) { 3648 /* Insert in increasing lo_first order */ 3649 lop = LIST_FIRST(&lfp->lf_lock); 3650 if (lop == LIST_END(&lfp->lf_lock) || 3651 new_lop->lo_first <= lop->lo_first) { 3652 LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile); 3653 } else { 3654 nlop = LIST_NEXT(lop, lo_lckfile); 3655 while (nlop != LIST_END(&lfp->lf_lock) && 3656 nlop->lo_first < new_lop->lo_first) { 3657 lop = nlop; 3658 nlop = LIST_NEXT(lop, lo_lckfile); 3659 } 3660 LIST_INSERT_AFTER(lop, new_lop, lo_lckfile); 3661 } 3662 } else { 3663 new_lop->lo_lckfile.le_prev = NULL; /* list not used */ 3664 } 3665 3666 /* 3667 * Insert after insert_lop, which is overloaded as stp or lfp for 3668 * an empty list. 3669 */ 3670 if (stp == NULL && (struct nfslockfile *)insert_lop == lfp) 3671 LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner); 3672 else if ((struct nfsstate *)insert_lop == stp) 3673 LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner); 3674 else 3675 LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner); 3676 if (stp != NULL) { 3677 nfsstatsv1.srvlocks++; 3678 nfsrv_openpluslock++; 3679 } 3680 } 3681 3682 /* 3683 * This function updates the locking for a lock owner and given file. It 3684 * maintains a list of lock ranges ordered on increasing file offset that 3685 * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style). 3686 * It always adds new_lop to the list and sometimes uses the one pointed 3687 * at by other_lopp. 3688 */ 3689 static void 3690 nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, 3691 struct nfslock **other_lopp, struct nfslockfile *lfp) 3692 { 3693 struct nfslock *new_lop = *new_lopp; 3694 struct nfslock *lop, *tlop, *ilop; 3695 struct nfslock *other_lop = *other_lopp; 3696 int unlock = 0, myfile = 0; 3697 u_int64_t tmp; 3698 3699 /* 3700 * Work down the list until the lock is merged. 3701 */ 3702 if (new_lop->lo_flags & NFSLCK_UNLOCK) 3703 unlock = 1; 3704 if (stp != NULL) { 3705 ilop = (struct nfslock *)stp; 3706 lop = LIST_FIRST(&stp->ls_lock); 3707 } else { 3708 ilop = (struct nfslock *)lfp; 3709 lop = LIST_FIRST(&lfp->lf_locallock); 3710 } 3711 while (lop != NULL) { 3712 /* 3713 * Only check locks for this file that aren't before the start of 3714 * new lock's range. 3715 */ 3716 if (lop->lo_lfp == lfp) { 3717 myfile = 1; 3718 if (lop->lo_end >= new_lop->lo_first) { 3719 if (new_lop->lo_end < lop->lo_first) { 3720 /* 3721 * If the new lock ends before the start of the 3722 * current lock's range, no merge, just insert 3723 * the new lock. 3724 */ 3725 break; 3726 } 3727 if (new_lop->lo_flags == lop->lo_flags || 3728 (new_lop->lo_first <= lop->lo_first && 3729 new_lop->lo_end >= lop->lo_end)) { 3730 /* 3731 * This lock can be absorbed by the new lock/unlock. 3732 * This happens when it covers the entire range 3733 * of the old lock or is contiguous 3734 * with the old lock and is of the same type or an 3735 * unlock. 3736 */ 3737 if (lop->lo_first < new_lop->lo_first) 3738 new_lop->lo_first = lop->lo_first; 3739 if (lop->lo_end > new_lop->lo_end) 3740 new_lop->lo_end = lop->lo_end; 3741 tlop = lop; 3742 lop = LIST_NEXT(lop, lo_lckowner); 3743 nfsrv_freenfslock(tlop); 3744 continue; 3745 } 3746 3747 /* 3748 * All these cases are for contiguous locks that are not the 3749 * same type, so they can't be merged. 3750 */ 3751 if (new_lop->lo_first <= lop->lo_first) { 3752 /* 3753 * This case is where the new lock overlaps with the 3754 * first part of the old lock. Move the start of the 3755 * old lock to just past the end of the new lock. The 3756 * new lock will be inserted in front of the old, since 3757 * ilop hasn't been updated. (We are done now.) 3758 */ 3759 lop->lo_first = new_lop->lo_end; 3760 break; 3761 } 3762 if (new_lop->lo_end >= lop->lo_end) { 3763 /* 3764 * This case is where the new lock overlaps with the 3765 * end of the old lock's range. Move the old lock's 3766 * end to just before the new lock's first and insert 3767 * the new lock after the old lock. 3768 * Might not be done yet, since the new lock could 3769 * overlap further locks with higher ranges. 3770 */ 3771 lop->lo_end = new_lop->lo_first; 3772 ilop = lop; 3773 lop = LIST_NEXT(lop, lo_lckowner); 3774 continue; 3775 } 3776 /* 3777 * The final case is where the new lock's range is in the 3778 * middle of the current lock's and splits the current lock 3779 * up. Use *other_lopp to handle the second part of the 3780 * split old lock range. (We are done now.) 3781 * For unlock, we use new_lop as other_lop and tmp, since 3782 * other_lop and new_lop are the same for this case. 3783 * We noted the unlock case above, so we don't need 3784 * new_lop->lo_flags any longer. 3785 */ 3786 tmp = new_lop->lo_first; 3787 if (other_lop == NULL) { 3788 if (!unlock) 3789 panic("nfsd srv update unlock"); 3790 other_lop = new_lop; 3791 *new_lopp = NULL; 3792 } 3793 other_lop->lo_first = new_lop->lo_end; 3794 other_lop->lo_end = lop->lo_end; 3795 other_lop->lo_flags = lop->lo_flags; 3796 other_lop->lo_stp = stp; 3797 other_lop->lo_lfp = lfp; 3798 lop->lo_end = tmp; 3799 nfsrv_insertlock(other_lop, lop, stp, lfp); 3800 *other_lopp = NULL; 3801 ilop = lop; 3802 break; 3803 } 3804 } 3805 ilop = lop; 3806 lop = LIST_NEXT(lop, lo_lckowner); 3807 if (myfile && (lop == NULL || lop->lo_lfp != lfp)) 3808 break; 3809 } 3810 3811 /* 3812 * Insert the new lock in the list at the appropriate place. 3813 */ 3814 if (!unlock) { 3815 nfsrv_insertlock(new_lop, ilop, stp, lfp); 3816 *new_lopp = NULL; 3817 } 3818 } 3819 3820 /* 3821 * This function handles sequencing of locks, etc. 3822 * It returns an error that indicates what the caller should do. 3823 */ 3824 static int 3825 nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 3826 struct nfsstate *stp, struct nfsrvcache *op) 3827 { 3828 int error = 0; 3829 3830 if ((nd->nd_flag & ND_NFSV41) != 0) 3831 /* NFSv4.1 ignores the open_seqid and lock_seqid. */ 3832 goto out; 3833 if (op != nd->nd_rp) 3834 panic("nfsrvstate checkseqid"); 3835 if (!(op->rc_flag & RC_INPROG)) 3836 panic("nfsrvstate not inprog"); 3837 if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) { 3838 printf("refcnt=%d\n", stp->ls_op->rc_refcnt); 3839 panic("nfsrvstate op refcnt"); 3840 } 3841 if ((stp->ls_seq + 1) == seqid) { 3842 if (stp->ls_op) 3843 nfsrvd_derefcache(stp->ls_op); 3844 stp->ls_op = op; 3845 nfsrvd_refcache(op); 3846 stp->ls_seq = seqid; 3847 goto out; 3848 } else if (stp->ls_seq == seqid && stp->ls_op && 3849 op->rc_xid == stp->ls_op->rc_xid && 3850 op->rc_refcnt == 0 && 3851 op->rc_reqlen == stp->ls_op->rc_reqlen && 3852 op->rc_cksum == stp->ls_op->rc_cksum) { 3853 if (stp->ls_op->rc_flag & RC_INPROG) { 3854 error = NFSERR_DONTREPLY; 3855 goto out; 3856 } 3857 nd->nd_rp = stp->ls_op; 3858 nd->nd_rp->rc_flag |= RC_INPROG; 3859 nfsrvd_delcache(op); 3860 error = NFSERR_REPLYFROMCACHE; 3861 goto out; 3862 } 3863 error = NFSERR_BADSEQID; 3864 3865 out: 3866 NFSEXITCODE2(error, nd); 3867 return (error); 3868 } 3869 3870 /* 3871 * Get the client ip address for callbacks. If the strings can't be parsed, 3872 * just set lc_program to 0 to indicate no callbacks are possible. 3873 * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set 3874 * the address to the client's transport address. This won't be used 3875 * for callbacks, but can be printed out by nfsstats for info.) 3876 * Return error if the xdr can't be parsed, 0 otherwise. 3877 */ 3878 APPLESTATIC int 3879 nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp) 3880 { 3881 u_int32_t *tl; 3882 u_char *cp, *cp2; 3883 int i, j; 3884 struct sockaddr_in *rad, *sad; 3885 u_char protocol[5], addr[24]; 3886 int error = 0, cantparse = 0; 3887 union { 3888 u_long ival; 3889 u_char cval[4]; 3890 } ip; 3891 union { 3892 u_short sval; 3893 u_char cval[2]; 3894 } port; 3895 3896 rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 3897 rad->sin_family = AF_INET; 3898 rad->sin_len = sizeof (struct sockaddr_in); 3899 rad->sin_addr.s_addr = 0; 3900 rad->sin_port = 0; 3901 clp->lc_req.nr_client = NULL; 3902 clp->lc_req.nr_lock = 0; 3903 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3904 i = fxdr_unsigned(int, *tl); 3905 if (i >= 3 && i <= 4) { 3906 error = nfsrv_mtostr(nd, protocol, i); 3907 if (error) 3908 goto nfsmout; 3909 if (!strcmp(protocol, "tcp")) { 3910 clp->lc_flags |= LCL_TCPCALLBACK; 3911 clp->lc_req.nr_sotype = SOCK_STREAM; 3912 clp->lc_req.nr_soproto = IPPROTO_TCP; 3913 } else if (!strcmp(protocol, "udp")) { 3914 clp->lc_req.nr_sotype = SOCK_DGRAM; 3915 clp->lc_req.nr_soproto = IPPROTO_UDP; 3916 } else { 3917 cantparse = 1; 3918 } 3919 } else { 3920 cantparse = 1; 3921 if (i > 0) { 3922 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 3923 if (error) 3924 goto nfsmout; 3925 } 3926 } 3927 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3928 i = fxdr_unsigned(int, *tl); 3929 if (i < 0) { 3930 error = NFSERR_BADXDR; 3931 goto nfsmout; 3932 } else if (i == 0) { 3933 cantparse = 1; 3934 } else if (!cantparse && i <= 23 && i >= 11) { 3935 error = nfsrv_mtostr(nd, addr, i); 3936 if (error) 3937 goto nfsmout; 3938 3939 /* 3940 * Parse out the address fields. We expect 6 decimal numbers 3941 * separated by '.'s. 3942 */ 3943 cp = addr; 3944 i = 0; 3945 while (*cp && i < 6) { 3946 cp2 = cp; 3947 while (*cp2 && *cp2 != '.') 3948 cp2++; 3949 if (*cp2) 3950 *cp2++ = '\0'; 3951 else if (i != 5) { 3952 cantparse = 1; 3953 break; 3954 } 3955 j = nfsrv_getipnumber(cp); 3956 if (j >= 0) { 3957 if (i < 4) 3958 ip.cval[3 - i] = j; 3959 else 3960 port.cval[5 - i] = j; 3961 } else { 3962 cantparse = 1; 3963 break; 3964 } 3965 cp = cp2; 3966 i++; 3967 } 3968 if (!cantparse) { 3969 if (ip.ival != 0x0) { 3970 rad->sin_addr.s_addr = htonl(ip.ival); 3971 rad->sin_port = htons(port.sval); 3972 } else { 3973 cantparse = 1; 3974 } 3975 } 3976 } else { 3977 cantparse = 1; 3978 if (i > 0) { 3979 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 3980 if (error) 3981 goto nfsmout; 3982 } 3983 } 3984 if (cantparse) { 3985 sad = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); 3986 rad->sin_addr.s_addr = sad->sin_addr.s_addr; 3987 rad->sin_port = 0x0; 3988 clp->lc_program = 0; 3989 } 3990 nfsmout: 3991 NFSEXITCODE2(error, nd); 3992 return (error); 3993 } 3994 3995 /* 3996 * Turn a string of up to three decimal digits into a number. Return -1 upon 3997 * error. 3998 */ 3999 static int 4000 nfsrv_getipnumber(u_char *cp) 4001 { 4002 int i = 0, j = 0; 4003 4004 while (*cp) { 4005 if (j > 2 || *cp < '0' || *cp > '9') 4006 return (-1); 4007 i *= 10; 4008 i += (*cp - '0'); 4009 cp++; 4010 j++; 4011 } 4012 if (i < 256) 4013 return (i); 4014 return (-1); 4015 } 4016 4017 /* 4018 * This function checks for restart conditions. 4019 */ 4020 static int 4021 nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 4022 nfsv4stateid_t *stateidp, int specialid) 4023 { 4024 int ret = 0; 4025 4026 /* 4027 * First check for a server restart. Open, LockT, ReleaseLockOwner 4028 * and DelegPurge have a clientid, the rest a stateid. 4029 */ 4030 if (flags & 4031 (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { 4032 if (clientid.lval[0] != nfsrvboottime) { 4033 ret = NFSERR_STALECLIENTID; 4034 goto out; 4035 } 4036 } else if (stateidp->other[0] != nfsrvboottime && 4037 specialid == 0) { 4038 ret = NFSERR_STALESTATEID; 4039 goto out; 4040 } 4041 4042 /* 4043 * Read, Write, Setattr and LockT can return NFSERR_GRACE and do 4044 * not use a lock/open owner seqid#, so the check can be done now. 4045 * (The others will be checked, as required, later.) 4046 */ 4047 if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST))) 4048 goto out; 4049 4050 NFSLOCKSTATE(); 4051 ret = nfsrv_checkgrace(NULL, NULL, flags); 4052 NFSUNLOCKSTATE(); 4053 4054 out: 4055 NFSEXITCODE(ret); 4056 return (ret); 4057 } 4058 4059 /* 4060 * Check for grace. 4061 */ 4062 static int 4063 nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp, 4064 u_int32_t flags) 4065 { 4066 int error = 0; 4067 4068 if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) { 4069 if (flags & NFSLCK_RECLAIM) { 4070 error = NFSERR_NOGRACE; 4071 goto out; 4072 } 4073 } else { 4074 if (!(flags & NFSLCK_RECLAIM)) { 4075 error = NFSERR_GRACE; 4076 goto out; 4077 } 4078 if (nd != NULL && clp != NULL && 4079 (nd->nd_flag & ND_NFSV41) != 0 && 4080 (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) { 4081 error = NFSERR_NOGRACE; 4082 goto out; 4083 } 4084 4085 /* 4086 * If grace is almost over and we are still getting Reclaims, 4087 * extend grace a bit. 4088 */ 4089 if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > 4090 nfsrv_stablefirst.nsf_eograce) 4091 nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC + 4092 NFSRV_LEASEDELTA; 4093 } 4094 4095 out: 4096 NFSEXITCODE(error); 4097 return (error); 4098 } 4099 4100 /* 4101 * Do a server callback. 4102 */ 4103 static int 4104 nfsrv_docallback(struct nfsclient *clp, int procnum, 4105 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, 4106 struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p) 4107 { 4108 mbuf_t m; 4109 u_int32_t *tl; 4110 struct nfsrv_descript nfsd, *nd = &nfsd; 4111 struct ucred *cred; 4112 int error = 0; 4113 u_int32_t callback; 4114 struct nfsdsession *sep = NULL; 4115 4116 cred = newnfs_getcred(); 4117 NFSLOCKSTATE(); /* mostly for lc_cbref++ */ 4118 if (clp->lc_flags & LCL_NEEDSCONFIRM) { 4119 NFSUNLOCKSTATE(); 4120 panic("docallb"); 4121 } 4122 clp->lc_cbref++; 4123 4124 /* 4125 * Fill the callback program# and version into the request 4126 * structure for newnfs_connect() to use. 4127 */ 4128 clp->lc_req.nr_prog = clp->lc_program; 4129 #ifdef notnow 4130 if ((clp->lc_flags & LCL_NFSV41) != 0) 4131 clp->lc_req.nr_vers = NFSV41_CBVERS; 4132 else 4133 #endif 4134 clp->lc_req.nr_vers = NFSV4_CBVERS; 4135 4136 /* 4137 * First, fill in some of the fields of nd and cr. 4138 */ 4139 nd->nd_flag = ND_NFSV4; 4140 if (clp->lc_flags & LCL_GSS) 4141 nd->nd_flag |= ND_KERBV; 4142 if ((clp->lc_flags & LCL_NFSV41) != 0) 4143 nd->nd_flag |= ND_NFSV41; 4144 nd->nd_repstat = 0; 4145 cred->cr_uid = clp->lc_uid; 4146 cred->cr_gid = clp->lc_gid; 4147 callback = clp->lc_callback; 4148 NFSUNLOCKSTATE(); 4149 cred->cr_ngroups = 1; 4150 4151 /* 4152 * Get the first mbuf for the request. 4153 */ 4154 MGET(m, M_WAITOK, MT_DATA); 4155 mbuf_setlen(m, 0); 4156 nd->nd_mreq = nd->nd_mb = m; 4157 nd->nd_bpos = NFSMTOD(m, caddr_t); 4158 4159 /* 4160 * and build the callback request. 4161 */ 4162 if (procnum == NFSV4OP_CBGETATTR) { 4163 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4164 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR, 4165 "CB Getattr", &sep); 4166 if (error != 0) { 4167 mbuf_freem(nd->nd_mreq); 4168 goto errout; 4169 } 4170 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 4171 (void)nfsrv_putattrbit(nd, attrbitp); 4172 } else if (procnum == NFSV4OP_CBRECALL) { 4173 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4174 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL, 4175 "CB Recall", &sep); 4176 if (error != 0) { 4177 mbuf_freem(nd->nd_mreq); 4178 goto errout; 4179 } 4180 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID); 4181 *tl++ = txdr_unsigned(stateidp->seqid); 4182 NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl, 4183 NFSX_STATEIDOTHER); 4184 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4185 if (trunc) 4186 *tl = newnfs_true; 4187 else 4188 *tl = newnfs_false; 4189 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 4190 } else if (procnum == NFSV4PROC_CBNULL) { 4191 nd->nd_procnum = NFSV4PROC_CBNULL; 4192 if ((clp->lc_flags & LCL_NFSV41) != 0) { 4193 error = nfsv4_getcbsession(clp, &sep); 4194 if (error != 0) { 4195 mbuf_freem(nd->nd_mreq); 4196 goto errout; 4197 } 4198 } 4199 } else { 4200 error = NFSERR_SERVERFAULT; 4201 mbuf_freem(nd->nd_mreq); 4202 goto errout; 4203 } 4204 4205 /* 4206 * Call newnfs_connect(), as required, and then newnfs_request(). 4207 */ 4208 (void) newnfs_sndlock(&clp->lc_req.nr_lock); 4209 if (clp->lc_req.nr_client == NULL) { 4210 if ((clp->lc_flags & LCL_NFSV41) != 0) 4211 error = ECONNREFUSED; 4212 else if (nd->nd_procnum == NFSV4PROC_CBNULL) 4213 error = newnfs_connect(NULL, &clp->lc_req, cred, 4214 NULL, 1); 4215 else 4216 error = newnfs_connect(NULL, &clp->lc_req, cred, 4217 NULL, 3); 4218 } 4219 newnfs_sndunlock(&clp->lc_req.nr_lock); 4220 if (!error) { 4221 if ((nd->nd_flag & ND_NFSV41) != 0) { 4222 KASSERT(sep != NULL, ("sep NULL")); 4223 if (sep->sess_cbsess.nfsess_xprt != NULL) 4224 error = newnfs_request(nd, NULL, clp, 4225 &clp->lc_req, NULL, NULL, cred, 4226 clp->lc_program, clp->lc_req.nr_vers, NULL, 4227 1, NULL, &sep->sess_cbsess); 4228 else { 4229 /* 4230 * This should probably never occur, but if a 4231 * client somehow does an RPC without a 4232 * SequenceID Op that causes a callback just 4233 * after the nfsd threads have been terminated 4234 * and restared we could conceivably get here 4235 * without a backchannel xprt. 4236 */ 4237 printf("nfsrv_docallback: no xprt\n"); 4238 error = ECONNREFUSED; 4239 } 4240 nfsrv_freesession(sep, NULL); 4241 } else 4242 error = newnfs_request(nd, NULL, clp, &clp->lc_req, 4243 NULL, NULL, cred, clp->lc_program, 4244 clp->lc_req.nr_vers, NULL, 1, NULL, NULL); 4245 } 4246 errout: 4247 NFSFREECRED(cred); 4248 4249 /* 4250 * If error is set here, the Callback path isn't working 4251 * properly, so twiddle the appropriate LCL_ flags. 4252 * (nd_repstat != 0 indicates the Callback path is working, 4253 * but the callback failed on the client.) 4254 */ 4255 if (error) { 4256 /* 4257 * Mark the callback pathway down, which disabled issuing 4258 * of delegations and gets Renew to return NFSERR_CBPATHDOWN. 4259 */ 4260 NFSLOCKSTATE(); 4261 clp->lc_flags |= LCL_CBDOWN; 4262 NFSUNLOCKSTATE(); 4263 } else { 4264 /* 4265 * Callback worked. If the callback path was down, disable 4266 * callbacks, so no more delegations will be issued. (This 4267 * is done on the assumption that the callback pathway is 4268 * flakey.) 4269 */ 4270 NFSLOCKSTATE(); 4271 if (clp->lc_flags & LCL_CBDOWN) 4272 clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON); 4273 NFSUNLOCKSTATE(); 4274 if (nd->nd_repstat) 4275 error = nd->nd_repstat; 4276 else if (error == 0 && procnum == NFSV4OP_CBGETATTR) 4277 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, 4278 NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 4279 p, NULL); 4280 mbuf_freem(nd->nd_mrep); 4281 } 4282 NFSLOCKSTATE(); 4283 clp->lc_cbref--; 4284 if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) { 4285 clp->lc_flags &= ~LCL_WAKEUPWANTED; 4286 wakeup(clp); 4287 } 4288 NFSUNLOCKSTATE(); 4289 4290 NFSEXITCODE(error); 4291 return (error); 4292 } 4293 4294 /* 4295 * Set up the compound RPC for the callback. 4296 */ 4297 static int 4298 nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp, 4299 uint32_t callback, int op, const char *optag, struct nfsdsession **sepp) 4300 { 4301 uint32_t *tl; 4302 int error, len; 4303 4304 len = strlen(optag); 4305 (void)nfsm_strtom(nd, optag, len); 4306 NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED); 4307 if ((nd->nd_flag & ND_NFSV41) != 0) { 4308 *tl++ = txdr_unsigned(NFSV41_MINORVERSION); 4309 *tl++ = txdr_unsigned(callback); 4310 *tl++ = txdr_unsigned(2); 4311 *tl = txdr_unsigned(NFSV4OP_CBSEQUENCE); 4312 error = nfsv4_setcbsequence(nd, clp, 1, sepp); 4313 if (error != 0) 4314 return (error); 4315 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 4316 *tl = txdr_unsigned(op); 4317 } else { 4318 *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 4319 *tl++ = txdr_unsigned(callback); 4320 *tl++ = txdr_unsigned(1); 4321 *tl = txdr_unsigned(op); 4322 } 4323 return (0); 4324 } 4325 4326 /* 4327 * Return the next index# for a clientid. Mostly just increment and return 4328 * the next one, but... if the 32bit unsigned does actually wrap around, 4329 * it should be rebooted. 4330 * At an average rate of one new client per second, it will wrap around in 4331 * approximately 136 years. (I think the server will have been shut 4332 * down or rebooted before then.) 4333 */ 4334 static u_int32_t 4335 nfsrv_nextclientindex(void) 4336 { 4337 static u_int32_t client_index = 0; 4338 4339 client_index++; 4340 if (client_index != 0) 4341 return (client_index); 4342 4343 printf("%s: out of clientids\n", __func__); 4344 return (client_index); 4345 } 4346 4347 /* 4348 * Return the next index# for a stateid. Mostly just increment and return 4349 * the next one, but... if the 32bit unsigned does actually wrap around 4350 * (will a BSD server stay up that long?), find 4351 * new start and end values. 4352 */ 4353 static u_int32_t 4354 nfsrv_nextstateindex(struct nfsclient *clp) 4355 { 4356 struct nfsstate *stp; 4357 int i; 4358 u_int32_t canuse, min_index, max_index; 4359 4360 if (!(clp->lc_flags & LCL_INDEXNOTOK)) { 4361 clp->lc_stateindex++; 4362 if (clp->lc_stateindex != clp->lc_statemaxindex) 4363 return (clp->lc_stateindex); 4364 } 4365 4366 /* 4367 * Yuck, we've hit the end. 4368 * Look for a new min and max. 4369 */ 4370 min_index = 0; 4371 max_index = 0xffffffff; 4372 for (i = 0; i < nfsrv_statehashsize; i++) { 4373 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 4374 if (stp->ls_stateid.other[2] > 0x80000000) { 4375 if (stp->ls_stateid.other[2] < max_index) 4376 max_index = stp->ls_stateid.other[2]; 4377 } else { 4378 if (stp->ls_stateid.other[2] > min_index) 4379 min_index = stp->ls_stateid.other[2]; 4380 } 4381 } 4382 } 4383 4384 /* 4385 * Yikes, highly unlikely, but I'll handle it anyhow. 4386 */ 4387 if (min_index == 0x80000000 && max_index == 0x80000001) { 4388 canuse = 0; 4389 /* 4390 * Loop around until we find an unused entry. Return that 4391 * and set LCL_INDEXNOTOK, so the search will continue next time. 4392 * (This is one of those rare cases where a goto is the 4393 * cleanest way to code the loop.) 4394 */ 4395 tryagain: 4396 for (i = 0; i < nfsrv_statehashsize; i++) { 4397 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 4398 if (stp->ls_stateid.other[2] == canuse) { 4399 canuse++; 4400 goto tryagain; 4401 } 4402 } 4403 } 4404 clp->lc_flags |= LCL_INDEXNOTOK; 4405 return (canuse); 4406 } 4407 4408 /* 4409 * Ok to start again from min + 1. 4410 */ 4411 clp->lc_stateindex = min_index + 1; 4412 clp->lc_statemaxindex = max_index; 4413 clp->lc_flags &= ~LCL_INDEXNOTOK; 4414 return (clp->lc_stateindex); 4415 } 4416 4417 /* 4418 * The following functions handle the stable storage file that deals with 4419 * the edge conditions described in RFC3530 Sec. 8.6.3. 4420 * The file is as follows: 4421 * - a single record at the beginning that has the lease time of the 4422 * previous server instance (before the last reboot) and the nfsrvboottime 4423 * values for the previous server boots. 4424 * These previous boot times are used to ensure that the current 4425 * nfsrvboottime does not, somehow, get set to a previous one. 4426 * (This is important so that Stale ClientIDs and StateIDs can 4427 * be recognized.) 4428 * The number of previous nfsvrboottime values precedes the list. 4429 * - followed by some number of appended records with: 4430 * - client id string 4431 * - flag that indicates it is a record revoking state via lease 4432 * expiration or similar 4433 * OR has successfully acquired state. 4434 * These structures vary in length, with the client string at the end, up 4435 * to NFSV4_OPAQUELIMIT in size. 4436 * 4437 * At the end of the grace period, the file is truncated, the first 4438 * record is rewritten with updated information and any acquired state 4439 * records for successful reclaims of state are written. 4440 * 4441 * Subsequent records are appended when the first state is issued to 4442 * a client and when state is revoked for a client. 4443 * 4444 * When reading the file in, state issued records that come later in 4445 * the file override older ones, since the append log is in cronological order. 4446 * If, for some reason, the file can't be read, the grace period is 4447 * immediately terminated and all reclaims get NFSERR_NOGRACE. 4448 */ 4449 4450 /* 4451 * Read in the stable storage file. Called by nfssvc() before the nfsd 4452 * processes start servicing requests. 4453 */ 4454 APPLESTATIC void 4455 nfsrv_setupstable(NFSPROC_T *p) 4456 { 4457 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4458 struct nfsrv_stable *sp, *nsp; 4459 struct nfst_rec *tsp; 4460 int error, i, tryagain; 4461 off_t off = 0; 4462 ssize_t aresid, len; 4463 4464 /* 4465 * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without 4466 * a reboot, so state has not been lost. 4467 */ 4468 if (sf->nsf_flags & NFSNSF_UPDATEDONE) 4469 return; 4470 /* 4471 * Set Grace over just until the file reads successfully. 4472 */ 4473 nfsrvboottime = time_second; 4474 LIST_INIT(&sf->nsf_head); 4475 sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); 4476 sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA; 4477 if (sf->nsf_fp == NULL) 4478 return; 4479 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4480 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE, 4481 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4482 if (error || aresid || sf->nsf_numboots == 0 || 4483 sf->nsf_numboots > NFSNSF_MAXNUMBOOTS) 4484 return; 4485 4486 /* 4487 * Now, read in the boottimes. 4488 */ 4489 sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) * 4490 sizeof (time_t), M_TEMP, M_WAITOK); 4491 off = sizeof (struct nfsf_rec); 4492 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4493 (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off, 4494 UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4495 if (error || aresid) { 4496 free((caddr_t)sf->nsf_bootvals, M_TEMP); 4497 sf->nsf_bootvals = NULL; 4498 return; 4499 } 4500 4501 /* 4502 * Make sure this nfsrvboottime is different from all recorded 4503 * previous ones. 4504 */ 4505 do { 4506 tryagain = 0; 4507 for (i = 0; i < sf->nsf_numboots; i++) { 4508 if (nfsrvboottime == sf->nsf_bootvals[i]) { 4509 nfsrvboottime++; 4510 tryagain = 1; 4511 break; 4512 } 4513 } 4514 } while (tryagain); 4515 4516 sf->nsf_flags |= NFSNSF_OK; 4517 off += (sf->nsf_numboots * sizeof (time_t)); 4518 4519 /* 4520 * Read through the file, building a list of records for grace 4521 * checking. 4522 * Each record is between sizeof (struct nfst_rec) and 4523 * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1 4524 * and is actually sizeof (struct nfst_rec) + nst_len - 1. 4525 */ 4526 tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4527 NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK); 4528 do { 4529 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4530 (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1, 4531 off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4532 len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid; 4533 if (error || (len > 0 && (len < sizeof (struct nfst_rec) || 4534 len < (sizeof (struct nfst_rec) + tsp->len - 1)))) { 4535 /* 4536 * Yuck, the file has been corrupted, so just return 4537 * after clearing out any restart state, so the grace period 4538 * is over. 4539 */ 4540 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4541 LIST_REMOVE(sp, nst_list); 4542 free((caddr_t)sp, M_TEMP); 4543 } 4544 free((caddr_t)tsp, M_TEMP); 4545 sf->nsf_flags &= ~NFSNSF_OK; 4546 free((caddr_t)sf->nsf_bootvals, M_TEMP); 4547 sf->nsf_bootvals = NULL; 4548 return; 4549 } 4550 if (len > 0) { 4551 off += sizeof (struct nfst_rec) + tsp->len - 1; 4552 /* 4553 * Search the list for a matching client. 4554 */ 4555 LIST_FOREACH(sp, &sf->nsf_head, nst_list) { 4556 if (tsp->len == sp->nst_len && 4557 !NFSBCMP(tsp->client, sp->nst_client, tsp->len)) 4558 break; 4559 } 4560 if (sp == LIST_END(&sf->nsf_head)) { 4561 sp = (struct nfsrv_stable *)malloc(tsp->len + 4562 sizeof (struct nfsrv_stable) - 1, M_TEMP, 4563 M_WAITOK); 4564 NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec, 4565 sizeof (struct nfst_rec) + tsp->len - 1); 4566 LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list); 4567 } else { 4568 if (tsp->flag == NFSNST_REVOKE) 4569 sp->nst_flag |= NFSNST_REVOKE; 4570 else 4571 /* 4572 * A subsequent timestamp indicates the client 4573 * did a setclientid/confirm and any previous 4574 * revoke is no longer relevant. 4575 */ 4576 sp->nst_flag &= ~NFSNST_REVOKE; 4577 } 4578 } 4579 } while (len > 0); 4580 free((caddr_t)tsp, M_TEMP); 4581 sf->nsf_flags = NFSNSF_OK; 4582 sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease + 4583 NFSRV_LEASEDELTA; 4584 } 4585 4586 /* 4587 * Update the stable storage file, now that the grace period is over. 4588 */ 4589 APPLESTATIC void 4590 nfsrv_updatestable(NFSPROC_T *p) 4591 { 4592 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4593 struct nfsrv_stable *sp, *nsp; 4594 int i; 4595 struct nfsvattr nva; 4596 vnode_t vp; 4597 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) 4598 mount_t mp = NULL; 4599 #endif 4600 int error; 4601 4602 if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE)) 4603 return; 4604 sf->nsf_flags |= NFSNSF_UPDATEDONE; 4605 /* 4606 * Ok, we need to rewrite the stable storage file. 4607 * - truncate to 0 length 4608 * - write the new first structure 4609 * - loop through the data structures, writing out any that 4610 * have timestamps older than the old boot 4611 */ 4612 if (sf->nsf_bootvals) { 4613 sf->nsf_numboots++; 4614 for (i = sf->nsf_numboots - 2; i >= 0; i--) 4615 sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i]; 4616 } else { 4617 sf->nsf_numboots = 1; 4618 sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t), 4619 M_TEMP, M_WAITOK); 4620 } 4621 sf->nsf_bootvals[0] = nfsrvboottime; 4622 sf->nsf_lease = nfsrv_lease; 4623 NFSVNO_ATTRINIT(&nva); 4624 NFSVNO_SETATTRVAL(&nva, size, 0); 4625 vp = NFSFPVNODE(sf->nsf_fp); 4626 vn_start_write(vp, &mp, V_WAIT); 4627 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { 4628 error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p, 4629 NULL); 4630 NFSVOPUNLOCK(vp, 0); 4631 } else 4632 error = EPERM; 4633 vn_finished_write(mp); 4634 if (!error) 4635 error = NFSD_RDWR(UIO_WRITE, vp, 4636 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0, 4637 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4638 if (!error) 4639 error = NFSD_RDWR(UIO_WRITE, vp, 4640 (caddr_t)sf->nsf_bootvals, 4641 sf->nsf_numboots * sizeof (time_t), 4642 (off_t)(sizeof (struct nfsf_rec)), 4643 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4644 free((caddr_t)sf->nsf_bootvals, M_TEMP); 4645 sf->nsf_bootvals = NULL; 4646 if (error) { 4647 sf->nsf_flags &= ~NFSNSF_OK; 4648 printf("EEK! Can't write NfsV4 stable storage file\n"); 4649 return; 4650 } 4651 sf->nsf_flags |= NFSNSF_OK; 4652 4653 /* 4654 * Loop through the list and write out timestamp records for 4655 * any clients that successfully reclaimed state. 4656 */ 4657 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4658 if (sp->nst_flag & NFSNST_GOTSTATE) { 4659 nfsrv_writestable(sp->nst_client, sp->nst_len, 4660 NFSNST_NEWSTATE, p); 4661 sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE; 4662 } 4663 LIST_REMOVE(sp, nst_list); 4664 free((caddr_t)sp, M_TEMP); 4665 } 4666 nfsrv_backupstable(); 4667 } 4668 4669 /* 4670 * Append a record to the stable storage file. 4671 */ 4672 APPLESTATIC void 4673 nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p) 4674 { 4675 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4676 struct nfst_rec *sp; 4677 int error; 4678 4679 if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL) 4680 return; 4681 sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4682 len - 1, M_TEMP, M_WAITOK); 4683 sp->len = len; 4684 NFSBCOPY(client, sp->client, len); 4685 sp->flag = flag; 4686 error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp), 4687 (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0, 4688 UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p); 4689 free((caddr_t)sp, M_TEMP); 4690 if (error) { 4691 sf->nsf_flags &= ~NFSNSF_OK; 4692 printf("EEK! Can't write NfsV4 stable storage file\n"); 4693 } 4694 } 4695 4696 /* 4697 * This function is called during the grace period to mark a client 4698 * that successfully reclaimed state. 4699 */ 4700 static void 4701 nfsrv_markstable(struct nfsclient *clp) 4702 { 4703 struct nfsrv_stable *sp; 4704 4705 /* 4706 * First find the client structure. 4707 */ 4708 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4709 if (sp->nst_len == clp->lc_idlen && 4710 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4711 break; 4712 } 4713 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) 4714 return; 4715 4716 /* 4717 * Now, just mark it and set the nfsclient back pointer. 4718 */ 4719 sp->nst_flag |= NFSNST_GOTSTATE; 4720 sp->nst_clp = clp; 4721 } 4722 4723 /* 4724 * This function is called for a reclaim, to see if it gets grace. 4725 * It returns 0 if a reclaim is allowed, 1 otherwise. 4726 */ 4727 static int 4728 nfsrv_checkstable(struct nfsclient *clp) 4729 { 4730 struct nfsrv_stable *sp; 4731 4732 /* 4733 * First, find the entry for the client. 4734 */ 4735 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4736 if (sp->nst_len == clp->lc_idlen && 4737 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4738 break; 4739 } 4740 4741 /* 4742 * If not in the list, state was revoked or no state was issued 4743 * since the previous reboot, a reclaim is denied. 4744 */ 4745 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) || 4746 (sp->nst_flag & NFSNST_REVOKE) || 4747 !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK)) 4748 return (1); 4749 return (0); 4750 } 4751 4752 /* 4753 * Test for and try to clear out a conflicting client. This is called by 4754 * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients 4755 * a found. 4756 * The trick here is that it can't revoke a conflicting client with an 4757 * expired lease unless it holds the v4root lock, so... 4758 * If no v4root lock, get the lock and return 1 to indicate "try again". 4759 * Return 0 to indicate the conflict can't be revoked and 1 to indicate 4760 * the revocation worked and the conflicting client is "bye, bye", so it 4761 * can be tried again. 4762 * Return 2 to indicate that the vnode is VI_DOOMED after NFSVOPLOCK(). 4763 * Unlocks State before a non-zero value is returned. 4764 */ 4765 static int 4766 nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp, 4767 NFSPROC_T *p) 4768 { 4769 int gotlock, lktype = 0; 4770 4771 /* 4772 * If lease hasn't expired, we can't fix it. 4773 */ 4774 if (clp->lc_expiry >= NFSD_MONOSEC || 4775 !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) 4776 return (0); 4777 if (*haslockp == 0) { 4778 NFSUNLOCKSTATE(); 4779 if (vp != NULL) { 4780 lktype = NFSVOPISLOCKED(vp); 4781 NFSVOPUNLOCK(vp, 0); 4782 } 4783 NFSLOCKV4ROOTMUTEX(); 4784 nfsv4_relref(&nfsv4rootfs_lock); 4785 do { 4786 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4787 NFSV4ROOTLOCKMUTEXPTR, NULL); 4788 } while (!gotlock); 4789 NFSUNLOCKV4ROOTMUTEX(); 4790 *haslockp = 1; 4791 if (vp != NULL) { 4792 NFSVOPLOCK(vp, lktype | LK_RETRY); 4793 if ((vp->v_iflag & VI_DOOMED) != 0) 4794 return (2); 4795 } 4796 return (1); 4797 } 4798 NFSUNLOCKSTATE(); 4799 4800 /* 4801 * Ok, we can expire the conflicting client. 4802 */ 4803 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 4804 nfsrv_backupstable(); 4805 nfsrv_cleanclient(clp, p); 4806 nfsrv_freedeleglist(&clp->lc_deleg); 4807 nfsrv_freedeleglist(&clp->lc_olddeleg); 4808 LIST_REMOVE(clp, lc_hash); 4809 nfsrv_zapclient(clp, p); 4810 return (1); 4811 } 4812 4813 /* 4814 * Resolve a delegation conflict. 4815 * Returns 0 to indicate the conflict was resolved without sleeping. 4816 * Return -1 to indicate that the caller should check for conflicts again. 4817 * Return > 0 for an error that should be returned, normally NFSERR_DELAY. 4818 * 4819 * Also, manipulate the nfsv4root_lock, as required. It isn't changed 4820 * for a return of 0, since there was no sleep and it could be required 4821 * later. It is released for a return of NFSERR_DELAY, since the caller 4822 * will return that error. It is released when a sleep was done waiting 4823 * for the delegation to be returned or expire (so that other nfsds can 4824 * handle ops). Then, it must be acquired for the write to stable storage. 4825 * (This function is somewhat similar to nfsrv_clientconflict(), but 4826 * the semantics differ in a couple of subtle ways. The return of 0 4827 * indicates the conflict was resolved without sleeping here, not 4828 * that the conflict can't be resolved and the handling of nfsv4root_lock 4829 * differs, as noted above.) 4830 * Unlocks State before returning a non-zero value. 4831 */ 4832 static int 4833 nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p, 4834 vnode_t vp) 4835 { 4836 struct nfsclient *clp = stp->ls_clp; 4837 int gotlock, error, lktype = 0, retrycnt, zapped_clp; 4838 nfsv4stateid_t tstateid; 4839 fhandle_t tfh; 4840 4841 /* 4842 * If the conflict is with an old delegation... 4843 */ 4844 if (stp->ls_flags & NFSLCK_OLDDELEG) { 4845 /* 4846 * You can delete it, if it has expired. 4847 */ 4848 if (clp->lc_delegtime < NFSD_MONOSEC) { 4849 nfsrv_freedeleg(stp); 4850 NFSUNLOCKSTATE(); 4851 error = -1; 4852 goto out; 4853 } 4854 NFSUNLOCKSTATE(); 4855 /* 4856 * During this delay, the old delegation could expire or it 4857 * could be recovered by the client via an Open with 4858 * CLAIM_DELEGATE_PREV. 4859 * Release the nfsv4root_lock, if held. 4860 */ 4861 if (*haslockp) { 4862 *haslockp = 0; 4863 NFSLOCKV4ROOTMUTEX(); 4864 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4865 NFSUNLOCKV4ROOTMUTEX(); 4866 } 4867 error = NFSERR_DELAY; 4868 goto out; 4869 } 4870 4871 /* 4872 * It's a current delegation, so: 4873 * - check to see if the delegation has expired 4874 * - if so, get the v4root lock and then expire it 4875 */ 4876 if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) { 4877 /* 4878 * - do a recall callback, since not yet done 4879 * For now, never allow truncate to be set. To use 4880 * truncate safely, it must be guaranteed that the 4881 * Remove, Rename or Setattr with size of 0 will 4882 * succeed and that would require major changes to 4883 * the VFS/Vnode OPs. 4884 * Set the expiry time large enough so that it won't expire 4885 * until after the callback, then set it correctly, once 4886 * the callback is done. (The delegation will now time 4887 * out whether or not the Recall worked ok. The timeout 4888 * will be extended when ops are done on the delegation 4889 * stateid, up to the timelimit.) 4890 */ 4891 stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) + 4892 NFSRV_LEASEDELTA; 4893 stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) + 4894 NFSRV_LEASEDELTA; 4895 stp->ls_flags |= NFSLCK_DELEGRECALL; 4896 4897 /* 4898 * Loop NFSRV_CBRETRYCNT times while the CBRecall replies 4899 * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done 4900 * in order to try and avoid a race that could happen 4901 * when a CBRecall request passed the Open reply with 4902 * the delegation in it when transitting the network. 4903 * Since nfsrv_docallback will sleep, don't use stp after 4904 * the call. 4905 */ 4906 NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid, 4907 sizeof (tstateid)); 4908 NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh, 4909 sizeof (tfh)); 4910 NFSUNLOCKSTATE(); 4911 if (*haslockp) { 4912 *haslockp = 0; 4913 NFSLOCKV4ROOTMUTEX(); 4914 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4915 NFSUNLOCKV4ROOTMUTEX(); 4916 } 4917 retrycnt = 0; 4918 do { 4919 error = nfsrv_docallback(clp, NFSV4OP_CBRECALL, 4920 &tstateid, 0, &tfh, NULL, NULL, p); 4921 retrycnt++; 4922 } while ((error == NFSERR_BADSTATEID || 4923 error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT); 4924 error = NFSERR_DELAY; 4925 goto out; 4926 } 4927 4928 if (clp->lc_expiry >= NFSD_MONOSEC && 4929 stp->ls_delegtime >= NFSD_MONOSEC) { 4930 NFSUNLOCKSTATE(); 4931 /* 4932 * A recall has been done, but it has not yet expired. 4933 * So, RETURN_DELAY. 4934 */ 4935 if (*haslockp) { 4936 *haslockp = 0; 4937 NFSLOCKV4ROOTMUTEX(); 4938 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4939 NFSUNLOCKV4ROOTMUTEX(); 4940 } 4941 error = NFSERR_DELAY; 4942 goto out; 4943 } 4944 4945 /* 4946 * If we don't yet have the lock, just get it and then return, 4947 * since we need that before deleting expired state, such as 4948 * this delegation. 4949 * When getting the lock, unlock the vnode, so other nfsds that 4950 * are in progress, won't get stuck waiting for the vnode lock. 4951 */ 4952 if (*haslockp == 0) { 4953 NFSUNLOCKSTATE(); 4954 if (vp != NULL) { 4955 lktype = NFSVOPISLOCKED(vp); 4956 NFSVOPUNLOCK(vp, 0); 4957 } 4958 NFSLOCKV4ROOTMUTEX(); 4959 nfsv4_relref(&nfsv4rootfs_lock); 4960 do { 4961 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4962 NFSV4ROOTLOCKMUTEXPTR, NULL); 4963 } while (!gotlock); 4964 NFSUNLOCKV4ROOTMUTEX(); 4965 *haslockp = 1; 4966 if (vp != NULL) { 4967 NFSVOPLOCK(vp, lktype | LK_RETRY); 4968 if ((vp->v_iflag & VI_DOOMED) != 0) { 4969 *haslockp = 0; 4970 NFSLOCKV4ROOTMUTEX(); 4971 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4972 NFSUNLOCKV4ROOTMUTEX(); 4973 error = NFSERR_PERM; 4974 goto out; 4975 } 4976 } 4977 error = -1; 4978 goto out; 4979 } 4980 4981 NFSUNLOCKSTATE(); 4982 /* 4983 * Ok, we can delete the expired delegation. 4984 * First, write the Revoke record to stable storage and then 4985 * clear out the conflict. 4986 * Since all other nfsd threads are now blocked, we can safely 4987 * sleep without the state changing. 4988 */ 4989 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 4990 nfsrv_backupstable(); 4991 if (clp->lc_expiry < NFSD_MONOSEC) { 4992 nfsrv_cleanclient(clp, p); 4993 nfsrv_freedeleglist(&clp->lc_deleg); 4994 nfsrv_freedeleglist(&clp->lc_olddeleg); 4995 LIST_REMOVE(clp, lc_hash); 4996 zapped_clp = 1; 4997 } else { 4998 nfsrv_freedeleg(stp); 4999 zapped_clp = 0; 5000 } 5001 if (zapped_clp) 5002 nfsrv_zapclient(clp, p); 5003 error = -1; 5004 5005 out: 5006 NFSEXITCODE(error); 5007 return (error); 5008 } 5009 5010 /* 5011 * Check for a remove allowed, if remove is set to 1 and get rid of 5012 * delegations. 5013 */ 5014 APPLESTATIC int 5015 nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p) 5016 { 5017 struct nfsstate *stp; 5018 struct nfslockfile *lfp; 5019 int error, haslock = 0; 5020 fhandle_t nfh; 5021 5022 /* 5023 * First, get the lock file structure. 5024 * (A return of -1 means no associated state, so remove ok.) 5025 */ 5026 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 5027 tryagain: 5028 NFSLOCKSTATE(); 5029 if (!error) 5030 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 5031 if (error) { 5032 NFSUNLOCKSTATE(); 5033 if (haslock) { 5034 NFSLOCKV4ROOTMUTEX(); 5035 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5036 NFSUNLOCKV4ROOTMUTEX(); 5037 } 5038 if (error == -1) 5039 error = 0; 5040 goto out; 5041 } 5042 5043 /* 5044 * Now, we must Recall any delegations. 5045 */ 5046 error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p); 5047 if (error) { 5048 /* 5049 * nfsrv_cleandeleg() unlocks state for non-zero 5050 * return. 5051 */ 5052 if (error == -1) 5053 goto tryagain; 5054 if (haslock) { 5055 NFSLOCKV4ROOTMUTEX(); 5056 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5057 NFSUNLOCKV4ROOTMUTEX(); 5058 } 5059 goto out; 5060 } 5061 5062 /* 5063 * Now, look for a conflicting open share. 5064 */ 5065 if (remove) { 5066 /* 5067 * If the entry in the directory was the last reference to the 5068 * corresponding filesystem object, the object can be destroyed 5069 * */ 5070 if(lfp->lf_usecount>1) 5071 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 5072 if (stp->ls_flags & NFSLCK_WRITEDENY) { 5073 error = NFSERR_FILEOPEN; 5074 break; 5075 } 5076 } 5077 } 5078 5079 NFSUNLOCKSTATE(); 5080 if (haslock) { 5081 NFSLOCKV4ROOTMUTEX(); 5082 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5083 NFSUNLOCKV4ROOTMUTEX(); 5084 } 5085 5086 out: 5087 NFSEXITCODE(error); 5088 return (error); 5089 } 5090 5091 /* 5092 * Clear out all delegations for the file referred to by lfp. 5093 * May return NFSERR_DELAY, if there will be a delay waiting for 5094 * delegations to expire. 5095 * Returns -1 to indicate it slept while recalling a delegation. 5096 * This function has the side effect of deleting the nfslockfile structure, 5097 * if it no longer has associated state and didn't have to sleep. 5098 * Unlocks State before a non-zero value is returned. 5099 */ 5100 static int 5101 nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 5102 struct nfsclient *clp, int *haslockp, NFSPROC_T *p) 5103 { 5104 struct nfsstate *stp, *nstp; 5105 int ret = 0; 5106 5107 stp = LIST_FIRST(&lfp->lf_deleg); 5108 while (stp != LIST_END(&lfp->lf_deleg)) { 5109 nstp = LIST_NEXT(stp, ls_file); 5110 if (stp->ls_clp != clp) { 5111 ret = nfsrv_delegconflict(stp, haslockp, p, vp); 5112 if (ret) { 5113 /* 5114 * nfsrv_delegconflict() unlocks state 5115 * when it returns non-zero. 5116 */ 5117 goto out; 5118 } 5119 } 5120 stp = nstp; 5121 } 5122 out: 5123 NFSEXITCODE(ret); 5124 return (ret); 5125 } 5126 5127 /* 5128 * There are certain operations that, when being done outside of NFSv4, 5129 * require that any NFSv4 delegation for the file be recalled. 5130 * This function is to be called for those cases: 5131 * VOP_RENAME() - When a delegation is being recalled for any reason, 5132 * the client may have to do Opens against the server, using the file's 5133 * final component name. If the file has been renamed on the server, 5134 * that component name will be incorrect and the Open will fail. 5135 * VOP_REMOVE() - Theoretically, a client could Open a file after it has 5136 * been removed on the server, if there is a delegation issued to 5137 * that client for the file. I say "theoretically" since clients 5138 * normally do an Access Op before the Open and that Access Op will 5139 * fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so 5140 * they will detect the file's removal in the same manner. (There is 5141 * one case where RFC3530 allows a client to do an Open without first 5142 * doing an Access Op, which is passage of a check against the ACE 5143 * returned with a Write delegation, but current practice is to ignore 5144 * the ACE and always do an Access Op.) 5145 * Since the functions can only be called with an unlocked vnode, this 5146 * can't be done at this time. 5147 * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range 5148 * locks locally in the client, which are not visible to the server. To 5149 * deal with this, issuing of delegations for a vnode must be disabled 5150 * and all delegations for the vnode recalled. This is done via the 5151 * second function, using the VV_DISABLEDELEG vflag on the vnode. 5152 */ 5153 APPLESTATIC void 5154 nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p) 5155 { 5156 time_t starttime; 5157 int error; 5158 5159 /* 5160 * First, check to see if the server is currently running and it has 5161 * been called for a regular file when issuing delegations. 5162 */ 5163 if (newnfs_numnfsd == 0 || vp->v_type != VREG || 5164 nfsrv_issuedelegs == 0) 5165 return; 5166 5167 KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp)); 5168 /* 5169 * First, get a reference on the nfsv4rootfs_lock so that an 5170 * exclusive lock cannot be acquired by another thread. 5171 */ 5172 NFSLOCKV4ROOTMUTEX(); 5173 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 5174 NFSUNLOCKV4ROOTMUTEX(); 5175 5176 /* 5177 * Now, call nfsrv_checkremove() in a loop while it returns 5178 * NFSERR_DELAY. Return upon any other error or when timed out. 5179 */ 5180 starttime = NFSD_MONOSEC; 5181 do { 5182 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { 5183 error = nfsrv_checkremove(vp, 0, p); 5184 NFSVOPUNLOCK(vp, 0); 5185 } else 5186 error = EPERM; 5187 if (error == NFSERR_DELAY) { 5188 if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO) 5189 break; 5190 /* Sleep for a short period of time */ 5191 (void) nfs_catnap(PZERO, 0, "nfsremove"); 5192 } 5193 } while (error == NFSERR_DELAY); 5194 NFSLOCKV4ROOTMUTEX(); 5195 nfsv4_relref(&nfsv4rootfs_lock); 5196 NFSUNLOCKV4ROOTMUTEX(); 5197 } 5198 5199 APPLESTATIC void 5200 nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p) 5201 { 5202 5203 #ifdef VV_DISABLEDELEG 5204 /* 5205 * First, flag issuance of delegations disabled. 5206 */ 5207 atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG); 5208 #endif 5209 5210 /* 5211 * Then call nfsd_recalldelegation() to get rid of all extant 5212 * delegations. 5213 */ 5214 nfsd_recalldelegation(vp, p); 5215 } 5216 5217 /* 5218 * Check for conflicting locks, etc. and then get rid of delegations. 5219 * (At one point I thought that I should get rid of delegations for any 5220 * Setattr, since it could potentially disallow the I/O op (read or write) 5221 * allowed by the delegation. However, Setattr Ops that aren't changing 5222 * the size get a stateid of all 0s, so you can't tell if it is a delegation 5223 * for the same client or a different one, so I decided to only get rid 5224 * of delegations for other clients when the size is being changed.) 5225 * In general, a Setattr can disable NFS I/O Ops that are outstanding, such 5226 * as Write backs, even if there is no delegation, so it really isn't any 5227 * different?) 5228 */ 5229 APPLESTATIC int 5230 nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd, 5231 nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp, 5232 struct nfsexstuff *exp, NFSPROC_T *p) 5233 { 5234 struct nfsstate st, *stp = &st; 5235 struct nfslock lo, *lop = &lo; 5236 int error = 0; 5237 nfsquad_t clientid; 5238 5239 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) { 5240 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 5241 lop->lo_first = nvap->na_size; 5242 } else { 5243 stp->ls_flags = 0; 5244 lop->lo_first = 0; 5245 } 5246 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) || 5247 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) || 5248 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) || 5249 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL)) 5250 stp->ls_flags |= NFSLCK_SETATTR; 5251 if (stp->ls_flags == 0) 5252 goto out; 5253 lop->lo_end = NFS64BITSSET; 5254 lop->lo_flags = NFSLCK_WRITE; 5255 stp->ls_ownerlen = 0; 5256 stp->ls_op = NULL; 5257 stp->ls_uid = nd->nd_cred->cr_uid; 5258 stp->ls_stateid.seqid = stateidp->seqid; 5259 clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0]; 5260 clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1]; 5261 stp->ls_stateid.other[2] = stateidp->other[2]; 5262 error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 5263 stateidp, exp, nd, p); 5264 5265 out: 5266 NFSEXITCODE2(error, nd); 5267 return (error); 5268 } 5269 5270 /* 5271 * Check for a write delegation and do a CBGETATTR if there is one, updating 5272 * the attributes, as required. 5273 * Should I return an error if I can't get the attributes? (For now, I'll 5274 * just return ok. 5275 */ 5276 APPLESTATIC int 5277 nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp, 5278 struct nfsvattr *nvap, nfsattrbit_t *attrbitp, struct ucred *cred, 5279 NFSPROC_T *p) 5280 { 5281 struct nfsstate *stp; 5282 struct nfslockfile *lfp; 5283 struct nfsclient *clp; 5284 struct nfsvattr nva; 5285 fhandle_t nfh; 5286 int error = 0; 5287 nfsattrbit_t cbbits; 5288 u_quad_t delegfilerev; 5289 5290 NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits); 5291 if (!NFSNONZERO_ATTRBIT(&cbbits)) 5292 goto out; 5293 5294 /* 5295 * Get the lock file structure. 5296 * (A return of -1 means no associated state, so return ok.) 5297 */ 5298 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 5299 NFSLOCKSTATE(); 5300 if (!error) 5301 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 5302 if (error) { 5303 NFSUNLOCKSTATE(); 5304 if (error == -1) 5305 error = 0; 5306 goto out; 5307 } 5308 5309 /* 5310 * Now, look for a write delegation. 5311 */ 5312 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 5313 if (stp->ls_flags & NFSLCK_DELEGWRITE) 5314 break; 5315 } 5316 if (stp == LIST_END(&lfp->lf_deleg)) { 5317 NFSUNLOCKSTATE(); 5318 goto out; 5319 } 5320 clp = stp->ls_clp; 5321 delegfilerev = stp->ls_filerev; 5322 5323 /* 5324 * If the Write delegation was issued as a part of this Compound RPC 5325 * or if we have an Implied Clientid (used in a previous Op in this 5326 * compound) and it is the client the delegation was issued to, 5327 * just return ok. 5328 * I also assume that it is from the same client iff the network 5329 * host IP address is the same as the callback address. (Not 5330 * exactly correct by the RFC, but avoids a lot of Getattr 5331 * callbacks.) 5332 */ 5333 if (nd->nd_compref == stp->ls_compref || 5334 ((nd->nd_flag & ND_IMPLIEDCLID) && 5335 clp->lc_clientid.qval == nd->nd_clientid.qval) || 5336 nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) { 5337 NFSUNLOCKSTATE(); 5338 goto out; 5339 } 5340 5341 /* 5342 * We are now done with the delegation state structure, 5343 * so the statelock can be released and we can now tsleep(). 5344 */ 5345 5346 /* 5347 * Now, we must do the CB Getattr callback, to see if Change or Size 5348 * has changed. 5349 */ 5350 if (clp->lc_expiry >= NFSD_MONOSEC) { 5351 NFSUNLOCKSTATE(); 5352 NFSVNO_ATTRINIT(&nva); 5353 nva.na_filerev = NFS64BITSSET; 5354 error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL, 5355 0, &nfh, &nva, &cbbits, p); 5356 if (!error) { 5357 if ((nva.na_filerev != NFS64BITSSET && 5358 nva.na_filerev > delegfilerev) || 5359 (NFSVNO_ISSETSIZE(&nva) && 5360 nva.na_size != nvap->na_size)) { 5361 error = nfsvno_updfilerev(vp, nvap, cred, p); 5362 if (NFSVNO_ISSETSIZE(&nva)) 5363 nvap->na_size = nva.na_size; 5364 } 5365 } else 5366 error = 0; /* Ignore callback errors for now. */ 5367 } else { 5368 NFSUNLOCKSTATE(); 5369 } 5370 5371 out: 5372 NFSEXITCODE2(error, nd); 5373 return (error); 5374 } 5375 5376 /* 5377 * This function looks for openowners that haven't had any opens for 5378 * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS 5379 * is set. 5380 */ 5381 APPLESTATIC void 5382 nfsrv_throwawayopens(NFSPROC_T *p) 5383 { 5384 struct nfsclient *clp, *nclp; 5385 struct nfsstate *stp, *nstp; 5386 int i; 5387 5388 NFSLOCKSTATE(); 5389 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS; 5390 /* 5391 * For each client... 5392 */ 5393 for (i = 0; i < nfsrv_clienthashsize; i++) { 5394 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 5395 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { 5396 if (LIST_EMPTY(&stp->ls_open) && 5397 (stp->ls_noopens > NFSNOOPEN || 5398 (nfsrv_openpluslock * 2) > 5399 nfsrv_v4statelimit)) 5400 nfsrv_freeopenowner(stp, 0, p); 5401 } 5402 } 5403 } 5404 NFSUNLOCKSTATE(); 5405 } 5406 5407 /* 5408 * This function checks to see if the credentials are the same. 5409 * Returns 1 for not same, 0 otherwise. 5410 */ 5411 static int 5412 nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp) 5413 { 5414 5415 if (nd->nd_flag & ND_GSS) { 5416 if (!(clp->lc_flags & LCL_GSS)) 5417 return (1); 5418 if (clp->lc_flags & LCL_NAME) { 5419 if (nd->nd_princlen != clp->lc_namelen || 5420 NFSBCMP(nd->nd_principal, clp->lc_name, 5421 clp->lc_namelen)) 5422 return (1); 5423 else 5424 return (0); 5425 } 5426 if (nd->nd_cred->cr_uid == clp->lc_uid) 5427 return (0); 5428 else 5429 return (1); 5430 } else if (clp->lc_flags & LCL_GSS) 5431 return (1); 5432 /* 5433 * For AUTH_SYS, allow the same uid or root. (This is underspecified 5434 * in RFC3530, which talks about principals, but doesn't say anything 5435 * about uids for AUTH_SYS.) 5436 */ 5437 if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0) 5438 return (0); 5439 else 5440 return (1); 5441 } 5442 5443 /* 5444 * Calculate the lease expiry time. 5445 */ 5446 static time_t 5447 nfsrv_leaseexpiry(void) 5448 { 5449 5450 if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC) 5451 return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA)); 5452 return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA); 5453 } 5454 5455 /* 5456 * Delay the delegation timeout as far as ls_delegtimelimit, as required. 5457 */ 5458 static void 5459 nfsrv_delaydelegtimeout(struct nfsstate *stp) 5460 { 5461 5462 if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0) 5463 return; 5464 5465 if ((stp->ls_delegtime + 15) > NFSD_MONOSEC && 5466 stp->ls_delegtime < stp->ls_delegtimelimit) { 5467 stp->ls_delegtime += nfsrv_lease; 5468 if (stp->ls_delegtime > stp->ls_delegtimelimit) 5469 stp->ls_delegtime = stp->ls_delegtimelimit; 5470 } 5471 } 5472 5473 /* 5474 * This function checks to see if there is any other state associated 5475 * with the openowner for this Open. 5476 * It returns 1 if there is no other state, 0 otherwise. 5477 */ 5478 static int 5479 nfsrv_nootherstate(struct nfsstate *stp) 5480 { 5481 struct nfsstate *tstp; 5482 5483 LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) { 5484 if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock)) 5485 return (0); 5486 } 5487 return (1); 5488 } 5489 5490 /* 5491 * Create a list of lock deltas (changes to local byte range locking 5492 * that can be rolled back using the list) and apply the changes via 5493 * nfsvno_advlock(). Optionally, lock the list. It is expected that either 5494 * the rollback or update function will be called after this. 5495 * It returns an error (and rolls back, as required), if any nfsvno_advlock() 5496 * call fails. If it returns an error, it will unlock the list. 5497 */ 5498 static int 5499 nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, 5500 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5501 { 5502 struct nfslock *lop, *nlop; 5503 int error = 0; 5504 5505 /* Loop through the list of locks. */ 5506 lop = LIST_FIRST(&lfp->lf_locallock); 5507 while (first < end && lop != NULL) { 5508 nlop = LIST_NEXT(lop, lo_lckowner); 5509 if (first >= lop->lo_end) { 5510 /* not there yet */ 5511 lop = nlop; 5512 } else if (first < lop->lo_first) { 5513 /* new one starts before entry in list */ 5514 if (end <= lop->lo_first) { 5515 /* no overlap between old and new */ 5516 error = nfsrv_dolocal(vp, lfp, flags, 5517 NFSLCK_UNLOCK, first, end, cfp, p); 5518 if (error != 0) 5519 break; 5520 first = end; 5521 } else { 5522 /* handle fragment overlapped with new one */ 5523 error = nfsrv_dolocal(vp, lfp, flags, 5524 NFSLCK_UNLOCK, first, lop->lo_first, cfp, 5525 p); 5526 if (error != 0) 5527 break; 5528 first = lop->lo_first; 5529 } 5530 } else { 5531 /* new one overlaps this entry in list */ 5532 if (end <= lop->lo_end) { 5533 /* overlaps all of new one */ 5534 error = nfsrv_dolocal(vp, lfp, flags, 5535 lop->lo_flags, first, end, cfp, p); 5536 if (error != 0) 5537 break; 5538 first = end; 5539 } else { 5540 /* handle fragment overlapped with new one */ 5541 error = nfsrv_dolocal(vp, lfp, flags, 5542 lop->lo_flags, first, lop->lo_end, cfp, p); 5543 if (error != 0) 5544 break; 5545 first = lop->lo_end; 5546 lop = nlop; 5547 } 5548 } 5549 } 5550 if (first < end && error == 0) 5551 /* handle fragment past end of list */ 5552 error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first, 5553 end, cfp, p); 5554 5555 NFSEXITCODE(error); 5556 return (error); 5557 } 5558 5559 /* 5560 * Local lock unlock. Unlock all byte ranges that are no longer locked 5561 * by NFSv4. To do this, unlock any subranges of first-->end that 5562 * do not overlap with the byte ranges of any lock in the lfp->lf_lock 5563 * list. This list has all locks for the file held by other 5564 * <clientid, lockowner> tuples. The list is ordered by increasing 5565 * lo_first value, but may have entries that overlap each other, for 5566 * the case of read locks. 5567 */ 5568 static void 5569 nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first, 5570 uint64_t init_end, NFSPROC_T *p) 5571 { 5572 struct nfslock *lop; 5573 uint64_t first, end, prevfirst; 5574 5575 first = init_first; 5576 end = init_end; 5577 while (first < init_end) { 5578 /* Loop through all nfs locks, adjusting first and end */ 5579 prevfirst = 0; 5580 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { 5581 KASSERT(prevfirst <= lop->lo_first, 5582 ("nfsv4 locks out of order")); 5583 KASSERT(lop->lo_first < lop->lo_end, 5584 ("nfsv4 bogus lock")); 5585 prevfirst = lop->lo_first; 5586 if (first >= lop->lo_first && 5587 first < lop->lo_end) 5588 /* 5589 * Overlaps with initial part, so trim 5590 * off that initial part by moving first past 5591 * it. 5592 */ 5593 first = lop->lo_end; 5594 else if (end > lop->lo_first && 5595 lop->lo_first > first) { 5596 /* 5597 * This lock defines the end of the 5598 * segment to unlock, so set end to the 5599 * start of it and break out of the loop. 5600 */ 5601 end = lop->lo_first; 5602 break; 5603 } 5604 if (first >= end) 5605 /* 5606 * There is no segment left to do, so 5607 * break out of this loop and then exit 5608 * the outer while() since first will be set 5609 * to end, which must equal init_end here. 5610 */ 5611 break; 5612 } 5613 if (first < end) { 5614 /* Unlock this segment */ 5615 (void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK, 5616 NFSLCK_READ, first, end, NULL, p); 5617 nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK, 5618 first, end); 5619 } 5620 /* 5621 * Now move past this segment and look for any further 5622 * segment in the range, if there is one. 5623 */ 5624 first = end; 5625 end = init_end; 5626 } 5627 } 5628 5629 /* 5630 * Do the local lock operation and update the rollback list, as required. 5631 * Perform the rollback and return the error if nfsvno_advlock() fails. 5632 */ 5633 static int 5634 nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags, 5635 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5636 { 5637 struct nfsrollback *rlp; 5638 int error = 0, ltype, oldltype; 5639 5640 if (flags & NFSLCK_WRITE) 5641 ltype = F_WRLCK; 5642 else if (flags & NFSLCK_READ) 5643 ltype = F_RDLCK; 5644 else 5645 ltype = F_UNLCK; 5646 if (oldflags & NFSLCK_WRITE) 5647 oldltype = F_WRLCK; 5648 else if (oldflags & NFSLCK_READ) 5649 oldltype = F_RDLCK; 5650 else 5651 oldltype = F_UNLCK; 5652 if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK)) 5653 /* nothing to do */ 5654 goto out; 5655 error = nfsvno_advlock(vp, ltype, first, end, p); 5656 if (error != 0) { 5657 if (cfp != NULL) { 5658 cfp->cl_clientid.lval[0] = 0; 5659 cfp->cl_clientid.lval[1] = 0; 5660 cfp->cl_first = 0; 5661 cfp->cl_end = NFS64BITSSET; 5662 cfp->cl_flags = NFSLCK_WRITE; 5663 cfp->cl_ownerlen = 5; 5664 NFSBCOPY("LOCAL", cfp->cl_owner, 5); 5665 } 5666 nfsrv_locallock_rollback(vp, lfp, p); 5667 } else if (ltype != F_UNLCK) { 5668 rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK, 5669 M_WAITOK); 5670 rlp->rlck_first = first; 5671 rlp->rlck_end = end; 5672 rlp->rlck_type = oldltype; 5673 LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list); 5674 } 5675 5676 out: 5677 NFSEXITCODE(error); 5678 return (error); 5679 } 5680 5681 /* 5682 * Roll back local lock changes and free up the rollback list. 5683 */ 5684 static void 5685 nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p) 5686 { 5687 struct nfsrollback *rlp, *nrlp; 5688 5689 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) { 5690 (void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first, 5691 rlp->rlck_end, p); 5692 free(rlp, M_NFSDROLLBACK); 5693 } 5694 LIST_INIT(&lfp->lf_rollback); 5695 } 5696 5697 /* 5698 * Update local lock list and delete rollback list (ie now committed to the 5699 * local locks). Most of the work is done by the internal function. 5700 */ 5701 static void 5702 nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first, 5703 uint64_t end) 5704 { 5705 struct nfsrollback *rlp, *nrlp; 5706 struct nfslock *new_lop, *other_lop; 5707 5708 new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK); 5709 if (flags & (NFSLCK_READ | NFSLCK_WRITE)) 5710 other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, 5711 M_WAITOK); 5712 else 5713 other_lop = NULL; 5714 new_lop->lo_flags = flags; 5715 new_lop->lo_first = first; 5716 new_lop->lo_end = end; 5717 nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp); 5718 if (new_lop != NULL) 5719 free(new_lop, M_NFSDLOCK); 5720 if (other_lop != NULL) 5721 free(other_lop, M_NFSDLOCK); 5722 5723 /* and get rid of the rollback list */ 5724 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) 5725 free(rlp, M_NFSDROLLBACK); 5726 LIST_INIT(&lfp->lf_rollback); 5727 } 5728 5729 /* 5730 * Lock the struct nfslockfile for local lock updating. 5731 */ 5732 static void 5733 nfsrv_locklf(struct nfslockfile *lfp) 5734 { 5735 int gotlock; 5736 5737 /* lf_usecount ensures *lfp won't be free'd */ 5738 lfp->lf_usecount++; 5739 do { 5740 gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL, 5741 NFSSTATEMUTEXPTR, NULL); 5742 } while (gotlock == 0); 5743 lfp->lf_usecount--; 5744 } 5745 5746 /* 5747 * Unlock the struct nfslockfile after local lock updating. 5748 */ 5749 static void 5750 nfsrv_unlocklf(struct nfslockfile *lfp) 5751 { 5752 5753 nfsv4_unlock(&lfp->lf_locallock_lck, 0); 5754 } 5755 5756 /* 5757 * Clear out all state for the NFSv4 server. 5758 * Must be called by a thread that can sleep when no nfsds are running. 5759 */ 5760 void 5761 nfsrv_throwawayallstate(NFSPROC_T *p) 5762 { 5763 struct nfsclient *clp, *nclp; 5764 struct nfslockfile *lfp, *nlfp; 5765 int i; 5766 5767 /* 5768 * For each client, clean out the state and then free the structure. 5769 */ 5770 for (i = 0; i < nfsrv_clienthashsize; i++) { 5771 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 5772 nfsrv_cleanclient(clp, p); 5773 nfsrv_freedeleglist(&clp->lc_deleg); 5774 nfsrv_freedeleglist(&clp->lc_olddeleg); 5775 free(clp->lc_stateid, M_NFSDCLIENT); 5776 free(clp, M_NFSDCLIENT); 5777 } 5778 } 5779 5780 /* 5781 * Also, free up any remaining lock file structures. 5782 */ 5783 for (i = 0; i < nfsrv_lockhashsize; i++) { 5784 LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) { 5785 printf("nfsd unload: fnd a lock file struct\n"); 5786 nfsrv_freenfslockfile(lfp); 5787 } 5788 } 5789 } 5790 5791 /* 5792 * Check the sequence# for the session and slot provided as an argument. 5793 * Also, renew the lease if the session will return NFS_OK. 5794 */ 5795 int 5796 nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid, 5797 uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this, 5798 uint32_t *sflagsp, NFSPROC_T *p) 5799 { 5800 struct nfsdsession *sep; 5801 struct nfssessionhash *shp; 5802 int error; 5803 SVCXPRT *savxprt; 5804 5805 shp = NFSSESSIONHASH(nd->nd_sessionid); 5806 NFSLOCKSESSION(shp); 5807 sep = nfsrv_findsession(nd->nd_sessionid); 5808 if (sep == NULL) { 5809 NFSUNLOCKSESSION(shp); 5810 return (NFSERR_BADSESSION); 5811 } 5812 error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp, 5813 sep->sess_slots, NULL, NFSV4_SLOTS - 1); 5814 if (error != 0) { 5815 NFSUNLOCKSESSION(shp); 5816 return (error); 5817 } 5818 if (cache_this != 0) 5819 nd->nd_flag |= ND_SAVEREPLY; 5820 /* Renew the lease. */ 5821 sep->sess_clp->lc_expiry = nfsrv_leaseexpiry(); 5822 nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval; 5823 nd->nd_flag |= ND_IMPLIEDCLID; 5824 5825 /* 5826 * If this session handles the backchannel, save the nd_xprt for this 5827 * RPC, since this is the one being used. 5828 */ 5829 if (sep->sess_clp->lc_req.nr_client != NULL && 5830 (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) { 5831 savxprt = sep->sess_cbsess.nfsess_xprt; 5832 SVC_ACQUIRE(nd->nd_xprt); 5833 nd->nd_xprt->xp_p2 = 5834 sep->sess_clp->lc_req.nr_client->cl_private; 5835 nd->nd_xprt->xp_idletimeout = 0; /* Disable timeout. */ 5836 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt; 5837 if (savxprt != NULL) 5838 SVC_RELEASE(savxprt); 5839 } 5840 5841 *sflagsp = 0; 5842 if (sep->sess_clp->lc_req.nr_client == NULL) 5843 *sflagsp |= NFSV4SEQ_CBPATHDOWN; 5844 NFSUNLOCKSESSION(shp); 5845 if (error == NFSERR_EXPIRED) { 5846 *sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED; 5847 error = 0; 5848 } else if (error == NFSERR_ADMINREVOKED) { 5849 *sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED; 5850 error = 0; 5851 } 5852 *highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1; 5853 return (0); 5854 } 5855 5856 /* 5857 * Check/set reclaim complete for this session/clientid. 5858 */ 5859 int 5860 nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd) 5861 { 5862 struct nfsdsession *sep; 5863 struct nfssessionhash *shp; 5864 int error = 0; 5865 5866 shp = NFSSESSIONHASH(nd->nd_sessionid); 5867 NFSLOCKSTATE(); 5868 NFSLOCKSESSION(shp); 5869 sep = nfsrv_findsession(nd->nd_sessionid); 5870 if (sep == NULL) { 5871 NFSUNLOCKSESSION(shp); 5872 NFSUNLOCKSTATE(); 5873 return (NFSERR_BADSESSION); 5874 } 5875 5876 /* Check to see if reclaim complete has already happened. */ 5877 if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) 5878 error = NFSERR_COMPLETEALREADY; 5879 else 5880 sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE; 5881 NFSUNLOCKSESSION(shp); 5882 NFSUNLOCKSTATE(); 5883 return (error); 5884 } 5885 5886 /* 5887 * Cache the reply in a session slot. 5888 */ 5889 void 5890 nfsrv_cache_session(uint8_t *sessionid, uint32_t slotid, int repstat, 5891 struct mbuf **m) 5892 { 5893 struct nfsdsession *sep; 5894 struct nfssessionhash *shp; 5895 5896 shp = NFSSESSIONHASH(sessionid); 5897 NFSLOCKSESSION(shp); 5898 sep = nfsrv_findsession(sessionid); 5899 if (sep == NULL) { 5900 NFSUNLOCKSESSION(shp); 5901 printf("nfsrv_cache_session: no session\n"); 5902 m_freem(*m); 5903 return; 5904 } 5905 nfsv4_seqsess_cacherep(slotid, sep->sess_slots, repstat, m); 5906 NFSUNLOCKSESSION(shp); 5907 } 5908 5909 /* 5910 * Search for a session that matches the sessionid. 5911 */ 5912 static struct nfsdsession * 5913 nfsrv_findsession(uint8_t *sessionid) 5914 { 5915 struct nfsdsession *sep; 5916 struct nfssessionhash *shp; 5917 5918 shp = NFSSESSIONHASH(sessionid); 5919 LIST_FOREACH(sep, &shp->list, sess_hash) { 5920 if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID)) 5921 break; 5922 } 5923 return (sep); 5924 } 5925 5926 /* 5927 * Destroy a session. 5928 */ 5929 int 5930 nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid) 5931 { 5932 int error, samesess; 5933 5934 samesess = 0; 5935 if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID)) { 5936 samesess = 1; 5937 if ((nd->nd_flag & ND_LASTOP) == 0) 5938 return (NFSERR_BADSESSION); 5939 } 5940 error = nfsrv_freesession(NULL, sessionid); 5941 if (error == 0 && samesess != 0) 5942 nd->nd_flag &= ~ND_HASSEQUENCE; 5943 return (error); 5944 } 5945 5946 /* 5947 * Free up a session structure. 5948 */ 5949 static int 5950 nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid) 5951 { 5952 struct nfssessionhash *shp; 5953 int i; 5954 5955 NFSLOCKSTATE(); 5956 if (sep == NULL) { 5957 shp = NFSSESSIONHASH(sessionid); 5958 NFSLOCKSESSION(shp); 5959 sep = nfsrv_findsession(sessionid); 5960 } else { 5961 shp = NFSSESSIONHASH(sep->sess_sessionid); 5962 NFSLOCKSESSION(shp); 5963 } 5964 if (sep != NULL) { 5965 sep->sess_refcnt--; 5966 if (sep->sess_refcnt > 0) { 5967 NFSUNLOCKSESSION(shp); 5968 NFSUNLOCKSTATE(); 5969 return (0); 5970 } 5971 LIST_REMOVE(sep, sess_hash); 5972 LIST_REMOVE(sep, sess_list); 5973 } 5974 NFSUNLOCKSESSION(shp); 5975 NFSUNLOCKSTATE(); 5976 if (sep == NULL) 5977 return (NFSERR_BADSESSION); 5978 for (i = 0; i < NFSV4_SLOTS; i++) 5979 if (sep->sess_slots[i].nfssl_reply != NULL) 5980 m_freem(sep->sess_slots[i].nfssl_reply); 5981 if (sep->sess_cbsess.nfsess_xprt != NULL) 5982 SVC_RELEASE(sep->sess_cbsess.nfsess_xprt); 5983 free(sep, M_NFSDSESSION); 5984 return (0); 5985 } 5986 5987 /* 5988 * Free a stateid. 5989 * RFC5661 says that it should fail when there are associated opens, locks 5990 * or delegations. Since stateids represent opens, I don't see how you can 5991 * free an open stateid (it will be free'd when closed), so this function 5992 * only works for lock stateids (freeing the lock_owner) or delegations. 5993 */ 5994 int 5995 nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, 5996 NFSPROC_T *p) 5997 { 5998 struct nfsclient *clp; 5999 struct nfsstate *stp; 6000 int error; 6001 6002 NFSLOCKSTATE(); 6003 /* 6004 * Look up the stateid 6005 */ 6006 error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp, 6007 NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); 6008 if (error == 0) { 6009 /* First, check for a delegation. */ 6010 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) { 6011 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other, 6012 NFSX_STATEIDOTHER)) 6013 break; 6014 } 6015 if (stp != NULL) { 6016 nfsrv_freedeleg(stp); 6017 NFSUNLOCKSTATE(); 6018 return (error); 6019 } 6020 } 6021 /* Not a delegation, try for a lock_owner. */ 6022 if (error == 0) 6023 error = nfsrv_getstate(clp, stateidp, 0, &stp); 6024 if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD | 6025 NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0)) 6026 /* Not a lock_owner stateid. */ 6027 error = NFSERR_LOCKSHELD; 6028 if (error == 0 && !LIST_EMPTY(&stp->ls_lock)) 6029 error = NFSERR_LOCKSHELD; 6030 if (error == 0) 6031 nfsrv_freelockowner(stp, NULL, 0, p); 6032 NFSUNLOCKSTATE(); 6033 return (error); 6034 } 6035 6036 /* 6037 * Generate the xdr for an NFSv4.1 CBSequence Operation. 6038 */ 6039 static int 6040 nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp, 6041 int dont_replycache, struct nfsdsession **sepp) 6042 { 6043 struct nfsdsession *sep; 6044 uint32_t *tl, slotseq = 0; 6045 int maxslot, slotpos; 6046 uint8_t sessionid[NFSX_V4SESSIONID]; 6047 int error; 6048 6049 error = nfsv4_getcbsession(clp, sepp); 6050 if (error != 0) 6051 return (error); 6052 sep = *sepp; 6053 (void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot, 6054 &slotseq, sessionid); 6055 KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot")); 6056 6057 /* Build the Sequence arguments. */ 6058 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED); 6059 bcopy(sessionid, tl, NFSX_V4SESSIONID); 6060 tl += NFSX_V4SESSIONID / NFSX_UNSIGNED; 6061 nd->nd_slotseq = tl; 6062 *tl++ = txdr_unsigned(slotseq); 6063 *tl++ = txdr_unsigned(slotpos); 6064 *tl++ = txdr_unsigned(maxslot); 6065 if (dont_replycache == 0) 6066 *tl++ = newnfs_true; 6067 else 6068 *tl++ = newnfs_false; 6069 *tl = 0; /* No referring call list, for now. */ 6070 nd->nd_flag |= ND_HASSEQUENCE; 6071 return (0); 6072 } 6073 6074 /* 6075 * Get a session for the callback. 6076 */ 6077 static int 6078 nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp) 6079 { 6080 struct nfsdsession *sep; 6081 6082 NFSLOCKSTATE(); 6083 LIST_FOREACH(sep, &clp->lc_session, sess_list) { 6084 if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) 6085 break; 6086 } 6087 if (sep == NULL) { 6088 NFSUNLOCKSTATE(); 6089 return (NFSERR_BADSESSION); 6090 } 6091 sep->sess_refcnt++; 6092 *sepp = sep; 6093 NFSUNLOCKSTATE(); 6094 return (0); 6095 } 6096 6097 /* 6098 * Free up all backchannel xprts. This needs to be done when the nfsd threads 6099 * exit, since those transports will all be going away. 6100 * This is only called after all the nfsd threads are done performing RPCs, 6101 * so locking shouldn't be an issue. 6102 */ 6103 APPLESTATIC void 6104 nfsrv_freeallbackchannel_xprts(void) 6105 { 6106 struct nfsdsession *sep; 6107 struct nfsclient *clp; 6108 SVCXPRT *xprt; 6109 int i; 6110 6111 for (i = 0; i < nfsrv_clienthashsize; i++) { 6112 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 6113 LIST_FOREACH(sep, &clp->lc_session, sess_list) { 6114 xprt = sep->sess_cbsess.nfsess_xprt; 6115 sep->sess_cbsess.nfsess_xprt = NULL; 6116 if (xprt != NULL) 6117 SVC_RELEASE(xprt); 6118 } 6119 } 6120 } 6121 } 6122 6123