summaryrefslogtreecommitdiffstats
path: root/sys/nfs/nfs_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfs/nfs_common.c')
-rw-r--r--sys/nfs/nfs_common.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/sys/nfs/nfs_common.c b/sys/nfs/nfs_common.c
new file mode 100644
index 0000000..b99c3b0
--- /dev/null
+++ b/sys/nfs/nfs_common.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * These functions support the macros and help fiddle mbuf chains for
+ * the nfs op functions. They do things like create the rpc header and
+ * copy data between mbuf chains and uio lists.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/namei.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/malloc.h>
+#include <sys/sysent.h>
+#include <sys/syscall.h>
+
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfsserver/nfs.h>
+#include <nfs/xdr_subs.h>
+#include <nfs/nfs_common.h>
+
+#include <netinet/in.h>
+
+enum vtype nv3tov_type[8]= {
+ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
+};
+nfstype nfsv3_type[9] = {
+ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, NFFIFO, NFNON
+};
+
+u_quad_t
+nfs_curusec(void)
+{
+ struct timeval tv;
+
+ getmicrotime(&tv);
+ return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec);
+}
+
+/*
+ * copies mbuf chain to the uio scatter/gather list
+ */
+int
+nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
+{
+ char *mbufcp, *uiocp;
+ int xfer, left, len;
+ struct mbuf *mp;
+ long uiosiz, rem;
+ int error = 0;
+
+ mp = *mrep;
+ mbufcp = *dpos;
+ len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
+ rem = nfsm_rndup(siz)-siz;
+ while (siz > 0) {
+ if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
+ return (EFBIG);
+ left = uiop->uio_iov->iov_len;
+ uiocp = uiop->uio_iov->iov_base;
+ if (left > siz)
+ left = siz;
+ uiosiz = left;
+ while (left > 0) {
+ while (len == 0) {
+ mp = mp->m_next;
+ if (mp == NULL)
+ return (EBADRPC);
+ mbufcp = mtod(mp, caddr_t);
+ len = mp->m_len;
+ }
+ xfer = (left > len) ? len : left;
+#ifdef notdef
+ /* Not Yet.. */
+ if (uiop->uio_iov->iov_op != NULL)
+ (*(uiop->uio_iov->iov_op))
+ (mbufcp, uiocp, xfer);
+ else
+#endif
+ if (uiop->uio_segflg == UIO_SYSSPACE)
+ bcopy(mbufcp, uiocp, xfer);
+ else
+ copyout(mbufcp, uiocp, xfer);
+ left -= xfer;
+ len -= xfer;
+ mbufcp += xfer;
+ uiocp += xfer;
+ uiop->uio_offset += xfer;
+ uiop->uio_resid -= xfer;
+ }
+ if (uiop->uio_iov->iov_len <= siz) {
+ uiop->uio_iovcnt--;
+ uiop->uio_iov++;
+ } else {
+ uiop->uio_iov->iov_base =
+ (char *)uiop->uio_iov->iov_base + uiosiz;
+ uiop->uio_iov->iov_len -= uiosiz;
+ }
+ siz -= uiosiz;
+ }
+ *dpos = mbufcp;
+ *mrep = mp;
+ if (rem > 0) {
+ if (len < rem)
+ error = nfs_adv(mrep, dpos, rem, len);
+ else
+ *dpos += rem;
+ }
+ return (error);
+}
+
+/*
+ * Help break down an mbuf chain by setting the first siz bytes contiguous
+ * pointed to by returned val.
+ * This is used by the macros nfsm_dissect for tough
+ * cases. (The macros use the vars. dpos and dpos2)
+ */
+void *
+nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left)
+{
+ struct mbuf *mp, *mp2;
+ int siz2, xfer;
+ caddr_t ptr;
+ void *ret;
+
+ mp = *mdp;
+ while (left == 0) {
+ *mdp = mp = mp->m_next;
+ if (mp == NULL)
+ return NULL;
+ left = mp->m_len;
+ *dposp = mtod(mp, caddr_t);
+ }
+ if (left >= siz) {
+ ret = *dposp;
+ *dposp += siz;
+ } else if (mp->m_next == NULL) {
+ return NULL;
+ } else if (siz > MHLEN) {
+ panic("nfs S too big");
+ } else {
+ MGET(mp2, M_TRYWAIT, MT_DATA);
+ mp2->m_next = mp->m_next;
+ mp->m_next = mp2;
+ mp->m_len -= left;
+ mp = mp2;
+ ptr = mtod(mp, caddr_t);
+ ret = ptr;
+ bcopy(*dposp, ptr, left); /* Copy what was left */
+ siz2 = siz-left;
+ ptr += left;
+ mp2 = mp->m_next;
+ /* Loop around copying up the siz2 bytes */
+ while (siz2 > 0) {
+ if (mp2 == NULL)
+ return NULL;
+ xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
+ if (xfer > 0) {
+ bcopy(mtod(mp2, caddr_t), ptr, xfer);
+ mp2->m_data += xfer;
+ mp2->m_len -= xfer;
+ ptr += xfer;
+ siz2 -= xfer;
+ }
+ if (siz2 > 0)
+ mp2 = mp2->m_next;
+ }
+ mp->m_len = siz;
+ *mdp = mp2;
+ *dposp = mtod(mp2, caddr_t);
+ }
+ return ret;
+}
+
+/*
+ * Advance the position in the mbuf chain.
+ */
+int
+nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left)
+{
+ struct mbuf *m;
+ int s;
+
+ m = *mdp;
+ s = left;
+ while (s < offs) {
+ offs -= s;
+ m = m->m_next;
+ if (m == NULL)
+ return (EBADRPC);
+ s = m->m_len;
+ }
+ *mdp = m;
+ *dposp = mtod(m, caddr_t)+offs;
+ return (0);
+}
+
+void *
+nfsm_build_xx(int s, struct mbuf **mb, caddr_t *bpos)
+{
+ struct mbuf *mb2;
+ void *ret;
+
+ if (s > M_TRAILINGSPACE(*mb)) {
+ MGET(mb2, M_TRYWAIT, MT_DATA);
+ if (s > MLEN)
+ panic("build > MLEN");
+ (*mb)->m_next = mb2;
+ *mb = mb2;
+ (*mb)->m_len = 0;
+ *bpos = mtod(*mb, caddr_t);
+ }
+ ret = *bpos;
+ (*mb)->m_len += s;
+ *bpos += s;
+ return ret;
+}
+
+void *
+nfsm_dissect_xx(int s, struct mbuf **md, caddr_t *dpos)
+{
+ int t1;
+ char *cp2;
+ void *ret;
+
+ t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos;
+ if (t1 >= s) {
+ ret = *dpos;
+ *dpos += s;
+ return ret;
+ }
+ cp2 = nfsm_disct(md, dpos, s, t1);
+ return cp2;
+}
+
+int
+nfsm_strsiz_xx(int *s, int m, struct mbuf **mb, caddr_t *bpos)
+{
+ u_int32_t *tl;
+
+ tl = nfsm_dissect_xx(NFSX_UNSIGNED, mb, bpos);
+ if (tl == NULL)
+ return EBADRPC;
+ *s = fxdr_unsigned(int32_t, *tl);
+ if (*s > m)
+ return EBADRPC;
+ return 0;
+}
+
+int
+nfsm_adv_xx(int s, struct mbuf **md, caddr_t *dpos)
+{
+ int t1;
+
+ t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos;
+ if (t1 >= s) {
+ *dpos += s;
+ return 0;
+ }
+ t1 = nfs_adv(md, dpos, s, t1);
+ if (t1)
+ return t1;
+ return 0;
+}
OpenPOWER on IntegriCloud