Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Apr 2011 23:00:23 +0000 (UTC)
From:      Dag-Erling Smorgrav <des@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r221233 - head/sbin/fsck_ffs
Message-ID:  <201104292300.p3TN0N8N019287@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: des
Date: Fri Apr 29 23:00:23 2011
New Revision: 221233
URL: http://svn.freebsd.org/changeset/base/221233

Log:
  Add an -E option to mirror newfs's.  The idea is that if you have a system
  that was built before ffs grew support for TRIM, your filesystem will have
  plenty of free blocks that the flash chip doesn't know are free, so it
  can't take advantage of them for wear leveling.  Once you've upgraded your
  kernel, you enable TRIM on the filesystem (tunefs -t enable), then run
  fsck_ffs -E on it before mounting it.
  
  I tested this patch by half-filling an mdconfig'ed filesystem image,
  running fsck_ffs -E on it, then verifying that the contents were not
  damaged by comparing them to a pristine copy using rsync's checksum
  functionality.  There is no reliable way to test it on real hardware.
  
  Many thanks to mckusick@, who provided the tricky parts of this patch and
  reviewed the final version.
  
  Reviewed by:	mckusick@
  MFC after:	3 weeks

Modified:
  head/sbin/fsck_ffs/fsck.h
  head/sbin/fsck_ffs/fsck_ffs.8
  head/sbin/fsck_ffs/fsutil.c
  head/sbin/fsck_ffs/main.c
  head/sbin/fsck_ffs/pass5.c

Modified: head/sbin/fsck_ffs/fsck.h
==============================================================================
--- head/sbin/fsck_ffs/fsck.h	Fri Apr 29 22:40:11 2011	(r221232)
+++ head/sbin/fsck_ffs/fsck.h	Fri Apr 29 23:00:23 2011	(r221233)
@@ -274,6 +274,7 @@ char	yflag;			/* assume a yes response *
 int	bkgrdflag;		/* use a snapshot to run on an active system */
 int	bflag;			/* location of alternate super block */
 int	debug;			/* output debugging info */
+int	Eflag;			/* zero out empty data blocks */
 int	inoopt;			/* trim out unused inodes */
 char	ckclean;		/* only do work if not cleanly unmounted */
 int	cvtlevel;		/* convert to newer file system format */
@@ -337,6 +338,7 @@ char	       *blockcheck(char *name);
 int		blread(int fd, char *buf, ufs2_daddr_t blk, long size);
 void		bufinit(void);
 void		blwrite(int fd, char *buf, ufs2_daddr_t blk, long size);
+void		blerase(int fd, ufs2_daddr_t blk, long size);
 void		cacheino(union dinode *dp, ino_t inumber);
 void		catch(int);
 void		catchquit(int);

Modified: head/sbin/fsck_ffs/fsck_ffs.8
==============================================================================
--- head/sbin/fsck_ffs/fsck_ffs.8	Fri Apr 29 22:40:11 2011	(r221232)
+++ head/sbin/fsck_ffs/fsck_ffs.8	Fri Apr 29 23:00:23 2011	(r221233)
@@ -29,7 +29,7 @@
 .\"	@(#)fsck.8	8.4 (Berkeley) 5/9/95
 .\" $FreeBSD$
 .\"
-.Dd January 25, 2009
+.Dd April 27, 2011
 .Dt FSCK_FFS 8
 .Os
 .Sh NAME
@@ -38,7 +38,7 @@
 .Nd file system consistency check and interactive repair
 .Sh SYNOPSIS
 .Nm
-.Op Fl BFfnpry
+.Op Fl BEFfnpry
 .Op Fl b Ar block
 .Op Fl c Ar level
 .Op Fl m Ar mode
@@ -149,6 +149,24 @@ If unexpected errors are found,
 the file system is marked as needing a foreground check and
 .Nm
 exits without attempting any further cleaning.
+.It Fl E
+Clear unallocated blocks, notifying the underlying device that they
+are not used and that their contents may be discarded.
+This is useful for filesystems which have been mounted on systems
+without TRIM support, or with TRIM support disabled, as well as
+filesystems which have been copied from one device to another.
+.Pp
+See the
+.Fl E
+and
+.Fl t
+flags of
+.Xr newfs 8 ,
+and
+the
+.Fl t
+flag of
+.Xr tunefs 8 .
 .It Fl F
 Determine whether the file system needs to be cleaned immediately
 in foreground, or if its cleaning can be deferred to background.

Modified: head/sbin/fsck_ffs/fsutil.c
==============================================================================
--- head/sbin/fsck_ffs/fsutil.c	Fri Apr 29 22:40:11 2011	(r221232)
+++ head/sbin/fsck_ffs/fsutil.c	Fri Apr 29 23:00:23 2011	(r221233)
@@ -39,9 +39,10 @@ __FBSDID("$FreeBSD$");
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/sysctl.h>
+#include <sys/disk.h>
 #include <sys/disklabel.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
