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