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:
parent
f62bbc4d90
commit
65589a29f4
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user