pass2.c revision a5abfe0382729fba2c5fea6aaae486cb8bc98f00
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass2.c --- check directory structure 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o 521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header% 721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * License. 921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header% 10efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 of e2fsck iterates through all active directory inodes, and 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * applies to following tests to each directory entry in the directory 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * blocks in the inodes: 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The length of the directory entry (rec_len) should be at 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * least 8 bytes, and no more than the remaining space 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * left in the directory block. 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The length of the name in the directory entry (name_len) 19efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * should be less than (rec_len - 8). 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode number in the directory entry should be within 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * legal bounds. 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode number should refer to a in-use inode. 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The first entry should be '.', and its inode should be 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * the inode of the directory. 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The second entry should be '..'. 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * To minimize disk seek time, the directory blocks are processed in 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * sorted order of block numbers. 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 also collects the following information: 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode numbers of the subdirectories for each directory. 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 relies on the following information from previous passes: 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The directory information collected in pass 1. 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_used_map bitmap 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_bad_map bitmap 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_dir_map bitmap 383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 frees the following data structures 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_bad_map bitmap 41aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * - The inode_reg_map bitmap 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 44b969b1b8a5c13992cadb026114731958644540d8Matthias Andree#define _GNU_SOURCE 1 /* get strnlen() */ 45d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h" 4648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#include <string.h> 4748e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 4921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h" 500926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o#include "dict.h" 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 52aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#ifdef NO_INLINE_FUNCS 53aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ 54aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#else 55aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ inline 56aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#endif 57aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 58ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o/* #define DX_DEBUG */ 598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Keeps track of how many times an inode is referenced. 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 634035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf); 64a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wongstatic int check_dir_block2(ext2_filsys fs, 65a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong struct ext2_db_entry2 *dir_blocks_info, 66a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong void *priv_data); 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs, 686dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *dir_blocks_info, 6954dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data); 701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx, 716dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *dir_blocks_info, 7221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o char *buf, struct problem_context *pctx); 738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino); 74ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir, 75ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o struct dx_dirblock_info *dx_db); 76ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b); 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ostruct check_dir_struct { 7921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o char *buf; 8021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 81f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o int count, max; 821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 83a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong unsigned long long list_offset; 84a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong unsigned long long ra_entries; 85a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong unsigned long long next_ra_off; 86efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o}; 8721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 8808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass2(e2fsck_t ctx) 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 90a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o struct ext2_super_block *sb = ctx->fs->super; 91a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o struct problem_context pctx; 92a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2_filsys fs = ctx->fs; 93a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o char *buf; 948bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct resource_track rtrack; 968bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 9721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct check_dir_struct cd; 988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir; 998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db, *dx_parent; 100830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o unsigned int save_type; 101544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int b; 102ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int i, depth; 1038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o problem_t code; 1048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o int bad_dir; 105a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong int (*check_dir_func)(ext2_filsys fs, 106a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong struct ext2_db_entry2 *dir_blocks_info, 107a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong void *priv_data); 1088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1096d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o init_resource_track(&rtrack, ctx->fs->io); 1101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&cd.pctx); 1111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o mtrace_print("Pass 2"); 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ctx->options & E2F_OPT_PREEN)) 1171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx); 1181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 119efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT, 12034b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o &ctx->inode_count); 12134b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o if (ctx->inode_count) 12234b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o cd.pctx.errcode = 0; 123830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o else { 124830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE, 125830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o "inode_count", &save_type); 126efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o cd.pctx.errcode = ext2fs_create_icount2(fs, 12734b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o EXT2_ICOUNT_OPT_INCREMENT, 1281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 0, ctx->inode_link_info, 1291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &ctx->inode_count); 130830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o fs->default_bitmap_type = save_type; 131830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o } 1321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd.pctx.errcode) { 1331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx); 13408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 13508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 13621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 137bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize, 13854dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o "directory scan buffer"); 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 14021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o /* 14121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Set up the parent pointer for the root directory, if 14221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * present. (If the root directory is not present, we will 14321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * create it in pass 3.) 14421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 14528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o (void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); 14621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 14721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd.buf = buf; 1481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd.ctx = ctx; 149f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o cd.count = 1; 1506dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson cd.max = ext2fs_dblist_count2(fs->dblist); 151a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd.list_offset = 0; 152a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd.ra_entries = ctx->readahead_kb * 1024 / ctx->fs->blocksize; 153a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd.next_ra_off = 0; 154f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o 155f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o if (ctx->progress) 156f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o (void) (ctx->progress)(ctx, 2, 0, cd.max); 157ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 158ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) 1596dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp); 160efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 161a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong check_dir_func = cd.ra_entries ? check_dir_block2 : check_dir_block; 162a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_func, 1636dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson &cd); 16449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) 16508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1666267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger 1676267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger if (ctx->flags & E2F_FLAG_RESTART_LATER) { 1686267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger ctx->flags |= E2F_FLAG_RESTART; 1696267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger return; 1706267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger } 1716267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger 1721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd.pctx.errcode) { 1731b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx); 17408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 17508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1767ac02a5ebddcc6187c893eedc80d92777b399575Theodore Ts'o } 1778fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1788fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 1798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) { 1804cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 1814cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return; 182d02d019557d993c8dfe2f7d0fea841101f0d9e61Darrick J. Wong if (e2fsck_dir_will_be_rehashed(ctx, dx_dir->ino) || 183d02d019557d993c8dfe2f7d0fea841101f0d9e61Darrick J. Wong dx_dir->numblocks == 0) 1848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 1858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o clear_problem_context(&pctx); 1868fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir = 0; 1878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.dir = dx_dir->ino; 1888fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = dx_dir->dx_block; 1898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_REFERENCED) 1908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_DUP_REF; 1918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o else 1928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_REFERENCED; 1938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * Find all of the first and last leaf blocks, and 1958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * update their parent's min and max hash values 1968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (b=0, dx_db = dx_dir->dx_block; 1988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b < dx_dir->numblocks; 1998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b++, dx_db++) { 2008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if ((dx_db->type != DX_DIRBLOCK_LEAF) || 2018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST))) 2028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 2038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent = &dx_dir->dx_block[dx_db->parent]; 2048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 2058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * XXX Make sure dx_parent->min_hash > dx_db->min_hash 2068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 2078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_FIRST) 2088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent->min_hash = dx_db->min_hash; 2098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 2108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * XXX Make sure dx_parent->max_hash < dx_db->max_hash 2118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 2128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_LAST) 2138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent->max_hash = dx_db->max_hash; 2148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 215efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (b=0, dx_db = dx_dir->dx_block; 2178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b < dx_dir->numblocks; 2188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b++, dx_db++) { 2198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blkcount = b; 2208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.group = dx_db->parent; 2218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = 0; 2228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (!(dx_db->flags & DX_FLAG_FIRST) && 2238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->min_hash < dx_db->node_min_hash)) { 2248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk = dx_db->min_hash; 2258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk2 = dx_db->node_min_hash; 2268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_MIN_HASH; 2278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 230ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (dx_db->type == DX_DIRBLOCK_LEAF) { 231ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o depth = htree_depth(dx_dir, dx_db); 232ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (depth != dx_dir->depth) { 233e5e12db959d3c18f6cf4ac938a14f68be0a89accAndreas Dilger pctx.num = dx_dir->depth; 234ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o code = PR_2_HTREE_BAD_DEPTH; 235ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o fix_problem(ctx, code, &pctx); 236ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o bad_dir++; 237ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 238ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 2398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 240efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * This test doesn't apply for the root block 2418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * at block #0 2428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 2438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (b && 2448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->max_hash > dx_db->node_max_hash)) { 2458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk = dx_db->max_hash; 2468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk2 = dx_db->node_max_hash; 2478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_MAX_HASH; 2488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 249503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o bad_dir++; 2508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (!(dx_db->flags & DX_FLAG_REFERENCED)) { 2528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_NOTREF; 2538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2558fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else if (dx_db->flags & DX_FLAG_DUP_REF) { 2568fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_DUPREF; 2578fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2618fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) { 2628fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o clear_htree(ctx, dx_dir->ino); 26362acaa1de132a808949d71264731bba7fe095705Theodore Ts'o dx_dir->numblocks = 0; 2648fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 26623f75f6efaac6b756e0f3e4e1d33b6798347f66aTheodore Ts'o e2fsck_free_dx_dir_info(ctx); 2678fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 268c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&buf); 26921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ext2fs_free_dblist(fs->dblist); 27021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 2711b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ctx->inode_bad_map) { 2721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_bad_map); 2731b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->inode_bad_map = 0; 2743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 275aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (ctx->inode_reg_map) { 276aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_reg_map); 277aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ctx->inode_reg_map = 0; 278aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } 279dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o if (ctx->encrypted_dirs) { 280dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o ext2fs_u32_list_free(ctx->encrypted_dirs); 281dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o ctx->encrypted_dirs = 0; 282dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o } 283a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 284a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o clear_problem_context(&pctx); 285a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (ctx->large_files) { 286a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (!(sb->s_feature_ro_compat & 287a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE) && 288a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) { 289a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o sb->s_feature_ro_compat |= 290a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE; 2910cfce7f749ea519522929d91e705cf90518594c4Theodore Ts'o fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 292a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 293a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 294a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (sb->s_rev_level == EXT2_GOOD_OLD_REV && 295a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) { 296a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_update_dynamic_rev(fs); 297a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 298a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 299a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 300efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 3019facd076ae8af6e908e228392cea866ce0faf1bcKen Chen print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io); 3023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 3033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 304ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o#define MAX_DEPTH 32000 305ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir, 306ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o struct dx_dirblock_info *dx_db) 307ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o{ 308ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int depth = 0; 309ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 310ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) { 311ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_db = &dx_dir->dx_block[dx_db->parent]; 312ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o depth++; 313ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 314ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return depth; 315ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o} 316ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 3170926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'ostatic int dict_de_cmp(const void *a, const void *b) 3180926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o{ 319520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o const struct ext2_dir_entry *de_a, *de_b; 3200926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o int a_len, b_len; 3210926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 322520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o de_a = (const struct ext2_dir_entry *) a; 32370f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara a_len = ext2fs_dirent_name_len(de_a); 324520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o de_b = (const struct ext2_dir_entry *) b; 32570f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara b_len = ext2fs_dirent_name_len(de_b); 3260926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 3270926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (a_len != b_len) 3280926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return (a_len - b_len); 3290926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 330baa14bd17fb7f83b8f95e32318a7319a762ce000Theodore Ts'o return memcmp(de_a->name, de_b->name, a_len); 3310926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o} 332ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 3333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 334ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This is special sort function that makes sure that directory blocks 335ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * with a dirblock of zero are sorted to the beginning of the list. 336ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This guarantees that the root node of the htree directories are 337ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * processed first, so we know what hash version to use. 338ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o */ 339ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b) 340ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o{ 3416dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson const struct ext2_db_entry2 *db_a = 3426dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson (const struct ext2_db_entry2 *) a; 3436dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson const struct ext2_db_entry2 *db_b = 3446dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson (const struct ext2_db_entry2 *) b; 345ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 346ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->blockcnt && !db_b->blockcnt) 347ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return 1; 348ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 349ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (!db_a->blockcnt && db_b->blockcnt) 350ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return -1; 351efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 352ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->blk != db_b->blk) 353ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->blk - db_b->blk); 354efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 355ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->ino != db_b->ino) 356ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->ino - db_b->ino); 357ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 358ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->blockcnt - db_b->blockcnt); 359ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o} 360ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 361ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 362ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o/* 3633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the first entry in the directory is '.', and that the 3643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane. 3653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 3661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dot(e2fsck_t ctx, 3673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 36886c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino, struct problem_context *pctx) 3693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *nextdir; 3718a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len, new_len; 3723c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o int status = 0; 3733c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o int created = 0; 3743c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o problem_t problem = 0; 375efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 37621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode) 37721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_MISSING_DOT; 37870f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara else if ((ext2fs_dirent_name_len(dirent) != 1) || 37921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[0] != '.')) 38021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_1ST_NOT_DOT; 38121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else if (dirent->name[1] != '\0') 38221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_DOT_NULL_TERM; 3835dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o 3848a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); 38521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (problem) { 3861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, pctx)) { 3875dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len < 12) 3885dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o rec_len = dirent->rec_len = 12; 3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = ino; 39070f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_name_len(dirent, 1); 39170f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN); 3923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[0] = '.'; 39321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->name[1] = '\0'; 3943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o created = 1; 3963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dirent->inode != ino) { 3991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) { 4003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = ino; 4013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 40221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 4033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4045dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len > 12) { 4055dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o new_len = rec_len - 12; 4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (new_len > 12) { 4073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (created || 408f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) { 4093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir = (struct ext2_dir_entry *) 4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ((char *) dirent + 12); 4113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->rec_len = 12; 4128a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(ctx->fs, new_len, 4138a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o nextdir); 4143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir->inode = 0; 41570f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_name_len(nextdir, 0); 41670f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_file_type(nextdir, 41770f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara EXT2_FT_UNKNOWN); 4183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 4193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return status; 4233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the second entry in the directory is '..', and that the 4273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane. We do not check the inode number of '..' 4283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * here; this gets done in pass 3. 4293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dotdot(e2fsck_t ctx, 4313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 43228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t ino, struct problem_context *pctx) 4333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4343c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o problem_t problem = 0; 435cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger unsigned int rec_len; 436efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 43721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode) 43821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_MISSING_DOT_DOT; 43970f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara else if ((ext2fs_dirent_name_len(dirent) != 2) || 44021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[0] != '.') || 44121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[1] != '.')) 44221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_2ND_NOT_DOT_DOT; 44321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else if (dirent->name[2] != '\0') 44421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_DOT_DOT_NULL_TERM; 44521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 4468a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); 44721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (problem) { 4481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, pctx)) { 4495dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len < 12) 45021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->rec_len = 12; 4513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Note: we don't have the parent inode just 4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * yet, so we will fill it in with the root 4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * inode. This will get fixed in pass 3. 4553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = EXT2_ROOT_INO; 45770f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_name_len(dirent, 2); 45870f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN); 4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[0] = '.'; 4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[1] = '.'; 46121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->name[2] = '\0'; 4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 463efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o } 4643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 46628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) { 46728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o fix_problem(ctx, PR_2_NO_DIRINFO, pctx); 46828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o return -1; 46928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 4703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Check to make sure a directory entry doesn't contain any illegal 4753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * characters. 4763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4771b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_name(e2fsck_t ctx, 4783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 479dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o ext2_ino_t dir_ino, 480544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 4813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 4833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int fixup = -1; 4843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int ret = 0; 485efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 48670f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara for ( i = 0; i < ext2fs_dirent_name_len(dirent); i++) { 487dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o if (dirent->name[i] != '/' && dirent->name[i] != '\0') 488dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o continue; 489dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o if (fixup < 0) 490dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); 491dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o if (fixup == 0) 492dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o return 0; 493dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o dirent->name[i] = '.'; 494dbff534ec685ea0815544746558dbd3e31284912Theodore Ts'o ret = 1; 4953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ret; 4973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 499aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o/* 500aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * Check the directory filetype (if present) 501aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o */ 502aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'ostatic _INLINE_ int check_filetype(e2fsck_t ctx, 503544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct ext2_dir_entry *dirent, 504544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ext2_ino_t dir_ino EXT2FS_ATTR((unused)), 505544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 506aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o{ 50770f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara int filetype = ext2fs_dirent_file_type(dirent); 508aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o int should_be = EXT2_FT_UNKNOWN; 509aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o struct ext2_inode inode; 510aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 511aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (!(ctx->fs->super->s_feature_incompat & 5127847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o EXT2_FEATURE_INCOMPAT_FILETYPE)) { 5137847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o if (filetype == 0 || 5147847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx)) 5157847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o return 0; 51670f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN); 5177847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o return 1; 5187847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o } 519aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 520c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) { 521aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = EXT2_FT_DIR; 522c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson } else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map, 523aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->inode)) { 524aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = EXT2_FT_REG_FILE; 525aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } else if (ctx->inode_bad_map && 526c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_test_inode_bitmap2(ctx->inode_bad_map, 527aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->inode)) 528aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = 0; 529aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o else { 530aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o e2fsck_read_inode(ctx, dirent->inode, &inode, 531aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o "check_filetype"); 5326fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o should_be = ext2_file_type(inode.i_mode); 533aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } 534aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (filetype == should_be) 535aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 0; 536aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o pctx->num = should_be; 537aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 538aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE, 539aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o pctx) == 0) 540aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 0; 541efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 54270f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_file_type(dirent, should_be); 543aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 1; 544aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o} 545aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 5468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 5478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void parse_int_node(ext2_filsys fs, 5486dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 5498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct check_dir_struct *cd, 5508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir, 55107307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong char *block_buf, int failed_csum) 5528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{ 5538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_root_info *root; 5548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_entry *ent; 5558fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_countlimit *limit; 5568fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db; 557ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int i, expect_limit, count; 5588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o blk_t blk; 5598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t min_hash = 0xffffffff; 5608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t max_hash = 0; 561ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o ext2_dirhash_t hash = 0, prev_hash; 56207307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong int csum_size = 0; 5638fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5648fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt == 0) { 5658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o root = (struct ext2_dx_root_info *) (block_buf + 24); 566efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 5678fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 5688fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("Root node dump:\n"); 5698deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("\t Reserved zero: %u\n", root->reserved_zero); 5708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Hash Version: %d\n", root->hash_version); 5718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Info length: %d\n", root->info_length); 5728fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Indirect levels: %d\n", root->indirect_levels); 5738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Flags: %d\n", root->unused_flags); 5748fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length); 57707307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong 57807307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong if (failed_csum && 57907307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong (e2fsck_dir_will_be_rehashed(cd->ctx, cd->pctx.ino) || 58007307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong fix_problem(cd->ctx, PR_2_HTREE_ROOT_CSUM_INVALID, 58107307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong &cd->pctx))) 58207307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong goto clear_and_exit; 5838fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else { 5848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ent = (struct ext2_dx_entry *) (block_buf+8); 58507307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong 58607307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong if (failed_csum && 58707307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong (e2fsck_dir_will_be_rehashed(cd->ctx, cd->pctx.ino) || 58807307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong fix_problem(cd->ctx, PR_2_HTREE_NODE_CSUM_INVALID, 58907307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong &cd->pctx))) 59007307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong goto clear_and_exit; 5918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 59207307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong 5938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o limit = (struct ext2_dx_countlimit *) ent; 5948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 596efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o printf("Number of entries (count): %d\n", 5978132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le16_to_cpu(limit->count)); 598efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o printf("Number of entries (limit): %d\n", 5998132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le16_to_cpu(limit->limit)); 6008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 6018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 6028132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o count = ext2fs_le16_to_cpu(limit->count); 60307307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 60407307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) 60507307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong csum_size = sizeof(struct ext2_dx_tail); 60607307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong expect_limit = (fs->blocksize - 60707307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong (csum_size + ((char *) ent - block_buf))) / 60807307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong sizeof(struct ext2_dx_entry); 6098132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) { 6108132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o cd->pctx.num = ext2fs_le16_to_cpu(limit->limit); 611ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx)) 612ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 613ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 6148132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if (count > expect_limit) { 6158132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o cd->pctx.num = count; 616ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx)) 617ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 618ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o count = expect_limit; 619ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 620efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 621ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o for (i=0; i < count; i++) { 622ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o prev_hash = hash; 6238132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0; 6248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 6258deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("Entry #%d: Hash 0x%08x, block %u\n", i, 6268132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o hash, ext2fs_le32_to_cpu(ent[i].block)); 6278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 6288132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff; 6298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* Check to make sure the block is valid */ 630977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o if (blk >= (blk_t) dx_dir->numblocks) { 631b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o cd->pctx.blk = blk; 6328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK, 633ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o &cd->pctx)) 634ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 635977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o continue; 6368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 637ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (hash < prev_hash && 638ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx)) 639ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 6408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[blk]; 6418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_REFERENCED) { 6428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_DUP_REF; 6438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else { 6448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_REFERENCED; 6458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->parent = db->blockcnt; 6468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash < min_hash) 6488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o min_hash = hash; 6498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash > max_hash) 6508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o max_hash = hash; 6518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->node_min_hash = hash; 6528132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if ((i+1) < count) 653efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o dx_db->node_max_hash = 6548132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le32_to_cpu(ent[i+1].hash) & ~1; 6558fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o else { 6568fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->node_max_hash = 0xfffffffe; 6578fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_LAST; 6588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (i == 0) 6608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_FIRST; 6618fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6628fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 6638fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n", 6648fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o db->blockcnt, min_hash, max_hash); 6658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 6668fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[db->blockcnt]; 6678fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = min_hash; 6688fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = max_hash; 669ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 670ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 671ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'oclear_and_exit: 672ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o clear_htree(cd->ctx, cd->pctx.ino); 673ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_dir->numblocks = 0; 67407307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong e2fsck_rehash_dir_later(cd->ctx, cd->pctx.ino); 6758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o} 6768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 677aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 678e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o/* 679e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Given a busted directory, try to salvage it somehow. 680efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 681e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 682ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic void salvage_directory(ext2_filsys fs, 683e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *dirent, 684e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *prev, 68582ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong unsigned int *offset, 68682ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong unsigned int block_len) 687e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o{ 688e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o char *cp = (char *) dirent; 6898a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o int left; 6908a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len, prev_rec_len; 6914a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong unsigned int name_len; 692e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o 6934a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong /* 6944a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong * If the space left for the entry is too small to be an entry, 6954a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong * we can't access dirent's fields, so plumb in the values needed 6964a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong * so that the previous entry absorbs this one. 6974a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong */ 6984a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong if (block_len - *offset < EXT2_DIR_ENTRY_HEADER_LEN) { 6994a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong name_len = 0; 7004a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong rec_len = block_len - *offset; 7014a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong } else { 7024a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong name_len = ext2fs_dirent_name_len(dirent); 7034a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 7044a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong } 70582ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong left = block_len - *offset - rec_len; 7065dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o 707e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 708e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Special case of directory entry of size 8: copy what's left 709e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * of the directory block up to cover up the invalid hole. 710e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 7114a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong if ((left >= 12) && (rec_len == EXT2_DIR_ENTRY_HEADER_LEN)) { 7124a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong memmove(cp, cp+EXT2_DIR_ENTRY_HEADER_LEN, left); 7134a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong memset(cp + left, 0, EXT2_DIR_ENTRY_HEADER_LEN); 714ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 715ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 716ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o /* 717ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * If the directory entry overruns the end of the directory 718ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * block, and the name is small enough to fit, then adjust the 719ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * record length. 720ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o */ 721ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if ((left < 0) && 7224a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong ((int) rec_len + left > EXT2_DIR_ENTRY_HEADER_LEN) && 7234a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong ((int) name_len + EXT2_DIR_ENTRY_HEADER_LEN <= (int) rec_len + left) && 724ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dirent->inode <= fs->super->s_inodes_count && 725ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o strnlen(dirent->name, name_len) == name_len) { 7268a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent); 727ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 728e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 729e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 730575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * If the record length of the directory entry is a multiple 731575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * of four, and not too big, such that it is valid, let the 732575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * previous directory entry absorb the invalid one. 733e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 7345dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (prev && rec_len && (rec_len % 4) == 0 && 73582ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong (*offset + rec_len <= block_len)) { 7368a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len); 7378a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o prev_rec_len += rec_len; 7388a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, prev_rec_len, prev); 7395dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o *offset += rec_len; 740ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 741e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 742e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 743e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Default salvage method --- kill all of the directory 744e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * entries for the rest of the block. We will either try to 745e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * absorb it into the previous directory entry, or create a 746e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * new empty directory entry the rest of the directory block. 747e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 748e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if (prev) { 7498a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len); 75082ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong prev_rec_len += block_len - *offset; 7518a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, prev_rec_len, prev); 752ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o *offset = fs->blocksize; 753e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else { 75482ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong rec_len = block_len - *offset; 7558a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, rec_len, dirent); 75670f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_name_len(dirent, 0); 75770f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN); 758e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dirent->inode = 0; 759e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 760e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o} 761e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o 762d3eb1502fd07a4c751d20ad5fa4b75bfda039d52Darrick J. Wong#define NEXT_DIRENT(d) ((void *)((char *)(d) + (d)->rec_len)) 76317641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wongstatic errcode_t insert_dirent_tail(ext2_filsys fs, void *dirbuf) 76417641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong{ 76517641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong struct ext2_dir_entry *d; 76617641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong void *top; 76717641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong struct ext2_dir_entry_tail *t; 76817641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong 76917641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong d = dirbuf; 77017641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong top = EXT2_DIRENT_TAIL(dirbuf, fs->blocksize); 77117641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong 772d3eb1502fd07a4c751d20ad5fa4b75bfda039d52Darrick J. Wong while (d->rec_len && !(d->rec_len & 0x3) && NEXT_DIRENT(d) <= top) 773d3eb1502fd07a4c751d20ad5fa4b75bfda039d52Darrick J. Wong d = NEXT_DIRENT(d); 77417641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong 77517641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong if (d != top) { 77617641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong size_t min_size = EXT2_DIR_REC_LEN( 77717641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong ext2fs_dirent_name_len(dirbuf)); 778d3eb1502fd07a4c751d20ad5fa4b75bfda039d52Darrick J. Wong if (min_size > top - (void *)d) 77917641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 780d3eb1502fd07a4c751d20ad5fa4b75bfda039d52Darrick J. Wong d->rec_len = top - (void *)d; 78117641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong } 78217641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong 78317641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong t = (struct ext2_dir_entry_tail *)top; 78417641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong if (t->det_reserved_zero1 || 78517641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong t->det_rec_len != sizeof(struct ext2_dir_entry_tail) || 78617641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong t->det_reserved_name_len != EXT2_DIR_NAME_LEN_CSUM) 78717641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong ext2fs_initialize_dirent_tail(fs, t); 78817641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong 78917641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong return 0; 79017641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong} 791d3eb1502fd07a4c751d20ad5fa4b75bfda039d52Darrick J. Wong#undef NEXT_DIRENT 79217641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong 79352b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wongstatic errcode_t fix_inline_dir_size(e2fsck_t ctx, ext2_ino_t ino, 79452b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong size_t *inline_data_size, 79552b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong struct problem_context *pctx, 79652b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong char *buf) 79752b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong{ 79852b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong ext2_filsys fs = ctx->fs; 79952b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong struct ext2_inode inode; 80052b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong size_t new_size, old_size; 80152b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong errcode_t retval; 80252b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong 80352b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong old_size = *inline_data_size; 8040ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong /* 8050ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong * If there's not enough bytes to start the "second" dir block 8060ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong * (in the EA space) then truncate everything to the first block. 8070ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong */ 8080ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (old_size > EXT4_MIN_INLINE_DATA_SIZE && 8090ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong old_size < EXT4_MIN_INLINE_DATA_SIZE + 8100ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong EXT2_DIR_REC_LEN(1)) { 8110ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong old_size = EXT4_MIN_INLINE_DATA_SIZE; 8120ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong new_size = old_size; 8130ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong } else 8140ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong /* Increase to the next four-byte boundary for salvaging */ 8150ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong new_size = old_size + (4 - (old_size & 3)); 81652b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong memset(buf + old_size, 0, new_size - old_size); 81752b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong retval = ext2fs_inline_data_set(fs, ino, 0, buf, new_size); 81852b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (retval == EXT2_ET_INLINE_DATA_NO_SPACE) { 8190ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong /* Or we can't, so truncate. */ 82052b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong new_size -= 4; 82152b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong retval = ext2fs_inline_data_set(fs, ino, 0, buf, new_size); 82252b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (retval) { 82352b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (fix_problem(ctx, PR_2_FIX_INLINE_DIR_FAILED, 82452b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong pctx)) { 82552b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong new_size = 0; 82652b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong goto write_inode; 82752b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong } 82852b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong goto err; 82952b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong } 83052b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong } else if (retval) { 83152b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (fix_problem(ctx, PR_2_FIX_INLINE_DIR_FAILED, 83252b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong pctx)) { 83352b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong new_size = 0; 83452b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong goto write_inode; 83552b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong } 83652b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong goto err; 83752b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong } 83852b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong 83952b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wongwrite_inode: 84052b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong retval = ext2fs_read_inode(fs, ino, &inode); 84152b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (retval) 84252b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong goto err; 84352b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong 84452b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong retval = ext2fs_inode_size_set(fs, &inode, new_size); 84552b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (retval) 84652b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong goto err; 84752b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (new_size == 0) 84852b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong inode.i_flags &= ~EXT4_INLINE_DATA_FL; 84952b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong retval = ext2fs_write_inode(fs, ino, &inode); 85052b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (retval) 85152b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong goto err; 85252b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong *inline_data_size = new_size; 85352b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong 85452b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wongerr: 85552b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong return retval; 85652b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong} 85752b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong 85862ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'oint get_filename_hash(ext2_filsys fs, int encrypted, int version, 85962ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o const char *name, int len, ext2_dirhash_t *ret_hash, 86062ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o ext2_dirhash_t *ret_minor_hash) 86162ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o{ 86262ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o char buf[2*EXT2FS_DIGEST_SIZE]; 86362ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o int buf_len; 86462ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o 86562ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o if (!encrypted) 86662ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o return ext2fs_dirhash(version, name, len, 86762ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o fs->super->s_hash_seed, 86862ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o ret_hash, ret_minor_hash); 86962ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o 87062ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o if (len <= EXT2FS_DIGEST_SIZE) 87162ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o buf_len = ext2fs_digest_encode(name, len, buf); 87262ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o else { 87362ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o ext2fs_sha256(name, len, buf + EXT2FS_DIGEST_SIZE); 87462ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o buf[0] = 'I'; 87562ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o buf_len = ext2fs_digest_encode(buf + EXT2FS_DIGEST_SIZE, 87662ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o EXT2FS_DIGEST_SIZE, buf + 1); 87762ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o buf_len++; 87862ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o } 87962ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o return ext2fs_dirhash(version, buf, buf_len, 88062ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o fs->super->s_hash_seed, 88162ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o ret_hash, ret_minor_hash); 88262ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o} 88362ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o 884a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wongstatic int check_dir_block2(ext2_filsys fs, 885a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong struct ext2_db_entry2 *db, 886a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong void *priv_data) 887a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong{ 888a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong int err; 889a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong struct check_dir_struct *cd = priv_data; 890a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong 891a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong if (cd->ra_entries && cd->list_offset >= cd->next_ra_off) { 892a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong err = e2fsck_readahead_dblist(fs, 893a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong E2FSCK_RA_DBLIST_IGNORE_BLOCKCNT, 894a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong fs->dblist, 895a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd->list_offset + cd->ra_entries / 8, 896a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd->ra_entries); 897a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong if (err) 898a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd->ra_entries = 0; 899a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd->next_ra_off = cd->list_offset + (cd->ra_entries * 7 / 8); 900a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong } 901a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong 902a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong err = check_dir_block(fs, db, priv_data); 903a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong cd->list_offset++; 904a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong return err; 905a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong} 906a5abfe0382729fba2c5fea6aaae486cb8bc98f00Darrick J. Wong 9073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs, 9086dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 90954dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 9103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 9118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir; 9128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 9138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db = 0; 9148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 9156582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu struct ext2_dir_entry *dirent, *prev, dot, dotdot; 9168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t hash; 917544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 9183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dir_modified = 0; 91921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int dot_state; 92003fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o unsigned int rec_len; 9216dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t block_nr = db->blk; 92286c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino = db->ino; 92328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t subdir_parent; 92421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o __u16 links; 92554dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct check_dir_struct *cd; 9260ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong char *buf, *ibuf; 9271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 9283c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o problem_t problem; 929ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o struct ext2_dx_root_info *root; 930e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o struct ext2_dx_countlimit *limit; 9310926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o static dict_t de_dict; 9320926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o struct problem_context pctx; 9330926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o int dups_found = 0; 93428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o int ret; 935e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong int dx_csum_size = 0, de_csum_size = 0; 93681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong int failed_csum = 0; 937e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong int is_leaf = 1; 93824997f1cd2b3c3ea7a5a2c7fe37013de36a6d8a3Darrick J. Wong size_t inline_data_size = 0; 9396582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu int filetype = 0; 94062ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o int encrypted = 0; 9410ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong size_t max_block_size; 9421b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 94354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o cd = (struct check_dir_struct *) priv_data; 9440ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong ibuf = buf = cd->buf; 9451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx = cd->ctx; 946f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 94749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) 9484cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return DIRENT_ABORT; 949efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 9504cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max)) 9514cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return DIRENT_ABORT; 952efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 95307307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 954e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { 95507307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong dx_csum_size = sizeof(struct ext2_dx_tail); 956e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong de_csum_size = sizeof(struct ext2_dir_entry_tail); 957e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong } 95807307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong 9596582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, 9606582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu EXT2_FEATURE_INCOMPAT_FILETYPE)) 9616582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu filetype = EXT2_FT_DIR << 8; 9626582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu 9633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 964efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Make sure the inode is still in use (could have been 9653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * deleted in the duplicate/bad blocks pass. 9663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 967c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino))) 9683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 96950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 97021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino = ino; 97121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.blk = block_nr; 97221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.blkcount = db->blockcnt; 97321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino2 = 0; 97421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.dirent = 0; 97521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.num = 0; 97621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 9776582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, 9786582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu EXT4_FEATURE_INCOMPAT_INLINE_DATA)) { 9796582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu errcode_t ec; 9806582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu 9816582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu ec = ext2fs_inline_data_size(fs, ino, &inline_data_size); 9826582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu if (ec && ec != EXT2_ET_NO_INLINE_DATA) 9836582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu return DIRENT_ABORT; 9846582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } 9856582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu 9866582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu if (db->blk == 0 && !inline_data_size) { 9871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (allocate_dir_block(ctx, db, buf, &cd->pctx)) 98850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 98950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o block_nr = db->blk; 99050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 991efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 9923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (db->blockcnt) 9933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dot_state = 2; 9943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 9953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dot_state = 0; 9963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 9970926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (ctx->dirs_to_hash && 9980926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ext2fs_u32_list_test(ctx->dirs_to_hash, ino)) 9990926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dups_found++; 10000926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 10013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 1002f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr, 10033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o db->blockcnt, ino); 10043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 1005efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1006f85a9ae6397ff074193322a12ed721dbf5751e41Eric Sandeen ehandler_operation(_("reading directory block")); 1007cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong if (inline_data_size) { 10084a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong memset(buf, 0, fs->blocksize - inline_data_size); 10096582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu cd->pctx.errcode = ext2fs_inline_data_get(fs, ino, 0, buf, 0); 1010cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong if (cd->pctx.errcode) 1011cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong goto inline_read_fail; 1012cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong#ifdef WORDS_BIGENDIAN 10130ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (db->blockcnt) 10140ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong goto skip_first_read_swab; 1015cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong *((__u32 *)buf) = ext2fs_le32_to_cpu(*((__u32 *)buf)); 1016cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong cd->pctx.errcode = ext2fs_dirent_swab_in2(fs, 1017cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong buf + EXT4_INLINE_DATA_DOTDOT_SIZE, 10180ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE, 10190ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong 0); 10200ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (cd->pctx.errcode) 10210ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong goto inline_read_fail; 10220ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wongskip_first_read_swab: 10230ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (inline_data_size <= EXT4_MIN_INLINE_DATA_SIZE || 10240ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong !db->blockcnt) 10250ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong goto inline_read_fail; 10260ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong cd->pctx.errcode = ext2fs_dirent_swab_in2(fs, 10270ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong buf + EXT4_MIN_INLINE_DATA_SIZE, 10280ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong inline_data_size - EXT4_MIN_INLINE_DATA_SIZE, 1029cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong 0); 1030cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong#endif 1031cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong } else 10326582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu cd->pctx.errcode = ext2fs_read_dir_block4(fs, block_nr, 10336582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu buf, 0, ino); 1034cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wonginline_read_fail: 103552b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong pctx.ino = ino; 103652b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong pctx.num = inline_data_size; 10370ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (((inline_data_size & 3) || 10380ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong (inline_data_size > EXT4_MIN_INLINE_DATA_SIZE && 10390ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong inline_data_size < EXT4_MIN_INLINE_DATA_SIZE + 10400ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong EXT2_DIR_REC_LEN(1))) && 104152b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong fix_problem(ctx, PR_2_BAD_INLINE_DIR_SIZE, &pctx)) { 104252b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong errcode_t err = fix_inline_dir_size(ctx, ino, 104352b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong &inline_data_size, &pctx, 104452b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong buf); 104552b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong if (err) 104652b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong return DIRENT_ABORT; 104752b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong 104852b0c6e6c9b2497f5d749bf30e6bc632aa45e6cbDarrick J. Wong } 1049e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o ehandler_operation(0); 1050b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED) 1051b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o cd->pctx.errcode = 0; /* We'll handle this ourselves */ 105281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong else if (cd->pctx.errcode == EXT2_ET_DIR_CSUM_INVALID) { 105381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong cd->pctx.errcode = 0; /* We'll handle this ourselves */ 105481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong failed_csum = 1; 105581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong } 10561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd->pctx.errcode) { 1057e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong char *buf2; 105808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) { 105908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 106008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return DIRENT_ABORT; 106108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o } 1062e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong ext2fs_new_dir_block(fs, db->blockcnt == 0 ? ino : 0, 1063e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong EXT2_ROOT_INO, &buf2); 1064e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong memcpy(buf, buf2, fs->blocksize); 1065e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong ext2fs_free_mem(&buf2); 10663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10678fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 10688fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_dir = e2fsck_get_dx_dir_info(ctx, ino); 106962acaa1de132a808949d71264731bba7fe095705Theodore Ts'o if (dx_dir && dx_dir->numblocks) { 10708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt >= dx_dir->numblocks) { 1071ea9085c711e92c3727538a0637bc805141333d83Darrick J. Wong pctx.dir = ino; 1072efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK, 1073d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o &pctx)) { 1074d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o clear_htree(ctx, ino); 1075d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o dx_dir->numblocks = 0; 1076d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o dx_db = 0; 1077d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o goto out_htree; 1078d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o } 1079d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o fatal_error(ctx, _("Can not continue.")); 10808fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 10818fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[db->blockcnt]; 10828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_LEAF; 10838fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->phys = block_nr; 10848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = ~0; 10858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = 0; 1086efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 10878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dirent = (struct ext2_dir_entry *) buf; 10888a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 1089e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o limit = (struct ext2_dx_countlimit *) (buf+8); 10908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt == 0) { 1091ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root = (struct ext2_dx_root_info *) (buf + 24); 10928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_ROOT; 10938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST; 1094ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if ((root->reserved_zero || 1095ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root->info_length < 8 || 1096ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root->indirect_levels > 1) && 1097ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) { 1098ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o clear_htree(ctx, ino); 1099ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_dir->numblocks = 0; 1100ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_db = 0; 1101f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o } 1102ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_dir->hashversion = root->hash_version; 1103f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o if ((dx_dir->hashversion <= EXT2_HASH_TEA) && 1104f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 1105f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o dx_dir->hashversion += 3; 1106ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_dir->depth = root->indirect_levels + 1; 11078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else if ((dirent->inode == 0) && 11085dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (rec_len == fs->blocksize) && 110970f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara (ext2fs_dirent_name_len(dirent) == 0) && 1110efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (ext2fs_le16_to_cpu(limit->limit) == 111107307114dea005917b0c3a18a08948435f4a2abcDarrick J. Wong ((fs->blocksize - (8 + dx_csum_size)) / 11128132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o sizeof(struct ext2_dx_entry)))) 11138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_NODE; 1114e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong is_leaf = 0; 11158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 1116d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'oout_htree: 11178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 11183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 11197f43a46fad362435f8420f656c6157dc8be8dd4dDarrick J. Wong /* Leaf node with no space for csum? Rebuild dirs in pass 3A. */ 11207f43a46fad362435f8420f656c6157dc8be8dd4dDarrick J. Wong if (is_leaf && !inline_data_size && failed_csum && 11217f43a46fad362435f8420f656c6157dc8be8dd4dDarrick J. Wong !ext2fs_dirent_has_tail(fs, (struct ext2_dir_entry *)buf)) { 11227f43a46fad362435f8420f656c6157dc8be8dd4dDarrick J. Wong de_csum_size = 0; 1123d02d019557d993c8dfe2f7d0fea841101f0d9e61Darrick J. Wong if (e2fsck_dir_will_be_rehashed(ctx, ino)) { 1124d02d019557d993c8dfe2f7d0fea841101f0d9e61Darrick J. Wong failed_csum = 0; 1125d02d019557d993c8dfe2f7d0fea841101f0d9e61Darrick J. Wong goto skip_checksum; 1126d02d019557d993c8dfe2f7d0fea841101f0d9e61Darrick J. Wong } 1127d02d019557d993c8dfe2f7d0fea841101f0d9e61Darrick J. Wong if (!fix_problem(cd->ctx, PR_2_LEAF_NODE_MISSING_CSUM, 11287f43a46fad362435f8420f656c6157dc8be8dd4dDarrick J. Wong &cd->pctx)) 1129e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong goto skip_checksum; 11307f43a46fad362435f8420f656c6157dc8be8dd4dDarrick J. Wong e2fsck_rehash_dir_later(ctx, ino); 1131d02d019557d993c8dfe2f7d0fea841101f0d9e61Darrick J. Wong failed_csum = 0; 11327f43a46fad362435f8420f656c6157dc8be8dd4dDarrick J. Wong goto skip_checksum; 1133e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong } 1134e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong /* htree nodes don't use fake dirents to store checksums */ 1135e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong if (!is_leaf) 1136e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong de_csum_size = 0; 1137e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong 1138e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wongskip_checksum: 11390ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (inline_data_size) { 11400ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (db->blockcnt) { 11410ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong buf += EXT4_MIN_INLINE_DATA_SIZE; 11420ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong max_block_size = inline_data_size - EXT4_MIN_INLINE_DATA_SIZE; 11430ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong /* Zero-length second block, just exit */ 11440ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (max_block_size == 0) 11450ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong return 0; 11460ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong } else { 11470ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong max_block_size = EXT4_MIN_INLINE_DATA_SIZE; 11480ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong } 11490ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong } else 11500ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong max_block_size = fs->blocksize - de_csum_size; 11510ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong 115262ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o if (ctx->encrypted_dirs) 115362ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o encrypted = ext2fs_u32_list_test(ctx->encrypted_dirs, ino); 115462ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o 11550926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp); 1156e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o prev = 0; 11573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o do { 11583971bfe878d6c30f9b5be3a2c0310943982a4775Theodore Ts'o dgrp_t group; 115949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2_ino_t first_unused_inode; 116070f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara unsigned int name_len; 116149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 11621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = 0; 11636582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu if (!inline_data_size || dot_state > 1) { 11646582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent = (struct ext2_dir_entry *) (buf + offset); 11654a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong /* 11664a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong * If there's not even space for the entry header, 11674a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong * force salvaging this dir. 11684a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong */ 11694a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong if (max_block_size - offset < EXT2_DIR_ENTRY_HEADER_LEN) 11704a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong rec_len = EXT2_DIR_REC_LEN(1); 11714a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong else 11724a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 11736582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu cd->pctx.dirent = dirent; 11746582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu cd->pctx.num = offset; 11754a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong if ((offset + rec_len > max_block_size) || 11766582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu (rec_len < 12) || 11776582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu ((rec_len % 4) != 0) || 11784a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong ((ext2fs_dirent_name_len(dirent) + EXT2_DIR_ENTRY_HEADER_LEN) > rec_len)) { 117982ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong if (fix_problem(ctx, PR_2_DIR_CORRUPTED, 118082ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong &cd->pctx)) { 11814348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong#ifdef WORDS_BIGENDIAN 11824348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong /* 11834348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * On big-endian systems, if the dirent 11844348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * swap routine finds a rec_len that it 11854348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * doesn't like, it continues 11864348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * processing the block as if rec_len 11874a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong * == EXT2_DIR_ENTRY_HEADER_LEN. This means that the name 11884348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * field gets byte swapped, which means 11894348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * that salvage will not detect the 11904348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * correct name length (unless the name 11914348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * has a length that's an exact 11924348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * multiple of four bytes), and it'll 11934348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * discard the entry (unnecessarily) 11944348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * and the rest of the dirent block. 11954348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * Therefore, swap the rest of the 11964348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * block back to disk order, run 11974348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * salvage, and re-swap anything after 11984348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong * the salvaged dirent. 11994348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong */ 12004348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong int need_reswab = 0; 12014a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong if (rec_len < EXT2_DIR_ENTRY_HEADER_LEN || rec_len % 4) { 12024348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong need_reswab = 1; 12034348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong ext2fs_dirent_swab_in2(fs, 12044a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong ((char *)dirent) + EXT2_DIR_ENTRY_HEADER_LEN, 12054a3dc1f0b670960acd570ee64acb436c254135c8Darrick J. Wong max_block_size - offset - EXT2_DIR_ENTRY_HEADER_LEN, 12064348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong 0); 12074348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong } 12084348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong#endif 120982ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong salvage_directory(fs, dirent, prev, 121082ad476d4709faf9f39a9aa581f9679e8181bbeaDarrick J. Wong &offset, 12113a748dfc1cc28878b5c0ffc1042c3efb3d26360eDarrick J. Wong max_block_size); 12124348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong#ifdef WORDS_BIGENDIAN 12134348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong if (need_reswab) { 12144348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong (void) ext2fs_get_rec_len(fs, 12154348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong dirent, &rec_len); 12164348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong ext2fs_dirent_swab_in2(fs, 12174348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong ((char *)dirent) + offset + rec_len, 12184348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong max_block_size - offset - rec_len, 12194348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong 0); 12204348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong } 12214348709c5c1daebb1ad2307dbd37f3d04104634eDarrick J. Wong#endif 12226582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dir_modified++; 12236582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu continue; 12246582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } else 12256582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu goto abort_free_dict; 12266582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } 12276582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } else { 12286582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu if (dot_state == 0) { 12296582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu memset(&dot, 0, sizeof(dot)); 12306582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent = ˙ 12316582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->inode = ino; 12326582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->rec_len = EXT2_DIR_REC_LEN(1); 12336582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->name_len = 1 | filetype; 12346582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->name[0] = '.'; 12356582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } else if (dot_state == 1) { 12366582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu memset(&dotdot, 0, sizeof(dotdot)); 12376582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent = &dotdot; 12386582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->inode = 12396582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu ((struct ext2_dir_entry *)buf)->inode; 12406582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->rec_len = EXT2_DIR_REC_LEN(2); 12416582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->name_len = 2 | filetype; 12426582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->name[0] = '.'; 12436582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu dirent->name[1] = '.'; 12446582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } else { 12456582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu fatal_error(ctx, _("Can not continue.")); 12466582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } 12476582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu cd->pctx.dirent = dirent; 12486582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu cd->pctx.num = offset; 12493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 125050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 1251e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if (dot_state == 0) { 12521b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (check_dot(ctx, dirent, ino, &cd->pctx)) 12533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 1254e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if (dot_state == 1) { 125528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ret = check_dotdot(ctx, dirent, ino, &cd->pctx); 125628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (ret < 0) 12570926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 125828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (ret) 12593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 12603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } else if (dirent->inode == ino) { 12611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_LINK_DOT; 12621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) { 12633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 12643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 126521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o goto next; 12663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 12673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1268efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (!dirent->inode) 12693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 1270efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 12713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 12723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the inode listed is a legal one. 1273efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o */ 127470f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara name_len = ext2fs_dirent_name_len(dirent); 12753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (((dirent->inode != EXT2_ROOT_INO) && 12767f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o (dirent->inode < EXT2_FIRST_INODE(fs->super))) || 12773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o (dirent->inode > fs->super->s_inodes_count)) { 12781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_BAD_INO; 12791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } else if (ctx->inode_bb_map && 1280c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson (ext2fs_test_inode_bitmap2(ctx->inode_bb_map, 12811b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dirent->inode))) { 12821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 12831b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If the inode is in a bad block, offer to 12841b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * clear it. 12851b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 12861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_BB_INODE; 128770f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara } else if ((dot_state > 1) && (name_len == 1) && 12881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->name[0] == '.')) { 12891b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 12901b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If there's a '.' entry in anything other 12911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * than the first directory entry, it's a 12921b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * duplicate entry that should be removed. 12931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 12941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_DUP_DOT; 129570f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara } else if ((dot_state > 1) && (name_len == 2) && 1296efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (dirent->name[0] == '.') && 12971b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->name[1] == '.')) { 12981b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 12991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If there's a '..' entry in anything other 13001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * than the second directory entry, it's a 13011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * duplicate entry that should be removed. 13021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 13031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_DUP_DOT_DOT; 1304e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 13051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->inode == EXT2_ROOT_INO)) { 13061b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 13071b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * Don't allow links to the root directory. 13081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * We check this specially to make sure we 13091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * catch this error case even if the root 13101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * directory hasn't been created yet. 13111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 13121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_LINK_ROOT; 131370f4632b626e3db94dd02c9dc9b4e643ffb0d048Jan Kara } else if ((dot_state > 1) && (name_len == 0)) { 1314c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o /* 1315c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o * Don't allow zero-length directory names. 1316c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o */ 1317c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o problem = PR_2_NULL_NAME; 131821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 131921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 13201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (problem) { 13211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, &cd->pctx)) { 132221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->inode = 0; 132321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dir_modified++; 132421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o goto next; 13251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } else { 13261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_unmark_valid(fs); 13271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (problem == PR_2_BAD_INO) 13281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o goto next; 132921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 13303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 13313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 13323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 13333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If the inode was marked as having bad fields in 13343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass1, process it and offer to fix/clear it. 13353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * (We wait until now so that we can display the 13363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pathname to the user.) 13373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 13381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ctx->inode_bad_map && 1339c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_test_inode_bitmap2(ctx->inode_bad_map, 13403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode)) { 1341e72a9ba39471364ad2f9397f645ca547090e3485Theodore Ts'o if (e2fsck_process_bad_inode(ctx, ino, 1342bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o dirent->inode, 1343bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o buf + fs->blocksize)) { 13443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 13453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 13463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 13473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1348a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 134908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return DIRENT_ABORT; 13503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 13513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 135249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos group = ext2fs_group_of_ino(fs, dirent->inode); 135349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos first_unused_inode = group * fs->super->s_inodes_per_group + 135449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 1 + fs->super->s_inodes_per_group - 1355d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_itable_unused(fs, group); 135649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos cd->pctx.group = group; 135749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 135849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos /* 135942e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * Check if the inode was missed out because 136042e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * _INODE_UNINIT flag was set or bg_itable_unused was 136142e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * incorrect. If so, clear the _INODE_UNINIT flag and 136242e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * restart e2fsck. In the future it would be nice if 136342e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * we could call a function in pass1.c that checks the 136442e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * newly visible inodes. 136549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos */ 1366cd65a24e756b8f6770a5961fd94c67eb00dd7baaTheodore Ts'o if (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)) { 13676267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger pctx.num = dirent->inode; 136849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT, 136949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos &cd->pctx)){ 1370e633b58ac75f2f544b7d6572e37d4b63da31e59cEric Sandeen ext2fs_bg_flags_clear(fs, group, 1371732c8cd58ff30ffae0d3276c411a08920717a46cTheodore Ts'o EXT2_BG_INODE_UNINIT); 137242e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o ext2fs_mark_super_dirty(fs); 13736267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger ctx->flags |= E2F_FLAG_RESTART_LATER; 137449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } else { 137549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2fs_unmark_valid(fs); 137649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (problem == PR_2_BAD_INO) 137749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos goto next; 137849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 137949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } else if (dirent->inode >= first_unused_inode) { 13806267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger pctx.num = dirent->inode; 138149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){ 1382d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_itable_unused_set(fs, group, 0); 138349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2fs_mark_super_dirty(fs); 13846267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger ctx->flags |= E2F_FLAG_RESTART_LATER; 138549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } else { 138649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2fs_unmark_valid(fs); 138749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (problem == PR_2_BAD_INO) 138849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos goto next; 138949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 139049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 139149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 13920433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o /* 13930433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * Offer to clear unused inodes; if we are going to be 13940433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * restarting the scan due to bg_itable_unused being 13950433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * wrong, then don't clear any inodes to avoid zapping 13960433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * inodes that were skipped during pass1 due to an 13970433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * incorrect bg_itable_unused; we'll get any real 13980433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * problems after we restart. 13990433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o */ 14000433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o if (!(ctx->flags & E2F_FLAG_RESTART_LATER) && 140197d26ce9e3589e9f5fa17014467a9730a884d158Theodore Ts'o !(ext2fs_test_inode_bitmap2(ctx->inode_used_map, 140297d26ce9e3589e9f5fa17014467a9730a884d158Theodore Ts'o dirent->inode))) 140349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos problem = PR_2_UNUSED_INODE; 140449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 140549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (problem) { 140649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (fix_problem(ctx, problem, &cd->pctx)) { 140749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos dirent->inode = 0; 140849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos dir_modified++; 140949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos goto next; 141049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } else { 141149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2fs_unmark_valid(fs); 141249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (problem == PR_2_BAD_INO) 141349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos goto next; 141449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 141549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 141649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 141762ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o if (!encrypted && check_name(ctx, dirent, ino, &cd->pctx)) 14181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dir_modified++; 14191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 1420aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (check_filetype(ctx, dirent, ino, &cd->pctx)) 1421aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dir_modified++; 1422aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 14238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 14248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db) { 142562ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o get_filename_hash(fs, encrypted, dx_dir->hashversion, 142662ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o dirent->name, 142762ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o ext2fs_dirent_name_len(dirent), 142862ad24802c6e9abd0acf3e6d12aeaab3ae8c6f5aTheodore Ts'o &hash, 0); 14298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash < dx_db->min_hash) 14308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = hash; 14318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash > dx_db->max_hash) 14328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = hash; 14338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 14348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 14358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 143621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o /* 14373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If this is a directory, then mark its parent in its 14383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * dir_info structure. If the parent field is already 14393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * filled in, then this directory has more than one 14403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * hard link. We assume the first link is correct, 14413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * and ask the user if he/she wants to clear this one. 14423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1443e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if ((dot_state > 1) && 1444c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, 14453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode))) { 144628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_get_parent(ctx, dirent->inode, 144728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o &subdir_parent)) { 14481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd->pctx.ino = dirent->inode; 14491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx); 14500926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 14513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 145228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (subdir_parent) { 145328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o cd->pctx.ino2 = subdir_parent; 14541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_LINK_DIR, 145521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o &cd->pctx)) { 14563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 14573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 14583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 145921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 146021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino2 = 0; 146128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } else { 1462efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (void) e2fsck_dir_info_set_parent(ctx, 146328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o dirent->inode, ino); 146428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 14653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 14660926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 14670926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (dups_found) { 14680926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ; 14690926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o } else if (dict_lookup(&de_dict, dirent)) { 14700926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o clear_problem_context(&pctx); 14710926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o pctx.ino = ino; 14720926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o pctx.dirent = dirent; 14730926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx); 1474e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong e2fsck_rehash_dir_later(ctx, ino); 14750926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dups_found++; 14760926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o } else 14770926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_alloc_insert(&de_dict, dirent, dirent); 1478efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 14791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_increment(ctx->inode_count, dirent->inode, 14801b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &links); 148121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (links > 1) 14821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->fs_links_count++; 14831b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->fs_total_count++; 14843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o next: 1485e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o prev = dirent; 14865dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (dir_modified) 14878a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 14886582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu if (!inline_data_size || dot_state > 1) { 14896582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu offset += rec_len; 14906582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } else { 14916698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong if (dot_state == 1) { 14926582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu offset = 4; 14936698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong /* 14946698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong * If we get here, we're checking an inline 14956698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong * directory and we've just checked a (fake) 14966698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong * dotdot entry that we created on the stack. 14976698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong * Therefore set 'prev' to NULL so that if we 14986698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong * call salvage_directory on the next entry, 14996698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong * it won't try to absorb the next entry into 15006698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong * the on-stack dotdot entry. 15016698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong */ 15026698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong prev = NULL; 15036698374cc0a0d99c954aa61db771ba4128432337Darrick J. Wong } 15046582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } 1505e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dot_state++; 15060ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong } while (offset < max_block_size); 15073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 15083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o printf("\n"); 15093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 15108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 15118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db) { 15128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 15138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n", 15148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o db->blockcnt, dx_db->type, 15158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash, dx_db->max_hash); 15168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 1517b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o cd->pctx.dir = cd->pctx.ino; 15188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if ((dx_db->type == DX_DIRBLOCK_ROOT) || 15198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->type == DX_DIRBLOCK_NODE)) 152081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong parse_int_node(fs, db, cd, dx_dir, buf, failed_csum); 15218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 15228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 1523e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong 15240ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (offset != max_block_size) { 15250ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong cd->pctx.num = rec_len + offset - max_block_size; 15260ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) { 15270ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong dirent->rec_len = cd->pctx.num; 15280ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong dir_modified++; 15291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 15303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 15313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dir_modified) { 15322e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong int flags, will_rehash; 1533e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong /* leaf block with no tail? Rehash dirs later. */ 1534e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 1535e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && 1536e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong is_leaf && 153717641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong !inline_data_size && 153817641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong !ext2fs_dirent_has_tail(fs, (struct ext2_dir_entry *)buf)) { 153917641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong if (insert_dirent_tail(fs, buf) == 0) 154017641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong goto write_and_fix; 1541e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong e2fsck_rehash_dir_later(ctx, ino); 154217641bf208afc98a59a0a245ecaa06ecb8e081ddDarrick J. Wong } 1543e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong 1544e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wongwrite_and_fix: 15452e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong will_rehash = e2fsck_dir_will_be_rehashed(ctx, ino); 15462e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong if (will_rehash) { 15472e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong flags = ctx->fs->flags; 1548e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong ctx->fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS; 15492e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong } 15506582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu if (inline_data_size) { 15510ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong buf = ibuf; 1552cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong#ifdef WORDS_BIGENDIAN 15530ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (db->blockcnt) 15540ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong goto skip_first_write_swab; 1555cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong *((__u32 *)buf) = ext2fs_le32_to_cpu(*((__u32 *)buf)); 1556cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong cd->pctx.errcode = ext2fs_dirent_swab_out2(fs, 1557cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong buf + EXT4_INLINE_DATA_DOTDOT_SIZE, 15580ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong EXT4_MIN_INLINE_DATA_SIZE - 1559cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong EXT4_INLINE_DATA_DOTDOT_SIZE, 1560cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong 0); 15610ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (cd->pctx.errcode) 15620ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong goto skip_second_write_swab; 15630ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wongskip_first_write_swab: 15640ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong if (inline_data_size <= EXT4_MIN_INLINE_DATA_SIZE || 15650ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong !db->blockcnt) 15660ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong goto skip_second_write_swab; 15670ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong cd->pctx.errcode = ext2fs_dirent_swab_out2(fs, 15680ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong buf + EXT4_MIN_INLINE_DATA_SIZE, 15690ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong inline_data_size - 15700ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong EXT4_MIN_INLINE_DATA_SIZE, 15710ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wong 0); 15720ac4b3973f313a0bd914b21e85c67b1b76e742fbDarrick J. Wongskip_second_write_swab: 1573cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong if (cd->pctx.errcode && 1574cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong !fix_problem(ctx, PR_2_WRITE_DIRBLOCK, &cd->pctx)) 1575cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong goto abort_free_dict; 1576cd971869d77a9899db326d2ed42e1ef2916ba29fDarrick J. Wong#endif 15776582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu cd->pctx.errcode = 15786582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu ext2fs_inline_data_set(fs, ino, 0, buf, 15796582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu inline_data_size); 15806582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu } else 15816582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu cd->pctx.errcode = ext2fs_write_dir_block4(fs, block_nr, 15826582dbe91b368ba01eb685d1314dd830fa00bde4Zheng Liu buf, 0, ino); 15832e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong if (will_rehash) 15842e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong ctx->fs->flags = (flags & 15852e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong EXT2_FLAG_IGNORE_CSUM_ERRORS) | 15862e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong (ctx->fs->flags & 15872e9d8391560ecde48e0b21f174fdb7bf3331345aDarrick J. Wong ~EXT2_FLAG_IGNORE_CSUM_ERRORS); 15881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd->pctx.errcode) { 158908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, 15900926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o &cd->pctx)) 15910926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 15923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 15933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_changed(fs); 1594e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong } else if (is_leaf && failed_csum && !dir_modified) { 1595e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong /* 1596e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong * If a leaf node that fails csum makes it this far without 1597e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong * alteration, ask the user if the checksum should be fixed. 1598e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong */ 1599e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong if (fix_problem(ctx, PR_2_LEAF_NODE_ONLY_CSUM_INVALID, 1600e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong &cd->pctx)) 1601e8548796a5bb59b2319c81973b7a460f036faa3eDarrick J. Wong goto write_and_fix; 16023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 16030926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_free_nodes(&de_dict); 16043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 16050926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'oabort_free_dict: 16060926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 160749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos dict_free_nodes(&de_dict); 16080926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return DIRENT_ABORT; 16093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 16103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1611624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kalistruct del_block { 1612624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali e2fsck_t ctx; 1613624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali e2_blkcnt_t num; 1614624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali}; 1615624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali 16163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 16173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This function is called to deallocate a block, and is an interator 16183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * functioned called by deallocate inode via ext2fs_iterate_block(). 16193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 16203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int deallocate_inode_block(ext2_filsys fs, 16216dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t *block_nr, 1622544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 16236dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t ref_block EXT2FS_ATTR((unused)), 1624544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 1625133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o void *priv_data) 16263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1627624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali struct del_block *p = priv_data; 1628efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 16294a05268cf86f7138c78d80a53f7e162f32128a3dTheodore Ts'o if (*block_nr == 0) 16303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 16311ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o if ((*block_nr < fs->super->s_first_data_block) || 16324efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson (*block_nr >= ext2fs_blocks_count(fs->super))) 16331ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o return 0; 16348dd650ab9ac394c6d6d19b02e8bb22d5a1e5da0dDarrick J. Wong if ((*block_nr % EXT2FS_CLUSTER_RATIO(fs)) == 0) 16358dd650ab9ac394c6d6d19b02e8bb22d5a1e5da0dDarrick J. Wong ext2fs_block_alloc_stats2(fs, *block_nr, -1); 1636624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali p->num++; 16373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 16383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1639efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 16403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 16413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This fuction deallocates an inode 16423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 16434035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) 16443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 16451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 16463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 16471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 16480684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o __u32 count; 1649624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali struct del_block del_block; 1650efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 165108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); 16521b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 16531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.ino = ino; 1654f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 16553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 16563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Fix up the bitmaps... 16573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1658f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 16590684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); 16600684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o 16610c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o if (ext2fs_file_acl_block(fs, &inode) && 16620684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 166339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong pctx.errcode = ext2fs_adjust_ea_refcount3(fs, 166439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong ext2fs_file_acl_block(fs, &inode), 166539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong block_buf, -1, &count, ino); 16660684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { 16670684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o pctx.errcode = 0; 16680684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o count = 1; 16690684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 16700684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (pctx.errcode) { 16710c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o pctx.blk = ext2fs_file_acl_block(fs, &inode); 16720684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); 16730684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 16740684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o return; 16750684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 16760684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (count == 0) { 167748f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson ext2fs_block_alloc_stats2(fs, 16780c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block(fs, &inode), -1); 16790684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 16800c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block_set(fs, &inode, 0); 16810684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 16823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 16830c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) 1684c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o goto clear_inode; 1685a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 16862ece839011f3074c2249dcfbf99945c93cc1927dDarrick J. Wong /* Inline data inodes don't have blocks to iterate */ 16872ece839011f3074c2249dcfbf99945c93cc1927dDarrick J. Wong if (inode.i_flags & EXT4_INLINE_DATA_FL) 16882ece839011f3074c2249dcfbf99945c93cc1927dDarrick J. Wong goto clear_inode; 16892ece839011f3074c2249dcfbf99945c93cc1927dDarrick J. Wong 16903b6c0938ec5aa401c7ae6c95e94e5ad30a7b8562Darrick J. Wong if (LINUX_S_ISREG(inode.i_mode) && 16913b6c0938ec5aa401c7ae6c95e94e5ad30a7b8562Darrick J. Wong ext2fs_needs_large_file_feature(EXT2_I_SIZE(&inode))) 1692a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ctx->large_files--; 1693a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 1694624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali del_block.ctx = ctx; 1695624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali del_block.num = 0; 16966dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, 1697624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali deallocate_inode_block, 1698624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali &del_block); 16991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 17001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); 170108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 170208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 17031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 1704c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'oclear_inode: 1705c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o /* Inode may have changed by block_iterate, so reread it */ 1706c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); 1707c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode"); 17083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 17093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 17108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o/* 17118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * This fuction clears the htree flag on an inode 17128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 17138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino) 17148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{ 17158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_inode inode; 1716efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 17178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "clear_htree"); 17188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL; 17198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "clear_htree"); 1720b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o if (ctx->dirs_to_hash) 1721b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o ext2fs_u32_list_add(ctx->dirs_to_hash, ino); 17228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o} 17238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 17248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1725f404167dda29a59d2be2882328aeb074b9899669Theodore Ts'oint e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, 1726f404167dda29a59d2be2882328aeb074b9899669Theodore Ts'o ext2_ino_t ino, char *buf) 17273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 17281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 17293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 17303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int inode_modified = 0; 17316c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o int not_fixed = 0; 17321e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o unsigned char *frag, *fsize; 173321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 17343c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o problem_t problem = 0; 17353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 173608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); 173721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 173821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o clear_problem_context(&pctx); 173921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.ino = ino; 174021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.dir = dir; 174121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.inode = &inode; 174221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 17430c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o if (ext2fs_file_acl_block(fs, &inode) && 1744f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 1745f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { 17460c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block_set(fs, &inode, 0); 1747f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o inode_modified++; 1748f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o } else 1749f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o not_fixed++; 1750f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o } 17516c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o 175250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && 175350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && 175450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && 175508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o !(LINUX_S_ISSOCK(inode.i_mode))) 175608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_MODE; 1757fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISCHR(inode.i_mode) 17580684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 175908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_CHAR_DEV; 1760fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISBLK(inode.i_mode) 17610684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 176208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_BLOCK_DEV; 1763fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISFIFO(inode.i_mode) 17640684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 17651dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o problem = PR_2_BAD_FIFO; 1766fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISSOCK(inode.i_mode) 17670684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 17681dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o problem = PR_2_BAD_SOCKET; 1769fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISLNK(inode.i_mode) 17707cadc57780f3e3e8e644e8976e11a336902d4a25Theodore Ts'o && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) { 1771bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o problem = PR_2_INVALID_SYMLINK; 177267052a8aeeca8cd80d1dd33c2792f917573accc8Andreas Dilger } 17731dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o 177408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (problem) { 177508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (fix_problem(ctx, problem, &pctx)) { 17761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o deallocate_inode(ctx, ino, 0); 1777a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 177808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return 0; 17797cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o return 1; 17806c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 17816c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 178208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = 0; 17837cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o } 1784efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 17856c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (inode.i_faddr) { 17866c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { 17876c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_faddr = 0; 17886c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 17896c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 17906c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 17913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 17921e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o 17931e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o switch (fs->super->s_creator_os) { 17941e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o case EXT2_OS_HURD: 17951e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = &inode.osd2.hurd2.h_i_frag; 17961e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o fsize = &inode.osd2.hurd2.h_i_fsize; 17971e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o break; 17981e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o default: 17991e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = fsize = 0; 18001e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o } 180121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (frag && *frag) { 180221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = *frag; 18031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { 180421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *frag = 0; 180521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o inode_modified++; 18067e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o } else 18077e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o not_fixed++; 180821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = 0; 180921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 181021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (fsize && *fsize) { 181121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = *fsize; 18121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { 181321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *fsize = 0; 181421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o inode_modified++; 18156c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 18166c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 181721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = 0; 181821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 181921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 18205d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o if ((fs->super->s_creator_os == EXT2_OS_LINUX) && 1821efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o !(fs->super->s_feature_ro_compat & 18225d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && 18235d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o (inode.osd2.linux2.l_i_blocks_hi != 0)) { 18245d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o pctx.num = inode.osd2.linux2.l_i_blocks_hi; 18255d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) { 18265d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o inode.osd2.linux2.l_i_blocks_hi = 0; 18275d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o inode_modified++; 18285d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o } 18295d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o } 18305d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o 183136769c606c270094df0431cbcab9932905adcedcJustus Winter if ((fs->super->s_creator_os == EXT2_OS_LINUX) && 183236769c606c270094df0431cbcab9932905adcedcJustus Winter !(fs->super->s_feature_incompat & 1833911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o EXT4_FEATURE_INCOMPAT_64BIT) && 1834911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode.osd2.linux2.l_i_file_acl_high != 0) { 1835911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o pctx.num = inode.osd2.linux2.l_i_file_acl_high; 1836911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) { 1837911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode.osd2.linux2.l_i_file_acl_high = 0; 1838911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode_modified++; 1839911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o } else 1840911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o not_fixed++; 1841911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o } 1842911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o 18430c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o if (ext2fs_file_acl_block(fs, &inode) && 18440c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) || 18450c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o (ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) { 18466c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { 18470c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block_set(fs, &inode, 0); 18486c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 18496c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 18506c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 1851342d847db355d81299218e07a1e58ece82080a04Theodore Ts'o } 185221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (inode.i_dir_acl && 18536c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o LINUX_S_ISDIR(inode.i_mode)) { 18546c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { 18556c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_dir_acl = 0; 18566c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 18576c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 18586c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 185921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 18606c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o 1861f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (inode_modified) 186208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); 1863f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o if (!not_fixed && ctx->inode_bad_map) 1864c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); 18653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 18663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 18673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 186850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/* 186950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * allocate_dir_block --- this function allocates a new directory 187050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * block for a particular inode; this is done if a directory has 187150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * a "hole" in it, or if a directory has a illegal block number 187250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * that was zeroed out and now needs to be replaced. 187350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 18741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx, 18756dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 1876efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o char *buf EXT2FS_ATTR((unused)), 1877544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 187850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{ 18791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 1880ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong blk64_t blk = 0; 188150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o char *block; 188250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o struct ext2_inode inode; 188350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 18841b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0) 188550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 188650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 188750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 188850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Read the inode and block bitmaps in; we'll be messing with 188950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * them. 189050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 1891f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 1892efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 189350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 189450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * First, find a free block 189550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 1896ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block"); 1897ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong pctx->errcode = ext2fs_map_cluster_block(fs, db->ino, &inode, 1898ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong db->blockcnt, &blk); 1899ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong if (pctx->errcode || blk == 0) { 19007b486ec08cda3bc67b7f6bdcbcc9cb5783322e6cDarrick J. Wong blk = ext2fs_find_inode_goal(fs, db->ino, &inode, db->blockcnt); 19017b486ec08cda3bc67b7f6bdcbcc9cb5783322e6cDarrick J. Wong pctx->errcode = ext2fs_new_block2(fs, blk, 1902ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong ctx->block_found_map, &blk); 1903ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong if (pctx->errcode) { 1904ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong pctx->str = "ext2fs_new_block"; 1905ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 1906ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong return 1; 1907ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong } 190850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 1909c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); 1910c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_mark_block_bitmap2(fs->block_map, blk); 191150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o ext2fs_mark_bb_dirty(fs); 191250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 191350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 191450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Now let's create the actual data block for the inode 191550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 191650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (db->blockcnt) 19171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block); 191850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o else 19191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_dir_block(fs, db->ino, 19201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o EXT2_ROOT_INO, &block); 192150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 19221b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 19231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_new_dir_block"; 19241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 192550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 192650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 192750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 192881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong pctx->errcode = ext2fs_write_dir_block4(fs, blk, block, 0, db->ino); 1929c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 19301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 19311b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_write_dir_block"; 19321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 193350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 193450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 193550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 193650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 193750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Update the inode block count 193850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 19391ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_add_blocks(fs, &inode, 1); 194097c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong if (EXT2_I_SIZE(&inode) < (db->blockcnt+1) * fs->blocksize) { 194197c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong pctx->errcode = ext2fs_inode_size_set(fs, &inode, 194297c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong (db->blockcnt+1) * fs->blocksize); 194397c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong if (pctx->errcode) { 194497c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong pctx->str = "ext2fs_inode_size_set"; 194597c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 194697c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong return 1; 194797c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong } 194897c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong } 194908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block"); 195050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 195150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 195250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Finally, update the block pointers for the inode 195350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 195450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o db->blk = blk; 19552d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET, 19562d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o db->blockcnt, 0, &blk); 19571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 19581b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_block_iterate"; 19591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 196050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 196150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 196250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 196350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 196450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o} 1965