add memory filesystem initialization
[unix-history] / usr / src / sys / kern / sys_generic.c
index 6dbdb49..27ba545 100644 (file)
@@ -1,22 +1,35 @@
 /*
 /*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
  *
  *
- *     @(#)sys_generic.c       7.3 (Berkeley) %G%
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)sys_generic.c       7.12 (Berkeley) %G%
  */
 
 #include "param.h"
 #include "systm.h"
  */
 
 #include "param.h"
 #include "systm.h"
-#include "dir.h"
-#include "user.h"
+#include "syscontext.h"
 #include "ioctl.h"
 #include "file.h"
 #include "proc.h"
 #include "uio.h"
 #include "kernel.h"
 #include "stat.h"
 #include "ioctl.h"
 #include "file.h"
 #include "proc.h"
 #include "uio.h"
 #include "kernel.h"
 #include "stat.h"
-#include "buf.h"                               /* XXX */
+#include "malloc.h"
+#ifdef KTRACE
+#include "ktrace.h"
+#endif
 
 /*
  * Read system call.
 
 /*
  * Read system call.
@@ -28,14 +41,51 @@ read()
                char    *cbuf;
                unsigned count;
        } *uap = (struct a *)u.u_ap;
                char    *cbuf;
                unsigned count;
        } *uap = (struct a *)u.u_ap;
+       register struct file *fp;
        struct uio auio;
        struct iovec aiov;
        struct uio auio;
        struct iovec aiov;
+       long cnt, error = 0;
+#ifdef KTRACE
+       struct iovec ktriov;
+#endif
 
 
+       if (((unsigned)uap->fdes) >= NOFILE ||
+           (fp = u.u_ofile[uap->fdes]) == NULL ||
+           (fp->f_flag & FREAD) == 0)
+               RETURN (EBADF);
+       if (uap->count < 0)
+               RETURN (EINVAL);
        aiov.iov_base = (caddr_t)uap->cbuf;
        aiov.iov_len = uap->count;
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
        aiov.iov_base = (caddr_t)uap->cbuf;
        aiov.iov_len = uap->count;
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
-       rwuio(&auio, UIO_READ);
+       auio.uio_resid = uap->count;
+       auio.uio_rw = UIO_READ;
+       auio.uio_segflg = UIO_USERSPACE;
+#ifdef KTRACE
+       /*
+        * if tracing, save a copy of iovec
+        */
+       if (KTRPOINT(u.u_procp, KTR_GENIO))
+               ktriov = aiov;
+#endif
+       cnt = uap->count;
+       if (setjmp(&u.u_qsave)) {
+               if (auio.uio_resid == cnt) {
+                       if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
+                               error = EINTR;
+                       else
+                               u.u_eosys = RESTARTSYS;
+               }
+       } else
+               error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
+       cnt -= auio.uio_resid;
+#ifdef KTRACE
+       if (KTRPOINT(u.u_procp, KTR_GENIO))
+               ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt);
+#endif
+       u.u_r.r_val1 = cnt;
+       RETURN (error);
 }
 
 readv()
 }
 
 readv()
@@ -45,20 +95,79 @@ readv()
                struct  iovec *iovp;
                unsigned iovcnt;
        } *uap = (struct a *)u.u_ap;
                struct  iovec *iovp;
                unsigned iovcnt;
        } *uap = (struct a *)u.u_ap;
+       register struct file *fp;
        struct uio auio;
        struct uio auio;
