The branch stable/13 has been updated by mckusick:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=007322a94ceeca654c3bb3bf1fdf6e2bea30d683

commit 007322a94ceeca654c3bb3bf1fdf6e2bea30d683
Author:     Kirk McKusick <[email protected]>
AuthorDate: 2023-05-26 02:27:04 +0000
Commit:     Kirk McKusick <[email protected]>
CommitDate: 2023-06-07 22:34:39 +0000

    Add the ability to adjust directory depths to background fsck_ffs(8).
    
    Sponsored by: The FreeBSD Foundation
    
    (cherry picked from commit e4a905d1e0d94ddb8e15de50d37e67f13e058047)
---
 sbin/fsck_ffs/dir.c     | 26 +++++++++++++++++++++-----
 sbin/fsck_ffs/fsck.h    |  1 +
 sbin/fsck_ffs/globs.c   |  2 ++
 sys/ufs/ffs/ffs_alloc.c | 28 ++++++++++++++++++++++++++++
 sys/ufs/ffs/fs.h        |  3 ++-
 5 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c
index cc5305c390a4..e5f0e1e7e7f4 100644
--- a/sbin/fsck_ffs/dir.c
+++ b/sbin/fsck_ffs/dir.c
@@ -105,6 +105,7 @@ check_dirdepth(struct inoinfo *inp)
        struct inode ip;
        union dinode *dp;
        int saveresolved;
+       size_t size;
        static int updateasked, dirdepthupdate;
 
        if ((parentinp = getinoinfo(inp->i_parent)) == NULL) {
@@ -141,9 +142,11 @@ check_dirdepth(struct inoinfo *inp)
                }
        }
        /*
-        * If we are not converting, nothing more to do.
+        * If we are not converting or we are running in no-write mode
+        * there is nothing more to do.
         */
-       if (inp->i_depth == 0 && dirdepthupdate == 0)
+       if ((inp->i_depth == 0 && dirdepthupdate == 0) ||
+           (fswritefd < 0 && bkgrdflag == 0))
                return;
        /*
         * Individual directory at wrong depth. Report it and correct if
@@ -174,8 +177,20 @@ check_dirdepth(struct inoinfo *inp)
                        printf(" (ADJUSTED)\n");
        }
        inp->i_depth = parentinp->i_depth + 1;
-       DIP_SET(dp, di_dirdepth, inp->i_depth);
-       inodirty(&ip);
+       if (bkgrdflag == 0) {
+               DIP_SET(dp, di_dirdepth, inp->i_depth);
+               inodirty(&ip);
+       } else {
+               cmd.value = inp->i_number;
+               cmd.size = (int64_t)inp->i_depth - DIP(dp, di_dirdepth);
+               if (debug)
+                       printf("adjdepth ino %ld amt %jd\n", (long)cmd.value,
+                           (intmax_t)cmd.size);
+               size = MIBSIZE;
+               if (sysctlnametomib("vfs.ffs.adjdepth", adjdepth, &size) < 0 ||
+                   sysctl(adjdepth, MIBSIZE, 0, 0, &cmd, sizeof cmd) == -1)
+                       rwerror("ADJUST INODE DEPTH", cmd.value);
+       }
        irelse(&ip);
 }
 
@@ -506,7 +521,8 @@ adjust(struct inodesc *idesc, int lcnt)
                                            (long long)cmd.size);
                                if (sysctl(adjrefcnt, MIBSIZE, 0, 0,
                                    &cmd, sizeof cmd) == -1)
-                                       rwerror("ADJUST INODE", cmd.value);
+                                       rwerror("ADJUST INODE LINK COUNT",
+                                           cmd.value);
                        }
                }
        }
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 4e5878b0b12f..9f9b1e0a8857 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -333,6 +333,7 @@ extern int adjnbfree[MIBSIZE];      /* MIB cmd to adjust 
number of free blocks */
 extern int adjnifree[MIBSIZE]; /* MIB cmd to adjust number of free inodes */
 extern int adjnffree[MIBSIZE]; /* MIB cmd to adjust number of free frags */
 extern int adjnumclusters[MIBSIZE]; /* MIB cmd adjust number of free clusters 
*/
+extern int adjdepth[MIBSIZE];  /* MIB cmd to adjust directory depth count */
 extern int freefiles[MIBSIZE]; /* MIB cmd to free a set of files */
 extern int freedirs[MIBSIZE];  /* MIB cmd to free a set of directories */
 extern int freeblks[MIBSIZE];  /* MIB cmd to free a set of data blocks */
