~csurbhi/ubuntu/maverick/e2fsprogs/e2fsprogs.fix-505719

« back to all changes in this revision

Viewing changes to e2fsck/pass1.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2008-08-08 20:32:11 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20080808203211-w72lpsd9q7o3bw6x
Tags: 1.41.0-3ubuntu1
* Merge from Debian unstable (LP: #254152, #246461), remaining changes:
  - Do not build-depend on dietlibc-dev, which is in universe.

Show diffs side-by-side

added added

removed removed

Lines of Context:
163
163
 * Check to make sure a symlink inode is real.  Returns 1 if the symlink
164
164
 * checks out, 0 if not.
165
165
 */
166
 
int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode,
167
 
                               char *buf)
 
166
int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino,
 
167
                               struct ext2_inode *inode, char *buf)
168
168
{
169
169
        unsigned int len;
170
170
        int i;
171
171
        blk_t   blocks;
 
172
        ext2_extent_handle_t    handle;
 
173
        struct ext2_extent_info info;
 
174
        struct ext2fs_extent    extent;
172
175
 
173
176
        if ((inode->i_size_high || inode->i_size == 0) ||
174
177
            (inode->i_flags & EXT2_INDEX_FL))
175
178
                return 0;
176
179
 
 
180
        if (inode->i_flags & EXT4_EXTENTS_FL) {
 
181
                if (inode->i_size > fs->blocksize)
 
182
                        return 0;
 
183
                if (ext2fs_extent_open(fs, ino, &handle))
 
184
                        return 0;
 
185
                i = 0;
 
186
                if (ext2fs_extent_get_info(handle, &info) ||
 
187
                    (info.num_entries != 1) ||
 
188
                    (info.max_depth != 0))
 
189
                        goto exit_extent;
 
190
                if (ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent) ||
 
191
                    (extent.e_lblk != 0) ||
 
192
                    (extent.e_len != 1) ||
 
193
                    (extent.e_pblk < fs->super->s_first_data_block) ||
 
194
                    (extent.e_pblk >= fs->super->s_blocks_count))
 
195
                        goto exit_extent;
 
196
                i = 1;
 
197
        exit_extent:
 
198
                ext2fs_extent_free(handle);
 
199
                return i;
 
200
        }
 
201
 
177
202
        blocks = ext2fs_inode_data_blocks(fs, inode);
178
203
        if (blocks) {
179
204
                if ((inode->i_size >= fs->blocksize) ||
264
289
        remain = storage_size - sizeof(__u32); 
265
290
 
266
291
        while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
 
292
                __u32 hash;
267
293
 
268
294
                /* header eats this space */
269
295
                remain -= sizeof(struct ext2_ext_attr_entry);
291
317
                        problem = PR_1_ATTR_VALUE_BLOCK;
292
318
                        goto fix;
293
319
                }
294
 
                
295
 
                /* e_hash must be 0 in inode's ea */
296
 
                if (entry->e_hash != 0) {
 
320
 
 
321
                hash = ext2fs_ext_attr_hash_entry(entry,
 
322
                                                  start + entry->e_value_offs);
 
323
 
 
324
                /* e_hash may be 0 in older inode's ea */
 
325
                if (entry->e_hash != 0 && entry->e_hash != hash) {
297
326
                        pctx->num = entry->e_hash;
298
327
                        problem = PR_1_ATTR_HASH;
299
328
                        goto fix;
308
337
         * it seems like a corruption. it's very unlikely we could repair
309
338
         * EA(s) in automatic fashion -bzzz
310
339
         */
311
 
#if 0
312
 
        problem = PR_1_ATTR_HASH;
313
 
#endif
314
340
        if (problem == 0 || !fix_problem(ctx, problem, pctx))
315
341
                return;
316
342
 
317
 
        /* simple remove all possible EA(s) */
 
343
        /* simply remove all possible EA(s) */
318
344
        *((__u32 *)start) = 0UL;
319
 
        e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *) inode,
 
345
        e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
320
346
                                EXT2_INODE_SIZE(sb), "pass1");
321
347
}
322
348
 