-       struct iovec aiov[16];          /* XXX */
+       register struct iovec *iov;
+       struct iovec aiov[UIO_SMALLIOV];
+       long i, cnt, error = 0;
+#ifdef KTRACE
+       struct iovec *ktriov = NULL;
+#endif
 
 
-       if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
-               u.u_error = EINVAL;
-               return;
-       }
-       auio.uio_iov = aiov;
+       if (((unsigned)uap->fdes) >= NOFILE ||
+           (fp = u.u_ofile[uap->fdes]) == NULL ||
+           (fp->f_flag & FREAD) == 0)
+               RETURN (EBADF);
+       if (uap->iovcnt > UIO_SMALLIOV) {
+               if (uap->iovcnt > UIO_MAXIOV)
+                       RETURN (EINVAL);
+               MALLOC(iov, struct iovec *, 
+                     sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
+       } else
+               iov = aiov;
+       auio.uio_iov = iov;
        auio.uio_iovcnt = uap->iovcnt;
        auio.uio_iovcnt = uap->iovcnt;
-       u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
-           uap->iovcnt * sizeof (struct iovec));
-       if (u.u_error)
-               return;
-       rwuio(&auio, UIO_READ);
+       auio.uio_rw = UIO_READ;
+       auio.uio_segflg = UIO_USERSPACE;
+       if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
+           uap->iovcnt * sizeof (struct iovec)))
+               goto done;
+       auio.uio_resid = 0;
+       for (i = 0; i < uap->iovcnt; i++) {
+               if (iov->iov_len < 0) {
+                       error = EINVAL;
+                       goto done;
+               }
+               auio.uio_resid += iov->iov_len;
+               if (auio.uio_resid < 0) {
+                       error = EINVAL;
+                       goto done;
+               }
+               iov++;
+       }
+#ifdef KTRACE
+       /*
+        * if tracing, save a copy of iovec
+        */
+       if (KTRPOINT(u.u_procp, KTR_GENIO))  {
+               int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
+
+               MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
+               bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
+       }
+#endif
+       cnt = auio.uio_resid;
+       if (setjmp(&u.u_qsave)) {
+               if (auio.uio_resid == cnt) {
+                       if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
+                               error = EINTR;
+                       else
+                               u.u_eosys = RESTARTSYS;
+               }
+       } else
+               error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
+       cnt -= auio.uio_resid;
+#ifdef KTRACE
+       if (ktriov != NULL) {
+               ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, ktriov, cnt);
+               FREE(ktriov, M_TEMP);
+       }
+#endif
+       u.u_r.r_val1 = cnt;
+done:
+       if (uap->iovcnt > UIO_SMALLIOV)
+               FREE(iov, M_IOV);
+       RETURN (error);
 }
 
 /*
 }
 
 /*
@@ -71,14 +180,52 @@ write()
                char    *cbuf;
                unsigned count;
        } *uap = (struct a *)u.u_ap;
                char    *cbuf;
                unsigned count;
        } *uap = (struct a *)u.u_ap;
+       register struct file *fp;
        struct uio auio;
        struct iovec aiov;
        struct uio auio;
        struct iovec aiov;
+       long cnt, error = 0;
+#ifdef KTRACE
+       struct iovec ktriov;
+#endif
 
 
+       if (((unsigned)uap->fdes) >= NOFILE ||
+           (fp = u.u_ofile[uap->fdes]) == NULL ||
+           (fp->f_flag & FWRITE) == 0)
+               RETURN (EBADF);
+       if (uap->count < 0)
+               RETURN (EINVAL);
+       aiov.iov_base = (caddr_t)uap->cbuf;
+       aiov.iov_len = uap->count;
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
-       aiov.iov_base = uap->cbuf;
-       aiov.iov_len = uap->count;
-       rwuio(&auio, UIO_WRITE);
+       auio.uio_resid = uap->count;
+       auio.uio_rw = UIO_WRITE;
+       auio.uio_segflg = UIO_USERSPACE;
+#ifdef KTRACE
+       /*
+        * if tracing, save a copy of iovec
+        */
+       if (KTRPOINT(u.u_procp, KTR_GENIO))
+               ktriov = aiov;
+#endif
+       cnt = uap->count;
+       if (setjmp(&u.u_qsave)) {
+               if (auio.uio_resid == cnt) {
+                       if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
+                               error = EINTR;
+                       else
+                               u.u_eosys = RESTARTSYS;
+               }
+       } else
+               error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
+       cnt -= auio.uio_resid;
+#ifdef KTRACE
+       if (KTRPOINT(u.u_procp, KTR_GENIO))
+               ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE,
+                   &ktriov, cnt);
+#endif
+       u.u_r.r_val1 = cnt;
+       RETURN (error);
 }
 
 writev()
 }
 
 writev()
@@ -88,64 +235,80 @@ writev()
                struct  iovec *iovp;
                unsigned iovcnt;
        } *uap = (struct a *)u.u_ap;
                struct  iovec *iovp;
                unsigned iovcnt;
        } *uap = (struct a *)u.u_ap;