diff --git a/sbin/fsck_ffs/globs.c b/sbin/fsck_ffs/globs.c
index 92e77b61f9d4..2340636fe3a9 100644
--- a/sbin/fsck_ffs/globs.c
+++ b/sbin/fsck_ffs/globs.c
@@ -68,6 +68,7 @@ int   adjnbfree[MIBSIZE];     /* MIB command to adjust number 
of free blocks */
 int    adjnifree[MIBSIZE];     /* MIB command to adjust number of free inodes 
*/
 int    adjnffree[MIBSIZE];     /* MIB command to adjust number of free frags */
 int    adjnumclusters[MIBSIZE];        /* MIB command to adjust number of free 
clusters */
+int    adjdepth[MIBSIZE];      /* MIB cmd to adjust directory depth count */
 int    freefiles[MIBSIZE];     /* MIB command to free a set of files */
 int    freedirs[MIBSIZE];      /* MIB command to free a set of directories */
 int    freeblks[MIBSIZE];      /* MIB command to free a set of data blocks */
@@ -141,6 +142,7 @@ fsckinit(void)
        bzero(adjnifree, sizeof(int) * MIBSIZE);
        bzero(adjnffree, sizeof(int) * MIBSIZE);
        bzero(adjnumclusters, sizeof(int) * MIBSIZE);
+       bzero(adjdepth, sizeof(int) * MIBSIZE);
        bzero(freefiles, sizeof(int) * MIBSIZE);
        bzero(freedirs, sizeof(int) * MIBSIZE);
        bzero(freeblks, sizeof(int) * MIBSIZE);
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 6d37afcfadf6..195ba9f8a299 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -3108,6 +3108,8 @@ ffs_fserr(struct fs *fs,
  *     the count to zero will cause the inode to be freed.
  * adjblkcnt(inode, amt) - adjust the number of blocks used by the
  *     inode by the specified amount.
+ * adjdepth(inode, amt) - adjust the depth of the specified directory
+ *     inode by the specified amount.
  * setsize(inode, size) - set the size of the inode to the
  *     specified size.
  * adjndir, adjbfree, adjifree, adjffree, adjnumclusters(amt) -
@@ -3142,6 +3144,10 @@ static SYSCTL_NODE(_vfs_ffs, FFS_ADJ_BLKCNT, adjblkcnt,
     CTLFLAG_WR | CTLFLAG_NEEDGIANT, sysctl_ffs_fsck,
     "Adjust Inode Used Blocks Count");
 
+static SYSCTL_NODE(_vfs_ffs, FFS_ADJ_DEPTH, adjdepth,
+    CTLFLAG_WR | CTLFLAG_NEEDGIANT, sysctl_ffs_fsck,
+    "Adjust Directory Inode Depth");
+
 static SYSCTL_NODE(_vfs_ffs, FFS_SET_SIZE, setsize,
     CTLFLAG_WR | CTLFLAG_NEEDGIANT, sysctl_ffs_fsck,
     "Set the inode size");
@@ -3299,6 +3305,28 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
                vput(vp);
                break;
 
+       case FFS_ADJ_DEPTH:
+#ifdef DIAGNOSTIC
+               if (fsckcmds) {
+                       printf("%s: adjust directory inode %jd depth by %jd\n",
+                           mp->mnt_stat.f_mntonname, (intmax_t)cmd.value,
+                           (intmax_t)cmd.size);
+               }
+#endif /* DIAGNOSTIC */
+               if ((error = ffs_vget(mp, (ino_t)cmd.value, LK_EXCLUSIVE, &vp)))
+                       break;
+               if (vp->v_type != VDIR) {
+                       vput(vp);
+                       error = ENOTDIR;
+                       break;
+               }
+               ip = VTOI(vp);
+               DIP_SET(ip, i_dirdepth, DIP(ip, i_dirdepth) + cmd.size);
+               UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_MODIFIED);
+               error = ffs_update(vp, 1);
+               vput(vp);
+               break;
+
        case FFS_SET_SIZE:
 #ifdef DIAGNOSTIC
                if (fsckcmds) {
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index b2ed2051471c..70e24242b01b 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -224,7 +224,8 @@
 /* Was FFS_SET_INODE           15 */
 /* Was FFS_SET_BUFOUTPUT       16 */
 #define        FFS_SET_SIZE            17      /* set inode size */
-#define        FFS_MAXID               17      /* number of valid ffs ids */
+#define        FFS_ADJ_DEPTH           18      /* adjust directory inode depth 
*/
+#define        FFS_MAXID               18      /* number of valid ffs ids */
 
 /*
  * Command structure passed in to the filesystem to adjust filesystem values.

Reply via email to