nfs_common.c revision 104908
176105Sphantom/* 276105Sphantom * Copyright (c) 1989, 1993 376105Sphantom * The Regents of the University of California. All rights reserved. 476105Sphantom * 576105Sphantom * This code is derived from software contributed to Berkeley by 676105Sphantom * Rick Macklem at The University of Guelph. 776105Sphantom * 876105Sphantom * Redistribution and use in source and binary forms, with or without 976105Sphantom * modification, are permitted provided that the following conditions 1076105Sphantom * are met: 1176105Sphantom * 1. Redistributions of source code must retain the above copyright 1276105Sphantom * notice, this list of conditions and the following disclaimer. 1376105Sphantom * 2. Redistributions in binary form must reproduce the above copyright 1476105Sphantom * notice, this list of conditions and the following disclaimer in the 1576105Sphantom * documentation and/or other materials provided with the distribution. 1676105Sphantom * 3. All advertising materials mentioning features or use of this software 1776105Sphantom * must display the following acknowledgement: 1876105Sphantom * This product includes software developed by the University of 1976105Sphantom * California, Berkeley and its contributors. 2076105Sphantom * 4. Neither the name of the University nor the names of its contributors 2176105Sphantom * may be used to endorse or promote products derived from this software 2276105Sphantom * without specific prior written permission. 2376105Sphantom * 2476105Sphantom * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2576105Sphantom * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2676105Sphantom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2776105Sphantom * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2876105Sphantom * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2976105Sphantom * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3076105Sphantom * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3176105Sphantom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3276105Sphantom * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3376105Sphantom * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3476105Sphantom * SUCH DAMAGE. 3576105Sphantom * 3676105Sphantom * @(#)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 104908 2002-10-11 14:58:34Z mike $"); 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 68#include <nfs/rpcv2.h> 69#include <nfs/nfsproto.h> 70#include <nfsserver/nfs.h> 71#include <nfs/xdr_subs.h> 72#include <nfs/nfs_common.h> 73 74#include <netinet/in.h> 75 76enum vtype nv3tov_type[8]= { 77 VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO 78}; 79nfstype nfsv3_type[9] = { 80 NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, NFFIFO, NFNON 81}; 82 83u_quad_t 84nfs_curusec(void) 85{ 86 struct timeval tv; 87 88 getmicrotime(&tv); 89 return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec); 90} 91 92/* 93 * copies mbuf chain to the uio scatter/gather list 94 */ 95int 96nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos) 97{ 98 char *mbufcp, *uiocp; 99 int xfer, left, len; 100 struct mbuf *mp; 101 long uiosiz, rem; 102 int error = 0; 103 104 mp = *mrep; 105 mbufcp = *dpos; 106 len = mtod(mp, caddr_t)+mp->m_len-mbufcp; 107 rem = nfsm_rndup(siz)-siz; 108 while (siz > 0) { 109 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 110 return (EFBIG); 111 left = uiop->uio_iov->iov_len; 112 uiocp = uiop->uio_iov->iov_base; 113 if (left > siz) 114 left = siz; 115 uiosiz = left; 116 while (left > 0) { 117 while (len == 0) { 118 mp = mp->m_next; 119 if (mp == NULL) 120 return (EBADRPC); 121 mbufcp = mtod(mp, caddr_t); 122 len = mp->m_len; 123 } 124 xfer = (left > len) ? len : left; 125#ifdef notdef 126 /* Not Yet.. */ 127 if (uiop->uio_iov->iov_op != NULL) 128 (*(uiop->uio_iov->iov_op)) 129 (mbufcp, uiocp, xfer); 130 else 131#endif 132 if (uiop->uio_segflg == UIO_SYSSPACE) 133 bcopy(mbufcp, uiocp, xfer); 134 else 135 copyout(mbufcp, uiocp, xfer); 136 left -= xfer; 137 len -= xfer; 138 mbufcp += xfer; 139 uiocp += xfer; 140 uiop->uio_offset += xfer; 141 uiop->uio_resid -= xfer; 142 } 143 if (uiop->uio_iov->iov_len <= siz) { 144 uiop->uio_iovcnt--; 145 uiop->uio_iov++; 146 } else { 147 uiop->uio_iov->iov_base = 148 (char *)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 for tough 168 * cases. (The macros use the vars. dpos and dpos2) 169 */ 170void * 171nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left) 172{ 173 struct mbuf *mp, *mp2; 174 int siz2, xfer; 175 caddr_t ptr; 176 void *ret; 177 178 mp = *mdp; 179 while (left == 0) { 180 *mdp = mp = mp->m_next; 181 if (mp == NULL) 182 return NULL; 183 left = mp->m_len; 184 *dposp = mtod(mp, caddr_t); 185 } 186 if (left >= siz) { 187 ret = *dposp; 188 *dposp += siz; 189 } else if (mp->m_next == NULL) { 190 return NULL; 191 } else if (siz > MHLEN) { 192 panic("nfs S too big"); 193 } else { 194 MGET(mp2, M_TRYWAIT, MT_DATA); 195 mp2->m_next = mp->m_next; 196 mp->m_next = mp2; 197 mp->m_len -= left; 198 mp = mp2; 199 ptr = mtod(mp, caddr_t); 200 ret = ptr; 201 bcopy(*dposp, ptr, left); /* Copy what was left */ 202 siz2 = siz-left; 203 ptr += left; 204 mp2 = mp->m_next; 205 /* Loop around copying up the siz2 bytes */ 206 while (siz2 > 0) { 207 if (mp2 == NULL) 208 return NULL; 209 xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2; 210 if (xfer > 0) { 211 bcopy(mtod(mp2, caddr_t), ptr, xfer); 212 mp2->m_data += xfer; 213 mp2->m_len -= xfer; 214 ptr += xfer; 215 siz2 -= xfer; 216 } 217 if (siz2 > 0) 218 mp2 = mp2->m_next; 219 } 220 mp->m_len = siz; 221 *mdp = mp2; 222 *dposp = mtod(mp2, caddr_t); 223 } 224 return ret; 225} 226 227/* 228 * Advance the position in the mbuf chain. 229 */ 230int 231nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left) 232{ 233 struct mbuf *m; 234 int s; 235 236 m = *mdp; 237 s = left; 238 while (s < offs) { 239 offs -= s; 240 m = m->m_next; 241 if (m == NULL) 242 return (EBADRPC); 243 s = m->m_len; 244 } 245 *mdp = m; 246 *dposp = mtod(m, caddr_t)+offs; 247 return (0); 248} 249 250void * 251nfsm_build_xx(int s, struct mbuf **mb, caddr_t *bpos) 252{ 253 struct mbuf *mb2; 254 void *ret; 255 256 if (s > M_TRAILINGSPACE(*mb)) { 257 MGET(mb2, M_TRYWAIT, MT_DATA); 258 if (s > MLEN) 259 panic("build > MLEN"); 260 (*mb)->m_next = mb2; 261 *mb = mb2; 262 (*mb)->m_len = 0; 263 *bpos = mtod(*mb, caddr_t); 264 } 265 ret = *bpos; 266 (*mb)->m_len += s; 267 *bpos += s; 268 return ret; 269} 270 271void * 272nfsm_dissect_xx(int s, struct mbuf **md, caddr_t *dpos) 273{ 274 int t1; 275 char *cp2; 276 void *ret; 277 278 t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos; 279 if (t1 >= s) { 280 ret = *dpos; 281 *dpos += s; 282 return ret; 283 } 284 cp2 = nfsm_disct(md, dpos, s, t1); 285 return cp2; 286} 287 288int 289nfsm_strsiz_xx(int *s, int m, struct mbuf **mb, caddr_t *bpos) 290{ 291 u_int32_t *tl; 292 293 tl = nfsm_dissect_xx(NFSX_UNSIGNED, mb, bpos); 294 if (tl == NULL) 295 return EBADRPC; 296 *s = fxdr_unsigned(int32_t, *tl); 297 if (*s > m) 298 return EBADRPC; 299 return 0; 300} 301 302int 303nfsm_adv_xx(int s, struct mbuf **md, caddr_t *dpos) 304{ 305 int t1; 306 307 t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos; 308 if (t1 >= s) { 309 *dpos += s; 310 return 0; 311 } 312 t1 = nfs_adv(md, dpos, s, t1); 313 if (t1) 314 return t1; 315 return 0; 316} 317