summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2013-04-29 20:13:09 +0000
committerdes <des@FreeBSD.org>2013-04-29 20:13:09 +0000
commita44b26897fe945895cdaceab1334e351f45d0901 (patch)
tree76cb8332af9430e1c1556bbc8a24c5168fc2de7f /sbin
parent6cfe294dedc835f600fbdf81a4eebbd6aafe7099 (diff)
downloadFreeBSD-src-a44b26897fe945895cdaceab1334e351f45d0901.zip
FreeBSD-src-a44b26897fe945895cdaceab1334e351f45d0901.tar.gz
Add a -Z option which zeroes unused blocks. It can be combined with -E,
in which case unused blocks are first zeroed and then erased. Reviewed by: mckusick MFC after: 3 weeks
Diffstat (limited to 'sbin')
-rw-r--r--sbin/fsck_ffs/fsck.h5
-rw-r--r--sbin/fsck_ffs/fsck_ffs.811
-rw-r--r--sbin/fsck_ffs/fsutil.c29
-rw-r--r--sbin/fsck_ffs/main.c6
-rw-r--r--sbin/fsck_ffs/pass5.c12
5 files changed, 56 insertions, 7 deletions
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 7b45d48..45b242c 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -74,6 +74,7 @@
#define MINBUFS 10 /* minimum number of buffers required */
#define MAXBUFS 40 /* maximum space to allocate to buffers */
#define INOBUFSIZE 64*1024 /* size of buffer to read inodes in pass1 */
+#define ZEROBUFSIZE (dev_bsize * 128) /* size of zero buffer used by -Z */
union dinode {
struct ufs1_dinode dp1;
@@ -306,7 +307,8 @@ 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 Eflag; /* delete empty data blocks */
+int Zflag; /* zero 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 */
@@ -402,6 +404,7 @@ 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, ssize_t size);
void blerase(int fd, ufs2_daddr_t blk, long size);
+void blzero(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 0513017..0b3f992 100644
--- a/sbin/fsck_ffs/fsck_ffs.8
+++ b/sbin/fsck_ffs/fsck_ffs.8
@@ -38,7 +38,7 @@
.Nd file system consistency check and interactive repair
.Sh SYNOPSIS
.Nm
-.Op Fl BEFfnpry
+.Op Fl BEFfnpryZ
.Op Fl b Ar block
.Op Fl c Ar level
.Op Fl m Ar mode
@@ -280,6 +280,15 @@ Assume a yes response to all questions asked by
.Nm ;
this should be used with great caution as this is a free license
to continue after essentially unlimited trouble has been encountered.
+.It Fl Z
+Similar to
+.Fl E ,
+but overwrites unused blocks with zeroes.
+If both
+.Fl E
+and
+.Fl Z
+are specified, blocks are first zeroed and then erased.
.El
.Pp
Inconsistencies checked are as follows:
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 9ebc342..f177408 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -618,6 +618,35 @@ blerase(int fd, ufs2_daddr_t blk, long size)
return;
}
+void
+blzero(int fd, ufs2_daddr_t blk, long size)
+{
+ static char *zero;
+ off_t offset, len;
+
+ if (fd < 0)
+ return;
+ len = ZEROBUFSIZE;
+ if (zero == NULL) {
+ zero = calloc(len, 1);
+ if (zero == NULL)
+ errx(EEXIT, "cannot allocate buffer pool");
+ }
+ offset = blk * dev_bsize;
+ if (lseek(fd, offset, 0) < 0)
+ rwerror("SEEK BLK", blk);
+ while (size > 0) {
+ if (size > len)
+ size = len;
+ else
+ len = size;
+ if (write(fd, zero, len) != len)
+ rwerror("WRITE BLK", blk);
+ blk += len / dev_bsize;
+ size -= len;
+ }
+}
+
/*
* 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 27f17db..d074447 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:CdEfFm:npry")) != -1) {
+ while ((ch = getopt(argc, argv, "b:Bc:CdEfFm:npryZ")) != -1) {
switch (ch) {
case 'b':
skipclean = 0;
@@ -147,6 +147,10 @@ main(int argc, char *argv[])
nflag = 0;
break;
+ case 'Z':
+ Zflag++;
+ break;
+
default:
usage();
}
diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c
index 146acec..38068eb 100644
--- a/sbin/fsck_ffs/pass5.c
+++ b/sbin/fsck_ffs/pass5.c
@@ -252,7 +252,7 @@ pass5(void)
frags = 0;
for (j = 0; j < fs->fs_frag; j++) {
if (testbmap(d + j)) {
- if (Eflag && start != -1) {
+ if ((Eflag || Zflag) && start != -1) {
clear_blocks(start, d + j - 1);
start = -1;
}
@@ -274,7 +274,7 @@ pass5(void)
ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
}
}
- if (Eflag && start != -1)
+ if ((Eflag || Zflag) && start != -1)
clear_blocks(start, d - 1);
if (fs->fs_contigsumsize > 0) {
int32_t *sump = cg_clustersum(newcg);
@@ -586,6 +586,10 @@ 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));
+ if (Zflag)
+ blzero(fswritefd, fsbtodb(&sblock, start),
+ lfragtosize(&sblock, end - start + 1));
+ if (Eflag)
+ blerase(fswritefd, fsbtodb(&sblock, start),
+ lfragtosize(&sblock, end - start + 1));
}
OpenPOWER on IntegriCloud