git: d3a36e4b7459 - main - Delete snapshot after opening it when running fsck_ffs(9) in background.

From: Kirk McKusick <mckusick_at_FreeBSD.org>
Date: Wed, 25 Oct 2023 22:38:31 UTC
The branch main has been updated by mckusick:

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

commit d3a36e4b7459b2d62c4cd50de7a8e3195d7241c7
Author:     Kirk McKusick <mckusick@FreeBSD.org>
AuthorDate: 2023-10-25 22:36:45 +0000
Commit:     Kirk McKusick <mckusick@FreeBSD.org>
CommitDate: 2023-10-25 22:38:11 +0000

    Delete snapshot after opening it when running fsck_ffs(9) in background.
    
    When fsck_ffs(8) runs in background, it creates a snapshot named
    fsck_snapshot in the filesystem's .snap directory. The fsck_snapshot
    file was removed when the background fsck finished. If the system
    crashed or the fsck exited unexpectedly, the fsck_snapshot file
    would remain. The snapshot would consume ever more space as the
    filesystem changed over time until it was removed by a system
    administrator or a future run of background fsck removed it to
    create a new snapshot file.
    
    This commit unlinks the .snap/fsck_snapshot file immediately after
    opening it so that it will be reclaimed when fsck closes it at the
    conclusion of its run. After a system crash, it will be removed as
    part of the filesystem cleanup because of its zero reference count.
    As only a few milliseconds pass between its creation and unlinking,
    there is far less opportunity for it to be accidentally left behind.
    
    PR:           106107
    MFC-after:    1 week
---
 sbin/fsck_ffs/fsck.h   | 1 -
 sbin/fsck_ffs/fsutil.c | 1 -
 sbin/fsck_ffs/globs.c  | 2 --
 sbin/fsck_ffs/main.c   | 8 +++++---
 sbin/fsck_ffs/setup.c  | 8 ++++----
 5 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 1864ea19f4ca..3b795783f39c 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -376,7 +376,6 @@ extern long secsize;		/* actual disk sector size */
 extern char skipclean;		/* skip clean file systems if preening */
 extern int snapcnt;		/* number of active snapshots */
 extern struct inode snaplist[FSMAXSNAP + 1]; /* list of active snapshots */
-extern char snapname[BUFSIZ];	/* when doing snapshots, the name of the file */
 extern int sujrecovery;		/* 1 => doing check using the journal */
 extern int surrender;		/* Give up if reads fail */
 extern char usedsoftdep;	/* just fix soft dependency inconsistencies */
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 5cf17e22fe80..2583e324e94c 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -616,7 +616,6 @@ ckfini(int markclean)
 	int ofsmodified, cnt, cg;
 
 	if (bkgrdflag) {
-		unlink(snapname);
 		if ((!(sblock.fs_flags & FS_UNCLEAN)) != markclean) {
 			cmd.value = FS_UNCLEAN;
 			cmd.size = markclean ? -1 : 1;
diff --git a/sbin/fsck_ffs/globs.c b/sbin/fsck_ffs/globs.c
index 038fc3475742..b004dd7d48b7 100644
--- a/sbin/fsck_ffs/globs.c
+++ b/sbin/fsck_ffs/globs.c
@@ -71,7 +71,6 @@ int	freefiles[MIBSIZE];	/* MIB cmd to free a set of files */
 int	freedirs[MIBSIZE];	/* MIB cmd to free a set of directories */
 int	freeblks[MIBSIZE];	/* MIB cmd to free a set of data blocks */
 struct	fsck_cmd cmd;		/* sysctl file system update commands */
-char	snapname[BUFSIZ];	/* when doing snapshots, the name of the file */
 char	*cdevname;		/* name of device being checked */
 long	dev_bsize;		/* computed value of DEV_BSIZE */
 long	secsize;		/* actual disk sector size */
@@ -144,7 +143,6 @@ fsckinit(void)
 	bzero(freedirs, sizeof(int) * MIBSIZE);
 	bzero(freeblks, sizeof(int) * MIBSIZE);
 	bzero(&cmd, sizeof(struct fsck_cmd));
-	bzero(snapname, sizeof(char) * BUFSIZ);
 	cdevname = NULL;
 	dev_bsize = 0;
 	secsize = 0;
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 58e184f3581f..ee39760f4dd2 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -68,7 +68,8 @@ static char sccsid[] = "@(#)main.c	8.6 (Berkeley) 5/14/95";
 
 #include "fsck.h"
 
-static int	restarts;
+static int  restarts;
+static char snapname[BUFSIZ];	/* when doing snapshots, the name of the file */
 
 static void usage(void) __dead2;
 static intmax_t argtoimax(int flag, const char *req, const char *str, int base);
@@ -664,8 +665,7 @@ setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys)
 		    "SUPPORT\n");
 	}
 	/* Find or create the snapshot directory */
-	snprintf(snapname, sizeof snapname, "%s/.snap",
-	    mntp->f_mntonname);
+	snprintf(snapname, sizeof snapname, "%s/.snap", mntp->f_mntonname);
 	if (stat(snapname, &snapdir) < 0) {
 		if (errno != ENOENT) {
 			pwarn("CANNOT FIND SNAPSHOT DIRECTORY %s: %s, CANNOT "
@@ -713,6 +713,8 @@ setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys)
 		    "BACKGROUND\n", snapname, strerror(errno));
 		return (0);
 	}
+	/* Immediately unlink snapshot so that it will be deleted when closed */
+	unlink(snapname);
 	free(sblock.fs_csp);
 	free(sblock.fs_si);
 	if (readsb() == 0) {
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index d1d09d07b43a..c9aa19c7eded 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -380,14 +380,14 @@ openfilesys(char *dev)
 	if ((statb.st_mode & S_IFMT) != S_IFCHR &&
 	    (statb.st_mode & S_IFMT) != S_IFBLK) {
 		if (bkgrdflag != 0 && (statb.st_flags & SF_SNAPSHOT) == 0) {
-			pfatal("BACKGROUND FSCK LACKS A SNAPSHOT\n");
-			exit(EEXIT);
+			pwarn("BACKGROUND FSCK LACKS A SNAPSHOT\n");
+			return (0);
 		}
 		if (bkgrdflag != 0) {
 			cursnapshot = statb.st_ino;
 		} else {
-			pfatal("%s IS NOT A DISK DEVICE\n", dev);
-			if (reply("CONTINUE") == 0)
+			pwarn("%s IS NOT A DISK DEVICE\n", dev);
+			if (preen || reply("CONTINUE") == 0)
 				return (0);
 		}
 	}