1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2009 Rick Macklem, University of Guelph 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #ifndef APPLEKEXT 34 #include <sys/extattr.h> 35 #include <fs/nfs/nfsport.h> 36 37 struct nfsrv_stablefirst nfsrv_stablefirst; 38 int nfsrv_issuedelegs = 0; 39 int nfsrv_dolocallocks = 0; 40 struct nfsv4lock nfsv4rootfs_lock; 41 time_t nfsdev_time = 0; 42 int nfsrv_layouthashsize; 43 volatile int nfsrv_layoutcnt = 0; 44 45 extern int newnfs_numnfsd; 46 extern struct nfsstatsv1 nfsstatsv1; 47 extern int nfsrv_lease; 48 extern struct timeval nfsboottime; 49 extern u_int32_t newnfs_true, newnfs_false; 50 extern struct mtx nfsrv_dslock_mtx; 51 extern struct mtx nfsrv_recalllock_mtx; 52 extern struct mtx nfsrv_dontlistlock_mtx; 53 extern int nfsd_debuglevel; 54 extern u_int nfsrv_dsdirsize; 55 extern struct nfsdevicehead nfsrv_devidhead; 56 extern int nfsrv_doflexfile; 57 extern int nfsrv_maxpnfsmirror; 58 NFSV4ROOTLOCKMUTEX; 59 NFSSTATESPINLOCK; 60 extern struct nfsdontlisthead nfsrv_dontlisthead; 61 extern volatile int nfsrv_devidcnt; 62 extern struct nfslayouthead nfsrv_recalllisthead; 63 64 SYSCTL_DECL(_vfs_nfsd); 65 int nfsrv_statehashsize = NFSSTATEHASHSIZE; 66 SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN, 67 &nfsrv_statehashsize, 0, 68 "Size of state hash table set via loader.conf"); 69 70 int nfsrv_clienthashsize = NFSCLIENTHASHSIZE; 71 SYSCTL_INT(_vfs_nfsd, OID_AUTO, clienthashsize, CTLFLAG_RDTUN, 72 &nfsrv_clienthashsize, 0, 73 "Size of client hash table set via loader.conf"); 74 75 int nfsrv_lockhashsize = NFSLOCKHASHSIZE; 76 SYSCTL_INT(_vfs_nfsd, OID_AUTO, fhhashsize, CTLFLAG_RDTUN, 77 &nfsrv_lockhashsize, 0, 78 "Size of file handle hash table set via loader.conf"); 79 80 int nfsrv_sessionhashsize = NFSSESSIONHASHSIZE; 81 SYSCTL_INT(_vfs_nfsd, OID_AUTO, sessionhashsize, CTLFLAG_RDTUN, 82 &nfsrv_sessionhashsize, 0, 83 "Size of session hash table set via loader.conf"); 84 85 int nfsrv_layouthighwater = NFSLAYOUTHIGHWATER; 86 SYSCTL_INT(_vfs_nfsd, OID_AUTO, layouthighwater, CTLFLAG_RDTUN, 87 &nfsrv_layouthighwater, 0, 88 "High water mark for number of layouts set via loader.conf"); 89 90 static int nfsrv_v4statelimit = NFSRV_V4STATELIMIT; 91 SYSCTL_INT(_vfs_nfsd, OID_AUTO, v4statelimit, CTLFLAG_RWTUN, 92 &nfsrv_v4statelimit, 0, 93 "High water limit for NFSv4 opens+locks+delegations"); 94 95 static int nfsrv_writedelegifpos = 0; 96 SYSCTL_INT(_vfs_nfsd, OID_AUTO, writedelegifpos, CTLFLAG_RW, 97 &nfsrv_writedelegifpos, 0, 98 "Issue a write delegation for read opens if possible"); 99 100 static int nfsrv_allowreadforwriteopen = 1; 101 SYSCTL_INT(_vfs_nfsd, OID_AUTO, allowreadforwriteopen, CTLFLAG_RW, 102 &nfsrv_allowreadforwriteopen, 0, 103 "Allow Reads to be done with Write Access StateIDs"); 104 105 int nfsrv_pnfsatime = 0; 106 SYSCTL_INT(_vfs_nfsd, OID_AUTO, pnfsstrictatime, CTLFLAG_RW, 107 &nfsrv_pnfsatime, 0, 108 "For pNFS service, do Getattr ops to keep atime up-to-date"); 109 110 int nfsrv_flexlinuxhack = 0; 111 SYSCTL_INT(_vfs_nfsd, OID_AUTO, flexlinuxhack, CTLFLAG_RW, 112 &nfsrv_flexlinuxhack, 0, 113 "For Linux clients, hack around Flex File Layout bug"); 114 115 /* 116 * Hash lists for nfs V4. 117 */ 118 struct nfsclienthashhead *nfsclienthash; 119 struct nfslockhashhead *nfslockhash; 120 struct nfssessionhash *nfssessionhash; 121 struct nfslayouthash *nfslayouthash; 122 volatile int nfsrv_dontlistlen = 0; 123 #endif /* !APPLEKEXT */ 124 125 static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 0; 126 static time_t nfsrvboottime; 127 static int nfsrv_returnoldstateid = 0, nfsrv_clients = 0; 128 static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER; 129 static int nfsrv_nogsscallback = 0; 130 static volatile int nfsrv_writedelegcnt = 0; 131 static int nfsrv_faildscnt; 132 133 /* local functions */ 134 static void nfsrv_dumpaclient(struct nfsclient *clp, 135 struct nfsd_dumpclients *dumpp); 136 static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, 137 NFSPROC_T *p); 138 static int nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, 139 NFSPROC_T *p); 140 static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, 141 NFSPROC_T *p); 142 static void nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, 143 int cansleep, NFSPROC_T *p); 144 static void nfsrv_freenfslock(struct nfslock *lop); 145 static void nfsrv_freenfslockfile(struct nfslockfile *lfp); 146 static void nfsrv_freedeleg(struct nfsstate *); 147 static int nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, 148 u_int32_t flags, struct nfsstate **stpp); 149 static void nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, 150 struct nfsstate **stpp); 151 static int nfsrv_getlockfh(vnode_t vp, u_short flags, 152 struct nfslockfile *new_lfp, fhandle_t *nfhp, NFSPROC_T *p); 153 static int nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, 154 struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit); 155 static void nfsrv_insertlock(struct nfslock *new_lop, 156 struct nfslock *insert_lop, struct nfsstate *stp, struct nfslockfile *lfp); 157 static void nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, 158 struct nfslock **other_lopp, struct nfslockfile *lfp); 159 static int nfsrv_getipnumber(u_char *cp); 160 static int nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 161 nfsv4stateid_t *stateidp, int specialid); 162 static int nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp, 163 u_int32_t flags); 164 static int nfsrv_docallback(struct nfsclient *clp, int procnum, 165 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, 166 struct nfsvattr *nap, nfsattrbit_t *attrbitp, int laytype, NFSPROC_T *p); 167 static int nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp, 168 uint32_t callback, int op, const char *optag, struct nfsdsession **sepp); 169 static u_int32_t nfsrv_nextclientindex(void); 170 static u_int32_t nfsrv_nextstateindex(struct nfsclient *clp); 171 static void nfsrv_markstable(struct nfsclient *clp); 172 static void nfsrv_markreclaim(struct nfsclient *clp); 173 static int nfsrv_checkstable(struct nfsclient *clp); 174 static int nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, struct 175 vnode *vp, NFSPROC_T *p); 176 static int nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, 177 NFSPROC_T *p, vnode_t vp); 178 static int nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 179 struct nfsclient *clp, int *haslockp, NFSPROC_T *p); 180 static int nfsrv_notsamecredname(struct nfsrv_descript *nd, 181 struct nfsclient *clp); 182 static time_t nfsrv_leaseexpiry(void); 183 static void nfsrv_delaydelegtimeout(struct nfsstate *stp); 184 static int nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 185 struct nfsstate *stp, struct nfsrvcache *op); 186 static int nfsrv_nootherstate(struct nfsstate *stp); 187 static int nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, 188 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p); 189 static void nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, 190 uint64_t init_first, uint64_t init_end, NFSPROC_T *p); 191 static int nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, 192 int oldflags, uint64_t first, uint64_t end, struct nfslockconflict *cfp, 193 NFSPROC_T *p); 194 static void nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, 195 NFSPROC_T *p); 196 static void nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, 197 uint64_t first, uint64_t end); 198 static void nfsrv_locklf(struct nfslockfile *lfp); 199 static void nfsrv_unlocklf(struct nfslockfile *lfp); 200 static struct nfsdsession *nfsrv_findsession(uint8_t *sessionid); 201 static int nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid); 202 static int nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp, 203 int dont_replycache, struct nfsdsession **sepp); 204 static int nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp); 205 static int nfsrv_addlayout(struct nfsrv_descript *nd, struct nfslayout **lypp, 206 nfsv4stateid_t *stateidp, char *layp, int *layoutlenp, NFSPROC_T *p); 207 static void nfsrv_freelayout(struct nfslayouthead *lhp, struct nfslayout *lyp); 208 static void nfsrv_freelayoutlist(nfsquad_t clientid); 209 static void nfsrv_freelayouts(nfsquad_t *clid, fsid_t *fs, int laytype, 210 int iomode); 211 static void nfsrv_freealllayouts(void); 212 static void nfsrv_freedevid(struct nfsdevice *ds); 213 static int nfsrv_setdsserver(char *dspathp, NFSPROC_T *p, 214 struct nfsdevice **dsp); 215 static int nfsrv_delds(char *devid, NFSPROC_T *p); 216 static void nfsrv_deleteds(struct nfsdevice *fndds); 217 static void nfsrv_allocdevid(struct nfsdevice *ds, char *addr, char *dnshost); 218 static void nfsrv_freealldevids(void); 219 static void nfsrv_flexlayouterr(struct nfsrv_descript *nd, uint32_t *layp, 220 int maxcnt, NFSPROC_T *p); 221 static int nfsrv_recalllayout(nfsquad_t clid, nfsv4stateid_t *stateidp, 222 fhandle_t *fhp, struct nfslayout *lyp, struct nfslayouthead *lyheadp, 223 int laytype, NFSPROC_T *p); 224 static int nfsrv_findlayout(nfsquad_t *clientidp, fhandle_t *fhp, int laytype, 225 NFSPROC_T *, struct nfslayout **lypp); 226 static int nfsrv_fndclid(nfsquad_t *clidvec, nfsquad_t clid, int clidcnt); 227 static struct nfslayout *nfsrv_filelayout(struct nfsrv_descript *nd, int iomode, 228 fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs); 229 static struct nfslayout *nfsrv_flexlayout(struct nfsrv_descript *nd, int iomode, 230 int mirrorcnt, fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs); 231 static int nfsrv_dontlayout(fhandle_t *fhp); 232 static int nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf, 233 vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p, 234 vnode_t *tvpp); 235 236 /* 237 * Scan the client list for a match and either return the current one, 238 * create a new entry or return an error. 239 * If returning a non-error, the clp structure must either be linked into 240 * the client list or free'd. 241 */ 242 APPLESTATIC int 243 nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, 244 nfsquad_t *clientidp, nfsquad_t *confirmp, NFSPROC_T *p) 245 { 246 struct nfsclient *clp = NULL, *new_clp = *new_clpp; 247 int i, error = 0, ret; 248 struct nfsstate *stp, *tstp; 249 struct sockaddr_in *sad, *rad; 250 struct nfsdsession *sep, *nsep; 251 int zapit = 0, gotit, hasstate = 0, igotlock; 252 static u_int64_t confirm_index = 0; 253 254 /* 255 * Check for state resource limit exceeded. 256 */ 257 if (nfsrv_openpluslock > nfsrv_v4statelimit) { 258 error = NFSERR_RESOURCE; 259 goto out; 260 } 261 262 if (nfsrv_issuedelegs == 0 || 263 ((nd->nd_flag & ND_GSS) != 0 && nfsrv_nogsscallback != 0)) 264 /* 265 * Don't do callbacks when delegations are disabled or 266 * for AUTH_GSS unless enabled via nfsrv_nogsscallback. 267 * If establishing a callback connection is attempted 268 * when a firewall is blocking the callback path, the 269 * server may wait too long for the connect attempt to 270 * succeed during the Open. Some clients, such as Linux, 271 * may timeout and give up on the Open before the server 272 * replies. Also, since AUTH_GSS callbacks are not 273 * yet interoperability tested, they might cause the 274 * server to crap out, if they get past the Init call to 275 * the client. 276 */ 277 new_clp->lc_program = 0; 278 279 /* Lock out other nfsd threads */ 280 NFSLOCKV4ROOTMUTEX(); 281 nfsv4_relref(&nfsv4rootfs_lock); 282 do { 283 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 284 NFSV4ROOTLOCKMUTEXPTR, NULL); 285 } while (!igotlock); 286 NFSUNLOCKV4ROOTMUTEX(); 287 288 /* 289 * Search for a match in the client list. 290 */ 291 gotit = i = 0; 292 while (i < nfsrv_clienthashsize && !gotit) { 293 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 294 if (new_clp->lc_idlen == clp->lc_idlen && 295 !NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) { 296 gotit = 1; 297 break; 298 } 299 } 300 if (gotit == 0) 301 i++; 302 } 303 if (!gotit || 304 (clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_ADMINREVOKED))) { 305 if ((nd->nd_flag & ND_NFSV41) != 0 && confirmp->lval[1] != 0) { 306 /* 307 * For NFSv4.1, if confirmp->lval[1] is non-zero, the 308 * client is trying to update a confirmed clientid. 309 */ 310 NFSLOCKV4ROOTMUTEX(); 311 nfsv4_unlock(&nfsv4rootfs_lock, 1); 312 NFSUNLOCKV4ROOTMUTEX(); 313 confirmp->lval[1] = 0; 314 error = NFSERR_NOENT; 315 goto out; 316 } 317 /* 318 * Get rid of the old one. 319 */ 320 if (i != nfsrv_clienthashsize) { 321 LIST_REMOVE(clp, lc_hash); 322 nfsrv_cleanclient(clp, p); 323 nfsrv_freedeleglist(&clp->lc_deleg); 324 nfsrv_freedeleglist(&clp->lc_olddeleg); 325 zapit = 1; 326 } 327 /* 328 * Add it after assigning a client id to it. 329 */ 330 new_clp->lc_flags |= LCL_NEEDSCONFIRM; 331 if ((nd->nd_flag & ND_NFSV41) != 0) 332 new_clp->lc_confirm.lval[0] = confirmp->lval[0] = 333 ++confirm_index; 334 else 335 confirmp->qval = new_clp->lc_confirm.qval = 336 ++confirm_index; 337 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 338 (u_int32_t)nfsrvboottime; 339 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 340 nfsrv_nextclientindex(); 341 new_clp->lc_stateindex = 0; 342 new_clp->lc_statemaxindex = 0; 343 new_clp->lc_cbref = 0; 344 new_clp->lc_expiry = nfsrv_leaseexpiry(); 345 LIST_INIT(&new_clp->lc_open); 346 LIST_INIT(&new_clp->lc_deleg); 347 LIST_INIT(&new_clp->lc_olddeleg); 348 LIST_INIT(&new_clp->lc_session); 349 for (i = 0; i < nfsrv_statehashsize; i++) 350 LIST_INIT(&new_clp->lc_stateid[i]); 351 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 352 lc_hash); 353 nfsstatsv1.srvclients++; 354 nfsrv_openpluslock++; 355 nfsrv_clients++; 356 NFSLOCKV4ROOTMUTEX(); 357 nfsv4_unlock(&nfsv4rootfs_lock, 1); 358 NFSUNLOCKV4ROOTMUTEX(); 359 if (zapit) 360 nfsrv_zapclient(clp, p); 361 *new_clpp = NULL; 362 goto out; 363 } 364 365 /* 366 * Now, handle the cases where the id is already issued. 367 */ 368 if (nfsrv_notsamecredname(nd, clp)) { 369 /* 370 * Check to see if there is expired state that should go away. 371 */ 372 if (clp->lc_expiry < NFSD_MONOSEC && 373 (!LIST_EMPTY(&clp->lc_open) || !LIST_EMPTY(&clp->lc_deleg))) { 374 nfsrv_cleanclient(clp, p); 375 nfsrv_freedeleglist(&clp->lc_deleg); 376 } 377 378 /* 379 * If there is outstanding state, then reply NFSERR_CLIDINUSE per 380 * RFC3530 Sec. 8.1.2 last para. 381 */ 382 if (!LIST_EMPTY(&clp->lc_deleg)) { 383 hasstate = 1; 384 } else if (LIST_EMPTY(&clp->lc_open)) { 385 hasstate = 0; 386 } else { 387 hasstate = 0; 388 /* Look for an Open on the OpenOwner */ 389 LIST_FOREACH(stp, &clp->lc_open, ls_list) { 390 if (!LIST_EMPTY(&stp->ls_open)) { 391 hasstate = 1; 392 break; 393 } 394 } 395 } 396 if (hasstate) { 397 /* 398 * If the uid doesn't match, return NFSERR_CLIDINUSE after 399 * filling out the correct ipaddr and portnum. 400 */ 401 sad = NFSSOCKADDR(new_clp->lc_req.nr_nam, struct sockaddr_in *); 402 rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 403 sad->sin_addr.s_addr = rad->sin_addr.s_addr; 404 sad->sin_port = rad->sin_port; 405 NFSLOCKV4ROOTMUTEX(); 406 nfsv4_unlock(&nfsv4rootfs_lock, 1); 407 NFSUNLOCKV4ROOTMUTEX(); 408 error = NFSERR_CLIDINUSE; 409 goto out; 410 } 411 } 412 413 if (NFSBCMP(new_clp->lc_verf, clp->lc_verf, NFSX_VERF)) { 414 /* 415 * If the verifier has changed, the client has rebooted 416 * and a new client id is issued. The old state info 417 * can be thrown away once the SETCLIENTID_CONFIRM occurs. 418 */ 419 LIST_REMOVE(clp, lc_hash); 420 421 /* Get rid of all sessions on this clientid. */ 422 LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) { 423 ret = nfsrv_freesession(sep, NULL); 424 if (ret != 0) 425 printf("nfsrv_setclient: verifier changed free" 426 " session failed=%d\n", ret); 427 } 428 429 new_clp->lc_flags |= LCL_NEEDSCONFIRM; 430 if ((nd->nd_flag & ND_NFSV41) != 0) 431 new_clp->lc_confirm.lval[0] = confirmp->lval[0] = 432 ++confirm_index; 433 else 434 confirmp->qval = new_clp->lc_confirm.qval = 435 ++confirm_index; 436 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 437 nfsrvboottime; 438 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 439 nfsrv_nextclientindex(); 440 new_clp->lc_stateindex = 0; 441 new_clp->lc_statemaxindex = 0; 442 new_clp->lc_cbref = 0; 443 new_clp->lc_expiry = nfsrv_leaseexpiry(); 444 445 /* 446 * Save the state until confirmed. 447 */ 448 LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list); 449 LIST_FOREACH(tstp, &new_clp->lc_open, ls_list) 450 tstp->ls_clp = new_clp; 451 LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list); 452 LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list) 453 tstp->ls_clp = new_clp; 454 LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, 455 ls_list); 456 LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list) 457 tstp->ls_clp = new_clp; 458 for (i = 0; i < nfsrv_statehashsize; i++) { 459 LIST_NEWHEAD(&new_clp->lc_stateid[i], 460 &clp->lc_stateid[i], ls_hash); 461 LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) 462 tstp->ls_clp = new_clp; 463 } 464 LIST_INIT(&new_clp->lc_session); 465 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 466 lc_hash); 467 nfsstatsv1.srvclients++; 468 nfsrv_openpluslock++; 469 nfsrv_clients++; 470 NFSLOCKV4ROOTMUTEX(); 471 nfsv4_unlock(&nfsv4rootfs_lock, 1); 472 NFSUNLOCKV4ROOTMUTEX(); 473 474 /* 475 * Must wait until any outstanding callback on the old clp 476 * completes. 477 */ 478 NFSLOCKSTATE(); 479 while (clp->lc_cbref) { 480 clp->lc_flags |= LCL_WAKEUPWANTED; 481 (void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1, 482 "nfsd clp", 10 * hz); 483 } 484 NFSUNLOCKSTATE(); 485 nfsrv_zapclient(clp, p); 486 *new_clpp = NULL; 487 goto out; 488 } 489 490 /* For NFSv4.1, mark that we found a confirmed clientid. */ 491 if ((nd->nd_flag & ND_NFSV41) != 0) { 492 clientidp->lval[0] = clp->lc_clientid.lval[0]; 493 clientidp->lval[1] = clp->lc_clientid.lval[1]; 494 confirmp->lval[0] = 0; /* Ignored by client */ 495 confirmp->lval[1] = 1; 496 } else { 497 /* 498 * id and verifier match, so update the net address info 499 * and get rid of any existing callback authentication 500 * handle, so a new one will be acquired. 501 */ 502 LIST_REMOVE(clp, lc_hash); 503 new_clp->lc_flags |= (LCL_NEEDSCONFIRM | LCL_DONTCLEAN); 504 new_clp->lc_expiry = nfsrv_leaseexpiry(); 505 confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; 506 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 507 clp->lc_clientid.lval[0]; 508 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 509 clp->lc_clientid.lval[1]; 510 new_clp->lc_delegtime = clp->lc_delegtime; 511 new_clp->lc_stateindex = clp->lc_stateindex; 512 new_clp->lc_statemaxindex = clp->lc_statemaxindex; 513 new_clp->lc_cbref = 0; 514 LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list); 515 LIST_FOREACH(tstp, &new_clp->lc_open, ls_list) 516 tstp->ls_clp = new_clp; 517 LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list); 518 LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list) 519 tstp->ls_clp = new_clp; 520 LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, ls_list); 521 LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list) 522 tstp->ls_clp = new_clp; 523 for (i = 0; i < nfsrv_statehashsize; i++) { 524 LIST_NEWHEAD(&new_clp->lc_stateid[i], 525 &clp->lc_stateid[i], ls_hash); 526 LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash) 527 tstp->ls_clp = new_clp; 528 } 529 LIST_INIT(&new_clp->lc_session); 530 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 531 lc_hash); 532 nfsstatsv1.srvclients++; 533 nfsrv_openpluslock++; 534 nfsrv_clients++; 535 } 536 NFSLOCKV4ROOTMUTEX(); 537 nfsv4_unlock(&nfsv4rootfs_lock, 1); 538 NFSUNLOCKV4ROOTMUTEX(); 539 540 if ((nd->nd_flag & ND_NFSV41) == 0) { 541 /* 542 * Must wait until any outstanding callback on the old clp 543 * completes. 544 */ 545 NFSLOCKSTATE(); 546 while (clp->lc_cbref) { 547 clp->lc_flags |= LCL_WAKEUPWANTED; 548 (void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1, 549 "nfsdclp", 10 * hz); 550 } 551 NFSUNLOCKSTATE(); 552 nfsrv_zapclient(clp, p); 553 *new_clpp = NULL; 554 } 555 556 out: 557 NFSEXITCODE2(error, nd); 558 return (error); 559 } 560 561 /* 562 * Check to see if the client id exists and optionally confirm it. 563 */ 564 APPLESTATIC int 565 nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, 566 struct nfsdsession *nsep, nfsquad_t confirm, uint32_t cbprogram, 567 struct nfsrv_descript *nd, NFSPROC_T *p) 568 { 569 struct nfsclient *clp; 570 struct nfsstate *stp; 571 int i; 572 struct nfsclienthashhead *hp; 573 int error = 0, igotlock, doneok; 574 struct nfssessionhash *shp; 575 struct nfsdsession *sep; 576 uint64_t sessid[2]; 577 static uint64_t next_sess = 0; 578 579 if (clpp) 580 *clpp = NULL; 581 if ((nd == NULL || (nd->nd_flag & ND_NFSV41) == 0 || 582 opflags != CLOPS_RENEW) && nfsrvboottime != clientid.lval[0]) { 583 error = NFSERR_STALECLIENTID; 584 goto out; 585 } 586 587 /* 588 * If called with opflags == CLOPS_RENEW, the State Lock is 589 * already held. Otherwise, we need to get either that or, 590 * for the case of Confirm, lock out the nfsd threads. 591 */ 592 if (opflags & CLOPS_CONFIRM) { 593 NFSLOCKV4ROOTMUTEX(); 594 nfsv4_relref(&nfsv4rootfs_lock); 595 do { 596 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 597 NFSV4ROOTLOCKMUTEXPTR, NULL); 598 } while (!igotlock); 599 /* 600 * Create a new sessionid here, since we need to do it where 601 * there is a mutex held to serialize update of next_sess. 602 */ 603 if ((nd->nd_flag & ND_NFSV41) != 0) { 604 sessid[0] = ++next_sess; 605 sessid[1] = clientid.qval; 606 } 607 NFSUNLOCKV4ROOTMUTEX(); 608 } else if (opflags != CLOPS_RENEW) { 609 NFSLOCKSTATE(); 610 } 611 612 /* For NFSv4.1, the clp is acquired from the associated session. */ 613 if (nd != NULL && (nd->nd_flag & ND_NFSV41) != 0 && 614 opflags == CLOPS_RENEW) { 615 clp = NULL; 616 if ((nd->nd_flag & ND_HASSEQUENCE) != 0) { 617 shp = NFSSESSIONHASH(nd->nd_sessionid); 618 NFSLOCKSESSION(shp); 619 sep = nfsrv_findsession(nd->nd_sessionid); 620 if (sep != NULL) 621 clp = sep->sess_clp; 622 NFSUNLOCKSESSION(shp); 623 } 624 } else { 625 hp = NFSCLIENTHASH(clientid); 626 LIST_FOREACH(clp, hp, lc_hash) { 627 if (clp->lc_clientid.lval[1] == clientid.lval[1]) 628 break; 629 } 630 } 631 if (clp == NULL) { 632 if (opflags & CLOPS_CONFIRM) 633 error = NFSERR_STALECLIENTID; 634 else 635 error = NFSERR_EXPIRED; 636 } else if (clp->lc_flags & LCL_ADMINREVOKED) { 637 /* 638 * If marked admin revoked, just return the error. 639 */ 640 error = NFSERR_ADMINREVOKED; 641 } 642 if (error) { 643 if (opflags & CLOPS_CONFIRM) { 644 NFSLOCKV4ROOTMUTEX(); 645 nfsv4_unlock(&nfsv4rootfs_lock, 1); 646 NFSUNLOCKV4ROOTMUTEX(); 647 } else if (opflags != CLOPS_RENEW) { 648 NFSUNLOCKSTATE(); 649 } 650 goto out; 651 } 652 653 /* 654 * Perform any operations specified by the opflags. 655 */ 656 if (opflags & CLOPS_CONFIRM) { 657 if (((nd->nd_flag & ND_NFSV41) != 0 && 658 clp->lc_confirm.lval[0] != confirm.lval[0]) || 659 ((nd->nd_flag & ND_NFSV41) == 0 && 660 clp->lc_confirm.qval != confirm.qval)) 661 error = NFSERR_STALECLIENTID; 662 else if (nfsrv_notsamecredname(nd, clp)) 663 error = NFSERR_CLIDINUSE; 664 665 if (!error) { 666 if ((clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_DONTCLEAN)) == 667 LCL_NEEDSCONFIRM) { 668 /* 669 * Hang onto the delegations (as old delegations) 670 * for an Open with CLAIM_DELEGATE_PREV unless in 671 * grace, but get rid of the rest of the state. 672 */ 673 nfsrv_cleanclient(clp, p); 674 nfsrv_freedeleglist(&clp->lc_olddeleg); 675 if (nfsrv_checkgrace(nd, clp, 0)) { 676 /* In grace, so just delete delegations */ 677 nfsrv_freedeleglist(&clp->lc_deleg); 678 } else { 679 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) 680 stp->ls_flags |= NFSLCK_OLDDELEG; 681 clp->lc_delegtime = NFSD_MONOSEC + 682 nfsrv_lease + NFSRV_LEASEDELTA; 683 LIST_NEWHEAD(&clp->lc_olddeleg, &clp->lc_deleg, 684 ls_list); 685 } 686 if ((nd->nd_flag & ND_NFSV41) != 0) 687 clp->lc_program = cbprogram; 688 } 689 clp->lc_flags &= ~(LCL_NEEDSCONFIRM | LCL_DONTCLEAN); 690 if (clp->lc_program) 691 clp->lc_flags |= LCL_NEEDSCBNULL; 692 /* For NFSv4.1, link the session onto the client. */ 693 if (nsep != NULL) { 694 /* Hold a reference on the xprt for a backchannel. */ 695 if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) 696 != 0) { 697 if (clp->lc_req.nr_client == NULL) 698 clp->lc_req.nr_client = (struct __rpc_client *) 699 clnt_bck_create(nd->nd_xprt->xp_socket, 700 cbprogram, NFSV4_CBVERS); 701 if (clp->lc_req.nr_client != NULL) { 702 SVC_ACQUIRE(nd->nd_xprt); 703 nd->nd_xprt->xp_p2 = 704 clp->lc_req.nr_client->cl_private; 705 /* Disable idle timeout. */ 706 nd->nd_xprt->xp_idletimeout = 0; 707 nsep->sess_cbsess.nfsess_xprt = nd->nd_xprt; 708 } else 709 nsep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN; 710 } 711 NFSBCOPY(sessid, nsep->sess_sessionid, 712 NFSX_V4SESSIONID); 713 NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid, 714 NFSX_V4SESSIONID); 715 shp = NFSSESSIONHASH(nsep->sess_sessionid); 716 NFSLOCKSTATE(); 717 NFSLOCKSESSION(shp); 718 LIST_INSERT_HEAD(&shp->list, nsep, sess_hash); 719 LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list); 720 nsep->sess_clp = clp; 721 NFSUNLOCKSESSION(shp); 722 NFSUNLOCKSTATE(); 723 } 724 } 725 } else if (clp->lc_flags & LCL_NEEDSCONFIRM) { 726 error = NFSERR_EXPIRED; 727 } 728 729 /* 730 * If called by the Renew Op, we must check the principal. 731 */ 732 if (!error && (opflags & CLOPS_RENEWOP)) { 733 if (nfsrv_notsamecredname(nd, clp)) { 734 doneok = 0; 735 for (i = 0; i < nfsrv_statehashsize && doneok == 0; i++) { 736 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 737 if ((stp->ls_flags & NFSLCK_OPEN) && 738 stp->ls_uid == nd->nd_cred->cr_uid) { 739 doneok = 1; 740 break; 741 } 742 } 743 } 744 if (!doneok) 745 error = NFSERR_ACCES; 746 } 747 if (!error && (clp->lc_flags & LCL_CBDOWN)) 748 error = NFSERR_CBPATHDOWN; 749 } 750 if ((!error || error == NFSERR_CBPATHDOWN) && 751 (opflags & CLOPS_RENEW)) { 752 clp->lc_expiry = nfsrv_leaseexpiry(); 753 } 754 if (opflags & CLOPS_CONFIRM) { 755 NFSLOCKV4ROOTMUTEX(); 756 nfsv4_unlock(&nfsv4rootfs_lock, 1); 757 NFSUNLOCKV4ROOTMUTEX(); 758 } else if (opflags != CLOPS_RENEW) { 759 NFSUNLOCKSTATE(); 760 } 761 if (clpp) 762 *clpp = clp; 763 764 out: 765 NFSEXITCODE2(error, nd); 766 return (error); 767 } 768 769 /* 770 * Perform the NFSv4.1 destroy clientid. 771 */ 772 int 773 nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p) 774 { 775 struct nfsclient *clp; 776 struct nfsclienthashhead *hp; 777 int error = 0, i, igotlock; 778 779 if (nfsrvboottime != clientid.lval[0]) { 780 error = NFSERR_STALECLIENTID; 781 goto out; 782 } 783 784 /* Lock out other nfsd threads */ 785 NFSLOCKV4ROOTMUTEX(); 786 nfsv4_relref(&nfsv4rootfs_lock); 787 do { 788 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 789 NFSV4ROOTLOCKMUTEXPTR, NULL); 790 } while (igotlock == 0); 791 NFSUNLOCKV4ROOTMUTEX(); 792 793 hp = NFSCLIENTHASH(clientid); 794 LIST_FOREACH(clp, hp, lc_hash) { 795 if (clp->lc_clientid.lval[1] == clientid.lval[1]) 796 break; 797 } 798 if (clp == NULL) { 799 NFSLOCKV4ROOTMUTEX(); 800 nfsv4_unlock(&nfsv4rootfs_lock, 1); 801 NFSUNLOCKV4ROOTMUTEX(); 802 /* Just return ok, since it is gone. */ 803 goto out; 804 } 805 806 /* 807 * Free up all layouts on the clientid. Should the client return the 808 * layouts? 809 */ 810 nfsrv_freelayoutlist(clientid); 811 812 /* Scan for state on the clientid. */ 813 for (i = 0; i < nfsrv_statehashsize; i++) 814 if (!LIST_EMPTY(&clp->lc_stateid[i])) { 815 NFSLOCKV4ROOTMUTEX(); 816 nfsv4_unlock(&nfsv4rootfs_lock, 1); 817 NFSUNLOCKV4ROOTMUTEX(); 818 error = NFSERR_CLIENTIDBUSY; 819 goto out; 820 } 821 if (!LIST_EMPTY(&clp->lc_session) || !LIST_EMPTY(&clp->lc_deleg)) { 822 NFSLOCKV4ROOTMUTEX(); 823 nfsv4_unlock(&nfsv4rootfs_lock, 1); 824 NFSUNLOCKV4ROOTMUTEX(); 825 error = NFSERR_CLIENTIDBUSY; 826 goto out; 827 } 828 829 /* Destroy the clientid and return ok. */ 830 nfsrv_cleanclient(clp, p); 831 nfsrv_freedeleglist(&clp->lc_deleg); 832 nfsrv_freedeleglist(&clp->lc_olddeleg); 833 LIST_REMOVE(clp, lc_hash); 834 NFSLOCKV4ROOTMUTEX(); 835 nfsv4_unlock(&nfsv4rootfs_lock, 1); 836 NFSUNLOCKV4ROOTMUTEX(); 837 nfsrv_zapclient(clp, p); 838 out: 839 NFSEXITCODE2(error, nd); 840 return (error); 841 } 842 843 /* 844 * Called from the new nfssvc syscall to admin revoke a clientid. 845 * Returns 0 for success, error otherwise. 846 */ 847 APPLESTATIC int 848 nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p) 849 { 850 struct nfsclient *clp = NULL; 851 int i, error = 0; 852 int gotit, igotlock; 853 854 /* 855 * First, lock out the nfsd so that state won't change while the 856 * revocation record is being written to the stable storage restart 857 * file. 858 */ 859 NFSLOCKV4ROOTMUTEX(); 860 do { 861 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 862 NFSV4ROOTLOCKMUTEXPTR, NULL); 863 } while (!igotlock); 864 NFSUNLOCKV4ROOTMUTEX(); 865 866 /* 867 * Search for a match in the client list. 868 */ 869 gotit = i = 0; 870 while (i < nfsrv_clienthashsize && !gotit) { 871 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 872 if (revokep->nclid_idlen == clp->lc_idlen && 873 !NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) { 874 gotit = 1; 875 break; 876 } 877 } 878 i++; 879 } 880 if (!gotit) { 881 NFSLOCKV4ROOTMUTEX(); 882 nfsv4_unlock(&nfsv4rootfs_lock, 0); 883 NFSUNLOCKV4ROOTMUTEX(); 884 error = EPERM; 885 goto out; 886 } 887 888 /* 889 * Now, write out the revocation record 890 */ 891 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 892 nfsrv_backupstable(); 893 894 /* 895 * and clear out the state, marking the clientid revoked. 896 */ 897 clp->lc_flags &= ~LCL_CALLBACKSON; 898 clp->lc_flags |= LCL_ADMINREVOKED; 899 nfsrv_cleanclient(clp, p); 900 nfsrv_freedeleglist(&clp->lc_deleg); 901 nfsrv_freedeleglist(&clp->lc_olddeleg); 902 NFSLOCKV4ROOTMUTEX(); 903 nfsv4_unlock(&nfsv4rootfs_lock, 0); 904 NFSUNLOCKV4ROOTMUTEX(); 905 906 out: 907 NFSEXITCODE(error); 908 return (error); 909 } 910 911 /* 912 * Dump out stats for all clients. Called from nfssvc(2), that is used 913 * nfsstatsv1. 914 */ 915 APPLESTATIC void 916 nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt) 917 { 918 struct nfsclient *clp; 919 int i = 0, cnt = 0; 920 921 /* 922 * First, get a reference on the nfsv4rootfs_lock so that an 923 * exclusive lock cannot be acquired while dumping the clients. 924 */ 925 NFSLOCKV4ROOTMUTEX(); 926 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 927 NFSUNLOCKV4ROOTMUTEX(); 928 NFSLOCKSTATE(); 929 /* 930 * Rattle through the client lists until done. 931 */ 932 while (i < nfsrv_clienthashsize && cnt < maxcnt) { 933 clp = LIST_FIRST(&nfsclienthash[i]); 934 while (clp != LIST_END(&nfsclienthash[i]) && cnt < maxcnt) { 935 nfsrv_dumpaclient(clp, &dumpp[cnt]); 936 cnt++; 937 clp = LIST_NEXT(clp, lc_hash); 938 } 939 i++; 940 } 941 if (cnt < maxcnt) 942 dumpp[cnt].ndcl_clid.nclid_idlen = 0; 943 NFSUNLOCKSTATE(); 944 NFSLOCKV4ROOTMUTEX(); 945 nfsv4_relref(&nfsv4rootfs_lock); 946 NFSUNLOCKV4ROOTMUTEX(); 947 } 948 949 /* 950 * Dump stats for a client. Must be called with the NFSSTATELOCK and spl'd. 951 */ 952 static void 953 nfsrv_dumpaclient(struct nfsclient *clp, struct nfsd_dumpclients *dumpp) 954 { 955 struct nfsstate *stp, *openstp, *lckownstp; 956 struct nfslock *lop; 957 struct sockaddr *sad; 958 struct sockaddr_in *rad; 959 struct sockaddr_in6 *rad6; 960 961 dumpp->ndcl_nopenowners = dumpp->ndcl_nlockowners = 0; 962 dumpp->ndcl_nopens = dumpp->ndcl_nlocks = 0; 963 dumpp->ndcl_ndelegs = dumpp->ndcl_nolddelegs = 0; 964 dumpp->ndcl_flags = clp->lc_flags; 965 dumpp->ndcl_clid.nclid_idlen = clp->lc_idlen; 966 NFSBCOPY(clp->lc_id, dumpp->ndcl_clid.nclid_id, clp->lc_idlen); 967 sad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr *); 968 dumpp->ndcl_addrfam = sad->sa_family; 969 if (sad->sa_family == AF_INET) { 970 rad = (struct sockaddr_in *)sad; 971 dumpp->ndcl_cbaddr.sin_addr = rad->sin_addr; 972 } else { 973 rad6 = (struct sockaddr_in6 *)sad; 974 dumpp->ndcl_cbaddr.sin6_addr = rad6->sin6_addr; 975 } 976 977 /* 978 * Now, scan the state lists and total up the opens and locks. 979 */ 980 LIST_FOREACH(stp, &clp->lc_open, ls_list) { 981 dumpp->ndcl_nopenowners++; 982 LIST_FOREACH(openstp, &stp->ls_open, ls_list) { 983 dumpp->ndcl_nopens++; 984 LIST_FOREACH(lckownstp, &openstp->ls_open, ls_list) { 985 dumpp->ndcl_nlockowners++; 986 LIST_FOREACH(lop, &lckownstp->ls_lock, lo_lckowner) { 987 dumpp->ndcl_nlocks++; 988 } 989 } 990 } 991 } 992 993 /* 994 * and the delegation lists. 995 */ 996 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) { 997 dumpp->ndcl_ndelegs++; 998 } 999 LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) { 1000 dumpp->ndcl_nolddelegs++; 1001 } 1002 } 1003 1004 /* 1005 * Dump out lock stats for a file. 1006 */ 1007 APPLESTATIC void 1008 nfsrv_dumplocks(vnode_t vp, struct nfsd_dumplocks *ldumpp, int maxcnt, 1009 NFSPROC_T *p) 1010 { 1011 struct nfsstate *stp; 1012 struct nfslock *lop; 1013 int cnt = 0; 1014 struct nfslockfile *lfp; 1015 struct sockaddr *sad; 1016 struct sockaddr_in *rad; 1017 struct sockaddr_in6 *rad6; 1018 int ret; 1019 fhandle_t nfh; 1020 1021 ret = nfsrv_getlockfh(vp, 0, NULL, &nfh, p); 1022 /* 1023 * First, get a reference on the nfsv4rootfs_lock so that an 1024 * exclusive lock on it cannot be acquired while dumping the locks. 1025 */ 1026 NFSLOCKV4ROOTMUTEX(); 1027 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 1028 NFSUNLOCKV4ROOTMUTEX(); 1029 NFSLOCKSTATE(); 1030 if (!ret) 1031 ret = nfsrv_getlockfile(0, NULL, &lfp, &nfh, 0); 1032 if (ret) { 1033 ldumpp[0].ndlck_clid.nclid_idlen = 0; 1034 NFSUNLOCKSTATE(); 1035 NFSLOCKV4ROOTMUTEX(); 1036 nfsv4_relref(&nfsv4rootfs_lock); 1037 NFSUNLOCKV4ROOTMUTEX(); 1038 return; 1039 } 1040 1041 /* 1042 * For each open share on file, dump it out. 1043 */ 1044 stp = LIST_FIRST(&lfp->lf_open); 1045 while (stp != LIST_END(&lfp->lf_open) && cnt < maxcnt) { 1046 ldumpp[cnt].ndlck_flags = stp->ls_flags; 1047 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 1048 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 1049 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 1050 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 1051 ldumpp[cnt].ndlck_owner.nclid_idlen = 1052 stp->ls_openowner->ls_ownerlen; 1053 NFSBCOPY(stp->ls_openowner->ls_owner, 1054 ldumpp[cnt].ndlck_owner.nclid_id, 1055 stp->ls_openowner->ls_ownerlen); 1056 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 1057 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 1058 stp->ls_clp->lc_idlen); 1059 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 1060 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 1061 if (sad->sa_family == AF_INET) { 1062 rad = (struct sockaddr_in *)sad; 1063 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 1064 } else { 1065 rad6 = (struct sockaddr_in6 *)sad; 1066 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 1067 } 1068 stp = LIST_NEXT(stp, ls_file); 1069 cnt++; 1070 } 1071 1072 /* 1073 * and all locks. 1074 */ 1075 lop = LIST_FIRST(&lfp->lf_lock); 1076 while (lop != LIST_END(&lfp->lf_lock) && cnt < maxcnt) { 1077 stp = lop->lo_stp; 1078 ldumpp[cnt].ndlck_flags = lop->lo_flags; 1079 ldumpp[cnt].ndlck_first = lop->lo_first; 1080 ldumpp[cnt].ndlck_end = lop->lo_end; 1081 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 1082 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 1083 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 1084 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 1085 ldumpp[cnt].ndlck_owner.nclid_idlen = stp->ls_ownerlen; 1086 NFSBCOPY(stp->ls_owner, ldumpp[cnt].ndlck_owner.nclid_id, 1087 stp->ls_ownerlen); 1088 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 1089 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 1090 stp->ls_clp->lc_idlen); 1091 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 1092 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 1093 if (sad->sa_family == AF_INET) { 1094 rad = (struct sockaddr_in *)sad; 1095 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 1096 } else { 1097 rad6 = (struct sockaddr_in6 *)sad; 1098 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 1099 } 1100 lop = LIST_NEXT(lop, lo_lckfile); 1101 cnt++; 1102 } 1103 1104 /* 1105 * and the delegations. 1106 */ 1107 stp = LIST_FIRST(&lfp->lf_deleg); 1108 while (stp != LIST_END(&lfp->lf_deleg) && cnt < maxcnt) { 1109 ldumpp[cnt].ndlck_flags = stp->ls_flags; 1110 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 1111 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 1112 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 1113 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 1114 ldumpp[cnt].ndlck_owner.nclid_idlen = 0; 1115 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 1116 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 1117 stp->ls_clp->lc_idlen); 1118 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 1119 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 1120 if (sad->sa_family == AF_INET) { 1121 rad = (struct sockaddr_in *)sad; 1122 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 1123 } else { 1124 rad6 = (struct sockaddr_in6 *)sad; 1125 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 1126 } 1127 stp = LIST_NEXT(stp, ls_file); 1128 cnt++; 1129 } 1130 1131 /* 1132 * If list isn't full, mark end of list by setting the client name 1133 * to zero length. 1134 */ 1135 if (cnt < maxcnt) 1136 ldumpp[cnt].ndlck_clid.nclid_idlen = 0; 1137 NFSUNLOCKSTATE(); 1138 NFSLOCKV4ROOTMUTEX(); 1139 nfsv4_relref(&nfsv4rootfs_lock); 1140 NFSUNLOCKV4ROOTMUTEX(); 1141 } 1142 1143 /* 1144 * Server timer routine. It can scan any linked list, so long 1145 * as it holds the spin/mutex lock and there is no exclusive lock on 1146 * nfsv4rootfs_lock. 1147 * (For OpenBSD, a kthread is ok. For FreeBSD, I think it is ok 1148 * to do this from a callout, since the spin locks work. For 1149 * Darwin, I'm not sure what will work correctly yet.) 1150 * Should be called once per second. 1151 */ 1152 APPLESTATIC void 1153 nfsrv_servertimer(void) 1154 { 1155 struct nfsclient *clp, *nclp; 1156 struct nfsstate *stp, *nstp; 1157 int got_ref, i; 1158 1159 /* 1160 * Make sure nfsboottime is set. This is used by V3 as well 1161 * as V4. Note that nfsboottime is not nfsrvboottime, which is 1162 * only used by the V4 server for leases. 1163 */ 1164 if (nfsboottime.tv_sec == 0) 1165 NFSSETBOOTTIME(nfsboottime); 1166 1167 /* 1168 * If server hasn't started yet, just return. 1169 */ 1170 NFSLOCKSTATE(); 1171 if (nfsrv_stablefirst.nsf_eograce == 0) { 1172 NFSUNLOCKSTATE(); 1173 return; 1174 } 1175 if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) { 1176 if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) && 1177 NFSD_MONOSEC > nfsrv_stablefirst.nsf_eograce) 1178 nfsrv_stablefirst.nsf_flags |= 1179 (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); 1180 NFSUNLOCKSTATE(); 1181 return; 1182 } 1183 1184 /* 1185 * Try and get a reference count on the nfsv4rootfs_lock so that 1186 * no nfsd thread can acquire an exclusive lock on it before this 1187 * call is done. If it is already exclusively locked, just return. 1188 */ 1189 NFSLOCKV4ROOTMUTEX(); 1190 got_ref = nfsv4_getref_nonblock(&nfsv4rootfs_lock); 1191 NFSUNLOCKV4ROOTMUTEX(); 1192 if (got_ref == 0) { 1193 NFSUNLOCKSTATE(); 1194 return; 1195 } 1196 1197 /* 1198 * For each client... 1199 */ 1200 for (i = 0; i < nfsrv_clienthashsize; i++) { 1201 clp = LIST_FIRST(&nfsclienthash[i]); 1202 while (clp != LIST_END(&nfsclienthash[i])) { 1203 nclp = LIST_NEXT(clp, lc_hash); 1204 if (!(clp->lc_flags & LCL_EXPIREIT)) { 1205 if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC 1206 && ((LIST_EMPTY(&clp->lc_deleg) 1207 && LIST_EMPTY(&clp->lc_open)) || 1208 nfsrv_clients > nfsrv_clienthighwater)) || 1209 (clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC || 1210 (clp->lc_expiry < NFSD_MONOSEC && 1211 (nfsrv_openpluslock * 10 / 9) > nfsrv_v4statelimit)) { 1212 /* 1213 * Lease has expired several nfsrv_lease times ago: 1214 * PLUS 1215 * - no state is associated with it 1216 * OR 1217 * - above high water mark for number of clients 1218 * (nfsrv_clienthighwater should be large enough 1219 * that this only occurs when clients fail to 1220 * use the same nfs_client_id4.id. Maybe somewhat 1221 * higher that the maximum number of clients that 1222 * will mount this server?) 1223 * OR 1224 * Lease has expired a very long time ago 1225 * OR 1226 * Lease has expired PLUS the number of opens + locks 1227 * has exceeded 90% of capacity 1228 * 1229 * --> Mark for expiry. The actual expiry will be done 1230 * by an nfsd sometime soon. 1231 */ 1232 clp->lc_flags |= LCL_EXPIREIT; 1233 nfsrv_stablefirst.nsf_flags |= 1234 (NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT); 1235 } else { 1236 /* 1237 * If there are no opens, increment no open tick cnt 1238 * If time exceeds NFSNOOPEN, mark it to be thrown away 1239 * otherwise, if there is an open, reset no open time 1240 * Hopefully, this will avoid excessive re-creation 1241 * of open owners and subsequent open confirms. 1242 */ 1243 stp = LIST_FIRST(&clp->lc_open); 1244 while (stp != LIST_END(&clp->lc_open)) { 1245 nstp = LIST_NEXT(stp, ls_list); 1246 if (LIST_EMPTY(&stp->ls_open)) { 1247 stp->ls_noopens++; 1248 if (stp->ls_noopens > NFSNOOPEN || 1249 (nfsrv_openpluslock * 2) > 1250 nfsrv_v4statelimit) 1251 nfsrv_stablefirst.nsf_flags |= 1252 NFSNSF_NOOPENS; 1253 } else { 1254 stp->ls_noopens = 0; 1255 } 1256 stp = nstp; 1257 } 1258 } 1259 } 1260 clp = nclp; 1261 } 1262 } 1263 NFSUNLOCKSTATE(); 1264 NFSLOCKV4ROOTMUTEX(); 1265 nfsv4_relref(&nfsv4rootfs_lock); 1266 NFSUNLOCKV4ROOTMUTEX(); 1267 } 1268 1269 /* 1270 * The following set of functions free up the various data structures. 1271 */ 1272 /* 1273 * Clear out all open/lock state related to this nfsclient. 1274 * Caller must hold an exclusive lock on nfsv4rootfs_lock, so that 1275 * there are no other active nfsd threads. 1276 */ 1277 APPLESTATIC void 1278 nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p) 1279 { 1280 struct nfsstate *stp, *nstp; 1281 struct nfsdsession *sep, *nsep; 1282 1283 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) 1284 nfsrv_freeopenowner(stp, 1, p); 1285 if ((clp->lc_flags & LCL_ADMINREVOKED) == 0) 1286 LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) 1287 (void)nfsrv_freesession(sep, NULL); 1288 } 1289 1290 /* 1291 * Free a client that has been cleaned. It should also already have been 1292 * removed from the lists. 1293 * (Just to be safe w.r.t. newnfs_disconnect(), call this function when 1294 * softclock interrupts are enabled.) 1295 */ 1296 APPLESTATIC void 1297 nfsrv_zapclient(struct nfsclient *clp, NFSPROC_T *p) 1298 { 1299 1300 #ifdef notyet 1301 if ((clp->lc_flags & (LCL_GSS | LCL_CALLBACKSON)) == 1302 (LCL_GSS | LCL_CALLBACKSON) && 1303 (clp->lc_hand.nfsh_flag & NFSG_COMPLETE) && 1304 clp->lc_handlelen > 0) { 1305 clp->lc_hand.nfsh_flag &= ~NFSG_COMPLETE; 1306 clp->lc_hand.nfsh_flag |= NFSG_DESTROYED; 1307 (void) nfsrv_docallback(clp, NFSV4PROC_CBNULL, 1308 NULL, 0, NULL, NULL, NULL, 0, p); 1309 } 1310 #endif 1311 newnfs_disconnect(&clp->lc_req); 1312 free(clp->lc_req.nr_nam, M_SONAME); 1313 NFSFREEMUTEX(&clp->lc_req.nr_mtx); 1314 free(clp->lc_stateid, M_NFSDCLIENT); 1315 free(clp, M_NFSDCLIENT); 1316 NFSLOCKSTATE(); 1317 nfsstatsv1.srvclients--; 1318 nfsrv_openpluslock--; 1319 nfsrv_clients--; 1320 NFSUNLOCKSTATE(); 1321 } 1322 1323 /* 1324 * Free a list of delegation state structures. 1325 * (This function will also free all nfslockfile structures that no 1326 * longer have associated state.) 1327 */ 1328 APPLESTATIC void 1329 nfsrv_freedeleglist(struct nfsstatehead *sthp) 1330 { 1331 struct nfsstate *stp, *nstp; 1332 1333 LIST_FOREACH_SAFE(stp, sthp, ls_list, nstp) { 1334 nfsrv_freedeleg(stp); 1335 } 1336 LIST_INIT(sthp); 1337 } 1338 1339 /* 1340 * Free up a delegation. 1341 */ 1342 static void 1343 nfsrv_freedeleg(struct nfsstate *stp) 1344 { 1345 struct nfslockfile *lfp; 1346 1347 LIST_REMOVE(stp, ls_hash); 1348 LIST_REMOVE(stp, ls_list); 1349 LIST_REMOVE(stp, ls_file); 1350 if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0) 1351 nfsrv_writedelegcnt--; 1352 lfp = stp->ls_lfp; 1353 if (LIST_EMPTY(&lfp->lf_open) && 1354 LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) && 1355 LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && 1356 lfp->lf_usecount == 0 && 1357 nfsv4_testlock(&lfp->lf_locallock_lck) == 0) 1358 nfsrv_freenfslockfile(lfp); 1359 free(stp, M_NFSDSTATE); 1360 nfsstatsv1.srvdelegates--; 1361 nfsrv_openpluslock--; 1362 nfsrv_delegatecnt--; 1363 } 1364 1365 /* 1366 * This function frees an open owner and all associated opens. 1367 */ 1368 static void 1369 nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p) 1370 { 1371 struct nfsstate *nstp, *tstp; 1372 1373 LIST_REMOVE(stp, ls_list); 1374 /* 1375 * Now, free all associated opens. 1376 */ 1377 nstp = LIST_FIRST(&stp->ls_open); 1378 while (nstp != LIST_END(&stp->ls_open)) { 1379 tstp = nstp; 1380 nstp = LIST_NEXT(nstp, ls_list); 1381 (void) nfsrv_freeopen(tstp, NULL, cansleep, p); 1382 } 1383 if (stp->ls_op) 1384 nfsrvd_derefcache(stp->ls_op); 1385 free(stp, M_NFSDSTATE); 1386 nfsstatsv1.srvopenowners--; 1387 nfsrv_openpluslock--; 1388 } 1389 1390 /* 1391 * This function frees an open (nfsstate open structure) with all associated 1392 * lock_owners and locks. It also frees the nfslockfile structure iff there 1393 * are no other opens on the file. 1394 * Returns 1 if it free'd the nfslockfile, 0 otherwise. 1395 */ 1396 static int 1397 nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p) 1398 { 1399 struct nfsstate *nstp, *tstp; 1400 struct nfslockfile *lfp; 1401 int ret; 1402 1403 LIST_REMOVE(stp, ls_hash); 1404 LIST_REMOVE(stp, ls_list); 1405 LIST_REMOVE(stp, ls_file); 1406 1407 lfp = stp->ls_lfp; 1408 /* 1409 * Now, free all lockowners associated with this open. 1410 */ 1411 LIST_FOREACH_SAFE(tstp, &stp->ls_open, ls_list, nstp) 1412 nfsrv_freelockowner(tstp, vp, cansleep, p); 1413 1414 /* 1415 * The nfslockfile is freed here if there are no locks 1416 * associated with the open. 1417 * If there are locks associated with the open, the 1418 * nfslockfile structure can be freed via nfsrv_freelockowner(). 1419 * Acquire the state mutex to avoid races with calls to 1420 * nfsrv_getlockfile(). 1421 */ 1422 if (cansleep != 0) 1423 NFSLOCKSTATE(); 1424 if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) && 1425 LIST_EMPTY(&lfp->lf_deleg) && LIST_EMPTY(&lfp->lf_lock) && 1426 LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && 1427 lfp->lf_usecount == 0 && 1428 (cansleep != 0 || nfsv4_testlock(&lfp->lf_locallock_lck) == 0)) { 1429 nfsrv_freenfslockfile(lfp); 1430 ret = 1; 1431 } else 1432 ret = 0; 1433 if (cansleep != 0) 1434 NFSUNLOCKSTATE(); 1435 free(stp, M_NFSDSTATE); 1436 nfsstatsv1.srvopens--; 1437 nfsrv_openpluslock--; 1438 return (ret); 1439 } 1440 1441 /* 1442 * Frees a lockowner and all associated locks. 1443 */ 1444 static void 1445 nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, 1446 NFSPROC_T *p) 1447 { 1448 1449 LIST_REMOVE(stp, ls_hash); 1450 LIST_REMOVE(stp, ls_list); 1451 nfsrv_freeallnfslocks(stp, vp, cansleep, p); 1452 if (stp->ls_op) 1453 nfsrvd_derefcache(stp->ls_op); 1454 free(stp, M_NFSDSTATE); 1455 nfsstatsv1.srvlockowners--; 1456 nfsrv_openpluslock--; 1457 } 1458 1459 /* 1460 * Free all the nfs locks on a lockowner. 1461 */ 1462 static void 1463 nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep, 1464 NFSPROC_T *p) 1465 { 1466 struct nfslock *lop, *nlop; 1467 struct nfsrollback *rlp, *nrlp; 1468 struct nfslockfile *lfp = NULL; 1469 int gottvp = 0; 1470 vnode_t tvp = NULL; 1471 uint64_t first, end; 1472 1473 if (vp != NULL) 1474 ASSERT_VOP_UNLOCKED(vp, "nfsrv_freeallnfslocks: vnode locked"); 1475 lop = LIST_FIRST(&stp->ls_lock); 1476 while (lop != LIST_END(&stp->ls_lock)) { 1477 nlop = LIST_NEXT(lop, lo_lckowner); 1478 /* 1479 * Since all locks should be for the same file, lfp should 1480 * not change. 1481 */ 1482 if (lfp == NULL) 1483 lfp = lop->lo_lfp; 1484 else if (lfp != lop->lo_lfp) 1485 panic("allnfslocks"); 1486 /* 1487 * If vp is NULL and cansleep != 0, a vnode must be acquired 1488 * from the file handle. This only occurs when called from 1489 * nfsrv_cleanclient(). 1490 */ 1491 if (gottvp == 0) { 1492 if (nfsrv_dolocallocks == 0) 1493 tvp = NULL; 1494 else if (vp == NULL && cansleep != 0) { 1495 tvp = nfsvno_getvp(&lfp->lf_fh); 1496 NFSVOPUNLOCK(tvp, 0); 1497 } else 1498 tvp = vp; 1499 gottvp = 1; 1500 } 1501 1502 if (tvp != NULL) { 1503 if (cansleep == 0) 1504 panic("allnfs2"); 1505 first = lop->lo_first; 1506 end = lop->lo_end; 1507 nfsrv_freenfslock(lop); 1508 nfsrv_localunlock(tvp, lfp, first, end, p); 1509 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, 1510 nrlp) 1511 free(rlp, M_NFSDROLLBACK); 1512 LIST_INIT(&lfp->lf_rollback); 1513 } else 1514 nfsrv_freenfslock(lop); 1515 lop = nlop; 1516 } 1517 if (vp == NULL && tvp != NULL) 1518 vrele(tvp); 1519 } 1520 1521 /* 1522 * Free an nfslock structure. 1523 */ 1524 static void 1525 nfsrv_freenfslock(struct nfslock *lop) 1526 { 1527 1528 if (lop->lo_lckfile.le_prev != NULL) { 1529 LIST_REMOVE(lop, lo_lckfile); 1530 nfsstatsv1.srvlocks--; 1531 nfsrv_openpluslock--; 1532 } 1533 LIST_REMOVE(lop, lo_lckowner); 1534 free(lop, M_NFSDLOCK); 1535 } 1536 1537 /* 1538 * This function frees an nfslockfile structure. 1539 */ 1540 static void 1541 nfsrv_freenfslockfile(struct nfslockfile *lfp) 1542 { 1543 1544 LIST_REMOVE(lfp, lf_hash); 1545 free(lfp, M_NFSDLOCKFILE); 1546 } 1547 1548 /* 1549 * This function looks up an nfsstate structure via stateid. 1550 */ 1551 static int 1552 nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32_t flags, 1553 struct nfsstate **stpp) 1554 { 1555 struct nfsstate *stp; 1556 struct nfsstatehead *hp; 1557 int error = 0; 1558 1559 *stpp = NULL; 1560 hp = NFSSTATEHASH(clp, *stateidp); 1561 LIST_FOREACH(stp, hp, ls_hash) { 1562 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other, 1563 NFSX_STATEIDOTHER)) 1564 break; 1565 } 1566 1567 /* 1568 * If no state id in list, return NFSERR_BADSTATEID. 1569 */ 1570 if (stp == LIST_END(hp)) { 1571 error = NFSERR_BADSTATEID; 1572 goto out; 1573 } 1574 *stpp = stp; 1575 1576 out: 1577 NFSEXITCODE(error); 1578 return (error); 1579 } 1580 1581 /* 1582 * This function gets an nfsstate structure via owner string. 1583 */ 1584 static void 1585 nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, 1586 struct nfsstate **stpp) 1587 { 1588 struct nfsstate *stp; 1589 1590 *stpp = NULL; 1591 LIST_FOREACH(stp, hp, ls_list) { 1592 if (new_stp->ls_ownerlen == stp->ls_ownerlen && 1593 !NFSBCMP(new_stp->ls_owner,stp->ls_owner,stp->ls_ownerlen)) { 1594 *stpp = stp; 1595 return; 1596 } 1597 } 1598 } 1599 1600 /* 1601 * Lock control function called to update lock status. 1602 * Returns 0 upon success, -1 if there is no lock and the flags indicate 1603 * that one isn't to be created and an NFSERR_xxx for other errors. 1604 * The structures new_stp and new_lop are passed in as pointers that should 1605 * be set to NULL if the structure is used and shouldn't be free'd. 1606 * For the NFSLCK_TEST and NFSLCK_CHECK cases, the structures are 1607 * never used and can safely be allocated on the stack. For all other 1608 * cases, *new_stpp and *new_lopp should be malloc'd before the call, 1609 * in case they are used. 1610 */ 1611 APPLESTATIC int 1612 nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp, 1613 struct nfslock **new_lopp, struct nfslockconflict *cfp, 1614 nfsquad_t clientid, nfsv4stateid_t *stateidp, 1615 __unused struct nfsexstuff *exp, 1616 struct nfsrv_descript *nd, NFSPROC_T *p) 1617 { 1618 struct nfslock *lop; 1619 struct nfsstate *new_stp = *new_stpp; 1620 struct nfslock *new_lop = *new_lopp; 1621 struct nfsstate *tstp, *mystp, *nstp; 1622 int specialid = 0; 1623 struct nfslockfile *lfp; 1624 struct nfslock *other_lop = NULL; 1625 struct nfsstate *stp, *lckstp = NULL; 1626 struct nfsclient *clp = NULL; 1627 u_int32_t bits; 1628 int error = 0, haslock = 0, ret, reterr; 1629 int getlckret, delegation = 0, filestruct_locked, vnode_unlocked = 0; 1630 fhandle_t nfh; 1631 uint64_t first, end; 1632 uint32_t lock_flags; 1633 1634 if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_SETATTR)) { 1635 /* 1636 * Note the special cases of "all 1s" or "all 0s" stateids and 1637 * let reads with all 1s go ahead. 1638 */ 1639 if (new_stp->ls_stateid.seqid == 0x0 && 1640 new_stp->ls_stateid.other[0] == 0x0 && 1641 new_stp->ls_stateid.other[1] == 0x0 && 1642 new_stp->ls_stateid.other[2] == 0x0) 1643 specialid = 1; 1644 else if (new_stp->ls_stateid.seqid == 0xffffffff && 1645 new_stp->ls_stateid.other[0] == 0xffffffff && 1646 new_stp->ls_stateid.other[1] == 0xffffffff && 1647 new_stp->ls_stateid.other[2] == 0xffffffff) 1648 specialid = 2; 1649 } 1650 1651 /* 1652 * Check for restart conditions (client and server). 1653 */ 1654 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 1655 &new_stp->ls_stateid, specialid); 1656 if (error) 1657 goto out; 1658 1659 /* 1660 * Check for state resource limit exceeded. 1661 */ 1662 if ((new_stp->ls_flags & NFSLCK_LOCK) && 1663 nfsrv_openpluslock > nfsrv_v4statelimit) { 1664 error = NFSERR_RESOURCE; 1665 goto out; 1666 } 1667 1668 /* 1669 * For the lock case, get another nfslock structure, 1670 * just in case we need it. 1671 * Malloc now, before we start sifting through the linked lists, 1672 * in case we have to wait for memory. 1673 */ 1674 tryagain: 1675 if (new_stp->ls_flags & NFSLCK_LOCK) 1676 other_lop = malloc(sizeof (struct nfslock), 1677 M_NFSDLOCK, M_WAITOK); 1678 filestruct_locked = 0; 1679 reterr = 0; 1680 lfp = NULL; 1681 1682 /* 1683 * Get the lockfile structure for CFH now, so we can do a sanity 1684 * check against the stateid, before incrementing the seqid#, since 1685 * we want to return NFSERR_BADSTATEID on failure and the seqid# 1686 * shouldn't be incremented for this case. 1687 * If nfsrv_getlockfile() returns -1, it means "not found", which 1688 * will be handled later. 1689 * If we are doing Lock/LockU and local locking is enabled, sleep 1690 * lock the nfslockfile structure. 1691 */ 1692 getlckret = nfsrv_getlockfh(vp, new_stp->ls_flags, NULL, &nfh, p); 1693 NFSLOCKSTATE(); 1694 if (getlckret == 0) { 1695 if ((new_stp->ls_flags & (NFSLCK_LOCK | NFSLCK_UNLOCK)) != 0 && 1696 nfsrv_dolocallocks != 0 && nd->nd_repstat == 0) { 1697 getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, 1698 &lfp, &nfh, 1); 1699 if (getlckret == 0) 1700 filestruct_locked = 1; 1701 } else 1702 getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, 1703 &lfp, &nfh, 0); 1704 } 1705 if (getlckret != 0 && getlckret != -1) 1706 reterr = getlckret; 1707 1708 if (filestruct_locked != 0) { 1709 LIST_INIT(&lfp->lf_rollback); 1710 if ((new_stp->ls_flags & NFSLCK_LOCK)) { 1711 /* 1712 * For local locking, do the advisory locking now, so 1713 * that any conflict can be detected. A failure later 1714 * can be rolled back locally. If an error is returned, 1715 * struct nfslockfile has been unlocked and any local 1716 * locking rolled back. 1717 */ 1718 NFSUNLOCKSTATE(); 1719 if (vnode_unlocked == 0) { 1720 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl1"); 1721 vnode_unlocked = 1; 1722 NFSVOPUNLOCK(vp, 0); 1723 } 1724 reterr = nfsrv_locallock(vp, lfp, 1725 (new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)), 1726 new_lop->lo_first, new_lop->lo_end, cfp, p); 1727 NFSLOCKSTATE(); 1728 } 1729 } 1730 1731 if (specialid == 0) { 1732 if (new_stp->ls_flags & NFSLCK_TEST) { 1733 /* 1734 * RFC 3530 does not list LockT as an op that renews a 1735 * lease, but the consensus seems to be that it is ok 1736 * for a server to do so. 1737 */ 1738 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 1739 (nfsquad_t)((u_quad_t)0), 0, nd, p); 1740 1741 /* 1742 * Since NFSERR_EXPIRED, NFSERR_ADMINREVOKED are not valid 1743 * error returns for LockT, just go ahead and test for a lock, 1744 * since there are no locks for this client, but other locks 1745 * can conflict. (ie. same client will always be false) 1746 */ 1747 if (error == NFSERR_EXPIRED || error == NFSERR_ADMINREVOKED) 1748 error = 0; 1749 lckstp = new_stp; 1750 } else { 1751 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 1752 (nfsquad_t)((u_quad_t)0), 0, nd, p); 1753 if (error == 0) 1754 /* 1755 * Look up the stateid 1756 */ 1757 error = nfsrv_getstate(clp, &new_stp->ls_stateid, 1758 new_stp->ls_flags, &stp); 1759 /* 1760 * do some sanity checks for an unconfirmed open or a 1761 * stateid that refers to the wrong file, for an open stateid 1762 */ 1763 if (error == 0 && (stp->ls_flags & NFSLCK_OPEN) && 1764 ((stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM) || 1765 (getlckret == 0 && stp->ls_lfp != lfp))){ 1766 /* 1767 * NFSLCK_SETATTR should return OK rather than NFSERR_BADSTATEID 1768 * The only exception is using SETATTR with SIZE. 1769 * */ 1770 if ((new_stp->ls_flags & 1771 (NFSLCK_SETATTR | NFSLCK_CHECK)) != NFSLCK_SETATTR) 1772 error = NFSERR_BADSTATEID; 1773 } 1774 1775 if (error == 0 && 1776 (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) && 1777 getlckret == 0 && stp->ls_lfp != lfp) 1778 error = NFSERR_BADSTATEID; 1779 1780 /* 1781 * If the lockowner stateid doesn't refer to the same file, 1782 * I believe that is considered ok, since some clients will 1783 * only create a single lockowner and use that for all locks 1784 * on all files. 1785 * For now, log it as a diagnostic, instead of considering it 1786 * a BadStateid. 1787 */ 1788 if (error == 0 && (stp->ls_flags & 1789 (NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 && 1790 getlckret == 0 && stp->ls_lfp != lfp) { 1791 #ifdef DIAGNOSTIC 1792 printf("Got a lock statid for different file open\n"); 1793 #endif 1794 /* 1795 error = NFSERR_BADSTATEID; 1796 */ 1797 } 1798 1799 if (error == 0) { 1800 if (new_stp->ls_flags & NFSLCK_OPENTOLOCK) { 1801 /* 1802 * If haslock set, we've already checked the seqid. 1803 */ 1804 if (!haslock) { 1805 if (stp->ls_flags & NFSLCK_OPEN) 1806 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 1807 stp->ls_openowner, new_stp->ls_op); 1808 else 1809 error = NFSERR_BADSTATEID; 1810 } 1811 if (!error) 1812 nfsrv_getowner(&stp->ls_open, new_stp, &lckstp); 1813 if (lckstp) 1814 /* 1815 * I believe this should be an error, but it 1816 * isn't obvious what NFSERR_xxx would be 1817 * appropriate, so I'll use NFSERR_INVAL for now. 1818 */ 1819 error = NFSERR_INVAL; 1820 else 1821 lckstp = new_stp; 1822 } else if (new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK)) { 1823 /* 1824 * If haslock set, ditto above. 1825 */ 1826 if (!haslock) { 1827 if (stp->ls_flags & NFSLCK_OPEN) 1828 error = NFSERR_BADSTATEID; 1829 else 1830 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 1831 stp, new_stp->ls_op); 1832 } 1833 lckstp = stp; 1834 } else { 1835 lckstp = stp; 1836 } 1837 } 1838 /* 1839 * If the seqid part of the stateid isn't the same, return 1840 * NFSERR_OLDSTATEID for cases other than I/O Ops. 1841 * For I/O Ops, only return NFSERR_OLDSTATEID if 1842 * nfsrv_returnoldstateid is set. (The consensus on the email 1843 * list was that most clients would prefer to not receive 1844 * NFSERR_OLDSTATEID for I/O Ops, but the RFC suggests that that 1845 * is what will happen, so I use the nfsrv_returnoldstateid to 1846 * allow for either server configuration.) 1847 */ 1848 if (!error && stp->ls_stateid.seqid!=new_stp->ls_stateid.seqid && 1849 (((nd->nd_flag & ND_NFSV41) == 0 && 1850 (!(new_stp->ls_flags & NFSLCK_CHECK) || 1851 nfsrv_returnoldstateid)) || 1852 ((nd->nd_flag & ND_NFSV41) != 0 && 1853 new_stp->ls_stateid.seqid != 0))) 1854 error = NFSERR_OLDSTATEID; 1855 } 1856 } 1857 1858 /* 1859 * Now we can check for grace. 1860 */ 1861 if (!error) 1862 error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags); 1863 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error && 1864 nfsrv_checkstable(clp)) 1865 error = NFSERR_NOGRACE; 1866 /* 1867 * If we successfully Reclaimed state, note that. 1868 */ 1869 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error) 1870 nfsrv_markstable(clp); 1871 1872 /* 1873 * At this point, either error == NFSERR_BADSTATEID or the 1874 * seqid# has been updated, so we can return any error. 1875 * If error == 0, there may be an error in: 1876 * nd_repstat - Set by the calling function. 1877 * reterr - Set above, if getting the nfslockfile structure 1878 * or acquiring the local lock failed. 1879 * (If both of these are set, nd_repstat should probably be 1880 * returned, since that error was detected before this 1881 * function call.) 1882 */ 1883 if (error != 0 || nd->nd_repstat != 0 || reterr != 0) { 1884 if (error == 0) { 1885 if (nd->nd_repstat != 0) 1886 error = nd->nd_repstat; 1887 else 1888 error = reterr; 1889 } 1890 if (filestruct_locked != 0) { 1891 /* Roll back local locks. */ 1892 NFSUNLOCKSTATE(); 1893 if (vnode_unlocked == 0) { 1894 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl2"); 1895 vnode_unlocked = 1; 1896 NFSVOPUNLOCK(vp, 0); 1897 } 1898 nfsrv_locallock_rollback(vp, lfp, p); 1899 NFSLOCKSTATE(); 1900 nfsrv_unlocklf(lfp); 1901 } 1902 NFSUNLOCKSTATE(); 1903 goto out; 1904 } 1905 1906 /* 1907 * Check the nfsrv_getlockfile return. 1908 * Returned -1 if no structure found. 1909 */ 1910 if (getlckret == -1) { 1911 error = NFSERR_EXPIRED; 1912 /* 1913 * Called from lockt, so no lock is OK. 1914 */ 1915 if (new_stp->ls_flags & NFSLCK_TEST) { 1916 error = 0; 1917 } else if (new_stp->ls_flags & 1918 (NFSLCK_CHECK | NFSLCK_SETATTR)) { 1919 /* 1920 * Called to check for a lock, OK if the stateid is all 1921 * 1s or all 0s, but there should be an nfsstate 1922 * otherwise. 1923 * (ie. If there is no open, I'll assume no share 1924 * deny bits.) 1925 */ 1926 if (specialid) 1927 error = 0; 1928 else 1929 error = NFSERR_BADSTATEID; 1930 } 1931 NFSUNLOCKSTATE(); 1932 goto out; 1933 } 1934 1935 /* 1936 * For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict. 1937 * For NFSLCK_CHECK, allow a read if write access is granted, 1938 * but check for a deny. For NFSLCK_LOCK, require correct access, 1939 * which implies a conflicting deny can't exist. 1940 */ 1941 if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_LOCK)) { 1942 /* 1943 * Four kinds of state id: 1944 * - specialid (all 0s or all 1s), only for NFSLCK_CHECK 1945 * - stateid for an open 1946 * - stateid for a delegation 1947 * - stateid for a lock owner 1948 */ 1949 if (!specialid) { 1950 if (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { 1951 delegation = 1; 1952 mystp = stp; 1953 nfsrv_delaydelegtimeout(stp); 1954 } else if (stp->ls_flags & NFSLCK_OPEN) { 1955 mystp = stp; 1956 } else { 1957 mystp = stp->ls_openstp; 1958 } 1959 /* 1960 * If locking or checking, require correct access 1961 * bit set. 1962 */ 1963 if (((new_stp->ls_flags & NFSLCK_LOCK) && 1964 !((new_lop->lo_flags >> NFSLCK_LOCKSHIFT) & 1965 mystp->ls_flags & NFSLCK_ACCESSBITS)) || 1966 ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_READACCESS)) == 1967 (NFSLCK_CHECK | NFSLCK_READACCESS) && 1968 !(mystp->ls_flags & NFSLCK_READACCESS) && 1969 nfsrv_allowreadforwriteopen == 0) || 1970 ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) == 1971 (NFSLCK_CHECK | NFSLCK_WRITEACCESS) && 1972 !(mystp->ls_flags & NFSLCK_WRITEACCESS))) { 1973 if (filestruct_locked != 0) { 1974 /* Roll back local locks. */ 1975 NFSUNLOCKSTATE(); 1976 if (vnode_unlocked == 0) { 1977 ASSERT_VOP_ELOCKED(vp, 1978 "nfsrv_lockctrl3"); 1979 vnode_unlocked = 1; 1980 NFSVOPUNLOCK(vp, 0); 1981 } 1982 nfsrv_locallock_rollback(vp, lfp, p); 1983 NFSLOCKSTATE(); 1984 nfsrv_unlocklf(lfp); 1985 } 1986 NFSUNLOCKSTATE(); 1987 error = NFSERR_OPENMODE; 1988 goto out; 1989 } 1990 } else 1991 mystp = NULL; 1992 if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) { 1993 /* 1994 * Check for a conflicting deny bit. 1995 */ 1996 LIST_FOREACH(tstp, &lfp->lf_open, ls_file) { 1997 if (tstp != mystp) { 1998 bits = tstp->ls_flags; 1999 bits >>= NFSLCK_SHIFT; 2000 if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) { 2001 KASSERT(vnode_unlocked == 0, 2002 ("nfsrv_lockctrl: vnode unlocked1")); 2003 ret = nfsrv_clientconflict(tstp->ls_clp, &haslock, 2004 vp, p); 2005 if (ret == 1) { 2006 /* 2007 * nfsrv_clientconflict unlocks state 2008 * when it returns non-zero. 2009 */ 2010 lckstp = NULL; 2011 goto tryagain; 2012 } 2013 if (ret == 0) 2014 NFSUNLOCKSTATE(); 2015 if (ret == 2) 2016 error = NFSERR_PERM; 2017 else 2018 error = NFSERR_OPENMODE; 2019 goto out; 2020 } 2021 } 2022 } 2023 2024 /* We're outta here */ 2025 NFSUNLOCKSTATE(); 2026 goto out; 2027 } 2028 } 2029 2030 /* 2031 * For setattr, just get rid of all the Delegations for other clients. 2032 */ 2033 if (new_stp->ls_flags & NFSLCK_SETATTR) { 2034 KASSERT(vnode_unlocked == 0, 2035 ("nfsrv_lockctrl: vnode unlocked2")); 2036 ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p); 2037 if (ret) { 2038 /* 2039 * nfsrv_cleandeleg() unlocks state when it 2040 * returns non-zero. 2041 */ 2042 if (ret == -1) { 2043 lckstp = NULL; 2044 goto tryagain; 2045 } 2046 error = ret; 2047 goto out; 2048 } 2049 if (!(new_stp->ls_flags & NFSLCK_CHECK) || 2050 (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) && 2051 LIST_EMPTY(&lfp->lf_deleg))) { 2052 NFSUNLOCKSTATE(); 2053 goto out; 2054 } 2055 } 2056 2057 /* 2058 * Check for a conflicting delegation. If one is found, call 2059 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2060 * been set yet, it will get the lock. Otherwise, it will recall 2061 * the delegation. Then, we try try again... 2062 * I currently believe the conflict algorithm to be: 2063 * For Lock Ops (Lock/LockT/LockU) 2064 * - there is a conflict iff a different client has a write delegation 2065 * For Reading (Read Op) 2066 * - there is a conflict iff a different client has a write delegation 2067 * (the specialids are always a different client) 2068 * For Writing (Write/Setattr of size) 2069 * - there is a conflict if a different client has any delegation 2070 * - there is a conflict if the same client has a read delegation 2071 * (I don't understand why this isn't allowed, but that seems to be 2072 * the current consensus?) 2073 */ 2074 tstp = LIST_FIRST(&lfp->lf_deleg); 2075 while (tstp != LIST_END(&lfp->lf_deleg)) { 2076 nstp = LIST_NEXT(tstp, ls_file); 2077 if ((((new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK|NFSLCK_TEST))|| 2078 ((new_stp->ls_flags & NFSLCK_CHECK) && 2079 (new_lop->lo_flags & NFSLCK_READ))) && 2080 clp != tstp->ls_clp && 2081 (tstp->ls_flags & NFSLCK_DELEGWRITE)) || 2082 ((new_stp->ls_flags & NFSLCK_CHECK) && 2083 (new_lop->lo_flags & NFSLCK_WRITE) && 2084 (clp != tstp->ls_clp || 2085 (tstp->ls_flags & NFSLCK_DELEGREAD)))) { 2086 ret = 0; 2087 if (filestruct_locked != 0) { 2088 /* Roll back local locks. */ 2089 NFSUNLOCKSTATE(); 2090 if (vnode_unlocked == 0) { 2091 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl4"); 2092 NFSVOPUNLOCK(vp, 0); 2093 } 2094 nfsrv_locallock_rollback(vp, lfp, p); 2095 NFSLOCKSTATE(); 2096 nfsrv_unlocklf(lfp); 2097 NFSUNLOCKSTATE(); 2098 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 2099 vnode_unlocked = 0; 2100 if ((vp->v_iflag & VI_DOOMED) != 0) 2101 ret = NFSERR_SERVERFAULT; 2102 NFSLOCKSTATE(); 2103 } 2104 if (ret == 0) 2105 ret = nfsrv_delegconflict(tstp, &haslock, p, vp); 2106 if (ret) { 2107 /* 2108 * nfsrv_delegconflict unlocks state when it 2109 * returns non-zero, which it always does. 2110 */ 2111 if (other_lop) { 2112 free(other_lop, M_NFSDLOCK); 2113 other_lop = NULL; 2114 } 2115 if (ret == -1) { 2116 lckstp = NULL; 2117 goto tryagain; 2118 } 2119 error = ret; 2120 goto out; 2121 } 2122 /* Never gets here. */ 2123 } 2124 tstp = nstp; 2125 } 2126 2127 /* 2128 * Handle the unlock case by calling nfsrv_updatelock(). 2129 * (Should I have done some access checking above for unlock? For now, 2130 * just let it happen.) 2131 */ 2132 if (new_stp->ls_flags & NFSLCK_UNLOCK) { 2133 first = new_lop->lo_first; 2134 end = new_lop->lo_end; 2135 nfsrv_updatelock(stp, new_lopp, &other_lop, lfp); 2136 stateidp->seqid = ++(stp->ls_stateid.seqid); 2137 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0) 2138 stateidp->seqid = stp->ls_stateid.seqid = 1; 2139 stateidp->other[0] = stp->ls_stateid.other[0]; 2140 stateidp->other[1] = stp->ls_stateid.other[1]; 2141 stateidp->other[2] = stp->ls_stateid.other[2]; 2142 if (filestruct_locked != 0) { 2143 NFSUNLOCKSTATE(); 2144 if (vnode_unlocked == 0) { 2145 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl5"); 2146 vnode_unlocked = 1; 2147 NFSVOPUNLOCK(vp, 0); 2148 } 2149 /* Update the local locks. */ 2150 nfsrv_localunlock(vp, lfp, first, end, p); 2151 NFSLOCKSTATE(); 2152 nfsrv_unlocklf(lfp); 2153 } 2154 NFSUNLOCKSTATE(); 2155 goto out; 2156 } 2157 2158 /* 2159 * Search for a conflicting lock. A lock conflicts if: 2160 * - the lock range overlaps and 2161 * - at least one lock is a write lock and 2162 * - it is not owned by the same lock owner 2163 */ 2164 if (!delegation) { 2165 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { 2166 if (new_lop->lo_end > lop->lo_first && 2167 new_lop->lo_first < lop->lo_end && 2168 (new_lop->lo_flags == NFSLCK_WRITE || 2169 lop->lo_flags == NFSLCK_WRITE) && 2170 lckstp != lop->lo_stp && 2171 (clp != lop->lo_stp->ls_clp || 2172 lckstp->ls_ownerlen != lop->lo_stp->ls_ownerlen || 2173 NFSBCMP(lckstp->ls_owner, lop->lo_stp->ls_owner, 2174 lckstp->ls_ownerlen))) { 2175 if (other_lop) { 2176 free(other_lop, M_NFSDLOCK); 2177 other_lop = NULL; 2178 } 2179 if (vnode_unlocked != 0) 2180 ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock, 2181 NULL, p); 2182 else 2183 ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock, 2184 vp, p); 2185 if (ret == 1) { 2186 if (filestruct_locked != 0) { 2187 if (vnode_unlocked == 0) { 2188 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl6"); 2189 NFSVOPUNLOCK(vp, 0); 2190 } 2191 /* Roll back local locks. */ 2192 nfsrv_locallock_rollback(vp, lfp, p); 2193 NFSLOCKSTATE(); 2194 nfsrv_unlocklf(lfp); 2195 NFSUNLOCKSTATE(); 2196 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 2197 vnode_unlocked = 0; 2198 if ((vp->v_iflag & VI_DOOMED) != 0) { 2199 error = NFSERR_SERVERFAULT; 2200 goto out; 2201 } 2202 } 2203 /* 2204 * nfsrv_clientconflict() unlocks state when it 2205 * returns non-zero. 2206 */ 2207 lckstp = NULL; 2208 goto tryagain; 2209 } 2210 /* 2211 * Found a conflicting lock, so record the conflict and 2212 * return the error. 2213 */ 2214 if (cfp != NULL && ret == 0) { 2215 cfp->cl_clientid.lval[0]=lop->lo_stp->ls_stateid.other[0]; 2216 cfp->cl_clientid.lval[1]=lop->lo_stp->ls_stateid.other[1]; 2217 cfp->cl_first = lop->lo_first; 2218 cfp->cl_end = lop->lo_end; 2219 cfp->cl_flags = lop->lo_flags; 2220 cfp->cl_ownerlen = lop->lo_stp->ls_ownerlen; 2221 NFSBCOPY(lop->lo_stp->ls_owner, cfp->cl_owner, 2222 cfp->cl_ownerlen); 2223 } 2224 if (ret == 2) 2225 error = NFSERR_PERM; 2226 else if (new_stp->ls_flags & NFSLCK_RECLAIM) 2227 error = NFSERR_RECLAIMCONFLICT; 2228 else if (new_stp->ls_flags & NFSLCK_CHECK) 2229 error = NFSERR_LOCKED; 2230 else 2231 error = NFSERR_DENIED; 2232 if (filestruct_locked != 0 && ret == 0) { 2233 /* Roll back local locks. */ 2234 NFSUNLOCKSTATE(); 2235 if (vnode_unlocked == 0) { 2236 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl7"); 2237 vnode_unlocked = 1; 2238 NFSVOPUNLOCK(vp, 0); 2239 } 2240 nfsrv_locallock_rollback(vp, lfp, p); 2241 NFSLOCKSTATE(); 2242 nfsrv_unlocklf(lfp); 2243 } 2244 if (ret == 0) 2245 NFSUNLOCKSTATE(); 2246 goto out; 2247 } 2248 } 2249 } 2250 2251 /* 2252 * We only get here if there was no lock that conflicted. 2253 */ 2254 if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) { 2255 NFSUNLOCKSTATE(); 2256 goto out; 2257 } 2258 2259 /* 2260 * We only get here when we are creating or modifying a lock. 2261 * There are two variants: 2262 * - exist_lock_owner where lock_owner exists 2263 * - open_to_lock_owner with new lock_owner 2264 */ 2265 first = new_lop->lo_first; 2266 end = new_lop->lo_end; 2267 lock_flags = new_lop->lo_flags; 2268 if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) { 2269 nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp); 2270 stateidp->seqid = ++(lckstp->ls_stateid.seqid); 2271 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0) 2272 stateidp->seqid = lckstp->ls_stateid.seqid = 1; 2273 stateidp->other[0] = lckstp->ls_stateid.other[0]; 2274 stateidp->other[1] = lckstp->ls_stateid.other[1]; 2275 stateidp->other[2] = lckstp->ls_stateid.other[2]; 2276 } else { 2277 /* 2278 * The new open_to_lock_owner case. 2279 * Link the new nfsstate into the lists. 2280 */ 2281 new_stp->ls_seq = new_stp->ls_opentolockseq; 2282 nfsrvd_refcache(new_stp->ls_op); 2283 stateidp->seqid = new_stp->ls_stateid.seqid = 1; 2284 stateidp->other[0] = new_stp->ls_stateid.other[0] = 2285 clp->lc_clientid.lval[0]; 2286 stateidp->other[1] = new_stp->ls_stateid.other[1] = 2287 clp->lc_clientid.lval[1]; 2288 stateidp->other[2] = new_stp->ls_stateid.other[2] = 2289 nfsrv_nextstateindex(clp); 2290 new_stp->ls_clp = clp; 2291 LIST_INIT(&new_stp->ls_lock); 2292 new_stp->ls_openstp = stp; 2293 new_stp->ls_lfp = lfp; 2294 nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp, 2295 lfp); 2296 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid), 2297 new_stp, ls_hash); 2298 LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list); 2299 *new_lopp = NULL; 2300 *new_stpp = NULL; 2301 nfsstatsv1.srvlockowners++; 2302 nfsrv_openpluslock++; 2303 } 2304 if (filestruct_locked != 0) { 2305 NFSUNLOCKSTATE(); 2306 nfsrv_locallock_commit(lfp, lock_flags, first, end); 2307 NFSLOCKSTATE(); 2308 nfsrv_unlocklf(lfp); 2309 } 2310 NFSUNLOCKSTATE(); 2311 2312 out: 2313 if (haslock) { 2314 NFSLOCKV4ROOTMUTEX(); 2315 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2316 NFSUNLOCKV4ROOTMUTEX(); 2317 } 2318 if (vnode_unlocked != 0) { 2319 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 2320 if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0) 2321 error = NFSERR_SERVERFAULT; 2322 } 2323 if (other_lop) 2324 free(other_lop, M_NFSDLOCK); 2325 NFSEXITCODE2(error, nd); 2326 return (error); 2327 } 2328 2329 /* 2330 * Check for state errors for Open. 2331 * repstat is passed back out as an error if more critical errors 2332 * are not detected. 2333 */ 2334 APPLESTATIC int 2335 nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp, 2336 struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd, 2337 NFSPROC_T *p, int repstat) 2338 { 2339 struct nfsstate *stp, *nstp; 2340 struct nfsclient *clp; 2341 struct nfsstate *ownerstp; 2342 struct nfslockfile *lfp, *new_lfp; 2343 int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0; 2344 2345 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 2346 readonly = 1; 2347 /* 2348 * Check for restart conditions (client and server). 2349 */ 2350 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2351 &new_stp->ls_stateid, 0); 2352 if (error) 2353 goto out; 2354 2355 /* 2356 * Check for state resource limit exceeded. 2357 * Technically this should be SMP protected, but the worst 2358 * case error is "out by one or two" on the count when it 2359 * returns NFSERR_RESOURCE and the limit is just a rather 2360 * arbitrary high water mark, so no harm is done. 2361 */ 2362 if (nfsrv_openpluslock > nfsrv_v4statelimit) { 2363 error = NFSERR_RESOURCE; 2364 goto out; 2365 } 2366 2367 tryagain: 2368 new_lfp = malloc(sizeof (struct nfslockfile), 2369 M_NFSDLOCKFILE, M_WAITOK); 2370 if (vp) 2371 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp, 2372 NULL, p); 2373 NFSLOCKSTATE(); 2374 /* 2375 * Get the nfsclient structure. 2376 */ 2377 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 2378 (nfsquad_t)((u_quad_t)0), 0, nd, p); 2379 2380 /* 2381 * Look up the open owner. See if it needs confirmation and 2382 * check the seq#, as required. 2383 */ 2384 if (!error) 2385 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp); 2386 2387 if (!error && ownerstp) { 2388 error = nfsrv_checkseqid(nd, new_stp->ls_seq, ownerstp, 2389 new_stp->ls_op); 2390 /* 2391 * If the OpenOwner hasn't been confirmed, assume the 2392 * old one was a replay and this one is ok. 2393 * See: RFC3530 Sec. 14.2.18. 2394 */ 2395 if (error == NFSERR_BADSEQID && 2396 (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM)) 2397 error = 0; 2398 } 2399 2400 /* 2401 * Check for grace. 2402 */ 2403 if (!error) 2404 error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags); 2405 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error && 2406 nfsrv_checkstable(clp)) 2407 error = NFSERR_NOGRACE; 2408 2409 /* 2410 * If none of the above errors occurred, let repstat be 2411 * returned. 2412 */ 2413 if (repstat && !error) 2414 error = repstat; 2415 if (error) { 2416 NFSUNLOCKSTATE(); 2417 if (haslock) { 2418 NFSLOCKV4ROOTMUTEX(); 2419 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2420 NFSUNLOCKV4ROOTMUTEX(); 2421 } 2422 free(new_lfp, M_NFSDLOCKFILE); 2423 goto out; 2424 } 2425 2426 /* 2427 * If vp == NULL, the file doesn't exist yet, so return ok. 2428 * (This always happens on the first pass, so haslock must be 0.) 2429 */ 2430 if (vp == NULL) { 2431 NFSUNLOCKSTATE(); 2432 free(new_lfp, M_NFSDLOCKFILE); 2433 goto out; 2434 } 2435 2436 /* 2437 * Get the structure for the underlying file. 2438 */ 2439 if (getfhret) 2440 error = getfhret; 2441 else 2442 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, 2443 NULL, 0); 2444 if (new_lfp) 2445 free(new_lfp, M_NFSDLOCKFILE); 2446 if (error) { 2447 NFSUNLOCKSTATE(); 2448 if (haslock) { 2449 NFSLOCKV4ROOTMUTEX(); 2450 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2451 NFSUNLOCKV4ROOTMUTEX(); 2452 } 2453 goto out; 2454 } 2455 2456 /* 2457 * Search for a conflicting open/share. 2458 */ 2459 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2460 /* 2461 * For Delegate_Cur, search for the matching Delegation, 2462 * which indicates no conflict. 2463 * An old delegation should have been recovered by the 2464 * client doing a Claim_DELEGATE_Prev, so I won't let 2465 * it match and return NFSERR_EXPIRED. Should I let it 2466 * match? 2467 */ 2468 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2469 if (!(stp->ls_flags & NFSLCK_OLDDELEG) && 2470 (((nd->nd_flag & ND_NFSV41) != 0 && 2471 stateidp->seqid == 0) || 2472 stateidp->seqid == stp->ls_stateid.seqid) && 2473 !NFSBCMP(stateidp->other, stp->ls_stateid.other, 2474 NFSX_STATEIDOTHER)) 2475 break; 2476 } 2477 if (stp == LIST_END(&lfp->lf_deleg) || 2478 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) && 2479 (stp->ls_flags & NFSLCK_DELEGREAD))) { 2480 NFSUNLOCKSTATE(); 2481 if (haslock) { 2482 NFSLOCKV4ROOTMUTEX(); 2483 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2484 NFSUNLOCKV4ROOTMUTEX(); 2485 } 2486 error = NFSERR_EXPIRED; 2487 goto out; 2488 } 2489 } 2490 2491 /* 2492 * Check for access/deny bit conflicts. I check for the same 2493 * owner as well, in case the client didn't bother. 2494 */ 2495 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 2496 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR) && 2497 (((new_stp->ls_flags & NFSLCK_ACCESSBITS) & 2498 ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))|| 2499 ((stp->ls_flags & NFSLCK_ACCESSBITS) & 2500 ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS)))){ 2501 ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p); 2502 if (ret == 1) { 2503 /* 2504 * nfsrv_clientconflict() unlocks 2505 * state when it returns non-zero. 2506 */ 2507 goto tryagain; 2508 } 2509 if (ret == 2) 2510 error = NFSERR_PERM; 2511 else if (new_stp->ls_flags & NFSLCK_RECLAIM) 2512 error = NFSERR_RECLAIMCONFLICT; 2513 else 2514 error = NFSERR_SHAREDENIED; 2515 if (ret == 0) 2516 NFSUNLOCKSTATE(); 2517 if (haslock) { 2518 NFSLOCKV4ROOTMUTEX(); 2519 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2520 NFSUNLOCKV4ROOTMUTEX(); 2521 } 2522 goto out; 2523 } 2524 } 2525 2526 /* 2527 * Check for a conflicting delegation. If one is found, call 2528 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2529 * been set yet, it will get the lock. Otherwise, it will recall 2530 * the delegation. Then, we try try again... 2531 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there 2532 * isn't a conflict.) 2533 * I currently believe the conflict algorithm to be: 2534 * For Open with Read Access and Deny None 2535 * - there is a conflict iff a different client has a write delegation 2536 * For Open with other Write Access or any Deny except None 2537 * - there is a conflict if a different client has any delegation 2538 * - there is a conflict if the same client has a read delegation 2539 * (The current consensus is that this last case should be 2540 * considered a conflict since the client with a read delegation 2541 * could have done an Open with ReadAccess and WriteDeny 2542 * locally and then not have checked for the WriteDeny.) 2543 * Don't check for a Reclaim, since that will be dealt with 2544 * by nfsrv_openctrl(). 2545 */ 2546 if (!(new_stp->ls_flags & 2547 (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR | NFSLCK_RECLAIM))) { 2548 stp = LIST_FIRST(&lfp->lf_deleg); 2549 while (stp != LIST_END(&lfp->lf_deleg)) { 2550 nstp = LIST_NEXT(stp, ls_file); 2551 if ((readonly && stp->ls_clp != clp && 2552 (stp->ls_flags & NFSLCK_DELEGWRITE)) || 2553 (!readonly && (stp->ls_clp != clp || 2554 (stp->ls_flags & NFSLCK_DELEGREAD)))) { 2555 ret = nfsrv_delegconflict(stp, &haslock, p, vp); 2556 if (ret) { 2557 /* 2558 * nfsrv_delegconflict() unlocks state 2559 * when it returns non-zero. 2560 */ 2561 if (ret == -1) 2562 goto tryagain; 2563 error = ret; 2564 goto out; 2565 } 2566 } 2567 stp = nstp; 2568 } 2569 } 2570 NFSUNLOCKSTATE(); 2571 if (haslock) { 2572 NFSLOCKV4ROOTMUTEX(); 2573 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2574 NFSUNLOCKV4ROOTMUTEX(); 2575 } 2576 2577 out: 2578 NFSEXITCODE2(error, nd); 2579 return (error); 2580 } 2581 2582 /* 2583 * Open control function to create/update open state for an open. 2584 */ 2585 APPLESTATIC int 2586 nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp, 2587 struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp, 2588 nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp, 2589 NFSPROC_T *p, u_quad_t filerev) 2590 { 2591 struct nfsstate *new_stp = *new_stpp; 2592 struct nfsstate *stp, *nstp; 2593 struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg; 2594 struct nfslockfile *lfp, *new_lfp; 2595 struct nfsclient *clp; 2596 int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1; 2597 int readonly = 0, cbret = 1, getfhret = 0; 2598 int gotstate = 0, len = 0; 2599 u_char *clidp = NULL; 2600 2601 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 2602 readonly = 1; 2603 /* 2604 * Check for restart conditions (client and server). 2605 * (Paranoia, should have been detected by nfsrv_opencheck().) 2606 * If an error does show up, return NFSERR_EXPIRED, since the 2607 * the seqid# has already been incremented. 2608 */ 2609 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2610 &new_stp->ls_stateid, 0); 2611 if (error) { 2612 printf("Nfsd: openctrl unexpected restart err=%d\n", 2613 error); 2614 error = NFSERR_EXPIRED; 2615 goto out; 2616 } 2617 2618 clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK); 2619 tryagain: 2620 new_lfp = malloc(sizeof (struct nfslockfile), 2621 M_NFSDLOCKFILE, M_WAITOK); 2622 new_open = malloc(sizeof (struct nfsstate), 2623 M_NFSDSTATE, M_WAITOK); 2624 new_deleg = malloc(sizeof (struct nfsstate), 2625 M_NFSDSTATE, M_WAITOK); 2626 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp, 2627 NULL, p); 2628 NFSLOCKSTATE(); 2629 /* 2630 * Get the client structure. Since the linked lists could be changed 2631 * by other nfsd processes if this process does a tsleep(), one of 2632 * two things must be done. 2633 * 1 - don't tsleep() 2634 * or 2635 * 2 - get the nfsv4_lock() { indicated by haslock == 1 } 2636 * before using the lists, since this lock stops the other 2637 * nfsd. This should only be used for rare cases, since it 2638 * essentially single threads the nfsd. 2639 * At this time, it is only done for cases where the stable 2640 * storage file must be written prior to completion of state 2641 * expiration. 2642 */ 2643 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 2644 (nfsquad_t)((u_quad_t)0), 0, nd, p); 2645 if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) && 2646 clp->lc_program) { 2647 /* 2648 * This happens on the first open for a client 2649 * that supports callbacks. 2650 */ 2651 NFSUNLOCKSTATE(); 2652 /* 2653 * Although nfsrv_docallback() will sleep, clp won't 2654 * go away, since they are only removed when the 2655 * nfsv4_lock() has blocked the nfsd threads. The 2656 * fields in clp can change, but having multiple 2657 * threads do this Null callback RPC should be 2658 * harmless. 2659 */ 2660 cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL, 2661 NULL, 0, NULL, NULL, NULL, 0, p); 2662 NFSLOCKSTATE(); 2663 clp->lc_flags &= ~LCL_NEEDSCBNULL; 2664 if (!cbret) 2665 clp->lc_flags |= LCL_CALLBACKSON; 2666 } 2667 2668 /* 2669 * Look up the open owner. See if it needs confirmation and 2670 * check the seq#, as required. 2671 */ 2672 if (!error) 2673 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp); 2674 2675 if (error) { 2676 NFSUNLOCKSTATE(); 2677 printf("Nfsd: openctrl unexpected state err=%d\n", 2678 error); 2679 free(new_lfp, M_NFSDLOCKFILE); 2680 free(new_open, M_NFSDSTATE); 2681 free(new_deleg, M_NFSDSTATE); 2682 if (haslock) { 2683 NFSLOCKV4ROOTMUTEX(); 2684 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2685 NFSUNLOCKV4ROOTMUTEX(); 2686 } 2687 error = NFSERR_EXPIRED; 2688 goto out; 2689 } 2690 2691 if (new_stp->ls_flags & NFSLCK_RECLAIM) 2692 nfsrv_markstable(clp); 2693 2694 /* 2695 * Get the structure for the underlying file. 2696 */ 2697 if (getfhret) 2698 error = getfhret; 2699 else 2700 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, 2701 NULL, 0); 2702 if (new_lfp) 2703 free(new_lfp, M_NFSDLOCKFILE); 2704 if (error) { 2705 NFSUNLOCKSTATE(); 2706 printf("Nfsd openctrl unexpected getlockfile err=%d\n", 2707 error); 2708 free(new_open, M_NFSDSTATE); 2709 free(new_deleg, M_NFSDSTATE); 2710 if (haslock) { 2711 NFSLOCKV4ROOTMUTEX(); 2712 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2713 NFSUNLOCKV4ROOTMUTEX(); 2714 } 2715 goto out; 2716 } 2717 2718 /* 2719 * Search for a conflicting open/share. 2720 */ 2721 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2722 /* 2723 * For Delegate_Cur, search for the matching Delegation, 2724 * which indicates no conflict. 2725 * An old delegation should have been recovered by the 2726 * client doing a Claim_DELEGATE_Prev, so I won't let 2727 * it match and return NFSERR_EXPIRED. Should I let it 2728 * match? 2729 */ 2730 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2731 if (!(stp->ls_flags & NFSLCK_OLDDELEG) && 2732 (((nd->nd_flag & ND_NFSV41) != 0 && 2733 stateidp->seqid == 0) || 2734 stateidp->seqid == stp->ls_stateid.seqid) && 2735 !NFSBCMP(stateidp->other, stp->ls_stateid.other, 2736 NFSX_STATEIDOTHER)) 2737 break; 2738 } 2739 if (stp == LIST_END(&lfp->lf_deleg) || 2740 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) && 2741 (stp->ls_flags & NFSLCK_DELEGREAD))) { 2742 NFSUNLOCKSTATE(); 2743 printf("Nfsd openctrl unexpected expiry\n"); 2744 free(new_open, M_NFSDSTATE); 2745 free(new_deleg, M_NFSDSTATE); 2746 if (haslock) { 2747 NFSLOCKV4ROOTMUTEX(); 2748 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2749 NFSUNLOCKV4ROOTMUTEX(); 2750 } 2751 error = NFSERR_EXPIRED; 2752 goto out; 2753 } 2754 2755 /* 2756 * Don't issue a Delegation, since one already exists and 2757 * delay delegation timeout, as required. 2758 */ 2759 delegate = 0; 2760 nfsrv_delaydelegtimeout(stp); 2761 } 2762 2763 /* 2764 * Check for access/deny bit conflicts. I also check for the 2765 * same owner, since the client might not have bothered to check. 2766 * Also, note an open for the same file and owner, if found, 2767 * which is all we do here for Delegate_Cur, since conflict 2768 * checking is already done. 2769 */ 2770 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 2771 if (ownerstp && stp->ls_openowner == ownerstp) 2772 openstp = stp; 2773 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) { 2774 /* 2775 * If another client has the file open, the only 2776 * delegation that can be issued is a Read delegation 2777 * and only if it is a Read open with Deny none. 2778 */ 2779 if (clp != stp->ls_clp) { 2780 if ((stp->ls_flags & NFSLCK_SHAREBITS) == 2781 NFSLCK_READACCESS) 2782 writedeleg = 0; 2783 else 2784 delegate = 0; 2785 } 2786 if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) & 2787 ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))|| 2788 ((stp->ls_flags & NFSLCK_ACCESSBITS) & 2789 ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){ 2790 ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p); 2791 if (ret == 1) { 2792 /* 2793 * nfsrv_clientconflict() unlocks state 2794 * when it returns non-zero. 2795 */ 2796 free(new_open, M_NFSDSTATE); 2797 free(new_deleg, M_NFSDSTATE); 2798 openstp = NULL; 2799 goto tryagain; 2800 } 2801 if (ret == 2) 2802 error = NFSERR_PERM; 2803 else if (new_stp->ls_flags & NFSLCK_RECLAIM) 2804 error = NFSERR_RECLAIMCONFLICT; 2805 else 2806 error = NFSERR_SHAREDENIED; 2807 if (ret == 0) 2808 NFSUNLOCKSTATE(); 2809 if (haslock) { 2810 NFSLOCKV4ROOTMUTEX(); 2811 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2812 NFSUNLOCKV4ROOTMUTEX(); 2813 } 2814 free(new_open, M_NFSDSTATE); 2815 free(new_deleg, M_NFSDSTATE); 2816 printf("nfsd openctrl unexpected client cnfl\n"); 2817 goto out; 2818 } 2819 } 2820 } 2821 2822 /* 2823 * Check for a conflicting delegation. If one is found, call 2824 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2825 * been set yet, it will get the lock. Otherwise, it will recall 2826 * the delegation. Then, we try try again... 2827 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there 2828 * isn't a conflict.) 2829 * I currently believe the conflict algorithm to be: 2830 * For Open with Read Access and Deny None 2831 * - there is a conflict iff a different client has a write delegation 2832 * For Open with other Write Access or any Deny except None 2833 * - there is a conflict if a different client has any delegation 2834 * - there is a conflict if the same client has a read delegation 2835 * (The current consensus is that this last case should be 2836 * considered a conflict since the client with a read delegation 2837 * could have done an Open with ReadAccess and WriteDeny 2838 * locally and then not have checked for the WriteDeny.) 2839 */ 2840 if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) { 2841 stp = LIST_FIRST(&lfp->lf_deleg); 2842 while (stp != LIST_END(&lfp->lf_deleg)) { 2843 nstp = LIST_NEXT(stp, ls_file); 2844 if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD)) 2845 writedeleg = 0; 2846 else 2847 delegate = 0; 2848 if ((readonly && stp->ls_clp != clp && 2849 (stp->ls_flags & NFSLCK_DELEGWRITE)) || 2850 (!readonly && (stp->ls_clp != clp || 2851 (stp->ls_flags & NFSLCK_DELEGREAD)))) { 2852 if (new_stp->ls_flags & NFSLCK_RECLAIM) { 2853 delegate = 2; 2854 } else { 2855 ret = nfsrv_delegconflict(stp, &haslock, p, vp); 2856 if (ret) { 2857 /* 2858 * nfsrv_delegconflict() unlocks state 2859 * when it returns non-zero. 2860 */ 2861 printf("Nfsd openctrl unexpected deleg cnfl\n"); 2862 free(new_open, M_NFSDSTATE); 2863 free(new_deleg, M_NFSDSTATE); 2864 if (ret == -1) { 2865 openstp = NULL; 2866 goto tryagain; 2867 } 2868 error = ret; 2869 goto out; 2870 } 2871 } 2872 } 2873 stp = nstp; 2874 } 2875 } 2876 2877 /* 2878 * We only get here if there was no open that conflicted. 2879 * If an open for the owner exists, or in the access/deny bits. 2880 * Otherwise it is a new open. If the open_owner hasn't been 2881 * confirmed, replace the open with the new one needing confirmation, 2882 * otherwise add the open. 2883 */ 2884 if (new_stp->ls_flags & NFSLCK_DELEGPREV) { 2885 /* 2886 * Handle NFSLCK_DELEGPREV by searching the old delegations for 2887 * a match. If found, just move the old delegation to the current 2888 * delegation list and issue open. If not found, return 2889 * NFSERR_EXPIRED. 2890 */ 2891 LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) { 2892 if (stp->ls_lfp == lfp) { 2893 /* Found it */ 2894 if (stp->ls_clp != clp) 2895 panic("olddeleg clp"); 2896 LIST_REMOVE(stp, ls_list); 2897 LIST_REMOVE(stp, ls_hash); 2898 stp->ls_flags &= ~NFSLCK_OLDDELEG; 2899 stp->ls_stateid.seqid = delegstateidp->seqid = 1; 2900 stp->ls_stateid.other[0] = delegstateidp->other[0] = 2901 clp->lc_clientid.lval[0]; 2902 stp->ls_stateid.other[1] = delegstateidp->other[1] = 2903 clp->lc_clientid.lval[1]; 2904 stp->ls_stateid.other[2] = delegstateidp->other[2] = 2905 nfsrv_nextstateindex(clp); 2906 stp->ls_compref = nd->nd_compref; 2907 LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list); 2908 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2909 stp->ls_stateid), stp, ls_hash); 2910 if (stp->ls_flags & NFSLCK_DELEGWRITE) 2911 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2912 else 2913 *rflagsp |= NFSV4OPEN_READDELEGATE; 2914 clp->lc_delegtime = NFSD_MONOSEC + 2915 nfsrv_lease + NFSRV_LEASEDELTA; 2916 2917 /* 2918 * Now, do the associated open. 2919 */ 2920 new_open->ls_stateid.seqid = 1; 2921 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2922 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2923 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2924 new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)| 2925 NFSLCK_OPEN; 2926 if (stp->ls_flags & NFSLCK_DELEGWRITE) 2927 new_open->ls_flags |= (NFSLCK_READACCESS | 2928 NFSLCK_WRITEACCESS); 2929 else 2930 new_open->ls_flags |= NFSLCK_READACCESS; 2931 new_open->ls_uid = new_stp->ls_uid; 2932 new_open->ls_lfp = lfp; 2933 new_open->ls_clp = clp; 2934 LIST_INIT(&new_open->ls_open); 2935 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2936 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2937 new_open, ls_hash); 2938 /* 2939 * and handle the open owner 2940 */ 2941 if (ownerstp) { 2942 new_open->ls_openowner = ownerstp; 2943 LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list); 2944 } else { 2945 new_open->ls_openowner = new_stp; 2946 new_stp->ls_flags = 0; 2947 nfsrvd_refcache(new_stp->ls_op); 2948 new_stp->ls_noopens = 0; 2949 LIST_INIT(&new_stp->ls_open); 2950 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 2951 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 2952 *new_stpp = NULL; 2953 nfsstatsv1.srvopenowners++; 2954 nfsrv_openpluslock++; 2955 } 2956 openstp = new_open; 2957 new_open = NULL; 2958 nfsstatsv1.srvopens++; 2959 nfsrv_openpluslock++; 2960 break; 2961 } 2962 } 2963 if (stp == LIST_END(&clp->lc_olddeleg)) 2964 error = NFSERR_EXPIRED; 2965 } else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { 2966 /* 2967 * Scan to see that no delegation for this client and file 2968 * doesn't already exist. 2969 * There also shouldn't yet be an Open for this file and 2970 * openowner. 2971 */ 2972 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2973 if (stp->ls_clp == clp) 2974 break; 2975 } 2976 if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) { 2977 /* 2978 * This is the Claim_Previous case with a delegation 2979 * type != Delegate_None. 2980 */ 2981 /* 2982 * First, add the delegation. (Although we must issue the 2983 * delegation, we can also ask for an immediate return.) 2984 */ 2985 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 2986 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] = 2987 clp->lc_clientid.lval[0]; 2988 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] = 2989 clp->lc_clientid.lval[1]; 2990 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] = 2991 nfsrv_nextstateindex(clp); 2992 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) { 2993 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 2994 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 2995 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2996 nfsrv_writedelegcnt++; 2997 } else { 2998 new_deleg->ls_flags = (NFSLCK_DELEGREAD | 2999 NFSLCK_READACCESS); 3000 *rflagsp |= NFSV4OPEN_READDELEGATE; 3001 } 3002 new_deleg->ls_uid = new_stp->ls_uid; 3003 new_deleg->ls_lfp = lfp; 3004 new_deleg->ls_clp = clp; 3005 new_deleg->ls_filerev = filerev; 3006 new_deleg->ls_compref = nd->nd_compref; 3007 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 3008 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3009 new_deleg->ls_stateid), new_deleg, ls_hash); 3010 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 3011 new_deleg = NULL; 3012 if (delegate == 2 || nfsrv_issuedelegs == 0 || 3013 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 3014 LCL_CALLBACKSON || 3015 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) || 3016 !NFSVNO_DELEGOK(vp)) 3017 *rflagsp |= NFSV4OPEN_RECALL; 3018 nfsstatsv1.srvdelegates++; 3019 nfsrv_openpluslock++; 3020 nfsrv_delegatecnt++; 3021 3022 /* 3023 * Now, do the associated open. 3024 */ 3025 new_open->ls_stateid.seqid = 1; 3026 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 3027 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 3028 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 3029 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) | 3030 NFSLCK_OPEN; 3031 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) 3032 new_open->ls_flags |= (NFSLCK_READACCESS | 3033 NFSLCK_WRITEACCESS); 3034 else 3035 new_open->ls_flags |= NFSLCK_READACCESS; 3036 new_open->ls_uid = new_stp->ls_uid; 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(NFSSTATEHASH(clp, new_open->ls_stateid), 3042 new_open, ls_hash); 3043 /* 3044 * and handle the open owner 3045 */ 3046 if (ownerstp) { 3047 new_open->ls_openowner = ownerstp; 3048 LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); 3049 } else { 3050 new_open->ls_openowner = new_stp; 3051 new_stp->ls_flags = 0; 3052 nfsrvd_refcache(new_stp->ls_op); 3053 new_stp->ls_noopens = 0; 3054 LIST_INIT(&new_stp->ls_open); 3055 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 3056 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 3057 *new_stpp = NULL; 3058 nfsstatsv1.srvopenowners++; 3059 nfsrv_openpluslock++; 3060 } 3061 openstp = new_open; 3062 new_open = NULL; 3063 nfsstatsv1.srvopens++; 3064 nfsrv_openpluslock++; 3065 } else { 3066 error = NFSERR_RECLAIMCONFLICT; 3067 } 3068 } else if (ownerstp) { 3069 if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) { 3070 /* Replace the open */ 3071 if (ownerstp->ls_op) 3072 nfsrvd_derefcache(ownerstp->ls_op); 3073 ownerstp->ls_op = new_stp->ls_op; 3074 nfsrvd_refcache(ownerstp->ls_op); 3075 ownerstp->ls_seq = new_stp->ls_seq; 3076 *rflagsp |= NFSV4OPEN_RESULTCONFIRM; 3077 stp = LIST_FIRST(&ownerstp->ls_open); 3078 stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) | 3079 NFSLCK_OPEN; 3080 stp->ls_stateid.seqid = 1; 3081 stp->ls_uid = new_stp->ls_uid; 3082 if (lfp != stp->ls_lfp) { 3083 LIST_REMOVE(stp, ls_file); 3084 LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file); 3085 stp->ls_lfp = lfp; 3086 } 3087 openstp = stp; 3088 } else if (openstp) { 3089 openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS); 3090 openstp->ls_stateid.seqid++; 3091 if ((nd->nd_flag & ND_NFSV41) != 0 && 3092 openstp->ls_stateid.seqid == 0) 3093 openstp->ls_stateid.seqid = 1; 3094 3095 /* 3096 * This is where we can choose to issue a delegation. 3097 */ 3098 if (delegate == 0 || writedeleg == 0 || 3099 NFSVNO_EXRDONLY(exp) || (readonly != 0 && 3100 nfsrv_writedelegifpos == 0) || 3101 !NFSVNO_DELEGOK(vp) || 3102 (new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 || 3103 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 3104 LCL_CALLBACKSON) 3105 *rflagsp |= NFSV4OPEN_WDCONTENTION; 3106 else if (nfsrv_issuedelegs == 0 || 3107 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt)) 3108 *rflagsp |= NFSV4OPEN_WDRESOURCE; 3109 else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0) 3110 *rflagsp |= NFSV4OPEN_WDNOTWANTED; 3111 else { 3112 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 3113 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] 3114 = clp->lc_clientid.lval[0]; 3115 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] 3116 = clp->lc_clientid.lval[1]; 3117 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] 3118 = nfsrv_nextstateindex(clp); 3119 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 3120 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 3121 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3122 new_deleg->ls_uid = new_stp->ls_uid; 3123 new_deleg->ls_lfp = lfp; 3124 new_deleg->ls_clp = clp; 3125 new_deleg->ls_filerev = filerev; 3126 new_deleg->ls_compref = nd->nd_compref; 3127 nfsrv_writedelegcnt++; 3128 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 3129 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3130 new_deleg->ls_stateid), new_deleg, ls_hash); 3131 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 3132 new_deleg = NULL; 3133 nfsstatsv1.srvdelegates++; 3134 nfsrv_openpluslock++; 3135 nfsrv_delegatecnt++; 3136 } 3137 } else { 3138 new_open->ls_stateid.seqid = 1; 3139 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 3140 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 3141 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 3142 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)| 3143 NFSLCK_OPEN; 3144 new_open->ls_uid = new_stp->ls_uid; 3145 new_open->ls_openowner = ownerstp; 3146 new_open->ls_lfp = lfp; 3147 new_open->ls_clp = clp; 3148 LIST_INIT(&new_open->ls_open); 3149 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 3150 LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); 3151 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 3152 new_open, ls_hash); 3153 openstp = new_open; 3154 new_open = NULL; 3155 nfsstatsv1.srvopens++; 3156 nfsrv_openpluslock++; 3157 3158 /* 3159 * This is where we can choose to issue a delegation. 3160 */ 3161 if (delegate == 0 || (writedeleg == 0 && readonly == 0) || 3162 !NFSVNO_DELEGOK(vp) || 3163 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 3164 LCL_CALLBACKSON) 3165 *rflagsp |= NFSV4OPEN_WDCONTENTION; 3166 else if (nfsrv_issuedelegs == 0 || 3167 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt)) 3168 *rflagsp |= NFSV4OPEN_WDRESOURCE; 3169 else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0) 3170 *rflagsp |= NFSV4OPEN_WDNOTWANTED; 3171 else { 3172 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1; 3173 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] 3174 = clp->lc_clientid.lval[0]; 3175 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] 3176 = clp->lc_clientid.lval[1]; 3177 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] 3178 = nfsrv_nextstateindex(clp); 3179 if (writedeleg && !NFSVNO_EXRDONLY(exp) && 3180 (nfsrv_writedelegifpos || !readonly) && 3181 (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) { 3182 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 3183 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 3184 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3185 nfsrv_writedelegcnt++; 3186 } else { 3187 new_deleg->ls_flags = (NFSLCK_DELEGREAD | 3188 NFSLCK_READACCESS); 3189 *rflagsp |= NFSV4OPEN_READDELEGATE; 3190 } 3191 new_deleg->ls_uid = new_stp->ls_uid; 3192 new_deleg->ls_lfp = lfp; 3193 new_deleg->ls_clp = clp; 3194 new_deleg->ls_filerev = filerev; 3195 new_deleg->ls_compref = nd->nd_compref; 3196 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 3197 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3198 new_deleg->ls_stateid), new_deleg, ls_hash); 3199 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 3200 new_deleg = NULL; 3201 nfsstatsv1.srvdelegates++; 3202 nfsrv_openpluslock++; 3203 nfsrv_delegatecnt++; 3204 } 3205 } 3206 } else { 3207 /* 3208 * New owner case. Start the open_owner sequence with a 3209 * Needs confirmation (unless a reclaim) and hang the 3210 * new open off it. 3211 */ 3212 new_open->ls_stateid.seqid = 1; 3213 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 3214 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 3215 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 3216 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) | 3217 NFSLCK_OPEN; 3218 new_open->ls_uid = new_stp->ls_uid; 3219 LIST_INIT(&new_open->ls_open); 3220 new_open->ls_openowner = new_stp; 3221 new_open->ls_lfp = lfp; 3222 new_open->ls_clp = clp; 3223 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 3224 if (new_stp->ls_flags & NFSLCK_RECLAIM) { 3225 new_stp->ls_flags = 0; 3226 } else if ((nd->nd_flag & ND_NFSV41) != 0) { 3227 /* NFSv4.1 never needs confirmation. */ 3228 new_stp->ls_flags = 0; 3229 3230 /* 3231 * This is where we can choose to issue a delegation. 3232 */ 3233 if (delegate && nfsrv_issuedelegs && 3234 (writedeleg || readonly) && 3235 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) == 3236 LCL_CALLBACKSON && 3237 !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) && 3238 NFSVNO_DELEGOK(vp) && 3239 ((nd->nd_flag & ND_NFSV41) == 0 || 3240 (new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) { 3241 new_deleg->ls_stateid.seqid = 3242 delegstateidp->seqid = 1; 3243 new_deleg->ls_stateid.other[0] = 3244 delegstateidp->other[0] 3245 = clp->lc_clientid.lval[0]; 3246 new_deleg->ls_stateid.other[1] = 3247 delegstateidp->other[1] 3248 = clp->lc_clientid.lval[1]; 3249 new_deleg->ls_stateid.other[2] = 3250 delegstateidp->other[2] 3251 = nfsrv_nextstateindex(clp); 3252 if (writedeleg && !NFSVNO_EXRDONLY(exp) && 3253 (nfsrv_writedelegifpos || !readonly) && 3254 ((nd->nd_flag & ND_NFSV41) == 0 || 3255 (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 3256 0)) { 3257 new_deleg->ls_flags = 3258 (NFSLCK_DELEGWRITE | 3259 NFSLCK_READACCESS | 3260 NFSLCK_WRITEACCESS); 3261 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 3262 nfsrv_writedelegcnt++; 3263 } else { 3264 new_deleg->ls_flags = 3265 (NFSLCK_DELEGREAD | 3266 NFSLCK_READACCESS); 3267 *rflagsp |= NFSV4OPEN_READDELEGATE; 3268 } 3269 new_deleg->ls_uid = new_stp->ls_uid; 3270 new_deleg->ls_lfp = lfp; 3271 new_deleg->ls_clp = clp; 3272 new_deleg->ls_filerev = filerev; 3273 new_deleg->ls_compref = nd->nd_compref; 3274 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, 3275 ls_file); 3276 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 3277 new_deleg->ls_stateid), new_deleg, ls_hash); 3278 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, 3279 ls_list); 3280 new_deleg = NULL; 3281 nfsstatsv1.srvdelegates++; 3282 nfsrv_openpluslock++; 3283 nfsrv_delegatecnt++; 3284 } 3285 /* 3286 * Since NFSv4.1 never does an OpenConfirm, the first 3287 * open state will be acquired here. 3288 */ 3289 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { 3290 clp->lc_flags |= LCL_STAMPEDSTABLE; 3291 len = clp->lc_idlen; 3292 NFSBCOPY(clp->lc_id, clidp, len); 3293 gotstate = 1; 3294 } 3295 } else { 3296 *rflagsp |= NFSV4OPEN_RESULTCONFIRM; 3297 new_stp->ls_flags = NFSLCK_NEEDSCONFIRM; 3298 } 3299 nfsrvd_refcache(new_stp->ls_op); 3300 new_stp->ls_noopens = 0; 3301 LIST_INIT(&new_stp->ls_open); 3302 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 3303 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 3304 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 3305 new_open, ls_hash); 3306 openstp = new_open; 3307 new_open = NULL; 3308 *new_stpp = NULL; 3309 nfsstatsv1.srvopens++; 3310 nfsrv_openpluslock++; 3311 nfsstatsv1.srvopenowners++; 3312 nfsrv_openpluslock++; 3313 } 3314 if (!error) { 3315 stateidp->seqid = openstp->ls_stateid.seqid; 3316 stateidp->other[0] = openstp->ls_stateid.other[0]; 3317 stateidp->other[1] = openstp->ls_stateid.other[1]; 3318 stateidp->other[2] = openstp->ls_stateid.other[2]; 3319 } 3320 NFSUNLOCKSTATE(); 3321 if (haslock) { 3322 NFSLOCKV4ROOTMUTEX(); 3323 nfsv4_unlock(&nfsv4rootfs_lock, 1); 3324 NFSUNLOCKV4ROOTMUTEX(); 3325 } 3326 if (new_open) 3327 free(new_open, M_NFSDSTATE); 3328 if (new_deleg) 3329 free(new_deleg, M_NFSDSTATE); 3330 3331 /* 3332 * If the NFSv4.1 client just acquired its first open, write a timestamp 3333 * to the stable storage file. 3334 */ 3335 if (gotstate != 0) { 3336 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p); 3337 nfsrv_backupstable(); 3338 } 3339 3340 out: 3341 free(clidp, M_TEMP); 3342 NFSEXITCODE2(error, nd); 3343 return (error); 3344 } 3345 3346 /* 3347 * Open update. Does the confirm, downgrade and close. 3348 */ 3349 APPLESTATIC int 3350 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid, 3351 nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p, 3352 int *retwriteaccessp) 3353 { 3354 struct nfsstate *stp; 3355 struct nfsclient *clp; 3356 struct nfslockfile *lfp; 3357 u_int32_t bits; 3358 int error = 0, gotstate = 0, len = 0; 3359 u_char *clidp = NULL; 3360 3361 /* 3362 * Check for restart conditions (client and server). 3363 */ 3364 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 3365 &new_stp->ls_stateid, 0); 3366 if (error) 3367 goto out; 3368 3369 clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK); 3370 NFSLOCKSTATE(); 3371 /* 3372 * Get the open structure via clientid and stateid. 3373 */ 3374 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3375 (nfsquad_t)((u_quad_t)0), 0, nd, p); 3376 if (!error) 3377 error = nfsrv_getstate(clp, &new_stp->ls_stateid, 3378 new_stp->ls_flags, &stp); 3379 3380 /* 3381 * Sanity check the open. 3382 */ 3383 if (!error && (!(stp->ls_flags & NFSLCK_OPEN) || 3384 (!(new_stp->ls_flags & NFSLCK_CONFIRM) && 3385 (stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) || 3386 ((new_stp->ls_flags & NFSLCK_CONFIRM) && 3387 (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))))) 3388 error = NFSERR_BADSTATEID; 3389 3390 if (!error) 3391 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 3392 stp->ls_openowner, new_stp->ls_op); 3393 if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid && 3394 (((nd->nd_flag & ND_NFSV41) == 0 && 3395 !(new_stp->ls_flags & NFSLCK_CONFIRM)) || 3396 ((nd->nd_flag & ND_NFSV41) != 0 && 3397 new_stp->ls_stateid.seqid != 0))) 3398 error = NFSERR_OLDSTATEID; 3399 if (!error && vnode_vtype(vp) != VREG) { 3400 if (vnode_vtype(vp) == VDIR) 3401 error = NFSERR_ISDIR; 3402 else 3403 error = NFSERR_INVAL; 3404 } 3405 3406 if (error) { 3407 /* 3408 * If a client tries to confirm an Open with a bad 3409 * seqid# and there are no byte range locks or other Opens 3410 * on the openowner, just throw it away, so the next use of the 3411 * openowner will start a fresh seq#. 3412 */ 3413 if (error == NFSERR_BADSEQID && 3414 (new_stp->ls_flags & NFSLCK_CONFIRM) && 3415 nfsrv_nootherstate(stp)) 3416 nfsrv_freeopenowner(stp->ls_openowner, 0, p); 3417 NFSUNLOCKSTATE(); 3418 goto out; 3419 } 3420 3421 /* 3422 * Set the return stateid. 3423 */ 3424 stateidp->seqid = stp->ls_stateid.seqid + 1; 3425 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0) 3426 stateidp->seqid = 1; 3427 stateidp->other[0] = stp->ls_stateid.other[0]; 3428 stateidp->other[1] = stp->ls_stateid.other[1]; 3429 stateidp->other[2] = stp->ls_stateid.other[2]; 3430 /* 3431 * Now, handle the three cases. 3432 */ 3433 if (new_stp->ls_flags & NFSLCK_CONFIRM) { 3434 /* 3435 * If the open doesn't need confirmation, it seems to me that 3436 * there is a client error, but I'll just log it and keep going? 3437 */ 3438 if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) 3439 printf("Nfsv4d: stray open confirm\n"); 3440 stp->ls_openowner->ls_flags = 0; 3441 stp->ls_stateid.seqid++; 3442 if ((nd->nd_flag & ND_NFSV41) != 0 && 3443 stp->ls_stateid.seqid == 0) 3444 stp->ls_stateid.seqid = 1; 3445 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { 3446 clp->lc_flags |= LCL_STAMPEDSTABLE; 3447 len = clp->lc_idlen; 3448 NFSBCOPY(clp->lc_id, clidp, len); 3449 gotstate = 1; 3450 } 3451 NFSUNLOCKSTATE(); 3452 } else if (new_stp->ls_flags & NFSLCK_CLOSE) { 3453 lfp = stp->ls_lfp; 3454 if (retwriteaccessp != NULL) { 3455 if ((stp->ls_flags & NFSLCK_WRITEACCESS) != 0) 3456 *retwriteaccessp = 1; 3457 else 3458 *retwriteaccessp = 0; 3459 } 3460 if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) { 3461 /* Get the lf lock */ 3462 nfsrv_locklf(lfp); 3463 NFSUNLOCKSTATE(); 3464 ASSERT_VOP_ELOCKED(vp, "nfsrv_openupdate"); 3465 NFSVOPUNLOCK(vp, 0); 3466 if (nfsrv_freeopen(stp, vp, 1, p) == 0) { 3467 NFSLOCKSTATE(); 3468 nfsrv_unlocklf(lfp); 3469 NFSUNLOCKSTATE(); 3470 } 3471 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 3472 } else { 3473 (void) nfsrv_freeopen(stp, NULL, 0, p); 3474 NFSUNLOCKSTATE(); 3475 } 3476 } else { 3477 /* 3478 * Update the share bits, making sure that the new set are a 3479 * subset of the old ones. 3480 */ 3481 bits = (new_stp->ls_flags & NFSLCK_SHAREBITS); 3482 if (~(stp->ls_flags) & bits) { 3483 NFSUNLOCKSTATE(); 3484 error = NFSERR_INVAL; 3485 goto out; 3486 } 3487 stp->ls_flags = (bits | NFSLCK_OPEN); 3488 stp->ls_stateid.seqid++; 3489 if ((nd->nd_flag & ND_NFSV41) != 0 && 3490 stp->ls_stateid.seqid == 0) 3491 stp->ls_stateid.seqid = 1; 3492 NFSUNLOCKSTATE(); 3493 } 3494 3495 /* 3496 * If the client just confirmed its first open, write a timestamp 3497 * to the stable storage file. 3498 */ 3499 if (gotstate != 0) { 3500 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p); 3501 nfsrv_backupstable(); 3502 } 3503 3504 out: 3505 free(clidp, M_TEMP); 3506 NFSEXITCODE2(error, nd); 3507 return (error); 3508 } 3509 3510 /* 3511 * Delegation update. Does the purge and return. 3512 */ 3513 APPLESTATIC int 3514 nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid, 3515 nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred, 3516 NFSPROC_T *p, int *retwriteaccessp) 3517 { 3518 struct nfsstate *stp; 3519 struct nfsclient *clp; 3520 int error = 0; 3521 fhandle_t fh; 3522 3523 /* 3524 * Do a sanity check against the file handle for DelegReturn. 3525 */ 3526 if (vp) { 3527 error = nfsvno_getfh(vp, &fh, p); 3528 if (error) 3529 goto out; 3530 } 3531 /* 3532 * Check for restart conditions (client and server). 3533 */ 3534 if (op == NFSV4OP_DELEGRETURN) 3535 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN, 3536 stateidp, 0); 3537 else 3538 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE, 3539 stateidp, 0); 3540 3541 NFSLOCKSTATE(); 3542 /* 3543 * Get the open structure via clientid and stateid. 3544 */ 3545 if (!error) 3546 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3547 (nfsquad_t)((u_quad_t)0), 0, nd, p); 3548 if (error) { 3549 if (error == NFSERR_CBPATHDOWN) 3550 error = 0; 3551 if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN) 3552 error = NFSERR_STALESTATEID; 3553 } 3554 if (!error && op == NFSV4OP_DELEGRETURN) { 3555 error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp); 3556 if (!error && stp->ls_stateid.seqid != stateidp->seqid && 3557 ((nd->nd_flag & ND_NFSV41) == 0 || stateidp->seqid != 0)) 3558 error = NFSERR_OLDSTATEID; 3559 } 3560 /* 3561 * NFSERR_EXPIRED means that the state has gone away, 3562 * so Delegations have been purged. Just return ok. 3563 */ 3564 if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) { 3565 NFSUNLOCKSTATE(); 3566 error = 0; 3567 goto out; 3568 } 3569 if (error) { 3570 NFSUNLOCKSTATE(); 3571 goto out; 3572 } 3573 3574 if (op == NFSV4OP_DELEGRETURN) { 3575 if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh, 3576 sizeof (fhandle_t))) { 3577 NFSUNLOCKSTATE(); 3578 error = NFSERR_BADSTATEID; 3579 goto out; 3580 } 3581 if (retwriteaccessp != NULL) { 3582 if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0) 3583 *retwriteaccessp = 1; 3584 else 3585 *retwriteaccessp = 0; 3586 } 3587 nfsrv_freedeleg(stp); 3588 } else { 3589 nfsrv_freedeleglist(&clp->lc_olddeleg); 3590 } 3591 NFSUNLOCKSTATE(); 3592 error = 0; 3593 3594 out: 3595 NFSEXITCODE(error); 3596 return (error); 3597 } 3598 3599 /* 3600 * Release lock owner. 3601 */ 3602 APPLESTATIC int 3603 nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid, 3604 NFSPROC_T *p) 3605 { 3606 struct nfsstate *stp, *nstp, *openstp, *ownstp; 3607 struct nfsclient *clp; 3608 int error = 0; 3609 3610 /* 3611 * Check for restart conditions (client and server). 3612 */ 3613 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 3614 &new_stp->ls_stateid, 0); 3615 if (error) 3616 goto out; 3617 3618 NFSLOCKSTATE(); 3619 /* 3620 * Get the lock owner by name. 3621 */ 3622 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL, 3623 (nfsquad_t)((u_quad_t)0), 0, NULL, p); 3624 if (error) { 3625 NFSUNLOCKSTATE(); 3626 goto out; 3627 } 3628 LIST_FOREACH(ownstp, &clp->lc_open, ls_list) { 3629 LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) { 3630 stp = LIST_FIRST(&openstp->ls_open); 3631 while (stp != LIST_END(&openstp->ls_open)) { 3632 nstp = LIST_NEXT(stp, ls_list); 3633 /* 3634 * If the owner matches, check for locks and 3635 * then free or return an error. 3636 */ 3637 if (stp->ls_ownerlen == new_stp->ls_ownerlen && 3638 !NFSBCMP(stp->ls_owner, new_stp->ls_owner, 3639 stp->ls_ownerlen)){ 3640 if (LIST_EMPTY(&stp->ls_lock)) { 3641 nfsrv_freelockowner(stp, NULL, 0, p); 3642 } else { 3643 NFSUNLOCKSTATE(); 3644 error = NFSERR_LOCKSHELD; 3645 goto out; 3646 } 3647 } 3648 stp = nstp; 3649 } 3650 } 3651 } 3652 NFSUNLOCKSTATE(); 3653 3654 out: 3655 NFSEXITCODE(error); 3656 return (error); 3657 } 3658 3659 /* 3660 * Get the file handle for a lock structure. 3661 */ 3662 static int 3663 nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile *new_lfp, 3664 fhandle_t *nfhp, NFSPROC_T *p) 3665 { 3666 fhandle_t *fhp = NULL; 3667 int error; 3668 3669 /* 3670 * For lock, use the new nfslock structure, otherwise just 3671 * a fhandle_t on the stack. 3672 */ 3673 if (flags & NFSLCK_OPEN) { 3674 KASSERT(new_lfp != NULL, ("nfsrv_getlockfh: new_lfp NULL")); 3675 fhp = &new_lfp->lf_fh; 3676 } else if (nfhp) { 3677 fhp = nfhp; 3678 } else { 3679 panic("nfsrv_getlockfh"); 3680 } 3681 error = nfsvno_getfh(vp, fhp, p); 3682 NFSEXITCODE(error); 3683 return (error); 3684 } 3685 3686 /* 3687 * Get an nfs lock structure. Allocate one, as required, and return a 3688 * pointer to it. 3689 * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock. 3690 */ 3691 static int 3692 nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, 3693 struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit) 3694 { 3695 struct nfslockfile *lfp; 3696 fhandle_t *fhp = NULL, *tfhp; 3697 struct nfslockhashhead *hp; 3698 struct nfslockfile *new_lfp = NULL; 3699 3700 /* 3701 * For lock, use the new nfslock structure, otherwise just 3702 * a fhandle_t on the stack. 3703 */ 3704 if (flags & NFSLCK_OPEN) { 3705 new_lfp = *new_lfpp; 3706 fhp = &new_lfp->lf_fh; 3707 } else if (nfhp) { 3708 fhp = nfhp; 3709 } else { 3710 panic("nfsrv_getlockfile"); 3711 } 3712 3713 hp = NFSLOCKHASH(fhp); 3714 LIST_FOREACH(lfp, hp, lf_hash) { 3715 tfhp = &lfp->lf_fh; 3716 if (NFSVNO_CMPFH(fhp, tfhp)) { 3717 if (lockit) 3718 nfsrv_locklf(lfp); 3719 *lfpp = lfp; 3720 return (0); 3721 } 3722 } 3723 if (!(flags & NFSLCK_OPEN)) 3724 return (-1); 3725 3726 /* 3727 * No match, so chain the new one into the list. 3728 */ 3729 LIST_INIT(&new_lfp->lf_open); 3730 LIST_INIT(&new_lfp->lf_lock); 3731 LIST_INIT(&new_lfp->lf_deleg); 3732 LIST_INIT(&new_lfp->lf_locallock); 3733 LIST_INIT(&new_lfp->lf_rollback); 3734 new_lfp->lf_locallock_lck.nfslock_usecnt = 0; 3735 new_lfp->lf_locallock_lck.nfslock_lock = 0; 3736 new_lfp->lf_usecount = 0; 3737 LIST_INSERT_HEAD(hp, new_lfp, lf_hash); 3738 *lfpp = new_lfp; 3739 *new_lfpp = NULL; 3740 return (0); 3741 } 3742 3743 /* 3744 * This function adds a nfslock lock structure to the list for the associated 3745 * nfsstate and nfslockfile structures. It will be inserted after the 3746 * entry pointed at by insert_lop. 3747 */ 3748 static void 3749 nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop, 3750 struct nfsstate *stp, struct nfslockfile *lfp) 3751 { 3752 struct nfslock *lop, *nlop; 3753 3754 new_lop->lo_stp = stp; 3755 new_lop->lo_lfp = lfp; 3756 3757 if (stp != NULL) { 3758 /* Insert in increasing lo_first order */ 3759 lop = LIST_FIRST(&lfp->lf_lock); 3760 if (lop == LIST_END(&lfp->lf_lock) || 3761 new_lop->lo_first <= lop->lo_first) { 3762 LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile); 3763 } else { 3764 nlop = LIST_NEXT(lop, lo_lckfile); 3765 while (nlop != LIST_END(&lfp->lf_lock) && 3766 nlop->lo_first < new_lop->lo_first) { 3767 lop = nlop; 3768 nlop = LIST_NEXT(lop, lo_lckfile); 3769 } 3770 LIST_INSERT_AFTER(lop, new_lop, lo_lckfile); 3771 } 3772 } else { 3773 new_lop->lo_lckfile.le_prev = NULL; /* list not used */ 3774 } 3775 3776 /* 3777 * Insert after insert_lop, which is overloaded as stp or lfp for 3778 * an empty list. 3779 */ 3780 if (stp == NULL && (struct nfslockfile *)insert_lop == lfp) 3781 LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner); 3782 else if ((struct nfsstate *)insert_lop == stp) 3783 LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner); 3784 else 3785 LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner); 3786 if (stp != NULL) { 3787 nfsstatsv1.srvlocks++; 3788 nfsrv_openpluslock++; 3789 } 3790 } 3791 3792 /* 3793 * This function updates the locking for a lock owner and given file. It 3794 * maintains a list of lock ranges ordered on increasing file offset that 3795 * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style). 3796 * It always adds new_lop to the list and sometimes uses the one pointed 3797 * at by other_lopp. 3798 */ 3799 static void 3800 nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, 3801 struct nfslock **other_lopp, struct nfslockfile *lfp) 3802 { 3803 struct nfslock *new_lop = *new_lopp; 3804 struct nfslock *lop, *tlop, *ilop; 3805 struct nfslock *other_lop = *other_lopp; 3806 int unlock = 0, myfile = 0; 3807 u_int64_t tmp; 3808 3809 /* 3810 * Work down the list until the lock is merged. 3811 */ 3812 if (new_lop->lo_flags & NFSLCK_UNLOCK) 3813 unlock = 1; 3814 if (stp != NULL) { 3815 ilop = (struct nfslock *)stp; 3816 lop = LIST_FIRST(&stp->ls_lock); 3817 } else { 3818 ilop = (struct nfslock *)lfp; 3819 lop = LIST_FIRST(&lfp->lf_locallock); 3820 } 3821 while (lop != NULL) { 3822 /* 3823 * Only check locks for this file that aren't before the start of 3824 * new lock's range. 3825 */ 3826 if (lop->lo_lfp == lfp) { 3827 myfile = 1; 3828 if (lop->lo_end >= new_lop->lo_first) { 3829 if (new_lop->lo_end < lop->lo_first) { 3830 /* 3831 * If the new lock ends before the start of the 3832 * current lock's range, no merge, just insert 3833 * the new lock. 3834 */ 3835 break; 3836 } 3837 if (new_lop->lo_flags == lop->lo_flags || 3838 (new_lop->lo_first <= lop->lo_first && 3839 new_lop->lo_end >= lop->lo_end)) { 3840 /* 3841 * This lock can be absorbed by the new lock/unlock. 3842 * This happens when it covers the entire range 3843 * of the old lock or is contiguous 3844 * with the old lock and is of the same type or an 3845 * unlock. 3846 */ 3847 if (lop->lo_first < new_lop->lo_first) 3848 new_lop->lo_first = lop->lo_first; 3849 if (lop->lo_end > new_lop->lo_end) 3850 new_lop->lo_end = lop->lo_end; 3851 tlop = lop; 3852 lop = LIST_NEXT(lop, lo_lckowner); 3853 nfsrv_freenfslock(tlop); 3854 continue; 3855 } 3856 3857 /* 3858 * All these cases are for contiguous locks that are not the 3859 * same type, so they can't be merged. 3860 */ 3861 if (new_lop->lo_first <= lop->lo_first) { 3862 /* 3863 * This case is where the new lock overlaps with the 3864 * first part of the old lock. Move the start of the 3865 * old lock to just past the end of the new lock. The 3866 * new lock will be inserted in front of the old, since 3867 * ilop hasn't been updated. (We are done now.) 3868 */ 3869 lop->lo_first = new_lop->lo_end; 3870 break; 3871 } 3872 if (new_lop->lo_end >= lop->lo_end) { 3873 /* 3874 * This case is where the new lock overlaps with the 3875 * end of the old lock's range. Move the old lock's 3876 * end to just before the new lock's first and insert 3877 * the new lock after the old lock. 3878 * Might not be done yet, since the new lock could 3879 * overlap further locks with higher ranges. 3880 */ 3881 lop->lo_end = new_lop->lo_first; 3882 ilop = lop; 3883 lop = LIST_NEXT(lop, lo_lckowner); 3884 continue; 3885 } 3886 /* 3887 * The final case is where the new lock's range is in the 3888 * middle of the current lock's and splits the current lock 3889 * up. Use *other_lopp to handle the second part of the 3890 * split old lock range. (We are done now.) 3891 * For unlock, we use new_lop as other_lop and tmp, since 3892 * other_lop and new_lop are the same for this case. 3893 * We noted the unlock case above, so we don't need 3894 * new_lop->lo_flags any longer. 3895 */ 3896 tmp = new_lop->lo_first; 3897 if (other_lop == NULL) { 3898 if (!unlock) 3899 panic("nfsd srv update unlock"); 3900 other_lop = new_lop; 3901 *new_lopp = NULL; 3902 } 3903 other_lop->lo_first = new_lop->lo_end; 3904 other_lop->lo_end = lop->lo_end; 3905 other_lop->lo_flags = lop->lo_flags; 3906 other_lop->lo_stp = stp; 3907 other_lop->lo_lfp = lfp; 3908 lop->lo_end = tmp; 3909 nfsrv_insertlock(other_lop, lop, stp, lfp); 3910 *other_lopp = NULL; 3911 ilop = lop; 3912 break; 3913 } 3914 } 3915 ilop = lop; 3916 lop = LIST_NEXT(lop, lo_lckowner); 3917 if (myfile && (lop == NULL || lop->lo_lfp != lfp)) 3918 break; 3919 } 3920 3921 /* 3922 * Insert the new lock in the list at the appropriate place. 3923 */ 3924 if (!unlock) { 3925 nfsrv_insertlock(new_lop, ilop, stp, lfp); 3926 *new_lopp = NULL; 3927 } 3928 } 3929 3930 /* 3931 * This function handles sequencing of locks, etc. 3932 * It returns an error that indicates what the caller should do. 3933 */ 3934 static int 3935 nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 3936 struct nfsstate *stp, struct nfsrvcache *op) 3937 { 3938 int error = 0; 3939 3940 if ((nd->nd_flag & ND_NFSV41) != 0) 3941 /* NFSv4.1 ignores the open_seqid and lock_seqid. */ 3942 goto out; 3943 if (op != nd->nd_rp) 3944 panic("nfsrvstate checkseqid"); 3945 if (!(op->rc_flag & RC_INPROG)) 3946 panic("nfsrvstate not inprog"); 3947 if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) { 3948 printf("refcnt=%d\n", stp->ls_op->rc_refcnt); 3949 panic("nfsrvstate op refcnt"); 3950 } 3951 if ((stp->ls_seq + 1) == seqid) { 3952 if (stp->ls_op) 3953 nfsrvd_derefcache(stp->ls_op); 3954 stp->ls_op = op; 3955 nfsrvd_refcache(op); 3956 stp->ls_seq = seqid; 3957 goto out; 3958 } else if (stp->ls_seq == seqid && stp->ls_op && 3959 op->rc_xid == stp->ls_op->rc_xid && 3960 op->rc_refcnt == 0 && 3961 op->rc_reqlen == stp->ls_op->rc_reqlen && 3962 op->rc_cksum == stp->ls_op->rc_cksum) { 3963 if (stp->ls_op->rc_flag & RC_INPROG) { 3964 error = NFSERR_DONTREPLY; 3965 goto out; 3966 } 3967 nd->nd_rp = stp->ls_op; 3968 nd->nd_rp->rc_flag |= RC_INPROG; 3969 nfsrvd_delcache(op); 3970 error = NFSERR_REPLYFROMCACHE; 3971 goto out; 3972 } 3973 error = NFSERR_BADSEQID; 3974 3975 out: 3976 NFSEXITCODE2(error, nd); 3977 return (error); 3978 } 3979 3980 /* 3981 * Get the client ip address for callbacks. If the strings can't be parsed, 3982 * just set lc_program to 0 to indicate no callbacks are possible. 3983 * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set 3984 * the address to the client's transport address. This won't be used 3985 * for callbacks, but can be printed out by nfsstats for info.) 3986 * Return error if the xdr can't be parsed, 0 otherwise. 3987 */ 3988 APPLESTATIC int 3989 nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp) 3990 { 3991 u_int32_t *tl; 3992 u_char *cp, *cp2; 3993 int i, j; 3994 struct sockaddr_in *rad, *sad; 3995 u_char protocol[5], addr[24]; 3996 int error = 0, cantparse = 0; 3997 union { 3998 in_addr_t ival; 3999 u_char cval[4]; 4000 } ip; 4001 union { 4002 in_port_t sval; 4003 u_char cval[2]; 4004 } port; 4005 4006 rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 4007 rad->sin_family = AF_INET; 4008 rad->sin_len = sizeof (struct sockaddr_in); 4009 rad->sin_addr.s_addr = 0; 4010 rad->sin_port = 0; 4011 clp->lc_req.nr_client = NULL; 4012 clp->lc_req.nr_lock = 0; 4013 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 4014 i = fxdr_unsigned(int, *tl); 4015 if (i >= 3 && i <= 4) { 4016 error = nfsrv_mtostr(nd, protocol, i); 4017 if (error) 4018 goto nfsmout; 4019 if (!strcmp(protocol, "tcp")) { 4020 clp->lc_flags |= LCL_TCPCALLBACK; 4021 clp->lc_req.nr_sotype = SOCK_STREAM; 4022 clp->lc_req.nr_soproto = IPPROTO_TCP; 4023 } else if (!strcmp(protocol, "udp")) { 4024 clp->lc_req.nr_sotype = SOCK_DGRAM; 4025 clp->lc_req.nr_soproto = IPPROTO_UDP; 4026 } else { 4027 cantparse = 1; 4028 } 4029 } else { 4030 cantparse = 1; 4031 if (i > 0) { 4032 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 4033 if (error) 4034 goto nfsmout; 4035 } 4036 } 4037 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 4038 i = fxdr_unsigned(int, *tl); 4039 if (i < 0) { 4040 error = NFSERR_BADXDR; 4041 goto nfsmout; 4042 } else if (i == 0) { 4043 cantparse = 1; 4044 } else if (!cantparse && i <= 23 && i >= 11) { 4045 error = nfsrv_mtostr(nd, addr, i); 4046 if (error) 4047 goto nfsmout; 4048 4049 /* 4050 * Parse out the address fields. We expect 6 decimal numbers 4051 * separated by '.'s. 4052 */ 4053 cp = addr; 4054 i = 0; 4055 while (*cp && i < 6) { 4056 cp2 = cp; 4057 while (*cp2 && *cp2 != '.') 4058 cp2++; 4059 if (*cp2) 4060 *cp2++ = '\0'; 4061 else if (i != 5) { 4062 cantparse = 1; 4063 break; 4064 } 4065 j = nfsrv_getipnumber(cp); 4066 if (j >= 0) { 4067 if (i < 4) 4068 ip.cval[3 - i] = j; 4069 else 4070 port.cval[5 - i] = j; 4071 } else { 4072 cantparse = 1; 4073 break; 4074 } 4075 cp = cp2; 4076 i++; 4077 } 4078 if (!cantparse) { 4079 if (ip.ival != 0x0) { 4080 rad->sin_addr.s_addr = htonl(ip.ival); 4081 rad->sin_port = htons(port.sval); 4082 } else { 4083 cantparse = 1; 4084 } 4085 } 4086 } else { 4087 cantparse = 1; 4088 if (i > 0) { 4089 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 4090 if (error) 4091 goto nfsmout; 4092 } 4093 } 4094 if (cantparse) { 4095 sad = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); 4096 if (sad->sin_family == AF_INET) { 4097 rad->sin_addr.s_addr = sad->sin_addr.s_addr; 4098 rad->sin_port = 0x0; 4099 } 4100 clp->lc_program = 0; 4101 } 4102 nfsmout: 4103 NFSEXITCODE2(error, nd); 4104 return (error); 4105 } 4106 4107 /* 4108 * Turn a string of up to three decimal digits into a number. Return -1 upon 4109 * error. 4110 */ 4111 static int 4112 nfsrv_getipnumber(u_char *cp) 4113 { 4114 int i = 0, j = 0; 4115 4116 while (*cp) { 4117 if (j > 2 || *cp < '0' || *cp > '9') 4118 return (-1); 4119 i *= 10; 4120 i += (*cp - '0'); 4121 cp++; 4122 j++; 4123 } 4124 if (i < 256) 4125 return (i); 4126 return (-1); 4127 } 4128 4129 /* 4130 * This function checks for restart conditions. 4131 */ 4132 static int 4133 nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 4134 nfsv4stateid_t *stateidp, int specialid) 4135 { 4136 int ret = 0; 4137 4138 /* 4139 * First check for a server restart. Open, LockT, ReleaseLockOwner 4140 * and DelegPurge have a clientid, the rest a stateid. 4141 */ 4142 if (flags & 4143 (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { 4144 if (clientid.lval[0] != nfsrvboottime) { 4145 ret = NFSERR_STALECLIENTID; 4146 goto out; 4147 } 4148 } else if (stateidp->other[0] != nfsrvboottime && 4149 specialid == 0) { 4150 ret = NFSERR_STALESTATEID; 4151 goto out; 4152 } 4153 4154 /* 4155 * Read, Write, Setattr and LockT can return NFSERR_GRACE and do 4156 * not use a lock/open owner seqid#, so the check can be done now. 4157 * (The others will be checked, as required, later.) 4158 */ 4159 if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST))) 4160 goto out; 4161 4162 NFSLOCKSTATE(); 4163 ret = nfsrv_checkgrace(NULL, NULL, flags); 4164 NFSUNLOCKSTATE(); 4165 4166 out: 4167 NFSEXITCODE(ret); 4168 return (ret); 4169 } 4170 4171 /* 4172 * Check for grace. 4173 */ 4174 static int 4175 nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp, 4176 u_int32_t flags) 4177 { 4178 int error = 0, notreclaimed; 4179 struct nfsrv_stable *sp; 4180 4181 if ((nfsrv_stablefirst.nsf_flags & (NFSNSF_UPDATEDONE | 4182 NFSNSF_GRACEOVER)) == 0) { 4183 /* 4184 * First, check to see if all of the clients have done a 4185 * ReclaimComplete. If so, grace can end now. 4186 */ 4187 notreclaimed = 0; 4188 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4189 if ((sp->nst_flag & NFSNST_RECLAIMED) == 0) { 4190 notreclaimed = 1; 4191 break; 4192 } 4193 } 4194 if (notreclaimed == 0) 4195 nfsrv_stablefirst.nsf_flags |= (NFSNSF_GRACEOVER | 4196 NFSNSF_NEEDLOCK); 4197 } 4198 4199 if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) { 4200 if (flags & NFSLCK_RECLAIM) { 4201 error = NFSERR_NOGRACE; 4202 goto out; 4203 } 4204 } else { 4205 if (!(flags & NFSLCK_RECLAIM)) { 4206 error = NFSERR_GRACE; 4207 goto out; 4208 } 4209 if (nd != NULL && clp != NULL && 4210 (nd->nd_flag & ND_NFSV41) != 0 && 4211 (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) { 4212 error = NFSERR_NOGRACE; 4213 goto out; 4214 } 4215 4216 /* 4217 * If grace is almost over and we are still getting Reclaims, 4218 * extend grace a bit. 4219 */ 4220 if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > 4221 nfsrv_stablefirst.nsf_eograce) 4222 nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC + 4223 NFSRV_LEASEDELTA; 4224 } 4225 4226 out: 4227 NFSEXITCODE(error); 4228 return (error); 4229 } 4230 4231 /* 4232 * Do a server callback. 4233 */ 4234 static int 4235 nfsrv_docallback(struct nfsclient *clp, int procnum, nfsv4stateid_t *stateidp, 4236 int trunc, fhandle_t *fhp, struct nfsvattr *nap, nfsattrbit_t *attrbitp, 4237 int laytype, NFSPROC_T *p) 4238 { 4239 mbuf_t m; 4240 u_int32_t *tl; 4241 struct nfsrv_descript *nd; 4242 struct ucred *cred; 4243 int error = 0; 4244 u_int32_t callback; 4245 struct nfsdsession *sep = NULL; 4246 uint64_t tval; 4247 4248 nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO); 4249 cred = newnfs_getcred(); 4250 NFSLOCKSTATE(); /* mostly for lc_cbref++ */ 4251 if (clp->lc_flags & LCL_NEEDSCONFIRM) { 4252 NFSUNLOCKSTATE(); 4253 panic("docallb"); 4254 } 4255 clp->lc_cbref++; 4256 4257 /* 4258 * Fill the callback program# and version into the request 4259 * structure for newnfs_connect() to use. 4260 */ 4261 clp->lc_req.nr_prog = clp->lc_program; 4262 #ifdef notnow 4263 if ((clp->lc_flags & LCL_NFSV41) != 0) 4264 clp->lc_req.nr_vers = NFSV41_CBVERS; 4265 else 4266 #endif 4267 clp->lc_req.nr_vers = NFSV4_CBVERS; 4268 4269 /* 4270 * First, fill in some of the fields of nd and cr. 4271 */ 4272 nd->nd_flag = ND_NFSV4; 4273 if (clp->lc_flags & LCL_GSS) 4274 nd->nd_flag |= ND_KERBV; 4275 if ((clp->lc_flags & LCL_NFSV41) != 0) 4276 nd->nd_flag |= ND_NFSV41; 4277 nd->nd_repstat = 0; 4278 cred->cr_uid = clp->lc_uid; 4279 cred->cr_gid = clp->lc_gid; 4280 callback = clp->lc_callback; 4281 NFSUNLOCKSTATE(); 4282 cred->cr_ngroups = 1; 4283 4284 /* 4285 * Get the first mbuf for the request. 4286 */ 4287 MGET(m, M_WAITOK, MT_DATA); 4288 mbuf_setlen(m, 0); 4289 nd->nd_mreq = nd->nd_mb = m; 4290 nd->nd_bpos = NFSMTOD(m, caddr_t); 4291 4292 /* 4293 * and build the callback request. 4294 */ 4295 if (procnum == NFSV4OP_CBGETATTR) { 4296 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4297 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR, 4298 "CB Getattr", &sep); 4299 if (error != 0) { 4300 mbuf_freem(nd->nd_mreq); 4301 goto errout; 4302 } 4303 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 4304 (void)nfsrv_putattrbit(nd, attrbitp); 4305 } else if (procnum == NFSV4OP_CBRECALL) { 4306 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4307 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL, 4308 "CB Recall", &sep); 4309 if (error != 0) { 4310 mbuf_freem(nd->nd_mreq); 4311 goto errout; 4312 } 4313 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID); 4314 *tl++ = txdr_unsigned(stateidp->seqid); 4315 NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl, 4316 NFSX_STATEIDOTHER); 4317 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4318 if (trunc) 4319 *tl = newnfs_true; 4320 else 4321 *tl = newnfs_false; 4322 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 4323 } else if (procnum == NFSV4OP_CBLAYOUTRECALL) { 4324 NFSD_DEBUG(4, "docallback layout recall\n"); 4325 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 4326 error = nfsrv_cbcallargs(nd, clp, callback, 4327 NFSV4OP_CBLAYOUTRECALL, "CB Reclayout", &sep); 4328 NFSD_DEBUG(4, "aft cbcallargs=%d\n", error); 4329 if (error != 0) { 4330 mbuf_freem(nd->nd_mreq); 4331 goto errout; 4332 } 4333 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 4334 *tl++ = txdr_unsigned(laytype); 4335 *tl++ = txdr_unsigned(NFSLAYOUTIOMODE_ANY); 4336 *tl++ = newnfs_true; 4337 *tl = txdr_unsigned(NFSV4LAYOUTRET_FILE); 4338 nfsm_fhtom(nd, (uint8_t *)fhp, NFSX_MYFH, 0); 4339 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER + NFSX_STATEID); 4340 tval = 0; 4341 txdr_hyper(tval, tl); tl += 2; 4342 tval = UINT64_MAX; 4343 txdr_hyper(tval, tl); tl += 2; 4344 *tl++ = txdr_unsigned(stateidp->seqid); 4345 NFSBCOPY(stateidp->other, tl, NFSX_STATEIDOTHER); 4346 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 4347 NFSD_DEBUG(4, "aft args\n"); 4348 } else if (procnum == NFSV4PROC_CBNULL) { 4349 nd->nd_procnum = NFSV4PROC_CBNULL; 4350 if ((clp->lc_flags & LCL_NFSV41) != 0) { 4351 error = nfsv4_getcbsession(clp, &sep); 4352 if (error != 0) { 4353 mbuf_freem(nd->nd_mreq); 4354 goto errout; 4355 } 4356 } 4357 } else { 4358 error = NFSERR_SERVERFAULT; 4359 mbuf_freem(nd->nd_mreq); 4360 goto errout; 4361 } 4362 4363 /* 4364 * Call newnfs_connect(), as required, and then newnfs_request(). 4365 */ 4366 (void) newnfs_sndlock(&clp->lc_req.nr_lock); 4367 if (clp->lc_req.nr_client == NULL) { 4368 if ((clp->lc_flags & LCL_NFSV41) != 0) { 4369 error = ECONNREFUSED; 4370 nfsrv_freesession(sep, NULL); 4371 } else if (nd->nd_procnum == NFSV4PROC_CBNULL) 4372 error = newnfs_connect(NULL, &clp->lc_req, cred, 4373 NULL, 1); 4374 else 4375 error = newnfs_connect(NULL, &clp->lc_req, cred, 4376 NULL, 3); 4377 } 4378 newnfs_sndunlock(&clp->lc_req.nr_lock); 4379 NFSD_DEBUG(4, "aft sndunlock=%d\n", error); 4380 if (!error) { 4381 if ((nd->nd_flag & ND_NFSV41) != 0) { 4382 KASSERT(sep != NULL, ("sep NULL")); 4383 if (sep->sess_cbsess.nfsess_xprt != NULL) 4384 error = newnfs_request(nd, NULL, clp, 4385 &clp->lc_req, NULL, NULL, cred, 4386 clp->lc_program, clp->lc_req.nr_vers, NULL, 4387 1, NULL, &sep->sess_cbsess); 4388 else { 4389 /* 4390 * This should probably never occur, but if a 4391 * client somehow does an RPC without a 4392 * SequenceID Op that causes a callback just 4393 * after the nfsd threads have been terminated 4394 * and restared we could conceivably get here 4395 * without a backchannel xprt. 4396 */ 4397 printf("nfsrv_docallback: no xprt\n"); 4398 error = ECONNREFUSED; 4399 } 4400 NFSD_DEBUG(4, "aft newnfs_request=%d\n", error); 4401 nfsrv_freesession(sep, NULL); 4402 } else 4403 error = newnfs_request(nd, NULL, clp, &clp->lc_req, 4404 NULL, NULL, cred, clp->lc_program, 4405 clp->lc_req.nr_vers, NULL, 1, NULL, NULL); 4406 } 4407 errout: 4408 NFSFREECRED(cred); 4409 4410 /* 4411 * If error is set here, the Callback path isn't working 4412 * properly, so twiddle the appropriate LCL_ flags. 4413 * (nd_repstat != 0 indicates the Callback path is working, 4414 * but the callback failed on the client.) 4415 */ 4416 if (error) { 4417 /* 4418 * Mark the callback pathway down, which disabled issuing 4419 * of delegations and gets Renew to return NFSERR_CBPATHDOWN. 4420 */ 4421 NFSLOCKSTATE(); 4422 clp->lc_flags |= LCL_CBDOWN; 4423 NFSUNLOCKSTATE(); 4424 } else { 4425 /* 4426 * Callback worked. If the callback path was down, disable 4427 * callbacks, so no more delegations will be issued. (This 4428 * is done on the assumption that the callback pathway is 4429 * flakey.) 4430 */ 4431 NFSLOCKSTATE(); 4432 if (clp->lc_flags & LCL_CBDOWN) 4433 clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON); 4434 NFSUNLOCKSTATE(); 4435 if (nd->nd_repstat) { 4436 error = nd->nd_repstat; 4437 NFSD_DEBUG(1, "nfsrv_docallback op=%d err=%d\n", 4438 procnum, error); 4439 } else if (error == 0 && procnum == NFSV4OP_CBGETATTR) 4440 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, 4441 NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 4442 p, NULL); 4443 mbuf_freem(nd->nd_mrep); 4444 } 4445 NFSLOCKSTATE(); 4446 clp->lc_cbref--; 4447 if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) { 4448 clp->lc_flags &= ~LCL_WAKEUPWANTED; 4449 wakeup(clp); 4450 } 4451 NFSUNLOCKSTATE(); 4452 4453 free(nd, M_TEMP); 4454 NFSEXITCODE(error); 4455 return (error); 4456 } 4457 4458 /* 4459 * Set up the compound RPC for the callback. 4460 */ 4461 static int 4462 nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp, 4463 uint32_t callback, int op, const char *optag, struct nfsdsession **sepp) 4464 { 4465 uint32_t *tl; 4466 int error, len; 4467 4468 len = strlen(optag); 4469 (void)nfsm_strtom(nd, optag, len); 4470 NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED); 4471 if ((nd->nd_flag & ND_NFSV41) != 0) { 4472 *tl++ = txdr_unsigned(NFSV41_MINORVERSION); 4473 *tl++ = txdr_unsigned(callback); 4474 *tl++ = txdr_unsigned(2); 4475 *tl = txdr_unsigned(NFSV4OP_CBSEQUENCE); 4476 error = nfsv4_setcbsequence(nd, clp, 1, sepp); 4477 if (error != 0) 4478 return (error); 4479 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 4480 *tl = txdr_unsigned(op); 4481 } else { 4482 *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 4483 *tl++ = txdr_unsigned(callback); 4484 *tl++ = txdr_unsigned(1); 4485 *tl = txdr_unsigned(op); 4486 } 4487 return (0); 4488 } 4489 4490 /* 4491 * Return the next index# for a clientid. Mostly just increment and return 4492 * the next one, but... if the 32bit unsigned does actually wrap around, 4493 * it should be rebooted. 4494 * At an average rate of one new client per second, it will wrap around in 4495 * approximately 136 years. (I think the server will have been shut 4496 * down or rebooted before then.) 4497 */ 4498 static u_int32_t 4499 nfsrv_nextclientindex(void) 4500 { 4501 static u_int32_t client_index = 0; 4502 4503 client_index++; 4504 if (client_index != 0) 4505 return (client_index); 4506 4507 printf("%s: out of clientids\n", __func__); 4508 return (client_index); 4509 } 4510 4511 /* 4512 * Return the next index# for a stateid. Mostly just increment and return 4513 * the next one, but... if the 32bit unsigned does actually wrap around 4514 * (will a BSD server stay up that long?), find 4515 * new start and end values. 4516 */ 4517 static u_int32_t 4518 nfsrv_nextstateindex(struct nfsclient *clp) 4519 { 4520 struct nfsstate *stp; 4521 int i; 4522 u_int32_t canuse, min_index, max_index; 4523 4524 if (!(clp->lc_flags & LCL_INDEXNOTOK)) { 4525 clp->lc_stateindex++; 4526 if (clp->lc_stateindex != clp->lc_statemaxindex) 4527 return (clp->lc_stateindex); 4528 } 4529 4530 /* 4531 * Yuck, we've hit the end. 4532 * Look for a new min and max. 4533 */ 4534 min_index = 0; 4535 max_index = 0xffffffff; 4536 for (i = 0; i < nfsrv_statehashsize; i++) { 4537 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 4538 if (stp->ls_stateid.other[2] > 0x80000000) { 4539 if (stp->ls_stateid.other[2] < max_index) 4540 max_index = stp->ls_stateid.other[2]; 4541 } else { 4542 if (stp->ls_stateid.other[2] > min_index) 4543 min_index = stp->ls_stateid.other[2]; 4544 } 4545 } 4546 } 4547 4548 /* 4549 * Yikes, highly unlikely, but I'll handle it anyhow. 4550 */ 4551 if (min_index == 0x80000000 && max_index == 0x80000001) { 4552 canuse = 0; 4553 /* 4554 * Loop around until we find an unused entry. Return that 4555 * and set LCL_INDEXNOTOK, so the search will continue next time. 4556 * (This is one of those rare cases where a goto is the 4557 * cleanest way to code the loop.) 4558 */ 4559 tryagain: 4560 for (i = 0; i < nfsrv_statehashsize; i++) { 4561 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 4562 if (stp->ls_stateid.other[2] == canuse) { 4563 canuse++; 4564 goto tryagain; 4565 } 4566 } 4567 } 4568 clp->lc_flags |= LCL_INDEXNOTOK; 4569 return (canuse); 4570 } 4571 4572 /* 4573 * Ok to start again from min + 1. 4574 */ 4575 clp->lc_stateindex = min_index + 1; 4576 clp->lc_statemaxindex = max_index; 4577 clp->lc_flags &= ~LCL_INDEXNOTOK; 4578 return (clp->lc_stateindex); 4579 } 4580 4581 /* 4582 * The following functions handle the stable storage file that deals with 4583 * the edge conditions described in RFC3530 Sec. 8.6.3. 4584 * The file is as follows: 4585 * - a single record at the beginning that has the lease time of the 4586 * previous server instance (before the last reboot) and the nfsrvboottime 4587 * values for the previous server boots. 4588 * These previous boot times are used to ensure that the current 4589 * nfsrvboottime does not, somehow, get set to a previous one. 4590 * (This is important so that Stale ClientIDs and StateIDs can 4591 * be recognized.) 4592 * The number of previous nfsvrboottime values precedes the list. 4593 * - followed by some number of appended records with: 4594 * - client id string 4595 * - flag that indicates it is a record revoking state via lease 4596 * expiration or similar 4597 * OR has successfully acquired state. 4598 * These structures vary in length, with the client string at the end, up 4599 * to NFSV4_OPAQUELIMIT in size. 4600 * 4601 * At the end of the grace period, the file is truncated, the first 4602 * record is rewritten with updated information and any acquired state 4603 * records for successful reclaims of state are written. 4604 * 4605 * Subsequent records are appended when the first state is issued to 4606 * a client and when state is revoked for a client. 4607 * 4608 * When reading the file in, state issued records that come later in 4609 * the file override older ones, since the append log is in cronological order. 4610 * If, for some reason, the file can't be read, the grace period is 4611 * immediately terminated and all reclaims get NFSERR_NOGRACE. 4612 */ 4613 4614 /* 4615 * Read in the stable storage file. Called by nfssvc() before the nfsd 4616 * processes start servicing requests. 4617 */ 4618 APPLESTATIC void 4619 nfsrv_setupstable(NFSPROC_T *p) 4620 { 4621 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4622 struct nfsrv_stable *sp, *nsp; 4623 struct nfst_rec *tsp; 4624 int error, i, tryagain; 4625 off_t off = 0; 4626 ssize_t aresid, len; 4627 4628 /* 4629 * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without 4630 * a reboot, so state has not been lost. 4631 */ 4632 if (sf->nsf_flags & NFSNSF_UPDATEDONE) 4633 return; 4634 /* 4635 * Set Grace over just until the file reads successfully. 4636 */ 4637 nfsrvboottime = time_second; 4638 LIST_INIT(&sf->nsf_head); 4639 sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); 4640 sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA; 4641 if (sf->nsf_fp == NULL) 4642 return; 4643 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4644 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE, 4645 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4646 if (error || aresid || sf->nsf_numboots == 0 || 4647 sf->nsf_numboots > NFSNSF_MAXNUMBOOTS) 4648 return; 4649 4650 /* 4651 * Now, read in the boottimes. 4652 */ 4653 sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) * 4654 sizeof (time_t), M_TEMP, M_WAITOK); 4655 off = sizeof (struct nfsf_rec); 4656 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4657 (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off, 4658 UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4659 if (error || aresid) { 4660 free(sf->nsf_bootvals, M_TEMP); 4661 sf->nsf_bootvals = NULL; 4662 return; 4663 } 4664 4665 /* 4666 * Make sure this nfsrvboottime is different from all recorded 4667 * previous ones. 4668 */ 4669 do { 4670 tryagain = 0; 4671 for (i = 0; i < sf->nsf_numboots; i++) { 4672 if (nfsrvboottime == sf->nsf_bootvals[i]) { 4673 nfsrvboottime++; 4674 tryagain = 1; 4675 break; 4676 } 4677 } 4678 } while (tryagain); 4679 4680 sf->nsf_flags |= NFSNSF_OK; 4681 off += (sf->nsf_numboots * sizeof (time_t)); 4682 4683 /* 4684 * Read through the file, building a list of records for grace 4685 * checking. 4686 * Each record is between sizeof (struct nfst_rec) and 4687 * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1 4688 * and is actually sizeof (struct nfst_rec) + nst_len - 1. 4689 */ 4690 tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4691 NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK); 4692 do { 4693 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 4694 (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1, 4695 off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 4696 len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid; 4697 if (error || (len > 0 && (len < sizeof (struct nfst_rec) || 4698 len < (sizeof (struct nfst_rec) + tsp->len - 1)))) { 4699 /* 4700 * Yuck, the file has been corrupted, so just return 4701 * after clearing out any restart state, so the grace period 4702 * is over. 4703 */ 4704 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4705 LIST_REMOVE(sp, nst_list); 4706 free(sp, M_TEMP); 4707 } 4708 free(tsp, M_TEMP); 4709 sf->nsf_flags &= ~NFSNSF_OK; 4710 free(sf->nsf_bootvals, M_TEMP); 4711 sf->nsf_bootvals = NULL; 4712 return; 4713 } 4714 if (len > 0) { 4715 off += sizeof (struct nfst_rec) + tsp->len - 1; 4716 /* 4717 * Search the list for a matching client. 4718 */ 4719 LIST_FOREACH(sp, &sf->nsf_head, nst_list) { 4720 if (tsp->len == sp->nst_len && 4721 !NFSBCMP(tsp->client, sp->nst_client, tsp->len)) 4722 break; 4723 } 4724 if (sp == LIST_END(&sf->nsf_head)) { 4725 sp = (struct nfsrv_stable *)malloc(tsp->len + 4726 sizeof (struct nfsrv_stable) - 1, M_TEMP, 4727 M_WAITOK); 4728 NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec, 4729 sizeof (struct nfst_rec) + tsp->len - 1); 4730 LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list); 4731 } else { 4732 if (tsp->flag == NFSNST_REVOKE) 4733 sp->nst_flag |= NFSNST_REVOKE; 4734 else 4735 /* 4736 * A subsequent timestamp indicates the client 4737 * did a setclientid/confirm and any previous 4738 * revoke is no longer relevant. 4739 */ 4740 sp->nst_flag &= ~NFSNST_REVOKE; 4741 } 4742 } 4743 } while (len > 0); 4744 free(tsp, M_TEMP); 4745 sf->nsf_flags = NFSNSF_OK; 4746 sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease + 4747 NFSRV_LEASEDELTA; 4748 } 4749 4750 /* 4751 * Update the stable storage file, now that the grace period is over. 4752 */ 4753 APPLESTATIC void 4754 nfsrv_updatestable(NFSPROC_T *p) 4755 { 4756 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4757 struct nfsrv_stable *sp, *nsp; 4758 int i; 4759 struct nfsvattr nva; 4760 vnode_t vp; 4761 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) 4762 mount_t mp = NULL; 4763 #endif 4764 int error; 4765 4766 if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE)) 4767 return; 4768 sf->nsf_flags |= NFSNSF_UPDATEDONE; 4769 /* 4770 * Ok, we need to rewrite the stable storage file. 4771 * - truncate to 0 length 4772 * - write the new first structure 4773 * - loop through the data structures, writing out any that 4774 * have timestamps older than the old boot 4775 */ 4776 if (sf->nsf_bootvals) { 4777 sf->nsf_numboots++; 4778 for (i = sf->nsf_numboots - 2; i >= 0; i--) 4779 sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i]; 4780 } else { 4781 sf->nsf_numboots = 1; 4782 sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t), 4783 M_TEMP, M_WAITOK); 4784 } 4785 sf->nsf_bootvals[0] = nfsrvboottime; 4786 sf->nsf_lease = nfsrv_lease; 4787 NFSVNO_ATTRINIT(&nva); 4788 NFSVNO_SETATTRVAL(&nva, size, 0); 4789 vp = NFSFPVNODE(sf->nsf_fp); 4790 vn_start_write(vp, &mp, V_WAIT); 4791 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { 4792 error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p, 4793 NULL); 4794 NFSVOPUNLOCK(vp, 0); 4795 } else 4796 error = EPERM; 4797 vn_finished_write(mp); 4798 if (!error) 4799 error = NFSD_RDWR(UIO_WRITE, vp, 4800 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0, 4801 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4802 if (!error) 4803 error = NFSD_RDWR(UIO_WRITE, vp, 4804 (caddr_t)sf->nsf_bootvals, 4805 sf->nsf_numboots * sizeof (time_t), 4806 (off_t)(sizeof (struct nfsf_rec)), 4807 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4808 free(sf->nsf_bootvals, M_TEMP); 4809 sf->nsf_bootvals = NULL; 4810 if (error) { 4811 sf->nsf_flags &= ~NFSNSF_OK; 4812 printf("EEK! Can't write NfsV4 stable storage file\n"); 4813 return; 4814 } 4815 sf->nsf_flags |= NFSNSF_OK; 4816 4817 /* 4818 * Loop through the list and write out timestamp records for 4819 * any clients that successfully reclaimed state. 4820 */ 4821 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4822 if (sp->nst_flag & NFSNST_GOTSTATE) { 4823 nfsrv_writestable(sp->nst_client, sp->nst_len, 4824 NFSNST_NEWSTATE, p); 4825 sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE; 4826 } 4827 LIST_REMOVE(sp, nst_list); 4828 free(sp, M_TEMP); 4829 } 4830 nfsrv_backupstable(); 4831 } 4832 4833 /* 4834 * Append a record to the stable storage file. 4835 */ 4836 APPLESTATIC void 4837 nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p) 4838 { 4839 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4840 struct nfst_rec *sp; 4841 int error; 4842 4843 if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL) 4844 return; 4845 sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4846 len - 1, M_TEMP, M_WAITOK); 4847 sp->len = len; 4848 NFSBCOPY(client, sp->client, len); 4849 sp->flag = flag; 4850 error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp), 4851 (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0, 4852 UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p); 4853 free(sp, M_TEMP); 4854 if (error) { 4855 sf->nsf_flags &= ~NFSNSF_OK; 4856 printf("EEK! Can't write NfsV4 stable storage file\n"); 4857 } 4858 } 4859 4860 /* 4861 * This function is called during the grace period to mark a client 4862 * that successfully reclaimed state. 4863 */ 4864 static void 4865 nfsrv_markstable(struct nfsclient *clp) 4866 { 4867 struct nfsrv_stable *sp; 4868 4869 /* 4870 * First find the client structure. 4871 */ 4872 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4873 if (sp->nst_len == clp->lc_idlen && 4874 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4875 break; 4876 } 4877 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) 4878 return; 4879 4880 /* 4881 * Now, just mark it and set the nfsclient back pointer. 4882 */ 4883 sp->nst_flag |= NFSNST_GOTSTATE; 4884 sp->nst_clp = clp; 4885 } 4886 4887 /* 4888 * This function is called when a NFSv4.1 client does a ReclaimComplete. 4889 * Very similar to nfsrv_markstable(), except for the flag being set. 4890 */ 4891 static void 4892 nfsrv_markreclaim(struct nfsclient *clp) 4893 { 4894 struct nfsrv_stable *sp; 4895 4896 /* 4897 * First find the client structure. 4898 */ 4899 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4900 if (sp->nst_len == clp->lc_idlen && 4901 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4902 break; 4903 } 4904 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) 4905 return; 4906 4907 /* 4908 * Now, just set the flag. 4909 */ 4910 sp->nst_flag |= NFSNST_RECLAIMED; 4911 } 4912 4913 /* 4914 * This function is called for a reclaim, to see if it gets grace. 4915 * It returns 0 if a reclaim is allowed, 1 otherwise. 4916 */ 4917 static int 4918 nfsrv_checkstable(struct nfsclient *clp) 4919 { 4920 struct nfsrv_stable *sp; 4921 4922 /* 4923 * First, find the entry for the client. 4924 */ 4925 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4926 if (sp->nst_len == clp->lc_idlen && 4927 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4928 break; 4929 } 4930 4931 /* 4932 * If not in the list, state was revoked or no state was issued 4933 * since the previous reboot, a reclaim is denied. 4934 */ 4935 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) || 4936 (sp->nst_flag & NFSNST_REVOKE) || 4937 !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK)) 4938 return (1); 4939 return (0); 4940 } 4941 4942 /* 4943 * Test for and try to clear out a conflicting client. This is called by 4944 * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients 4945 * a found. 4946 * The trick here is that it can't revoke a conflicting client with an 4947 * expired lease unless it holds the v4root lock, so... 4948 * If no v4root lock, get the lock and return 1 to indicate "try again". 4949 * Return 0 to indicate the conflict can't be revoked and 1 to indicate 4950 * the revocation worked and the conflicting client is "bye, bye", so it 4951 * can be tried again. 4952 * Return 2 to indicate that the vnode is VI_DOOMED after NFSVOPLOCK(). 4953 * Unlocks State before a non-zero value is returned. 4954 */ 4955 static int 4956 nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp, 4957 NFSPROC_T *p) 4958 { 4959 int gotlock, lktype = 0; 4960 4961 /* 4962 * If lease hasn't expired, we can't fix it. 4963 */ 4964 if (clp->lc_expiry >= NFSD_MONOSEC || 4965 !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) 4966 return (0); 4967 if (*haslockp == 0) { 4968 NFSUNLOCKSTATE(); 4969 if (vp != NULL) { 4970 lktype = NFSVOPISLOCKED(vp); 4971 NFSVOPUNLOCK(vp, 0); 4972 } 4973 NFSLOCKV4ROOTMUTEX(); 4974 nfsv4_relref(&nfsv4rootfs_lock); 4975 do { 4976 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4977 NFSV4ROOTLOCKMUTEXPTR, NULL); 4978 } while (!gotlock); 4979 NFSUNLOCKV4ROOTMUTEX(); 4980 *haslockp = 1; 4981 if (vp != NULL) { 4982 NFSVOPLOCK(vp, lktype | LK_RETRY); 4983 if ((vp->v_iflag & VI_DOOMED) != 0) 4984 return (2); 4985 } 4986 return (1); 4987 } 4988 NFSUNLOCKSTATE(); 4989 4990 /* 4991 * Ok, we can expire the conflicting client. 4992 */ 4993 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 4994 nfsrv_backupstable(); 4995 nfsrv_cleanclient(clp, p); 4996 nfsrv_freedeleglist(&clp->lc_deleg); 4997 nfsrv_freedeleglist(&clp->lc_olddeleg); 4998 LIST_REMOVE(clp, lc_hash); 4999 nfsrv_zapclient(clp, p); 5000 return (1); 5001 } 5002 5003 /* 5004 * Resolve a delegation conflict. 5005 * Returns 0 to indicate the conflict was resolved without sleeping. 5006 * Return -1 to indicate that the caller should check for conflicts again. 5007 * Return > 0 for an error that should be returned, normally NFSERR_DELAY. 5008 * 5009 * Also, manipulate the nfsv4root_lock, as required. It isn't changed 5010 * for a return of 0, since there was no sleep and it could be required 5011 * later. It is released for a return of NFSERR_DELAY, since the caller 5012 * will return that error. It is released when a sleep was done waiting 5013 * for the delegation to be returned or expire (so that other nfsds can 5014 * handle ops). Then, it must be acquired for the write to stable storage. 5015 * (This function is somewhat similar to nfsrv_clientconflict(), but 5016 * the semantics differ in a couple of subtle ways. The return of 0 5017 * indicates the conflict was resolved without sleeping here, not 5018 * that the conflict can't be resolved and the handling of nfsv4root_lock 5019 * differs, as noted above.) 5020 * Unlocks State before returning a non-zero value. 5021 */ 5022 static int 5023 nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p, 5024 vnode_t vp) 5025 { 5026 struct nfsclient *clp = stp->ls_clp; 5027 int gotlock, error, lktype = 0, retrycnt, zapped_clp; 5028 nfsv4stateid_t tstateid; 5029 fhandle_t tfh; 5030 5031 /* 5032 * If the conflict is with an old delegation... 5033 */ 5034 if (stp->ls_flags & NFSLCK_OLDDELEG) { 5035 /* 5036 * You can delete it, if it has expired. 5037 */ 5038 if (clp->lc_delegtime < NFSD_MONOSEC) { 5039 nfsrv_freedeleg(stp); 5040 NFSUNLOCKSTATE(); 5041 error = -1; 5042 goto out; 5043 } 5044 NFSUNLOCKSTATE(); 5045 /* 5046 * During this delay, the old delegation could expire or it 5047 * could be recovered by the client via an Open with 5048 * CLAIM_DELEGATE_PREV. 5049 * Release the nfsv4root_lock, if held. 5050 */ 5051 if (*haslockp) { 5052 *haslockp = 0; 5053 NFSLOCKV4ROOTMUTEX(); 5054 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5055 NFSUNLOCKV4ROOTMUTEX(); 5056 } 5057 error = NFSERR_DELAY; 5058 goto out; 5059 } 5060 5061 /* 5062 * It's a current delegation, so: 5063 * - check to see if the delegation has expired 5064 * - if so, get the v4root lock and then expire it 5065 */ 5066 if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) { 5067 /* 5068 * - do a recall callback, since not yet done 5069 * For now, never allow truncate to be set. To use 5070 * truncate safely, it must be guaranteed that the 5071 * Remove, Rename or Setattr with size of 0 will 5072 * succeed and that would require major changes to 5073 * the VFS/Vnode OPs. 5074 * Set the expiry time large enough so that it won't expire 5075 * until after the callback, then set it correctly, once 5076 * the callback is done. (The delegation will now time 5077 * out whether or not the Recall worked ok. The timeout 5078 * will be extended when ops are done on the delegation 5079 * stateid, up to the timelimit.) 5080 */ 5081 stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) + 5082 NFSRV_LEASEDELTA; 5083 stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) + 5084 NFSRV_LEASEDELTA; 5085 stp->ls_flags |= NFSLCK_DELEGRECALL; 5086 5087 /* 5088 * Loop NFSRV_CBRETRYCNT times while the CBRecall replies 5089 * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done 5090 * in order to try and avoid a race that could happen 5091 * when a CBRecall request passed the Open reply with 5092 * the delegation in it when transitting the network. 5093 * Since nfsrv_docallback will sleep, don't use stp after 5094 * the call. 5095 */ 5096 NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid, 5097 sizeof (tstateid)); 5098 NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh, 5099 sizeof (tfh)); 5100 NFSUNLOCKSTATE(); 5101 if (*haslockp) { 5102 *haslockp = 0; 5103 NFSLOCKV4ROOTMUTEX(); 5104 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5105 NFSUNLOCKV4ROOTMUTEX(); 5106 } 5107 retrycnt = 0; 5108 do { 5109 error = nfsrv_docallback(clp, NFSV4OP_CBRECALL, 5110 &tstateid, 0, &tfh, NULL, NULL, 0, p); 5111 retrycnt++; 5112 } while ((error == NFSERR_BADSTATEID || 5113 error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT); 5114 error = NFSERR_DELAY; 5115 goto out; 5116 } 5117 5118 if (clp->lc_expiry >= NFSD_MONOSEC && 5119 stp->ls_delegtime >= NFSD_MONOSEC) { 5120 NFSUNLOCKSTATE(); 5121 /* 5122 * A recall has been done, but it has not yet expired. 5123 * So, RETURN_DELAY. 5124 */ 5125 if (*haslockp) { 5126 *haslockp = 0; 5127 NFSLOCKV4ROOTMUTEX(); 5128 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5129 NFSUNLOCKV4ROOTMUTEX(); 5130 } 5131 error = NFSERR_DELAY; 5132 goto out; 5133 } 5134 5135 /* 5136 * If we don't yet have the lock, just get it and then return, 5137 * since we need that before deleting expired state, such as 5138 * this delegation. 5139 * When getting the lock, unlock the vnode, so other nfsds that 5140 * are in progress, won't get stuck waiting for the vnode lock. 5141 */ 5142 if (*haslockp == 0) { 5143 NFSUNLOCKSTATE(); 5144 if (vp != NULL) { 5145 lktype = NFSVOPISLOCKED(vp); 5146 NFSVOPUNLOCK(vp, 0); 5147 } 5148 NFSLOCKV4ROOTMUTEX(); 5149 nfsv4_relref(&nfsv4rootfs_lock); 5150 do { 5151 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 5152 NFSV4ROOTLOCKMUTEXPTR, NULL); 5153 } while (!gotlock); 5154 NFSUNLOCKV4ROOTMUTEX(); 5155 *haslockp = 1; 5156 if (vp != NULL) { 5157 NFSVOPLOCK(vp, lktype | LK_RETRY); 5158 if ((vp->v_iflag & VI_DOOMED) != 0) { 5159 *haslockp = 0; 5160 NFSLOCKV4ROOTMUTEX(); 5161 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5162 NFSUNLOCKV4ROOTMUTEX(); 5163 error = NFSERR_PERM; 5164 goto out; 5165 } 5166 } 5167 error = -1; 5168 goto out; 5169 } 5170 5171 NFSUNLOCKSTATE(); 5172 /* 5173 * Ok, we can delete the expired delegation. 5174 * First, write the Revoke record to stable storage and then 5175 * clear out the conflict. 5176 * Since all other nfsd threads are now blocked, we can safely 5177 * sleep without the state changing. 5178 */ 5179 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 5180 nfsrv_backupstable(); 5181 if (clp->lc_expiry < NFSD_MONOSEC) { 5182 nfsrv_cleanclient(clp, p); 5183 nfsrv_freedeleglist(&clp->lc_deleg); 5184 nfsrv_freedeleglist(&clp->lc_olddeleg); 5185 LIST_REMOVE(clp, lc_hash); 5186 zapped_clp = 1; 5187 } else { 5188 nfsrv_freedeleg(stp); 5189 zapped_clp = 0; 5190 } 5191 if (zapped_clp) 5192 nfsrv_zapclient(clp, p); 5193 error = -1; 5194 5195 out: 5196 NFSEXITCODE(error); 5197 return (error); 5198 } 5199 5200 /* 5201 * Check for a remove allowed, if remove is set to 1 and get rid of 5202 * delegations. 5203 */ 5204 APPLESTATIC int 5205 nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p) 5206 { 5207 struct nfsstate *stp; 5208 struct nfslockfile *lfp; 5209 int error, haslock = 0; 5210 fhandle_t nfh; 5211 5212 /* 5213 * First, get the lock file structure. 5214 * (A return of -1 means no associated state, so remove ok.) 5215 */ 5216 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 5217 tryagain: 5218 NFSLOCKSTATE(); 5219 if (!error) 5220 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 5221 if (error) { 5222 NFSUNLOCKSTATE(); 5223 if (haslock) { 5224 NFSLOCKV4ROOTMUTEX(); 5225 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5226 NFSUNLOCKV4ROOTMUTEX(); 5227 } 5228 if (error == -1) 5229 error = 0; 5230 goto out; 5231 } 5232 5233 /* 5234 * Now, we must Recall any delegations. 5235 */ 5236 error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p); 5237 if (error) { 5238 /* 5239 * nfsrv_cleandeleg() unlocks state for non-zero 5240 * return. 5241 */ 5242 if (error == -1) 5243 goto tryagain; 5244 if (haslock) { 5245 NFSLOCKV4ROOTMUTEX(); 5246 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5247 NFSUNLOCKV4ROOTMUTEX(); 5248 } 5249 goto out; 5250 } 5251 5252 /* 5253 * Now, look for a conflicting open share. 5254 */ 5255 if (remove) { 5256 /* 5257 * If the entry in the directory was the last reference to the 5258 * corresponding filesystem object, the object can be destroyed 5259 * */ 5260 if(lfp->lf_usecount>1) 5261 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 5262 if (stp->ls_flags & NFSLCK_WRITEDENY) { 5263 error = NFSERR_FILEOPEN; 5264 break; 5265 } 5266 } 5267 } 5268 5269 NFSUNLOCKSTATE(); 5270 if (haslock) { 5271 NFSLOCKV4ROOTMUTEX(); 5272 nfsv4_unlock(&nfsv4rootfs_lock, 1); 5273 NFSUNLOCKV4ROOTMUTEX(); 5274 } 5275 5276 out: 5277 NFSEXITCODE(error); 5278 return (error); 5279 } 5280 5281 /* 5282 * Clear out all delegations for the file referred to by lfp. 5283 * May return NFSERR_DELAY, if there will be a delay waiting for 5284 * delegations to expire. 5285 * Returns -1 to indicate it slept while recalling a delegation. 5286 * This function has the side effect of deleting the nfslockfile structure, 5287 * if it no longer has associated state and didn't have to sleep. 5288 * Unlocks State before a non-zero value is returned. 5289 */ 5290 static int 5291 nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 5292 struct nfsclient *clp, int *haslockp, NFSPROC_T *p) 5293 { 5294 struct nfsstate *stp, *nstp; 5295 int ret = 0; 5296 5297 stp = LIST_FIRST(&lfp->lf_deleg); 5298 while (stp != LIST_END(&lfp->lf_deleg)) { 5299 nstp = LIST_NEXT(stp, ls_file); 5300 if (stp->ls_clp != clp) { 5301 ret = nfsrv_delegconflict(stp, haslockp, p, vp); 5302 if (ret) { 5303 /* 5304 * nfsrv_delegconflict() unlocks state 5305 * when it returns non-zero. 5306 */ 5307 goto out; 5308 } 5309 } 5310 stp = nstp; 5311 } 5312 out: 5313 NFSEXITCODE(ret); 5314 return (ret); 5315 } 5316 5317 /* 5318 * There are certain operations that, when being done outside of NFSv4, 5319 * require that any NFSv4 delegation for the file be recalled. 5320 * This function is to be called for those cases: 5321 * VOP_RENAME() - When a delegation is being recalled for any reason, 5322 * the client may have to do Opens against the server, using the file's 5323 * final component name. If the file has been renamed on the server, 5324 * that component name will be incorrect and the Open will fail. 5325 * VOP_REMOVE() - Theoretically, a client could Open a file after it has 5326 * been removed on the server, if there is a delegation issued to 5327 * that client for the file. I say "theoretically" since clients 5328 * normally do an Access Op before the Open and that Access Op will 5329 * fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so 5330 * they will detect the file's removal in the same manner. (There is 5331 * one case where RFC3530 allows a client to do an Open without first 5332 * doing an Access Op, which is passage of a check against the ACE 5333 * returned with a Write delegation, but current practice is to ignore 5334 * the ACE and always do an Access Op.) 5335 * Since the functions can only be called with an unlocked vnode, this 5336 * can't be done at this time. 5337 * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range 5338 * locks locally in the client, which are not visible to the server. To 5339 * deal with this, issuing of delegations for a vnode must be disabled 5340 * and all delegations for the vnode recalled. This is done via the 5341 * second function, using the VV_DISABLEDELEG vflag on the vnode. 5342 */ 5343 APPLESTATIC void 5344 nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p) 5345 { 5346 time_t starttime; 5347 int error; 5348 5349 /* 5350 * First, check to see if the server is currently running and it has 5351 * been called for a regular file when issuing delegations. 5352 */ 5353 if (newnfs_numnfsd == 0 || vp->v_type != VREG || 5354 nfsrv_issuedelegs == 0) 5355 return; 5356 5357 KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp)); 5358 /* 5359 * First, get a reference on the nfsv4rootfs_lock so that an 5360 * exclusive lock cannot be acquired by another thread. 5361 */ 5362 NFSLOCKV4ROOTMUTEX(); 5363 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); 5364 NFSUNLOCKV4ROOTMUTEX(); 5365 5366 /* 5367 * Now, call nfsrv_checkremove() in a loop while it returns 5368 * NFSERR_DELAY. Return upon any other error or when timed out. 5369 */ 5370 starttime = NFSD_MONOSEC; 5371 do { 5372 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) { 5373 error = nfsrv_checkremove(vp, 0, p); 5374 NFSVOPUNLOCK(vp, 0); 5375 } else 5376 error = EPERM; 5377 if (error == NFSERR_DELAY) { 5378 if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO) 5379 break; 5380 /* Sleep for a short period of time */ 5381 (void) nfs_catnap(PZERO, 0, "nfsremove"); 5382 } 5383 } while (error == NFSERR_DELAY); 5384 NFSLOCKV4ROOTMUTEX(); 5385 nfsv4_relref(&nfsv4rootfs_lock); 5386 NFSUNLOCKV4ROOTMUTEX(); 5387 } 5388 5389 APPLESTATIC void 5390 nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p) 5391 { 5392 5393 #ifdef VV_DISABLEDELEG 5394 /* 5395 * First, flag issuance of delegations disabled. 5396 */ 5397 atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG); 5398 #endif 5399 5400 /* 5401 * Then call nfsd_recalldelegation() to get rid of all extant 5402 * delegations. 5403 */ 5404 nfsd_recalldelegation(vp, p); 5405 } 5406 5407 /* 5408 * Check for conflicting locks, etc. and then get rid of delegations. 5409 * (At one point I thought that I should get rid of delegations for any 5410 * Setattr, since it could potentially disallow the I/O op (read or write) 5411 * allowed by the delegation. However, Setattr Ops that aren't changing 5412 * the size get a stateid of all 0s, so you can't tell if it is a delegation 5413 * for the same client or a different one, so I decided to only get rid 5414 * of delegations for other clients when the size is being changed.) 5415 * In general, a Setattr can disable NFS I/O Ops that are outstanding, such 5416 * as Write backs, even if there is no delegation, so it really isn't any 5417 * different?) 5418 */ 5419 APPLESTATIC int 5420 nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd, 5421 nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp, 5422 struct nfsexstuff *exp, NFSPROC_T *p) 5423 { 5424 struct nfsstate st, *stp = &st; 5425 struct nfslock lo, *lop = &lo; 5426 int error = 0; 5427 nfsquad_t clientid; 5428 5429 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) { 5430 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 5431 lop->lo_first = nvap->na_size; 5432 } else { 5433 stp->ls_flags = 0; 5434 lop->lo_first = 0; 5435 } 5436 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) || 5437 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) || 5438 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) || 5439 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL)) 5440 stp->ls_flags |= NFSLCK_SETATTR; 5441 if (stp->ls_flags == 0) 5442 goto out; 5443 lop->lo_end = NFS64BITSSET; 5444 lop->lo_flags = NFSLCK_WRITE; 5445 stp->ls_ownerlen = 0; 5446 stp->ls_op = NULL; 5447 stp->ls_uid = nd->nd_cred->cr_uid; 5448 stp->ls_stateid.seqid = stateidp->seqid; 5449 clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0]; 5450 clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1]; 5451 stp->ls_stateid.other[2] = stateidp->other[2]; 5452 error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 5453 stateidp, exp, nd, p); 5454 5455 out: 5456 NFSEXITCODE2(error, nd); 5457 return (error); 5458 } 5459 5460 /* 5461 * Check for a write delegation and do a CBGETATTR if there is one, updating 5462 * the attributes, as required. 5463 * Should I return an error if I can't get the attributes? (For now, I'll 5464 * just return ok. 5465 */ 5466 APPLESTATIC int 5467 nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp, 5468 struct nfsvattr *nvap, nfsattrbit_t *attrbitp, NFSPROC_T *p) 5469 { 5470 struct nfsstate *stp; 5471 struct nfslockfile *lfp; 5472 struct nfsclient *clp; 5473 struct nfsvattr nva; 5474 fhandle_t nfh; 5475 int error = 0; 5476 nfsattrbit_t cbbits; 5477 u_quad_t delegfilerev; 5478 5479 NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits); 5480 if (!NFSNONZERO_ATTRBIT(&cbbits)) 5481 goto out; 5482 if (nfsrv_writedelegcnt == 0) 5483 goto out; 5484 5485 /* 5486 * Get the lock file structure. 5487 * (A return of -1 means no associated state, so return ok.) 5488 */ 5489 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 5490 NFSLOCKSTATE(); 5491 if (!error) 5492 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 5493 if (error) { 5494 NFSUNLOCKSTATE(); 5495 if (error == -1) 5496 error = 0; 5497 goto out; 5498 } 5499 5500 /* 5501 * Now, look for a write delegation. 5502 */ 5503 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 5504 if (stp->ls_flags & NFSLCK_DELEGWRITE) 5505 break; 5506 } 5507 if (stp == LIST_END(&lfp->lf_deleg)) { 5508 NFSUNLOCKSTATE(); 5509 goto out; 5510 } 5511 clp = stp->ls_clp; 5512 delegfilerev = stp->ls_filerev; 5513 5514 /* 5515 * If the Write delegation was issued as a part of this Compound RPC 5516 * or if we have an Implied Clientid (used in a previous Op in this 5517 * compound) and it is the client the delegation was issued to, 5518 * just return ok. 5519 * I also assume that it is from the same client iff the network 5520 * host IP address is the same as the callback address. (Not 5521 * exactly correct by the RFC, but avoids a lot of Getattr 5522 * callbacks.) 5523 */ 5524 if (nd->nd_compref == stp->ls_compref || 5525 ((nd->nd_flag & ND_IMPLIEDCLID) && 5526 clp->lc_clientid.qval == nd->nd_clientid.qval) || 5527 nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) { 5528 NFSUNLOCKSTATE(); 5529 goto out; 5530 } 5531 5532 /* 5533 * We are now done with the delegation state structure, 5534 * so the statelock can be released and we can now tsleep(). 5535 */ 5536 5537 /* 5538 * Now, we must do the CB Getattr callback, to see if Change or Size 5539 * has changed. 5540 */ 5541 if (clp->lc_expiry >= NFSD_MONOSEC) { 5542 NFSUNLOCKSTATE(); 5543 NFSVNO_ATTRINIT(&nva); 5544 nva.na_filerev = NFS64BITSSET; 5545 error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL, 5546 0, &nfh, &nva, &cbbits, 0, p); 5547 if (!error) { 5548 if ((nva.na_filerev != NFS64BITSSET && 5549 nva.na_filerev > delegfilerev) || 5550 (NFSVNO_ISSETSIZE(&nva) && 5551 nva.na_size != nvap->na_size)) { 5552 error = nfsvno_updfilerev(vp, nvap, nd, p); 5553 if (NFSVNO_ISSETSIZE(&nva)) 5554 nvap->na_size = nva.na_size; 5555 } 5556 } else 5557 error = 0; /* Ignore callback errors for now. */ 5558 } else { 5559 NFSUNLOCKSTATE(); 5560 } 5561 5562 out: 5563 NFSEXITCODE2(error, nd); 5564 return (error); 5565 } 5566 5567 /* 5568 * This function looks for openowners that haven't had any opens for 5569 * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS 5570 * is set. 5571 */ 5572 APPLESTATIC void 5573 nfsrv_throwawayopens(NFSPROC_T *p) 5574 { 5575 struct nfsclient *clp, *nclp; 5576 struct nfsstate *stp, *nstp; 5577 int i; 5578 5579 NFSLOCKSTATE(); 5580 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS; 5581 /* 5582 * For each client... 5583 */ 5584 for (i = 0; i < nfsrv_clienthashsize; i++) { 5585 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 5586 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { 5587 if (LIST_EMPTY(&stp->ls_open) && 5588 (stp->ls_noopens > NFSNOOPEN || 5589 (nfsrv_openpluslock * 2) > 5590 nfsrv_v4statelimit)) 5591 nfsrv_freeopenowner(stp, 0, p); 5592 } 5593 } 5594 } 5595 NFSUNLOCKSTATE(); 5596 } 5597 5598 /* 5599 * This function checks to see if the credentials are the same. 5600 * Returns 1 for not same, 0 otherwise. 5601 */ 5602 static int 5603 nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp) 5604 { 5605 5606 if (nd->nd_flag & ND_GSS) { 5607 if (!(clp->lc_flags & LCL_GSS)) 5608 return (1); 5609 if (clp->lc_flags & LCL_NAME) { 5610 if (nd->nd_princlen != clp->lc_namelen || 5611 NFSBCMP(nd->nd_principal, clp->lc_name, 5612 clp->lc_namelen)) 5613 return (1); 5614 else 5615 return (0); 5616 } 5617 if (nd->nd_cred->cr_uid == clp->lc_uid) 5618 return (0); 5619 else 5620 return (1); 5621 } else if (clp->lc_flags & LCL_GSS) 5622 return (1); 5623 /* 5624 * For AUTH_SYS, allow the same uid or root. (This is underspecified 5625 * in RFC3530, which talks about principals, but doesn't say anything 5626 * about uids for AUTH_SYS.) 5627 */ 5628 if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0) 5629 return (0); 5630 else 5631 return (1); 5632 } 5633 5634 /* 5635 * Calculate the lease expiry time. 5636 */ 5637 static time_t 5638 nfsrv_leaseexpiry(void) 5639 { 5640 5641 if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC) 5642 return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA)); 5643 return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA); 5644 } 5645 5646 /* 5647 * Delay the delegation timeout as far as ls_delegtimelimit, as required. 5648 */ 5649 static void 5650 nfsrv_delaydelegtimeout(struct nfsstate *stp) 5651 { 5652 5653 if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0) 5654 return; 5655 5656 if ((stp->ls_delegtime + 15) > NFSD_MONOSEC && 5657 stp->ls_delegtime < stp->ls_delegtimelimit) { 5658 stp->ls_delegtime += nfsrv_lease; 5659 if (stp->ls_delegtime > stp->ls_delegtimelimit) 5660 stp->ls_delegtime = stp->ls_delegtimelimit; 5661 } 5662 } 5663 5664 /* 5665 * This function checks to see if there is any other state associated 5666 * with the openowner for this Open. 5667 * It returns 1 if there is no other state, 0 otherwise. 5668 */ 5669 static int 5670 nfsrv_nootherstate(struct nfsstate *stp) 5671 { 5672 struct nfsstate *tstp; 5673 5674 LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) { 5675 if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock)) 5676 return (0); 5677 } 5678 return (1); 5679 } 5680 5681 /* 5682 * Create a list of lock deltas (changes to local byte range locking 5683 * that can be rolled back using the list) and apply the changes via 5684 * nfsvno_advlock(). Optionally, lock the list. It is expected that either 5685 * the rollback or update function will be called after this. 5686 * It returns an error (and rolls back, as required), if any nfsvno_advlock() 5687 * call fails. If it returns an error, it will unlock the list. 5688 */ 5689 static int 5690 nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, 5691 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5692 { 5693 struct nfslock *lop, *nlop; 5694 int error = 0; 5695 5696 /* Loop through the list of locks. */ 5697 lop = LIST_FIRST(&lfp->lf_locallock); 5698 while (first < end && lop != NULL) { 5699 nlop = LIST_NEXT(lop, lo_lckowner); 5700 if (first >= lop->lo_end) { 5701 /* not there yet */ 5702 lop = nlop; 5703 } else if (first < lop->lo_first) { 5704 /* new one starts before entry in list */ 5705 if (end <= lop->lo_first) { 5706 /* no overlap between old and new */ 5707 error = nfsrv_dolocal(vp, lfp, flags, 5708 NFSLCK_UNLOCK, first, end, cfp, p); 5709 if (error != 0) 5710 break; 5711 first = end; 5712 } else { 5713 /* handle fragment overlapped with new one */ 5714 error = nfsrv_dolocal(vp, lfp, flags, 5715 NFSLCK_UNLOCK, first, lop->lo_first, cfp, 5716 p); 5717 if (error != 0) 5718 break; 5719 first = lop->lo_first; 5720 } 5721 } else { 5722 /* new one overlaps this entry in list */ 5723 if (end <= lop->lo_end) { 5724 /* overlaps all of new one */ 5725 error = nfsrv_dolocal(vp, lfp, flags, 5726 lop->lo_flags, first, end, cfp, p); 5727 if (error != 0) 5728 break; 5729 first = end; 5730 } else { 5731 /* handle fragment overlapped with new one */ 5732 error = nfsrv_dolocal(vp, lfp, flags, 5733 lop->lo_flags, first, lop->lo_end, cfp, p); 5734 if (error != 0) 5735 break; 5736 first = lop->lo_end; 5737 lop = nlop; 5738 } 5739 } 5740 } 5741 if (first < end && error == 0) 5742 /* handle fragment past end of list */ 5743 error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first, 5744 end, cfp, p); 5745 5746 NFSEXITCODE(error); 5747 return (error); 5748 } 5749 5750 /* 5751 * Local lock unlock. Unlock all byte ranges that are no longer locked 5752 * by NFSv4. To do this, unlock any subranges of first-->end that 5753 * do not overlap with the byte ranges of any lock in the lfp->lf_lock 5754 * list. This list has all locks for the file held by other 5755 * <clientid, lockowner> tuples. The list is ordered by increasing 5756 * lo_first value, but may have entries that overlap each other, for 5757 * the case of read locks. 5758 */ 5759 static void 5760 nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first, 5761 uint64_t init_end, NFSPROC_T *p) 5762 { 5763 struct nfslock *lop; 5764 uint64_t first, end, prevfirst; 5765 5766 first = init_first; 5767 end = init_end; 5768 while (first < init_end) { 5769 /* Loop through all nfs locks, adjusting first and end */ 5770 prevfirst = 0; 5771 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { 5772 KASSERT(prevfirst <= lop->lo_first, 5773 ("nfsv4 locks out of order")); 5774 KASSERT(lop->lo_first < lop->lo_end, 5775 ("nfsv4 bogus lock")); 5776 prevfirst = lop->lo_first; 5777 if (first >= lop->lo_first && 5778 first < lop->lo_end) 5779 /* 5780 * Overlaps with initial part, so trim 5781 * off that initial part by moving first past 5782 * it. 5783 */ 5784 first = lop->lo_end; 5785 else if (end > lop->lo_first && 5786 lop->lo_first > first) { 5787 /* 5788 * This lock defines the end of the 5789 * segment to unlock, so set end to the 5790 * start of it and break out of the loop. 5791 */ 5792 end = lop->lo_first; 5793 break; 5794 } 5795 if (first >= end) 5796 /* 5797 * There is no segment left to do, so 5798 * break out of this loop and then exit 5799 * the outer while() since first will be set 5800 * to end, which must equal init_end here. 5801 */ 5802 break; 5803 } 5804 if (first < end) { 5805 /* Unlock this segment */ 5806 (void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK, 5807 NFSLCK_READ, first, end, NULL, p); 5808 nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK, 5809 first, end); 5810 } 5811 /* 5812 * Now move past this segment and look for any further 5813 * segment in the range, if there is one. 5814 */ 5815 first = end; 5816 end = init_end; 5817 } 5818 } 5819 5820 /* 5821 * Do the local lock operation and update the rollback list, as required. 5822 * Perform the rollback and return the error if nfsvno_advlock() fails. 5823 */ 5824 static int 5825 nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags, 5826 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5827 { 5828 struct nfsrollback *rlp; 5829 int error = 0, ltype, oldltype; 5830 5831 if (flags & NFSLCK_WRITE) 5832 ltype = F_WRLCK; 5833 else if (flags & NFSLCK_READ) 5834 ltype = F_RDLCK; 5835 else 5836 ltype = F_UNLCK; 5837 if (oldflags & NFSLCK_WRITE) 5838 oldltype = F_WRLCK; 5839 else if (oldflags & NFSLCK_READ) 5840 oldltype = F_RDLCK; 5841 else 5842 oldltype = F_UNLCK; 5843 if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK)) 5844 /* nothing to do */ 5845 goto out; 5846 error = nfsvno_advlock(vp, ltype, first, end, p); 5847 if (error != 0) { 5848 if (cfp != NULL) { 5849 cfp->cl_clientid.lval[0] = 0; 5850 cfp->cl_clientid.lval[1] = 0; 5851 cfp->cl_first = 0; 5852 cfp->cl_end = NFS64BITSSET; 5853 cfp->cl_flags = NFSLCK_WRITE; 5854 cfp->cl_ownerlen = 5; 5855 NFSBCOPY("LOCAL", cfp->cl_owner, 5); 5856 } 5857 nfsrv_locallock_rollback(vp, lfp, p); 5858 } else if (ltype != F_UNLCK) { 5859 rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK, 5860 M_WAITOK); 5861 rlp->rlck_first = first; 5862 rlp->rlck_end = end; 5863 rlp->rlck_type = oldltype; 5864 LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list); 5865 } 5866 5867 out: 5868 NFSEXITCODE(error); 5869 return (error); 5870 } 5871 5872 /* 5873 * Roll back local lock changes and free up the rollback list. 5874 */ 5875 static void 5876 nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p) 5877 { 5878 struct nfsrollback *rlp, *nrlp; 5879 5880 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) { 5881 (void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first, 5882 rlp->rlck_end, p); 5883 free(rlp, M_NFSDROLLBACK); 5884 } 5885 LIST_INIT(&lfp->lf_rollback); 5886 } 5887 5888 /* 5889 * Update local lock list and delete rollback list (ie now committed to the 5890 * local locks). Most of the work is done by the internal function. 5891 */ 5892 static void 5893 nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first, 5894 uint64_t end) 5895 { 5896 struct nfsrollback *rlp, *nrlp; 5897 struct nfslock *new_lop, *other_lop; 5898 5899 new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK); 5900 if (flags & (NFSLCK_READ | NFSLCK_WRITE)) 5901 other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, 5902 M_WAITOK); 5903 else 5904 other_lop = NULL; 5905 new_lop->lo_flags = flags; 5906 new_lop->lo_first = first; 5907 new_lop->lo_end = end; 5908 nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp); 5909 if (new_lop != NULL) 5910 free(new_lop, M_NFSDLOCK); 5911 if (other_lop != NULL) 5912 free(other_lop, M_NFSDLOCK); 5913 5914 /* and get rid of the rollback list */ 5915 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) 5916 free(rlp, M_NFSDROLLBACK); 5917 LIST_INIT(&lfp->lf_rollback); 5918 } 5919 5920 /* 5921 * Lock the struct nfslockfile for local lock updating. 5922 */ 5923 static void 5924 nfsrv_locklf(struct nfslockfile *lfp) 5925 { 5926 int gotlock; 5927 5928 /* lf_usecount ensures *lfp won't be free'd */ 5929 lfp->lf_usecount++; 5930 do { 5931 gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL, 5932 NFSSTATEMUTEXPTR, NULL); 5933 } while (gotlock == 0); 5934 lfp->lf_usecount--; 5935 } 5936 5937 /* 5938 * Unlock the struct nfslockfile after local lock updating. 5939 */ 5940 static void 5941 nfsrv_unlocklf(struct nfslockfile *lfp) 5942 { 5943 5944 nfsv4_unlock(&lfp->lf_locallock_lck, 0); 5945 } 5946 5947 /* 5948 * Clear out all state for the NFSv4 server. 5949 * Must be called by a thread that can sleep when no nfsds are running. 5950 */ 5951 void 5952 nfsrv_throwawayallstate(NFSPROC_T *p) 5953 { 5954 struct nfsclient *clp, *nclp; 5955 struct nfslockfile *lfp, *nlfp; 5956 int i; 5957 5958 /* 5959 * For each client, clean out the state and then free the structure. 5960 */ 5961 for (i = 0; i < nfsrv_clienthashsize; i++) { 5962 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 5963 nfsrv_cleanclient(clp, p); 5964 nfsrv_freedeleglist(&clp->lc_deleg); 5965 nfsrv_freedeleglist(&clp->lc_olddeleg); 5966 free(clp->lc_stateid, M_NFSDCLIENT); 5967 free(clp, M_NFSDCLIENT); 5968 } 5969 } 5970 5971 /* 5972 * Also, free up any remaining lock file structures. 5973 */ 5974 for (i = 0; i < nfsrv_lockhashsize; i++) { 5975 LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) { 5976 printf("nfsd unload: fnd a lock file struct\n"); 5977 nfsrv_freenfslockfile(lfp); 5978 } 5979 } 5980 5981 /* And get rid of the deviceid structures and layouts. */ 5982 nfsrv_freealllayoutsanddevids(); 5983 } 5984 5985 /* 5986 * Check the sequence# for the session and slot provided as an argument. 5987 * Also, renew the lease if the session will return NFS_OK. 5988 */ 5989 int 5990 nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid, 5991 uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this, 5992 uint32_t *sflagsp, NFSPROC_T *p) 5993 { 5994 struct nfsdsession *sep; 5995 struct nfssessionhash *shp; 5996 int error; 5997 SVCXPRT *savxprt; 5998 5999 shp = NFSSESSIONHASH(nd->nd_sessionid); 6000 NFSLOCKSESSION(shp); 6001 sep = nfsrv_findsession(nd->nd_sessionid); 6002 if (sep == NULL) { 6003 NFSUNLOCKSESSION(shp); 6004 return (NFSERR_BADSESSION); 6005 } 6006 error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp, 6007 sep->sess_slots, NULL, NFSV4_SLOTS - 1); 6008 if (error != 0) { 6009 NFSUNLOCKSESSION(shp); 6010 return (error); 6011 } 6012 if (cache_this != 0) 6013 nd->nd_flag |= ND_SAVEREPLY; 6014 /* Renew the lease. */ 6015 sep->sess_clp->lc_expiry = nfsrv_leaseexpiry(); 6016 nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval; 6017 nd->nd_flag |= ND_IMPLIEDCLID; 6018 6019 /* 6020 * If this session handles the backchannel, save the nd_xprt for this 6021 * RPC, since this is the one being used. 6022 * RFC-5661 specifies that the fore channel will be implicitly 6023 * bound by a Sequence operation. However, since some NFSv4.1 clients 6024 * erroneously assumed that the back channel would be implicitly 6025 * bound as well, do the implicit binding unless a 6026 * BindConnectiontoSession has already been done on the session. 6027 */ 6028 if (sep->sess_clp->lc_req.nr_client != NULL && 6029 sep->sess_cbsess.nfsess_xprt != nd->nd_xprt && 6030 (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0 && 6031 (sep->sess_clp->lc_flags & LCL_DONEBINDCONN) == 0) { 6032 NFSD_DEBUG(2, 6033 "nfsrv_checksequence: implicit back channel bind\n"); 6034 savxprt = sep->sess_cbsess.nfsess_xprt; 6035 SVC_ACQUIRE(nd->nd_xprt); 6036 nd->nd_xprt->xp_p2 = 6037 sep->sess_clp->lc_req.nr_client->cl_private; 6038 nd->nd_xprt->xp_idletimeout = 0; /* Disable timeout. */ 6039 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt; 6040 if (savxprt != NULL) 6041 SVC_RELEASE(savxprt); 6042 } 6043 6044 *sflagsp = 0; 6045 if (sep->sess_clp->lc_req.nr_client == NULL) 6046 *sflagsp |= NFSV4SEQ_CBPATHDOWN; 6047 NFSUNLOCKSESSION(shp); 6048 if (error == NFSERR_EXPIRED) { 6049 *sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED; 6050 error = 0; 6051 } else if (error == NFSERR_ADMINREVOKED) { 6052 *sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED; 6053 error = 0; 6054 } 6055 *highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1; 6056 return (0); 6057 } 6058 6059 /* 6060 * Check/set reclaim complete for this session/clientid. 6061 */ 6062 int 6063 nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd) 6064 { 6065 struct nfsdsession *sep; 6066 struct nfssessionhash *shp; 6067 int error = 0; 6068 6069 shp = NFSSESSIONHASH(nd->nd_sessionid); 6070 NFSLOCKSTATE(); 6071 NFSLOCKSESSION(shp); 6072 sep = nfsrv_findsession(nd->nd_sessionid); 6073 if (sep == NULL) { 6074 NFSUNLOCKSESSION(shp); 6075 NFSUNLOCKSTATE(); 6076 return (NFSERR_BADSESSION); 6077 } 6078 6079 /* Check to see if reclaim complete has already happened. */ 6080 if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) 6081 error = NFSERR_COMPLETEALREADY; 6082 else { 6083 sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE; 6084 nfsrv_markreclaim(sep->sess_clp); 6085 } 6086 NFSUNLOCKSESSION(shp); 6087 NFSUNLOCKSTATE(); 6088 return (error); 6089 } 6090 6091 /* 6092 * Cache the reply in a session slot. 6093 */ 6094 void 6095 nfsrv_cache_session(uint8_t *sessionid, uint32_t slotid, int repstat, 6096 struct mbuf **m) 6097 { 6098 struct nfsdsession *sep; 6099 struct nfssessionhash *shp; 6100 6101 shp = NFSSESSIONHASH(sessionid); 6102 NFSLOCKSESSION(shp); 6103 sep = nfsrv_findsession(sessionid); 6104 if (sep == NULL) { 6105 NFSUNLOCKSESSION(shp); 6106 printf("nfsrv_cache_session: no session\n"); 6107 m_freem(*m); 6108 return; 6109 } 6110 nfsv4_seqsess_cacherep(slotid, sep->sess_slots, repstat, m); 6111 NFSUNLOCKSESSION(shp); 6112 } 6113 6114 /* 6115 * Search for a session that matches the sessionid. 6116 */ 6117 static struct nfsdsession * 6118 nfsrv_findsession(uint8_t *sessionid) 6119 { 6120 struct nfsdsession *sep; 6121 struct nfssessionhash *shp; 6122 6123 shp = NFSSESSIONHASH(sessionid); 6124 LIST_FOREACH(sep, &shp->list, sess_hash) { 6125 if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID)) 6126 break; 6127 } 6128 return (sep); 6129 } 6130 6131 /* 6132 * Destroy a session. 6133 */ 6134 int 6135 nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid) 6136 { 6137 int error, igotlock, samesess; 6138 6139 samesess = 0; 6140 if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID) && 6141 (nd->nd_flag & ND_HASSEQUENCE) != 0) { 6142 samesess = 1; 6143 if ((nd->nd_flag & ND_LASTOP) == 0) 6144 return (NFSERR_BADSESSION); 6145 } 6146 6147 /* Lock out other nfsd threads */ 6148 NFSLOCKV4ROOTMUTEX(); 6149 nfsv4_relref(&nfsv4rootfs_lock); 6150 do { 6151 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 6152 NFSV4ROOTLOCKMUTEXPTR, NULL); 6153 } while (igotlock == 0); 6154 NFSUNLOCKV4ROOTMUTEX(); 6155 6156 error = nfsrv_freesession(NULL, sessionid); 6157 if (error == 0 && samesess != 0) 6158 nd->nd_flag &= ~ND_HASSEQUENCE; 6159 6160 NFSLOCKV4ROOTMUTEX(); 6161 nfsv4_unlock(&nfsv4rootfs_lock, 1); 6162 NFSUNLOCKV4ROOTMUTEX(); 6163 return (error); 6164 } 6165 6166 /* 6167 * Bind a connection to a session. 6168 * For now, only certain variants are supported, since the current session 6169 * structure can only handle a single backchannel entry, which will be 6170 * applied to all connections if it is set. 6171 */ 6172 int 6173 nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp) 6174 { 6175 struct nfssessionhash *shp; 6176 struct nfsdsession *sep; 6177 struct nfsclient *clp; 6178 SVCXPRT *savxprt; 6179 int error; 6180 6181 error = 0; 6182 shp = NFSSESSIONHASH(sessionid); 6183 NFSLOCKSTATE(); 6184 NFSLOCKSESSION(shp); 6185 sep = nfsrv_findsession(sessionid); 6186 if (sep != NULL) { 6187 clp = sep->sess_clp; 6188 if (*foreaftp == NFSCDFC4_BACK || 6189 *foreaftp == NFSCDFC4_BACK_OR_BOTH || 6190 *foreaftp == NFSCDFC4_FORE_OR_BOTH) { 6191 /* Try to set up a backchannel. */ 6192 if (clp->lc_req.nr_client == NULL) { 6193 NFSD_DEBUG(2, "nfsrv_bindconnsess: acquire " 6194 "backchannel\n"); 6195 clp->lc_req.nr_client = (struct __rpc_client *) 6196 clnt_bck_create(nd->nd_xprt->xp_socket, 6197 sep->sess_cbprogram, NFSV4_CBVERS); 6198 } 6199 if (clp->lc_req.nr_client != NULL) { 6200 NFSD_DEBUG(2, "nfsrv_bindconnsess: set up " 6201 "backchannel\n"); 6202 savxprt = sep->sess_cbsess.nfsess_xprt; 6203 SVC_ACQUIRE(nd->nd_xprt); 6204 nd->nd_xprt->xp_p2 = 6205 clp->lc_req.nr_client->cl_private; 6206 /* Disable idle timeout. */ 6207 nd->nd_xprt->xp_idletimeout = 0; 6208 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt; 6209 if (savxprt != NULL) 6210 SVC_RELEASE(savxprt); 6211 sep->sess_crflags |= NFSV4CRSESS_CONNBACKCHAN; 6212 clp->lc_flags |= LCL_DONEBINDCONN; 6213 if (*foreaftp == NFSCDFS4_BACK) 6214 *foreaftp = NFSCDFS4_BACK; 6215 else 6216 *foreaftp = NFSCDFS4_BOTH; 6217 } else if (*foreaftp != NFSCDFC4_BACK) { 6218 NFSD_DEBUG(2, "nfsrv_bindconnsess: can't set " 6219 "up backchannel\n"); 6220 sep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN; 6221 clp->lc_flags |= LCL_DONEBINDCONN; 6222 *foreaftp = NFSCDFS4_FORE; 6223 } else { 6224 error = NFSERR_NOTSUPP; 6225 printf("nfsrv_bindconnsess: Can't add " 6226 "backchannel\n"); 6227 } 6228 } else { 6229 NFSD_DEBUG(2, "nfsrv_bindconnsess: Set forechannel\n"); 6230 clp->lc_flags |= LCL_DONEBINDCONN; 6231 *foreaftp = NFSCDFS4_FORE; 6232 } 6233 } else 6234 error = NFSERR_BADSESSION; 6235 NFSUNLOCKSESSION(shp); 6236 NFSUNLOCKSTATE(); 6237 return (error); 6238 } 6239 6240 /* 6241 * Free up a session structure. 6242 */ 6243 static int 6244 nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid) 6245 { 6246 struct nfssessionhash *shp; 6247 int i; 6248 6249 NFSLOCKSTATE(); 6250 if (sep == NULL) { 6251 shp = NFSSESSIONHASH(sessionid); 6252 NFSLOCKSESSION(shp); 6253 sep = nfsrv_findsession(sessionid); 6254 } else { 6255 shp = NFSSESSIONHASH(sep->sess_sessionid); 6256 NFSLOCKSESSION(shp); 6257 } 6258 if (sep != NULL) { 6259 sep->sess_refcnt--; 6260 if (sep->sess_refcnt > 0) { 6261 NFSUNLOCKSESSION(shp); 6262 NFSUNLOCKSTATE(); 6263 return (NFSERR_BACKCHANBUSY); 6264 } 6265 LIST_REMOVE(sep, sess_hash); 6266 LIST_REMOVE(sep, sess_list); 6267 } 6268 NFSUNLOCKSESSION(shp); 6269 NFSUNLOCKSTATE(); 6270 if (sep == NULL) 6271 return (NFSERR_BADSESSION); 6272 for (i = 0; i < NFSV4_SLOTS; i++) 6273 if (sep->sess_slots[i].nfssl_reply != NULL) 6274 m_freem(sep->sess_slots[i].nfssl_reply); 6275 if (sep->sess_cbsess.nfsess_xprt != NULL) 6276 SVC_RELEASE(sep->sess_cbsess.nfsess_xprt); 6277 free(sep, M_NFSDSESSION); 6278 return (0); 6279 } 6280 6281 /* 6282 * Free a stateid. 6283 * RFC5661 says that it should fail when there are associated opens, locks 6284 * or delegations. Since stateids represent opens, I don't see how you can 6285 * free an open stateid (it will be free'd when closed), so this function 6286 * only works for lock stateids (freeing the lock_owner) or delegations. 6287 */ 6288 int 6289 nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, 6290 NFSPROC_T *p) 6291 { 6292 struct nfsclient *clp; 6293 struct nfsstate *stp; 6294 int error; 6295 6296 NFSLOCKSTATE(); 6297 /* 6298 * Look up the stateid 6299 */ 6300 error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp, 6301 NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); 6302 if (error == 0) { 6303 /* First, check for a delegation. */ 6304 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) { 6305 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other, 6306 NFSX_STATEIDOTHER)) 6307 break; 6308 } 6309 if (stp != NULL) { 6310 nfsrv_freedeleg(stp); 6311 NFSUNLOCKSTATE(); 6312 return (error); 6313 } 6314 } 6315 /* Not a delegation, try for a lock_owner. */ 6316 if (error == 0) 6317 error = nfsrv_getstate(clp, stateidp, 0, &stp); 6318 if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD | 6319 NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0)) 6320 /* Not a lock_owner stateid. */ 6321 error = NFSERR_LOCKSHELD; 6322 if (error == 0 && !LIST_EMPTY(&stp->ls_lock)) 6323 error = NFSERR_LOCKSHELD; 6324 if (error == 0) 6325 nfsrv_freelockowner(stp, NULL, 0, p); 6326 NFSUNLOCKSTATE(); 6327 return (error); 6328 } 6329 6330 /* 6331 * Test a stateid. 6332 */ 6333 int 6334 nfsrv_teststateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, 6335 NFSPROC_T *p) 6336 { 6337 struct nfsclient *clp; 6338 struct nfsstate *stp; 6339 int error; 6340 6341 NFSLOCKSTATE(); 6342 /* 6343 * Look up the stateid 6344 */ 6345 error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp, 6346 NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); 6347 if (error == 0) 6348 error = nfsrv_getstate(clp, stateidp, 0, &stp); 6349 if (error == 0 && stateidp->seqid != 0 && 6350 SEQ_LT(stateidp->seqid, stp->ls_stateid.seqid)) 6351 error = NFSERR_OLDSTATEID; 6352 NFSUNLOCKSTATE(); 6353 return (error); 6354 } 6355 6356 /* 6357 * Generate the xdr for an NFSv4.1 CBSequence Operation. 6358 */ 6359 static int 6360 nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp, 6361 int dont_replycache, struct nfsdsession **sepp) 6362 { 6363 struct nfsdsession *sep; 6364 uint32_t *tl, slotseq = 0; 6365 int maxslot, slotpos; 6366 uint8_t sessionid[NFSX_V4SESSIONID]; 6367 int error; 6368 6369 error = nfsv4_getcbsession(clp, sepp); 6370 if (error != 0) 6371 return (error); 6372 sep = *sepp; 6373 (void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot, 6374 &slotseq, sessionid); 6375 KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot")); 6376 6377 /* Build the Sequence arguments. */ 6378 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED); 6379 bcopy(sessionid, tl, NFSX_V4SESSIONID); 6380 tl += NFSX_V4SESSIONID / NFSX_UNSIGNED; 6381 nd->nd_slotseq = tl; 6382 *tl++ = txdr_unsigned(slotseq); 6383 *tl++ = txdr_unsigned(slotpos); 6384 *tl++ = txdr_unsigned(maxslot); 6385 if (dont_replycache == 0) 6386 *tl++ = newnfs_true; 6387 else 6388 *tl++ = newnfs_false; 6389 *tl = 0; /* No referring call list, for now. */ 6390 nd->nd_flag |= ND_HASSEQUENCE; 6391 return (0); 6392 } 6393 6394 /* 6395 * Get a session for the callback. 6396 */ 6397 static int 6398 nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp) 6399 { 6400 struct nfsdsession *sep; 6401 6402 NFSLOCKSTATE(); 6403 LIST_FOREACH(sep, &clp->lc_session, sess_list) { 6404 if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) 6405 break; 6406 } 6407 if (sep == NULL) { 6408 NFSUNLOCKSTATE(); 6409 return (NFSERR_BADSESSION); 6410 } 6411 sep->sess_refcnt++; 6412 *sepp = sep; 6413 NFSUNLOCKSTATE(); 6414 return (0); 6415 } 6416 6417 /* 6418 * Free up all backchannel xprts. This needs to be done when the nfsd threads 6419 * exit, since those transports will all be going away. 6420 * This is only called after all the nfsd threads are done performing RPCs, 6421 * so locking shouldn't be an issue. 6422 */ 6423 APPLESTATIC void 6424 nfsrv_freeallbackchannel_xprts(void) 6425 { 6426 struct nfsdsession *sep; 6427 struct nfsclient *clp; 6428 SVCXPRT *xprt; 6429 int i; 6430 6431 for (i = 0; i < nfsrv_clienthashsize; i++) { 6432 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 6433 LIST_FOREACH(sep, &clp->lc_session, sess_list) { 6434 xprt = sep->sess_cbsess.nfsess_xprt; 6435 sep->sess_cbsess.nfsess_xprt = NULL; 6436 if (xprt != NULL) 6437 SVC_RELEASE(xprt); 6438 } 6439 } 6440 } 6441 } 6442 6443 /* 6444 * Do a layout commit. Actually just call nfsrv_updatemdsattr(). 6445 * I have no idea if the rest of these arguments will ever be useful? 6446 */ 6447 int 6448 nfsrv_layoutcommit(struct nfsrv_descript *nd, vnode_t vp, int layouttype, 6449 int hasnewoff, uint64_t newoff, uint64_t offset, uint64_t len, 6450 int hasnewmtime, struct timespec *newmtimep, int reclaim, 6451 nfsv4stateid_t *stateidp, int maxcnt, char *layp, int *hasnewsizep, 6452 uint64_t *newsizep, struct ucred *cred, NFSPROC_T *p) 6453 { 6454 struct nfsvattr na; 6455 int error; 6456 6457 error = nfsrv_updatemdsattr(vp, &na, p); 6458 if (error == 0) { 6459 *hasnewsizep = 1; 6460 *newsizep = na.na_size; 6461 } 6462 return (error); 6463 } 6464 6465 /* 6466 * Try and get a layout. 6467 */ 6468 int 6469 nfsrv_layoutget(struct nfsrv_descript *nd, vnode_t vp, struct nfsexstuff *exp, 6470 int layouttype, int *iomode, uint64_t *offset, uint64_t *len, 6471 uint64_t minlen, nfsv4stateid_t *stateidp, int maxcnt, int *retonclose, 6472 int *layoutlenp, char *layp, struct ucred *cred, NFSPROC_T *p) 6473 { 6474 struct nfslayouthash *lhyp; 6475 struct nfslayout *lyp; 6476 char *devid; 6477 fhandle_t fh, *dsfhp; 6478 int error, mirrorcnt; 6479 6480 if (nfsrv_devidcnt == 0) 6481 return (NFSERR_UNKNLAYOUTTYPE); 6482 6483 if (*offset != 0) 6484 printf("nfsrv_layoutget: off=%ju len=%ju\n", (uintmax_t)*offset, 6485 (uintmax_t)*len); 6486 error = nfsvno_getfh(vp, &fh, p); 6487 NFSD_DEBUG(4, "layoutget getfh=%d\n", error); 6488 if (error != 0) 6489 return (error); 6490 6491 /* 6492 * For now, all layouts are for entire files. 6493 * Only issue Read/Write layouts if requested for a non-readonly fs. 6494 */ 6495 if (NFSVNO_EXRDONLY(exp)) { 6496 if (*iomode == NFSLAYOUTIOMODE_RW) 6497 return (NFSERR_LAYOUTTRYLATER); 6498 *iomode = NFSLAYOUTIOMODE_READ; 6499 } 6500 if (*iomode != NFSLAYOUTIOMODE_RW) 6501 *iomode = NFSLAYOUTIOMODE_READ; 6502 6503 /* 6504 * Check to see if a write layout can be issued for this file. 6505 * This is used during mirror recovery to avoid RW layouts being 6506 * issued for a file while it is being copied to the recovered 6507 * mirror. 6508 */ 6509 if (*iomode == NFSLAYOUTIOMODE_RW && nfsrv_dontlayout(&fh) != 0) 6510 return (NFSERR_LAYOUTTRYLATER); 6511 6512 *retonclose = 0; 6513 *offset = 0; 6514 *len = UINT64_MAX; 6515 6516 /* First, see if a layout already exists and return if found. */ 6517 lhyp = NFSLAYOUTHASH(&fh); 6518 NFSLOCKLAYOUT(lhyp); 6519 error = nfsrv_findlayout(&nd->nd_clientid, &fh, layouttype, p, &lyp); 6520 NFSD_DEBUG(4, "layoutget findlay=%d\n", error); 6521 /* 6522 * Not sure if the seqid must be the same, so I won't check it. 6523 */ 6524 if (error == 0 && (stateidp->other[0] != lyp->lay_stateid.other[0] || 6525 stateidp->other[1] != lyp->lay_stateid.other[1] || 6526 stateidp->other[2] != lyp->lay_stateid.other[2])) { 6527 if ((lyp->lay_flags & NFSLAY_CALLB) == 0) { 6528 NFSUNLOCKLAYOUT(lhyp); 6529 NFSD_DEBUG(1, "ret bad stateid\n"); 6530 return (NFSERR_BADSTATEID); 6531 } 6532 /* 6533 * I believe we get here because there is a race between 6534 * the client processing the CBLAYOUTRECALL and the layout 6535 * being deleted here on the server. 6536 * The client has now done a LayoutGet with a non-layout 6537 * stateid, as it would when there is no layout. 6538 * As such, free this layout and set error == NFSERR_BADSTATEID 6539 * so the code below will create a new layout structure as 6540 * would happen if no layout was found. 6541 * "lyp" will be set before being used below, but set it NULL 6542 * as a safety belt. 6543 */ 6544 nfsrv_freelayout(&lhyp->list, lyp); 6545 lyp = NULL; 6546 error = NFSERR_BADSTATEID; 6547 } 6548 if (error == 0) { 6549 if (lyp->lay_layoutlen > maxcnt) { 6550 NFSUNLOCKLAYOUT(lhyp); 6551 NFSD_DEBUG(1, "ret layout too small\n"); 6552 return (NFSERR_TOOSMALL); 6553 } 6554 if (*iomode == NFSLAYOUTIOMODE_RW) 6555 lyp->lay_flags |= NFSLAY_RW; 6556 else 6557 lyp->lay_flags |= NFSLAY_READ; 6558 NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen); 6559 *layoutlenp = lyp->lay_layoutlen; 6560 if (++lyp->lay_stateid.seqid == 0) 6561 lyp->lay_stateid.seqid = 1; 6562 stateidp->seqid = lyp->lay_stateid.seqid; 6563 NFSUNLOCKLAYOUT(lhyp); 6564 NFSD_DEBUG(4, "ret fnd layout\n"); 6565 return (0); 6566 } 6567 NFSUNLOCKLAYOUT(lhyp); 6568 6569 /* Find the device id and file handle. */ 6570 dsfhp = malloc(sizeof(fhandle_t) * NFSDEV_MAXMIRRORS, M_TEMP, M_WAITOK); 6571 devid = malloc(NFSX_V4DEVICEID * NFSDEV_MAXMIRRORS, M_TEMP, M_WAITOK); 6572 error = nfsrv_dsgetdevandfh(vp, p, &mirrorcnt, dsfhp, devid); 6573 NFSD_DEBUG(4, "layoutget devandfh=%d\n", error); 6574 if (error == 0) { 6575 if (layouttype == NFSLAYOUT_NFSV4_1_FILES) { 6576 if (NFSX_V4FILELAYOUT > maxcnt) 6577 error = NFSERR_TOOSMALL; 6578 else 6579 lyp = nfsrv_filelayout(nd, *iomode, &fh, dsfhp, 6580 devid, vp->v_mount->mnt_stat.f_fsid); 6581 } else { 6582 if (NFSX_V4FLEXLAYOUT(mirrorcnt) > maxcnt) 6583 error = NFSERR_TOOSMALL; 6584 else 6585 lyp = nfsrv_flexlayout(nd, *iomode, mirrorcnt, 6586 &fh, dsfhp, devid, 6587 vp->v_mount->mnt_stat.f_fsid); 6588 } 6589 } 6590 free(dsfhp, M_TEMP); 6591 free(devid, M_TEMP); 6592 if (error != 0) 6593 return (error); 6594 6595 /* 6596 * Now, add this layout to the list. 6597 */ 6598 error = nfsrv_addlayout(nd, &lyp, stateidp, layp, layoutlenp, p); 6599 NFSD_DEBUG(4, "layoutget addl=%d\n", error); 6600 /* 6601 * The lyp will be set to NULL by nfsrv_addlayout() if it 6602 * linked the new structure into the lists. 6603 */ 6604 free(lyp, M_NFSDSTATE); 6605 return (error); 6606 } 6607 6608 /* 6609 * Generate a File Layout. 6610 */ 6611 static struct nfslayout * 6612 nfsrv_filelayout(struct nfsrv_descript *nd, int iomode, fhandle_t *fhp, 6613 fhandle_t *dsfhp, char *devid, fsid_t fs) 6614 { 6615 uint32_t *tl; 6616 struct nfslayout *lyp; 6617 uint64_t pattern_offset; 6618 6619 lyp = malloc(sizeof(struct nfslayout) + NFSX_V4FILELAYOUT, M_NFSDSTATE, 6620 M_WAITOK | M_ZERO); 6621 lyp->lay_type = NFSLAYOUT_NFSV4_1_FILES; 6622 if (iomode == NFSLAYOUTIOMODE_RW) 6623 lyp->lay_flags = NFSLAY_RW; 6624 else 6625 lyp->lay_flags = NFSLAY_READ; 6626 NFSBCOPY(fhp, &lyp->lay_fh, sizeof(*fhp)); 6627 lyp->lay_clientid.qval = nd->nd_clientid.qval; 6628 lyp->lay_fsid = fs; 6629 6630 /* Fill in the xdr for the files layout. */ 6631 tl = (uint32_t *)lyp->lay_xdr; 6632 NFSBCOPY(devid, tl, NFSX_V4DEVICEID); /* Device ID. */ 6633 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); 6634 6635 /* 6636 * Make the stripe size as many 64K blocks as will fit in the stripe 6637 * mask. Since there is only one stripe, the stripe size doesn't really 6638 * matter, except that the Linux client will only handle an exact 6639 * multiple of their PAGE_SIZE (usually 4K). I chose 64K as a value 6640 * that should cover most/all arches w.r.t. PAGE_SIZE. 6641 */ 6642 *tl++ = txdr_unsigned(NFSFLAYUTIL_STRIPE_MASK & ~0xffff); 6643 *tl++ = 0; /* 1st stripe index. */ 6644 pattern_offset = 0; 6645 txdr_hyper(pattern_offset, tl); tl += 2; /* Pattern offset. */ 6646 *tl++ = txdr_unsigned(1); /* 1 file handle. */ 6647 *tl++ = txdr_unsigned(NFSX_V4PNFSFH); 6648 NFSBCOPY(dsfhp, tl, sizeof(*dsfhp)); 6649 lyp->lay_layoutlen = NFSX_V4FILELAYOUT; 6650 return (lyp); 6651 } 6652 6653 #define FLEX_OWNERID "999" 6654 #define FLEX_UID0 "0" 6655 /* 6656 * Generate a Flex File Layout. 6657 * The FLEX_OWNERID can be any string of 3 decimal digits. Although this 6658 * string goes on the wire, it isn't supposed to be used by the client, 6659 * since this server uses tight coupling. 6660 * Although not recommended by the spec., if vfs.nfsd.flexlinuxhack=1 use 6661 * a string of "0". This works around the Linux Flex File Layout driver bug 6662 * which uses the synthetic uid/gid strings for the "tightly coupled" case. 6663 */ 6664 static struct nfslayout * 6665 nfsrv_flexlayout(struct nfsrv_descript *nd, int iomode, int mirrorcnt, 6666 fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs) 6667 { 6668 uint32_t *tl; 6669 struct nfslayout *lyp; 6670 uint64_t lenval; 6671 int i; 6672 6673 lyp = malloc(sizeof(struct nfslayout) + NFSX_V4FLEXLAYOUT(mirrorcnt), 6674 M_NFSDSTATE, M_WAITOK | M_ZERO); 6675 lyp->lay_type = NFSLAYOUT_FLEXFILE; 6676 if (iomode == NFSLAYOUTIOMODE_RW) 6677 lyp->lay_flags = NFSLAY_RW; 6678 else 6679 lyp->lay_flags = NFSLAY_READ; 6680 NFSBCOPY(fhp, &lyp->lay_fh, sizeof(*fhp)); 6681 lyp->lay_clientid.qval = nd->nd_clientid.qval; 6682 lyp->lay_fsid = fs; 6683 lyp->lay_mirrorcnt = mirrorcnt; 6684 6685 /* Fill in the xdr for the files layout. */ 6686 tl = (uint32_t *)lyp->lay_xdr; 6687 lenval = 0; 6688 txdr_hyper(lenval, tl); tl += 2; /* Stripe unit. */ 6689 *tl++ = txdr_unsigned(mirrorcnt); /* # of mirrors. */ 6690 for (i = 0; i < mirrorcnt; i++) { 6691 *tl++ = txdr_unsigned(1); /* One stripe. */ 6692 NFSBCOPY(devid, tl, NFSX_V4DEVICEID); /* Device ID. */ 6693 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); 6694 devid += NFSX_V4DEVICEID; 6695 *tl++ = txdr_unsigned(1); /* Efficiency. */ 6696 *tl++ = 0; /* Proxy Stateid. */ 6697 *tl++ = 0x55555555; 6698 *tl++ = 0x55555555; 6699 *tl++ = 0x55555555; 6700 *tl++ = txdr_unsigned(1); /* 1 file handle. */ 6701 *tl++ = txdr_unsigned(NFSX_V4PNFSFH); 6702 NFSBCOPY(dsfhp, tl, sizeof(*dsfhp)); 6703 tl += (NFSM_RNDUP(NFSX_V4PNFSFH) / NFSX_UNSIGNED); 6704 dsfhp++; 6705 if (nfsrv_flexlinuxhack != 0) { 6706 *tl++ = txdr_unsigned(strlen(FLEX_UID0)); 6707 *tl = 0; /* 0 pad string. */ 6708 NFSBCOPY(FLEX_UID0, tl++, strlen(FLEX_UID0)); 6709 *tl++ = txdr_unsigned(strlen(FLEX_UID0)); 6710 *tl = 0; /* 0 pad string. */ 6711 NFSBCOPY(FLEX_UID0, tl++, strlen(FLEX_UID0)); 6712 } else { 6713 *tl++ = txdr_unsigned(strlen(FLEX_OWNERID)); 6714 NFSBCOPY(FLEX_OWNERID, tl++, NFSX_UNSIGNED); 6715 *tl++ = txdr_unsigned(strlen(FLEX_OWNERID)); 6716 NFSBCOPY(FLEX_OWNERID, tl++, NFSX_UNSIGNED); 6717 } 6718 } 6719 *tl++ = txdr_unsigned(0); /* ff_flags. */ 6720 *tl = txdr_unsigned(60); /* Status interval hint. */ 6721 lyp->lay_layoutlen = NFSX_V4FLEXLAYOUT(mirrorcnt); 6722 return (lyp); 6723 } 6724 6725 /* 6726 * Parse and process Flex File errors returned via LayoutReturn. 6727 */ 6728 static void 6729 nfsrv_flexlayouterr(struct nfsrv_descript *nd, uint32_t *layp, int maxcnt, 6730 NFSPROC_T *p) 6731 { 6732 uint32_t *tl; 6733 int cnt, errcnt, i, j, opnum, stat; 6734 char devid[NFSX_V4DEVICEID]; 6735 6736 tl = layp; 6737 cnt = fxdr_unsigned(int, *tl++); 6738 NFSD_DEBUG(4, "flexlayouterr cnt=%d\n", cnt); 6739 for (i = 0; i < cnt; i++) { 6740 /* Skip offset, length and stateid for now. */ 6741 tl += (4 + NFSX_STATEID / NFSX_UNSIGNED); 6742 errcnt = fxdr_unsigned(int, *tl++); 6743 NFSD_DEBUG(4, "flexlayouterr errcnt=%d\n", errcnt); 6744 for (j = 0; j < errcnt; j++) { 6745 NFSBCOPY(tl, devid, NFSX_V4DEVICEID); 6746 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); 6747 stat = fxdr_unsigned(int, *tl++); 6748 opnum = fxdr_unsigned(int, *tl++); 6749 NFSD_DEBUG(4, "flexlayouterr op=%d stat=%d\n", opnum, 6750 stat); 6751 /* 6752 * Except for NFSERR_ACCES errors, disable the mirror. 6753 */ 6754 if (stat != NFSERR_ACCES) 6755 nfsrv_delds(devid, p); 6756 } 6757 } 6758 } 6759 6760 /* 6761 * This function removes all flex file layouts which has a mirror with 6762 * a device id that matches the argument. 6763 * Called when the DS represented by the device id has failed. 6764 */ 6765 void 6766 nfsrv_flexmirrordel(char *devid, NFSPROC_T *p) 6767 { 6768 uint32_t *tl; 6769 struct nfslayout *lyp, *nlyp; 6770 struct nfslayouthash *lhyp; 6771 struct nfslayouthead loclyp; 6772 int i, j; 6773 6774 NFSD_DEBUG(4, "flexmirrordel\n"); 6775 /* Move all layouts found onto a local list. */ 6776 TAILQ_INIT(&loclyp); 6777 for (i = 0; i < nfsrv_layouthashsize; i++) { 6778 lhyp = &nfslayouthash[i]; 6779 NFSLOCKLAYOUT(lhyp); 6780 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) { 6781 if (lyp->lay_type == NFSLAYOUT_FLEXFILE && 6782 lyp->lay_mirrorcnt > 1) { 6783 NFSD_DEBUG(4, "possible match\n"); 6784 tl = lyp->lay_xdr; 6785 tl += 3; 6786 for (j = 0; j < lyp->lay_mirrorcnt; j++) { 6787 tl++; 6788 if (NFSBCMP(devid, tl, NFSX_V4DEVICEID) 6789 == 0) { 6790 /* Found one. */ 6791 NFSD_DEBUG(4, "fnd one\n"); 6792 TAILQ_REMOVE(&lhyp->list, lyp, 6793 lay_list); 6794 TAILQ_INSERT_HEAD(&loclyp, lyp, 6795 lay_list); 6796 break; 6797 } 6798 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED + 6799 NFSM_RNDUP(NFSX_V4PNFSFH) / 6800 NFSX_UNSIGNED + 11 * NFSX_UNSIGNED); 6801 } 6802 } 6803 } 6804 NFSUNLOCKLAYOUT(lhyp); 6805 } 6806 6807 /* Now, try to do a Layout recall for each one found. */ 6808 TAILQ_FOREACH_SAFE(lyp, &loclyp, lay_list, nlyp) { 6809 NFSD_DEBUG(4, "do layout recall\n"); 6810 /* 6811 * The layout stateid.seqid needs to be incremented 6812 * before doing a LAYOUT_RECALL callback. 6813 * Set lay_trycnt to UINT16_MAX so it won't set up a retry. 6814 */ 6815 if (++lyp->lay_stateid.seqid == 0) 6816 lyp->lay_stateid.seqid = 1; 6817 lyp->lay_trycnt = UINT16_MAX; 6818 nfsrv_recalllayout(lyp->lay_clientid, &lyp->lay_stateid, 6819 &lyp->lay_fh, lyp, &loclyp, lyp->lay_type, p); 6820 nfsrv_freelayout(&loclyp, lyp); 6821 } 6822 } 6823 6824 /* 6825 * Do a recall callback to the client for this layout. 6826 */ 6827 static int 6828 nfsrv_recalllayout(nfsquad_t clid, nfsv4stateid_t *stateidp, fhandle_t *fhp, 6829 struct nfslayout *lyp, struct nfslayouthead *lyheadp, int laytype, 6830 NFSPROC_T *p) 6831 { 6832 struct nfsclient *clp; 6833 int error; 6834 6835 NFSD_DEBUG(4, "nfsrv_recalllayout\n"); 6836 error = nfsrv_getclient(clid, 0, &clp, NULL, (nfsquad_t)((u_quad_t)0), 6837 0, NULL, p); 6838 NFSD_DEBUG(4, "aft nfsrv_getclient=%d\n", error); 6839 if (error != 0) 6840 return (error); 6841 if ((clp->lc_flags & LCL_NFSV41) != 0) { 6842 error = nfsrv_docallback(clp, NFSV4OP_CBLAYOUTRECALL, 6843 stateidp, 0, fhp, NULL, NULL, laytype, p); 6844 /* If lyp != NULL, handle an error return here. */ 6845 if (error != 0 && lyp != NULL) { 6846 NFSDRECALLLOCK(); 6847 if (error == NFSERR_NOMATCHLAYOUT) { 6848 /* 6849 * Mark it returned, since there is no layout. 6850 */ 6851 if ((lyp->lay_flags & NFSLAY_RECALL) != 0) { 6852 lyp->lay_flags |= NFSLAY_RETURNED; 6853 wakeup(lyp); 6854 } 6855 NFSDRECALLUNLOCK(); 6856 } else if ((lyp->lay_flags & NFSLAY_RETURNED) == 0 && 6857 lyp->lay_trycnt < 10) { 6858 /* 6859 * Clear recall, so it can be tried again 6860 * and put it at the end of the list to 6861 * delay the retry a little longer. 6862 */ 6863 lyp->lay_flags &= ~NFSLAY_RECALL; 6864 lyp->lay_trycnt++; 6865 TAILQ_REMOVE(lyheadp, lyp, lay_list); 6866 TAILQ_INSERT_TAIL(lyheadp, lyp, lay_list); 6867 NFSDRECALLUNLOCK(); 6868 nfs_catnap(PVFS, 0, "nfsrclay"); 6869 } else 6870 NFSDRECALLUNLOCK(); 6871 } 6872 } else 6873 printf("nfsrv_recalllayout: clp not NFSv4.1\n"); 6874 return (error); 6875 } 6876 6877 /* 6878 * Find a layout to recall when we exceed our high water mark. 6879 */ 6880 void 6881 nfsrv_recalloldlayout(NFSPROC_T *p) 6882 { 6883 struct nfslayouthash *lhyp; 6884 struct nfslayout *lyp; 6885 nfsquad_t clientid; 6886 nfsv4stateid_t stateid; 6887 fhandle_t fh; 6888 int error, laytype, ret; 6889 6890 lhyp = &nfslayouthash[arc4random() % nfsrv_layouthashsize]; 6891 NFSLOCKLAYOUT(lhyp); 6892 TAILQ_FOREACH_REVERSE(lyp, &lhyp->list, nfslayouthead, lay_list) { 6893 if ((lyp->lay_flags & NFSLAY_CALLB) == 0) { 6894 lyp->lay_flags |= NFSLAY_CALLB; 6895 /* 6896 * The layout stateid.seqid needs to be incremented 6897 * before doing a LAYOUT_RECALL callback. 6898 */ 6899 if (++lyp->lay_stateid.seqid == 0) 6900 lyp->lay_stateid.seqid = 1; 6901 clientid = lyp->lay_clientid; 6902 stateid = lyp->lay_stateid; 6903 fh = lyp->lay_fh; 6904 laytype = lyp->lay_type; 6905 break; 6906 } 6907 } 6908 NFSUNLOCKLAYOUT(lhyp); 6909 if (lyp != NULL) { 6910 error = nfsrv_recalllayout(clientid, &stateid, &fh, NULL, NULL, 6911 laytype, p); 6912 if (error != 0 && error != NFSERR_NOMATCHLAYOUT) 6913 printf("recallold=%d\n", error); 6914 if (error != 0) { 6915 NFSLOCKLAYOUT(lhyp); 6916 /* 6917 * Since the hash list was unlocked, we need to 6918 * find it again. 6919 */ 6920 ret = nfsrv_findlayout(&clientid, &fh, laytype, p, 6921 &lyp); 6922 if (ret == 0 && 6923 (lyp->lay_flags & NFSLAY_CALLB) != 0 && 6924 lyp->lay_stateid.other[0] == stateid.other[0] && 6925 lyp->lay_stateid.other[1] == stateid.other[1] && 6926 lyp->lay_stateid.other[2] == stateid.other[2]) { 6927 /* 6928 * The client no longer knows this layout, so 6929 * it can be free'd now. 6930 */ 6931 if (error == NFSERR_NOMATCHLAYOUT) 6932 nfsrv_freelayout(&lhyp->list, lyp); 6933 else { 6934 /* 6935 * Leave it to be tried later by 6936 * clearing NFSLAY_CALLB and moving 6937 * it to the head of the list, so it 6938 * won't be tried again for a while. 6939 */ 6940 lyp->lay_flags &= ~NFSLAY_CALLB; 6941 TAILQ_REMOVE(&lhyp->list, lyp, 6942 lay_list); 6943 TAILQ_INSERT_HEAD(&lhyp->list, lyp, 6944 lay_list); 6945 } 6946 } 6947 NFSUNLOCKLAYOUT(lhyp); 6948 } 6949 } 6950 } 6951 6952 /* 6953 * Try and return layout(s). 6954 */ 6955 int 6956 nfsrv_layoutreturn(struct nfsrv_descript *nd, vnode_t vp, 6957 int layouttype, int iomode, uint64_t offset, uint64_t len, int reclaim, 6958 int kind, nfsv4stateid_t *stateidp, int maxcnt, uint32_t *layp, int *fndp, 6959 struct ucred *cred, NFSPROC_T *p) 6960 { 6961 struct nfsvattr na; 6962 struct nfslayouthash *lhyp; 6963 struct nfslayout *lyp; 6964 fhandle_t fh; 6965 int error = 0; 6966 6967 *fndp = 0; 6968 if (kind == NFSV4LAYOUTRET_FILE) { 6969 error = nfsvno_getfh(vp, &fh, p); 6970 if (error == 0) { 6971 error = nfsrv_updatemdsattr(vp, &na, p); 6972 if (error != 0) 6973 printf("nfsrv_layoutreturn: updatemdsattr" 6974 " failed=%d\n", error); 6975 } 6976 if (error == 0) { 6977 if (reclaim == newnfs_true) { 6978 error = nfsrv_checkgrace(NULL, NULL, 6979 NFSLCK_RECLAIM); 6980 if (error != NFSERR_NOGRACE) 6981 error = 0; 6982 return (error); 6983 } 6984 lhyp = NFSLAYOUTHASH(&fh); 6985 NFSDRECALLLOCK(); 6986 NFSLOCKLAYOUT(lhyp); 6987 error = nfsrv_findlayout(&nd->nd_clientid, &fh, 6988 layouttype, p, &lyp); 6989 NFSD_DEBUG(4, "layoutret findlay=%d\n", error); 6990 if (error == 0 && 6991 stateidp->other[0] == lyp->lay_stateid.other[0] && 6992 stateidp->other[1] == lyp->lay_stateid.other[1] && 6993 stateidp->other[2] == lyp->lay_stateid.other[2]) { 6994 NFSD_DEBUG(4, "nfsrv_layoutreturn: stateid %d" 6995 " %x %x %x laystateid %d %x %x %x" 6996 " off=%ju len=%ju flgs=0x%x\n", 6997 stateidp->seqid, stateidp->other[0], 6998 stateidp->other[1], stateidp->other[2], 6999 lyp->lay_stateid.seqid, 7000 lyp->lay_stateid.other[0], 7001 lyp->lay_stateid.other[1], 7002 lyp->lay_stateid.other[2], 7003 (uintmax_t)offset, (uintmax_t)len, 7004 lyp->lay_flags); 7005 if (++lyp->lay_stateid.seqid == 0) 7006 lyp->lay_stateid.seqid = 1; 7007 stateidp->seqid = lyp->lay_stateid.seqid; 7008 if (offset == 0 && len == UINT64_MAX) { 7009 if ((iomode & NFSLAYOUTIOMODE_READ) != 7010 0) 7011 lyp->lay_flags &= ~NFSLAY_READ; 7012 if ((iomode & NFSLAYOUTIOMODE_RW) != 0) 7013 lyp->lay_flags &= ~NFSLAY_RW; 7014 if ((lyp->lay_flags & (NFSLAY_READ | 7015 NFSLAY_RW)) == 0) 7016 nfsrv_freelayout(&lhyp->list, 7017 lyp); 7018 else 7019 *fndp = 1; 7020 } else 7021 *fndp = 1; 7022 } 7023 NFSUNLOCKLAYOUT(lhyp); 7024 /* Search the nfsrv_recalllist for a match. */ 7025 TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) { 7026 if (NFSBCMP(&lyp->lay_fh, &fh, 7027 sizeof(fh)) == 0 && 7028 lyp->lay_clientid.qval == 7029 nd->nd_clientid.qval && 7030 stateidp->other[0] == 7031 lyp->lay_stateid.other[0] && 7032 stateidp->other[1] == 7033 lyp->lay_stateid.other[1] && 7034 stateidp->other[2] == 7035 lyp->lay_stateid.other[2]) { 7036 lyp->lay_flags |= NFSLAY_RETURNED; 7037 wakeup(lyp); 7038 error = 0; 7039 } 7040 } 7041 NFSDRECALLUNLOCK(); 7042 } 7043 if (layouttype == NFSLAYOUT_FLEXFILE) 7044 nfsrv_flexlayouterr(nd, layp, maxcnt, p); 7045 } else if (kind == NFSV4LAYOUTRET_FSID) 7046 nfsrv_freelayouts(&nd->nd_clientid, 7047 &vp->v_mount->mnt_stat.f_fsid, layouttype, iomode); 7048 else if (kind == NFSV4LAYOUTRET_ALL) 7049 nfsrv_freelayouts(&nd->nd_clientid, NULL, layouttype, iomode); 7050 else 7051 error = NFSERR_INVAL; 7052 if (error == -1) 7053 error = 0; 7054 return (error); 7055 } 7056 7057 /* 7058 * Look for an existing layout. 7059 */ 7060 static int 7061 nfsrv_findlayout(nfsquad_t *clientidp, fhandle_t *fhp, int laytype, 7062 NFSPROC_T *p, struct nfslayout **lypp) 7063 { 7064 struct nfslayouthash *lhyp; 7065 struct nfslayout *lyp; 7066 int ret; 7067 7068 *lypp = NULL; 7069 ret = 0; 7070 lhyp = NFSLAYOUTHASH(fhp); 7071 TAILQ_FOREACH(lyp, &lhyp->list, lay_list) { 7072 if (NFSBCMP(&lyp->lay_fh, fhp, sizeof(*fhp)) == 0 && 7073 lyp->lay_clientid.qval == clientidp->qval && 7074 lyp->lay_type == laytype) 7075 break; 7076 } 7077 if (lyp != NULL) 7078 *lypp = lyp; 7079 else 7080 ret = -1; 7081 return (ret); 7082 } 7083 7084 /* 7085 * Add the new layout, as required. 7086 */ 7087 static int 7088 nfsrv_addlayout(struct nfsrv_descript *nd, struct nfslayout **lypp, 7089 nfsv4stateid_t *stateidp, char *layp, int *layoutlenp, NFSPROC_T *p) 7090 { 7091 struct nfsclient *clp; 7092 struct nfslayouthash *lhyp; 7093 struct nfslayout *lyp, *nlyp; 7094 fhandle_t *fhp; 7095 int error; 7096 7097 KASSERT((nd->nd_flag & ND_IMPLIEDCLID) != 0, 7098 ("nfsrv_layoutget: no nd_clientid\n")); 7099 lyp = *lypp; 7100 fhp = &lyp->lay_fh; 7101 NFSLOCKSTATE(); 7102 error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp, 7103 NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); 7104 if (error != 0) { 7105 NFSUNLOCKSTATE(); 7106 return (error); 7107 } 7108 lyp->lay_stateid.seqid = stateidp->seqid = 1; 7109 lyp->lay_stateid.other[0] = stateidp->other[0] = 7110 clp->lc_clientid.lval[0]; 7111 lyp->lay_stateid.other[1] = stateidp->other[1] = 7112 clp->lc_clientid.lval[1]; 7113 lyp->lay_stateid.other[2] = stateidp->other[2] = 7114 nfsrv_nextstateindex(clp); 7115 NFSUNLOCKSTATE(); 7116 7117 lhyp = NFSLAYOUTHASH(fhp); 7118 NFSLOCKLAYOUT(lhyp); 7119 TAILQ_FOREACH(nlyp, &lhyp->list, lay_list) { 7120 if (NFSBCMP(&nlyp->lay_fh, fhp, sizeof(*fhp)) == 0 && 7121 nlyp->lay_clientid.qval == nd->nd_clientid.qval) 7122 break; 7123 } 7124 if (nlyp != NULL) { 7125 /* A layout already exists, so use it. */ 7126 nlyp->lay_flags |= (lyp->lay_flags & (NFSLAY_READ | NFSLAY_RW)); 7127 NFSBCOPY(nlyp->lay_xdr, layp, nlyp->lay_layoutlen); 7128 *layoutlenp = nlyp->lay_layoutlen; 7129 if (++nlyp->lay_stateid.seqid == 0) 7130 nlyp->lay_stateid.seqid = 1; 7131 stateidp->seqid = nlyp->lay_stateid.seqid; 7132 stateidp->other[0] = nlyp->lay_stateid.other[0]; 7133 stateidp->other[1] = nlyp->lay_stateid.other[1]; 7134 stateidp->other[2] = nlyp->lay_stateid.other[2]; 7135 NFSUNLOCKLAYOUT(lhyp); 7136 return (0); 7137 } 7138 7139 /* Insert the new layout in the lists. */ 7140 *lypp = NULL; 7141 atomic_add_int(&nfsrv_layoutcnt, 1); 7142 NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen); 7143 *layoutlenp = lyp->lay_layoutlen; 7144 TAILQ_INSERT_HEAD(&lhyp->list, lyp, lay_list); 7145 NFSUNLOCKLAYOUT(lhyp); 7146 return (0); 7147 } 7148 7149 /* 7150 * Get the devinfo for a deviceid. 7151 */ 7152 int 7153 nfsrv_getdevinfo(char *devid, int layouttype, uint32_t *maxcnt, 7154 uint32_t *notify, int *devaddrlen, char **devaddr) 7155 { 7156 struct nfsdevice *ds; 7157 7158 if ((layouttype != NFSLAYOUT_NFSV4_1_FILES && layouttype != 7159 NFSLAYOUT_FLEXFILE) || 7160 (nfsrv_maxpnfsmirror > 1 && layouttype == NFSLAYOUT_NFSV4_1_FILES)) 7161 return (NFSERR_UNKNLAYOUTTYPE); 7162 7163 /* 7164 * Now, search for the device id. Note that the structures won't go 7165 * away, but the order changes in the list. As such, the lock only 7166 * needs to be held during the search through the list. 7167 */ 7168 NFSDDSLOCK(); 7169 TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) { 7170 if (NFSBCMP(devid, ds->nfsdev_deviceid, NFSX_V4DEVICEID) == 0 && 7171 ds->nfsdev_nmp != NULL) 7172 break; 7173 } 7174 NFSDDSUNLOCK(); 7175 if (ds == NULL) 7176 return (NFSERR_NOENT); 7177 7178 /* If the correct nfsdev_XXXXaddrlen is > 0, we have the device info. */ 7179 *devaddrlen = 0; 7180 if (layouttype == NFSLAYOUT_NFSV4_1_FILES) { 7181 *devaddrlen = ds->nfsdev_fileaddrlen; 7182 *devaddr = ds->nfsdev_fileaddr; 7183 } else if (layouttype == NFSLAYOUT_FLEXFILE) { 7184 *devaddrlen = ds->nfsdev_flexaddrlen; 7185 *devaddr = ds->nfsdev_flexaddr; 7186 } 7187 if (*devaddrlen == 0) 7188 return (NFSERR_UNKNLAYOUTTYPE); 7189 7190 /* 7191 * The XDR overhead is 3 unsigned values: layout_type, 7192 * length_of_address and notify bitmap. 7193 * If the notify array is changed to not all zeros, the 7194 * count of unsigned values must be increased. 7195 */ 7196 if (*maxcnt > 0 && *maxcnt < NFSM_RNDUP(*devaddrlen) + 7197 3 * NFSX_UNSIGNED) { 7198 *maxcnt = NFSM_RNDUP(*devaddrlen) + 3 * NFSX_UNSIGNED; 7199 return (NFSERR_TOOSMALL); 7200 } 7201 return (0); 7202 } 7203 7204 /* 7205 * Free a list of layout state structures. 7206 */ 7207 static void 7208 nfsrv_freelayoutlist(nfsquad_t clientid) 7209 { 7210 struct nfslayouthash *lhyp; 7211 struct nfslayout *lyp, *nlyp; 7212 int i; 7213 7214 for (i = 0; i < nfsrv_layouthashsize; i++) { 7215 lhyp = &nfslayouthash[i]; 7216 NFSLOCKLAYOUT(lhyp); 7217 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) { 7218 if (lyp->lay_clientid.qval == clientid.qval) 7219 nfsrv_freelayout(&lhyp->list, lyp); 7220 } 7221 NFSUNLOCKLAYOUT(lhyp); 7222 } 7223 } 7224 7225 /* 7226 * Free up a layout. 7227 */ 7228 static void 7229 nfsrv_freelayout(struct nfslayouthead *lhp, struct nfslayout *lyp) 7230 { 7231 7232 NFSD_DEBUG(4, "Freelayout=%p\n", lyp); 7233 atomic_add_int(&nfsrv_layoutcnt, -1); 7234 TAILQ_REMOVE(lhp, lyp, lay_list); 7235 free(lyp, M_NFSDSTATE); 7236 } 7237 7238 /* 7239 * Free up a device id. 7240 */ 7241 void 7242 nfsrv_freeonedevid(struct nfsdevice *ds) 7243 { 7244 int i; 7245 7246 atomic_add_int(&nfsrv_devidcnt, -1); 7247 vrele(ds->nfsdev_dvp); 7248 for (i = 0; i < nfsrv_dsdirsize; i++) 7249 if (ds->nfsdev_dsdir[i] != NULL) 7250 vrele(ds->nfsdev_dsdir[i]); 7251 free(ds->nfsdev_fileaddr, M_NFSDSTATE); 7252 free(ds->nfsdev_flexaddr, M_NFSDSTATE); 7253 free(ds->nfsdev_host, M_NFSDSTATE); 7254 free(ds, M_NFSDSTATE); 7255 } 7256 7257 /* 7258 * Free up a device id and its mirrors. 7259 */ 7260 static void 7261 nfsrv_freedevid(struct nfsdevice *ds) 7262 { 7263 7264 TAILQ_REMOVE(&nfsrv_devidhead, ds, nfsdev_list); 7265 nfsrv_freeonedevid(ds); 7266 } 7267 7268 /* 7269 * Free all layouts and device ids. 7270 * Done when the nfsd threads are shut down since there may be a new 7271 * modified device id list created when the nfsd is restarted. 7272 */ 7273 void 7274 nfsrv_freealllayoutsanddevids(void) 7275 { 7276 struct nfsdontlist *mrp, *nmrp; 7277 struct nfslayout *lyp, *nlyp; 7278 7279 /* Get rid of the deviceid structures. */ 7280 nfsrv_freealldevids(); 7281 TAILQ_INIT(&nfsrv_devidhead); 7282 nfsrv_devidcnt = 0; 7283 7284 /* Get rid of all layouts. */ 7285 nfsrv_freealllayouts(); 7286 7287 /* Get rid of any nfsdontlist entries. */ 7288 LIST_FOREACH_SAFE(mrp, &nfsrv_dontlisthead, nfsmr_list, nmrp) 7289 free(mrp, M_NFSDSTATE); 7290 LIST_INIT(&nfsrv_dontlisthead); 7291 nfsrv_dontlistlen = 0; 7292 7293 /* Free layouts in the recall list. */ 7294 TAILQ_FOREACH_SAFE(lyp, &nfsrv_recalllisthead, lay_list, nlyp) 7295 nfsrv_freelayout(&nfsrv_recalllisthead, lyp); 7296 TAILQ_INIT(&nfsrv_recalllisthead); 7297 } 7298 7299 /* 7300 * Free layouts that match the arguments. 7301 */ 7302 static void 7303 nfsrv_freelayouts(nfsquad_t *clid, fsid_t *fs, int laytype, int iomode) 7304 { 7305 struct nfslayouthash *lhyp; 7306 struct nfslayout *lyp, *nlyp; 7307 int i; 7308 7309 for (i = 0; i < nfsrv_layouthashsize; i++) { 7310 lhyp = &nfslayouthash[i]; 7311 NFSLOCKLAYOUT(lhyp); 7312 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) { 7313 if (clid->qval != lyp->lay_clientid.qval) 7314 continue; 7315 if (fs != NULL && (fs->val[0] != lyp->lay_fsid.val[0] || 7316 fs->val[1] != lyp->lay_fsid.val[1])) 7317 continue; 7318 if (laytype != lyp->lay_type) 7319 continue; 7320 if ((iomode & NFSLAYOUTIOMODE_READ) != 0) 7321 lyp->lay_flags &= ~NFSLAY_READ; 7322 if ((iomode & NFSLAYOUTIOMODE_RW) != 0) 7323 lyp->lay_flags &= ~NFSLAY_RW; 7324 if ((lyp->lay_flags & (NFSLAY_READ | NFSLAY_RW)) == 0) 7325 nfsrv_freelayout(&lhyp->list, lyp); 7326 } 7327 NFSUNLOCKLAYOUT(lhyp); 7328 } 7329 } 7330 7331 /* 7332 * Free all layouts for the argument file. 7333 */ 7334 void 7335 nfsrv_freefilelayouts(fhandle_t *fhp) 7336 { 7337 struct nfslayouthash *lhyp; 7338 struct nfslayout *lyp, *nlyp; 7339 7340 lhyp = NFSLAYOUTHASH(fhp); 7341 NFSLOCKLAYOUT(lhyp); 7342 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) { 7343 if (NFSBCMP(&lyp->lay_fh, fhp, sizeof(*fhp)) == 0) 7344 nfsrv_freelayout(&lhyp->list, lyp); 7345 } 7346 NFSUNLOCKLAYOUT(lhyp); 7347 } 7348 7349 /* 7350 * Free all layouts. 7351 */ 7352 static void 7353 nfsrv_freealllayouts(void) 7354 { 7355 struct nfslayouthash *lhyp; 7356 struct nfslayout *lyp, *nlyp; 7357 int i; 7358 7359 for (i = 0; i < nfsrv_layouthashsize; i++) { 7360 lhyp = &nfslayouthash[i]; 7361 NFSLOCKLAYOUT(lhyp); 7362 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) 7363 nfsrv_freelayout(&lhyp->list, lyp); 7364 NFSUNLOCKLAYOUT(lhyp); 7365 } 7366 } 7367 7368 /* 7369 * Look up the mount path for the DS server. 7370 */ 7371 static int 7372 nfsrv_setdsserver(char *dspathp, NFSPROC_T *p, struct nfsdevice **dsp) 7373 { 7374 struct nameidata nd; 7375 struct nfsdevice *ds; 7376 int error, i; 7377 char *dsdirpath; 7378 size_t dsdirsize; 7379 7380 NFSD_DEBUG(4, "setdssrv path=%s\n", dspathp); 7381 *dsp = NULL; 7382 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE, 7383 dspathp, p); 7384 error = namei(&nd); 7385 NFSD_DEBUG(4, "lookup=%d\n", error); 7386 if (error != 0) 7387 return (error); 7388 if (nd.ni_vp->v_type != VDIR) { 7389 vput(nd.ni_vp); 7390 NFSD_DEBUG(4, "dspath not dir\n"); 7391 return (ENOTDIR); 7392 } 7393 if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) { 7394 vput(nd.ni_vp); 7395 NFSD_DEBUG(4, "dspath not an NFS mount\n"); 7396 return (ENXIO); 7397 } 7398 7399 /* 7400 * Allocate a DS server structure with the NFS mounted directory 7401 * vnode reference counted, so that a non-forced dismount will 7402 * fail with EBUSY. 7403 */ 7404 *dsp = ds = malloc(sizeof(*ds) + nfsrv_dsdirsize * sizeof(vnode_t), 7405 M_NFSDSTATE, M_WAITOK | M_ZERO); 7406 ds->nfsdev_dvp = nd.ni_vp; 7407 ds->nfsdev_nmp = VFSTONFS(nd.ni_vp->v_mount); 7408 NFSVOPUNLOCK(nd.ni_vp, 0); 7409 7410 dsdirsize = strlen(dspathp) + 16; 7411 dsdirpath = malloc(dsdirsize, M_TEMP, M_WAITOK); 7412 /* Now, create the DS directory structures. */ 7413 for (i = 0; i < nfsrv_dsdirsize; i++) { 7414 snprintf(dsdirpath, dsdirsize, "%s/ds%d", dspathp, i); 7415 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, 7416 UIO_SYSSPACE, dsdirpath, p); 7417 error = namei(&nd); 7418 NFSD_DEBUG(4, "dsdirpath=%s lookup=%d\n", dsdirpath, error); 7419 if (error != 0) 7420 break; 7421 if (nd.ni_vp->v_type != VDIR) { 7422 vput(nd.ni_vp); 7423 error = ENOTDIR; 7424 NFSD_DEBUG(4, "dsdirpath not a VDIR\n"); 7425 break; 7426 } 7427 if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) { 7428 vput(nd.ni_vp); 7429 error = ENXIO; 7430 NFSD_DEBUG(4, "dsdirpath not an NFS mount\n"); 7431 break; 7432 } 7433 ds->nfsdev_dsdir[i] = nd.ni_vp; 7434 NFSVOPUNLOCK(nd.ni_vp, 0); 7435 } 7436 free(dsdirpath, M_TEMP); 7437 7438 TAILQ_INSERT_TAIL(&nfsrv_devidhead, ds, nfsdev_list); 7439 atomic_add_int(&nfsrv_devidcnt, 1); 7440 return (error); 7441 } 7442 7443 /* 7444 * Look up the mount path for the DS server and delete it. 7445 */ 7446 int 7447 nfsrv_deldsserver(char *dspathp, NFSPROC_T *p) 7448 { 7449 struct mount *mp; 7450 struct nfsmount *nmp; 7451 struct nfsdevice *ds; 7452 int error; 7453 7454 NFSD_DEBUG(4, "deldssrv path=%s\n", dspathp); 7455 /* 7456 * Search for the path in the mount list. Avoid looking the path 7457 * up, since this mount point may be hung, with associated locked 7458 * vnodes, etc. 7459 * Set NFSMNTP_CANCELRPCS so that any forced dismount will be blocked 7460 * until this completes. 7461 * As noted in the man page, this should be done before any forced 7462 * dismount on the mount point, but at least the handshake on 7463 * NFSMNTP_CANCELRPCS should make it safe. 7464 */ 7465 error = 0; 7466 ds = NULL; 7467 nmp = NULL; 7468 mtx_lock(&mountlist_mtx); 7469 TAILQ_FOREACH(mp, &mountlist, mnt_list) { 7470 if (strcmp(mp->mnt_stat.f_mntonname, dspathp) == 0 && 7471 strcmp(mp->mnt_stat.f_fstypename, "nfs") == 0 && 7472 mp->mnt_data != NULL) { 7473 nmp = VFSTONFS(mp); 7474 NFSLOCKMNT(nmp); 7475 if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM | 7476 NFSMNTP_CANCELRPCS)) == 0) { 7477 nmp->nm_privflag |= NFSMNTP_CANCELRPCS; 7478 NFSUNLOCKMNT(nmp); 7479 } else { 7480 NFSUNLOCKMNT(nmp); 7481 nmp = NULL; 7482 } 7483 break; 7484 } 7485 } 7486 mtx_unlock(&mountlist_mtx); 7487 7488 if (nmp != NULL) { 7489 ds = nfsrv_deldsnmp(nmp, p); 7490 NFSD_DEBUG(4, "deldsnmp=%p\n", ds); 7491 if (ds != NULL) { 7492 nfsrv_killrpcs(nmp); 7493 NFSD_DEBUG(4, "aft killrpcs\n"); 7494 } else 7495 error = ENXIO; 7496 NFSLOCKMNT(nmp); 7497 nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS; 7498 wakeup(nmp); 7499 NFSUNLOCKMNT(nmp); 7500 } else 7501 error = EINVAL; 7502 return (error); 7503 } 7504 7505 /* 7506 * Search for and remove a DS entry which matches the "nmp" argument. 7507 * The nfsdevice structure pointer is returned so that the caller can 7508 * free it via nfsrv_freeonedevid(). 7509 */ 7510 struct nfsdevice * 7511 nfsrv_deldsnmp(struct nfsmount *nmp, NFSPROC_T *p) 7512 { 7513 struct nfsdevice *fndds; 7514 7515 NFSD_DEBUG(4, "deldsdvp\n"); 7516 NFSDDSLOCK(); 7517 if (nfsrv_faildscnt <= 0) { 7518 NFSDDSUNLOCK(); 7519 return (NULL); 7520 } 7521 fndds = nfsv4_findmirror(nmp); 7522 if (fndds != NULL) 7523 nfsrv_deleteds(fndds); 7524 NFSDDSUNLOCK(); 7525 if (fndds != NULL) { 7526 nfsrv_flexmirrordel(fndds->nfsdev_deviceid, p); 7527 printf("pNFS server: mirror %s failed\n", fndds->nfsdev_host); 7528 } 7529 return (fndds); 7530 } 7531 7532 /* 7533 * Similar to nfsrv_deldsnmp(), except that the DS is indicated by deviceid. 7534 * This function also calls nfsrv_killrpcs() to unblock RPCs on the mount 7535 * point. 7536 * Also, returns an error instead of the nfsdevice found. 7537 */ 7538 static int 7539 nfsrv_delds(char *devid, NFSPROC_T *p) 7540 { 7541 struct nfsdevice *ds, *fndds; 7542 struct nfsmount *nmp; 7543 int fndmirror; 7544 7545 NFSD_DEBUG(4, "delds\n"); 7546 /* 7547 * Search the DS server list for a match with devid. 7548 * Remove the DS entry if found and there is a mirror. 7549 */ 7550 fndds = NULL; 7551 nmp = NULL; 7552 fndmirror = 0; 7553 NFSDDSLOCK(); 7554 if (nfsrv_faildscnt <= 0) { 7555 NFSDDSUNLOCK(); 7556 return (ENXIO); 7557 } 7558 TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) { 7559 if (NFSBCMP(ds->nfsdev_deviceid, devid, NFSX_V4DEVICEID) == 0 && 7560 ds->nfsdev_nmp != NULL) { 7561 NFSD_DEBUG(4, "fnd main ds\n"); 7562 fndds = ds; 7563 } else if (ds->nfsdev_nmp != NULL) 7564 fndmirror = 1; 7565 if (fndds != NULL && fndmirror != 0) 7566 break; 7567 } 7568 if (fndds != NULL && fndmirror != 0) { 7569 nmp = fndds->nfsdev_nmp; 7570 NFSLOCKMNT(nmp); 7571 if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM | 7572 NFSMNTP_CANCELRPCS)) == 0) { 7573 nmp->nm_privflag |= NFSMNTP_CANCELRPCS; 7574 NFSUNLOCKMNT(nmp); 7575 nfsrv_deleteds(fndds); 7576 } else { 7577 NFSUNLOCKMNT(nmp); 7578 nmp = NULL; 7579 } 7580 } 7581 NFSDDSUNLOCK(); 7582 if (fndds != NULL && nmp != NULL) { 7583 nfsrv_flexmirrordel(fndds->nfsdev_deviceid, p); 7584 printf("pNFS server: mirror %s failed\n", fndds->nfsdev_host); 7585 nfsrv_killrpcs(nmp); 7586 NFSLOCKMNT(nmp); 7587 nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS; 7588 wakeup(nmp); 7589 NFSUNLOCKMNT(nmp); 7590 return (0); 7591 } 7592 return (ENXIO); 7593 } 7594 7595 /* 7596 * Mark a DS as disabled by setting nfsdev_nmp = NULL. 7597 */ 7598 static void 7599 nfsrv_deleteds(struct nfsdevice *fndds) 7600 { 7601 7602 NFSD_DEBUG(4, "deleteds: deleting a mirror\n"); 7603 fndds->nfsdev_nmp = NULL; 7604 nfsrv_faildscnt--; 7605 } 7606 7607 /* 7608 * Fill in the addr structures for the File and Flex File layouts. 7609 */ 7610 static void 7611 nfsrv_allocdevid(struct nfsdevice *ds, char *addr, char *dnshost) 7612 { 7613 uint32_t *tl; 7614 char *netprot; 7615 int addrlen; 7616 static uint64_t new_devid = 0; 7617 7618 if (strchr(addr, ':') != NULL) 7619 netprot = "tcp6"; 7620 else 7621 netprot = "tcp"; 7622 7623 /* Fill in the device id. */ 7624 NFSBCOPY(&nfsdev_time, ds->nfsdev_deviceid, sizeof(nfsdev_time)); 7625 new_devid++; 7626 NFSBCOPY(&new_devid, &ds->nfsdev_deviceid[sizeof(nfsdev_time)], 7627 sizeof(new_devid)); 7628 7629 /* 7630 * Fill in the file addr (actually the nfsv4_file_layout_ds_addr4 7631 * as defined in RFC5661) in XDR. 7632 */ 7633 addrlen = NFSM_RNDUP(strlen(addr)) + NFSM_RNDUP(strlen(netprot)) + 7634 6 * NFSX_UNSIGNED; 7635 NFSD_DEBUG(4, "hn=%s addr=%s netprot=%s\n", dnshost, addr, netprot); 7636 ds->nfsdev_fileaddrlen = addrlen; 7637 tl = malloc(addrlen, M_NFSDSTATE, M_WAITOK | M_ZERO); 7638 ds->nfsdev_fileaddr = (char *)tl; 7639 *tl++ = txdr_unsigned(1); /* One stripe with index 0. */ 7640 *tl++ = 0; 7641 *tl++ = txdr_unsigned(1); /* One multipath list */ 7642 *tl++ = txdr_unsigned(1); /* with one entry in it. */ 7643 /* The netaddr for this one entry. */ 7644 *tl++ = txdr_unsigned(strlen(netprot)); 7645 NFSBCOPY(netprot, tl, strlen(netprot)); 7646 tl += (NFSM_RNDUP(strlen(netprot)) / NFSX_UNSIGNED); 7647 *tl++ = txdr_unsigned(strlen(addr)); 7648 NFSBCOPY(addr, tl, strlen(addr)); 7649 7650 /* 7651 * Fill in the flex file addr (actually the ff_device_addr4 7652 * as defined for Flexible File Layout) in XDR. 7653 */ 7654 addrlen = NFSM_RNDUP(strlen(addr)) + NFSM_RNDUP(strlen(netprot)) + 7655 9 * NFSX_UNSIGNED; 7656 ds->nfsdev_flexaddrlen = addrlen; 7657 tl = malloc(addrlen, M_NFSDSTATE, M_WAITOK | M_ZERO); 7658 ds->nfsdev_flexaddr = (char *)tl; 7659 *tl++ = txdr_unsigned(1); /* One multipath entry. */ 7660 /* The netaddr for this one entry. */ 7661 *tl++ = txdr_unsigned(strlen(netprot)); 7662 NFSBCOPY(netprot, tl, strlen(netprot)); 7663 tl += (NFSM_RNDUP(strlen(netprot)) / NFSX_UNSIGNED); 7664 *tl++ = txdr_unsigned(strlen(addr)); 7665 NFSBCOPY(addr, tl, strlen(addr)); 7666 tl += (NFSM_RNDUP(strlen(addr)) / NFSX_UNSIGNED); 7667 *tl++ = txdr_unsigned(1); /* One NFS Version. */ 7668 *tl++ = txdr_unsigned(NFS_VER4); /* NFSv4. */ 7669 *tl++ = txdr_unsigned(NFSV41_MINORVERSION); /* Minor version 1. */ 7670 *tl++ = txdr_unsigned(NFS_SRVMAXIO); /* DS max rsize. */ 7671 *tl++ = txdr_unsigned(NFS_SRVMAXIO); /* DS max wsize. */ 7672 *tl = newnfs_true; /* Tightly coupled. */ 7673 7674 ds->nfsdev_hostnamelen = strlen(dnshost); 7675 ds->nfsdev_host = malloc(ds->nfsdev_hostnamelen + 1, M_NFSDSTATE, 7676 M_WAITOK); 7677 NFSBCOPY(dnshost, ds->nfsdev_host, ds->nfsdev_hostnamelen + 1); 7678 } 7679 7680 7681 /* 7682 * Create the device id list. 7683 * Return 0 if the nfsd threads are to run and ENXIO if the "-p" argument 7684 * is misconfigured. 7685 */ 7686 int 7687 nfsrv_createdevids(struct nfsd_nfsd_args *args, NFSPROC_T *p) 7688 { 7689 struct nfsdevice *ds; 7690 char *addrp, *dnshostp, *dspathp; 7691 int error, i; 7692 7693 addrp = args->addr; 7694 dnshostp = args->dnshost; 7695 dspathp = args->dspath; 7696 nfsrv_maxpnfsmirror = args->mirrorcnt; 7697 if (addrp == NULL || dnshostp == NULL || dspathp == NULL) 7698 return (0); 7699 7700 /* 7701 * Loop around for each nul-terminated string in args->addr, 7702 * args->dnshost and args->dnspath. 7703 */ 7704 while (addrp < (args->addr + args->addrlen) && 7705 dnshostp < (args->dnshost + args->dnshostlen) && 7706 dspathp < (args->dspath + args->dspathlen)) { 7707 error = nfsrv_setdsserver(dspathp, p, &ds); 7708 if (error != 0) { 7709 /* Free all DS servers. */ 7710 nfsrv_freealldevids(); 7711 nfsrv_devidcnt = 0; 7712 return (ENXIO); 7713 } 7714 nfsrv_allocdevid(ds, addrp, dnshostp); 7715 addrp += (strlen(addrp) + 1); 7716 dnshostp += (strlen(dnshostp) + 1); 7717 dspathp += (strlen(dspathp) + 1); 7718 } 7719 if (nfsrv_devidcnt < nfsrv_maxpnfsmirror) { 7720 /* Free all DS servers. */ 7721 nfsrv_freealldevids(); 7722 nfsrv_devidcnt = 0; 7723 nfsrv_maxpnfsmirror = 1; 7724 return (ENXIO); 7725 } 7726 /* We can fail at most one less DS than the mirror level. */ 7727 nfsrv_faildscnt = nfsrv_maxpnfsmirror - 1; 7728 7729 /* 7730 * Allocate the nfslayout hash table now, since this is a pNFS server. 7731 * Make it 1% of the high water mark and at least 100. 7732 */ 7733 if (nfslayouthash == NULL) { 7734 nfsrv_layouthashsize = nfsrv_layouthighwater / 100; 7735 if (nfsrv_layouthashsize < 100) 7736 nfsrv_layouthashsize = 100; 7737 nfslayouthash = mallocarray(nfsrv_layouthashsize, 7738 sizeof(struct nfslayouthash), M_NFSDSESSION, M_WAITOK | 7739 M_ZERO); 7740 for (i = 0; i < nfsrv_layouthashsize; i++) { 7741 mtx_init(&nfslayouthash[i].mtx, "nfslm", NULL, MTX_DEF); 7742 TAILQ_INIT(&nfslayouthash[i].list); 7743 } 7744 } 7745 return (0); 7746 } 7747 7748 /* 7749 * Free all device ids. 7750 */ 7751 static void 7752 nfsrv_freealldevids(void) 7753 { 7754 struct nfsdevice *ds, *nds; 7755 7756 TAILQ_FOREACH_SAFE(ds, &nfsrv_devidhead, nfsdev_list, nds) 7757 nfsrv_freedevid(ds); 7758 } 7759 7760 /* 7761 * Check to see if there is a Read/Write Layout plus either: 7762 * - A Write Delegation 7763 * or 7764 * - An Open with Write_access. 7765 * Return 1 if this is the case and 0 otherwise. 7766 * This function is used by nfsrv_proxyds() to decide if doing a Proxy 7767 * Getattr RPC to the Data Server (DS) is necessary. 7768 */ 7769 #define NFSCLIDVECSIZE 6 7770 APPLESTATIC int 7771 nfsrv_checkdsattr(struct nfsrv_descript *nd, vnode_t vp, NFSPROC_T *p) 7772 { 7773 fhandle_t fh, *tfhp; 7774 struct nfsstate *stp; 7775 struct nfslayout *lyp; 7776 struct nfslayouthash *lhyp; 7777 struct nfslockhashhead *hp; 7778 struct nfslockfile *lfp; 7779 nfsquad_t clid[NFSCLIDVECSIZE]; 7780 int clidcnt, ret; 7781 7782 ret = nfsvno_getfh(vp, &fh, p); 7783 if (ret != 0) 7784 return (0); 7785 7786 /* First check for a Read/Write Layout. */ 7787 clidcnt = 0; 7788 lhyp = NFSLAYOUTHASH(&fh); 7789 NFSLOCKLAYOUT(lhyp); 7790 TAILQ_FOREACH(lyp, &lhyp->list, lay_list) { 7791 if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 && 7792 ((lyp->lay_flags & NFSLAY_RW) != 0 || 7793 ((lyp->lay_flags & NFSLAY_READ) != 0 && 7794 nfsrv_pnfsatime != 0))) { 7795 if (clidcnt < NFSCLIDVECSIZE) 7796 clid[clidcnt].qval = lyp->lay_clientid.qval; 7797 clidcnt++; 7798 } 7799 } 7800 NFSUNLOCKLAYOUT(lhyp); 7801 if (clidcnt == 0) { 7802 /* None found, so return 0. */ 7803 return (0); 7804 } 7805 7806 /* Get the nfslockfile for this fh. */ 7807 NFSLOCKSTATE(); 7808 hp = NFSLOCKHASH(&fh); 7809 LIST_FOREACH(lfp, hp, lf_hash) { 7810 tfhp = &lfp->lf_fh; 7811 if (NFSVNO_CMPFH(&fh, tfhp)) 7812 break; 7813 } 7814 if (lfp == NULL) { 7815 /* None found, so return 0. */ 7816 NFSUNLOCKSTATE(); 7817 return (0); 7818 } 7819 7820 /* Now, look for a Write delegation for this clientid. */ 7821 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 7822 if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0 && 7823 nfsrv_fndclid(clid, stp->ls_clp->lc_clientid, clidcnt) != 0) 7824 break; 7825 } 7826 if (stp != NULL) { 7827 /* Found one, so return 1. */ 7828 NFSUNLOCKSTATE(); 7829 return (1); 7830 } 7831 7832 /* No Write delegation, so look for an Open with Write_access. */ 7833 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 7834 KASSERT((stp->ls_flags & NFSLCK_OPEN) != 0, 7835 ("nfsrv_checkdsattr: Non-open in Open list\n")); 7836 if ((stp->ls_flags & NFSLCK_WRITEACCESS) != 0 && 7837 nfsrv_fndclid(clid, stp->ls_clp->lc_clientid, clidcnt) != 0) 7838 break; 7839 } 7840 NFSUNLOCKSTATE(); 7841 if (stp != NULL) 7842 return (1); 7843 return (0); 7844 } 7845 7846 /* 7847 * Look for a matching clientid in the vector. Return 1 if one might match. 7848 */ 7849 static int 7850 nfsrv_fndclid(nfsquad_t *clidvec, nfsquad_t clid, int clidcnt) 7851 { 7852 int i; 7853 7854 /* If too many for the vector, return 1 since there might be a match. */ 7855 if (clidcnt > NFSCLIDVECSIZE) 7856 return (1); 7857 7858 for (i = 0; i < clidcnt; i++) 7859 if (clidvec[i].qval == clid.qval) 7860 return (1); 7861 return (0); 7862 } 7863 7864 /* 7865 * Check the don't list for "vp" and see if issuing an rw layout is allowed. 7866 * Return 1 if issuing an rw layout isn't allowed, 0 otherwise. 7867 */ 7868 static int 7869 nfsrv_dontlayout(fhandle_t *fhp) 7870 { 7871 struct nfsdontlist *mrp; 7872 int ret; 7873 7874 if (nfsrv_dontlistlen == 0) 7875 return (0); 7876 ret = 0; 7877 NFSDDONTLISTLOCK(); 7878 LIST_FOREACH(mrp, &nfsrv_dontlisthead, nfsmr_list) { 7879 if (NFSBCMP(fhp, &mrp->nfsmr_fh, sizeof(*fhp)) == 0 && 7880 (mrp->nfsmr_flags & NFSMR_DONTLAYOUT) != 0) { 7881 ret = 1; 7882 break; 7883 } 7884 } 7885 NFSDDONTLISTUNLOCK(); 7886 return (ret); 7887 } 7888 7889 #define PNFSDS_COPYSIZ 65536 7890 /* 7891 * Create a new file on a DS and copy the contents of an extant DS file to it. 7892 * This can be used for recovery of a DS file onto a recovered DS. 7893 * The steps are: 7894 * - When called, the MDS file's vnode is locked, blocking LayoutGet operations. 7895 * - Disable issuing of read/write layouts for the file via the nfsdontlist, 7896 * so that they will be disabled after the MDS file's vnode is unlocked. 7897 * - Set up the nfsrv_recalllist so that recall of read/write layouts can 7898 * be done. 7899 * - Unlock the MDS file's vnode, so that the client(s) can perform proxied 7900 * writes, LayoutCommits and LayoutReturns for the file when completing the 7901 * LayoutReturn requested by the LayoutRecall callback. 7902 * - Issue a LayoutRecall callback for all read/write layouts and wait for 7903 * them to be returned. (If the LayoutRecall callback replies 7904 * NFSERR_NOMATCHLAYOUT, they are gone and no LayoutReturn is needed.) 7905 * - Exclusively lock the MDS file's vnode. This ensures that no proxied 7906 * writes are in progress or can occur during the DS file copy. 7907 * It also blocks Setattr operations. 7908 * - Create the file on the recovered mirror. 7909 * - Copy the file from the operational DS. 7910 * - Copy any ACL from the MDS file to the new DS file. 7911 * - Set the modify time of the new DS file to that of the MDS file. 7912 * - Update the extended attribute for the MDS file. 7913 * - Enable issuing of rw layouts by deleting the nfsdontlist entry. 7914 * - The caller will unlock the MDS file's vnode allowing operations 7915 * to continue normally, since it is now on the mirror again. 7916 */ 7917 int 7918 nfsrv_copymr(vnode_t vp, vnode_t fvp, vnode_t dvp, struct nfsdevice *ds, 7919 struct pnfsdsfile *pf, struct pnfsdsfile *wpf, int mirrorcnt, 7920 struct ucred *cred, NFSPROC_T *p) 7921 { 7922 struct nfsdontlist *mrp, *nmrp; 7923 struct nfslayouthash *lhyp; 7924 struct nfslayout *lyp, *nlyp; 7925 struct nfslayouthead thl; 7926 struct mount *mp; 7927 struct acl *aclp; 7928 struct vattr va; 7929 struct timespec mtime; 7930 fhandle_t fh; 7931 vnode_t tvp; 7932 off_t rdpos, wrpos; 7933 ssize_t aresid; 7934 char *dat; 7935 int didprintf, ret, retacl, xfer; 7936 7937 ASSERT_VOP_LOCKED(fvp, "nfsrv_copymr fvp"); 7938 ASSERT_VOP_LOCKED(vp, "nfsrv_copymr vp"); 7939 /* 7940 * Allocate a nfsdontlist entry and set the NFSMR_DONTLAYOUT flag 7941 * so that no more RW layouts will get issued. 7942 */ 7943 ret = nfsvno_getfh(vp, &fh, p); 7944 if (ret != 0) { 7945 NFSD_DEBUG(4, "nfsrv_copymr: getfh=%d\n", ret); 7946 return (ret); 7947 } 7948 nmrp = malloc(sizeof(*nmrp), M_NFSDSTATE, M_WAITOK); 7949 nmrp->nfsmr_flags = NFSMR_DONTLAYOUT; 7950 NFSBCOPY(&fh, &nmrp->nfsmr_fh, sizeof(fh)); 7951 NFSDDONTLISTLOCK(); 7952 LIST_FOREACH(mrp, &nfsrv_dontlisthead, nfsmr_list) { 7953 if (NFSBCMP(&fh, &mrp->nfsmr_fh, sizeof(fh)) == 0) 7954 break; 7955 } 7956 if (mrp == NULL) { 7957 LIST_INSERT_HEAD(&nfsrv_dontlisthead, nmrp, nfsmr_list); 7958 mrp = nmrp; 7959 nmrp = NULL; 7960 nfsrv_dontlistlen++; 7961 NFSD_DEBUG(4, "nfsrv_copymr: in dontlist\n"); 7962 } else { 7963 NFSDDONTLISTUNLOCK(); 7964 free(nmrp, M_NFSDSTATE); 7965 NFSD_DEBUG(4, "nfsrv_copymr: dup dontlist\n"); 7966 return (ENXIO); 7967 } 7968 NFSDDONTLISTUNLOCK(); 7969 7970 /* 7971 * Search for all RW layouts for this file. Move them to the 7972 * recall list, so they can be recalled and their return noted. 7973 */ 7974 lhyp = NFSLAYOUTHASH(&fh); 7975 NFSDRECALLLOCK(); 7976 NFSLOCKLAYOUT(lhyp); 7977 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) { 7978 if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 && 7979 (lyp->lay_flags & NFSLAY_RW) != 0) { 7980 TAILQ_REMOVE(&lhyp->list, lyp, lay_list); 7981 TAILQ_INSERT_HEAD(&nfsrv_recalllisthead, lyp, lay_list); 7982 lyp->lay_trycnt = 0; 7983 } 7984 } 7985 NFSUNLOCKLAYOUT(lhyp); 7986 NFSDRECALLUNLOCK(); 7987 7988 ret = 0; 7989 didprintf = 0; 7990 TAILQ_INIT(&thl); 7991 /* Unlock the MDS vp, so that a LayoutReturn can be done on it. */ 7992 NFSVOPUNLOCK(vp, 0); 7993 /* Now, do a recall for all layouts not yet recalled. */ 7994 tryagain: 7995 NFSDRECALLLOCK(); 7996 TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) { 7997 if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 && 7998 (lyp->lay_flags & NFSLAY_RECALL) == 0) { 7999 lyp->lay_flags |= NFSLAY_RECALL; 8000 /* 8001 * The layout stateid.seqid needs to be incremented 8002 * before doing a LAYOUT_RECALL callback. 8003 */ 8004 if (++lyp->lay_stateid.seqid == 0) 8005 lyp->lay_stateid.seqid = 1; 8006 NFSDRECALLUNLOCK(); 8007 nfsrv_recalllayout(lyp->lay_clientid, &lyp->lay_stateid, 8008 &lyp->lay_fh, lyp, &nfsrv_recalllisthead, 8009 lyp->lay_type, p); 8010 NFSD_DEBUG(4, "nfsrv_copymr: recalled layout\n"); 8011 goto tryagain; 8012 } 8013 } 8014 8015 /* Now wait for them to be returned. */ 8016 tryagain2: 8017 TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) { 8018 if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0) { 8019 if ((lyp->lay_flags & NFSLAY_RETURNED) != 0) { 8020 TAILQ_REMOVE(&nfsrv_recalllisthead, lyp, 8021 lay_list); 8022 TAILQ_INSERT_HEAD(&thl, lyp, lay_list); 8023 NFSD_DEBUG(4, 8024 "nfsrv_copymr: layout returned\n"); 8025 } else { 8026 ret = mtx_sleep(lyp, NFSDRECALLMUTEXPTR, 8027 PVFS | PCATCH, "nfsmrl", hz); 8028 NFSD_DEBUG(4, "nfsrv_copymr: aft sleep=%d\n", 8029 ret); 8030 if (ret == EINTR || ret == ERESTART) 8031 break; 8032 if ((lyp->lay_flags & NFSLAY_RETURNED) == 0 && 8033 didprintf == 0) { 8034 printf("nfsrv_copymr: layout not " 8035 "returned\n"); 8036 didprintf = 1; 8037 } 8038 } 8039 goto tryagain2; 8040 } 8041 } 8042 NFSDRECALLUNLOCK(); 8043 /* We can now get rid of the layouts that have been returned. */ 8044 TAILQ_FOREACH_SAFE(lyp, &thl, lay_list, nlyp) 8045 nfsrv_freelayout(&thl, lyp); 8046 8047 /* 8048 * LK_EXCLUSIVE lock the MDS vnode, so that any 8049 * proxied writes through the MDS will be blocked until we have 8050 * completed the copy and update of the extended attributes. 8051 * This will also ensure that any attributes and ACL will not be 8052 * changed until the copy is complete. 8053 */ 8054 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 8055 if ((vp->v_iflag & VI_DOOMED) != 0) { 8056 NFSD_DEBUG(4, "nfsrv_copymr: lk_exclusive doomed\n"); 8057 ret = ESTALE; 8058 } 8059 8060 /* Create the data file on the recovered DS. */ 8061 if (ret == 0) 8062 ret = nfsrv_createdsfile(vp, &fh, pf, dvp, ds, cred, p, &tvp); 8063 8064 /* Copy the DS file, if created successfully. */ 8065 if (ret == 0) { 8066 /* 8067 * Get any NFSv4 ACL on the MDS file, so that it can be set 8068 * on the new DS file. 8069 */ 8070 aclp = acl_alloc(M_WAITOK | M_ZERO); 8071 retacl = VOP_GETACL(vp, ACL_TYPE_NFS4, aclp, cred, p); 8072 if (retacl != 0 && retacl != ENOATTR) 8073 NFSD_DEBUG(1, "nfsrv_copymr: vop_getacl=%d\n", retacl); 8074 dat = malloc(PNFSDS_COPYSIZ, M_TEMP, M_WAITOK); 8075 rdpos = wrpos = 0; 8076 mp = NULL; 8077 ret = vn_start_write(tvp, &mp, V_WAIT | PCATCH); 8078 aresid = 0; 8079 while (ret == 0 && aresid == 0) { 8080 ret = vn_rdwr(UIO_READ, fvp, dat, PNFSDS_COPYSIZ, 8081 rdpos, UIO_SYSSPACE, IO_NODELOCKED, cred, NULL, 8082 &aresid, p); 8083 xfer = PNFSDS_COPYSIZ - aresid; 8084 if (ret == 0 && xfer > 0) { 8085 rdpos += xfer; 8086 ret = vn_rdwr(UIO_WRITE, tvp, dat, xfer, 8087 wrpos, UIO_SYSSPACE, IO_NODELOCKED, 8088 cred, NULL, NULL, p); 8089 if (ret == 0) 8090 wrpos += xfer; 8091 } 8092 } 8093 8094 /* If there is an ACL and the copy succeeded, set the ACL. */ 8095 if (ret == 0 && retacl == 0) { 8096 ret = VOP_SETACL(tvp, ACL_TYPE_NFS4, aclp, cred, p); 8097 /* 8098 * Don't consider these as errors, since VOP_GETACL() 8099 * can return an ACL when they are not actually 8100 * supported. For example, for UFS, VOP_GETACL() 8101 * will return a trivial ACL based on the uid/gid/mode 8102 * when there is no ACL on the file. 8103 * This case should be recognized as a trivial ACL 8104 * by UFS's VOP_SETACL() and succeed, but... 8105 */ 8106 if (ret == ENOATTR || ret == EOPNOTSUPP || ret == EPERM) 8107 ret = 0; 8108 } 8109 8110 if (mp != NULL) 8111 vn_finished_write(mp); 8112 if (ret == 0) 8113 ret = VOP_FSYNC(tvp, MNT_WAIT, p); 8114 8115 /* Set the DS data file's modify time that of the MDS file. */ 8116 if (ret == 0) 8117 ret = VOP_GETATTR(vp, &va, cred); 8118 if (ret == 0) { 8119 mtime = va.va_mtime; 8120 VATTR_NULL(&va); 8121 va.va_mtime = mtime; 8122 ret = VOP_SETATTR(tvp, &va, cred); 8123 } 8124 8125 vput(tvp); 8126 acl_free(aclp); 8127 free(dat, M_TEMP); 8128 } 8129 8130 /* Update the extended attributes for the newly created DS file. */ 8131 if (ret == 0) { 8132 mp = NULL; 8133 ret = vn_start_write(vp, &mp, V_WAIT | PCATCH); 8134 if (ret == 0) 8135 ret = vn_extattr_set(vp, IO_NODELOCKED, 8136 EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile", 8137 sizeof(*wpf) * mirrorcnt, (char *)wpf, p); 8138 if (mp != NULL) 8139 vn_finished_write(mp); 8140 } 8141 8142 /* Get rid of the dontlist entry, so that Layouts can be issued. */ 8143 NFSDDONTLISTLOCK(); 8144 LIST_REMOVE(mrp, nfsmr_list); 8145 NFSDDONTLISTUNLOCK(); 8146 free(mrp, M_NFSDSTATE); 8147 return (ret); 8148 } 8149 8150 /* 8151 * Create a data storage file on the recovered DS. 8152 */ 8153 static int 8154 nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf, 8155 vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p, 8156 vnode_t *tvpp) 8157 { 8158 struct vattr va, nva; 8159 int error; 8160 8161 /* Make data file name based on FH. */ 8162 error = VOP_GETATTR(vp, &va, cred); 8163 if (error == 0) { 8164 /* Set the attributes for "vp" to Setattr the DS vp. */ 8165 VATTR_NULL(&nva); 8166 nva.va_uid = va.va_uid; 8167 nva.va_gid = va.va_gid; 8168 nva.va_mode = va.va_mode; 8169 nva.va_size = 0; 8170 VATTR_NULL(&va); 8171 va.va_type = VREG; 8172 va.va_mode = nva.va_mode; 8173 NFSD_DEBUG(4, "nfsrv_dscreatefile: dvp=%p pf=%p\n", dvp, pf); 8174 error = nfsrv_dscreate(dvp, &va, &nva, fhp, pf, NULL, 8175 pf->dsf_filename, cred, p, tvpp); 8176 } 8177 return (error); 8178 } 8179 8180 /* 8181 * Look up the MDS file shared locked, and then get the extended attribute 8182 * to find the extant DS file to be copied to the new mirror. 8183 * If successful, *vpp is set to the MDS file's vp and *nvpp is 8184 * set to a DS data file for the MDS file, both exclusively locked. 8185 * The "buf" argument has the pnfsdsfile structure from the MDS file 8186 * in it and buflen is set to its length. 8187 */ 8188 int 8189 nfsrv_mdscopymr(char *mdspathp, char *dspathp, char *curdspathp, char *buf, 8190 int *buflenp, char *fname, NFSPROC_T *p, struct vnode **vpp, 8191 struct vnode **nvpp, struct pnfsdsfile **pfp, struct nfsdevice **dsp, 8192 struct nfsdevice **fdsp) 8193 { 8194 struct nameidata nd; 8195 struct vnode *vp, *curvp; 8196 struct pnfsdsfile *pf; 8197 struct nfsmount *nmp, *curnmp; 8198 int dsdir, error, mirrorcnt, ippos; 8199 8200 vp = NULL; 8201 curvp = NULL; 8202 curnmp = NULL; 8203 *dsp = NULL; 8204 *fdsp = NULL; 8205 if (dspathp == NULL && curdspathp != NULL) 8206 return (EPERM); 8207 8208 /* 8209 * Look up the MDS file shared locked. The lock will be upgraded 8210 * to an exclusive lock after any rw layouts have been returned. 8211 */ 8212 NFSD_DEBUG(4, "mdsopen path=%s\n", mdspathp); 8213 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE, 8214 mdspathp, p); 8215 error = namei(&nd); 8216 NFSD_DEBUG(4, "lookup=%d\n", error); 8217 if (error != 0) 8218 return (error); 8219 if (nd.ni_vp->v_type != VREG) { 8220 vput(nd.ni_vp); 8221 NFSD_DEBUG(4, "mdspath not reg\n"); 8222 return (EISDIR); 8223 } 8224 vp = nd.ni_vp; 8225 8226 if (curdspathp != NULL) { 8227 /* 8228 * Look up the current DS path and find the nfsdev structure for 8229 * it. 8230 */ 8231 NFSD_DEBUG(4, "curmdsdev path=%s\n", curdspathp); 8232 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, 8233 UIO_SYSSPACE, curdspathp, p); 8234 error = namei(&nd); 8235 NFSD_DEBUG(4, "ds lookup=%d\n", error); 8236 if (error != 0) { 8237 vput(vp); 8238 return (error); 8239 } 8240 if (nd.ni_vp->v_type != VDIR) { 8241 vput(nd.ni_vp); 8242 vput(vp); 8243 NFSD_DEBUG(4, "curdspath not dir\n"); 8244 return (ENOTDIR); 8245 } 8246 if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) { 8247 vput(nd.ni_vp); 8248 vput(vp); 8249 NFSD_DEBUG(4, "curdspath not an NFS mount\n"); 8250 return (ENXIO); 8251 } 8252 curnmp = VFSTONFS(nd.ni_vp->v_mount); 8253 8254 /* Search the nfsdev list for a match. */ 8255 NFSDDSLOCK(); 8256 *fdsp = nfsv4_findmirror(curnmp); 8257 NFSDDSUNLOCK(); 8258 if (*fdsp == NULL) 8259 curnmp = NULL; 8260 if (curnmp == NULL) { 8261 vput(nd.ni_vp); 8262 vput(vp); 8263 NFSD_DEBUG(4, "mdscopymr: no current ds\n"); 8264 return (ENXIO); 8265 } 8266 curvp = nd.ni_vp; 8267 } 8268 8269 if (dspathp != NULL) { 8270 /* Look up the nfsdev path and find the nfsdev structure. */ 8271 NFSD_DEBUG(4, "mdsdev path=%s\n", dspathp); 8272 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, 8273 UIO_SYSSPACE, dspathp, p); 8274 error = namei(&nd); 8275 NFSD_DEBUG(4, "ds lookup=%d\n", error); 8276 if (error != 0) { 8277 vput(vp); 8278 if (curvp != NULL) 8279 vput(curvp); 8280 return (error); 8281 } 8282 if (nd.ni_vp->v_type != VDIR || nd.ni_vp == curvp) { 8283 vput(nd.ni_vp); 8284 vput(vp); 8285 if (curvp != NULL) 8286 vput(curvp); 8287 NFSD_DEBUG(4, "dspath not dir\n"); 8288 if (nd.ni_vp == curvp) 8289 return (EPERM); 8290 return (ENOTDIR); 8291 } 8292 if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) { 8293 vput(nd.ni_vp); 8294 vput(vp); 8295 if (curvp != NULL) 8296 vput(curvp); 8297 NFSD_DEBUG(4, "dspath not an NFS mount\n"); 8298 return (ENXIO); 8299 } 8300 nmp = VFSTONFS(nd.ni_vp->v_mount); 8301 8302 /* Search the nfsdev list for a match. */ 8303 NFSDDSLOCK(); 8304 *dsp = nfsv4_findmirror(nmp); 8305 NFSDDSUNLOCK(); 8306 if (*dsp == NULL) { 8307 vput(nd.ni_vp); 8308 vput(vp); 8309 if (curvp != NULL) 8310 vput(curvp); 8311 NFSD_DEBUG(4, "mdscopymr: no ds\n"); 8312 return (ENXIO); 8313 } 8314 } else { 8315 nd.ni_vp = NULL; 8316 nmp = NULL; 8317 } 8318 8319 /* 8320 * Get a vp for an available DS data file using the extended 8321 * attribute on the MDS file. 8322 * If there is a valid entry for the new DS in the extended attribute 8323 * on the MDS file (as checked via the nmp argument), 8324 * nfsrv_dsgetsockmnt() returns EEXIST, so no copying will occur. 8325 */ 8326 error = nfsrv_dsgetsockmnt(vp, 0, buf, buflenp, &mirrorcnt, p, 8327 NULL, NULL, NULL, fname, nvpp, &nmp, curnmp, &ippos, &dsdir); 8328 if (curvp != NULL) 8329 vput(curvp); 8330 if (nd.ni_vp == NULL) { 8331 if (error == 0 && nmp != NULL) { 8332 /* Search the nfsdev list for a match. */ 8333 NFSDDSLOCK(); 8334 *dsp = nfsv4_findmirror(nmp); 8335 NFSDDSUNLOCK(); 8336 } 8337 if (error == 0 && (nmp == NULL || *dsp == NULL)) { 8338 if (nvpp != NULL && *nvpp != NULL) { 8339 vput(*nvpp); 8340 *nvpp = NULL; 8341 } 8342 error = ENXIO; 8343 } 8344 } else 8345 vput(nd.ni_vp); 8346 8347 /* 8348 * When dspathp != NULL and curdspathp == NULL, this is a recovery 8349 * and is only allowed if there is a 0.0.0.0 IP address entry. 8350 * When curdspathp != NULL, the ippos will be set to that entry. 8351 */ 8352 if (error == 0 && dspathp != NULL && ippos == -1) { 8353 if (nvpp != NULL && *nvpp != NULL) { 8354 vput(*nvpp); 8355 *nvpp = NULL; 8356 } 8357 error = ENXIO; 8358 } 8359 if (error == 0) { 8360 *vpp = vp; 8361 8362 pf = (struct pnfsdsfile *)buf; 8363 if (ippos == -1) { 8364 /* If no zeroip pnfsdsfile, add one. */ 8365 ippos = *buflenp / sizeof(*pf); 8366 *buflenp += sizeof(*pf); 8367 pf += ippos; 8368 pf->dsf_dir = dsdir; 8369 strlcpy(pf->dsf_filename, fname, 8370 sizeof(pf->dsf_filename)); 8371 } else 8372 pf += ippos; 8373 *pfp = pf; 8374 } else 8375 vput(vp); 8376 return (error); 8377 } 8378 8379