diff options
author | des <des@FreeBSD.org> | 2011-04-29 23:00:23 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2011-04-29 23:00:23 +0000 |
commit | e9b6a49782626401ce568d3d1e87a29ec181aed0 (patch) | |
tree | e58bb5eb7293c08ac870dd7b462cbf76cdde8ec2 /sbin/fsck_ffs/pass5.c | |
parent | 5adbc718330a91ab900ef67c71de25f7154ab8b6 (diff) | |
download | FreeBSD-src-e9b6a49782626401ce568d3d1e87a29ec181aed0.zip FreeBSD-src-e9b6a49782626401ce568d3d1e87a29ec181aed0.tar.gz |
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
Diffstat (limited to 'sbin/fsck_ffs/pass5.c')
-rw-r--r-- | sbin/fsck_ffs/pass5.c | 25 |
1 files changed, 23 insertions, 2 deletions
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)); +} |