Index: sys/ufs/ufs/ufs_vnops.c =================================================================== --- sys/ufs/ufs/ufs_vnops.c (revision 250823) +++ sys/ufs/ufs/ufs_vnops.c (working copy) @@ -1812,10 +1812,13 @@ ufs_mkdir(ap) panic("ufs_mkdir: no name"); #endif dp = VTOI(dvp); - if ((nlink_t)dp->i_nlink >= LINK_MAX) { + error = 0; + if (DOINGSOFTDEP(dvp)) + error = softdep_check_linkcnt(dp); + else if ((nlink_t)dp->i_nlink >= LINK_MAX) error = EMLINK; + if (error != 0) goto out; - } dmode = vap->va_mode & 0777; dmode |= IFDIR; /* Index: sys/ufs/ffs/ffs_softdep.c =================================================================== --- sys/ufs/ffs/ffs_softdep.c (revision 250823) +++ sys/ufs/ffs/ffs_softdep.c (working copy) @@ -453,6 +453,14 @@ softdep_change_linkcnt(ip) panic("softdep_change_linkcnt called"); } +int +softdep_check_linkcnt(ip) + struct inode *ip; +{ + + panic("softdep_check_linkcnt called"); +} + void softdep_load_inodeblock(ip) struct inode *ip; @@ -1290,6 +1298,7 @@ static int stat_cleanup_blkrequests; /* static int stat_cleanup_inorequests; /* Number of inode cleanup requests */ static int stat_cleanup_retries; /* Number of cleanups that needed to flush */ static int stat_cleanup_failures; /* Number of cleanup requests that failed */ +static int stat_linkretry; SYSCTL_INT(_debug_softdep, OID_AUTO, max_softdeps, CTLFLAG_RW, &max_softdeps, 0, ""); @@ -1347,6 +1356,8 @@ SYSCTL_INT(_debug_softdep, OID_AUTO, cle &stat_cleanup_failures, 0, ""); SYSCTL_INT(_debug_softdep, OID_AUTO, flushcache, CTLFLAG_RW, &softdep_flushcache, 0, ""); +SYSCTL_INT(_debug_softdep, OID_AUTO, linkretry, CTLFLAG_RW, + &stat_linkretry, 0, ""); SYSCTL_DECL(_vfs_ffs); @@ -9153,6 +9164,28 @@ softdep_change_linkcnt(ip) FREE_LOCK(&lk); } +int +softdep_check_linkcnt(ip) + struct inode *ip; +{ + struct vnode *vp; + int error; + + vp = ITOV(ip); + ASSERT_VOP_LOCKED(vp, "softdep_check_linkcnt"); + + if (ip->i_nlink < LINK_MAX) + return (0); + if (ip->i_effnlink >= LINK_MAX) + return (EMLINK); + + stat_linkretry++; + error = VOP_FSYNC(vp, MNT_WAIT, curthread); + if (error != 0) + return (error); + return (ip->i_nlink < LINK_MAX ? 0 : EMLINK); +} + /* * Attach a sbdep dependency to the superblock buf so that we can keep * track of the head of the linked list of referenced but unlinked inodes.