do not return from sigsuspend prematurely
[unix-history] / usr / src / sys / kern / vfs_syscalls.c
index df17ab1..de3a53f 100644 (file)
@@ -4,22 +4,23 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)vfs_syscalls.c      7.95 (Berkeley) %G%
+ *     @(#)vfs_syscalls.c      7.102 (Berkeley) %G%
  */
 
  */
 
-#include "param.h"
-#include "systm.h"
-#include "namei.h"
-#include "filedesc.h"
-#include "kernel.h"
-#include "file.h"
-#include "stat.h"
-#include "vnode.h"
-#include "mount.h"
-#include "proc.h"
-#include "uio.h"
-#include "malloc.h"
-#include "dirent.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/dirent.h>
+
 #include <vm/vm.h>
 
 #ifdef REF_DIAGNOSTIC
 #include <vm/vm.h>
 
 #ifdef REF_DIAGNOSTIC
@@ -74,25 +75,26 @@ mount(p, uap, retval)
                        return (EINVAL);
                }
                mp = vp->v_mount;
                        return (EINVAL);
                }
                mp = vp->v_mount;
+               flag = mp->mnt_flag;
                /*
                /*
-                * We allow going from read-only to read-write,
-                * but not from read-write to read-only.
+                * We only allow the filesystem to be reloaded if it
+                * is currently mounted read-only.
                 */
                 */
-               if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
-                   (uap->flags & MNT_RDONLY) != 0) {
+               if ((uap->flags & MNT_RELOAD) &&
+                   ((mp->mnt_flag & MNT_RDONLY) == 0)) {
                        vput(vp);
                        return (EOPNOTSUPP);    /* Needs translation */
                }
                        vput(vp);
                        return (EOPNOTSUPP);    /* Needs translation */
                }
-               flag = mp->mnt_flag;
-               mp->mnt_flag |= MNT_UPDATE;
+               mp->mnt_flag |=
+                   uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
                VOP_UNLOCK(vp);
                goto update;
        }
                VOP_UNLOCK(vp);
                goto update;
        }
-       if (vp->v_usecount != 1) {
+       if (vp->v_usecount != 1 && (uap->flags & MNT_UNION) == 0) {
                vput(vp);
                return (EBUSY);
        }
                vput(vp);
                return (EBUSY);
        }
-       if (error = vinvalbuf(vp, 1, p->p_ucred, p))
+       if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
                return (error);
        if (vp->v_type != VDIR) {
                vput(vp);
                return (error);
        if (vp->v_type != VDIR) {
                vput(vp);
@@ -130,31 +132,22 @@ update:
         */
        if (uap->flags & MNT_RDONLY)
                mp->mnt_flag |= MNT_RDONLY;
         */
        if (uap->flags & MNT_RDONLY)
                mp->mnt_flag |= MNT_RDONLY;
-       else
-               mp->mnt_flag &= ~MNT_RDONLY;
-       if (uap->flags & MNT_NOSUID)
-               mp->mnt_flag |= MNT_NOSUID;
-       else
-               mp->mnt_flag &= ~MNT_NOSUID;
-       if (uap->flags & MNT_NOEXEC)
-               mp->mnt_flag |= MNT_NOEXEC;
-       else
-               mp->mnt_flag &= ~MNT_NOEXEC;
-       if (uap->flags & MNT_NODEV)
-               mp->mnt_flag |= MNT_NODEV;
-       else
-               mp->mnt_flag &= ~MNT_NODEV;
-       if (uap->flags & MNT_SYNCHRONOUS)
-               mp->mnt_flag |= MNT_SYNCHRONOUS;
-       else
-               mp->mnt_flag &= ~MNT_SYNCHRONOUS;
+       else if (mp->mnt_flag & MNT_RDONLY)
+               mp->mnt_flag |= MNT_WANTRDWR;
+       mp->mnt_flag &=~
+           (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION);
+       mp->mnt_flag |= uap->flags &
+           (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION);
        /*
         * Mount the filesystem.
         */
        error = VFS_MOUNT(mp, uap->dir, uap->data, &nd, p);
        if (mp->mnt_flag & MNT_UPDATE) {
        /*
         * Mount the filesystem.
         */
        error = VFS_MOUNT(mp, uap->dir, uap->data, &nd, p);
        if (mp->mnt_flag & MNT_UPDATE) {
-               mp->mnt_flag &= ~MNT_UPDATE;
                vrele(vp);
                vrele(vp);
+               if (mp->mnt_flag & MNT_WANTRDWR)
+                       mp->mnt_flag &= ~MNT_RDONLY;
+               mp->mnt_flag &=~
+                   (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
                if (error)
                        mp->mnt_flag = flag;
                return (error);
                if (error)
                        mp->mnt_flag = flag;
                return (error);
@@ -263,6 +256,10 @@ dounmount(mp, flags, p)
  * Sync system call.
  * Sync each mounted filesystem.
  */
  * Sync system call.
  * Sync each mounted filesystem.
  */
+#ifdef DIAGNOSTIC
+int syncprt = 0;
+#endif
+
 struct sync_args {
        int     dummy;
 };
 struct sync_args {
        int     dummy;
 };
@@ -290,6 +287,10 @@ sync(p, uap, retval)
                } else
                        mp = mp->mnt_next;
        } while (mp != rootfs);
                } else
                        mp = mp->mnt_next;
        } while (mp != rootfs);
+#ifdef DIAGNOSTIC
+       if (syncprt)
+               vfs_bufstats();
+#endif /* DIAGNOSTIC */
        return (0);
 }
 
        return (0);
 }
 
