]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
e2fsck: Fix directory i_size handling
authorTheodore Ts'o <tytso@mit.edu>
Thu, 13 Mar 2008 04:58:54 +0000 (00:58 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 13 Mar 2008 04:58:54 +0000 (00:58 -0400)
If a directory's i_size is bigger than the number of blocks, don't try
to allocate extra empty blocks to the end of the directory; there's no
real point to do that.  Also, if a directory's i_size is not a
multiple of the blocksize, flag that as a mistake so it can be fixed.

This more elegantly addresses the problem which was found on Bas van
Schaik's filesystem.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/pass1.c
tests/f_holedir/expect.1
tests/f_holedir/expect.2

index b4db8efcfadc56874a4f62d178c26f6d5003d668..839f099de978eaf560559d5f8d06839e690c7e38 100644 (file)
@@ -1546,6 +1546,26 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
                goto out;
        }
        
+       if (pb.is_dir) {
+               while (1) {
+                       struct ext2_db_entry *entry;
+
+                       if (ext2fs_dblist_get_last(fs->dblist, &entry) ||
+                           (entry->ino != ino) ||
+                           (entry->blk != 0) ||
+                           (entry->blockcnt == 0))
+                               break;
+                       /* printf("Dropping ino %lu blk %lu blockcnt %d\n", 
+                                 entry->ino, entry->blk, entry->blockcnt); */
+                       ext2fs_dblist_drop_last(fs->dblist);
+                       if (ext2fs_dblist_get_last(fs->dblist, &entry) ||
+                           (entry->ino != ino))
+                               pb.last_block--;
+                       else
+                               pb.last_block = entry->blockcnt;
+               }
+       }
+
        if (inode->i_flags & EXT2_INDEX_FL) {
                if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
                        inode->i_flags &= ~EXT2_INDEX_FL;
@@ -1583,7 +1603,9 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
 #endif
        if (pb.is_dir) {
                int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
-               if (nblock > (pb.last_block + 1))
+               if (inode->i_size & (fs->blocksize - 1)) 
+                       bad_size = 5;
+               else if (nblock > (pb.last_block + 1))
                        bad_size = 1;
                else if (nblock < (pb.last_block + 1)) {
                        if (((pb.last_block + 1) - nblock) >
@@ -1745,6 +1767,7 @@ static int process_block(ext2_filsys fs,
                        printf("Missing block (#%d) in directory inode %lu!\n",
                               blockcnt, p->ino);
 #endif
+                       p->last_block = blockcnt;
                        goto mark_dir;
                }
                return 0;
index 05e0cbbcc91c858b9e0be8ff793dcd7dd3c113a3..ad74fa6dae17e790f3745b65f84d72eb51f4f44d 100644 (file)
@@ -15,12 +15,19 @@ Directory inode 11 has an unallocated block #3.  Allocate? yes
 
 Directory inode 11 has an unallocated block #6.  Allocate? yes
 
-Directory inode 11 has an unallocated block #11.  Allocate? yes
-
 Pass 3: Checking directory connectivity
 Pass 4: Checking reference counts
 Pass 5: Checking group summary information
+Block bitmap differences:  -21
+Fix? yes
+
+Free blocks count wrong for group #0 (78, counted=79).
+Fix? yes
+
+Free blocks count wrong (78, counted=79).
+Fix? yes
+
 
 test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 11/32 files (9.1% non-contiguous), 22/100 blocks
+test_filesys: 11/32 files (9.1% non-contiguous), 21/100 blocks
 Exit status is 1
index a821f8783977506e99441b41a6821cece9c663cc..4c0b4f283fd81f513dd5fa14d8a4f4e943ce6769 100644 (file)
@@ -3,5 +3,5 @@ Pass 2: Checking directory structure
 Pass 3: Checking directory connectivity
 Pass 4: Checking reference counts
 Pass 5: Checking group summary information
-test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
+test_filesys: 11/32 files (0.0% non-contiguous), 21/100 blocks
 Exit status is 0