Right before msdosfs_link() in msdosfs_vnops.c is a comment about unlocking the parent and aborting the operation. Currently all that happens is a VOP_ABORTOP returning 0. Fixed in the diff below by adding lines for unlocking and returning an EPERM value. Looking at UFS, it seems that a vput() is needed to release the vnode.