@@ -1845,9 +1846,10 @@ ogetdirentries(p, uap, retval)
        VOP_LOCK(vp);
        loff = auio.uio_offset = fp->f_offset;
 #      if (BYTE_ORDER != LITTLE_ENDIAN)
        VOP_LOCK(vp);
        loff = auio.uio_offset = fp->f_offset;
 #      if (BYTE_ORDER != LITTLE_ENDIAN)
-               if (vp->v_mount->mnt_maxsymlinklen <= 0)
+               if (vp->v_mount->mnt_maxsymlinklen <= 0) {
                        error = VOP_READDIR(vp, &auio, fp->f_cred);
                        error = VOP_READDIR(vp, &auio, fp->f_cred);
-               else
+                       fp->f_offset = auio.uio_offset;
+               } else
 #      endif
        {
                kuio = auio;
 #      endif
        {
                kuio = auio;
@@ -1857,6 +1859,7 @@ ogetdirentries(p, uap, retval)
                MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
                kiov.iov_base = dirbuf;
                error = VOP_READDIR(vp, &kuio, fp->f_cred);
                MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
                kiov.iov_base = dirbuf;
                error = VOP_READDIR(vp, &kuio, fp->f_cred);
+               fp->f_offset = kuio.uio_offset;
                if (error == 0) {
                        readcnt = uap->count - kuio.uio_resid;
                        edp = (struct dirent *)&dirbuf[readcnt];
                if (error == 0) {
                        readcnt = uap->count - kuio.uio_resid;
                        edp = (struct dirent *)&dirbuf[readcnt];
@@ -1891,7 +1894,6 @@ ogetdirentries(p, uap, retval)
                }
                FREE(dirbuf, M_TEMP);
        }
                }
                FREE(dirbuf, M_TEMP);
        }
-       fp->f_offset = auio.uio_offset;
        VOP_UNLOCK(vp);
        if (error)
                return (error);
        VOP_UNLOCK(vp);
        if (error)
                return (error);
@@ -1927,6 +1929,7 @@ getdirentries(p, uap, retval)
        if ((fp->f_flag & FREAD) == 0)
                return (EBADF);
        vp = (struct vnode *)fp->f_data;
        if ((fp->f_flag & FREAD) == 0)
                return (EBADF);
        vp = (struct vnode *)fp->f_data;
+unionread:
        if (vp->v_type != VDIR)
                return (EINVAL);
        aiov.iov_base = uap->buf;
        if (vp->v_type != VDIR)
                return (EINVAL);
        aiov.iov_base = uap->buf;
@@ -1944,6 +1947,17 @@ getdirentries(p, uap, retval)
        VOP_UNLOCK(vp);
        if (error)
                return (error);
        VOP_UNLOCK(vp);
        if (error)
                return (error);
+       if ((uap->count == auio.uio_resid) &&
+           (vp->v_flag & VROOT) &&
+           (vp->v_mount->mnt_flag & MNT_UNION)) {
+               struct vnode *tvp = vp;
+               vp = vp->v_mount->mnt_vnodecovered;
+               VREF(vp);
+               fp->f_data = (caddr_t) vp;
+               fp->f_offset = 0;
+               vrele(tvp);
+               goto unionread;
+       }
        error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
        *retval = uap->count - auio.uio_resid;
        return (error);
        error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
        *retval = uap->count - auio.uio_resid;
        return (error);