Many files:
unix.c (main): If compression is enabled on the filesystem, print a
warning message (for now).
message.c: Add new compression shortcut: @c == compress
problem.c, problem.h (PR_1_COMPR_SET): Add new error code.
pass1.c (check_blocks): If the inode has EXT2_COMPRBLK_FL flag set,
check to see if the filesystem supports compression. If it does pass
this information down to process_block() so it can treat the
compressed block flag words correctly. If not, offer to clear the
flag, since it shouldn't be set.
(process_block): If an inode has the compressed inode flag set, allow
EXT2FS_COMPRESSED_BLKADDR.
pass1b.c (process_pass1b_block, delete_file_block, clone_file_block):
pass2.c (deallocate_inode_block): Use HOLE_BLKADDR to check to see if
the block can be skipped.
ChangeLog, Makefile.in:
Makefile.in: Exclude the internationalization files from being
distributed.
ChangeLog, configure, configure.in:
configure.in: Add support for --enable-compression. This is
experimental code only for now, which is why it's under --enable test.
Once it's stable, it will always be compiled in.
TODO:
Commit additional TODO items.
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 32a43ad..89c2133 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,3 +1,26 @@
+2000-02-11 <tytso@snap.thunk.org>
+
+ * unix.c (main): If compression is enabled on the filesystem,
+ print a warning message (for now).
+
+ * message.c: Add new compression shortcut: @c == compress
+
+ * problem.c, problem.h (PR_1_COMPR_SET): Add new error code.
+
+ * pass1.c (check_blocks): If the inode has EXT2_COMPRBLK_FL flag
+ set, check to see if the filesystem supports compression.
+ If it does pass this information down to process_block()
+ so it can treat the compressed block flag words
+ correctly. If not, offer to clear the flag, since it
+ shouldn't be set.
+ (process_block): If an inode has the compressed inode flag
+ set, allow EXT2FS_COMPRESSED_BLKADDR.
+
+ * pass1b.c (process_pass1b_block, delete_file_block,
+ clone_file_block):
+ * pass2.c (deallocate_inode_block): Use HOLE_BLKADDR to check to
+ see if the block can be skipped.
+
2000-02-08 <tytso@snap.thunk.org>
* util.c: Make resource tracking message more concise.
diff --git a/e2fsck/message.c b/e2fsck/message.c
index bace3c5..3018cc0 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -50,6 +50,7 @@
* @A error allocating
* @b block
* @B bitmap
+ * @c compress
* @C conflicts with some other fs block
* @i inode
* @I illegal
@@ -95,6 +96,7 @@
N_("Aerror allocating"),
N_("bblock"),
N_("Bbitmap"),
+ N_("ccompress"),
N_("Cconflicts with some other fs @b"),
N_("iinode"),
N_("Iillegal"),
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index cf30ef6..771c505 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -72,7 +72,8 @@
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 @@
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 @@
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 @@
* 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 @@
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;
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index a1cbf18..5db39ab 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -241,7 +241,7 @@
int i;
e2fsck_t ctx;
- if (!*block_nr)
+ if (HOLE_BLKADDR(*block_nr))
return 0;
p = (struct process_block_struct *) priv_data;
ctx = p->ctx;
@@ -493,7 +493,7 @@
pb = (struct process_block_struct *) priv_data;
ctx = pb->ctx;
- if (!*block_nr)
+ if (HOLE_BLKADDR(*block_nr))
return 0;
if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
@@ -567,7 +567,7 @@
ctx = cs->ctx;
- if (!*block_nr)
+ if (HOLE_BLKADDR(*block_nr))
return 0;
if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 826c0dc..6b95900 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -605,7 +605,7 @@
{
e2fsck_t ctx = (e2fsck_t) priv_data;
- if (!*block_nr)
+ if (HOLE_BLKADDR(*block_nr))
return 0;
ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 96509d8..0a72061 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -423,6 +423,11 @@
N_("Special (device/socket/fifo) @i %i has immutable flag set. "),
PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
+ /* Imagic flag set on an inode when filesystem doesn't support it */
+ { PR_1_COMPR_SET,
+ N_("@i %i has @cion flag set on @f without @cion support. "),
+ PROMPT_CLEAR, 0 },
+
/* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 9aa2cc9..1de1dc9 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -241,7 +241,10 @@
/* Immutable flag set on a device or socket inode */
#define PR_1_SET_IMMUTABLE 0x010030
-
+
+/* Compression flag set on a non-compressed filesystem */
+#define PR_1_COMPR_SET 0x010031
+
/*
* Pass 1b errors
*/
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index fbe5980..9696a77 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -757,6 +757,11 @@
"(%s)", ctx->filesystem_name);
goto get_newer;
}
+#ifdef ENABLE_COMPRESSION
+ if (s->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
+ com_err(ctx->program_name, 0,
+ _("Warning: compression support is experimental.\n"));
+#endif
if (ctx->device_name == 0 &&
(s->s_volume_name[0] != 0)) {
char *cp = malloc(sizeof(s->s_volume_name)+1);