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