summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/fsck_ffs/fsck.h2
-rw-r--r--sbin/fsck_ffs/fsck_ffs.822
-rw-r--r--sbin/fsck_ffs/fsutil.c17
-rw-r--r--sbin/fsck_ffs/main.c8
-rw-r--r--sbin/fsck_ffs/pass5.c25
5 files changed, 67 insertions, 7 deletions
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 342b95f..250fc1f 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -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);
diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8
index 2834149..523cb65 100644
--- a/sbin/fsck_ffs/fsck_ffs.8
+++ b/sbin/fsck_ffs/fsck_ffs.8
@@ -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.
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 68d113a..85ea033 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -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 blk, long size)
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.
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 127a612..e26494d 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -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);
diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c
index 639ce0f..01ed8a5 100644
--- a/sbin/fsck_ffs/pass5.c
+++ b/sbin/fsck_ffs/pass5.c
@@ -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));
+}
OpenPOWER on IntegriCloud