Fix vop_link, vop_symlink, and vop_remove semantics in several ways:

* Change the argument names to vop_link so they actually make sense.
* Implement vop_link and vop_symlink for all file systems, so they do proper
  cleanup.
* Require the file system to decide whether or not linking and unlinking of
  directories is allowed, and disable it for all current file systems.
This commit is contained in:
mycroft 1996-02-09 14:45:36 +00:00
parent d6b5a89f90
commit 53fccab940
13 changed files with 349 additions and 134 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: advnops.c,v 1.23 1996/02/01 00:13:47 jtc Exp $ */
/* $NetBSD: advnops.c,v 1.24 1996/02/09 14:45:40 mycroft Exp $ */
/*
* Copyright (c) 1994 Christian E. Hopps
@ -326,6 +326,49 @@ reterr:
return(error);
}
int
adosfs_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
adosfs_symlink(ap)
struct vop_symlink_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
char *a_target;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
adosfs_abortop(ap)
struct vop_abortop_args /* {
struct vnode *a_dvp;
struct componentname *a_cnp;
} */ *ap;
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
return (0);
}
/*
* lock the anode
*/
@ -895,12 +938,10 @@ int lease_check __P((struct vop_lease_args *));
#define adosfs_seek ((int (*) __P((struct vop_seek_args *)))adnullop)
#define adosfs_vfree ((int (*) __P((struct vop_vfree_args *)))adnullop)
#define adosfs_abortop ((int (*) __P((struct vop_abortop_args *)))adenotsup)
#define adosfs_advlock ((int (*) __P((struct vop_advlock_args *)))adenotsup)
#define adosfs_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))adenotsup)
#define adosfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))adenotsup)
#define adosfs_create ((int (*) __P((struct vop_create_args *)))adenotsup)
#define adosfs_link ((int (*) __P((struct vop_link_args *)))adenotsup)
#define adosfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))adenotsup)
#define adosfs_mknod ((int (*) __P((struct vop_mknod_args *)))adenotsup)
#define adosfs_mmap ((int (*) __P((struct vop_mmap_args *)))adenotsup)
@ -908,7 +949,6 @@ int lease_check __P((struct vop_lease_args *));
#define adosfs_rename ((int (*) __P((struct vop_rename_args *)))adenotsup)
#define adosfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))adenotsup)
#define adosfs_setattr ((int (*) __P((struct vop_setattr_args *)))adenotsup)
#define adosfs_symlink ((int (*) __P((struct vop_symlink_args *)))adenotsup)
#define adosfs_truncate ((int (*) __P((struct vop_truncate_args *)))adenotsup)
#define adosfs_update ((int (*) __P((struct vop_update_args *)))adenotsup)
#define adosfs_valloc ((int (*) __P((struct vop_valloc_args *)))adenotsup)

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660_vnops.c,v 1.26 1995/12/01 00:47:33 pk Exp $ */
/* $NetBSD: cd9660_vnops.c,v 1.27 1996/02/09 14:45:43 mycroft Exp $ */
/*-
* Copyright (c) 1994
@ -743,6 +743,36 @@ cd9660_readlink(ap)
return (0);
}
int
cd9660_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
cd9660_symlink(ap)
struct vop_symlink_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
char *a_target;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
/*
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
* done. If a buffer has been saved in anticipation of a CREATE, delete it.
@ -754,6 +784,7 @@ cd9660_abortop(ap)
struct componentname *a_cnp;
} */ *ap;
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
return (0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_syscalls.c,v 1.65 1996/02/08 02:54:20 mycroft Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.66 1996/02/09 14:45:36 mycroft Exp $ */
/*
* Copyright (c) 1989, 1993
@ -947,30 +947,23 @@ sys_link(p, v, retval)
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
if (vp->v_type != VDIR ||
(error = suser(p->p_ucred, &p->p_acflag)) == 0) {
nd.ni_cnd.cn_nameiop = CREATE;
nd.ni_cnd.cn_flags = LOCKPARENT;
nd.ni_dirp = SCARG(uap, link);
if ((error = namei(&nd)) == 0) {
if (nd.ni_vp != NULL)
error = EEXIST;
if (!error) {
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);
} else {
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);
}
}
NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
if ((error = namei(&nd)) != 0)
goto out;
if (nd.ni_vp) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
vrele(nd.ni_vp);
error = EEXIST;
goto out;
}
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);
out:
vrele(vp);
return (error);
}
@ -1084,29 +1077,24 @@ sys_unlink(p, v, retval)
VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
VOP_LOCK(vp);
if (vp->v_type != VDIR ||
(error = suser(p->p_ucred, &p->p_acflag)) == 0) {
/*
* The root of a mounted filesystem cannot be deleted.
*/
if (vp->v_flag & VROOT)
error = EBUSY;
else
(void)vnode_pager_uncache(vp);
}
if (!error) {
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
} else {
/*
* The root of a mounted filesystem cannot be deleted.
*/
if (vp->v_flag & VROOT) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
if (vp != NULLVP)
vput(vp);
vput(vp);
error = EBUSY;
goto out;
}
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
(void)vnode_pager_uncache(vp);
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
out:
return (error);
}