480
506
        struct          scan_callback_struct scan_struct;
481
507
        struct ext2_super_block *sb = ctx->fs->super;
482
508
        const char      *old_op;
483
 
        int             imagic_fs;
 
509
        int             imagic_fs, extent_fs;
484
510
        int             busted_fs_time = 0;
485
511
        int             inode_size;
486
512
        
487
513
#ifdef RESOURCE_TRACK
488
 
        init_resource_track(&rtrack);
 
514
        init_resource_track(&rtrack, ctx->fs->io);
489
515
#endif
490
516
        clear_problem_context(&pctx);
491
517
 
514
540
#undef EXT2_BPP
515
541
 
516
542
        imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
 
543
        extent_fs = (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS);
517
544
 
518
545
        /*
519
546
         * Allocate bitmaps structures
653
680
                                return;
654
681
                        }
655
682
                }
 
683
 
 
684
                /*
 
685
                 * Test for incorrect extent flag settings.
 
686
                 *
 
687
                 * On big-endian machines we must be careful:
 
688
                 * When the inode is read, the i_block array is not swapped
 
689
                 * if the extent flag is set.  Therefore if we are testing
 
690
                 * for or fixing a wrongly-set flag, we must potentially
 
691
                 * (un)swap before testing, or after fixing.
 
692
                 */
 
693
 
 
694
                /*
 
695
                 * In this case the extents flag was set when read, so
 
696
                 * extent_header_verify is ok.  If the inode is cleared,
 
697
                 * no need to swap... so no extra swapping here.
 
698
                 */
 
699
                if ((inode->i_flags & EXT4_EXTENTS_FL) && !extent_fs && 
 
700
                    (inode->i_links_count || (ino == EXT2_BAD_INO) ||
 
701
                     (ino == EXT2_ROOT_INO) || (ino == EXT2_JOURNAL_INO))) {
 
702
                        if ((ext2fs_extent_header_verify(inode->i_block, 
 
703
                                                 sizeof(inode->i_block)) == 0) &&
 
704
                            fix_problem(ctx, PR_1_EXTENT_FEATURE, &pctx)) {
 
705
                                sb->s_feature_incompat |= EXT3_FEATURE_INCOMPAT_EXTENTS;
 
706
                                ext2fs_mark_super_dirty(fs);
 
707
                                extent_fs = 1;
 
708
                        } else if (fix_problem(ctx, PR_1_EXTENTS_SET, &pctx)) {
 
709
                        clear_inode:
 
710
                                e2fsck_clear_inode(ctx, ino, inode, 0, "pass1");
 
711
                                if (ino == EXT2_BAD_INO)
 
712
                                        ext2fs_mark_inode_bitmap(ctx->inode_used_map, 
 
713
                                                                 ino);
 
714
                                continue;
 
715
                        }
 
716
                }
 
717
 
 
718
                /*
 
719
                 * For big-endian machines:
 
720
                 * If the inode didn't have the extents flag set when it
 
721
                 * was read, then the i_blocks array was swapped.  To test
 
722
                 * as an extents header, we must swap it back first.
 
723
                 * IF we then set the extents flag, the entire i_block
 
724
                 * array must be un/re-swapped to make it proper extents data.
 
725
                 */
 
726
                if (extent_fs && !(inode->i_flags & EXT4_EXTENTS_FL) &&
 
727
                    (inode->i_links_count || (ino == EXT2_BAD_INO) ||
 
728
                     (ino == EXT2_ROOT_INO) || (ino == EXT2_JOURNAL_INO)) &&
 
729
                    (LINUX_S_ISREG(inode->i_mode) ||
 
730
                     LINUX_S_ISDIR(inode->i_mode))) {
 
731
                        void *ehp;
 
732
#ifdef WORDS_BIGENDIAN
 
733
                        __u32 tmp_block[EXT2_N_BLOCKS];
 
734
 
 
735
                        for (i = 0; i < EXT2_N_BLOCKS; i++)
 
736
                                tmp_block[i] = ext2fs_swab32(inode->i_block[i]);
 
737
                        ehp = tmp_block;
 
738
#else
 
739
                        ehp = inode->i_block;
 
740
#endif
 
741
                        if ((ext2fs_extent_header_verify(ehp, 
 
742
                                         sizeof(inode->i_block)) == 0) &&
 
743
                            (fix_problem(ctx, PR_1_UNSET_EXTENT_FL, &pctx))) {
 
744
                                inode->i_flags |= EXT4_EXTENTS_FL;
 
745
#ifdef WORDS_BIGENDIAN
 
746
                                memcpy(inode->i_block, tmp_block, 
 
747
                                       sizeof(inode->i_block));
 
748
#endif
 
749
                                e2fsck_write_inode(ctx, ino, inode, "pass1");
 
750
                        }
 
751
                }
 
