git: 007322a94cee - stable/13 - Add the ability to adjust directory depths to background fsck_ffs(8).
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 07 Jun 2023 22:35:10 UTC
The branch stable/13 has been updated by mckusick:
URL: https://cgit.FreeBSD.org/src/commit/?id=007322a94ceeca654c3bb3bf1fdf6e2bea30d683
commit 007322a94ceeca654c3bb3bf1fdf6e2bea30d683
Author: Kirk McKusick <mckusick@FreeBSD.org>
AuthorDate: 2023-05-26 02:27:04 +0000
Commit: Kirk McKusick <mckusick@FreeBSD.org>
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.