The branch stable/14 has been updated by mckusick:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=636bf719194ce27390b45b8f68e430993670d2dd

commit 636bf719194ce27390b45b8f68e430993670d2dd
Author:     Kirk McKusick <[email protected]>
AuthorDate: 2023-12-03 20:36:42 +0000
Commit:     Kirk McKusick <[email protected]>
CommitDate: 2023-12-17 03:45:51 +0000

    Increase UFS/FFS maximum link count from 32767 to 65530.
    
    Differential Revision: https://reviews.freebsd.org/D42767
    
    (cherry picked from commit 35a301555bff2ac27a727c10641b7efb3f162988)
---
 sys/ufs/ffs/ffs_alloc.c   |  2 +-
 sys/ufs/ffs/ffs_softdep.c |  4 ++--
 sys/ufs/ufs/dinode.h      |  6 +++---
 sys/ufs/ufs/inode.h       | 10 ++++++++--
 sys/ufs/ufs/ufs_lookup.c  |  8 ++++----
 sys/ufs/ufs/ufs_vnops.c   | 32 ++++++++++++++++----------------
 6 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 2bf5b6c58302..690df0c12793 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -3332,7 +3332,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
                        break;
                ip = VTOI(vp);
                ip->i_nlink += cmd.size;
-               DIP_SET(ip, i_nlink, ip->i_nlink);
+               DIP_SET_NLINK(ip, ip->i_nlink);
                ip->i_effnlink += cmd.size;
                UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_MODIFIED);
                error = ffs_update(vp, 1);
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 28ffb806b308..961cb4493621 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -10048,7 +10048,7 @@ handle_workitem_remove(struct dirrem *dirrem, int flags)
                KASSERT(ip->i_nlink >= 0, ("handle_workitem_remove: file ino "
                    "%ju negative i_nlink %d", (intmax_t)ip->i_number,
                    ip->i_nlink));
-               DIP_SET(ip, i_nlink, ip->i_nlink);
+               DIP_SET_NLINK(ip, ip->i_nlink);
                UFS_INODE_SET_FLAG(ip, IN_CHANGE);
                if (ip->i_nlink < ip->i_effnlink)
                        panic("handle_workitem_remove: bad file delta");
@@ -10071,7 +10071,7 @@ handle_workitem_remove(struct dirrem *dirrem, int flags)
        ip->i_nlink -= 2;
        KASSERT(ip->i_nlink >= 0, ("handle_workitem_remove: directory ino "
            "%ju negative i_nlink %d", (intmax_t)ip->i_number, ip->i_nlink));
-       DIP_SET(ip, i_nlink, ip->i_nlink);
+       DIP_SET_NLINK(ip, ip->i_nlink);
        UFS_INODE_SET_FLAG(ip, IN_CHANGE);
        if (ip->i_nlink < ip->i_effnlink)
                panic("handle_workitem_remove: bad dir delta");
