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