summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_extattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r--sys/kern/vfs_extattr.c1321
1 files changed, 858 insertions, 463 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 22e16d84..83b6dec 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -50,6 +50,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/namei.h>
#include <sys/filedesc.h>
@@ -64,9 +65,11 @@
#include <sys/malloc.h>
#include <sys/dirent.h>
+/* see if this is needed XXX JH
#ifdef UNION
#include <miscfs/union/union.h>
#endif
+*/
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -74,7 +77,8 @@
#include <vm/vm_extern.h>
#include <sys/sysctl.h>
-static int change_dir __P((struct nameidata *ndp, struct proc *p));
+static int change_dir __P((struct nameidata *ndp, struct proc *p));
+static void checkdirs __P((struct vnode *olddp));
/*
* Virtual File System System Calls
@@ -85,7 +89,7 @@ static int change_dir __P((struct nameidata *ndp, struct proc *p));
*/
#ifndef _SYS_SYSPROTO_H_
struct mount_args {
- int type;
+ char *type;
char *path;
int flags;
caddr_t data;
@@ -95,29 +99,32 @@ struct mount_args {
int
mount(p, uap, retval)
struct proc *p;
- register struct mount_args *uap;
- int *retval;
+ register struct mount_args /* {
+ syscallarg(char *) type;
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(caddr_t) data;
+ } */ *uap;
+ register_t *retval;
{
- register struct vnode *vp;
- register struct mount *mp;
+ struct vnode *vp;
+ struct mount *mp;
+ struct vfsconf *vfsp;
int error, flag = 0;
+ struct vattr va;
+ u_long fstypenum;
struct nameidata nd;
+ char fstypename[MFSNAMELEN];
/*
- * Must be super user
- */
- error = suser(p->p_ucred, &p->p_acflag);
- if (error)
- return (error);
- /*
* Get vnode to be covered
*/
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- if (uap->flags & MNT_UPDATE) {
+ if (SCARG(uap, flags) & MNT_UPDATE) {
if ((vp->v_flag & VROOT) == 0) {
vput(vp);
return (EINVAL);
@@ -128,68 +135,135 @@ mount(p, uap, retval)
* We only allow the filesystem to be reloaded if it
* is currently mounted read-only.
*/
- if ((uap->flags & MNT_RELOAD) &&
+ if ((SCARG(uap, flags) & MNT_RELOAD) &&
((mp->mnt_flag & MNT_RDONLY) == 0)) {
vput(vp);
return (EOPNOTSUPP); /* Needs translation */
}
mp->mnt_flag |=
- uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
- VOP_UNLOCK(vp);
+ SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
+ /*
+ * Only root, or the user that did the original mount is
+ * permitted to update it.
+ */
+ if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
+ (error = suser(p->p_ucred, &p->p_acflag))) {
+ vput(vp);
+ return (error);
+ }
+ /*
+ * Do not allow NFS export by non-root users. Silently
+ * enforce MNT_NOSUID and MNT_NODEV for non-root users.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ if (SCARG(uap, flags) & MNT_EXPORTED) {
+ vput(vp);
+ return (EPERM);
+ }
+ SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
+ }
+ if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
+ vput(vp);
+ return (EBUSY);
+ }
+ VOP_UNLOCK(vp, 0, p);
goto update;
}
- error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0);
- if (error)
+ /*
+ * If the user is not root, ensure that they own the directory
+ * onto which we are attempting to mount.
+ */
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
+ (va.va_uid != p->p_ucred->cr_uid &&
+ (error = suser(p->p_ucred, &p->p_acflag)))) {
+ vput(vp);
+ return (error);
+ }
+ /*
+ * Do not allow NFS export by non-root users. Silently
+ * enforce MNT_NOSUID and MNT_NODEV for non-root users.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ if (SCARG(uap, flags) & MNT_EXPORTED) {
+ vput(vp);
+ return (EPERM);
+ }
+ SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
+ }
+ if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
return (error);
if (vp->v_type != VDIR) {
vput(vp);
return (ENOTDIR);
}
- if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
- vput(vp);
- return (ENODEV);
- }
-
+#ifdef COMPAT_43
/*
- * Allocate and initialize the file system.
+ * Historically filesystem types were identified by number. If we
+ * get an integer for the filesystem type instead of a string, we
+ * check to see if it matches one of the historic filesystem types.
*/
- mp = (struct mount *)malloc((u_long)sizeof(struct mount),
- M_MOUNT, M_WAITOK);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = vfssw[uap->type];
- mp->mnt_vfc = vfsconf[uap->type];
- error = vfs_lock(mp);
- if (error) {
- free((caddr_t)mp, M_MOUNT);
+ fstypenum = (u_long)SCARG(uap, type);
+ if (fstypenum < maxvfsconf) {
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (vfsp->vfc_typenum == fstypenum)
+ break;
+ if (vfsp == NULL) {
+ vput(vp);
+ return (ENODEV);
+ }
+ strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
+ } else
+#endif /* COMPAT_43 */
+ if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) {
vput(vp);
return (error);
}
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (!strcmp(vfsp->vfc_name, fstypename))
+ break;
+ if (vfsp == NULL) {
+ vput(vp);
+ return (ENODEV);
+ }
if (vp->v_mountedhere != NULL) {
- vfs_unlock(mp);
- free((caddr_t)mp, M_MOUNT);
vput(vp);
return (EBUSY);
}
+
+ /*
+ * Allocate and initialize the filesystem.
+ */
+ mp = (struct mount *)malloc((u_long)sizeof(struct mount),
+ M_MOUNT, M_WAITOK);
+ bzero((char *)mp, (u_long)sizeof(struct mount));
+ lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
+ (void)vfs_busy(mp, LK_NOWAIT, 0, p);
+ mp->mnt_op = vfsp->vfc_vfsops;
+ mp->mnt_vfc = vfsp;
+ vfsp->vfc_refcount++;
+ mp->mnt_stat.f_type = vfsp->vfc_typenum;
+ mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
+ strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
vp->v_mountedhere = mp;
mp->mnt_vnodecovered = vp;
- vfsconf[uap->type]->vfc_refcount++;
-
+ mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
update:
/*
* Set the mount level flags.
*/
- if (uap->flags & MNT_RDONLY)
+ if (SCARG(uap, flags) & MNT_RDONLY)
mp->mnt_flag |= MNT_RDONLY;
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 | MNT_ASYNC | MNT_NOATIME);
- mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
- MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | MNT_NOATIME);
+ mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
+ MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
+ MNT_NOATIME);
/*
* Mount the filesystem.
*/
- error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
+ error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
if (mp->mnt_flag & MNT_UPDATE) {
vrele(vp);
if (mp->mnt_flag & MNT_WANTRDWR)
@@ -198,6 +272,7 @@ update:
(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
if (error)
mp->mnt_flag = flag;
+ vfs_unbusy(mp, p);
return (error);
}
/*
@@ -205,23 +280,63 @@ update:
*/
cache_purge(vp);
if (!error) {
+ simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
- VOP_UNLOCK(vp);
- vfs_unlock(mp);
- error = VFS_START(mp, 0, p);
- if (error)
+ simple_unlock(&mountlist_slock);
+ checkdirs(vp);
+ VOP_UNLOCK(vp, 0, p);
+ vfs_unbusy(mp, p);
+ if (error = VFS_START(mp, 0, p))
vrele(vp);
} else {
mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
- vfs_unlock(mp);
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
free((caddr_t)mp, M_MOUNT);
vput(vp);
- vfsconf[uap->type]->vfc_refcount--;
}
return (error);
}
/*
+ * Scan all active processes to see if any of them have a current
+ * or root directory onto which the new filesystem has just been
+ * mounted. If so, replace them with the new mount point.
+ */
+static void
+checkdirs(olddp)
+ struct vnode *olddp;
+{
+ struct filedesc *fdp;
+ struct vnode *newdp;
+ struct proc *p;
+
+ if (olddp->v_usecount == 1)
+ return;
+ if (VFS_ROOT(olddp->v_mountedhere, &newdp))
+ panic("mount: lost mount");
+ for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
+ fdp = p->p_fd;
+ if (fdp->fd_cdir == olddp) {
+ vrele(fdp->fd_cdir);
+ VREF(newdp);
+ fdp->fd_cdir = newdp;
+ }
+ if (fdp->fd_rdir == olddp) {
+ vrele(fdp->fd_rdir);
+ VREF(newdp);
+ fdp->fd_rdir = newdp;
+ }
+ }
+ if (rootvnode == olddp) {
+ vrele(rootvnode);
+ VREF(newdp);
+ rootvnode = newdp;
+ }
+ vput(newdp);
+}
+
+/*
* Unmount a file system.
*
* Note: unmount takes a path to the vnode mounted on as argument,
@@ -237,47 +352,51 @@ struct unmount_args {
int
unmount(p, uap, retval)
struct proc *p;
- register struct unmount_args *uap;
- int *retval;
+ register struct unmount_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct mount *mp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
+ mp = vp->v_mount;
/*
- * Unless this is a user mount, then must
- * have suser privilege.
+ * Only root, or the user that did the original mount is
+ * permitted to unmount this filesystem.
*/
- if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
+ if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
(error = suser(p->p_ucred, &p->p_acflag))) {
vput(vp);
return (error);
}
/*
- * Must be the root of the filesystem
+ * Don't allow unmounting the root file system.
*/
- if ((vp->v_flag & VROOT) == 0) {
+ if (mp->mnt_flag & MNT_ROOTFS) {
vput(vp);
return (EINVAL);
}
- mp = vp->v_mount;
- vput(vp);
/*
- * Don't allow unmount of the root filesystem
+ * Must be the root of the filesystem
*/
- if (mp->mnt_flag & MNT_ROOTFS)
+ if ((vp->v_flag & VROOT) == 0) {
+ vput(vp);
return (EINVAL);
-
- return (dounmount(mp, uap->flags, p));
+ }
+ vput(vp);
+ return (dounmount(mp, SCARG(uap, flags), p));
}
/*
@@ -292,74 +411,86 @@ dounmount(mp, flags, p)
struct vnode *coveredvp;
int error;
- coveredvp = mp->mnt_vnodecovered;
- if (vfs_busy(mp))
- return (EBUSY);
+ simple_lock(&mountlist_slock);
mp->mnt_flag |= MNT_UNMOUNT;
- error = vfs_lock(mp);
- if (error)
- return (error);
-
+ lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
mp->mnt_flag &=~ MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
vnode_pager_umount(mp); /* release cached vnodes */
cache_purgevfs(mp); /* remove cache entries for this file sys */
- if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
+ if (((mp->mnt_flag & MNT_RDONLY) ||
+ (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
(flags & MNT_FORCE))
error = VFS_UNMOUNT(mp, flags, p);
- mp->mnt_flag &= ~MNT_UNMOUNT;
- vfs_unbusy(mp);
+ simple_lock(&mountlist_slock);
if (error) {
- vfs_unlock(mp);
- } else {
+ mp->mnt_flag &= ~MNT_UNMOUNT;
+ lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
+ &mountlist_slock, p);
+ return (error);
+ }
+ CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
+ if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
+ coveredvp->v_mountedhere = (struct mount *)0;
vrele(coveredvp);
- CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
- mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
- vfs_unlock(mp);
- mp->mnt_vfc->vfc_refcount--;
- if (mp->mnt_vnodelist.lh_first != NULL)
- panic("unmount: dangling vnode");
- free((caddr_t)mp, M_MOUNT);
}
- return (error);
+ mp->mnt_vfc->vfc_refcount--;
+ if (mp->mnt_vnodelist.lh_first != NULL)
+ panic("unmount: dangling vnode");
+ lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
+ if (mp->mnt_flag & MNT_MWAIT)
+ wakeup((caddr_t)mp);
+ free((caddr_t)mp, M_MOUNT);
+ return (0);
}
/*
* Sync each mounted filesystem.
*/
-
#ifndef _SYS_SYSPROTO_H_
struct sync_args {
int dummy;
};
#endif
+#ifdef DEBUG
+int syncprt = 0;
+SYSCTL_INT(_debug, 0, syncprt, CTLFLAG_RW, &syncprt, 0, "");
+#endif
+
/* ARGSUSED */
int
sync(p, uap, retval)
struct proc *p;
struct sync_args *uap;
- int *retval;
+ register_t *retval;
{
- register struct mount *mp;
+ register struct mount *mp, *nmp;
int asyncflag;
- for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = mp->mnt_list.cqe_next) {
- /*
- * The lock check below is to avoid races with mount
- * and unmount.
- */
- if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
- !vfs_busy(mp)) {
+ simple_lock(&mountlist_slock);
+ for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ nmp = mp->mnt_list.cqe_next;
+ continue;
+ }
+ if ((mp->mnt_flag & MNT_RDONLY) == 0) {
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
VFS_SYNC(mp, MNT_NOWAIT, p != NULL ? p->p_ucred : NOCRED, p);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
- vfs_unbusy(mp);
}
+ simple_lock(&mountlist_slock);
+ nmp = mp->mnt_list.cqe_next;
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
+#ifdef DIAGNOSTIC
+ if (syncprt)
+ vfs_bufstats();
+#endif /* DIAGNOSTIC */
return (0);
}
@@ -378,20 +509,25 @@ struct quotactl_args {
int
quotactl(p, uap, retval)
struct proc *p;
- register struct quotactl_args *uap;
- int *retval;
+ register struct quotactl_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) cmd;
+ syscallarg(int) uid;
+ syscallarg(caddr_t) arg;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
mp = nd.ni_vp->v_mount;
vrele(nd.ni_vp);
- return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
+ return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
+ SCARG(uap, arg), p));
}
/*
@@ -407,17 +543,19 @@ struct statfs_args {
int
statfs(p, uap, retval)
struct proc *p;
- register struct statfs_args *uap;
- int *retval;
+ register struct statfs_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct statfs *) buf;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp;
register struct statfs *sp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
mp = nd.ni_vp->v_mount;
sp = &mp->mnt_stat;
@@ -426,7 +564,7 @@ statfs(p, uap, retval)
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
+ return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
}
/*
@@ -442,16 +580,18 @@ struct fstatfs_args {
int
fstatfs(p, uap, retval)
struct proc *p;
- register struct fstatfs_args *uap;
- int *retval;
+ register struct fstatfs_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct statfs *) buf;
+ } */ *uap;
+ register_t *retval;
{
struct file *fp;
struct mount *mp;
register struct statfs *sp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
mp = ((struct vnode *)fp->f_data)->v_mount;
sp = &mp->mnt_stat;
@@ -459,7 +599,7 @@ fstatfs(p, uap, retval)
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
+ return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
}
/*
@@ -475,48 +615,55 @@ struct getfsstat_args {
int
getfsstat(p, uap, retval)
struct proc *p;
- register struct getfsstat_args *uap;
- int *retval;
+ register struct getfsstat_args /* {
+ syscallarg(struct statfs *) buf;
+ syscallarg(long) bufsize;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp, *nmp;
register struct statfs *sp;
caddr_t sfsp;
long count, maxcount, error;
- maxcount = uap->bufsize / sizeof(struct statfs);
- sfsp = (caddr_t)uap->buf;
+ maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
+ sfsp = (caddr_t)SCARG(uap, buf);
count = 0;
+ simple_lock(&mountlist_slock);
for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
- if (vfs_busy(mp)) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
nmp = mp->mnt_list.cqe_next;
continue;
}
- if (sfsp && count < maxcount &&
- ((mp->mnt_flag & MNT_MLOCK) == 0)) {
+ if (sfsp && count < maxcount) {
sp = &mp->mnt_stat;
/*
* If MNT_NOWAIT is specified, do not refresh the
* fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
*/
- if (((uap->flags & MNT_NOWAIT) == 0 ||
- (uap->flags & MNT_WAIT)) &&
+ if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
+ (SCARG(uap, flags) & MNT_WAIT)) &&
(error = VFS_STATFS(mp, sp, p))) {
+ simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
continue;
}
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
if (error) {
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
return (error);
}
sfsp += sizeof(*sp);
}
count++;
+ simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
if (sfsp && count > maxcount)
*retval = maxcount;
else
@@ -536,27 +683,41 @@ struct fchdir_args {
int
fchdir(p, uap, retval)
struct proc *p;
- struct fchdir_args *uap;
- int *retval;
+ struct fchdir_args /* {
+ syscallarg(int) fd;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
- register struct vnode *vp;
+ struct vnode *vp, *tdp;
+ struct mount *mp;
struct file *fp;
int error;
- error = getvnode(fdp, uap->fd, &fp);
- if (error)
+ if (error = getvnode(fdp, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- VOP_LOCK(vp);
+ VREF(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type != VDIR)
error = ENOTDIR;
else
error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
- VOP_UNLOCK(vp);
- if (error)
+ while (!error && (mp = vp->v_mountedhere) != NULL) {
+ if (vfs_busy(mp, 0, 0, p))
+ continue;
+ error = VFS_ROOT(mp, &tdp);
+ vfs_unbusy(mp, p);
+ if (error)
+ break;
+ vput(vp);
+ vp = tdp;
+ }
+ if (error) {
+ vput(vp);
return (error);
- VREF(vp);
+ }
+ VOP_UNLOCK(vp, 0, p);
vrele(fdp->fd_cdir);
fdp->fd_cdir = vp;
return (0);
@@ -574,16 +735,18 @@ struct chdir_args {
int
chdir(p, uap, retval)
struct proc *p;
- struct chdir_args *uap;
- int *retval;
+ struct chdir_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = change_dir(&nd, p);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = change_dir(&nd, p))
return (error);
vrele(fdp->fd_cdir);
fdp->fd_cdir = nd.ni_vp;
@@ -602,8 +765,10 @@ struct chroot_args {
int
chroot(p, uap, retval)
struct proc *p;
- struct chroot_args *uap;
- int *retval;
+ struct chroot_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
int error;
@@ -612,9 +777,9 @@ chroot(p, uap, retval)
error = suser(p->p_ucred, &p->p_acflag);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = change_dir(&nd, p);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = change_dir(&nd, p))
return (error);
if (fdp->fd_rdir != NULL)
vrele(fdp->fd_rdir);
@@ -641,9 +806,10 @@ change_dir(ndp, p)
error = ENOTDIR;
else
error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
- VOP_UNLOCK(vp);
if (error)
- vrele(vp);
+ vput(vp);
+ else
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -661,8 +827,12 @@ struct open_args {
int
open(p, uap, retval)
struct proc *p;
- register struct open_args *uap;
- int *retval;
+ register struct open_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
register struct file *fp;
@@ -677,17 +847,17 @@ open(p, uap, retval)
if (error)
return (error);
fp = nfp;
- flags = FFLAGS(uap->flags);
- cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
+ flags = FFLAGS(SCARG(uap, flags));
+ cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
p->p_dupfd = -indx - 1; /* XXX check for fdopen */
error = vn_open(&nd, flags, cmode);
if (error) {
ffree(fp);
if ((error == ENODEV || error == ENXIO) &&
- p->p_dupfd >= 0 && /* XXX from fdopen */
+ p->p_dupfd >= 0 && /* XXX from fdopen */
(error =
- dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
+ dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
*retval = indx;
return (0);
}
@@ -714,18 +884,17 @@ open(p, uap, retval)
type = F_FLOCK;
if ((flags & FNONBLOCK) == 0)
type |= F_WAIT;
- VOP_UNLOCK(vp);
- error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
- if (error) {
+ VOP_UNLOCK(vp, 0, p);
+ if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
ffree(fp);
fdp->fd_ofiles[indx] = NULL;
return (error);
}
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
fp->f_flag |= FHASLOCK;
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
*retval = indx;
return (0);
}
@@ -743,15 +912,22 @@ struct ocreat_args {
int
ocreat(p, uap, retval)
struct proc *p;
- register struct ocreat_args *uap;
- int *retval;
+ register struct ocreat_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
- struct open_args openuap;
-
- openuap.path = uap->path;
- openuap.mode = uap->mode;
- openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
- return (open(p, &openuap, retval));
+ struct open_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(int) mode;
+ } */ nuap;
+
+ SCARG(&nuap, path) = SCARG(uap, path);
+ SCARG(&nuap, mode) = SCARG(uap, mode);
+ SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
+ return (open(p, &nuap, retval));
}
#endif /* COMPAT_43 */
@@ -769,30 +945,35 @@ struct mknod_args {
int
mknod(p, uap, retval)
struct proc *p;
- register struct mknod_args *uap;
- int *retval;
+ register struct mknod_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ syscallarg(int) dev;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
+ int whiteout;
struct nameidata nd;
error = suser(p->p_ucred, &p->p_acflag);
if (error)
return (error);
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp != NULL)
error = EEXIST;
else {
VATTR_NULL(&vattr);
- vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
- vattr.va_rdev = uap->dev;
+ vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
+ vattr.va_rdev = SCARG(uap, dev);
+ whiteout = 0;
- switch (uap->mode & S_IFMT) {
+ switch (SCARG(uap, mode) & S_IFMT) {
case S_IFMT: /* used by badsect to flag bad sectors */
vattr.va_type = VBAD;
break;
@@ -802,14 +983,25 @@ mknod(p, uap, retval)
case S_IFBLK:
vattr.va_type = VBLK;
break;
+ case S_IFWHT:
+ whiteout = 1;
+ break;
default:
error = EINVAL;
break;
}
}
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ if (whiteout) {
+ error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
+ if (error)
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ vput(nd.ni_dvp);
+ } else {
+ error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
+ &nd.ni_cnd, &vattr);
+ }
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == vp)
@@ -823,7 +1015,7 @@ mknod(p, uap, retval)
}
/*
- * Create named pipe.
+ * Create a named pipe.
*/
#ifndef _SYS_SYSPROTO_H_
struct mkfifo_args {
@@ -835,16 +1027,21 @@ struct mkfifo_args {
int
mkfifo(p, uap, retval)
struct proc *p;
- register struct mkfifo_args *uap;
- int *retval;
+ register struct mkfifo_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
+#ifndef FIFO
+ return (EOPNOTSUPP);
+#else
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
if (nd.ni_vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -857,9 +1054,10 @@ mkfifo(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_type = VFIFO;
- vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
+#endif /* FIFO */
}
/*
@@ -875,22 +1073,24 @@ struct link_args {
int
link(p, uap, retval)
struct proc *p;
- register struct link_args *uap;
- int *retval;
+ register struct link_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) link;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct nameidata nd;
int error;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type == VDIR)
error = EPERM; /* POSIX */
else {
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
error = namei(&nd);
if (!error) {
if (nd.ni_vp != NULL) {
@@ -903,10 +1103,9 @@ link(p, uap, retval)
vrele(nd.ni_vp);
error = EEXIST;
} else {
- LEASE_CHECK(nd.ni_dvp,
- p, p->p_ucred, LEASE_WRITE);
- LEASE_CHECK(vp,
- p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
+ LEASE_WRITE);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
}
}
@@ -928,8 +1127,11 @@ struct symlink_args {
int
symlink(p, uap, retval)
struct proc *p;
- register struct symlink_args *uap;
- int *retval;
+ register struct symlink_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) link;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
char *path;
@@ -937,12 +1139,10 @@ symlink(p, uap, retval)
struct nameidata nd;
MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
- error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
- if (error)
+ if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL))
goto out;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
+ if (error = namei(&nd))
goto out;
if (nd.ni_vp) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -956,7 +1156,7 @@ symlink(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
out:
FREE(path, M_NAMEI);
@@ -964,6 +1164,45 @@ out:
}
/*
+ * Delete a whiteout from the filesystem.
+ */
+/* ARGSUSED */
+int
+undelete(p, uap, retval)
+ struct proc *p;
+ register struct undelete_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
+{
+ int error;
+ struct nameidata nd;
+
+ NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ error = namei(&nd);
+ if (error)
+ return (error);
+
+ if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ if (nd.ni_vp)
+ vrele(nd.ni_vp);
+ return (EEXIST);
+ }
+
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE))
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ vput(nd.ni_dvp);
+ return (error);
+}
+
+/*
* Delete a name from the filesystem.
*/
#ifndef _SYS_SYSPROTO_H_
@@ -975,20 +1214,21 @@ struct unlink_args {
int
unlink(p, uap, retval)
struct proc *p;
- struct unlink_args *uap;
- int *retval;
+ struct unlink_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
int error;
struct nameidata nd;
- NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EPERM; /* POSIX */
@@ -1001,11 +1241,11 @@ unlink(p, uap, retval)
if (vp->v_flag & VROOT)
error = EBUSY;
else
- (void) vnode_pager_uncache(vp);
+ (void) vnode_pager_uncache(vp, p);
}
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -1013,7 +1253,8 @@ unlink(p, uap, retval)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
- vput(vp);
+ if (vp != NULLVP)
+ vput(vp);
}
return (error);
}
@@ -1032,8 +1273,13 @@ struct lseek_args {
int
lseek(p, uap, retval)
struct proc *p;
- register struct lseek_args *uap;
- int *retval;
+ register struct lseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) offset;
+ syscallarg(int) whence;
+ } */ *uap;
+ register_t *retval; /* XXX */
{
struct ucred *cred = p->p_ucred;
register struct filedesc *fdp = p->p_fd;
@@ -1041,23 +1287,23 @@ lseek(p, uap, retval)
struct vattr vattr;
int error;
- if ((u_int)uap->fd >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[uap->fd]) == NULL)
+ if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
return (EBADF);
if (fp->f_type != DTYPE_VNODE)
return (ESPIPE);
- switch (uap->whence) {
+ switch (SCARG(uap, whence)) {
case L_INCR:
- fp->f_offset += uap->offset;
+ fp->f_offset += SCARG(uap, offset);
break;
case L_XTND:
error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
if (error)
return (error);
- fp->f_offset = uap->offset + vattr.va_size;
+ fp->f_offset = SCARG(uap, offset) + vattr.va_size;
break;
case L_SET:
- fp->f_offset = uap->offset;
+ fp->f_offset = SCARG(uap, offset);
break;
default:
return (EINVAL);
@@ -1080,17 +1326,26 @@ struct olseek_args {
int
olseek(p, uap, retval)
struct proc *p;
- register struct olseek_args *uap;
- int *retval;
+ register struct olseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(long) offset;
+ syscallarg(int) whence;
+ } */ *uap;
+ register_t *retval;
{
- struct lseek_args nuap;
+ struct lseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) offset;
+ syscallarg(int) whence;
+ } */ nuap;
off_t qret;
int error;
- nuap.fd = uap->fd;
- nuap.offset = uap->offset;
- nuap.whence = uap->whence;
- error = lseek(p, &nuap, (int *)&qret);
+ SCARG(&nuap, fd) = SCARG(uap, fd);
+ SCARG(&nuap, offset) = SCARG(uap, offset);
+ SCARG(&nuap, whence) = SCARG(uap, whence);
+ error = lseek(p, &nuap, (register_t *) &qret);
*(long *)retval = qret;
return (error);
}
@@ -1108,8 +1363,11 @@ struct access_args {
int
access(p, uap, retval)
struct proc *p;
- register struct access_args *uap;
- int *retval;
+ register struct access_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct ucred *cred = p->p_ucred;
register struct vnode *vp;
@@ -1120,20 +1378,20 @@ access(p, uap, retval)
t_gid = cred->cr_groups[0];
cred->cr_uid = p->p_cred->p_ruid;
cred->cr_groups[0] = p->p_cred->p_rgid;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
goto out1;
vp = nd.ni_vp;
/* Flags == 0 means only check for existence. */
- if (uap->flags) {
+ if (SCARG(uap, flags)) {
flags = 0;
- if (uap->flags & R_OK)
+ if (SCARG(uap, flags) & R_OK)
flags |= VREAD;
- if (uap->flags & W_OK)
+ if (SCARG(uap, flags) & W_OK)
flags |= VWRITE;
- if (uap->flags & X_OK)
+ if (SCARG(uap, flags) & X_OK)
flags |= VEXEC;
if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
error = VOP_ACCESS(vp, flags, cred, p);
@@ -1159,24 +1417,27 @@ struct ostat_args {
int
ostat(p, uap, retval)
struct proc *p;
- register struct ostat_args *uap;
- int *retval;
+ register struct ostat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct ostat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct stat sb;
struct ostat osb;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
error = vn_stat(nd.ni_vp, &sb, p);
vput(nd.ni_vp);
if (error)
return (error);
cvtstat(&sb, &osb);
- error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
+ error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
return (error);
}
@@ -1193,8 +1454,11 @@ struct olstat_args {
int
olstat(p, uap, retval)
struct proc *p;
- register struct olstat_args *uap;
- int *retval;
+ register struct olstat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct ostat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct vnode *vp, *dvp;
struct stat sb, sb1;
@@ -1203,9 +1467,8 @@ olstat(p, uap, retval)
struct nameidata nd;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
- uap->path, p);
- error = namei(&nd);
- if (error)
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
/*
* For symbolic links, always return the attributes of its
@@ -1240,7 +1503,7 @@ olstat(p, uap, retval)
sb.st_blocks = sb1.st_blocks;
}
cvtstat(&sb, &osb);
- error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
+ error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
return (error);
}
@@ -1287,22 +1550,25 @@ struct stat_args {
int
stat(p, uap, retval)
struct proc *p;
- register struct stat_args *uap;
- int *retval;
+ register struct stat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct stat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct stat sb;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
error = vn_stat(nd.ni_vp, &sb, p);
vput(nd.ni_vp);
if (error)
return (error);
- error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
+ error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
return (error);
}
@@ -1319,8 +1585,11 @@ struct lstat_args {
int
lstat(p, uap, retval)
struct proc *p;
- register struct lstat_args *uap;
- int *retval;
+ register struct lstat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct stat *) ub;
+ } */ *uap;
+ register_t *retval;
{
int error;
struct vnode *vp, *dvp;
@@ -1328,13 +1597,12 @@ lstat(p, uap, retval)
struct nameidata nd;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
- uap->path, p);
- error = namei(&nd);
- if (error)
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
/*
- * For symbolic links, always return the attributes of its
- * containing directory, except for mode, size, and links.
+ * For symbolic links, always return the attributes of its containing
+ * directory, except for mode, size, inode number, and links.
*/
vp = nd.ni_vp;
dvp = nd.ni_dvp;
@@ -1363,8 +1631,9 @@ lstat(p, uap, retval)
sb.st_nlink = sb1.st_nlink;
sb.st_size = sb1.st_size;
sb.st_blocks = sb1.st_blocks;
+ sb.st_ino = sb1.st_ino;
}
- error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
+ error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
return (error);
}
@@ -1381,17 +1650,20 @@ struct pathconf_args {
int
pathconf(p, uap, retval)
struct proc *p;
- register struct pathconf_args *uap;
- int *retval;
+ register struct pathconf_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) name;
+ } */ *uap;
+ register_t *retval;
{
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
- error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
+ error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
vput(nd.ni_vp);
return (error);
}
@@ -1410,8 +1682,12 @@ struct readlink_args {
int
readlink(p, uap, retval)
struct proc *p;
- register struct readlink_args *uap;
- int *retval;
+ register struct readlink_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) buf;
+ syscallarg(int) count;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct iovec aiov;
@@ -1419,27 +1695,27 @@ readlink(p, uap, retval)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type != VLNK)
error = EINVAL;
else {
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
+ auio.uio_resid = SCARG(uap, count);
error = VOP_READLINK(vp, &auio, p->p_ucred);
}
vput(vp);
- *retval = uap->count - auio.uio_resid;
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
@@ -1456,23 +1732,25 @@ struct chflags_args {
int
chflags(p, uap, retval)
struct proc *p;
- register struct chflags_args *uap;
- int *retval;
+ register struct chflags_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_flags = uap->flags;
+ vattr.va_flags = SCARG(uap, flags);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1491,24 +1769,26 @@ struct fchflags_args {
int
fchflags(p, uap, retval)
struct proc *p;
- register struct fchflags_args *uap;
- int *retval;
+ register struct fchflags_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_flags = uap->flags;
+ vattr.va_flags = SCARG(uap, flags);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1525,23 +1805,25 @@ struct chmod_args {
int
chmod(p, uap, retval)
struct proc *p;
- register struct chmod_args *uap;
- int *retval;
+ register struct chmod_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_mode = uap->mode & ALLPERMS;
+ vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1560,24 +1842,26 @@ struct fchmod_args {
int
fchmod(p, uap, retval)
struct proc *p;
- register struct fchmod_args *uap;
- int *retval;
+ register struct fchmod_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_mode = uap->mode & ALLPERMS;
+ vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1595,24 +1879,27 @@ struct chown_args {
int
chown(p, uap, retval)
struct proc *p;
- register struct chown_args *uap;
- int *retval;
+ register struct chown_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_uid = uap->uid;
- vattr.va_gid = uap->gid;
+ vattr.va_uid = SCARG(uap, uid);
+ vattr.va_gid = SCARG(uap, gid);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1632,25 +1919,28 @@ struct fchown_args {
int
fchown(p, uap, retval)
struct proc *p;
- register struct fchown_args *uap;
- int *retval;
+ register struct fchown_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_uid = uap->uid;
- vattr.va_gid = uap->gid;
+ vattr.va_uid = SCARG(uap, uid);
+ vattr.va_gid = SCARG(uap, gid);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1667,8 +1957,11 @@ struct utimes_args {
int
utimes(p, uap, retval)
struct proc *p;
- register struct utimes_args *uap;
- int *retval;
+ register struct utimes_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct timeval *) tptr;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct timeval tv[2];
@@ -1677,22 +1970,19 @@ utimes(p, uap, retval)
struct nameidata nd;
VATTR_NULL(&vattr);
- if (uap->tptr == NULL) {
+ if (SCARG(uap, tptr) == NULL) {
microtime(&tv[0]);
tv[1] = tv[0];
vattr.va_vaflags |= VA_UTIMES_NULL;
- } else {
- error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
- if (error)
- return (error);
- }
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
+ sizeof (tv)))
+ return (error);
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
vattr.va_atime.tv_sec = tv[0].tv_sec;
vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
vattr.va_mtime.tv_sec = tv[1].tv_sec;
@@ -1716,8 +2006,12 @@ struct truncate_args {
int
truncate(p, uap, retval)
struct proc *p;
- register struct truncate_args *uap;
- int *retval;
+ register struct truncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
@@ -1726,19 +2020,18 @@ truncate(p, uap, retval)
if (uap->length < 0)
return(EINVAL);
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EISDIR;
else if ((error = vn_writechk(vp)) == 0 &&
(error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
VATTR_NULL(&vattr);
- vattr.va_size = uap->length;
+ vattr.va_size = SCARG(uap, length);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
}
vput(vp);
@@ -1759,8 +2052,12 @@ struct ftruncate_args {
int
ftruncate(p, uap, retval)
struct proc *p;
- register struct ftruncate_args *uap;
- int *retval;
+ register struct ftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
@@ -1769,22 +2066,21 @@ ftruncate(p, uap, retval)
if (uap->length < 0)
return(EINVAL);
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
if ((fp->f_flag & FWRITE) == 0)
return (EINVAL);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EISDIR;
else if ((error = vn_writechk(vp)) == 0) {
VATTR_NULL(&vattr);
- vattr.va_size = uap->length;
+ vattr.va_size = SCARG(uap, length);
error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1802,13 +2098,20 @@ struct otruncate_args {
int
otruncate(p, uap, retval)
struct proc *p;
- register struct otruncate_args *uap;
- int *retval;
+ register struct otruncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(long) length;
+ } */ *uap;
+ register_t *retval;
{
- struct truncate_args nuap;
-
- nuap.path = uap->path;
- nuap.length = uap->length;
+ struct truncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ nuap;
+
+ SCARG(&nuap, path) = SCARG(uap, path);
+ SCARG(&nuap, length) = SCARG(uap, length);
return (truncate(p, &nuap, retval));
}
@@ -1825,13 +2128,20 @@ struct oftruncate_args {
int
oftruncate(p, uap, retval)
struct proc *p;
- register struct oftruncate_args *uap;
- int *retval;
+ register struct oftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(long) length;
+ } */ *uap;
+ register_t *retval;
{
- struct ftruncate_args nuap;
-
- nuap.fd = uap->fd;
- nuap.length = uap->length;
+ struct ftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ nuap;
+
+ SCARG(&nuap, fd) = SCARG(uap, fd);
+ SCARG(&nuap, length) = SCARG(uap, length);
return (ftruncate(p, &nuap, retval));
}
#endif /* COMPAT_43 || COMPAT_SUNOS */
@@ -1848,24 +2158,25 @@ struct fsync_args {
int
fsync(p, uap, retval)
struct proc *p;
- struct fsync_args *uap;
- int *retval;
+ struct fsync_args /* {
+ syscallarg(int) fd;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_object) {
vm_object_page_clean(vp->v_object, 0, 0 ,0, FALSE);
}
error = VOP_FSYNC(vp, fp->f_cred,
(vp->v_mount->mnt_flag & MNT_ASYNC) ? MNT_NOWAIT : MNT_WAIT, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1883,29 +2194,29 @@ struct rename_args {
int
rename(p, uap, retval)
struct proc *p;
- register struct rename_args *uap;
- int *retval;
+ register struct rename_args /* {
+ syscallarg(char *) from;
+ syscallarg(char *) to;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *tvp, *fvp, *tdvp;
struct nameidata fromnd, tond;
int error;
NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
- uap->from, p);
- error = namei(&fromnd);
- if (error)
+ SCARG(uap, from), p);
+ if (error = namei(&fromnd))
return (error);
fvp = fromnd.ni_vp;
NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
- UIO_USERSPACE, uap->to, p);
+ UIO_USERSPACE, SCARG(uap, to), p);
if (fromnd.ni_vp->v_type == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
- error = namei(&tond);
- if (error) {
+ if (error = namei(&tond)) {
/* Translate error code for rename("dir1", "dir2/."). */
if (error == EISDIR && fvp->v_type == VDIR)
error = EINVAL;
-
VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
vrele(fromnd.ni_dvp);
vrele(fvp);
@@ -1936,13 +2247,12 @@ rename(p, uap, retval)
error = -1;
out:
if (!error) {
- LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
- if (fromnd.ni_dvp != tdvp) {
- LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- }
+ VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
+ if (fromnd.ni_dvp != tdvp)
+ VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
if (tvp) {
- LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
- (void) vnode_pager_uncache(tvp);
+ VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
+ (void) vnode_pager_uncache(tvp, p);
}
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
@@ -1982,18 +2292,20 @@ struct mkdir_args {
int
mkdir(p, uap, retval)
struct proc *p;
- register struct mkdir_args *uap;
- int *retval;
+ register struct mkdir_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
nd.ni_cnd.cn_flags |= WILLBEDIR;
- error = namei(&nd);
- if (error)
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp != NULL) {
@@ -2007,8 +2319,8 @@ mkdir(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_type = VDIR;
- vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (!error)
vput(nd.ni_vp);
@@ -2027,16 +2339,18 @@ struct rmdir_args {
int
rmdir(p, uap, retval)
struct proc *p;
- struct rmdir_args *uap;
- int *retval;
+ struct rmdir_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
int error;
struct nameidata nd;
- NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type != VDIR) {
@@ -2057,8 +2371,8 @@ rmdir(p, uap, retval)
error = EBUSY;
out:
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -2086,8 +2400,13 @@ struct ogetdirentries_args {
int
ogetdirentries(p, uap, retval)
struct proc *p;
- register struct ogetdirentries_args *uap;
- int *retval;
+ register struct ogetdirentries_args /* {
+ syscallarg(int) fd;
+ syscallarg(char *) buf;
+ syscallarg(u_int) count;
+ syscallarg(long *) basep;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
@@ -2095,30 +2414,31 @@ ogetdirentries(p, uap, retval)
struct iovec aiov, kiov;
struct dirent *dp, *edp;
caddr_t dirbuf;
- int error, readcnt;
+ int error, eofflag, readcnt;
long loff;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
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;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
- VOP_LOCK(vp);
+ auio.uio_resid = SCARG(uap, count);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
loff = auio.uio_offset = fp->f_offset;
# if (BYTE_ORDER != LITTLE_ENDIAN)
if (vp->v_mount->mnt_maxsymlinklen <= 0) {
- error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
+ NULL, NULL);
fp->f_offset = auio.uio_offset;
} else
# endif
@@ -2126,13 +2446,14 @@ ogetdirentries(p, uap, retval)
kuio = auio;
kuio.uio_iov = &kiov;
kuio.uio_segflg = UIO_SYSSPACE;
- kiov.iov_len = uap->count;
- MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
+ kiov.iov_len = SCARG(uap, count);
+ MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
kiov.iov_base = dirbuf;
- error = VOP_READDIR(vp, &kuio, fp->f_cred, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
+ NULL, NULL);
fp->f_offset = kuio.uio_offset;
if (error == 0) {
- readcnt = uap->count - kuio.uio_resid;
+ readcnt = SCARG(uap, count) - kuio.uio_resid;
edp = (struct dirent *)&dirbuf[readcnt];
for (dp = (struct dirent *)dirbuf; dp < edp; ) {
# if (BYTE_ORDER == LITTLE_ENDIAN)
@@ -2165,14 +2486,70 @@ ogetdirentries(p, uap, retval)
}
FREE(dirbuf, M_TEMP);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
- error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
- *retval = uap->count - auio.uio_resid;
+
+#ifdef UNION
+{
+ extern int (**union_vnodeop_p)();
+ extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
+
+ if ((SCARG(uap, count) == auio.uio_resid) &&
+ (vp->v_op == union_vnodeop_p)) {
+ struct vnode *lvp;
+
+ lvp = union_dircache(vp, p);
+ if (lvp != NULLVP) {
+ struct vattr va;
+
+ /*
+ * If the directory is opaque,
+ * then don't show lower entries
+ */
+ error = VOP_GETATTR(vp, &va, fp->f_cred, p);
+ if (va.va_flags & OPAQUE) {
+ vput(lvp);
+ lvp = NULL;
+ }
+ }
+
+ if (lvp != NULLVP) {
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
+ if (error) {
+ vput(lvp);
+ return (error);
+ }
+ VOP_UNLOCK(lvp, 0, p);
+ fp->f_data = (caddr_t) lvp;
+ fp->f_offset = 0;
+ error = vn_close(vp, FREAD, fp->f_cred, p);
+ if (error)
+ return (error);
+ vp = lvp;
+ goto unionread;
+ }
+ }
+}
+#endif /* UNION */
+
+ if ((SCARG(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)SCARG(uap, basep),
+ sizeof(long));
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
-#endif
+#endif /* COMPAT_43 */
/*
* Read a block of directory entries in a file system independent format.
@@ -2188,18 +2565,22 @@ struct getdirentries_args {
int
getdirentries(p, uap, retval)
struct proc *p;
- register struct getdirentries_args *uap;
- int *retval;
+ register struct getdirentries_args /* {
+ syscallarg(int) fd;
+ syscallarg(char *) buf;
+ syscallarg(u_int) count;
+ syscallarg(long *) basep;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
struct uio auio;
struct iovec aiov;
long loff;
- int error;
+ int error, eofflag;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
if ((fp->f_flag & FREAD) == 0)
return (EBADF);
@@ -2207,51 +2588,66 @@ getdirentries(p, uap, retval)
unionread:
if (vp->v_type != VDIR)
return (EINVAL);
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
- VOP_LOCK(vp);
+ auio.uio_resid = SCARG(uap, count);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
loff = auio.uio_offset = fp->f_offset;
- error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
fp->f_offset = auio.uio_offset;
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
#ifdef UNION
{
- if ((uap->count == auio.uio_resid) &&
+ extern int (**union_vnodeop_p)();
+ extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
+
+ if ((SCARG(uap, count) == auio.uio_resid) &&
(vp->v_op == union_vnodeop_p)) {
- struct vnode *tvp = vp;
+ struct vnode *lvp;
+
+ lvp = union_dircache(vp, p);
+ if (lvp != NULLVP) {
+ struct vattr va;
- vp = union_lowervp(vp);
- if (vp != NULLVP) {
- VOP_LOCK(vp);
- error = VOP_OPEN(vp, FREAD, fp->f_cred, p);
- VOP_UNLOCK(vp);
+ /*
+ * If the directory is opaque,
+ * then don't show lower entries
+ */
+ error = VOP_GETATTR(vp, &va, fp->f_cred, p);
+ if (va.va_flags & OPAQUE) {
+ vput(lvp);
+ lvp = NULL;
+ }
+ }
+ if (lvp != NULLVP) {
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
if (error) {
- vrele(vp);
+ vput(lvp);
return (error);
}
- fp->f_data = (caddr_t) vp;
+ VOP_UNLOCK(lvp, 0, p);
+ fp->f_data = (caddr_t) lvp;
fp->f_offset = 0;
- error = vn_close(tvp, FREAD, fp->f_cred, p);
+ error = vn_close(vp, FREAD, fp->f_cred, p);
if (error)
return (error);
+ vp = lvp;
goto unionread;
}
}
}
-#endif
+#endif /* UNION */
- if ((uap->count == auio.uio_resid) &&
- vp &&
+ if ((SCARG(uap, count) == auio.uio_resid) &&
(vp->v_flag & VROOT) &&
(vp->v_mount->mnt_flag & MNT_UNION)) {
struct vnode *tvp = vp;
@@ -2262,8 +2658,9 @@ unionread:
vrele(tvp);
goto unionread;
}
- error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
- *retval = uap->count - auio.uio_resid;
+ error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
+ sizeof(long));
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
@@ -2275,17 +2672,19 @@ struct umask_args {
int newmask;
};
#endif
-mode_t /* XXX */
+int
umask(p, uap, retval)
struct proc *p;
- struct umask_args *uap;
- int *retval;
+ struct umask_args /* {
+ syscallarg(int) newmask;
+ } */ *uap;
+ int *retval; /* XXX */
{
register struct filedesc *fdp;
fdp = p->p_fd;
*retval = fdp->fd_cmask;
- fdp->fd_cmask = uap->newmask & ALLPERMS;
+ fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
return (0);
}
@@ -2302,31 +2701,27 @@ struct revoke_args {
int
revoke(p, uap, retval)
struct proc *p;
- register struct revoke_args *uap;
- int *retval;
+ register struct revoke_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- if (vp->v_type != VCHR && vp->v_type != VBLK) {
- error = EINVAL;
- goto out;
- }
- error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
- if (error)
+ if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
goto out;
if (p->p_ucred->cr_uid != vattr.va_uid &&
(error = suser(p->p_ucred, &p->p_acflag)))
goto out;
if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
- vgoneall(vp);
+ VOP_REVOKE(vp, REVOKEALL);
out:
vrele(vp);
return (error);
OpenPOWER on IntegriCloud