summaryrefslogtreecommitdiff
path: root/e2fsck/pass1.c
diff options
context:
space:
mode:
Diffstat (limited to 'e2fsck/pass1.c')
-rw-r--r--e2fsck/pass1.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index cf30ef60..771c505b 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -72,7 +72,8 @@ static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
struct process_block_struct {
ino_t ino;
- int is_dir:1, clear:1, suppress:1, fragmented:1;
+ int is_dir:1, clear:1, suppress:1,
+ fragmented:1, compressed:1;
blk_t num_blocks;
e2_blkcnt_t last_block;
int num_illegal_blocks;
@@ -773,12 +774,27 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
pb.num_illegal_blocks = 0;
pb.suppress = 0; pb.clear = 0;
pb.fragmented = 0;
+ pb.compressed = 0;
pb.previous_block = 0;
pb.is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
pb.inode = inode;
pb.pctx = pctx;
pb.ctx = ctx;
pctx->ino = ino;
+
+ if (inode->i_flags & EXT2_COMPRBLK_FL) {
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_INCOMPAT_COMPRESSION))
+ pb.compressed = 1;
+ else {
+ if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
+ inode->i_flags &= ~EXT2_COMPRBLK_FL;
+ e2fsck_write_inode(ctx, ino, inode,
+ "check_blocks");
+ }
+ }
+ }
+
pctx->errcode = ext2fs_block_iterate2(fs, ino,
pb.is_dir ? BLOCK_FLAG_HOLE : 0,
block_buf, process_block, &pb);
@@ -941,6 +957,28 @@ int process_block(ext2_filsys fs,
pctx = p->pctx;
ctx = p->ctx;
+ if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
+ /* todo: Check that the comprblk_fl is high, that the
+ blkaddr pattern looks right (all non-holes up to
+ first EXT2FS_COMPRESSED_BLKADDR, then all
+ EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
+ that the feature_incompat bit is high, and that the
+ inode is a regular file. If we're doing a "full
+ check" (a concept introduced to e2fsck by e2compr,
+ meaning that we look at data blocks as well as
+ metadata) then call some library routine that
+ checks the compressed data. I'll have to think
+ about this, because one particularly important
+ problem to be able to fix is to recalculate the
+ cluster size if necessary. I think that perhaps
+ we'd better do most/all e2compr-specific checks
+ separately, after the non-e2compr checks. If not
+ doing a full check, it may be useful to test that
+ the personality is linux; e.g. if it isn't then
+ perhaps this really is just an illegal block. */
+ return 0;
+ }
+
if (blk == 0) {
if (p->is_dir == 0) {
/*
@@ -976,7 +1014,7 @@ int process_block(ext2_filsys fs,
* file be contiguous. (Which can never be true for really
* big files that are greater than a block group.)
*/
- if (p->previous_block) {
+ if (!HOLE_BLKADDR(p->previous_block)) {
if (p->previous_block+1 != blk)
p->fragmented = 1;
}
@@ -1057,6 +1095,11 @@ int process_bad_block(ext2_filsys fs,
struct problem_context *pctx;
e2fsck_t ctx;
+ /*
+ * Note: This function processes blocks for the bad blocks
+ * inode, which is never compressed. So we don't use HOLE_BLKADDR().
+ */
+
if (!blk)
return 0;