mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 19:34:43 +01:00
UFS: make mkdir() and link() reliable when using SU and reaching nlink limit
i_nlink overflow might be transient, i_effnlink indicates the final value of the link count after all dependencies would be resolved. So if i_nlink reached the maximum but i_efflink did not, we should be able to make the link by syncing. We must sync the whole filesystem to resolve dependencies, which requires unlocking vnodes locked for VOPs. Use existing ERELOOKUP/VOP_UNLOCK_PAIR() mechanism to restart the VOP if sync with unlock was done. PR: 165392 Reported by: Vsevolod Volkov <[email protected]> Reviewed by: mckusick Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D35514
This commit is contained in:
1 parent
ef1976ccf5
commit
8db679af66
1 file changed
+35
-7
+35
-7
@@ -196,6 +196,35 @@ ufs_itimes(struct vnode *vp)
|
||||
VI_UNLOCK(vp);
|
||||
}
|
||||
|
||||
static int
|
||||
ufs_sync_nlink(struct vnode *vp, struct vnode *vp1)
|
||||
{
|
||||
struct inode *ip;
|
||||
struct mount *mp;
|
||||
int error;
|
||||
|
||||
ip = VTOI(vp);
|
||||
if (ip->i_nlink < UFS_LINK_MAX)
|
||||
return (0);
|
||||
if (!DOINGSOFTDEP(vp) || ip->i_effnlink >= UFS_LINK_MAX)
|
||||
return (EMLINK);
|
||||
|
||||
mp = vp->v_mount;
|
||||
vfs_ref(mp);
|
||||
VOP_UNLOCK(vp);
|
||||
if (vp1 != NULL)
|
||||
VOP_UNLOCK(vp1);
|
||||
error = vfs_busy(mp, 0);
|
||||
if (error == 0) {
|
||||
VFS_SYNC(mp, MNT_WAIT);
|
||||
vfs_unbusy(mp);
|
||||
error = ERELOOKUP;
|
||||
}
|
||||
vfs_rel(mp);
|
||||
vn_lock_pair(vp, false, vp1, false);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a regular file
|
||||
*/
|
||||
@@ -1086,11 +1115,11 @@ ufs_link(ap)
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ip = VTOI(vp);
|
||||
if (ip->i_nlink >= UFS_LINK_MAX) {
|
||||
error = EMLINK;
|
||||
error = ufs_sync_nlink(vp, tdvp);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
}
|
||||
ip = VTOI(vp);
|
||||
|
||||
/*
|
||||
* The file may have been removed after namei dropped the original
|
||||
* lock.
|
||||
@@ -1950,10 +1979,9 @@ ufs_mkdir(ap)
|
||||
panic("ufs_mkdir: no name");
|
||||
#endif
|
||||
dp = VTOI(dvp);
|
||||
if (dp->i_nlink >= UFS_LINK_MAX) {
|
||||
error = EMLINK;
|
||||
error = ufs_sync_nlink(dvp, NULL);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
}
|
||||
dmode = vap->va_mode & 0777;
|
||||
dmode |= IFDIR;
|
||||
|
||||
|
||||
Reference in new issue
Block a user