nfs_common.c revision 83651
1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95 37 */ 38 39#include <sys/cdefs.h> 40__FBSDID("$FreeBSD: head/sys/nfs/nfs_common.c 83651 2001-09-18 23:32:09Z peter $"); 41 42/* 43 * These functions support the macros and help fiddle mbuf chains for 44 * the nfs op functions. They do things like create the rpc header and 45 * copy data between mbuf chains and uio lists. 46 */ 47 48#include <sys/param.h> 49#include <sys/systm.h> 50#include <sys/kernel.h> 51#include <sys/bio.h> 52#include <sys/buf.h> 53#include <sys/proc.h> 54#include <sys/mount.h> 55#include <sys/vnode.h> 56#include <sys/namei.h> 57#include <sys/mbuf.h> 58#include <sys/socket.h> 59#include <sys/stat.h> 60#include <sys/malloc.h> 61#include <sys/sysent.h> 62#include <sys/syscall.h> 63 64#include <vm/vm.h> 65#include <vm/vm_object.h> 66#include <vm/vm_extern.h> 67#include <vm/vm_zone.h> 68 69#include <nfs/rpcv2.h> 70#include <nfs/nfsproto.h> 71#include <nfsserver/nfs.h> 72#include <nfs/xdr_subs.h> 73#include <nfs/nfs_common.h> 74 75#include <netinet/in.h> 76 77enum vtype nv3tov_type[8]= { 78 VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO 79}; 80nfstype nfsv3_type[9] = { 81 NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, NFFIFO, NFNON 82}; 83 84u_quad_t 85nfs_curusec(void) 86{ 87 struct timeval tv; 88 89 getmicrotime(&tv); 90 return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec); 91} 92 93/* 94 * copies mbuf chain to the uio scatter/gather list 95 */ 96int 97nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos) 98{ 99 char *mbufcp, *uiocp; 100 int xfer, left, len; 101 struct mbuf *mp; 102 long uiosiz, rem; 103 int error = 0; 104 105 mp = *mrep; 106 mbufcp = *dpos; 107 len = mtod(mp, caddr_t)+mp->m_len-mbufcp; 108 rem = nfsm_rndup(siz)-siz; 109 while (siz > 0) { 110 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 111 return (EFBIG); 112 left = uiop->uio_iov->iov_len; 113 uiocp = uiop->uio_iov->iov_base; 114 if (left > siz) 115 left = siz; 116 uiosiz = left; 117 while (left > 0) { 118 while (len == 0) { 119 mp = mp->m_next; 120 if (mp == NULL) 121 return (EBADRPC); 122 mbufcp = mtod(mp, caddr_t); 123 len = mp->m_len; 124 } 125 xfer = (left > len) ? len : left; 126#ifdef notdef 127 /* Not Yet.. */ 128 if (uiop->uio_iov->iov_op != NULL) 129 (*(uiop->uio_iov->iov_op)) 130 (mbufcp, uiocp, xfer); 131 else 132#endif 133 if (uiop->uio_segflg == UIO_SYSSPACE) 134 bcopy(mbufcp, uiocp, xfer); 135 else 136 copyout(mbufcp, uiocp, xfer); 137 left -= xfer; 138 len -= xfer; 139 mbufcp += xfer; 140 uiocp += xfer; 141 uiop->uio_offset += xfer; 142 uiop->uio_resid -= xfer; 143 } 144 if (uiop->uio_iov->iov_len <= siz) { 145 uiop->uio_iovcnt--; 146 uiop->uio_iov++; 147 } else { 148 uiop->uio_iov->iov_base += uiosiz; 149 uiop->uio_iov->iov_len -= uiosiz; 150 } 151 siz -= uiosiz; 152 } 153 *dpos = mbufcp; 154 *mrep = mp; 155 if (rem > 0) { 156 if (len < rem) 157 error = nfs_adv(mrep, dpos, rem, len); 158 else 159 *dpos += rem; 160 } 161 return (error); 162} 163 164/* 165 * Help break down an mbuf chain by setting the first siz bytes contiguous 166 * pointed to by returned val. 167 * This is used by the macros nfsm_dissect and nfsm_dissecton for tough 168 * cases. (The macros use the vars. dpos and dpos2) 169 */ 170int 171nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2) 172{ 173 struct mbuf *mp, *mp2; 174 int siz2, xfer; 175 caddr_t ptr; 176 177 mp = *mdp; 178 while (left == 0) { 179 *mdp = mp = mp->m_next; 180 if (mp == NULL) 181 return (EBADRPC); 182 left = mp->m_len; 183 *dposp = mtod(mp, caddr_t); 184 } 185 if (left >= siz) { 186 *cp2 = *dposp; 187 *dposp += siz; 188 } else if (mp->m_next == NULL) { 189 return (EBADRPC); 190 } else if (siz > MHLEN) { 191 panic("nfs S too big"); 192 } else { 193 MGET(mp2, M_TRYWAIT, MT_DATA); 194 mp2->m_next = mp->m_next; 195 mp->m_next = mp2; 196 mp->m_len -= left; 197 mp = mp2; 198 *cp2 = ptr = mtod(mp, caddr_t); 199 bcopy(*dposp, ptr, left); /* Copy what was left */ 200 siz2 = siz-left; 201 ptr += left; 202 mp2 = mp->m_next; 203 /* Loop around copying up the siz2 bytes */ 204 while (siz2 > 0) { 205 if (mp2 == NULL) 206 return (EBADRPC); 207 xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2; 208 if (xfer > 0) { 209 bcopy(mtod(mp2, caddr_t), ptr, xfer); 210 NFSMADV(mp2, xfer); 211 mp2->m_len -= xfer; 212 ptr += xfer; 213 siz2 -= xfer; 214 } 215 if (siz2 > 0) 216 mp2 = mp2->m_next; 217 } 218 mp->m_len = siz; 219 *mdp = mp2; 220 *dposp = mtod(mp2, caddr_t); 221 } 222 return (0); 223} 224 225/* 226 * Advance the position in the mbuf chain. 227 */ 228int 229nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left) 230{ 231 struct mbuf *m; 232 int s; 233 234 m = *mdp; 235 s = left; 236 while (s < offs) { 237 offs -= s; 238 m = m->m_next; 239 if (m == NULL) 240 return (EBADRPC); 241 s = m->m_len; 242 } 243 *mdp = m; 244 *dposp = mtod(m, caddr_t)+offs; 245 return (0); 246} 247 248void 249nfsm_build_xx(void **a, int s, struct mbuf **mb, caddr_t *bpos) 250{ 251 struct mbuf *mb2; 252 253 if (s > M_TRAILINGSPACE(*mb)) { 254 MGET(mb2, M_TRYWAIT, MT_DATA); 255 if (s > MLEN) 256 panic("build > MLEN"); 257 (*mb)->m_next = mb2; 258 *mb = mb2; 259 (*mb)->m_len = 0; 260 *bpos = mtod(*mb, caddr_t); 261 } 262 *a = *bpos; 263 (*mb)->m_len += s; 264 *bpos += s; 265} 266 267int 268nfsm_dissect_xx(void **a, int s, struct mbuf **md, caddr_t *dpos) 269{ 270 int t1; 271 char *cp2; 272 273 t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos; 274 if (t1 >= s) { 275 *a = *dpos; 276 *dpos += s; 277 return 0; 278 } 279 t1 = nfsm_disct(md, dpos, s, t1, &cp2); 280 if (t1 != 0) 281 return t1; 282 *a = cp2; 283 return 0; 284} 285 286int 287nfsm_strsiz_xx(int *s, int m, u_int32_t **tl, struct mbuf **mb, caddr_t *bpos) 288{ 289 int ret; 290 291 ret = nfsm_dissect_xx((void **)tl, NFSX_UNSIGNED, mb, bpos); 292 if (ret) 293 return ret; 294 *s = fxdr_unsigned(int32_t, **tl); 295 if (*s > m) 296 return EBADRPC; 297 return 0; 298} 299 300int 301nfsm_adv_xx(int s, u_int32_t **tl, struct mbuf **md, caddr_t *dpos) 302{ 303 int t1; 304 305 t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos; 306 if (t1 > s) { 307 *dpos += s; 308 return 0; 309 } 310 t1 = nfs_adv(md, dpos, s, t1); 311 if (t1) 312 return t1; 313 return 0; 314} 315