git: 65d8e97c4c23 - stable/13 - UFS: make mkdir() and link() reliable when using SU and reaching nlink limit
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 29 Jun 2022 09:39:29 UTC
The branch stable/13 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=65d8e97c4c23a0b27d9e0bc73e4150ebbb00b844
commit 65d8e97c4c23a0b27d9e0bc73e4150ebbb00b844
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-06-18 10:59:31 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-06-29 09:38:26 +0000
UFS: make mkdir() and link() reliable when using SU and reaching nlink limit
PR: 165392
(cherry picked from commit 8db679af66b023802139d41e275e41a77da1c515)
---
sys/ufs/ufs/ufs_vnops.c | 42 +++++++++++++++++++++++++++++++++++-------
1 file changed, 35 insertions(+), 7 deletions(-)
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index b4d23545fb0b..4353c51afcbe 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -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;