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