View File

@ -1,4 +1,4 @@
# $NetBSD: vnode_if.src,v 1.8 1994/12/14 18:58:43 mycroft Exp $
# $NetBSD: vnode_if.src,v 1.9 1996/02/09 14:45:38 mycroft Exp $
#
# Copyright (c) 1992, 1993
# The Regents of the University of California. All rights reserved.
@ -149,8 +149,8 @@ vop_remove {
};
vop_link {
IN WILLRELE struct vnode *vp;
IN struct vnode *tdvp;
IN WILLRELE struct vnode *dvp;
IN struct vnode *vp;
IN struct componentname *cnp;
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: fdesc_vnops.c,v 1.28 1996/02/01 00:31:05 jtc Exp $ */
/* $NetBSD: fdesc_vnops.c,v 1.29 1996/02/09 14:45:46 mycroft Exp $ */
/*
* Copyright (c) 1992, 1993
@ -845,6 +845,49 @@ fdesc_vfree(ap)
return (0);
}
int
fdesc_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
fdesc_symlink(ap)
struct vop_symlink_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
char *a_target;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
fdesc_abortop(ap)
struct vop_abortop_args /* {
struct vnode *a_dvp;
struct componentname *a_cnp;
} */ *ap;
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
return (0);
}
/*
* /dev/fd vnode unsupported operation
*/
@ -884,12 +927,9 @@ fdesc_nullop()
#define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp)
#define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp)
#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp)
#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp)
#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp)
#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp)
#define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop)
#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
#define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)

View File

@ -1,4 +1,4 @@
/* $NetBSD: kernfs_vnops.c,v 1.39 1995/10/09 14:25:02 mycroft Exp $ */
/* $NetBSD: kernfs_vnops.c,v 1.40 1996/02/09 14:45:48 mycroft Exp $ */
/*
* Copyright (c) 1992, 1993
@ -635,6 +635,49 @@ kernfs_vfree(ap)
return (0);
}
int
kernfs_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
kernfs_symlink(ap)
struct vop_symlink_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
char *a_target;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
kernfs_abortop(ap)
struct vop_abortop_args /* {
struct vnode *a_dvp;
struct componentname *a_cnp;
} */ *ap;
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
return (0);
}
/*
* /dev/fd vnode unsupported operation
*/
@ -672,14 +715,11 @@ kernfs_nullop()
#define kernfs_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define kernfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
#define kernfs_remove ((int (*) __P((struct vop_remove_args *)))kernfs_enotsupp)
#define kernfs_link ((int (*) __P((struct vop_link_args *)))kernfs_enotsupp)
#define kernfs_rename ((int (*) __P((struct vop_rename_args *)))kernfs_enotsupp)
#define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))kernfs_enotsupp)
#define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))kernfs_enotsupp)
#define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp)
#define kernfs_readlink \
((int (*) __P((struct vop_readlink_args *)))kernfs_enotsupp)
#define kernfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
#define kernfs_lock ((int (*) __P((struct vop_lock_args *)))nullop)
#define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
#define kernfs_bmap ((int (*) __P((struct vop_bmap_args *)))kernfs_badop)