-       struct uio auio;
-       struct iovec aiov[16];          /* XXX */
-
-       if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
-               u.u_error = EINVAL;
-               return;
-       }
-       auio.uio_iov = aiov;
-       auio.uio_iovcnt = uap->iovcnt;
-       u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
-           uap->iovcnt * sizeof (struct iovec));
-       if (u.u_error)
-               return;
-       rwuio(&auio, UIO_WRITE);
-}
-
-rwuio(uio, rw)
-       register struct uio *uio;
-       enum uio_rw rw;
-{
-       struct a {
-               int     fdes;
-       };
        register struct file *fp;
        register struct file *fp;
+       struct uio auio;
        register struct iovec *iov;
        register struct iovec *iov;
-       int i, count;
+       struct iovec aiov[UIO_SMALLIOV];
+       long i, cnt, error = 0;
+#ifdef KTRACE
+       struct iovec *ktriov = NULL;
+#endif
 
 
-       GETF(fp, ((struct a *)u.u_ap)->fdes);
-       if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
-               u.u_error = EBADF;
-               return;
-       }
-       uio->uio_resid = 0;
-       uio->uio_segflg = UIO_USERSPACE;
-       iov = uio->uio_iov;
-       for (i = 0; i < uio->uio_iovcnt; i++) {
+       if (((unsigned)uap->fdes) >= NOFILE ||
+           (fp = u.u_ofile[uap->fdes]) == NULL ||
+           (fp->f_flag & FWRITE) == 0)
+               RETURN (EBADF);
+       if (uap->iovcnt > UIO_SMALLIOV) {
+               if (uap->iovcnt > UIO_MAXIOV)
+                       RETURN (EINVAL);
+               MALLOC(iov, struct iovec *, 
+                     sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
+       } else
+               iov = aiov;
+       auio.uio_iov = iov;
+       auio.uio_iovcnt = uap->iovcnt;
+       auio.uio_rw = UIO_WRITE;
+       auio.uio_segflg = UIO_USERSPACE;
+       if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
+           uap->iovcnt * sizeof (struct iovec)))
+               goto done;
+       auio.uio_resid = 0;
+       for (i = 0; i < uap->iovcnt; i++) {
                if (iov->iov_len < 0) {
                if (iov->iov_len < 0) {
-                       u.u_error = EINVAL;
-                       return;
+                       error = EINVAL;
+                       goto done;
                }
                }
-               uio->uio_resid += iov->iov_len;
-               if (uio->uio_resid < 0) {
-                       u.u_error = EINVAL;
-                       return;
+               auio.uio_resid += iov->iov_len;
+               if (auio.uio_resid < 0) {
+                       error = EINVAL;
+                       goto done;
                }
                iov++;
        }
                }
                iov++;
        }
-       count = uio->uio_resid;
+#ifdef KTRACE
+       /*
+        * if tracing, save a copy of iovec
+        */
+       if (KTRPOINT(u.u_procp, KTR_GENIO))  {
+               int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
+
+               MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
+               bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
+       }
+#endif
+       cnt = auio.uio_resid;
        if (setjmp(&u.u_qsave)) {
        if (setjmp(&u.u_qsave)) {
-               if (uio->uio_resid == count) {
+               if (auio.uio_resid == cnt) {
                        if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
                        if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
-                               u.u_error = EINTR;
+                               error = EINTR;
                        else
                                u.u_eosys = RESTARTSYS;
                }
        } else
                        else
                                u.u_eosys = RESTARTSYS;
                }
        } else
