1 1.7 rin /* $NetBSD: nfs_clntsocket.c,v 1.7 2024/07/05 04:31:54 rin Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.1 pooka * Copyright (c) 1989, 1991, 1993, 1995 5 1.1 pooka * The Regents of the University of California. All rights reserved. 6 1.1 pooka * 7 1.1 pooka * This code is derived from software contributed to Berkeley by 8 1.1 pooka * Rick Macklem at The University of Guelph. 9 1.1 pooka * 10 1.1 pooka * Redistribution and use in source and binary forms, with or without 11 1.1 pooka * modification, are permitted provided that the following conditions 12 1.1 pooka * are met: 13 1.1 pooka * 1. Redistributions of source code must retain the above copyright 14 1.1 pooka * notice, this list of conditions and the following disclaimer. 15 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 pooka * notice, this list of conditions and the following disclaimer in the 17 1.1 pooka * documentation and/or other materials provided with the distribution. 18 1.1 pooka * 3. Neither the name of the University nor the names of its contributors 19 1.1 pooka * may be used to endorse or promote products derived from this software 20 1.1 pooka * without specific prior written permission. 21 1.1 pooka * 22 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 pooka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 pooka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 pooka * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 pooka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 pooka * SUCH DAMAGE. 33 1.1 pooka * 34 1.1 pooka * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95 35 1.1 pooka */ 36 1.1 pooka 37 1.1 pooka /* 38 1.1 pooka * Socket operations for use by nfs 39 1.1 pooka */ 40 1.1 pooka 41 1.1 pooka #include <sys/cdefs.h> 42 1.7 rin __KERNEL_RCSID(0, "$NetBSD: nfs_clntsocket.c,v 1.7 2024/07/05 04:31:54 rin Exp $"); 43 1.1 pooka 44 1.1 pooka #ifdef _KERNEL_OPT 45 1.1 pooka #include "opt_nfs.h" 46 1.1 pooka #include "opt_mbuftrace.h" 47 1.1 pooka #endif 48 1.1 pooka 49 1.1 pooka #include <sys/param.h> 50 1.1 pooka #include <sys/systm.h> 51 1.1 pooka #include <sys/evcnt.h> 52 1.1 pooka #include <sys/callout.h> 53 1.1 pooka #include <sys/proc.h> 54 1.1 pooka #include <sys/mount.h> 55 1.1 pooka #include <sys/kernel.h> 56 1.1 pooka #include <sys/kmem.h> 57 1.1 pooka #include <sys/mbuf.h> 58 1.1 pooka #include <sys/vnode.h> 59 1.1 pooka #include <sys/domain.h> 60 1.1 pooka #include <sys/protosw.h> 61 1.1 pooka #include <sys/socket.h> 62 1.1 pooka #include <sys/socketvar.h> 63 1.1 pooka #include <sys/syslog.h> 64 1.1 pooka #include <sys/tprintf.h> 65 1.1 pooka #include <sys/namei.h> 66 1.1 pooka #include <sys/signal.h> 67 1.1 pooka #include <sys/signalvar.h> 68 1.1 pooka #include <sys/kauth.h> 69 1.1 pooka 70 1.1 pooka #include <netinet/in.h> 71 1.1 pooka #include <netinet/tcp.h> 72 1.1 pooka 73 1.1 pooka #include <nfs/rpcv2.h> 74 1.1 pooka #include <nfs/nfsproto.h> 75 1.1 pooka #include <nfs/nfs.h> 76 1.1 pooka #include <nfs/xdr_subs.h> 77 1.1 pooka #include <nfs/nfsm_subs.h> 78 1.1 pooka #include <nfs/nfsmount.h> 79 1.1 pooka #include <nfs/nfsnode.h> 80 1.1 pooka #include <nfs/nfsrtt.h> 81 1.1 pooka #include <nfs/nfs_var.h> 82 1.1 pooka 83 1.1 pooka static int nfs_sndlock(struct nfsmount *, struct nfsreq *); 84 1.1 pooka static void nfs_sndunlock(struct nfsmount *); 85 1.1 pooka 86 1.1 pooka /* 87 1.1 pooka * Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all 88 1.1 pooka * done by soreceive(), but for SOCK_STREAM we must deal with the Record 89 1.1 pooka * Mark and consolidate the data into a new mbuf list. 90 1.1 pooka * nb: Sometimes TCP passes the data up to soreceive() in long lists of 91 1.1 pooka * small mbufs. 92 1.1 pooka * For SOCK_STREAM we must be very careful to read an entire record once 93 1.1 pooka * we have read any of it, even if the system call has been interrupted. 94 1.1 pooka */ 95 1.1 pooka static int 96 1.1 pooka nfs_receive(struct nfsreq *rep, struct mbuf **aname, struct mbuf **mp, 97 1.1 pooka struct lwp *l) 98 1.1 pooka { 99 1.1 pooka struct socket *so; 100 1.1 pooka struct uio auio; 101 1.1 pooka struct iovec aio; 102 1.1 pooka struct mbuf *m; 103 1.1 pooka struct mbuf *control; 104 1.1 pooka u_int32_t len; 105 1.1 pooka struct mbuf **getnam; 106 1.1 pooka int error, sotype, rcvflg; 107 1.1 pooka 108 1.1 pooka /* 109 1.1 pooka * Set up arguments for soreceive() 110 1.1 pooka */ 111 1.1 pooka *mp = NULL; 112 1.1 pooka *aname = NULL; 113 1.1 pooka sotype = rep->r_nmp->nm_sotype; 114 1.1 pooka 115 1.1 pooka /* 116 1.1 pooka * For reliable protocols, lock against other senders/receivers 117 1.1 pooka * in case a reconnect is necessary. 118 1.1 pooka * For SOCK_STREAM, first get the Record Mark to find out how much 119 1.1 pooka * more there is to get. 120 1.1 pooka * We must lock the socket against other receivers 121 1.1 pooka * until we have an entire rpc request/reply. 122 1.1 pooka */ 123 1.1 pooka if (sotype != SOCK_DGRAM) { 124 1.1 pooka error = nfs_sndlock(rep->r_nmp, rep); 125 1.1 pooka if (error) 126 1.1 pooka return (error); 127 1.1 pooka tryagain: 128 1.1 pooka /* 129 1.1 pooka * Check for fatal errors and resending request. 130 1.1 pooka */ 131 1.1 pooka /* 132 1.1 pooka * Ugh: If a reconnect attempt just happened, nm_so 133 1.1 pooka * would have changed. NULL indicates a failed 134 1.1 pooka * attempt that has essentially shut down this 135 1.1 pooka * mount point. 136 1.1 pooka */ 137 1.1 pooka if (rep->r_mrep || (rep->r_flags & R_SOFTTERM)) { 138 1.1 pooka nfs_sndunlock(rep->r_nmp); 139 1.1 pooka return (EINTR); 140 1.1 pooka } 141 1.1 pooka so = rep->r_nmp->nm_so; 142 1.1 pooka if (!so) { 143 1.1 pooka error = nfs_reconnect(rep); 144 1.1 pooka if (error) { 145 1.1 pooka nfs_sndunlock(rep->r_nmp); 146 1.1 pooka return (error); 147 1.1 pooka } 148 1.1 pooka goto tryagain; 149 1.1 pooka } 150 1.1 pooka while (rep->r_flags & R_MUSTRESEND) { 151 1.1 pooka m = m_copym(rep->r_mreq, 0, M_COPYALL, M_WAIT); 152 1.1 pooka nfsstats.rpcretries++; 153 1.1 pooka rep->r_rtt = 0; 154 1.1 pooka rep->r_flags &= ~R_TIMING; 155 1.1 pooka error = nfs_send(so, rep->r_nmp->nm_nam, m, rep, l); 156 1.1 pooka if (error) { 157 1.1 pooka if (error == EINTR || error == ERESTART || 158 1.1 pooka (error = nfs_reconnect(rep)) != 0) { 159 1.1 pooka nfs_sndunlock(rep->r_nmp); 160 1.1 pooka return (error); 161 1.1 pooka } 162 1.1 pooka goto tryagain; 163 1.1 pooka } 164 1.1 pooka } 165 1.1 pooka nfs_sndunlock(rep->r_nmp); 166 1.1 pooka if (sotype == SOCK_STREAM) { 167 1.1 pooka aio.iov_base = (void *) &len; 168 1.1 pooka aio.iov_len = sizeof(u_int32_t); 169 1.1 pooka auio.uio_iov = &aio; 170 1.1 pooka auio.uio_iovcnt = 1; 171 1.1 pooka auio.uio_rw = UIO_READ; 172 1.1 pooka auio.uio_offset = 0; 173 1.1 pooka auio.uio_resid = sizeof(u_int32_t); 174 1.1 pooka UIO_SETUP_SYSSPACE(&auio); 175 1.1 pooka do { 176 1.1 pooka rcvflg = MSG_WAITALL; 177 1.1 pooka error = (*so->so_receive)(so, NULL, &auio, 178 1.1 pooka NULL, NULL, &rcvflg); 179 1.1 pooka if (error == EWOULDBLOCK && rep) { 180 1.1 pooka if (rep->r_flags & R_SOFTTERM) 181 1.1 pooka return (EINTR); 182 1.1 pooka /* 183 1.1 pooka * if it seems that the server died after it 184 1.1 pooka * received our request, set EPIPE so that 185 1.1 pooka * we'll reconnect and retransmit requests. 186 1.1 pooka */ 187 1.1 pooka if (rep->r_rexmit >= rep->r_nmp->nm_retry) { 188 1.1 pooka nfsstats.rpctimeouts++; 189 1.1 pooka error = EPIPE; 190 1.1 pooka } 191 1.1 pooka } 192 1.1 pooka } while (error == EWOULDBLOCK); 193 1.1 pooka if (!error && auio.uio_resid > 0) { 194 1.1 pooka /* 195 1.1 pooka * Don't log a 0 byte receive; it means 196 1.1 pooka * that the socket has been closed, and 197 1.1 pooka * can happen during normal operation 198 1.1 pooka * (forcible unmount or Solaris server). 199 1.1 pooka */ 200 1.1 pooka if (auio.uio_resid != sizeof (u_int32_t)) 201 1.1 pooka log(LOG_INFO, 202 1.1 pooka "short receive (%lu/%lu) from nfs server %s\n", 203 1.1 pooka (u_long)sizeof(u_int32_t) - auio.uio_resid, 204 1.1 pooka (u_long)sizeof(u_int32_t), 205 1.1 pooka rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname); 206 1.1 pooka error = EPIPE; 207 1.1 pooka } 208 1.1 pooka if (error) 209 1.1 pooka goto errout; 210 1.1 pooka len = ntohl(len) & ~0x80000000; 211 1.1 pooka /* 212 1.1 pooka * This is SERIOUS! We are out of sync with the sender 213 1.1 pooka * and forcing a disconnect/reconnect is all I can do. 214 1.1 pooka */ 215 1.1 pooka if (len > NFS_MAXPACKET) { 216 1.1 pooka log(LOG_ERR, "%s (%d) from nfs server %s\n", 217 1.1 pooka "impossible packet length", 218 1.1 pooka len, 219 1.1 pooka rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname); 220 1.1 pooka error = EFBIG; 221 1.1 pooka goto errout; 222 1.1 pooka } 223 1.1 pooka auio.uio_resid = len; 224 1.1 pooka do { 225 1.1 pooka rcvflg = MSG_WAITALL; 226 1.1 pooka error = (*so->so_receive)(so, NULL, 227 1.1 pooka &auio, mp, NULL, &rcvflg); 228 1.1 pooka } while (error == EWOULDBLOCK || error == EINTR || 229 1.1 pooka error == ERESTART); 230 1.1 pooka if (!error && auio.uio_resid > 0) { 231 1.1 pooka if (len != auio.uio_resid) 232 1.1 pooka log(LOG_INFO, 233 1.1 pooka "short receive (%lu/%d) from nfs server %s\n", 234 1.1 pooka (u_long)len - auio.uio_resid, len, 235 1.1 pooka rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname); 236 1.1 pooka error = EPIPE; 237 1.1 pooka } 238 1.1 pooka } else { 239 1.1 pooka /* 240 1.1 pooka * NB: Since uio_resid is big, MSG_WAITALL is ignored 241 1.1 pooka * and soreceive() will return when it has either a 242 1.1 pooka * control msg or a data msg. 243 1.1 pooka * We have no use for control msg., but must grab them 244 1.1 pooka * and then throw them away so we know what is going 245 1.1 pooka * on. 246 1.1 pooka */ 247 1.1 pooka auio.uio_resid = len = 100000000; /* Anything Big */ 248 1.1 pooka /* not need to setup uio_vmspace */ 249 1.1 pooka do { 250 1.1 pooka rcvflg = 0; 251 1.1 pooka error = (*so->so_receive)(so, NULL, 252 1.1 pooka &auio, mp, &control, &rcvflg); 253 1.7 rin m_freem(control); 254 1.1 pooka if (error == EWOULDBLOCK && rep) { 255 1.1 pooka if (rep->r_flags & R_SOFTTERM) 256 1.1 pooka return (EINTR); 257 1.1 pooka } 258 1.1 pooka } while (error == EWOULDBLOCK || 259 1.1 pooka (!error && *mp == NULL && control)); 260 1.1 pooka if ((rcvflg & MSG_EOR) == 0) 261 1.1 pooka printf("Egad!!\n"); 262 1.1 pooka if (!error && *mp == NULL) 263 1.1 pooka error = EPIPE; 264 1.1 pooka len -= auio.uio_resid; 265 1.1 pooka } 266 1.1 pooka errout: 267 1.1 pooka if (error && error != EINTR && error != ERESTART) { 268 1.1 pooka m_freem(*mp); 269 1.1 pooka *mp = NULL; 270 1.1 pooka if (error != EPIPE) 271 1.1 pooka log(LOG_INFO, 272 1.1 pooka "receive error %d from nfs server %s\n", 273 1.1 pooka error, 274 1.1 pooka rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname); 275 1.1 pooka error = nfs_sndlock(rep->r_nmp, rep); 276 1.1 pooka if (!error) 277 1.1 pooka error = nfs_reconnect(rep); 278 1.1 pooka if (!error) 279 1.1 pooka goto tryagain; 280 1.1 pooka else 281 1.1 pooka nfs_sndunlock(rep->r_nmp); 282 1.1 pooka } 283 1.1 pooka } else { 284 1.1 pooka if ((so = rep->r_nmp->nm_so) == NULL) 285 1.1 pooka return (EACCES); 286 1.1 pooka if (so->so_state & SS_ISCONNECTED) 287 1.1 pooka getnam = NULL; 288 1.1 pooka else 289 1.1 pooka getnam = aname; 290 1.1 pooka auio.uio_resid = len = 1000000; 291 1.1 pooka /* not need to setup uio_vmspace */ 292 1.1 pooka do { 293 1.1 pooka rcvflg = 0; 294 1.1 pooka error = (*so->so_receive)(so, getnam, &auio, mp, 295 1.1 pooka NULL, &rcvflg); 296 1.6 christos if (error == EWOULDBLOCK) { 297 1.6 christos int intr = nfs_sigintr(rep->r_nmp, rep, l); 298 1.6 christos if (intr) 299 1.6 christos error = intr; 300 1.6 christos } 301 1.1 pooka } while (error == EWOULDBLOCK); 302 1.1 pooka len -= auio.uio_resid; 303 1.1 pooka if (!error && *mp == NULL) 304 1.1 pooka error = EPIPE; 305 1.1 pooka } 306 1.1 pooka if (error) { 307 1.1 pooka m_freem(*mp); 308 1.1 pooka *mp = NULL; 309 1.1 pooka } 310 1.1 pooka return (error); 311 1.1 pooka } 312 1.1 pooka 313 1.1 pooka /* 314 1.1 pooka * Implement receipt of reply on a socket. 315 1.1 pooka * We must search through the list of received datagrams matching them 316 1.1 pooka * with outstanding requests using the xid, until ours is found. 317 1.1 pooka */ 318 1.1 pooka /* ARGSUSED */ 319 1.1 pooka static int 320 1.1 pooka nfs_reply(struct nfsreq *myrep, struct lwp *lwp) 321 1.1 pooka { 322 1.1 pooka struct nfsreq *rep; 323 1.1 pooka struct nfsmount *nmp = myrep->r_nmp; 324 1.1 pooka int32_t t1; 325 1.1 pooka struct mbuf *mrep, *nam, *md; 326 1.1 pooka u_int32_t rxid, *tl; 327 1.1 pooka char *dpos, *cp2; 328 1.5 christos int error, s; 329 1.1 pooka 330 1.1 pooka /* 331 1.1 pooka * Loop around until we get our own reply 332 1.1 pooka */ 333 1.1 pooka for (;;) { 334 1.1 pooka /* 335 1.1 pooka * Lock against other receivers so that I don't get stuck in 336 1.1 pooka * sbwait() after someone else has received my reply for me. 337 1.1 pooka * Also necessary for connection based protocols to avoid 338 1.1 pooka * race conditions during a reconnect. 339 1.1 pooka */ 340 1.1 pooka error = nfs_rcvlock(nmp, myrep); 341 1.1 pooka if (error == EALREADY) 342 1.1 pooka return (0); 343 1.1 pooka if (error) 344 1.1 pooka return (error); 345 1.1 pooka /* 346 1.1 pooka * Get the next Rpc reply off the socket 347 1.1 pooka */ 348 1.1 pooka 349 1.1 pooka mutex_enter(&nmp->nm_lock); 350 1.1 pooka nmp->nm_waiters++; 351 1.1 pooka mutex_exit(&nmp->nm_lock); 352 1.1 pooka 353 1.1 pooka error = nfs_receive(myrep, &nam, &mrep, lwp); 354 1.1 pooka 355 1.1 pooka mutex_enter(&nmp->nm_lock); 356 1.1 pooka nmp->nm_waiters--; 357 1.1 pooka cv_signal(&nmp->nm_disconcv); 358 1.1 pooka mutex_exit(&nmp->nm_lock); 359 1.1 pooka 360 1.1 pooka if (error) { 361 1.1 pooka nfs_rcvunlock(nmp); 362 1.1 pooka 363 1.1 pooka if (nmp->nm_iflag & NFSMNT_DISMNT) { 364 1.1 pooka /* 365 1.1 pooka * Oops, we're going away now.. 366 1.1 pooka */ 367 1.1 pooka return error; 368 1.1 pooka } 369 1.1 pooka /* 370 1.1 pooka * Ignore routing errors on connectionless protocols? ? 371 1.1 pooka */ 372 1.1 pooka if (NFSIGNORE_SOERROR(nmp->nm_soflags, error)) { 373 1.1 pooka nmp->nm_so->so_error = 0; 374 1.1 pooka #ifdef DEBUG 375 1.1 pooka if (ratecheck(&nfs_reply_last_err_time, 376 1.1 pooka &nfs_err_interval)) 377 1.1 pooka printf("%s: ignoring error %d\n", 378 1.1 pooka __func__, error); 379 1.1 pooka #endif 380 1.1 pooka continue; 381 1.1 pooka } 382 1.1 pooka return (error); 383 1.1 pooka } 384 1.7 rin m_freem(nam); 385 1.1 pooka 386 1.1 pooka /* 387 1.1 pooka * Get the xid and check that it is an rpc reply 388 1.1 pooka */ 389 1.1 pooka md = mrep; 390 1.1 pooka dpos = mtod(md, void *); 391 1.1 pooka nfsm_dissect(tl, u_int32_t *, 2*NFSX_UNSIGNED); 392 1.1 pooka rxid = *tl++; 393 1.1 pooka if (*tl != rpc_reply) { 394 1.1 pooka nfsstats.rpcinvalid++; 395 1.1 pooka m_freem(mrep); 396 1.1 pooka nfsmout: 397 1.1 pooka nfs_rcvunlock(nmp); 398 1.1 pooka continue; 399 1.1 pooka } 400 1.1 pooka 401 1.1 pooka /* 402 1.1 pooka * Loop through the request list to match up the reply 403 1.1 pooka * Iff no match, just drop the datagram 404 1.1 pooka */ 405 1.5 christos s = splsoftnet(); 406 1.6 christos mutex_enter(&nfs_reqq_lock); 407 1.1 pooka TAILQ_FOREACH(rep, &nfs_reqq, r_chain) { 408 1.4 christos if (rep->r_mrep != NULL || rxid != rep->r_xid) 409 1.4 christos continue; 410 1.4 christos 411 1.4 christos /* Found it.. */ 412 1.4 christos rep->r_mrep = mrep; 413 1.4 christos rep->r_md = md; 414 1.4 christos rep->r_dpos = dpos; 415 1.4 christos if (nfsrtton) { 416 1.4 christos struct rttl *rt; 417 1.4 christos int proct = nfs_proct[rep->r_procnum]; 418 1.4 christos 419 1.4 christos rt = &nfsrtt.rttl[nfsrtt.pos]; 420 1.4 christos rt->proc = rep->r_procnum; 421 1.4 christos rt->rto = NFS_RTO(nmp, proct); 422 1.4 christos rt->sent = nmp->nm_sent; 423 1.4 christos rt->cwnd = nmp->nm_cwnd; 424 1.4 christos rt->srtt = nmp->nm_srtt[proct - 1]; 425 1.4 christos rt->sdrtt = nmp->nm_sdrtt[proct - 1]; 426 1.4 christos rt->fsid = nmp->nm_mountp->mnt_stat.f_fsidx; 427 1.4 christos getmicrotime(&rt->tstamp); 428 1.4 christos if (rep->r_flags & R_TIMING) 429 1.4 christos rt->rtt = rep->r_rtt; 430 1.4 christos else 431 1.4 christos rt->rtt = 1000000; 432 1.4 christos nfsrtt.pos = (nfsrtt.pos + 1) % NFSRTTLOGSIZ; 433 1.4 christos } 434 1.4 christos /* 435 1.4 christos * Update congestion window. 436 1.4 christos * Do the additive increase of 437 1.4 christos * one rpc/rtt. 438 1.4 christos */ 439 1.4 christos if (nmp->nm_cwnd <= nmp->nm_sent) { 440 1.4 christos nmp->nm_cwnd += 441 1.4 christos (NFS_CWNDSCALE * NFS_CWNDSCALE + 442 1.4 christos (nmp->nm_cwnd >> 1)) / nmp->nm_cwnd; 443 1.4 christos if (nmp->nm_cwnd > NFS_MAXCWND) 444 1.4 christos nmp->nm_cwnd = NFS_MAXCWND; 445 1.4 christos } 446 1.4 christos rep->r_flags &= ~R_SENT; 447 1.4 christos nmp->nm_sent -= NFS_CWNDSCALE; 448 1.4 christos /* 449 1.4 christos * Update rtt using a gain of 0.125 on the mean 450 1.4 christos * and a gain of 0.25 on the deviation. 451 1.4 christos */ 452 1.4 christos if (rep->r_flags & R_TIMING) { 453 1.1 pooka /* 454 1.4 christos * Since the timer resolution of 455 1.4 christos * NFS_HZ is so course, it can often 456 1.4 christos * result in r_rtt == 0. Since 457 1.4 christos * r_rtt == N means that the actual 458 1.4 christos * rtt is between N+dt and N+2-dt ticks, 459 1.4 christos * add 1. 460 1.1 pooka */ 461 1.4 christos t1 = rep->r_rtt + 1; 462 1.4 christos t1 -= (NFS_SRTT(rep) >> 3); 463 1.4 christos NFS_SRTT(rep) += t1; 464 1.4 christos if (t1 < 0) 465 1.4 christos t1 = -t1; 466 1.4 christos t1 -= (NFS_SDRTT(rep) >> 2); 467 1.4 christos NFS_SDRTT(rep) += t1; 468 1.1 pooka } 469 1.4 christos nmp->nm_timeouts = 0; 470 1.4 christos break; 471 1.1 pooka } 472 1.6 christos mutex_exit(&nfs_reqq_lock); 473 1.5 christos splx(s); 474 1.1 pooka nfs_rcvunlock(nmp); 475 1.1 pooka /* 476 1.1 pooka * If not matched to a request, drop it. 477 1.1 pooka * If it's mine, get out. 478 1.1 pooka */ 479 1.1 pooka if (rep == 0) { 480 1.1 pooka nfsstats.rpcunexpected++; 481 1.1 pooka m_freem(mrep); 482 1.1 pooka } else if (rep == myrep) { 483 1.1 pooka if (rep->r_mrep == NULL) 484 1.1 pooka panic("nfsreply nil"); 485 1.1 pooka return (0); 486 1.1 pooka } 487 1.1 pooka } 488 1.1 pooka } 489 1.1 pooka 490 1.1 pooka /* 491 1.1 pooka * nfs_request - goes something like this 492 1.1 pooka * - fill in request struct 493 1.1 pooka * - links it into list 494 1.1 pooka * - calls nfs_send() for first transmit 495 1.1 pooka * - calls nfs_receive() to get reply 496 1.1 pooka * - break down rpc header and return with nfs reply pointed to 497 1.1 pooka * by mrep or error 498 1.1 pooka * nb: always frees up mreq mbuf list 499 1.1 pooka */ 500 1.1 pooka int 501 1.1 pooka nfs_request(struct nfsnode *np, struct mbuf *mrest, int procnum, struct lwp *lwp, kauth_cred_t cred, struct mbuf **mrp, struct mbuf **mdp, char **dposp, int *rexmitp) 502 1.1 pooka { 503 1.1 pooka struct mbuf *m, *mrep; 504 1.1 pooka struct nfsreq *rep; 505 1.1 pooka u_int32_t *tl; 506 1.1 pooka int i; 507 1.1 pooka struct nfsmount *nmp = VFSTONFS(np->n_vnode->v_mount); 508 1.1 pooka struct mbuf *md, *mheadend; 509 1.1 pooka char nickv[RPCX_NICKVERF]; 510 1.1 pooka time_t waituntil; 511 1.1 pooka char *dpos, *cp2; 512 1.1 pooka int t1, s, error = 0, mrest_len, auth_len, auth_type; 513 1.1 pooka int trylater_delay = NFS_TRYLATERDEL, failed_auth = 0; 514 1.1 pooka int verf_len, verf_type; 515 1.1 pooka u_int32_t xid; 516 1.1 pooka char *auth_str, *verf_str; 517 1.1 pooka NFSKERBKEY_T key; /* save session key */ 518 1.1 pooka kauth_cred_t acred; 519 1.1 pooka struct mbuf *mrest_backup = NULL; 520 1.1 pooka kauth_cred_t origcred = NULL; /* XXX: gcc */ 521 1.1 pooka bool retry_cred = true; 522 1.1 pooka bool use_opencred = (np->n_flag & NUSEOPENCRED) != 0; 523 1.1 pooka 524 1.1 pooka if (rexmitp != NULL) 525 1.1 pooka *rexmitp = 0; 526 1.1 pooka 527 1.1 pooka acred = kauth_cred_alloc(); 528 1.1 pooka 529 1.1 pooka tryagain_cred: 530 1.1 pooka KASSERT(cred != NULL); 531 1.1 pooka rep = kmem_alloc(sizeof(*rep), KM_SLEEP); 532 1.1 pooka rep->r_nmp = nmp; 533 1.1 pooka KASSERT(lwp == NULL || lwp == curlwp); 534 1.1 pooka rep->r_lwp = lwp; 535 1.1 pooka rep->r_procnum = procnum; 536 1.1 pooka i = 0; 537 1.1 pooka m = mrest; 538 1.1 pooka while (m) { 539 1.1 pooka i += m->m_len; 540 1.1 pooka m = m->m_next; 541 1.1 pooka } 542 1.1 pooka mrest_len = i; 543 1.1 pooka 544 1.1 pooka /* 545 1.1 pooka * Get the RPC header with authorization. 546 1.1 pooka */ 547 1.1 pooka kerbauth: 548 1.1 pooka verf_str = auth_str = NULL; 549 1.1 pooka if (nmp->nm_flag & NFSMNT_KERB) { 550 1.1 pooka verf_str = nickv; 551 1.1 pooka verf_len = sizeof (nickv); 552 1.1 pooka auth_type = RPCAUTH_KERB4; 553 1.1 pooka memset((void *)key, 0, sizeof (key)); 554 1.1 pooka if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str, 555 1.1 pooka &auth_len, verf_str, verf_len)) { 556 1.1 pooka error = nfs_getauth(nmp, rep, cred, &auth_str, 557 1.1 pooka &auth_len, verf_str, &verf_len, key); 558 1.1 pooka if (error) { 559 1.1 pooka kmem_free(rep, sizeof(*rep)); 560 1.1 pooka m_freem(mrest); 561 1.1 pooka KASSERT(kauth_cred_getrefcnt(acred) == 1); 562 1.1 pooka kauth_cred_free(acred); 563 1.1 pooka return (error); 564 1.1 pooka } 565 1.1 pooka } 566 1.1 pooka retry_cred = false; 567 1.1 pooka } else { 568 1.1 pooka /* AUTH_UNIX */ 569 1.1 pooka uid_t uid; 570 1.1 pooka gid_t gid; 571 1.1 pooka 572 1.1 pooka /* 573 1.1 pooka * on the most unix filesystems, permission checks are 574 1.1 pooka * done when the file is open(2)'ed. 575 1.1 pooka * ie. once a file is successfully open'ed, 576 1.1 pooka * following i/o operations never fail with EACCES. 577 1.1 pooka * we try to follow the semantics as far as possible. 578 1.1 pooka * 579 1.1 pooka * note that we expect that the nfs server always grant 580 1.1 pooka * accesses by the file's owner. 581 1.1 pooka */ 582 1.1 pooka origcred = cred; 583 1.1 pooka switch (procnum) { 584 1.1 pooka case NFSPROC_READ: 585 1.1 pooka case NFSPROC_WRITE: 586 1.1 pooka case NFSPROC_COMMIT: 587 1.1 pooka uid = np->n_vattr->va_uid; 588 1.1 pooka gid = np->n_vattr->va_gid; 589 1.1 pooka if (kauth_cred_geteuid(cred) == uid && 590 1.1 pooka kauth_cred_getegid(cred) == gid) { 591 1.1 pooka retry_cred = false; 592 1.1 pooka break; 593 1.1 pooka } 594 1.1 pooka if (use_opencred) 595 1.1 pooka break; 596 1.1 pooka kauth_cred_setuid(acred, uid); 597 1.1 pooka kauth_cred_seteuid(acred, uid); 598 1.1 pooka kauth_cred_setsvuid(acred, uid); 599 1.1 pooka kauth_cred_setgid(acred, gid); 600 1.1 pooka kauth_cred_setegid(acred, gid); 601 1.1 pooka kauth_cred_setsvgid(acred, gid); 602 1.1 pooka cred = acred; 603 1.1 pooka break; 604 1.1 pooka default: 605 1.1 pooka retry_cred = false; 606 1.1 pooka break; 607 1.1 pooka } 608 1.1 pooka /* 609 1.1 pooka * backup mbuf chain if we can need it later to retry. 610 1.1 pooka * 611 1.1 pooka * XXX maybe we can keep a direct reference to 612 1.1 pooka * mrest without doing m_copym, but it's ...ugly. 613 1.1 pooka */ 614 1.1 pooka if (retry_cred) 615 1.1 pooka mrest_backup = m_copym(mrest, 0, M_COPYALL, M_WAIT); 616 1.1 pooka auth_type = RPCAUTH_UNIX; 617 1.1 pooka /* XXX elad - ngroups */ 618 1.1 pooka auth_len = (((kauth_cred_ngroups(cred) > nmp->nm_numgrps) ? 619 1.1 pooka nmp->nm_numgrps : kauth_cred_ngroups(cred)) << 2) + 620 1.1 pooka 5 * NFSX_UNSIGNED; 621 1.1 pooka } 622 1.1 pooka m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len, 623 1.1 pooka auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid); 624 1.1 pooka if (auth_str) 625 1.1 pooka free(auth_str, M_TEMP); 626 1.1 pooka 627 1.1 pooka /* 628 1.1 pooka * For stream protocols, insert a Sun RPC Record Mark. 629 1.1 pooka */ 630 1.1 pooka if (nmp->nm_sotype == SOCK_STREAM) { 631 1.1 pooka M_PREPEND(m, NFSX_UNSIGNED, M_WAIT); 632 1.1 pooka *mtod(m, u_int32_t *) = htonl(0x80000000 | 633 1.1 pooka (m->m_pkthdr.len - NFSX_UNSIGNED)); 634 1.1 pooka } 635 1.1 pooka rep->r_mreq = m; 636 1.1 pooka rep->r_xid = xid; 637 1.1 pooka tryagain: 638 1.1 pooka if (nmp->nm_flag & NFSMNT_SOFT) 639 1.1 pooka rep->r_retry = nmp->nm_retry; 640 1.1 pooka else 641 1.1 pooka rep->r_retry = NFS_MAXREXMIT + 1; /* past clip limit */ 642 1.1 pooka rep->r_rtt = rep->r_rexmit = 0; 643 1.1 pooka if (nfs_proct[procnum] > 0) 644 1.1 pooka rep->r_flags = R_TIMING; 645 1.1 pooka else 646 1.1 pooka rep->r_flags = 0; 647 1.1 pooka rep->r_mrep = NULL; 648 1.1 pooka 649 1.1 pooka /* 650 1.1 pooka * Do the client side RPC. 651 1.1 pooka */ 652 1.1 pooka nfsstats.rpcrequests++; 653 1.1 pooka /* 654 1.1 pooka * Chain request into list of outstanding requests. Be sure 655 1.1 pooka * to put it LAST so timer finds oldest requests first. 656 1.1 pooka */ 657 1.1 pooka s = splsoftnet(); 658 1.6 christos mutex_enter(&nfs_reqq_lock); 659 1.1 pooka TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain); 660 1.6 christos mutex_exit(&nfs_reqq_lock); 661 1.1 pooka nfs_timer_start(); 662 1.1 pooka 663 1.1 pooka /* 664 1.1 pooka * If backing off another request or avoiding congestion, don't 665 1.1 pooka * send this one now but let timer do it. If not timing a request, 666 1.1 pooka * do it now. 667 1.1 pooka */ 668 1.1 pooka if (nmp->nm_so && (nmp->nm_sotype != SOCK_DGRAM || 669 1.1 pooka (nmp->nm_flag & NFSMNT_DUMBTIMR) || nmp->nm_sent < nmp->nm_cwnd)) { 670 1.1 pooka splx(s); 671 1.1 pooka if (nmp->nm_soflags & PR_CONNREQUIRED) 672 1.1 pooka error = nfs_sndlock(nmp, rep); 673 1.1 pooka if (!error) { 674 1.1 pooka m = m_copym(rep->r_mreq, 0, M_COPYALL, M_WAIT); 675 1.1 pooka error = nfs_send(nmp->nm_so, nmp->nm_nam, m, rep, lwp); 676 1.1 pooka if (nmp->nm_soflags & PR_CONNREQUIRED) 677 1.1 pooka nfs_sndunlock(nmp); 678 1.1 pooka } 679 1.1 pooka s = splsoftnet(); 680 1.1 pooka if (!error && (rep->r_flags & R_MUSTRESEND) == 0) { 681 1.1 pooka if ((rep->r_flags & R_SENT) == 0) { 682 1.1 pooka nmp->nm_sent += NFS_CWNDSCALE; 683 1.1 pooka rep->r_flags |= R_SENT; 684 1.1 pooka } 685 1.1 pooka } 686 1.1 pooka splx(s); 687 1.1 pooka } else { 688 1.1 pooka splx(s); 689 1.1 pooka rep->r_rtt = -1; 690 1.1 pooka } 691 1.1 pooka 692 1.1 pooka /* 693 1.1 pooka * Wait for the reply from our send or the timer's. 694 1.1 pooka */ 695 1.1 pooka if (!error || error == EPIPE || error == EWOULDBLOCK) 696 1.1 pooka error = nfs_reply(rep, lwp); 697 1.1 pooka 698 1.1 pooka /* 699 1.1 pooka * RPC done, unlink the request. 700 1.1 pooka */ 701 1.1 pooka s = splsoftnet(); 702 1.6 christos mutex_enter(&nfs_reqq_lock); 703 1.1 pooka TAILQ_REMOVE(&nfs_reqq, rep, r_chain); 704 1.6 christos mutex_exit(&nfs_reqq_lock); 705 1.1 pooka 706 1.1 pooka /* 707 1.1 pooka * Decrement the outstanding request count. 708 1.1 pooka */ 709 1.1 pooka if (rep->r_flags & R_SENT) { 710 1.1 pooka rep->r_flags &= ~R_SENT; /* paranoia */ 711 1.1 pooka nmp->nm_sent -= NFS_CWNDSCALE; 712 1.1 pooka } 713 1.1 pooka splx(s); 714 1.1 pooka 715 1.1 pooka if (rexmitp != NULL) { 716 1.1 pooka int rexmit; 717 1.1 pooka 718 1.1 pooka if (nmp->nm_sotype != SOCK_DGRAM) 719 1.1 pooka rexmit = (rep->r_flags & R_REXMITTED) != 0; 720 1.1 pooka else 721 1.1 pooka rexmit = rep->r_rexmit; 722 1.1 pooka *rexmitp = rexmit; 723 1.1 pooka } 724 1.1 pooka 725 1.1 pooka /* 726 1.1 pooka * If there was a successful reply and a tprintf msg. 727 1.1 pooka * tprintf a response. 728 1.1 pooka */ 729 1.1 pooka if (!error && (rep->r_flags & R_TPRINTFMSG)) 730 1.1 pooka nfs_msg(rep->r_lwp, nmp->nm_mountp->mnt_stat.f_mntfromname, 731 1.1 pooka "is alive again"); 732 1.1 pooka mrep = rep->r_mrep; 733 1.1 pooka md = rep->r_md; 734 1.1 pooka dpos = rep->r_dpos; 735 1.1 pooka if (error) 736 1.1 pooka goto nfsmout; 737 1.1 pooka 738 1.1 pooka /* 739 1.1 pooka * break down the rpc header and check if ok 740 1.1 pooka */ 741 1.1 pooka nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 742 1.1 pooka if (*tl++ == rpc_msgdenied) { 743 1.1 pooka if (*tl == rpc_mismatch) 744 1.1 pooka error = EOPNOTSUPP; 745 1.1 pooka else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) { 746 1.1 pooka if (!failed_auth) { 747 1.1 pooka failed_auth++; 748 1.1 pooka mheadend->m_next = NULL; 749 1.1 pooka m_freem(mrep); 750 1.1 pooka m_freem(rep->r_mreq); 751 1.1 pooka goto kerbauth; 752 1.1 pooka } else 753 1.1 pooka error = EAUTH; 754 1.1 pooka } else 755 1.1 pooka error = EACCES; 756 1.1 pooka m_freem(mrep); 757 1.1 pooka goto nfsmout; 758 1.1 pooka } 759 1.1 pooka 760 1.1 pooka /* 761 1.1 pooka * Grab any Kerberos verifier, otherwise just throw it away. 762 1.1 pooka */ 763 1.1 pooka verf_type = fxdr_unsigned(int, *tl++); 764 1.1 pooka i = fxdr_unsigned(int32_t, *tl); 765 1.1 pooka if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) { 766 1.1 pooka error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep); 767 1.1 pooka if (error) 768 1.1 pooka goto nfsmout; 769 1.1 pooka } else if (i > 0) 770 1.1 pooka nfsm_adv(nfsm_rndup(i)); 771 1.1 pooka nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 772 1.1 pooka /* 0 == ok */ 773 1.1 pooka if (*tl == 0) { 774 1.1 pooka nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 775 1.1 pooka if (*tl != 0) { 776 1.1 pooka error = fxdr_unsigned(int, *tl); 777 1.1 pooka switch (error) { 778 1.1 pooka case NFSERR_PERM: 779 1.1 pooka error = EPERM; 780 1.1 pooka break; 781 1.1 pooka 782 1.1 pooka case NFSERR_NOENT: 783 1.1 pooka error = ENOENT; 784 1.1 pooka break; 785 1.1 pooka 786 1.1 pooka case NFSERR_IO: 787 1.1 pooka error = EIO; 788 1.1 pooka break; 789 1.1 pooka 790 1.1 pooka case NFSERR_NXIO: 791 1.1 pooka error = ENXIO; 792 1.1 pooka break; 793 1.1 pooka 794 1.1 pooka case NFSERR_ACCES: 795 1.1 pooka error = EACCES; 796 1.1 pooka if (!retry_cred) 797 1.1 pooka break; 798 1.1 pooka m_freem(mrep); 799 1.1 pooka m_freem(rep->r_mreq); 800 1.1 pooka kmem_free(rep, sizeof(*rep)); 801 1.1 pooka use_opencred = !use_opencred; 802 1.1 pooka if (mrest_backup == NULL) { 803 1.1 pooka /* m_copym failure */ 804 1.1 pooka KASSERT( 805 1.1 pooka kauth_cred_getrefcnt(acred) == 1); 806 1.1 pooka kauth_cred_free(acred); 807 1.1 pooka return ENOMEM; 808 1.1 pooka } 809 1.1 pooka mrest = mrest_backup; 810 1.1 pooka mrest_backup = NULL; 811 1.1 pooka cred = origcred; 812 1.1 pooka error = 0; 813 1.1 pooka retry_cred = false; 814 1.1 pooka goto tryagain_cred; 815 1.1 pooka 816 1.1 pooka case NFSERR_EXIST: 817 1.1 pooka error = EEXIST; 818 1.1 pooka break; 819 1.1 pooka 820 1.1 pooka case NFSERR_XDEV: 821 1.1 pooka error = EXDEV; 822 1.1 pooka break; 823 1.1 pooka 824 1.1 pooka case NFSERR_NODEV: 825 1.1 pooka error = ENODEV; 826 1.1 pooka break; 827 1.1 pooka 828 1.1 pooka case NFSERR_NOTDIR: 829 1.1 pooka error = ENOTDIR; 830 1.1 pooka break; 831 1.1 pooka 832 1.1 pooka case NFSERR_ISDIR: 833 1.1 pooka error = EISDIR; 834 1.1 pooka break; 835 1.1 pooka 836 1.1 pooka case NFSERR_INVAL: 837 1.1 pooka error = EINVAL; 838 1.1 pooka break; 839 1.1 pooka 840 1.1 pooka case NFSERR_FBIG: 841 1.1 pooka error = EFBIG; 842 1.1 pooka break; 843 1.1 pooka 844 1.1 pooka case NFSERR_NOSPC: 845 1.1 pooka error = ENOSPC; 846 1.1 pooka break; 847 1.1 pooka 848 1.1 pooka case NFSERR_ROFS: 849 1.1 pooka error = EROFS; 850 1.1 pooka break; 851 1.1 pooka 852 1.1 pooka case NFSERR_MLINK: 853 1.1 pooka error = EMLINK; 854 1.1 pooka break; 855 1.1 pooka 856 1.1 pooka case NFSERR_TIMEDOUT: 857 1.1 pooka error = ETIMEDOUT; 858 1.1 pooka break; 859 1.1 pooka 860 1.1 pooka case NFSERR_NAMETOL: 861 1.1 pooka error = ENAMETOOLONG; 862 1.1 pooka break; 863 1.1 pooka 864 1.1 pooka case NFSERR_NOTEMPTY: 865 1.1 pooka error = ENOTEMPTY; 866 1.1 pooka break; 867 1.1 pooka 868 1.1 pooka case NFSERR_DQUOT: 869 1.1 pooka error = EDQUOT; 870 1.1 pooka break; 871 1.1 pooka 872 1.1 pooka case NFSERR_STALE: 873 1.1 pooka /* 874 1.1 pooka * If the File Handle was stale, invalidate the 875 1.1 pooka * lookup cache, just in case. 876 1.1 pooka */ 877 1.1 pooka error = ESTALE; 878 1.1 pooka cache_purge(NFSTOV(np)); 879 1.1 pooka break; 880 1.1 pooka 881 1.1 pooka case NFSERR_REMOTE: 882 1.1 pooka error = EREMOTE; 883 1.1 pooka break; 884 1.1 pooka 885 1.1 pooka case NFSERR_WFLUSH: 886 1.1 pooka case NFSERR_BADHANDLE: 887 1.1 pooka case NFSERR_NOT_SYNC: 888 1.1 pooka case NFSERR_BAD_COOKIE: 889 1.1 pooka error = EINVAL; 890 1.1 pooka break; 891 1.1 pooka 892 1.1 pooka case NFSERR_NOTSUPP: 893 1.1 pooka error = ENOTSUP; 894 1.1 pooka break; 895 1.1 pooka 896 1.1 pooka case NFSERR_TOOSMALL: 897 1.1 pooka case NFSERR_SERVERFAULT: 898 1.1 pooka case NFSERR_BADTYPE: 899 1.1 pooka error = EINVAL; 900 1.1 pooka break; 901 1.1 pooka 902 1.1 pooka case NFSERR_TRYLATER: 903 1.1 pooka if ((nmp->nm_flag & NFSMNT_NFSV3) == 0) 904 1.1 pooka break; 905 1.1 pooka m_freem(mrep); 906 1.1 pooka error = 0; 907 1.1 pooka waituntil = time_second + trylater_delay; 908 1.1 pooka while (time_second < waituntil) { 909 1.1 pooka kpause("nfstrylater", false, hz, NULL); 910 1.1 pooka } 911 1.1 pooka trylater_delay *= NFS_TRYLATERDELMUL; 912 1.1 pooka if (trylater_delay > NFS_TRYLATERDELMAX) 913 1.1 pooka trylater_delay = NFS_TRYLATERDELMAX; 914 1.1 pooka /* 915 1.1 pooka * RFC1813: 916 1.1 pooka * The client should wait and then try 917 1.1 pooka * the request with a new RPC transaction ID. 918 1.1 pooka */ 919 1.1 pooka nfs_renewxid(rep); 920 1.1 pooka goto tryagain; 921 1.1 pooka 922 1.1 pooka default: 923 1.1 pooka #ifdef DIAGNOSTIC 924 1.1 pooka printf("Invalid rpc error code %d\n", error); 925 1.1 pooka #endif 926 1.1 pooka error = EINVAL; 927 1.1 pooka break; 928 1.1 pooka } 929 1.1 pooka 930 1.1 pooka if (nmp->nm_flag & NFSMNT_NFSV3) { 931 1.1 pooka *mrp = mrep; 932 1.1 pooka *mdp = md; 933 1.1 pooka *dposp = dpos; 934 1.1 pooka error |= NFSERR_RETERR; 935 1.1 pooka } else 936 1.1 pooka m_freem(mrep); 937 1.1 pooka goto nfsmout; 938 1.1 pooka } 939 1.1 pooka 940 1.1 pooka /* 941 1.1 pooka * note which credential worked to minimize number of retries. 942 1.1 pooka */ 943 1.1 pooka if (use_opencred) 944 1.1 pooka np->n_flag |= NUSEOPENCRED; 945 1.1 pooka else 946 1.1 pooka np->n_flag &= ~NUSEOPENCRED; 947 1.1 pooka 948 1.1 pooka *mrp = mrep; 949 1.1 pooka *mdp = md; 950 1.1 pooka *dposp = dpos; 951 1.1 pooka 952 1.1 pooka KASSERT(error == 0); 953 1.1 pooka goto nfsmout; 954 1.1 pooka } 955 1.1 pooka m_freem(mrep); 956 1.1 pooka error = EPROTONOSUPPORT; 957 1.1 pooka nfsmout: 958 1.1 pooka KASSERT(kauth_cred_getrefcnt(acred) == 1); 959 1.1 pooka kauth_cred_free(acred); 960 1.1 pooka m_freem(rep->r_mreq); 961 1.1 pooka kmem_free(rep, sizeof(*rep)); 962 1.1 pooka m_freem(mrest_backup); 963 1.1 pooka return (error); 964 1.1 pooka } 965 1.1 pooka 966 1.1 pooka /* 967 1.1 pooka * Lock a socket against others. 968 1.1 pooka * Necessary for STREAM sockets to ensure you get an entire rpc request/reply 969 1.1 pooka * and also to avoid race conditions between the processes with nfs requests 970 1.1 pooka * in progress when a reconnect is necessary. 971 1.1 pooka */ 972 1.1 pooka static int 973 1.1 pooka nfs_sndlock(struct nfsmount *nmp, struct nfsreq *rep) 974 1.1 pooka { 975 1.1 pooka struct lwp *l; 976 1.1 pooka int timeo = 0; 977 1.2 matt bool catch_p = false; 978 1.1 pooka int error = 0; 979 1.1 pooka 980 1.3 manu if (nmp->nm_flag & NFSMNT_SOFT) 981 1.3 manu timeo = nmp->nm_retry * nmp->nm_timeo; 982 1.3 manu 983 1.3 manu if (nmp->nm_iflag & NFSMNT_DISMNTFORCE) 984 1.3 manu timeo = hz; 985 1.3 manu 986 1.1 pooka if (rep) { 987 1.1 pooka l = rep->r_lwp; 988 1.1 pooka if (rep->r_nmp->nm_flag & NFSMNT_INT) 989 1.2 matt catch_p = true; 990 1.1 pooka } else 991 1.1 pooka l = NULL; 992 1.1 pooka mutex_enter(&nmp->nm_lock); 993 1.1 pooka while ((nmp->nm_iflag & NFSMNT_SNDLOCK) != 0) { 994 1.1 pooka if (rep && nfs_sigintr(rep->r_nmp, rep, l)) { 995 1.1 pooka error = EINTR; 996 1.1 pooka goto quit; 997 1.1 pooka } 998 1.2 matt if (catch_p) { 999 1.3 manu error = cv_timedwait_sig(&nmp->nm_sndcv, 1000 1.3 manu &nmp->nm_lock, timeo); 1001 1.1 pooka } else { 1002 1.3 manu error = cv_timedwait(&nmp->nm_sndcv, 1003 1.3 manu &nmp->nm_lock, timeo); 1004 1.3 manu } 1005 1.3 manu 1006 1.3 manu if (error) { 1007 1.3 manu if ((error == EWOULDBLOCK) && 1008 1.3 manu (nmp->nm_flag & NFSMNT_SOFT)) { 1009 1.3 manu error = EIO; 1010 1.3 manu goto quit; 1011 1.3 manu } 1012 1.3 manu error = 0; 1013 1.1 pooka } 1014 1.2 matt if (catch_p) { 1015 1.2 matt catch_p = false; 1016 1.1 pooka timeo = 2 * hz; 1017 1.1 pooka } 1018 1.1 pooka } 1019 1.1 pooka nmp->nm_iflag |= NFSMNT_SNDLOCK; 1020 1.1 pooka quit: 1021 1.1 pooka mutex_exit(&nmp->nm_lock); 1022 1.1 pooka return error; 1023 1.1 pooka } 1024 1.1 pooka 1025 1.1 pooka /* 1026 1.1 pooka * Unlock the stream socket for others. 1027 1.1 pooka */ 1028 1.1 pooka static void 1029 1.1 pooka nfs_sndunlock(struct nfsmount *nmp) 1030 1.1 pooka { 1031 1.1 pooka 1032 1.1 pooka mutex_enter(&nmp->nm_lock); 1033 1.1 pooka if ((nmp->nm_iflag & NFSMNT_SNDLOCK) == 0) 1034 1.1 pooka panic("nfs sndunlock"); 1035 1.1 pooka nmp->nm_iflag &= ~NFSMNT_SNDLOCK; 1036 1.1 pooka cv_signal(&nmp->nm_sndcv); 1037 1.1 pooka mutex_exit(&nmp->nm_lock); 1038 1.1 pooka } 1039