752
 
656
753
                if (ino == EXT2_BAD_INO) {
657
754
                        struct process_block_struct pb;
658
755
                        
695
792
                         * regnerated in pass #3.
696
793
                         */
697
794
                        if (!LINUX_S_ISDIR(inode->i_mode)) {
698
 
                                if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
699
 
                                        inode->i_dtime = ctx->now;
700
 
                                        inode->i_links_count = 0;
701
 
                                        ext2fs_icount_store(ctx->inode_link_info,
702
 
                                                            ino, 0);
703
 
                                        e2fsck_write_inode(ctx, ino, inode,
704
 
                                                           "pass1");
705
 
                                }
706
 
 
 
795
                                if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx))
 
796
                                        goto clear_inode;
707
797
                        }
708
798
                        /*
709
799
                         * If dtime is set, offer to clear it.  mke2fs
834
924
                        frag = inode->osd2.hurd2.h_i_frag;
835
925
                        fsize = inode->osd2.hurd2.h_i_fsize;
836
926
                        break;
837
 
                    case EXT2_OS_MASIX:
838
 
                        frag = inode->osd2.masix2.m_i_frag;
839
 
                        fsize = inode->osd2.masix2.m_i_fsize;
840
 
                        break;
841
927
                    default:
842
928
                        frag = fsize = 0;
843
929
                }
868
954
                check_inode_extra_space(ctx, &pctx);
869
955
                check_is_really_dir(ctx, &pctx, block_buf);
870
956
 
 
957
                /*
 
958
                 * ext2fs_inode_has_valid_blocks does not actually look
 
959
                 * at i_block[] values, so not endian-sensitive here.
 
960
                 */
 
961
                if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL) &&
 
962
                    LINUX_S_ISLNK(inode->i_mode) &&
 
963
                    !ext2fs_inode_has_valid_blocks(inode) &&
 
964
                    fix_problem(ctx, PR_1_FAST_SYMLINK_EXTENT_FL, &pctx)) {
 
965
                        inode->i_flags &= ~EXT4_EXTENTS_FL;
 
966
                        e2fsck_write_inode(ctx, ino, inode, "pass1");
 
967
                }
 
968
 
871
969
                if (LINUX_S_ISDIR(inode->i_mode)) {
872
970
                        ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
873
971
                        e2fsck_add_dir_info(ctx, ino, 0);
886
984
                        check_size(ctx, &pctx);
887
985
                        ctx->fs_blockdev_count++;
888
986
                } else if (LINUX_S_ISLNK (inode->i_mode) &&
889
 
                           e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
 
987
                           e2fsck_pass1_check_symlink(fs, ino, inode, 
 
988
                                                      block_buf)) {
890
989
                        check_immutable(ctx, &pctx);
891
990
                        ctx->fs_symlinks_count++;
892
991
                        if (ext2fs_inode_data_blocks(fs, inode) == 0) {
913
1012
                        ctx->fs_dind_count++;
914
1013
                if (inode->i_block[EXT2_TIND_BLOCK])
915
1014
                        ctx->fs_tind_count++;
916
 
                if (inode->i_block[EXT2_IND_BLOCK] ||
917
 
                    inode->i_block[EXT2_DIND_BLOCK] ||
918
 
                    inode->i_block[EXT2_TIND_BLOCK] ||
919
 
                    inode->i_file_acl) {
 
1015
                if (!(inode->i_flags & EXT4_EXTENTS_FL) &&
 
1016
                    (inode->i_block[EXT2_IND_BLOCK] ||
 
1017
                     inode->i_block[EXT2_DIND_BLOCK] ||
 
1018
                     inode->i_block[EXT2_TIND_BLOCK] ||
 
1019
                     inode->i_file_acl)) {
920
1020
                        inodes_to_process[process_inode_count].ino = ino;
921
1021
                        inodes_to_process[process_inode_count].inode = *inode;
922
1022
                        process_inode_count++;
1013
1113
#ifdef RESOURCE_TRACK
1014
1114
        if (ctx->options & E2F_OPT_TIME2) {
1015
1115
                e2fsck_clear_progbar(ctx);
1016
 
                print_resource_track(_("Pass 1"), &rtrack);
 
1116
                print_resource_track(_("Pass 1"), &rtrack, ctx->fs->io);
1017
1117
        }
1018
1118
#endif
1019
1119
}
1364
1464
        entry = (struct ext2_ext_attr_entry *)(header+1);
1365
1465
        end = block_buf + fs->blocksize;
1366
1466
        while ((char *)entry < end && *(__u32 *)entry) {
 
1467
                __u32 hash;
 
1468
 
1367
1469
                if (region_allocate(region, (char *)entry - (char *)header,
1368
1470
                                   EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
1369
1471
                        if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
1370
1472
                                goto clear_extattr;
 
1473
                        break;
1371
1474
                }
1372
1475
                if ((ctx->ext_attr_ver == 1 &&
1373
1476
                     (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
1375
1478
                     entry->e_name_index == 0)) {
1376
1479
                        if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
1377
1480
                                goto clear_extattr;
 
1481
                        break;
1378
1482
                }
1379
1483
                if (entry->e_value_block != 0) {
1380
1484
                        if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
1391
1495
                        if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
1392
1496
                                goto clear_extattr;
1393
1497
                }
 
1498
 
 
1499
                hash = ext2fs_ext_attr_hash_entry(entry, block_buf +
 
1500
                                                         entry->e_value_offs);
 
1501
 
 
1502
                if (entry->e_hash != hash) {
 
1503
                        pctx->num = entry->e_hash;
 
1504
                        if (fix_problem(ctx, PR_1_ATTR_HASH, pctx))
 
1505
                                goto clear_extattr;
 
1506
                        entry->e_hash = hash;
 
1507
                }
 
1508
 
1394
1509
                entry = EXT2_EXT_ATTR_NEXT(entry);
1395
1510
        }
1396
1511
        if (region_allocate(region, (char *)entry - (char *)header, 4)) {
1416
1531
 
1417
1532
/* Returns 1 if bad htree, 0 if OK */
1418
1533
static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
1419
 
                        ext2_ino_t ino EXT2FS_ATTR((unused)),
1420
 
                        struct ext2_inode *inode,
 
1534
                        ext2_ino_t ino, struct ext2_inode *inode,
1421
1535
                        char *block_buf)
1422
1536
{
1423
1537
        struct ext2_dx_root_info        *root;
1431
1545
             fix_problem(ctx, PR_1_HTREE_SET, pctx)))
1432
1546
                return 1;
1433
1547
 
1434
 
        blk = inode->i_block[0];
1435
 
        if (((blk == 0) ||
1436
 
             (blk < fs->super->s_first_data_block) ||
1437
 
             (blk >= fs->super->s_blocks_count)) &&
1438
 
            fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
1439
 
                return 1;
 
1548
        pctx->errcode = ext2fs_bmap(fs, ino, inode, 0, 0, 0, &blk);
 
1549
 
 
1550
        if ((pctx->errcode) ||
 
1551
            (blk == 0) ||
 
1552
            (blk < fs->super->s_first_data_block) ||
 
1553
            (blk >= fs->super->s_blocks_count)) {
 
1554
                if (fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
 
1555
                        return 1;
 
1556
                else
 
1557
                        return 0;
 
1558
        }
1440
1559
 
1441
1560
        retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
1442
1561
        if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
1468
1587
        return 0;
1469
1588
}
1470
1589
 
 
1590
void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino,
 
1591
                        struct ext2_inode *inode, int restart_flag,
 
1592
                        const char *source)
 
1593
{
 
1594
        inode->i_flags = 0;
 
1595
        inode->i_links_count = 0;
 
1596
        ext2fs_icount_store(ctx->inode_link_info, ino, 0);
 
1597
        inode->i_dtime = ctx->now;
 
1598
 
 
1599
        ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
 
1600
        ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
 
1601
        if (ctx->inode_reg_map)
 
1602
                ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
 
1603
        if (ctx->inode_bad_map)
 
1604
                ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
 
1605
 
 
1606
        /*
 
1607
         * If the inode was partially accounted for before processing
 
1608
         * was aborted, we need to restart the pass 1 scan.
 
1609
         */
 
1610
        ctx->flags |= restart_flag;
 
1611
 
 
1612
        e2fsck_write_inode(ctx, ino, inode, source);
 
1613
}
 
1614
 
 
1615
static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
 
1616
                             struct process_block_struct *pb,
 
1617
                             blk64_t start_block,
 
1618
                             ext2_extent_handle_t ehandle)
 
1619
{
 
1620
        struct ext2fs_extent    extent;
 
1621
        blk_t                   blk;
 
1622
        e2_blkcnt_t             blockcnt;
 
1623
        unsigned int            i;
 
1624
        int                     is_dir, is_leaf;
 
1625
        errcode_t               problem;
 
1626
        struct ext2_extent_info info;
 
1627
 
 
1628
        pctx->errcode = ext2fs_extent_get_info(ehandle, &info);
 
1629
        if (pctx->errcode)
 
1630
                return;
 
1631
 
 
1632
        pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_FIRST_SIB,
 
1633
                                          &extent);
 
1634
        while (!pctx->errcode && info.num_entries-- > 0) {
 
1635
                is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF;
 
1636
                is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
 
1637
 
 
1638
                problem = 0;
 
1639
                if (extent.e_pblk < ctx->fs->super->s_first_data_block ||
 
1640
                    extent.e_pblk >= ctx->fs->super->s_blocks_count)
 
1641
                        problem = PR_1_EXTENT_BAD_START_BLK;
 
1642
                else if (extent.e_lblk < start_block)
 
1643
                        problem = PR_1_OUT_OF_ORDER_EXTENTS;
 
1644
                else if (is_leaf &&
 
1645
                         (extent.e_pblk + extent.e_len) >
 
1646
                         ctx->fs->super->s_blocks_count)
 
1647
                        problem = PR_1_EXTENT_ENDS_BEYOND;
 
1648
 
 
1649
                if (problem) {
 
1650
                        pctx->blk = extent.e_pblk;
 
1651
                        pctx->blk2 = extent.e_lblk;
 
1652
                        pctx->num = extent.e_len;
 
1653
                        if (fix_problem(ctx, problem, pctx)) {
 
1654
                                pctx->errcode =
 
1655
                                        ext2fs_extent_delete(ehandle, 0);
 
1656
                                if (pctx->errcode) {
 
1657
                                        fix_problem(ctx,
 
1658
                                                    PR_1_EXTENT_DELETE_FAIL,
 
1659
                                                    pctx);
 
1660
                                        /* Should never get here */
 
1661
                                        ctx->flags |= E2F_FLAG_ABORT;
 
1662
                                        return;
 
1663
                                }
 
1664
                                pctx->errcode = ext2fs_extent_get(ehandle,
 
1665
                                                                  EXT2_EXTENT_CURRENT,
 
1666
                                                                  &extent);
 
1667
                                if (pctx->errcode == EXT2_ET_NO_CURRENT_NODE) {
 
1668
                                        pctx->errcode = 0;
 
1669
                                        break;
 
1670
                                }
 
1671
                                continue;
 
1672
                        }
 
1673
                        goto next;
 
1674
                }
 
1675
 
 
1676
                if (!is_leaf) {
 
1677
                        mark_block_used(ctx, extent.e_pblk);
 
1678
                        pb->num_blocks++;
 
1679
                        pctx->errcode = ext2fs_extent_get(ehandle,
 
1680
                                                  EXT2_EXTENT_DOWN, &extent);
 
1681
                        if (pctx->errcode) {
 
1682
                                printf("Error1: %s on inode %u\n",
 
1683
                                        error_message(pctx->errcode), pctx->ino);
 
1684
                                abort();
 
1685
                        }
 
1686
                        scan_extent_node(ctx, pctx, pb, extent.e_lblk, ehandle);
 
1687
                        pctx->errcode = ext2fs_extent_get(ehandle,
 
1688
                                                  EXT2_EXTENT_UP, &extent);
 
1689
                        if (pctx->errcode) {
 
1690
                                printf("Error1: %s on inode %u\n",
 
1691
                                        error_message(pctx->errcode), pctx->ino);
 
1692
                                abort();
 
1693
                        }
 
1694
                        goto next;
 
1695
                }
 
1696
 
 
1697
                for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0;
 
1698
                     i < extent.e_len;
 
1699
                     blk++, blockcnt++, i++) {
 
1700
                        mark_block_used(ctx, blk);
 
1701
 
 
1702
                        if (is_dir) {
 
1703
                                pctx->errcode = ext2fs_add_dir_block(ctx->fs->dblist, pctx->ino, blk, blockcnt);
 
1704
                                if (pctx->errcode) {
 
1705
                                        pctx->blk = blk;
 
1706
                                        pctx->num = blockcnt;
 
1707
                                        fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
 
1708
                                        /* Should never get here */
 
1709
                                        ctx->flags |= E2F_FLAG_ABORT;
 
1710
                                        return;
 
1711
                                }
 
1712
                        }
 
1713
                }
 
1714
                pb->num_blocks += extent.e_len;
 
1715
                start_block = pb->last_block = extent.e_lblk + extent.e_len - 1;
 
1716
        next:
 
1717
                pctx->errcode = ext2fs_extent_get(ehandle,
 
1718
                                                  EXT2_EXTENT_NEXT_SIB,
 
1719
                                                  &extent);
 
1720
        }
 
1721
        if (pctx->errcode == EXT2_ET_EXTENT_NO_NEXT)
 
1722
                pctx->errcode = 0;
 
1723
}
 
1724
 
 
1725
static void check_blocks_extents(e2fsck_t ctx, struct problem_context *pctx,
 
1726
                                 struct process_block_struct *pb)
 
1727
{
 
1728
        struct ext2_inode       *inode = pctx->inode;
 
1729
        ext2_extent_handle_t    ehandle;
 
1730
        ext2_filsys             fs = ctx->fs;
 
1731
        ext2_ino_t              ino = pctx->ino;
 
1732
 
 
1733
        pctx->errcode = ext2fs_extent_open(fs, ino, &ehandle);
 
1734
        if (pctx->errcode &&
 
1735
            fix_problem(ctx, PR_1_READ_EXTENT, pctx)) {
 
1736
                e2fsck_clear_inode(ctx, ino, inode, 0, "check_blocks_extents");
 
1737
                pctx->errcode = 0;
 
1738
                return;
 
1739
        }
 
1740
 
 
1741
        scan_extent_node(ctx, pctx, pb, 0, ehandle);
 
1742
 
 
1743
        ext2fs_extent_free(ehandle);
 
1744
}
 
1745
 
1471
1746
/*
1472
1747
 * This subroutine is called on each inode to account for all of the
1473
1748
 * blocks used by that inode.
1481
1756
        struct ext2_inode *inode = pctx->inode;
1482
1757
        int             bad_size = 0;
1483
1758
        int             dirty_inode = 0;
 
1759
        int             extent_fs;
1484
1760
        __u64           size;
1485
1761
        
1486
1762
        pb.ino = ino;
1500
1776
        pctx->ino = ino;
1501
1777
        pctx->errcode = 0;
1502
1778
 
 
1779
        extent_fs = (ctx->fs->super->s_feature_incompat &
 
1780
                     EXT3_FEATURE_INCOMPAT_EXTENTS);
 
1781
 
1503
1782
        if (inode->i_flags & EXT2_COMPRBLK_FL) {
1504
1783
                if (fs->super->s_feature_incompat &
1505
1784
                    EXT2_FEATURE_INCOMPAT_COMPRESSION)
1512
1791
                }
1513
1792
        }
1514
1793
 
1515
 
        if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
 
1794
        if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf)) {
 
1795
                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
 
1796
                        goto out;
1516
1797
                pb.num_blocks++;
 
1798
        }
1517
1799
 
1518
 
        if (ext2fs_inode_has_valid_blocks(inode))
1519
 
                pctx->errcode = ext2fs_block_iterate2(fs, ino,
1520
 
                                       pb.is_dir ? BLOCK_FLAG_HOLE : 0,
1521
 
                                       block_buf, process_block, &pb);
 
1800
        if (ext2fs_inode_has_valid_blocks(inode)) {
 
1801
                if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL))
 
1802
                        check_blocks_extents(ctx, pctx, &pb);
 
1803
                else
 
1804
                        pctx->errcode = ext2fs_block_iterate2(fs, ino,
 
1805
                                                pb.is_dir ? BLOCK_FLAG_HOLE : 0,
 
1806
                                                block_buf, process_block, &pb);
 
1807
        }
1522
1808
        end_problem_latch(ctx, PR_LATCH_BLOCK);
1523
1809
        end_problem_latch(ctx, PR_LATCH_TOOBIG);
1524
1810
        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
1530
1816
                ctx->fs_fragmented++;
1531
1817
 
1532
1818
        if (pb.clear) {
1533
 
                inode->i_links_count = 0;
1534
 
                ext2fs_icount_store(ctx->inode_link_info, ino, 0);
1535
 
                inode->i_dtime = ctx->now;
1536
 
                dirty_inode++;
1537
 
                ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
1538
 
                ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
1539
 
                ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
1540
 
                /*
1541
 
                 * The inode was probably partially accounted for
1542
 
                 * before processing was aborted, so we need to
1543
 
                 * restart the pass 1 scan.
1544
 
                 */
1545
 
                ctx->flags |= E2F_FLAG_RESTART;
1546
 
                goto out;
 
1819
                e2fsck_clear_inode(ctx, ino, inode, E2F_FLAG_RESTART,
 
1820
                                   "check_blocks");
 
1821
                return;
1547
1822
        }
1548
1823
        
1549
1824
        if (pb.is_dir) {
1583
1858
                
1584
1859
        if (!pb.num_blocks && pb.is_dir) {
1585
1860
                if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
1586
 
                        inode->i_links_count = 0;
1587
 
                        ext2fs_icount_store(ctx->inode_link_info, ino, 0);
1588
 
                        inode->i_dtime = ctx->now;
1589
 
                        dirty_inode++;
1590
 
                        ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
1591
 
                        ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
1592
 
                        ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
 
1861
                        e2fsck_clear_inode(ctx, ino, inode, 0, "check_blocks");
1593
1862
                        ctx->fs_directory_count--;
1594
 
                        goto out;
 
1863
                        return;
1595
1864
                }
1596
1865
        }
1597
1866
 
1598
 
        pb.num_blocks *= (fs->blocksize / 512);
 
1867
        if (!(fs->super->s_feature_ro_compat &
 
1868
              EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
 
1869
            !(inode->i_flags & EXT4_HUGE_FILE_FL))
 
1870
                pb.num_blocks *= (fs->blocksize / 512);
1599
1871
#if 0
1600
1872
        printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
1601
1873
               ino, inode->i_size, pb.last_block, inode->i_blocks,
1622
1894
                    (pb.last_block / blkpg * blkpg != pb.last_block ||
1623
1895
                     size < (__u64)(pb.last_block & ~(blkpg-1)) *fs->blocksize))
1624
1896
                        bad_size = 3;
1625
 
                else if (size > ext2_max_sizes[fs->super->s_log_block_size])
 
1897
                else if (!(extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) &&
 
1898
                         size > ext2_max_sizes[fs->super->s_log_block_size])
 
1899
                        /* too big for a direct/indirect-mapped file */
1626
1900
                        bad_size = 4;
 
1901
                else if ((extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) &&
 
1902
                         size > (1LL << (32 + fs->super->s_log_block_size) - 1))
 
1903
                        /* too big for an extent-based file - 32bit ee_block */
 
1904
                        bad_size = 6;
1627
1905
        }
1628
1906
        /* i_size for symlinks is checked elsewhere */
1629
1907
        if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
1639
1917
        if (LINUX_S_ISREG(inode->i_mode) &&
1640
1918
            (inode->i_size_high || inode->i_size & 0x80000000UL))
1641
1919
                ctx->large_files++;
1642
 
        if (pb.num_blocks != inode->i_blocks) {
 
1920
        if ((pb.num_blocks != inode->i_blocks) ||
 
1921
            ((fs->super->s_feature_ro_compat &
 
1922
              EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
 
1923
             (inode->i_flags & EXT4_HUGE_FILE_FL) &&
 
1924
             (inode->osd2.linux2.l_i_blocks_hi != 0))) {
1643
1925
                pctx->num = pb.num_blocks;
1644
1926
                if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
1645
1927
                        inode->i_blocks = pb.num_blocks;
 
1928
                        inode->osd2.linux2.l_i_blocks_hi = 0;
1646
1929
                        dirty_inode++;
1647
1930
                }
1648
1931
                pctx->num = 0;
2240
2523
        return 0;
2241
2524
}
2242
2525
 
 
2526
static errcode_t e2fsck_get_alloc_block(ext2_filsys fs, blk64_t goal,
 
2527
                                        blk64_t *ret)
 
2528
{
 
2529
        e2fsck_t ctx = (e2fsck_t) fs->priv_data;
 
2530
        errcode_t       retval;
 
2531
        blk_t           new_block;
 
2532
 
 
2533
        if (ctx->block_found_map) {
 
2534
                retval = ext2fs_new_block(fs, (blk_t) goal, 
 
2535
                                          ctx->block_found_map, &new_block);
 
2536
                if (retval)
 
2537
                        return retval;
 
2538
        } else {
 
2539
                if (!fs->block_map) {
 
2540
                        retval = ext2fs_read_block_bitmap(fs);
 
2541
                        if (retval)
 
2542
                                return retval;
 
2543
                }
 
2544
 
 
2545
                retval = ext2fs_new_block(fs, (blk_t) goal, 0, &new_block);
 
2546
                if (retval)
 
2547
                        return retval;
 
2548
        }
 
2549
                
 
2550
        *ret = new_block;
 
2551
        return (0);
 
2552
}
 
2553
 
 
2554
static void e2fsck_block_alloc_stats(ext2_filsys fs, blk64_t blk, int inuse)
 
2555
{
 
2556
        e2fsck_t ctx = (e2fsck_t) fs->priv_data;
 
2557
 
 
2558
        if (ctx->block_found_map) {
 
2559
                if (inuse > 0)
 
2560
                        ext2fs_mark_block_bitmap(ctx->block_found_map, 
 
2561
                                                 (blk_t) blk);
 
2562
                else
 
2563
                        ext2fs_unmark_block_bitmap(ctx->block_found_map, 
 
2564
                                                   (blk_t) blk);
 
2565
        }
 
2566
}
 
2567
 
2243
2568
void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
2244
2569
{
2245
2570
        ext2_filsys fs = ctx->fs;
2250
2575
                fs->read_inode = pass1_read_inode;
2251
2576
                fs->write_inode = pass1_write_inode;
2252
2577
                ctx->stashed_ino = 0;
 
2578
                ext2fs_set_alloc_block_callback(fs, e2fsck_get_alloc_block,
 
2579
                                                0);
 
2580
                ext2fs_set_block_alloc_stats_callback(fs,
 
2581
                                                      e2fsck_block_alloc_stats,
 
2582
                                                      0);
2253
2583
        } else {
2254
2584
                fs->get_blocks = 0;
2255
2585
                fs->check_directory = 0;