diff --git a/sys/ufs/ufs/dinode.h b/sys/ufs/ufs/dinode.h
index b429562f1159..b4117a99c262 100644
--- a/sys/ufs/ufs/dinode.h
+++ b/sys/ufs/ufs/dinode.h
@@ -125,7 +125,7 @@ typedef int64_t ufs_time_t;
 
 struct ufs2_dinode {
        uint16_t        di_mode;        /*   0: IFMT, permissions; see below. */
-       int16_t         di_nlink;       /*   2: File link count. */
+       uint16_t        di_nlink;       /*   2: File link count. */
        uint32_t        di_uid;         /*   4: File owner. */
        uint32_t        di_gid;         /*   8: File group. */
        uint32_t        di_blksize;     /*  12: Inode blocksize. */
@@ -180,7 +180,7 @@ struct ufs2_dinode {
  */
 struct ufs1_dinode {
        uint16_t        di_mode;        /*   0: IFMT, permissions; see below. */
-       int16_t         di_nlink;       /*   2: File link count. */
+       uint16_t        di_nlink;       /*   2: File link count. */
        union {
                uint32_t di_freelink;   /*   4: SUJ: Next unlinked inode. */
                uint32_t di_dirdepth;   /*   4: IFDIR: depth from root dir */
@@ -210,6 +210,6 @@ struct ufs1_dinode {
        uint64_t        di_modrev;      /* 120: i_modrev for NFSv4 */
 };
 
-#define        UFS_LINK_MAX    32767
+#define        UFS_LINK_MAX    65500   /* leave a few spare for special values 
*/
 
 #endif /* _UFS_UFS_DINODE_H_ */
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 81500e10ebb1..dc7e2560d6e3 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -97,7 +97,7 @@ struct inode {
 
        ino_t     i_number;     /* The identity of the inode. */
        uint32_t  i_flag;       /* flags, see below */
-       int       i_effnlink;   /* i_nlink when I/O completes */
+       int32_t   i_effnlink;   /* i_nlink when I/O completes */
 
        /*
         * Side effects; used during directory lookup.
@@ -133,7 +133,7 @@ struct inode {
        uint32_t i_flags;       /* Status flags (chflags). */
        uint32_t i_uid;         /* File owner. */
        uint32_t i_gid;         /* File group. */
-       int16_t  i_nlink;       /* File link count. */
+       int32_t  i_nlink;       /* File link count. */
        uint16_t i_mode;        /* IFMT, permissions; see below. */
 };
 /*
@@ -244,6 +244,12 @@ I_IS_UFS2(const struct inode *ip)
        else                                                    \
                (ip)->i_din2->d##field = (val);                 \
        } while (0)
+#define        DIP_SET_NLINK(ip, val) do {                                     
\
+       KASSERT(ip->i_nlink >= 0, ("%s:%d %s(): setting negative "      \
+           "nlink value %d for inode %jd\n", __FILE__, __LINE__,       \
+           __FUNCTION__, (ip)->i_nlink, (ip)->i_number));              \
+       DIP_SET(ip, i_nlink, val);                                      \
+       } while (0)
 
 #define        IS_SNAPSHOT(ip)         ((ip)->i_flags & SF_SNAPSHOT)
 #define        IS_UFS(vp)              ((vp)->v_data != NULL)
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index b1964addd65d..0beeeed32251 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -1123,7 +1123,7 @@ ufs_dirremove(struct vnode *dvp, struct inode *ip, int 
flags, int isrmdir)
                        softdep_setup_unlink(dp, ip);
                } else {
                        ip->i_nlink--;
-                       DIP_SET(ip, i_nlink, ip->i_nlink);
+                       DIP_SET_NLINK(ip, ip->i_nlink);
                        UFS_INODE_SET_FLAG(ip, IN_CHANGE);
                }
        }
@@ -1139,7 +1139,7 @@ ufs_dirremove(struct vnode *dvp, struct inode *ip, int 
flags, int isrmdir)
                                softdep_change_linkcnt(ip);
                        } else {
                                ip->i_nlink++;
-                               DIP_SET(ip, i_nlink, ip->i_nlink);
+                               DIP_SET_NLINK(ip, ip->i_nlink);
                                UFS_INODE_SET_FLAG(ip, IN_CHANGE);
                        }
                }
@@ -1243,7 +1243,7 @@ ufs_dirrewrite(struct inode *dp, struct inode *oip, ino_t 
newinum, int newtype,
                softdep_setup_unlink(dp, oip);
        } else {
                oip->i_nlink--;
-               DIP_SET(oip, i_nlink, oip->i_nlink);
+               DIP_SET_NLINK(oip, oip->i_nlink);
                UFS_INODE_SET_FLAG(oip, IN_CHANGE);
        }
 
@@ -1260,7 +1260,7 @@ ufs_dirrewrite(struct inode *dp, struct inode *oip, ino_t 
newinum, int newtype,
                        softdep_change_linkcnt(oip);
                } else {
                        oip->i_nlink++;
-                       DIP_SET(oip, i_nlink, oip->i_nlink);
+                       DIP_SET_NLINK(oip, oip->i_nlink);
                        UFS_INODE_SET_FLAG(oip, IN_CHANGE);
                }
                return (error);
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 79cca75fc563..ff1f2af7b65b 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1133,7 +1133,7 @@ ufs_link(
 
        ip->i_effnlink++;
        ip->i_nlink++;
-       DIP_SET(ip, i_nlink, ip->i_nlink);
+       DIP_SET_NLINK(ip, ip->i_nlink);
        UFS_INODE_SET_FLAG(ip, IN_CHANGE);
        if (DOINGSOFTDEP(vp))
                softdep_setup_link(VTOI(tdvp), ip);
@@ -1146,7 +1146,7 @@ ufs_link(
        if (error) {
                ip->i_effnlink--;
                ip->i_nlink--;
-               DIP_SET(ip, i_nlink, ip->i_nlink);
+               DIP_SET_NLINK(ip, ip->i_nlink);
                UFS_INODE_SET_FLAG(ip, IN_CHANGE);
                if (DOINGSOFTDEP(vp))
                        softdep_revert_link(VTOI(tdvp), ip);
@@ -1528,7 +1528,7 @@ relock:
         */
        fip->i_effnlink++;
        fip->i_nlink++;
-       DIP_SET(fip, i_nlink, fip->i_nlink);
+       DIP_SET_NLINK(fip, fip->i_nlink);
        UFS_INODE_SET_FLAG(fip, IN_CHANGE);
        if (DOINGSOFTDEP(fvp))
                softdep_setup_link(tdp, fip);
@@ -1557,7 +1557,7 @@ relock:
                        if (tdp->i_nlink >= UFS_LINK_MAX) {
                                fip->i_effnlink--;
                                fip->i_nlink--;
-                               DIP_SET(fip, i_nlink, fip->i_nlink);
+                               DIP_SET_NLINK(fip, fip->i_nlink);
                                UFS_INODE_SET_FLAG(fip, IN_CHANGE);
                                if (DOINGSOFTDEP(fvp))
                                        softdep_revert_link(tdp, fip);
@@ -1680,11 +1680,11 @@ relock:
                         */
                        if (!newparent) {
                                tdp->i_nlink--;
-                               DIP_SET(tdp, i_nlink, tdp->i_nlink);
+                               DIP_SET_NLINK(tdp, tdp->i_nlink);
                                UFS_INODE_SET_FLAG(tdp, IN_CHANGE);
                        }
                        tip->i_nlink--;
-                       DIP_SET(tip, i_nlink, tip->i_nlink);
+                       DIP_SET_NLINK(tip, tip->i_nlink);
                        UFS_INODE_SET_FLAG(tip, IN_CHANGE);
                }
        }
@@ -1719,7 +1719,7 @@ relock:
                if (tip == NULL) {
                        tdp->i_effnlink++;
                        tdp->i_nlink++;
-                       DIP_SET(tdp, i_nlink, tdp->i_nlink);
+                       DIP_SET_NLINK(tdp, tdp->i_nlink);
                        UFS_INODE_SET_FLAG(tdp, IN_CHANGE);
                        if (DOINGSOFTDEP(tdvp))
                                softdep_setup_dotdot_link(tdp, fip);
@@ -1782,7 +1782,7 @@ unlockout:
 bad:
        fip->i_effnlink--;
        fip->i_nlink--;
-       DIP_SET(fip, i_nlink, fip->i_nlink);
+       DIP_SET_NLINK(fip, fip->i_nlink);
        UFS_INODE_SET_FLAG(fip, IN_CHANGE);
        if (DOINGSOFTDEP(fvp))
                softdep_revert_link(tdp, fip);
@@ -2122,7 +2122,7 @@ ufs_mkdir(
        tvp->v_type = VDIR;     /* Rest init'd in getnewvnode(). */
        ip->i_effnlink = 2;
        ip->i_nlink = 2;
-       DIP_SET(ip, i_nlink, 2);
+       DIP_SET_NLINK(ip, 2);
        DIP_SET(ip, i_dirdepth, DIP(dp,i_dirdepth) + 1);
 
        if (cnp->cn_flags & ISWHITEOUT) {
@@ -2137,7 +2137,7 @@ ufs_mkdir(
         */
        dp->i_effnlink++;
        dp->i_nlink++;
-       DIP_SET(dp, i_nlink, dp->i_nlink);
+       DIP_SET_NLINK(dp, dp->i_nlink);
        UFS_INODE_SET_FLAG(dp, IN_CHANGE);
        if (DOINGSOFTDEP(dvp))
                softdep_setup_mkdir(dp, ip);
@@ -2228,7 +2228,7 @@ bad:
        } else {
                dp->i_effnlink--;
                dp->i_nlink--;
-               DIP_SET(dp, i_nlink, dp->i_nlink);
+               DIP_SET_NLINK(dp, dp->i_nlink);
                UFS_INODE_SET_FLAG(dp, IN_CHANGE);
                /*
                 * No need to do an explicit VOP_TRUNCATE here, vrele will
@@ -2236,7 +2236,7 @@ bad:
                 */
                ip->i_effnlink = 0;
                ip->i_nlink = 0;
-               DIP_SET(ip, i_nlink, 0);
+               DIP_SET_NLINK(ip, 0);
                UFS_INODE_SET_FLAG(ip, IN_CHANGE);
                if (DOINGSOFTDEP(tvp))
                        softdep_revert_mkdir(dp, ip);
@@ -2333,11 +2333,11 @@ ufs_rmdir(
         */
        if (!DOINGSOFTDEP(vp)) {
                dp->i_nlink--;
-               DIP_SET(dp, i_nlink, dp->i_nlink);
+               DIP_SET_NLINK(dp, dp->i_nlink);
                UFS_INODE_SET_FLAG(dp, IN_CHANGE);
                error = UFS_UPDATE(dvp, 0);
                ip->i_nlink--;
-               DIP_SET(ip, i_nlink, ip->i_nlink);
+               DIP_SET_NLINK(ip, ip->i_nlink);
                UFS_INODE_SET_FLAG(ip, IN_CHANGE);
        }
        cache_vop_rmdir(dvp, vp);
@@ -2874,7 +2874,7 @@ ufs_makeinode(int mode, struct vnode *dvp, struct vnode 
**vpp,
        tvp->v_type = IFTOVT(mode);     /* Rest init'd in getnewvnode(). */
        ip->i_effnlink = 1;
        ip->i_nlink = 1;
-       DIP_SET(ip, i_nlink, 1);
+       DIP_SET_NLINK(ip, 1);
        if (DOINGSOFTDEP(tvp))
                softdep_setup_create(VTOI(dvp), ip);
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
@@ -2930,7 +2930,7 @@ bad:
         */
        ip->i_effnlink = 0;
        ip->i_nlink = 0;
-       DIP_SET(ip, i_nlink, 0);
+       DIP_SET_NLINK(ip, 0);
        UFS_INODE_SET_FLAG(ip, IN_CHANGE);
        if (DOINGSOFTDEP(tvp))
                softdep_revert_create(VTOI(dvp), ip);

Reply via email to