View File

@ -1,4 +1,4 @@
/* $NetBSD: portal_vnops.c,v 1.14 1995/10/07 06:28:55 mycroft Exp $ */
/* $NetBSD: portal_vnops.c,v 1.15 1996/02/09 14:45:50 mycroft Exp $ */
/*
* Copyright (c) 1992, 1993
@ -596,6 +596,48 @@ portal_vfree(ap)
return (0);
}
int
portal_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
portal_symlink(ap)
struct vop_symlink_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
char *a_target;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
portal_abortop(ap)
struct vop_abortop_args /* {
struct vnode *a_dvp;
struct componentname *a_cnp;
} */ *ap;
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
return (0);
}
/*
* Portal vnode unsupported operation
@ -640,15 +682,11 @@ portal_nullop()
#define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop)
#define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp)
#define portal_link ((int (*) __P((struct vop_link_args *)))portal_enotsupp)
#define portal_rename ((int (*) __P((struct vop_rename_args *)))portal_enotsupp)
#define portal_mkdir ((int (*) __P((struct vop_mkdir_args *)))portal_enotsupp)
#define portal_rmdir ((int (*) __P((struct vop_rmdir_args *)))portal_enotsupp)
#define portal_symlink \
((int (*) __P((struct vop_symlink_args *)))portal_enotsupp)
#define portal_readlink \
((int (*) __P((struct vop_readlink_args *)))portal_enotsupp)
#define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
#define portal_lock ((int (*) __P((struct vop_lock_args *)))nullop)
#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
#define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop)

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_vnops.c,v 1.35 1995/10/09 14:03:38 mycroft Exp $ */
/* $NetBSD: procfs_vnops.c,v 1.36 1996/02/09 14:45:53 mycroft Exp $ */
/*
* Copyright (c) 1993 Jan-Simon Pendry
@ -304,6 +304,36 @@ procfs_print(ap)
pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
}
int
procfs_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
int
procfs_symlink(ap)
struct vop_symlink_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
char *a_target;
} */ *ap;
{
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EROFS);
}
/*
* _abortop is called when operations such as
* rename and create fail. this entry is responsible

View File

@ -1,4 +1,4 @@
/* $NetBSD: union_vnops.c,v 1.25 1995/07/13 13:19:18 mycroft Exp $ */
/* $NetBSD: union_vnops.c,v 1.26 1996/02/09 14:45:56 mycroft Exp $ */
/*
* Copyright (c) 1992, 1993, 1994 The Regents of the University of California.
@ -944,54 +944,55 @@ union_remove(ap)
int
union_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct vnode *a_tdvp;
struct componentname *a_cnp;
} */ *ap;
{
int error = 0;
struct union_node *un;
struct union_node *dun;
struct vnode *dvp;
struct vnode *vp;
struct vnode *tdvp;
un = VTOUNION(ap->a_vp);
dun = VTOUNION(ap->a_dvp);
if (ap->a_vp->v_op != ap->a_tdvp->v_op) {
tdvp = ap->a_tdvp;
if (ap->a_dvp->v_op != ap->a_vp->v_op) {
vp = ap->a_vp;
} else {
struct union_node *tdun = VTOUNION(ap->a_tdvp);
if (tdun->un_uppervp == NULLVP) {
VOP_LOCK(ap->a_tdvp);
if (un->un_uppervp == tdun->un_dirvp) {
un->un_flags &= ~UN_ULOCK;
VOP_UNLOCK(un->un_uppervp);
struct union_node *un = VTOUNION(ap->a_vp);
if (un->un_uppervp == NULLVP) {
VOP_LOCK(ap->a_vp);
if (dun->un_uppervp == un->un_dirvp) {
dun->un_flags &= ~UN_ULOCK;
VOP_UNLOCK(dun->un_uppervp);
}
error = union_copyup(tdun, 1, ap->a_cnp->cn_cred,
error = union_copyup(un, 1, ap->a_cnp->cn_cred,
ap->a_cnp->cn_proc);
if (un->un_uppervp == tdun->un_dirvp) {
VOP_LOCK(un->un_uppervp);
un->un_flags |= UN_ULOCK;
if (dun->un_uppervp == un->un_dirvp) {
VOP_LOCK(dun->un_uppervp);
dun->un_flags |= UN_ULOCK;
}
VOP_UNLOCK(ap->a_tdvp);
VOP_UNLOCK(ap->a_vp);
}
tdvp = tdun->un_uppervp;
vp = un->un_uppervp;
}
vp = un->un_uppervp;
if (vp == NULLVP)
dvp = dun->un_uppervp;
if (dvp == NULLVP)
error = EROFS;
if (error) {
vput(ap->a_vp);
vput(ap->a_dvp);
return (error);
}
FIXUP(un);
VREF(vp);
un->un_flags |= UN_KLOCK;
vput(ap->a_vp);
FIXUP(dun);
VREF(dvp);
dun->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
return (VOP_LINK(vp, tdvp, ap->a_cnp));
return (VOP_LINK(dvp, vp, ap->a_cnp));
}
int

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_vnops.c,v 1.44 1996/02/01 00:37:36 jtc Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.45 1996/02/09 14:45:59 mycroft Exp $ */
/*-
* Copyright (C) 1994, 1995 Wolfgang Solfrank.
@ -772,14 +772,14 @@ msdosfs_remove(ap)
int
msdosfs_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct vnode *a_tdvp;
struct componentname *a_cnp;
} */ *ap;
{
VOP_ABORTOP(ap->a_vp, ap->a_cnp);
vput(ap->a_vp);
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EOPNOTSUPP);
}
@ -1334,12 +1334,10 @@ msdosfs_symlink(ap)
char *a_target;
} */ *ap;
{
register struct vnode *dvp = ap->a_dvp;
register struct componentname *cnp = ap->a_cnp;
FREE(cnp->cn_pnbuf, M_NAMEI);
vput(dvp);
return (EINVAL);
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
vput(ap->a_dvp);
return (EOPNOTSUPP);
}
int

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_vnops.c,v 1.56 1996/02/01 00:41:19 jtc Exp $ */
/* $NetBSD: nfs_vnops.c,v 1.57 1996/02/09 14:46:03 mycroft Exp $ */
/*
* Copyright (c) 1989, 1993
@ -1301,13 +1301,13 @@ nfs_renameit(sdvp, scnp, sp)
int
nfs_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct vnode *a_tdvp;
struct componentname *a_cnp;
} */ *ap;
{
register struct vnode *dvp = ap->a_dvp;
register struct vnode *vp = ap->a_vp;
register struct vnode *tdvp = ap->a_tdvp;
register struct componentname *cnp = ap->a_cnp;
register u_int32_t *tl;
register caddr_t cp;
@ -1316,12 +1316,12 @@ nfs_link(ap)
int error = 0;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
if (vp->v_mount != tdvp->v_mount) {
/*VOP_ABORTOP(vp, cnp);*/
if (tdvp == vp)
vrele(vp);
if (dvp->v_mount != vp->v_mount) {
/*VOP_ABORTOP(dvp, cnp);*/
if (vp == dvp)
vrele(dvp);
else
vput(vp);
vput(dvp);
return (EXDEV);
}
@ -1330,21 +1330,21 @@ nfs_link(ap)
* doesn't get "out of sync" with the server.
* XXX There should be a better way!
*/
VOP_FSYNC(tdvp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
nfsstats.rpccnt[NFSPROC_LINK]++;
nfsm_reqhead(tdvp, NFSPROC_LINK,
nfsm_reqhead(vp, NFSPROC_LINK,
NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen));
nfsm_fhtom(tdvp);
nfsm_fhtom(vp);
nfsm_fhtom(dvp);
nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
nfsm_request(tdvp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
nfsm_reqdone;
FREE(cnp->cn_pnbuf, M_NAMEI);
VTONFS(tdvp)->n_attrstamp = 0;
VTONFS(vp)->n_flag |= NMODIFIED;
VTONFS(vp)->n_attrstamp = 0;
vrele(vp);
VTONFS(dvp)->n_flag |= NMODIFIED;
VTONFS(dvp)->n_attrstamp = 0;
vrele(dvp);
/*
* Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_vnops.c,v 1.8 1996/02/01 00:07:51 jtc Exp $ */
/* $NetBSD: lfs_vnops.c,v 1.9 1996/02/09 14:46:06 mycroft Exp $ */
/*
* Copyright (c) 1986, 1989, 1991, 1993
@ -370,17 +370,17 @@ lfs_rmdir(ap)
int
lfs_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct vnode *a_tdvp;
struct componentname *a_cnp;
} */ *ap;
{
int ret;
SET_DIROP(VTOI(ap->a_vp)->i_lfs);
MARK_VNODE(ap->a_vp);
SET_DIROP(VTOI(ap->a_dvp)->i_lfs);
MARK_VNODE(ap->a_dvp);
ret = ufs_link(ap);
SET_ENDOP(VTOI(ap->a_vp)->i_lfs);
SET_ENDOP(VTOI(ap->a_dvp)->i_lfs);
return (ret);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_vnops.c,v 1.13 1996/02/07 17:01:25 jtc Exp $ */
/* $NetBSD: ufs_vnops.c,v 1.14 1996/02/09 14:46:08 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -594,6 +594,10 @@ ufs_remove(ap)
register struct vnode *dvp = ap->a_dvp;
int error;
if (vp->v_type == VDIR) {
error = EISDIR;
goto out;
}
ip = VTOI(vp);
if ((ip->i_flags & (IMMUTABLE | APPEND)) ||
(VTOI(dvp)->i_flags & APPEND)) {
@ -619,13 +623,13 @@ out:
int
ufs_link(ap)
struct vop_link_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct vnode *a_tdvp;
struct componentname *a_cnp;
} */ *ap;
{
register struct vnode *dvp = ap->a_dvp;
register struct vnode *vp = ap->a_vp;
register struct vnode *tdvp = ap->a_tdvp;
register struct componentname *cnp = ap->a_cnp;
register struct inode *ip;
struct timeval tv;
@ -635,42 +639,47 @@ ufs_link(ap)
if ((cnp->cn_flags & HASBUF) == 0)
panic("ufs_link: no name");
#endif
if (vp->v_mount != tdvp->v_mount) {
VOP_ABORTOP(vp, cnp);
if (vp->v_type == VDIR) {
VOP_ABORTOP(dvp, cnp);
error = EISDIR;
goto out2;
}
if (dvp->v_mount != vp->v_mount) {
VOP_ABORTOP(dvp, cnp);
error = EXDEV;
goto out2;
}
if (vp != tdvp && (error = VOP_LOCK(tdvp))) {
VOP_ABORTOP(vp, cnp);
if (dvp != vp && (error = VOP_LOCK(vp))) {
VOP_ABORTOP(dvp, cnp);
goto out2;
}
ip = VTOI(tdvp);
ip = VTOI(vp);
if ((nlink_t)ip->i_nlink >= LINK_MAX) {
VOP_ABORTOP(vp, cnp);
VOP_ABORTOP(dvp, cnp);
error = EMLINK;
goto out1;
}
if (ip->i_flags & (IMMUTABLE | APPEND)) {
VOP_ABORTOP(vp, cnp);
VOP_ABORTOP(dvp, cnp);
error = EPERM;
goto out1;
}
ip->i_nlink++;
ip->i_flag |= IN_CHANGE;
tv = time;
error = VOP_UPDATE(tdvp, &tv, &tv, 1);
error = VOP_UPDATE(vp, &tv, &tv, 1);
if (!error)
error = ufs_direnter(ip, vp, cnp);
error = ufs_direnter(ip, dvp, cnp);
if (error) {
ip->i_nlink--;
ip->i_flag |= IN_CHANGE;
}
FREE(cnp->cn_pnbuf, M_NAMEI);
out1:
if (vp != tdvp)
VOP_UNLOCK(tdvp);
if (dvp != vp)
VOP_UNLOCK(vp);
out2:
vput(vp);
vput(dvp);
return (error);
}