-               u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
-       u.u_r.r_val1 = count - uio->uio_resid;
+               error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
+       cnt -= auio.uio_resid;
+#ifdef KTRACE
+       if (ktriov != NULL) {
+               ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE,
+                   ktriov, cnt);
+               FREE(ktriov, M_TEMP);
+       }
+#endif
+       u.u_r.r_val1 = cnt;
+done:
+       if (uap->iovcnt > UIO_SMALLIOV)
+               FREE(iov, M_IOV);
+       RETURN (error);
 }
 
 /*
 }
 
 /*
@@ -158,35 +321,23 @@ ioctl()
                int     fdes;
                int     cmd;
                caddr_t cmarg;
                int     fdes;
                int     cmd;
                caddr_t cmarg;
-       } *uap;
+       } *uap = (struct a *)u.u_ap;
        register int com;
        register u_int size;
        register int com;
        register u_int size;
-       struct buf *bp = 0;
+       caddr_t memp = 0;
 #define STK_PARAMS     128
 #define STK_PARAMS     128
-       char buf[STK_PARAMS];
-       caddr_t data = buf;
+       char stkbuf[STK_PARAMS];
+       caddr_t data = stkbuf;
 
 
-       uap = (struct a *)u.u_ap;
-       GETF(fp, uap->fdes);
+       if ((unsigned)uap->fdes >= NOFILE ||
+           (fp = u.u_ofile[uap->fdes]) == NULL)
+               RETURN (EBADF);
        if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
                u.u_error = EBADF;
                return;
        }
        com = uap->cmd;
 
        if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
                u.u_error = EBADF;
                return;
        }
        com = uap->cmd;
 
-#if defined(vax) && defined(COMPAT)
-       /*
-        * Map old style ioctl's into new for the
-        * sake of backwards compatibility (sigh).
-        */
-       if ((com&~0xffff) == 0) {
-               com = mapioctl(com);
-               if (com == 0) {
-                       u.u_error = EINVAL;
-                       return;
-               }
-       }
-#endif
        if (com == FIOCLEX) {
                u.u_pofile[uap->fdes] |= UF_EXCLOSE;
                return;
        if (com == FIOCLEX) {
                u.u_pofile[uap->fdes] |= UF_EXCLOSE;
                return;
@@ -203,25 +354,28 @@ ioctl()
         */
        size = IOCPARM_LEN(com);
        if (size > IOCPARM_MAX) {
         */
        size = IOCPARM_LEN(com);
        if (size > IOCPARM_MAX) {
-               u.u_error = EFAULT;
+               u.u_error = ENOTTY;
                return;
        }
                return;
        }
-       if (size > sizeof (buf)) {
-               bp = geteblk(IOCPARM_MAX);              /* XXX */
-               data = bp->b_un.b_addr;
+       if (size > sizeof (stkbuf)) {
+               memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS,
+                   M_WAITOK);
+               data = memp;
        }
        if (com&IOC_IN) {
                if (size) {
        }
        if (com&IOC_IN) {
                if (size) {
-                       u.u_error =
-                           copyin(uap->cmarg, data, (u_int)size);
-                       if (u.u_error)
+                       u.u_error = copyin(uap->cmarg, data, (u_int)size);
+                       if (u.u_error) {
+                               if (memp)
+                                       free(memp, M_IOCTLOPS);
                                return;
                                return;
+                       }
                } else
                        *(caddr_t *)data = uap->cmarg;
        } else if ((com&IOC_OUT) && size)
                /*
                } else
                        *(caddr_t *)data = uap->cmarg;
        } else if ((com&IOC_OUT) && size)
                /*
-                * Zero the buffer on the stack so the user
-                * always gets back something deterministic.
+                * Zero the buffer so the user always
+                * gets back something deterministic.
                 */
                bzero(data, size);
        else if (com&IOC_VOID)
                 */
                bzero(data, size);
        else if (com&IOC_VOID)
@@ -257,8 +411,8 @@ ioctl()
                        u.u_error = copyout(data, uap->cmarg, (u_int)size);
                break;
        }
                        u.u_error = copyout(data, uap->cmarg, (u_int)size);
                break;
        }
-       if (bp)
-               brelse(bp);
+       if (memp)
+               free(memp, M_IOCTLOPS);
 }
 
 int    unselect();
 }
 
 int    unselect();
@@ -322,7 +476,6 @@ retry:
                goto done;
        }
        if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
                goto done;
        }
        if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
-               u.u_procp->p_flag &= ~SSEL;
                splx(s);
                goto retry;
        }
                splx(s);
                goto retry;
        }
@@ -345,6 +498,7 @@ retry:
        splx(s);
        goto retry;
 done:
        splx(s);
        goto retry;
 done:
+       u.u_procp->p_flag &= ~SSEL;
 #define        putbits(name, x) \
        if (uap->name) { \
                int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
 #define        putbits(name, x) \
        if (uap->name) { \
                int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \