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