-#include <sys/disklabel.h>
 
 #include <ufs/ufs/dinode.h>
 #include <ufs/ufs/dir.h>
@@ -421,6 +422,20 @@ blwrite(int fd, char *buf, ufs2_daddr_t 
 	return;
 }
 
+void
+blerase(int fd, ufs2_daddr_t blk, long size)
+{
+	off_t ioarg[2];
+
+	if (fd < 0)
+		return;
+	ioarg[0] = blk * dev_bsize;
+	ioarg[1] = size;
+	ioctl(fd, DIOCGDELETE, ioarg);
+	/* we don't really care if we succeed or not */
+	return;
+}
+
 /*
  * Verify cylinder group's magic number and other parameters.  If the
  * test fails, offer an option to rebuild the whole cylinder group.

Modified: head/sbin/fsck_ffs/main.c
==============================================================================
--- head/sbin/fsck_ffs/main.c	Fri Apr 29 22:40:11 2011	(r221232)
+++ head/sbin/fsck_ffs/main.c	Fri Apr 29 23:00:23 2011	(r221233)
@@ -82,7 +82,7 @@ main(int argc, char *argv[])
 	sync();
 	skipclean = 1;
 	inoopt = 0;
-	while ((ch = getopt(argc, argv, "b:Bc:CdfFm:npry")) != -1) {
+	while ((ch = getopt(argc, argv, "b:Bc:CdEfFm:npry")) != -1) {
 		switch (ch) {
 		case 'b':
 			skipclean = 0;
@@ -106,6 +106,10 @@ main(int argc, char *argv[])
 			debug++;
 			break;
 
+		case 'E':
+			Eflag++;
+			break;
+
 		case 'f':
 			skipclean = 0;
 			break;
@@ -632,7 +636,7 @@ static void
 usage(void)
 {
 	(void) fprintf(stderr,
-	    "usage: %s [-BFprfny] [-b block] [-c level] [-m mode] "
+	    "usage: %s [-BEFprfny] [-b block] [-c level] [-m mode] "
 			"filesystem ...\n",
 	    getprogname());
 	exit(1);

Modified: head/sbin/fsck_ffs/pass5.c
==============================================================================
--- head/sbin/fsck_ffs/pass5.c	Fri Apr 29 22:40:11 2011	(r221232)
+++ head/sbin/fsck_ffs/pass5.c	Fri Apr 29 23:00:23 2011	(r221233)
@@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$");
 
 static void check_maps(u_char *, u_char *, int, ufs2_daddr_t, const char *, int *, int, int);
 
+static void clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end);
+
 void
 pass5(void)
 {
@@ -58,7 +60,7 @@ pass5(void)
 	int inomapsize, blkmapsize;
 	struct fs *fs = &sblock;
 	struct cg *cg = &cgrp;
-	ufs2_daddr_t d, dbase, dmax;
+	ufs2_daddr_t d, dbase, dmax, start;
 	int excessdirs, rewritecg = 0;
 	struct csum *cs;
 	struct csum_total cstotal;
@@ -242,13 +244,21 @@ pass5(void)
 				setbit(cg_inosused(newcg), i);
 				newcg->cg_cs.cs_nifree--;
 			}
+		start = -1;
 		for (i = 0, d = dbase;
 		     d < dmax;
 		     d += fs->fs_frag, i += fs->fs_frag) {
 			frags = 0;
 			for (j = 0; j < fs->fs_frag; j++) {
-				if (testbmap(d + j))
+				if (testbmap(d + j)) {
+					if (Eflag && start != -1) {
+						clear_blocks(start, d + j - 1);
+						start = -1;
+					}
 					continue;
+				}
+				if (start == -1)
+					start = d + j;
 				setbit(cg_blksfree(newcg), i + j);
 				frags++;
 			}
@@ -263,6 +273,8 @@ pass5(void)
 				ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
 			}
 		}
+		if (Eflag && start != -1)
+			clear_blocks(start, d - 1);
 		if (fs->fs_contigsumsize > 0) {
 			int32_t *sump = cg_clustersum(newcg);
 			u_char *mapp = cg_clustersfree(newcg);
@@ -551,3 +563,12 @@ check_maps(
 		}
 	}
 }
+
+static void clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end)
+{
+
+	if (debug)
+		printf("Zero frags %jd to %jd\n", start, end);
+	blerase(fswritefd, fsbtodb(&sblock, start),
+	    lfragtosize(&sblock, end - start + 1));
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104292300.p3TN0N8N019287>