Check for the cross-device cross-link attempt in the VFS, instead of

forcing filesystem VOP_LINK() methods to repeat the code.  In
tmpfs_link(), remove redundand check for the type of the source,
already done by VFS.

Note that NFS server already performs this check before calling
VOP_LINK().

Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2014-07-16 14:04:46 +00:00
parent f62bbc4d90
commit 65589a29f4
7 changed files with 9 additions and 41 deletions

View File

@ -666,10 +666,6 @@ ext2_link(struct vop_link_args *ap)
if ((cnp->cn_flags & HASBUF) == 0)
panic("ext2_link: no name");
#endif
if (tdvp->v_mount != vp->v_mount) {
error = EXDEV;
goto out;
}
ip = VTOI(vp);
if ((nlink_t)ip->i_nlink >= EXT2_LINK_MAX) {
error = EMLINK;

View File

@ -1355,9 +1355,6 @@ nandfs_link(struct vop_link_args *ap)
struct nandfs_inode *inode = &node->nn_inode;
int error;
if (tdvp->v_mount != vp->v_mount)
return (EXDEV);
if (inode->i_links_count >= LINK_MAX)
return (EMLINK);

View File

@ -1976,10 +1976,6 @@ nfs_link(struct vop_link_args *ap)
struct nfsvattr nfsva, dnfsva;
int error = 0, attrflag, dattrflag;
if (vp->v_mount != tdvp->v_mount) {
return (EXDEV);
}
/*
* Push all writes to the server, so that the attribute cache
* doesn't get "out of sync" with the server.

View File

@ -858,15 +858,6 @@ null_vptocnp(struct vop_vptocnp_args *ap)
return (error);
}
static int
null_link(struct vop_link_args *ap)
{
if (ap->a_tdvp->v_mount != ap->a_vp->v_mount)
return (EXDEV);
return (null_bypass((struct vop_generic_args *)ap));
}
/*
* Global vfs data structures
*/
@ -880,7 +871,6 @@ struct vop_vector null_vnodeops = {
.vop_getwritemount = null_getwritemount,
.vop_inactive = null_inactive,
.vop_islocked = vop_stdislocked,
.vop_link = null_link,
.vop_lock1 = null_lock,
.vop_lookup = null_lookup,
.vop_open = null_open,

View File

@ -571,21 +571,6 @@ tmpfs_link(struct vop_link_args *v)
MPASS(VOP_ISLOCKED(dvp));
MPASS(cnp->cn_flags & HASBUF);
MPASS(dvp != vp); /* XXX When can this be false? */
/* XXX: Why aren't the following two tests done by the caller? */
/* Hard links of directories are forbidden. */
if (vp->v_type == VDIR) {
error = EPERM;
goto out;
}
/* Cannot create cross-device links. */
if (dvp->v_mount != vp->v_mount) {
error = EXDEV;
goto out;
}
node = VP_TO_TMPFS_NODE(vp);
/* Ensure that we do not overflow the maximum number of links imposed

View File

@ -1578,7 +1578,15 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
vrele(nd.ni_vp);
error = EEXIST;
} else if ((error = vn_lock(vp, LK_EXCLUSIVE)) == 0) {
error = can_hardlink(vp, td->td_ucred);
/*
* Check for cross-device links. No need to
* recheck vp->v_type, since it cannot change
* for non-doomed vnode.
*/
if (nd.ni_dvp->v_mount != vp->v_mount)
error = EXDEV;
else
error = can_hardlink(vp, td->td_ucred);
if (error == 0)
#ifdef MAC
error = mac_vnode_check_link(td->td_ucred,

View File

@ -968,10 +968,6 @@ ufs_link(ap)
if ((cnp->cn_flags & HASBUF) == 0)
panic("ufs_link: no name");
#endif
if (tdvp->v_mount != vp->v_mount) {
error = EXDEV;
goto out;
}
if (VTOI(tdvp)->i_effnlink < 2)
panic("ufs_link: Bad link count %d on parent",
VTOI(tdvp)->i_effnlink);