nfs_nfsdstate.c revision 325448
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 325448 2017-11-05 20:28:28Z 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 in_addr_t ival; 3892 u_char cval[4]; 3893 } ip; 3894 union { 3895 in_port_t 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 if (sad->sin_family == AF_INET) { 3990 rad->sin_addr.s_addr = sad->sin_addr.s_addr; 3991 rad->sin_port = 0x0; 3992 } 3993 clp->lc_program = 0; 3994 } 3995nfsmout: 3996 NFSEXITCODE2(error, nd); 3997 return (error); 3998} 3999 4000/* 4001 * Turn a string of up to three decimal digits into a number. Return -1 upon 4002 * error. 4003 */ 4004static int 4005nfsrv_getipnumber(u_char *cp) 4006{ 4007 int i = 0, j = 0; 4008 4009 while (*cp) { 4010 if (j > 2 || *cp < '0' || *cp > '9') 4011 return (-1); 4012 i *= 10; 4013 i += (*cp - '0'); 4014 cp++; 4015 j++; 4016 } 4017 if (i < 256) 4018 return (i); 4019 return (-1); 4020} 4021 4022/* 4023 * This function checks for restart conditions. 4024 */ 4025static int 4026nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 4027 nfsv4stateid_t *stateidp, int specialid) 4028{ 4029 int ret = 0; 4030 4031 /* 4032 * First check for a server restart. Open, LockT, ReleaseLockOwner 4033 * and DelegPurge have a clientid, the rest a stateid. 4034 */ 4035 if (flags & 4036 (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { 4037 if (clientid.lval[0] != nfsrvboottime) { 4038 ret = NFSERR_STALECLIENTID; 4039 goto out; 4040 } 4041 } else if (stateidp->other[0] != nfsrvboottime && 4042 specialid == 0) { 4043 ret = NFSERR_STALESTATEID; 4044 goto out; 4045 } 4046 4047 /* 4048 * Read, Write, Setattr and LockT can return NFSERR_GRACE and do 4049 * not use a lock/open owner seqid#, so the check can be done now. 4050 * (The others will be checked, as required, later.) 4051 */ 4052 if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST))) 4053 goto out; 4054 4055 NFSLOCKSTATE(); 4056 ret = nfsrv_checkgrace(NULL, NULL, flags); 4057 NFSUNLOCKSTATE(); 4058 4059out: 4060 NFSEXITCODE(ret); 4061 return (ret); 4062} 4063 4064/* 4065 * Check for grace. 4066 */ 4067static int 4068nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp, 4069 u_int32_t flags) 4070{ 4071 int error = 0; 4072 4073 if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) { 4074 if (flags & NFSLCK_RECLAIM) { 4075 error = NFSERR_NOGRACE; 4076 goto out; 4077 } 4078 } else { 4079 if (!(flags & NFSLCK_RECLAIM)) { 4080 error = NFSERR_GRACE; 4081 goto out; 4082 } 4083 if (nd != NULL && clp != NULL && 4084 (nd->nd_flag & ND_NFSV41) != 0 && 4085 (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) { 4086 error = NFSERR_NOGRACE; 4087 goto out; 4088 } 4089 4090 /* 4091 * If grace is almost over and we are still getting Reclaims, 4092 * extend grace a bit. 4093 */ 4094 if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > 4095 nfsrv_stablefirst.nsf_eograce) 4096 nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC + 4097 NFSRV_LEASEDELTA; 4098 } 4099 4100out: 4101 NFSEXITCODE(error); 4102 return (error); 4103} 4104 4105/* 4106 * Do a server callback. 4107 */ 4108static int 4109nfsrv_docallback(struct nfsclient *clp, int procnum, 4110 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, 4111 struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p) 4112{ 4113 mbuf_t m; 4114 u_int32_t *tl; 4115 struct nfsrv_descript nfsd, *nd = &nfsd; 4116 struct ucred *cred; 4117 int error = 0; 4118 u_int32_t callback; 4119 struct nfsdsession *sep = NULL; 4120 4121 cred = newnfs_getcred(); 4122 NFSLOCKSTATE(); /* mostly for lc_cbref++ */ 4123 if (clp->lc_flags & LCL_NEEDSCONFIRM) { 4124 NFSUNLOCKSTATE(); 4125 panic("docallb"); 4126 } 4127 clp->lc_cbref++; 4128 4129 /* 4130 * Fill the callback program# and version into the request 4131 * structure for newnfs_connect() to use. 4132 */ 4133 clp->lc_req.nr_prog = clp->lc_program; 4134#ifdef notnow 4135 if ((clp->lc_flags & LCL_NFSV41) != 0) 4136 clp->lc_req.nr_vers = NFSV41_CBVERS; 4137 else 4138#endif 4139 clp->lc_req.nr_vers = NFSV4_CBVERS; 4140 4141 /* 4142 * First, fill in some of the fields of nd and cr. 4143 */ 4144 nd->nd_flag = ND_NFSV4; 4145 if (clp->lc_flags & LCL_GSS) 4146 nd->nd_flag |= ND_KERBV; 4147 if ((clp->lc_flags & LCL_NFSV41) != 0) 4148 nd->nd_flag |= ND_NFSV41; 4149 nd->nd_repstat = 0; 4150 cred->cr_uid = clp->lc_uid; 4151 cred->cr_gid = clp->lc_gid; 4152 callback = clp->lc_callback; 4153 NFSUNLOCKSTATE(); 4154 cred->cr_ngroups = 1; 4155 4156 /* 4157 * Get the first mbuf for the request. 4158 */ 4159 MGET(m, M_WAITOK, MT_DATA); 4160 mbuf_setlen(m, 0); 4161 nd->nd_mreq = nd->nd_mb = m; 4162 nd->nd_bpos = NFSMTOD(m, caddr_t); 4163 4164 /* 4165 * and build the callback request. 4166 */ 4167 if (procnum == NFSV4OP_CBGETATTR) { 4168 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4169 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR, 4170 "CB Getattr", &sep); 4171 if (error != 0) { 4172 mbuf_freem(nd->nd_mreq); 4173 goto errout; 4174 } 4175 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 4176 (void)nfsrv_putattrbit(nd, attrbitp); 4177 } else if (procnum == NFSV4OP_CBRECALL) { 4178 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4179 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL, 4180 "CB Recall", &sep); 4181 if (error != 0) { 4182 mbuf_freem(nd->nd_mreq); 4183 goto errout; 4184 } 4185 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID); 4186 *tl++ = txdr_unsigned(stateidp->seqid); 4187 NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl, 4188 NFSX_STATEIDOTHER); 4189 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4190 if (trunc) 4191 *tl = newnfs_true; 4192 else 4193 *tl = newnfs_false; 4194 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 4195 } else if (procnum == NFSV4PROC_CBNULL) { 4196 nd->nd_procnum = NFSV4PROC_CBNULL; 4197 if ((clp->lc_flags & LCL_NFSV41) != 0) { 4198 error = nfsv4_getcbsession(clp, &sep); 4199 if (error != 0) { 4200 mbuf_freem(nd->nd_mreq); 4201 goto errout; 4202 } 4203 } 4204 } else { 4205 error = NFSERR_SERVERFAULT; 4206 mbuf_freem(nd->nd_mreq); 4207 goto errout; 4208 } 4209 4210 /* 4211 * Call newnfs_connect(), as required, and then newnfs_request(). 4212 */ 4213 (void) newnfs_sndlock(&clp->lc_req.nr_lock); 4214 if (clp->lc_req.nr_client == NULL) { 4215 if ((clp->lc_flags & LCL_NFSV41) != 0) 4216 error = ECONNREFUSED; 4217 else if (nd->nd_procnum == NFSV4PROC_CBNULL) 4218 error = newnfs_connect(NULL, &clp->lc_req, cred, 4219 NULL, 1); 4220 else 4221 error = newnfs_connect(NULL, &clp->lc_req, cred, 4222 NULL, 3); 4223 } 4224 newnfs_sndunlock(&clp->lc_req.nr_lock); 4225 if (!error) { 4226 if ((nd->nd_flag & ND_NFSV41) != 0) { 4227 KASSERT(sep != NULL, ("sep NULL")); 4228 if (sep->sess_cbsess.nfsess_xprt != NULL) 4229 error = newnfs_request(nd, NULL, clp, 4230 &clp->lc_req, NULL, NULL, cred, 4231 clp->lc_program, clp->lc_req.nr_vers, NULL, 4232 1, NULL, &sep->sess_cbsess); 4233 else { 4234 /* 4235 * This should probably never occur, but if a 4236 * client somehow does an RPC without a 4237 * SequenceID Op that causes a callback just 4238 * after the nfsd threads have been terminated 4239 * and restared we could conceivably get here 4240 * without a backchannel xprt. 4241 */ 4242 printf("nfsrv_docallback: no xprt\n"); 4243 error = ECONNREFUSED; 4244 } 4245 nfsrv_freesession(sep, NULL); 4246 } else 4247 error = newnfs_request(nd, NULL, clp, &clp->lc_req, 4248 NULL, NULL, cred, clp->lc_program, 4249 clp->lc_req.nr_vers, NULL, 1, NULL, NULL); 4250 } 4251errout: 4252 NFSFREECRED(cred); 4253 4254 /* 4255 * If error is set here, the Callback path isn't working 4256 * properly, so twiddle the appropriate LCL_ flags. 4257 * (nd_repstat != 0 indicates the Callback path is working, 4258 * but the callback failed on the client.) 4259 */ 4260 if (error) { 4261 /* 4262 * Mark the callback pathway down, which disabled issuing 4263 * of delegations and gets Renew to return NFSERR_CBPATHDOWN. 4264 */ 4265 NFSLOCKSTATE(); 4266 clp->lc_flags |= LCL_CBDOWN; 4267 NFSUNLOCKSTATE(); 4268 } else { 4269 /* 4270 * Callback worked. If the callback path was down, disable 4271 * callbacks, so no more delegations will be issued. (This 4272 * is done on the assumption that the callback pathway is 4273 * flakey.) 4274 */ 4275 NFSLOCKSTATE(); 4276 if (clp->lc_flags & LCL_CBDOWN) 4277 clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON); 4278 NFSUNLOCKSTATE(); 4279 if (nd->nd_repstat) 4280 error = nd->nd_repstat; 4281 else if (error == 0 && procnum == NFSV4OP_CBGETATTR) 4282 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, 4283 NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 4284 p, NULL); 4285 mbuf_freem(nd->nd_mrep); 4286 } 4287 NFSLOCKSTATE(); 4288 clp->lc_cbref--; 4289 if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) { 4290 clp->lc_flags &= ~LCL_WAKEUPWANTED; 4291 wakeup(clp); 4292 } 4293 NFSUNLOCKSTATE(); 4294 4295 NFSEXITCODE(error); 4296 return (error); 4297} 4298 4299/* 4300 * Set up the compound RPC for the callback. 4301 */ 4302static int 4303nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp, 4304 uint32_t callback, int op, const char *optag, struct nfsdsession **sepp) 4305{ 4306 uint32_t *tl; 4307 int error, len; 4308 4309 len = strlen(optag); 4310 (void)nfsm_strtom(nd, optag, len); 4311 NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED); 4312 if ((nd->nd_flag & ND_NFSV41) != 0) { 4313 *tl++ = txdr_unsigned(NFSV41_MINORVERSION); 4314 *tl++ = txdr_unsigned(callback); 4315 *tl++ = txdr_unsigned(2); 4316 *tl = txdr_unsigned(NFSV4OP_CBSEQUENCE); 4317 error = nfsv4_setcbsequence(nd, clp, 1, sepp); 4318 if (error != 0) 4319 return (error); 4320 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 4321 *tl = txdr_unsigned(op); 4322 } else { 4323 *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 4324 *tl++ = txdr_unsigned(callback); 4325 *tl++ = txdr_unsigned(1); 4326 *tl = txdr_unsigned(op); 4327 } 4328 return (0); 4329} 4330 4331/* 4332 * Return the next index# for a clientid. Mostly just increment and return 4333 * the next one, but... if the 32bit unsigned does actually wrap around, 4334 * it should be rebooted. 4335 * At an average rate of one new client per second, it will wrap around in 4336 * approximately 136 years. (I think the server will have been shut 4337 * down or rebooted before then.) 4338 */ 4339static u_int32_t 4340nfsrv_nextclientindex(void) 4341{ 4342 static u_int32_t client_index = 0; 4343 4344 client_index++; 4345 if (client_index != 0) 4346 return (client_index); 4347 4348 printf("%s: out of clientids\n", __func__); 4349 return (client_index); 4350} 4351 4352/* 4353 * Return the next index# for a stateid. Mostly just increment and return 4354 * the next one, but... if the 32bit unsigned does actually wrap around 4355 * (will a BSD server stay up that long?), find 4356 * new start and end values. 4357 */ 4358static u_int32_t 4359nfsrv_nextstateindex(struct nfsclient *clp) 4360{ 4361 struct nfsstate *stp; 4362 int i; 4363 u_int32_t canuse, min_index, max_index; 4364 4365 if (!(clp->lc_flags & LCL_INDEXNOTOK)) { 4366 clp->lc_stateindex++; 4367 if (clp->lc_stateindex != clp->lc_statemaxindex) 4368 return (clp->lc_stateindex); 4369 } 4370 4371 /* 4372 * Yuck, we've hit the end. 4373 * Look for a new min and max. 4374 */ 4375 min_index = 0; 4376 max_index = 0xffffffff; 4377 for (i = 0; i < nfsrv_statehashsize; i++) { 4378 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 4379 if (stp->ls_stateid.other[2] > 0x80000000) { 4380 if (stp->ls_stateid.other[2] < max_index) 4381 max_index = stp->ls_stateid.other[2]; 4382 } else { 4383 if (stp->ls_stateid.other[2] > min_index) 4384 min_index = stp->ls_stateid.other[2]; 4385 } 4386 } 4387 } 4388 4389 /* 4390 * Yikes, highly unlikely, but I'll handle it anyhow. 4391 */ 4392 if (min_index == 0x80000000 && max_index == 0x80000001) { 4393 canuse = 0; 4394 /* 4395 * Loop around until we find an unused entry. Return that 4396 * and set LCL_INDEXNOTOK, so the search will continue next time. 4397 * (This is one of those rare cases where a goto is the 4398 * cleanest way to code the loop.) 4399 */ 4400tryagain: 4401 for (i = 0; i < nfsrv_statehashsize; i++) { 4402 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 4403 if (stp->ls_stateid.other[2] == canuse) { 4404 canuse++; 4405 goto tryagain; 4406 } 4407 } 4408 } 4409 clp->lc_flags |= LCL_INDEXNOTOK; 4410 return (canuse); 4411 } 4412 4413 /* 4414 * Ok to start again from min + 1. 4415 */ 4416 clp->lc_stateindex = min_index + 1; 4417 clp->lc_statemaxindex = max_index; 4418 clp->lc_flags &= ~LCL_INDEXNOTOK; 4419 return (clp->lc_stateindex); 4420} 4421 4422/* 4423 * The following functions handle the stable storage file that deals with 4424 * the edge conditions described in RFC3530 Sec. 8.6.3. 4425 * The file is as follows: 4426 * - a single record at the beginning that has the lease time of the 4427 * previous server instance (before the last reboot) and the nfsrvboottime 4428 * values for the previous server boots. 4429 * These previous boot times are used to ensure that the current 4430 * nfsrvboottime does not, somehow, get set to a previous one. 4431 * (This is important so that Stale ClientIDs and StateIDs can 4432 * be recognized.) 4433 * The number of previous nfsvrboottime values preceeds the list. 4434 * - followed by some number of appended records with: 4435 * - client id string 4436 * - flag that indicates it is a record revoking state via lease 4437 * expiration or similar 4438 * OR has successfully acquired state. 4439 * These structures vary in length, with the client string at the end, up 4440 * to NFSV4_OPAQUELIMIT in size. 4441 * 4442 * At the end of the grace period, the file is truncated, the first 4443 * record is rewritten with updated information and any acquired state 4444 * records for successful reclaims of state are written. 4445 * 4446 * Subsequent records are appended when the first state is issued to 4447 * a client and when state is revoked for a client. 4448 * 4449 * When reading the file in, state issued records that come later in 4450 * the file override older ones, since the append log is in cronological order. 4451 * If, for some reason, the file can't be read, the grace period is 4452 * immediately terminated and all reclaims get NFSERR_NOGRACE. 4453 */ 4454 4455/* 4456 * Read in the stable storage file. Called by nfssvc() before the nfsd 4457 * processes start servicing requests. 4458 */ 4459APPLESTATIC void 4460nfsrv_setupstable(NFSPROC_T *p) 4461{ 4462 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4463 struct nfsrv_stable *sp, *nsp; 4464 struct nfst_rec *tsp; 4465 int error, i, tryagain; 4466 off_t off = 0; 4467 ssize_t aresid, len; 4468 4469 /* 4470 * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without 4471 * a reboot, so state has not been lost. 4472 */ 4473 if (sf->nsf_flags & NFSNSF_UPDATEDONE) 4474 return; 4475 /* 4476 * Set Grace over just until the file reads successfully. 4477 */ 4478 nfsrvboottime = time_second; 4479 LIST_INIT(&sf->nsf_head); 4480 sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); 4481 sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA; 4482 if (sf->nsf_fp == NULL) 4483 return; 4484 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4485 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE, 4486 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4487 if (error || aresid || sf->nsf_numboots == 0 || 4488 sf->nsf_numboots > NFSNSF_MAXNUMBOOTS) 4489 return; 4490 4491 /* 4492 * Now, read in the boottimes. 4493 */ 4494 sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) * 4495 sizeof (time_t), M_TEMP, M_WAITOK); 4496 off = sizeof (struct nfsf_rec); 4497 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4498 (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off, 4499 UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4500 if (error || aresid) { 4501 free((caddr_t)sf->nsf_bootvals, M_TEMP); 4502 sf->nsf_bootvals = NULL; 4503 return; 4504 } 4505 4506 /* 4507 * Make sure this nfsrvboottime is different from all recorded 4508 * previous ones. 4509 */ 4510 do { 4511 tryagain = 0; 4512 for (i = 0; i < sf->nsf_numboots; i++) { 4513 if (nfsrvboottime == sf->nsf_bootvals[i]) { 4514 nfsrvboottime++; 4515 tryagain = 1; 4516 break; 4517 } 4518 } 4519 } while (tryagain); 4520 4521 sf->nsf_flags |= NFSNSF_OK; 4522 off += (sf->nsf_numboots * sizeof (time_t)); 4523 4524 /* 4525 * Read through the file, building a list of records for grace 4526 * checking. 4527 * Each record is between sizeof (struct nfst_rec) and 4528 * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1 4529 * and is actually sizeof (struct nfst_rec) + nst_len - 1. 4530 */ 4531 tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4532 NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK); 4533 do { 4534 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4535 (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1, 4536 off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4537 len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid; 4538 if (error || (len > 0 && (len < sizeof (struct nfst_rec) || 4539 len < (sizeof (struct nfst_rec) + tsp->len - 1)))) { 4540 /* 4541 * Yuck, the file has been corrupted, so just return 4542 * after clearing out any restart state, so the grace period 4543 * is over. 4544 */ 4545 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4546 LIST_REMOVE(sp, nst_list); 4547 free((caddr_t)sp, M_TEMP); 4548 } 4549 free((caddr_t)tsp, M_TEMP); 4550 sf->nsf_flags &= ~NFSNSF_OK; 4551 free((caddr_t)sf->nsf_bootvals, M_TEMP); 4552 sf->nsf_bootvals = NULL; 4553 return; 4554 } 4555 if (len > 0) { 4556 off += sizeof (struct nfst_rec) + tsp->len - 1; 4557 /* 4558 * Search the list for a matching client. 4559 */ 4560 LIST_FOREACH(sp, &sf->nsf_head, nst_list) { 4561 if (tsp->len == sp->nst_len && 4562 !NFSBCMP(tsp->client, sp->nst_client, tsp->len)) 4563 break; 4564 } 4565 if (sp == LIST_END(&sf->nsf_head)) { 4566 sp = (struct nfsrv_stable *)malloc(tsp->len + 4567 sizeof (struct nfsrv_stable) - 1, M_TEMP, 4568 M_WAITOK); 4569 NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec, 4570 sizeof (struct nfst_rec) + tsp->len - 1); 4571 LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list); 4572 } else { 4573 if (tsp->flag == NFSNST_REVOKE) 4574 sp->nst_flag |= NFSNST_REVOKE; 4575 else 4576 /* 4577 * A subsequent timestamp indicates the client 4578 * did a setclientid/confirm and any previous 4579 * revoke is no longer relevant. 4580 */ 4581 sp->nst_flag &= ~NFSNST_REVOKE; 4582 } 4583 } 4584 } while (len > 0); 4585 free((caddr_t)tsp, M_TEMP); 4586 sf->nsf_flags = NFSNSF_OK; 4587 sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease + 4588 NFSRV_LEASEDELTA; 4589} 4590 4591/* 4592 * Update the stable storage file, now that the grace period is over. 4593 */ 4594APPLESTATIC void 4595nfsrv_updatestable(NFSPROC_T *p) 4596{ 4597 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4598 struct nfsrv_stable *sp, *nsp; 4599 int i; 4600 struct nfsvattr nva; 4601 vnode_t vp; 4602#if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) 4603 mount_t mp = NULL; 4604#endif 4605 int error; 4606 4607 if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE)) 4608 return; 4609 sf->nsf_flags |= NFSNSF_UPDATEDONE; 4610 /* 4611 * Ok, we need to rewrite the stable storage file. 4612 * - truncate to 0 length 4613 * - write the new first structure 4614 * - loop through the data structures, writing out any that 4615 * have timestamps older than the old boot 4616 */ 4617 if (sf->nsf_bootvals) { 4618 sf->nsf_numboots++; 4619 for (i = sf->nsf_numboots - 2; i >= 0; i--) 4620 sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i]; 4621 } else { 4622 sf->nsf_numboots = 1; 4623 sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t), 4624 M_TEMP, M_WAITOK); 4625 } 4626 sf->nsf_bootvals[0] = nfsrvboottime; 4627 sf->nsf_lease = nfsrv_lease; 4628 NFSVNO_ATTRINIT(&nva); 4629 NFSVNO_SETATTRVAL(&nva, size, 0); 4630 vp = NFSFPVNODE(sf->nsf_fp); 4631 vn_start_write(vp, &mp, V_WAIT); 4632 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { 4633 error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p, 4634 NULL); 4635 NFSVOPUNLOCK(vp, 0); 4636 } else 4637 error = EPERM; 4638 vn_finished_write(mp); 4639 if (!error) 4640 error = NFSD_RDWR(UIO_WRITE, vp, 4641 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0, 4642 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4643 if (!error) 4644 error = NFSD_RDWR(UIO_WRITE, vp, 4645 (caddr_t)sf->nsf_bootvals, 4646 sf->nsf_numboots * sizeof (time_t), 4647 (off_t)(sizeof (struct nfsf_rec)), 4648 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4649 free((caddr_t)sf->nsf_bootvals, M_TEMP); 4650 sf->nsf_bootvals = NULL; 4651 if (error) { 4652 sf->nsf_flags &= ~NFSNSF_OK; 4653 printf("EEK! Can't write NfsV4 stable storage file\n"); 4654 return; 4655 } 4656 sf->nsf_flags |= NFSNSF_OK; 4657 4658 /* 4659 * Loop through the list and write out timestamp records for 4660 * any clients that successfully reclaimed state. 4661 */ 4662 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4663 if (sp->nst_flag & NFSNST_GOTSTATE) { 4664 nfsrv_writestable(sp->nst_client, sp->nst_len, 4665 NFSNST_NEWSTATE, p); 4666 sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE; 4667 } 4668 LIST_REMOVE(sp, nst_list); 4669 free((caddr_t)sp, M_TEMP); 4670 } 4671 nfsrv_backupstable(); 4672} 4673 4674/* 4675 * Append a record to the stable storage file. 4676 */ 4677APPLESTATIC void 4678nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p) 4679{ 4680 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4681 struct nfst_rec *sp; 4682 int error; 4683 4684 if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL) 4685 return; 4686 sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4687 len - 1, M_TEMP, M_WAITOK); 4688 sp->len = len; 4689 NFSBCOPY(client, sp->client, len); 4690 sp->flag = flag; 4691 error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp), 4692 (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0, 4693 UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p); 4694 free((caddr_t)sp, M_TEMP); 4695 if (error) { 4696 sf->nsf_flags &= ~NFSNSF_OK; 4697 printf("EEK! Can't write NfsV4 stable storage file\n"); 4698 } 4699} 4700 4701/* 4702 * This function is called during the grace period to mark a client 4703 * that successfully reclaimed state. 4704 */ 4705static void 4706nfsrv_markstable(struct nfsclient *clp) 4707{ 4708 struct nfsrv_stable *sp; 4709 4710 /* 4711 * First find the client structure. 4712 */ 4713 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4714 if (sp->nst_len == clp->lc_idlen && 4715 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4716 break; 4717 } 4718 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) 4719 return; 4720 4721 /* 4722 * Now, just mark it and set the nfsclient back pointer. 4723 */ 4724 sp->nst_flag |= NFSNST_GOTSTATE; 4725 sp->nst_clp = clp; 4726} 4727 4728/* 4729 * This function is called for a reclaim, to see if it gets grace. 4730 * It returns 0 if a reclaim is allowed, 1 otherwise. 4731 */ 4732static int 4733nfsrv_checkstable(struct nfsclient *clp) 4734{ 4735 struct nfsrv_stable *sp; 4736 4737 /* 4738 * First, find the entry for the client. 4739 */ 4740 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4741 if (sp->nst_len == clp->lc_idlen && 4742 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4743 break; 4744 } 4745 4746 /* 4747 * If not in the list, state was revoked or no state was issued 4748 * since the previous reboot, a reclaim is denied. 4749 */ 4750 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) || 4751 (sp->nst_flag & NFSNST_REVOKE) || 4752 !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK)) 4753 return (1); 4754 return (0); 4755} 4756 4757/* 4758 * Test for and try to clear out a conflicting client. This is called by 4759 * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients 4760 * a found. 4761 * The trick here is that it can't revoke a conflicting client with an 4762 * expired lease unless it holds the v4root lock, so... 4763 * If no v4root lock, get the lock and return 1 to indicate "try again". 4764 * Return 0 to indicate the conflict can't be revoked and 1 to indicate 4765 * the revocation worked and the conflicting client is "bye, bye", so it 4766 * can be tried again. 4767 * Return 2 to indicate that the vnode is VI_DOOMED after NFSVOPLOCK(). 4768 * Unlocks State before a non-zero value is returned. 4769 */ 4770static int 4771nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp, 4772 NFSPROC_T *p) 4773{ 4774 int gotlock, lktype = 0; 4775 4776 /* 4777 * If lease hasn't expired, we can't fix it. 4778 */ 4779 if (clp->lc_expiry >= NFSD_MONOSEC || 4780 !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) 4781 return (0); 4782 if (*haslockp == 0) { 4783 NFSUNLOCKSTATE(); 4784 if (vp != NULL) { 4785 lktype = NFSVOPISLOCKED(vp); 4786 NFSVOPUNLOCK(vp, 0); 4787 } 4788 NFSLOCKV4ROOTMUTEX(); 4789 nfsv4_relref(&nfsv4rootfs_lock); 4790 do { 4791 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4792 NFSV4ROOTLOCKMUTEXPTR, NULL); 4793 } while (!gotlock); 4794 NFSUNLOCKV4ROOTMUTEX(); 4795 *haslockp = 1; 4796 if (vp != NULL) { 4797 NFSVOPLOCK(vp, lktype | LK_RETRY); 4798 if ((vp->v_iflag & VI_DOOMED) != 0) 4799 return (2); 4800 } 4801 return (1); 4802 } 4803 NFSUNLOCKSTATE(); 4804 4805 /* 4806 * Ok, we can expire the conflicting client. 4807 */ 4808 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 4809 nfsrv_backupstable(); 4810 nfsrv_cleanclient(clp, p); 4811 nfsrv_freedeleglist(&clp->lc_deleg); 4812 nfsrv_freedeleglist(&clp->lc_olddeleg); 4813 LIST_REMOVE(clp, lc_hash); 4814 nfsrv_zapclient(clp, p); 4815 return (1); 4816} 4817 4818/* 4819 * Resolve a delegation conflict. 4820 * Returns 0 to indicate the conflict was resolved without sleeping. 4821 * Return -1 to indicate that the caller should check for conflicts again. 4822 * Return > 0 for an error that should be returned, normally NFSERR_DELAY. 4823 * 4824 * Also, manipulate the nfsv4root_lock, as required. It isn't changed 4825 * for a return of 0, since there was no sleep and it could be required 4826 * later. It is released for a return of NFSERR_DELAY, since the caller 4827 * will return that error. It is released when a sleep was done waiting 4828 * for the delegation to be returned or expire (so that other nfsds can 4829 * handle ops). Then, it must be acquired for the write to stable storage. 4830 * (This function is somewhat similar to nfsrv_clientconflict(), but 4831 * the semantics differ in a couple of subtle ways. The return of 0 4832 * indicates the conflict was resolved without sleeping here, not 4833 * that the conflict can't be resolved and the handling of nfsv4root_lock 4834 * differs, as noted above.) 4835 * Unlocks State before returning a non-zero value. 4836 */ 4837static int 4838nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p, 4839 vnode_t vp) 4840{ 4841 struct nfsclient *clp = stp->ls_clp; 4842 int gotlock, error, lktype = 0, retrycnt, zapped_clp; 4843 nfsv4stateid_t tstateid; 4844 fhandle_t tfh; 4845 4846 /* 4847 * If the conflict is with an old delegation... 4848 */ 4849 if (stp->ls_flags & NFSLCK_OLDDELEG) { 4850 /* 4851 * You can delete it, if it has expired. 4852 */ 4853 if (clp->lc_delegtime < NFSD_MONOSEC) { 4854 nfsrv_freedeleg(stp); 4855 NFSUNLOCKSTATE(); 4856 error = -1; 4857 goto out; 4858 } 4859 NFSUNLOCKSTATE(); 4860 /* 4861 * During this delay, the old delegation could expire or it 4862 * could be recovered by the client via an Open with 4863 * CLAIM_DELEGATE_PREV. 4864 * Release the nfsv4root_lock, if held. 4865 */ 4866 if (*haslockp) { 4867 *haslockp = 0; 4868 NFSLOCKV4ROOTMUTEX(); 4869 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4870 NFSUNLOCKV4ROOTMUTEX(); 4871 } 4872 error = NFSERR_DELAY; 4873 goto out; 4874 } 4875 4876 /* 4877 * It's a current delegation, so: 4878 * - check to see if the delegation has expired 4879 * - if so, get the v4root lock and then expire it 4880 */ 4881 if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) { 4882 /* 4883 * - do a recall callback, since not yet done 4884 * For now, never allow truncate to be set. To use 4885 * truncate safely, it must be guaranteed that the 4886 * Remove, Rename or Setattr with size of 0 will 4887 * succeed and that would require major changes to 4888 * the VFS/Vnode OPs. 4889 * Set the expiry time large enough so that it won't expire 4890 * until after the callback, then set it correctly, once 4891 * the callback is done. (The delegation will now time 4892 * out whether or not the Recall worked ok. The timeout 4893 * will be extended when ops are done on the delegation 4894 * stateid, up to the timelimit.) 4895 */ 4896 stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) + 4897 NFSRV_LEASEDELTA; 4898 stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) + 4899 NFSRV_LEASEDELTA; 4900 stp->ls_flags |= NFSLCK_DELEGRECALL; 4901 4902 /* 4903 * Loop NFSRV_CBRETRYCNT times while the CBRecall replies 4904 * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done 4905 * in order to try and avoid a race that could happen 4906 * when a CBRecall request passed the Open reply with 4907 * the delegation in it when transitting the network. 4908 * Since nfsrv_docallback will sleep, don't use stp after 4909 * the call. 4910 */ 4911 NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid, 4912 sizeof (tstateid)); 4913 NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh, 4914 sizeof (tfh)); 4915 NFSUNLOCKSTATE(); 4916 if (*haslockp) { 4917 *haslockp = 0; 4918 NFSLOCKV4ROOTMUTEX(); 4919 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4920 NFSUNLOCKV4ROOTMUTEX(); 4921 } 4922 retrycnt = 0; 4923 do { 4924 error = nfsrv_docallback(clp, NFSV4OP_CBRECALL, 4925 &tstateid, 0, &tfh, NULL, NULL, p); 4926 retrycnt++; 4927 } while ((error == NFSERR_BADSTATEID || 4928 error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT); 4929 error = NFSERR_DELAY; 4930 goto out; 4931 } 4932 4933 if (clp->lc_expiry >= NFSD_MONOSEC && 4934 stp->ls_delegtime >= NFSD_MONOSEC) { 4935 NFSUNLOCKSTATE(); 4936 /* 4937 * A recall has been done, but it has not yet expired. 4938 * So, RETURN_DELAY. 4939 */ 4940 if (*haslockp) { 4941 *haslockp = 0; 4942 NFSLOCKV4ROOTMUTEX(); 4943 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4944 NFSUNLOCKV4ROOTMUTEX(); 4945 } 4946 error = NFSERR_DELAY; 4947 goto out; 4948 } 4949 4950 /* 4951 * If we don't yet have the lock, just get it and then return, 4952 * since we need that before deleting expired state, such as 4953 * this delegation. 4954 * When getting the lock, unlock the vnode, so other nfsds that 4955 * are in progress, won't get stuck waiting for the vnode lock. 4956 */ 4957 if (*haslockp == 0) { 4958 NFSUNLOCKSTATE(); 4959 if (vp != NULL) { 4960 lktype = NFSVOPISLOCKED(vp); 4961 NFSVOPUNLOCK(vp, 0); 4962 } 4963 NFSLOCKV4ROOTMUTEX(); 4964 nfsv4_relref(&nfsv4rootfs_lock); 4965 do { 4966 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4967 NFSV4ROOTLOCKMUTEXPTR, NULL); 4968 } while (!gotlock); 4969 NFSUNLOCKV4ROOTMUTEX(); 4970 *haslockp = 1; 4971 if (vp != NULL) { 4972 NFSVOPLOCK(vp, lktype | LK_RETRY); 4973 if ((vp->v_iflag & VI_DOOMED) != 0) { 4974 *haslockp = 0; 4975 NFSLOCKV4ROOTMUTEX(); 4976 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4977 NFSUNLOCKV4ROOTMUTEX(); 4978 error = NFSERR_PERM; 4979 goto out; 4980 } 4981 } 4982 error = -1; 4983 goto out; 4984 } 4985 4986 NFSUNLOCKSTATE(); 4987 /* 4988 * Ok, we can delete the expired delegation. 4989 * First, write the Revoke record to stable storage and then 4990 * clear out the conflict. 4991 * Since all other nfsd threads are now blocked, we can safely 4992 * sleep without the state changing. 4993 */ 4994 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 4995 nfsrv_backupstable(); 4996 if (clp->lc_expiry < NFSD_MONOSEC) { 4997 nfsrv_cleanclient(clp, p); 4998 nfsrv_freedeleglist(&clp->lc_deleg); 4999 nfsrv_freedeleglist(&clp->lc_olddeleg); 5000 LIST_REMOVE(clp, lc_hash); 5001 zapped_clp = 1; 5002 } else { 5003 nfsrv_freedeleg(stp); 5004 zapped_clp = 0; 5005 } 5006 if (zapped_clp) 5007 nfsrv_zapclient(clp, p); 5008 error = -1; 5009 5010out: 5011 NFSEXITCODE(error); 5012 return (error); 5013} 5014 5015/* 5016 * Check for a remove allowed, if remove is set to 1 and get rid of 5017 * delegations. 5018 */ 5019APPLESTATIC int 5020nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p) 5021{ 5022 struct nfsstate *stp; 5023 struct nfslockfile *lfp; 5024 int error, haslock = 0; 5025 fhandle_t nfh; 5026 5027 /* 5028 * First, get the lock file structure. 5029 * (A return of -1 means no associated state, so remove ok.) 5030 */ 5031 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 5032tryagain: 5033 NFSLOCKSTATE(); 5034 if (!error) 5035 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 5036 if (error) { 5037 NFSUNLOCKSTATE(); 5038 if (haslock) { 5039 NFSLOCKV4ROOTMUTEX(); 5040 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5041 NFSUNLOCKV4ROOTMUTEX(); 5042 } 5043 if (error == -1) 5044 error = 0; 5045 goto out; 5046 } 5047 5048 /* 5049 * Now, we must Recall any delegations. 5050 */ 5051 error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p); 5052 if (error) { 5053 /* 5054 * nfsrv_cleandeleg() unlocks state for non-zero 5055 * return. 5056 */ 5057 if (error == -1) 5058 goto tryagain; 5059 if (haslock) { 5060 NFSLOCKV4ROOTMUTEX(); 5061 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5062 NFSUNLOCKV4ROOTMUTEX(); 5063 } 5064 goto out; 5065 } 5066 5067 /* 5068 * Now, look for a conflicting open share. 5069 */ 5070 if (remove) { 5071 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 5072 if (stp->ls_flags & NFSLCK_WRITEDENY) { 5073 error = NFSERR_FILEOPEN; 5074 break; 5075 } 5076 } 5077 } 5078 5079 NFSUNLOCKSTATE(); 5080 if (haslock) { 5081 NFSLOCKV4ROOTMUTEX(); 5082 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5083 NFSUNLOCKV4ROOTMUTEX(); 5084 } 5085 5086out: 5087 NFSEXITCODE(error); 5088 return (error); 5089} 5090 5091/* 5092 * Clear out all delegations for the file referred to by lfp. 5093 * May return NFSERR_DELAY, if there will be a delay waiting for 5094 * delegations to expire. 5095 * Returns -1 to indicate it slept while recalling a delegation. 5096 * This function has the side effect of deleting the nfslockfile structure, 5097 * if it no longer has associated state and didn't have to sleep. 5098 * Unlocks State before a non-zero value is returned. 5099 */ 5100static int 5101nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 5102 struct nfsclient *clp, int *haslockp, NFSPROC_T *p) 5103{ 5104 struct nfsstate *stp, *nstp; 5105 int ret = 0; 5106 5107 stp = LIST_FIRST(&lfp->lf_deleg); 5108 while (stp != LIST_END(&lfp->lf_deleg)) { 5109 nstp = LIST_NEXT(stp, ls_file); 5110 if (stp->ls_clp != clp) { 5111 ret = nfsrv_delegconflict(stp, haslockp, p, vp); 5112 if (ret) { 5113 /* 5114 * nfsrv_delegconflict() unlocks state 5115 * when it returns non-zero. 5116 */ 5117 goto out; 5118 } 5119 } 5120 stp = nstp; 5121 } 5122out: 5123 NFSEXITCODE(ret); 5124 return (ret); 5125} 5126 5127/* 5128 * There are certain operations that, when being done outside of NFSv4, 5129 * require that any NFSv4 delegation for the file be recalled. 5130 * This function is to be called for those cases: 5131 * VOP_RENAME() - When a delegation is being recalled for any reason, 5132 * the client may have to do Opens against the server, using the file's 5133 * final component name. If the file has been renamed on the server, 5134 * that component name will be incorrect and the Open will fail. 5135 * VOP_REMOVE() - Theoretically, a client could Open a file after it has 5136 * been removed on the server, if there is a delegation issued to 5137 * that client for the file. I say "theoretically" since clients 5138 * normally do an Access Op before the Open and that Access Op will 5139 * fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so 5140 * they will detect the file's removal in the same manner. (There is 5141 * one case where RFC3530 allows a client to do an Open without first 5142 * doing an Access Op, which is passage of a check against the ACE 5143 * returned with a Write delegation, but current practice is to ignore 5144 * the ACE and always do an Access Op.) 5145 * Since the functions can only be called with an unlocked vnode, this 5146 * can't be done at this time. 5147 * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range 5148 * locks locally in the client, which are not visible to the server. To 5149 * deal with this, issuing of delegations for a vnode must be disabled 5150 * and all delegations for the vnode recalled. This is done via the 5151 * second function, using the VV_DISABLEDELEG vflag on the vnode. 5152 */ 5153APPLESTATIC void 5154nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p) 5155{ 5156 time_t starttime; 5157 int error; 5158 5159 /* 5160 * First, check to see if the server is currently running and it has 5161 * been called for a regular file when issuing delegations. 5162 */ 5163 if (newnfs_numnfsd == 0 || vp->v_type != VREG || 5164 nfsrv_issuedelegs == 0) 5165 return; 5166 5167 KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp)); 5168 /* 5169 * First, get a reference on the nfsv4rootfs_lock so that an 5170 * exclusive lock cannot be acquired by another thread. 5171 */ 5172 NFSLOCKV4ROOTMUTEX(); 5173 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 5174 NFSUNLOCKV4ROOTMUTEX(); 5175 5176 /* 5177 * Now, call nfsrv_checkremove() in a loop while it returns 5178 * NFSERR_DELAY. Return upon any other error or when timed out. 5179 */ 5180 starttime = NFSD_MONOSEC; 5181 do { 5182 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { 5183 error = nfsrv_checkremove(vp, 0, p); 5184 NFSVOPUNLOCK(vp, 0); 5185 } else 5186 error = EPERM; 5187 if (error == NFSERR_DELAY) { 5188 if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO) 5189 break; 5190 /* Sleep for a short period of time */ 5191 (void) nfs_catnap(PZERO, 0, "nfsremove"); 5192 } 5193 } while (error == NFSERR_DELAY); 5194 NFSLOCKV4ROOTMUTEX(); 5195 nfsv4_relref(&nfsv4rootfs_lock); 5196 NFSUNLOCKV4ROOTMUTEX(); 5197} 5198 5199APPLESTATIC void 5200nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p) 5201{ 5202 5203#ifdef VV_DISABLEDELEG 5204 /* 5205 * First, flag issuance of delegations disabled. 5206 */ 5207 atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG); 5208#endif 5209 5210 /* 5211 * Then call nfsd_recalldelegation() to get rid of all extant 5212 * delegations. 5213 */ 5214 nfsd_recalldelegation(vp, p); 5215} 5216 5217/* 5218 * Check for conflicting locks, etc. and then get rid of delegations. 5219 * (At one point I thought that I should get rid of delegations for any 5220 * Setattr, since it could potentially disallow the I/O op (read or write) 5221 * allowed by the delegation. However, Setattr Ops that aren't changing 5222 * the size get a stateid of all 0s, so you can't tell if it is a delegation 5223 * for the same client or a different one, so I decided to only get rid 5224 * of delegations for other clients when the size is being changed.) 5225 * In general, a Setattr can disable NFS I/O Ops that are outstanding, such 5226 * as Write backs, even if there is no delegation, so it really isn't any 5227 * different?) 5228 */ 5229APPLESTATIC int 5230nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd, 5231 nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp, 5232 struct nfsexstuff *exp, NFSPROC_T *p) 5233{ 5234 struct nfsstate st, *stp = &st; 5235 struct nfslock lo, *lop = &lo; 5236 int error = 0; 5237 nfsquad_t clientid; 5238 5239 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) { 5240 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 5241 lop->lo_first = nvap->na_size; 5242 } else { 5243 stp->ls_flags = 0; 5244 lop->lo_first = 0; 5245 } 5246 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) || 5247 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) || 5248 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) || 5249 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL)) 5250 stp->ls_flags |= NFSLCK_SETATTR; 5251 if (stp->ls_flags == 0) 5252 goto out; 5253 lop->lo_end = NFS64BITSSET; 5254 lop->lo_flags = NFSLCK_WRITE; 5255 stp->ls_ownerlen = 0; 5256 stp->ls_op = NULL; 5257 stp->ls_uid = nd->nd_cred->cr_uid; 5258 stp->ls_stateid.seqid = stateidp->seqid; 5259 clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0]; 5260 clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1]; 5261 stp->ls_stateid.other[2] = stateidp->other[2]; 5262 error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 5263 stateidp, exp, nd, p); 5264 5265out: 5266 NFSEXITCODE2(error, nd); 5267 return (error); 5268} 5269 5270/* 5271 * Check for a write delegation and do a CBGETATTR if there is one, updating 5272 * the attributes, as required. 5273 * Should I return an error if I can't get the attributes? (For now, I'll 5274 * just return ok. 5275 */ 5276APPLESTATIC int 5277nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp, 5278 struct nfsvattr *nvap, nfsattrbit_t *attrbitp, struct ucred *cred, 5279 NFSPROC_T *p) 5280{ 5281 struct nfsstate *stp; 5282 struct nfslockfile *lfp; 5283 struct nfsclient *clp; 5284 struct nfsvattr nva; 5285 fhandle_t nfh; 5286 int error = 0; 5287 nfsattrbit_t cbbits; 5288 u_quad_t delegfilerev; 5289 5290 NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits); 5291 if (!NFSNONZERO_ATTRBIT(&cbbits)) 5292 goto out; 5293 5294 /* 5295 * Get the lock file structure. 5296 * (A return of -1 means no associated state, so return ok.) 5297 */ 5298 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 5299 NFSLOCKSTATE(); 5300 if (!error) 5301 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 5302 if (error) { 5303 NFSUNLOCKSTATE(); 5304 if (error == -1) 5305 error = 0; 5306 goto out; 5307 } 5308 5309 /* 5310 * Now, look for a write delegation. 5311 */ 5312 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 5313 if (stp->ls_flags & NFSLCK_DELEGWRITE) 5314 break; 5315 } 5316 if (stp == LIST_END(&lfp->lf_deleg)) { 5317 NFSUNLOCKSTATE(); 5318 goto out; 5319 } 5320 clp = stp->ls_clp; 5321 delegfilerev = stp->ls_filerev; 5322 5323 /* 5324 * If the Write delegation was issued as a part of this Compound RPC 5325 * or if we have an Implied Clientid (used in a previous Op in this 5326 * compound) and it is the client the delegation was issued to, 5327 * just return ok. 5328 * I also assume that it is from the same client iff the network 5329 * host IP address is the same as the callback address. (Not 5330 * exactly correct by the RFC, but avoids a lot of Getattr 5331 * callbacks.) 5332 */ 5333 if (nd->nd_compref == stp->ls_compref || 5334 ((nd->nd_flag & ND_IMPLIEDCLID) && 5335 clp->lc_clientid.qval == nd->nd_clientid.qval) || 5336 nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) { 5337 NFSUNLOCKSTATE(); 5338 goto out; 5339 } 5340 5341 /* 5342 * We are now done with the delegation state structure, 5343 * so the statelock can be released and we can now tsleep(). 5344 */ 5345 5346 /* 5347 * Now, we must do the CB Getattr callback, to see if Change or Size 5348 * has changed. 5349 */ 5350 if (clp->lc_expiry >= NFSD_MONOSEC) { 5351 NFSUNLOCKSTATE(); 5352 NFSVNO_ATTRINIT(&nva); 5353 nva.na_filerev = NFS64BITSSET; 5354 error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL, 5355 0, &nfh, &nva, &cbbits, p); 5356 if (!error) { 5357 if ((nva.na_filerev != NFS64BITSSET && 5358 nva.na_filerev > delegfilerev) || 5359 (NFSVNO_ISSETSIZE(&nva) && 5360 nva.na_size != nvap->na_size)) { 5361 error = nfsvno_updfilerev(vp, nvap, cred, p); 5362 if (NFSVNO_ISSETSIZE(&nva)) 5363 nvap->na_size = nva.na_size; 5364 } 5365 } else 5366 error = 0; /* Ignore callback errors for now. */ 5367 } else { 5368 NFSUNLOCKSTATE(); 5369 } 5370 5371out: 5372 NFSEXITCODE2(error, nd); 5373 return (error); 5374} 5375 5376/* 5377 * This function looks for openowners that haven't had any opens for 5378 * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS 5379 * is set. 5380 */ 5381APPLESTATIC void 5382nfsrv_throwawayopens(NFSPROC_T *p) 5383{ 5384 struct nfsclient *clp, *nclp; 5385 struct nfsstate *stp, *nstp; 5386 int i; 5387 5388 NFSLOCKSTATE(); 5389 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS; 5390 /* 5391 * For each client... 5392 */ 5393 for (i = 0; i < nfsrv_clienthashsize; i++) { 5394 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 5395 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { 5396 if (LIST_EMPTY(&stp->ls_open) && 5397 (stp->ls_noopens > NFSNOOPEN || 5398 (nfsrv_openpluslock * 2) > 5399 nfsrv_v4statelimit)) 5400 nfsrv_freeopenowner(stp, 0, p); 5401 } 5402 } 5403 } 5404 NFSUNLOCKSTATE(); 5405} 5406 5407/* 5408 * This function checks to see if the credentials are the same. 5409 * Returns 1 for not same, 0 otherwise. 5410 */ 5411static int 5412nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp) 5413{ 5414 5415 if (nd->nd_flag & ND_GSS) { 5416 if (!(clp->lc_flags & LCL_GSS)) 5417 return (1); 5418 if (clp->lc_flags & LCL_NAME) { 5419 if (nd->nd_princlen != clp->lc_namelen || 5420 NFSBCMP(nd->nd_principal, clp->lc_name, 5421 clp->lc_namelen)) 5422 return (1); 5423 else 5424 return (0); 5425 } 5426 if (nd->nd_cred->cr_uid == clp->lc_uid) 5427 return (0); 5428 else 5429 return (1); 5430 } else if (clp->lc_flags & LCL_GSS) 5431 return (1); 5432 /* 5433 * For AUTH_SYS, allow the same uid or root. (This is underspecified 5434 * in RFC3530, which talks about principals, but doesn't say anything 5435 * about uids for AUTH_SYS.) 5436 */ 5437 if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0) 5438 return (0); 5439 else 5440 return (1); 5441} 5442 5443/* 5444 * Calculate the lease expiry time. 5445 */ 5446static time_t 5447nfsrv_leaseexpiry(void) 5448{ 5449 5450 if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC) 5451 return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA)); 5452 return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA); 5453} 5454 5455/* 5456 * Delay the delegation timeout as far as ls_delegtimelimit, as required. 5457 */ 5458static void 5459nfsrv_delaydelegtimeout(struct nfsstate *stp) 5460{ 5461 5462 if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0) 5463 return; 5464 5465 if ((stp->ls_delegtime + 15) > NFSD_MONOSEC && 5466 stp->ls_delegtime < stp->ls_delegtimelimit) { 5467 stp->ls_delegtime += nfsrv_lease; 5468 if (stp->ls_delegtime > stp->ls_delegtimelimit) 5469 stp->ls_delegtime = stp->ls_delegtimelimit; 5470 } 5471} 5472 5473/* 5474 * This function checks to see if there is any other state associated 5475 * with the openowner for this Open. 5476 * It returns 1 if there is no other state, 0 otherwise. 5477 */ 5478static int 5479nfsrv_nootherstate(struct nfsstate *stp) 5480{ 5481 struct nfsstate *tstp; 5482 5483 LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) { 5484 if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock)) 5485 return (0); 5486 } 5487 return (1); 5488} 5489 5490/* 5491 * Create a list of lock deltas (changes to local byte range locking 5492 * that can be rolled back using the list) and apply the changes via 5493 * nfsvno_advlock(). Optionally, lock the list. It is expected that either 5494 * the rollback or update function will be called after this. 5495 * It returns an error (and rolls back, as required), if any nfsvno_advlock() 5496 * call fails. If it returns an error, it will unlock the list. 5497 */ 5498static int 5499nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, 5500 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5501{ 5502 struct nfslock *lop, *nlop; 5503 int error = 0; 5504 5505 /* Loop through the list of locks. */ 5506 lop = LIST_FIRST(&lfp->lf_locallock); 5507 while (first < end && lop != NULL) { 5508 nlop = LIST_NEXT(lop, lo_lckowner); 5509 if (first >= lop->lo_end) { 5510 /* not there yet */ 5511 lop = nlop; 5512 } else if (first < lop->lo_first) { 5513 /* new one starts before entry in list */ 5514 if (end <= lop->lo_first) { 5515 /* no overlap between old and new */ 5516 error = nfsrv_dolocal(vp, lfp, flags, 5517 NFSLCK_UNLOCK, first, end, cfp, p); 5518 if (error != 0) 5519 break; 5520 first = end; 5521 } else { 5522 /* handle fragment overlapped with new one */ 5523 error = nfsrv_dolocal(vp, lfp, flags, 5524 NFSLCK_UNLOCK, first, lop->lo_first, cfp, 5525 p); 5526 if (error != 0) 5527 break; 5528 first = lop->lo_first; 5529 } 5530 } else { 5531 /* new one overlaps this entry in list */ 5532 if (end <= lop->lo_end) { 5533 /* overlaps all of new one */ 5534 error = nfsrv_dolocal(vp, lfp, flags, 5535 lop->lo_flags, first, end, cfp, p); 5536 if (error != 0) 5537 break; 5538 first = end; 5539 } else { 5540 /* handle fragment overlapped with new one */ 5541 error = nfsrv_dolocal(vp, lfp, flags, 5542 lop->lo_flags, first, lop->lo_end, cfp, p); 5543 if (error != 0) 5544 break; 5545 first = lop->lo_end; 5546 lop = nlop; 5547 } 5548 } 5549 } 5550 if (first < end && error == 0) 5551 /* handle fragment past end of list */ 5552 error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first, 5553 end, cfp, p); 5554 5555 NFSEXITCODE(error); 5556 return (error); 5557} 5558 5559/* 5560 * Local lock unlock. Unlock all byte ranges that are no longer locked 5561 * by NFSv4. To do this, unlock any subranges of first-->end that 5562 * do not overlap with the byte ranges of any lock in the lfp->lf_lock 5563 * list. This list has all locks for the file held by other 5564 * <clientid, lockowner> tuples. The list is ordered by increasing 5565 * lo_first value, but may have entries that overlap each other, for 5566 * the case of read locks. 5567 */ 5568static void 5569nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first, 5570 uint64_t init_end, NFSPROC_T *p) 5571{ 5572 struct nfslock *lop; 5573 uint64_t first, end, prevfirst; 5574 5575 first = init_first; 5576 end = init_end; 5577 while (first < init_end) { 5578 /* Loop through all nfs locks, adjusting first and end */ 5579 prevfirst = 0; 5580 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { 5581 KASSERT(prevfirst <= lop->lo_first, 5582 ("nfsv4 locks out of order")); 5583 KASSERT(lop->lo_first < lop->lo_end, 5584 ("nfsv4 bogus lock")); 5585 prevfirst = lop->lo_first; 5586 if (first >= lop->lo_first && 5587 first < lop->lo_end) 5588 /* 5589 * Overlaps with initial part, so trim 5590 * off that initial part by moving first past 5591 * it. 5592 */ 5593 first = lop->lo_end; 5594 else if (end > lop->lo_first && 5595 lop->lo_first > first) { 5596 /* 5597 * This lock defines the end of the 5598 * segment to unlock, so set end to the 5599 * start of it and break out of the loop. 5600 */ 5601 end = lop->lo_first; 5602 break; 5603 } 5604 if (first >= end) 5605 /* 5606 * There is no segment left to do, so 5607 * break out of this loop and then exit 5608 * the outer while() since first will be set 5609 * to end, which must equal init_end here. 5610 */ 5611 break; 5612 } 5613 if (first < end) { 5614 /* Unlock this segment */ 5615 (void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK, 5616 NFSLCK_READ, first, end, NULL, p); 5617 nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK, 5618 first, end); 5619 } 5620 /* 5621 * Now move past this segment and look for any further 5622 * segment in the range, if there is one. 5623 */ 5624 first = end; 5625 end = init_end; 5626 } 5627} 5628 5629/* 5630 * Do the local lock operation and update the rollback list, as required. 5631 * Perform the rollback and return the error if nfsvno_advlock() fails. 5632 */ 5633static int 5634nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags, 5635 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5636{ 5637 struct nfsrollback *rlp; 5638 int error = 0, ltype, oldltype; 5639 5640 if (flags & NFSLCK_WRITE) 5641 ltype = F_WRLCK; 5642 else if (flags & NFSLCK_READ) 5643 ltype = F_RDLCK; 5644 else 5645 ltype = F_UNLCK; 5646 if (oldflags & NFSLCK_WRITE) 5647 oldltype = F_WRLCK; 5648 else if (oldflags & NFSLCK_READ) 5649 oldltype = F_RDLCK; 5650 else 5651 oldltype = F_UNLCK; 5652 if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK)) 5653 /* nothing to do */ 5654 goto out; 5655 error = nfsvno_advlock(vp, ltype, first, end, p); 5656 if (error != 0) { 5657 if (cfp != NULL) { 5658 cfp->cl_clientid.lval[0] = 0; 5659 cfp->cl_clientid.lval[1] = 0; 5660 cfp->cl_first = 0; 5661 cfp->cl_end = NFS64BITSSET; 5662 cfp->cl_flags = NFSLCK_WRITE; 5663 cfp->cl_ownerlen = 5; 5664 NFSBCOPY("LOCAL", cfp->cl_owner, 5); 5665 } 5666 nfsrv_locallock_rollback(vp, lfp, p); 5667 } else if (ltype != F_UNLCK) { 5668 rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK, 5669 M_WAITOK); 5670 rlp->rlck_first = first; 5671 rlp->rlck_end = end; 5672 rlp->rlck_type = oldltype; 5673 LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list); 5674 } 5675 5676out: 5677 NFSEXITCODE(error); 5678 return (error); 5679} 5680 5681/* 5682 * Roll back local lock changes and free up the rollback list. 5683 */ 5684static void 5685nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p) 5686{ 5687 struct nfsrollback *rlp, *nrlp; 5688 5689 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) { 5690 (void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first, 5691 rlp->rlck_end, p); 5692 free(rlp, M_NFSDROLLBACK); 5693 } 5694 LIST_INIT(&lfp->lf_rollback); 5695} 5696 5697/* 5698 * Update local lock list and delete rollback list (ie now committed to the 5699 * local locks). Most of the work is done by the internal function. 5700 */ 5701static void 5702nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first, 5703 uint64_t end) 5704{ 5705 struct nfsrollback *rlp, *nrlp; 5706 struct nfslock *new_lop, *other_lop; 5707 5708 new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK); 5709 if (flags & (NFSLCK_READ | NFSLCK_WRITE)) 5710 other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, 5711 M_WAITOK); 5712 else 5713 other_lop = NULL; 5714 new_lop->lo_flags = flags; 5715 new_lop->lo_first = first; 5716 new_lop->lo_end = end; 5717 nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp); 5718 if (new_lop != NULL) 5719 free(new_lop, M_NFSDLOCK); 5720 if (other_lop != NULL) 5721 free(other_lop, M_NFSDLOCK); 5722 5723 /* and get rid of the rollback list */ 5724 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) 5725 free(rlp, M_NFSDROLLBACK); 5726 LIST_INIT(&lfp->lf_rollback); 5727} 5728 5729/* 5730 * Lock the struct nfslockfile for local lock updating. 5731 */ 5732static void 5733nfsrv_locklf(struct nfslockfile *lfp) 5734{ 5735 int gotlock; 5736 5737 /* lf_usecount ensures *lfp won't be free'd */ 5738 lfp->lf_usecount++; 5739 do { 5740 gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL, 5741 NFSSTATEMUTEXPTR, NULL); 5742 } while (gotlock == 0); 5743 lfp->lf_usecount--; 5744} 5745 5746/* 5747 * Unlock the struct nfslockfile after local lock updating. 5748 */ 5749static void 5750nfsrv_unlocklf(struct nfslockfile *lfp) 5751{ 5752 5753 nfsv4_unlock(&lfp->lf_locallock_lck, 0); 5754} 5755 5756/* 5757 * Clear out all state for the NFSv4 server. 5758 * Must be called by a thread that can sleep when no nfsds are running. 5759 */ 5760void 5761nfsrv_throwawayallstate(NFSPROC_T *p) 5762{ 5763 struct nfsclient *clp, *nclp; 5764 struct nfslockfile *lfp, *nlfp; 5765 int i; 5766 5767 /* 5768 * For each client, clean out the state and then free the structure. 5769 */ 5770 for (i = 0; i < nfsrv_clienthashsize; i++) { 5771 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 5772 nfsrv_cleanclient(clp, p); 5773 nfsrv_freedeleglist(&clp->lc_deleg); 5774 nfsrv_freedeleglist(&clp->lc_olddeleg); 5775 free(clp->lc_stateid, M_NFSDCLIENT); 5776 free(clp, M_NFSDCLIENT); 5777 } 5778 } 5779 5780 /* 5781 * Also, free up any remaining lock file structures. 5782 */ 5783 for (i = 0; i < nfsrv_lockhashsize; i++) { 5784 LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) { 5785 printf("nfsd unload: fnd a lock file struct\n"); 5786 nfsrv_freenfslockfile(lfp); 5787 } 5788 } 5789} 5790 5791/* 5792 * Check the sequence# for the session and slot provided as an argument. 5793 * Also, renew the lease if the session will return NFS_OK. 5794 */ 5795int 5796nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid, 5797 uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this, 5798 uint32_t *sflagsp, NFSPROC_T *p) 5799{ 5800 struct nfsdsession *sep; 5801 struct nfssessionhash *shp; 5802 int error; 5803 SVCXPRT *savxprt; 5804 5805 shp = NFSSESSIONHASH(nd->nd_sessionid); 5806 NFSLOCKSESSION(shp); 5807 sep = nfsrv_findsession(nd->nd_sessionid); 5808 if (sep == NULL) { 5809 NFSUNLOCKSESSION(shp); 5810 return (NFSERR_BADSESSION); 5811 } 5812 error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp, 5813 sep->sess_slots, NULL, NFSV4_SLOTS - 1); 5814 if (error != 0) { 5815 NFSUNLOCKSESSION(shp); 5816 return (error); 5817 } 5818 if (cache_this != 0) 5819 nd->nd_flag |= ND_SAVEREPLY; 5820 /* Renew the lease. */ 5821 sep->sess_clp->lc_expiry = nfsrv_leaseexpiry(); 5822 nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval; 5823 nd->nd_flag |= ND_IMPLIEDCLID; 5824 5825 /* 5826 * If this session handles the backchannel, save the nd_xprt for this 5827 * RPC, since this is the one being used. 5828 */ 5829 if (sep->sess_clp->lc_req.nr_client != NULL && 5830 (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) { 5831 savxprt = sep->sess_cbsess.nfsess_xprt; 5832 SVC_ACQUIRE(nd->nd_xprt); 5833 nd->nd_xprt->xp_p2 = 5834 sep->sess_clp->lc_req.nr_client->cl_private; 5835 nd->nd_xprt->xp_idletimeout = 0; /* Disable timeout. */ 5836 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt; 5837 if (savxprt != NULL) 5838 SVC_RELEASE(savxprt); 5839 } 5840 5841 *sflagsp = 0; 5842 if (sep->sess_clp->lc_req.nr_client == NULL) 5843 *sflagsp |= NFSV4SEQ_CBPATHDOWN; 5844 NFSUNLOCKSESSION(shp); 5845 if (error == NFSERR_EXPIRED) { 5846 *sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED; 5847 error = 0; 5848 } else if (error == NFSERR_ADMINREVOKED) { 5849 *sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED; 5850 error = 0; 5851 } 5852 *highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1; 5853 return (0); 5854} 5855 5856/* 5857 * Check/set reclaim complete for this session/clientid. 5858 */ 5859int 5860nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd) 5861{ 5862 struct nfsdsession *sep; 5863 struct nfssessionhash *shp; 5864 int error = 0; 5865 5866 shp = NFSSESSIONHASH(nd->nd_sessionid); 5867 NFSLOCKSTATE(); 5868 NFSLOCKSESSION(shp); 5869 sep = nfsrv_findsession(nd->nd_sessionid); 5870 if (sep == NULL) { 5871 NFSUNLOCKSESSION(shp); 5872 NFSUNLOCKSTATE(); 5873 return (NFSERR_BADSESSION); 5874 } 5875 5876 /* Check to see if reclaim complete has already happened. */ 5877 if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) 5878 error = NFSERR_COMPLETEALREADY; 5879 else 5880 sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE; 5881 NFSUNLOCKSESSION(shp); 5882 NFSUNLOCKSTATE(); 5883 return (error); 5884} 5885 5886/* 5887 * Cache the reply in a session slot. 5888 */ 5889void 5890nfsrv_cache_session(uint8_t *sessionid, uint32_t slotid, int repstat, 5891 struct mbuf **m) 5892{ 5893 struct nfsdsession *sep; 5894 struct nfssessionhash *shp; 5895 5896 shp = NFSSESSIONHASH(sessionid); 5897 NFSLOCKSESSION(shp); 5898 sep = nfsrv_findsession(sessionid); 5899 if (sep == NULL) { 5900 NFSUNLOCKSESSION(shp); 5901 printf("nfsrv_cache_session: no session\n"); 5902 m_freem(*m); 5903 return; 5904 } 5905 nfsv4_seqsess_cacherep(slotid, sep->sess_slots, repstat, m); 5906 NFSUNLOCKSESSION(shp); 5907} 5908 5909/* 5910 * Search for a session that matches the sessionid. 5911 */ 5912static struct nfsdsession * 5913nfsrv_findsession(uint8_t *sessionid) 5914{ 5915 struct nfsdsession *sep; 5916 struct nfssessionhash *shp; 5917 5918 shp = NFSSESSIONHASH(sessionid); 5919 LIST_FOREACH(sep, &shp->list, sess_hash) { 5920 if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID)) 5921 break; 5922 } 5923 return (sep); 5924} 5925 5926/* 5927 * Destroy a session. 5928 */ 5929int 5930nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid) 5931{ 5932 int error, samesess; 5933 5934 samesess = 0; 5935 if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID)) { 5936 samesess = 1; 5937 if ((nd->nd_flag & ND_LASTOP) == 0) 5938 return (NFSERR_BADSESSION); 5939 } 5940 error = nfsrv_freesession(NULL, sessionid); 5941 if (error == 0 && samesess != 0) 5942 nd->nd_flag &= ~ND_HASSEQUENCE; 5943 return (error); 5944} 5945 5946/* 5947 * Free up a session structure. 5948 */ 5949static int 5950nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid) 5951{ 5952 struct nfssessionhash *shp; 5953 int i; 5954 5955 NFSLOCKSTATE(); 5956 if (sep == NULL) { 5957 shp = NFSSESSIONHASH(sessionid); 5958 NFSLOCKSESSION(shp); 5959 sep = nfsrv_findsession(sessionid); 5960 } else { 5961 shp = NFSSESSIONHASH(sep->sess_sessionid); 5962 NFSLOCKSESSION(shp); 5963 } 5964 if (sep != NULL) { 5965 sep->sess_refcnt--; 5966 if (sep->sess_refcnt > 0) { 5967 NFSUNLOCKSESSION(shp); 5968 NFSUNLOCKSTATE(); 5969 return (0); 5970 } 5971 LIST_REMOVE(sep, sess_hash); 5972 LIST_REMOVE(sep, sess_list); 5973 } 5974 NFSUNLOCKSESSION(shp); 5975 NFSUNLOCKSTATE(); 5976 if (sep == NULL) 5977 return (NFSERR_BADSESSION); 5978 for (i = 0; i < NFSV4_SLOTS; i++) 5979 if (sep->sess_slots[i].nfssl_reply != NULL) 5980 m_freem(sep->sess_slots[i].nfssl_reply); 5981 if (sep->sess_cbsess.nfsess_xprt != NULL) 5982 SVC_RELEASE(sep->sess_cbsess.nfsess_xprt); 5983 free(sep, M_NFSDSESSION); 5984 return (0); 5985} 5986 5987/* 5988 * Free a stateid. 5989 * RFC5661 says that it should fail when there are associated opens, locks 5990 * or delegations. Since stateids represent opens, I don't see how you can 5991 * free an open stateid (it will be free'd when closed), so this function 5992 * only works for lock stateids (freeing the lock_owner) or delegations. 5993 */ 5994int 5995nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, 5996 NFSPROC_T *p) 5997{ 5998 struct nfsclient *clp; 5999 struct nfsstate *stp; 6000 int error; 6001 6002 NFSLOCKSTATE(); 6003 /* 6004 * Look up the stateid 6005 */ 6006 error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp, 6007 NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); 6008 if (error == 0) { 6009 /* First, check for a delegation. */ 6010 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) { 6011 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other, 6012 NFSX_STATEIDOTHER)) 6013 break; 6014 } 6015 if (stp != NULL) { 6016 nfsrv_freedeleg(stp); 6017 NFSUNLOCKSTATE(); 6018 return (error); 6019 } 6020 } 6021 /* Not a delegation, try for a lock_owner. */ 6022 if (error == 0) 6023 error = nfsrv_getstate(clp, stateidp, 0, &stp); 6024 if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD | 6025 NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0)) 6026 /* Not a lock_owner stateid. */ 6027 error = NFSERR_LOCKSHELD; 6028 if (error == 0 && !LIST_EMPTY(&stp->ls_lock)) 6029 error = NFSERR_LOCKSHELD; 6030 if (error == 0) 6031 nfsrv_freelockowner(stp, NULL, 0, p); 6032 NFSUNLOCKSTATE(); 6033 return (error); 6034} 6035 6036/* 6037 * Generate the xdr for an NFSv4.1 CBSequence Operation. 6038 */ 6039static int 6040nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp, 6041 int dont_replycache, struct nfsdsession **sepp) 6042{ 6043 struct nfsdsession *sep; 6044 uint32_t *tl, slotseq = 0; 6045 int maxslot, slotpos; 6046 uint8_t sessionid[NFSX_V4SESSIONID]; 6047 int error; 6048 6049 error = nfsv4_getcbsession(clp, sepp); 6050 if (error != 0) 6051 return (error); 6052 sep = *sepp; 6053 (void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot, 6054 &slotseq, sessionid); 6055 KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot")); 6056 6057 /* Build the Sequence arguments. */ 6058 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED); 6059 bcopy(sessionid, tl, NFSX_V4SESSIONID); 6060 tl += NFSX_V4SESSIONID / NFSX_UNSIGNED; 6061 nd->nd_slotseq = tl; 6062 *tl++ = txdr_unsigned(slotseq); 6063 *tl++ = txdr_unsigned(slotpos); 6064 *tl++ = txdr_unsigned(maxslot); 6065 if (dont_replycache == 0) 6066 *tl++ = newnfs_true; 6067 else 6068 *tl++ = newnfs_false; 6069 *tl = 0; /* No referring call list, for now. */ 6070 nd->nd_flag |= ND_HASSEQUENCE; 6071 return (0); 6072} 6073 6074/* 6075 * Get a session for the callback. 6076 */ 6077static int 6078nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp) 6079{ 6080 struct nfsdsession *sep; 6081 6082 NFSLOCKSTATE(); 6083 LIST_FOREACH(sep, &clp->lc_session, sess_list) { 6084 if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) 6085 break; 6086 } 6087 if (sep == NULL) { 6088 NFSUNLOCKSTATE(); 6089 return (NFSERR_BADSESSION); 6090 } 6091 sep->sess_refcnt++; 6092 *sepp = sep; 6093 NFSUNLOCKSTATE(); 6094 return (0); 6095} 6096 6097/* 6098 * Free up all backchannel xprts. This needs to be done when the nfsd threads 6099 * exit, since those transports will all be going away. 6100 * This is only called after all the nfsd threads are done performing RPCs, 6101 * so locking shouldn't be an issue. 6102 */ 6103APPLESTATIC void 6104nfsrv_freeallbackchannel_xprts(void) 6105{ 6106 struct nfsdsession *sep; 6107 struct nfsclient *clp; 6108 SVCXPRT *xprt; 6109 int i; 6110 6111 for (i = 0; i < nfsrv_clienthashsize; i++) { 6112 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 6113 LIST_FOREACH(sep, &clp->lc_session, sess_list) { 6114 xprt = sep->sess_cbsess.nfsess_xprt; 6115 sep->sess_cbsess.nfsess_xprt = NULL; 6116 if (xprt != NULL) 6117 SVC_RELEASE(xprt); 6118 } 6119 } 6120 } 6121} 6122 6123