pass3.c revision 9facd076ae8af6e908e228392cea866ce0faf1bc
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass3.c -- pass #3 of e2fsck: Check for directory connectivity 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 4c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 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 #3 assures that all directories are connected to the 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * filesystem tree, using the following algorithm: 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * First, the root directory is checked to make sure it exists; if 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * not, e2fsck will offer to create a new one. It is then marked as 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * "done". 17efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Then, pass3 interates over all directory inodes; for each directory 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * it attempts to trace up the filesystem tree, using dirinfo.parent 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * until it reaches a directory which has been marked "done". If it 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * can not do so, then the directory must be disconnected, and e2fsck 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * will offer to reconnect it to /lost+found. While it is chasing 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * parent pointers up the filesystem tree, if pass3 sees a directory 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * twice, then it has detected a filesystem loop, and it will again 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * offer to reconnect the directory to /lost+found in to break the 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * filesystem loop. 27efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 2808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to 2908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * reconnect inodes to /lost+found; this subroutine is also used by 3008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which 3108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * is responsible for creating /lost+found if it does not exist. 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 3 frees the following data structures: 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The dirinfo directory information cache. 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_ERRNO_H 3850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 3950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 4221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h" 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void check_root(e2fsck_t ctx); 4528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'ostatic int check_directory(e2fsck_t ctx, ext2_ino_t ino, 4628ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o struct problem_context *pctx); 4728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'ostatic void fix_dotdot(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent); 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 49a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'ostatic ext2fs_inode_bitmap inode_loop_detect = 0; 50a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'ostatic ext2fs_inode_bitmap inode_done_map = 0; 51efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 5208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass3(e2fsck_t ctx) 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 5528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o struct dir_info_iter *iter; 568bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct resource_track rtrack; 588bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 5921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 6021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct dir_info *dir; 617f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o unsigned long maxdirs, count; 62f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 636d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o init_resource_track(&rtrack, ctx->fs->io); 641b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o mtrace_print("Pass 3"); 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ctx->options & E2F_OPT_PREEN)) 711b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_PASS_HEADER, &pctx); 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Allocate some bitmaps to do loop detection. 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 760c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"), 771b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &inode_done_map); 781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.num = 2; 801b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx); 8108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 82a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o goto abort_exit; 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 849facd076ae8af6e908e228392cea866ce0faf1bcKen Chen print_resource_track(ctx, _("Peak memory"), &ctx->global_rtrack, NULL); 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o check_root(ctx); 87a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 88a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o goto abort_exit; 8908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o 90f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO); 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 927f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o maxdirs = e2fsck_get_num_dirinfo(ctx); 93f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o count = 1; 94f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 95f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o if (ctx->progress) 967f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if ((ctx->progress)(ctx, 3, 0, maxdirs)) 97f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o goto abort_exit; 98efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 9928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o iter = e2fsck_dir_info_iter_begin(ctx); 10028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o while ((dir = e2fsck_dir_info_iter(ctx, iter)) != 0) { 1014cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 1024cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o goto abort_exit; 1034cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs)) 1044cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o goto abort_exit; 1051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino)) 10628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (check_directory(ctx, dir->ino, &pctx)) 10728ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o goto abort_exit; 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o e2fsck_dir_info_iter_end(ctx, iter); 110a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o 1115a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o /* 1125a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o * Force the creation of /lost+found if not present 1135a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o */ 1145a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o if ((ctx->flags & E2F_OPT_READONLY) == 0) 115850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o e2fsck_get_lost_and_found(ctx, 1); 1165a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o 117850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o /* 118850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o * If there are any directories that need to be indexed or 119850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o * optimized, do it here. 120850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o */ 121850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o e2fsck_rehash_directories(ctx); 122efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 123a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'oabort_exit: 12408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_free_dir_info(ctx); 12528ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o if (inode_loop_detect) { 126a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o ext2fs_free_inode_bitmap(inode_loop_detect); 12728ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o inode_loop_detect = 0; 12828ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o } 12928ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o if (inode_done_map) { 130a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o ext2fs_free_inode_bitmap(inode_done_map); 13128ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o inode_done_map = 0; 13228ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o } 133b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o 1349facd076ae8af6e908e228392cea866ce0faf1bcKen Chen print_resource_track(ctx, _("Pass 3"), &rtrack, ctx->fs->io); 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This makes sure the root inode is present; if not, we ask if the 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * user wants us to create it. Not creating it is a fatal error. 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void check_root(e2fsck_t ctx) 1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1431b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t blk; 1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * block; 1471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 148efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 150efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1511b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) { 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 15308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * If the root inode is not a directory, die here. The 1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * user must have answered 'no' in pass1 when we 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * offered to clear it. 1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map, 158f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o EXT2_ROOT_INO))) { 159f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx); 160f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 161f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o } 1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 165f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) { 166f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx); 167f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 168f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o return; 169f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o } 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 171f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 172efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * First, find a free block 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); 1771b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 1781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_new_block"; 1791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 18008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 18108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1831b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_block_bitmap(ctx->block_found_map, blk); 184f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_bb_dirty(fs); 1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Now let's create the actual data block for the inode 1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1901b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 1911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &block); 1921b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 1931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_new_dir_block"; 1941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 19508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 19608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_write_dir_block(fs, blk, block); 2001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 2011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_write_dir_block"; 2021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 20308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 20408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 206c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Set up the inode structure 2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(&inode, 0, sizeof(inode)); 2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_mode = 040755; 2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size = fs->blocksize; 2141f3ad14a5ad5df3ac4012d41ef5d76411cd8fff3Theodore Ts'o inode.i_atime = inode.i_ctime = inode.i_mtime = ctx->now; 2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count = 2; 2161ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_set(fs, &inode, 1); 2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_block[0] = blk; 2183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Write out the inode. 2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 222030970ed750b6a169c32ffb8b19bce3150198629Theodore Ts'o pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode); 2231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 2241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_write_inode"; 2251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 22608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 22708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 229efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Miscellaneous bookkeeping... 2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 23308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); 2341b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2); 2351b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2); 2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO); 2381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO); 239f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO); 2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_ib_dirty(fs); 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This subroutine is responsible for making sure that a particular 2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory is connected to the root; if it isn't we trace it up as 2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * far as we can go, and then offer to connect the resulting parent to 2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * the lost+found. We have to do loop detection; if we ever discover 2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * a loop, we treat that as a disconnected directory and offer to 2493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * reparent it to lost+found. 250efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 25128ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * However, loop detection is expensive, because for very large 25228ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * filesystems, the inode_loop_detect bitmap is huge, and clearing it 25328ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * is non-trivial. Loops in filesystems are also a rare error case, 25428ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * and we shouldn't optimize for error cases. So we try two passes of 25528ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * the algorithm. The first time, we ignore loop detection and merely 25628ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * increment a counter; if the counter exceeds some extreme threshold, 25728ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * then we try again with the loop detection bitmap enabled. 2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 25928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'ostatic int check_directory(e2fsck_t ctx, ext2_ino_t dir, 26028ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o struct problem_context *pctx) 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 26228ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o ext2_filsys fs = ctx->fs; 26328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t ino = dir, parent; 26428ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o int loop_pass = 0, parent_count = 0; 2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 26628ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o while (1) { 2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Mark this inode as being "done"; by the time we 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * return from this function, the inode we either be 2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * verified as being connected to the directory tree, 2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * or we will have offered to reconnect this to 2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * lost+found. 27328ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * 27428ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * If it was marked done already, then we've reached a 27528ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * parent we've already checked. 2763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 27728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (ext2fs_mark_inode_bitmap(inode_done_map, ino)) 27828ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o break; 2797f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o 28028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_get_parent(ctx, ino, &parent)) { 28128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o fix_problem(ctx, PR_3_NO_DIRINFO, pctx); 28228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o return 0; 28328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 28428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o 2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If this directory doesn't have a parent, or we've 2873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * seen the parent once already, then offer to 2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * reparent it to lost+found 2893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 29028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (!parent || 291efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (loop_pass && 29228ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o (ext2fs_test_inode_bitmap(inode_loop_detect, 29328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o parent)))) { 29428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o pctx->ino = ino; 2957f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) { 2962e5fcce05ea583c480b28bf3b1f2aa427a3dcc07Theodore Ts'o if (e2fsck_reconnect_file(ctx, pctx->ino)) 2977f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o ext2fs_unmark_valid(fs); 2987f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o else { 299efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fix_dotdot(ctx, pctx->ino, 30028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ctx->lost_and_found); 30128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o parent = ctx->lost_and_found; 3027f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o } 3037f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o } 3043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 3057f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o } 30628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ino = parent; 30728ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o if (loop_pass) { 30828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2fs_mark_inode_bitmap(inode_loop_detect, ino); 30928ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o } else if (parent_count++ > 2048) { 31028ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o /* 31128ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * If we've run into a path depth that's 31228ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * greater than 2048, try again with the inode 31328ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * loop bitmap turned on and start from the 31428ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o * top. 31528ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o */ 31628ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o loop_pass = 1; 31728ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o if (inode_loop_detect) 31828ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o ext2fs_clear_inode_bitmap(inode_loop_detect); 31928ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o else { 32028ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect); 32128ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o if (pctx->errcode) { 32228ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o pctx->num = 1; 323efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fix_problem(ctx, 32428ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o PR_3_ALLOCATE_IBITMAP_ERROR, pctx); 32528ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 32628ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o return -1; 32728ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o } 32828ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o } 32928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ino = dir; 3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 33121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 3323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 3343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure that .. and the parent directory are the same; 3353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * offer to fix it if not. 3363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 33728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o pctx->ino = dir; 33828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_get_dotdot(ctx, dir, &pctx->ino2) || 33928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o e2fsck_dir_info_get_parent(ctx, dir, &pctx->dir)) { 34028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o fix_problem(ctx, PR_3_NO_DIRINFO, pctx); 34128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o return 0; 34228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 34328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (pctx->ino2 != pctx->dir) { 3441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx)) 34528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o fix_dotdot(ctx, dir, pctx->dir); 3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 34728ffafb09c6fd8a9ebe716c06b02143771a9b17fTheodore Ts'o return 0; 348b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o} 3493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 3513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This routine gets the lost_and_found inode, making it a directory 3523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * if necessary 3533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 354850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'oext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix) 3553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 35786c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino; 3583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t blk; 3593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 3603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 3613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * block; 36253ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o static const char name[] = "lost+found"; 3631b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 3643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 365850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o if (ctx->lost_and_found) 366850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o return ctx->lost_and_found; 367850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o 3681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 369efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 37021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, 37121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o sizeof(name)-1, 0, &ino); 372850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o if (retval && !fix) 373850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o return 0; 3744a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o if (!retval) { 375850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) { 376850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o ctx->lost_and_found = ino; 3774a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o return ino; 378850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o } 379efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 3804a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o /* Lost+found isn't a directory! */ 381850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o if (!fix) 382850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o return 0; 3834a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o pctx.ino = ino; 3844a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx)) 3854a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o return 0; 3864a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o 387c54b3c3c99a5d3011f6f60934e90dae7f60b3b00Theodore Ts'o /* OK, unlink the old /lost+found file. */ 3884a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0); 3894a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o if (pctx.errcode) { 3904a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o pctx.str = "ext2fs_unlink"; 3914a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 3924a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o return 0; 3934a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o } 39428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o (void) e2fsck_dir_info_set_parent(ctx, ino, 0); 395b0700a1b6083f2f0c19c349f07ca80e70ec456beTheodore Ts'o e2fsck_adjust_inode_count(ctx, ino, -1); 3964a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o } else if (retval != EXT2_ET_FILE_NOT_FOUND) { 3971b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 3981b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx); 3991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 4001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0)) 4013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Read the inode and block bitmaps in; we'll be messing with 4053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * them. 4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 407f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 408efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 4093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * First, find a free block 4113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); 4133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 4141b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 4151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx); 4163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_block_bitmap(ctx->block_found_map, blk); 4190684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_block_alloc_stats(fs, blk, +1); 4203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Next find a free inode. 4233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 424b0700a1b6083f2f0c19c349f07ca80e70ec456beTheodore Ts'o retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700, 4251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->inode_used_map, &ino); 4263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 4271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 4281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx); 4293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4311b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); 4321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino); 4330684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_inode_alloc_stats2(fs, ino, +1, 1); 4343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Now let's create the actual data block for the inode 4373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block); 4393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 4401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 4411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx); 4423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 44550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o retval = ext2fs_write_dir_block(fs, blk, block); 446c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 4473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 4481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 4491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx); 4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Set up the inode structure 4553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(&inode, 0, sizeof(inode)); 45764aecc4dd35b48f66f452f06c49587c838990d39Theodore Ts'o inode.i_mode = 040700; 4583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size = fs->blocksize; 4591f3ad14a5ad5df3ac4012d41ef5d76411cd8fff3Theodore Ts'o inode.i_atime = inode.i_ctime = inode.i_mtime = ctx->now; 4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count = 2; 4611ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_set(fs, &inode, 1); 4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_block[0] = blk; 4633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Next, write out the inode. 4663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 467030970ed750b6a169c32ffb8b19bce3150198629Theodore Ts'o pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode); 4681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 4691b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_write_inode"; 4701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Finally, create the directory link 4753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4766fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR); 4771b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 4781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_link"; 4791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 4803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Miscellaneous bookkeeping that needs to be kept straight. 4853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 48608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO); 487b0700a1b6083f2f0c19c349f07ca80e70ec456beTheodore Ts'o e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1); 4881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_count, ino, 2); 4891b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_link_info, ino, 2); 490850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o ctx->lost_and_found = ino; 4913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 492f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("/lost+found created; inode #%lu\n", ino); 4933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 4943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ino; 4953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This routine will connect a file to lost+found 4993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 50086c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'oint e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino) 5013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 5021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 5033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 5043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char name[80]; 5051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 5066fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o struct ext2_inode inode; 5076fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o int file_type = 0; 5081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 5091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 5106fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o pctx.ino = ino; 5111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 512850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o if (!ctx->bad_lost_and_found && !ctx->lost_and_found) { 513850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o if (e2fsck_get_lost_and_found(ctx, 1) == 0) 514850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o ctx->bad_lost_and_found++; 5151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 516850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o if (ctx->bad_lost_and_found) { 5171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_NO_LPF, &pctx); 5183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 5193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 520efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 52186c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o sprintf(name, "#%u", ino); 5226fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o if (ext2fs_read_inode(fs, ino, &inode) == 0) 5236fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o file_type = ext2_file_type(inode.i_mode); 524850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type); 5253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval == EXT2_ET_DIR_NO_SPACE) { 5261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx)) 5273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 528efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = e2fsck_expand_directory(ctx, ctx->lost_and_found, 529850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o 1, 0); 5303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 5311b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 5321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx); 5333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 5343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 535850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o retval = ext2fs_link(fs, ctx->lost_and_found, name, 536850d05e9aa405497e57c72090b9561af98b1b661Theodore Ts'o ino, file_type); 5373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 5391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 5401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx); 5413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 5423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 543b0700a1b6083f2f0c19c349f07ca80e70ec456beTheodore Ts'o e2fsck_adjust_inode_count(ctx, ino, 1); 5443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 5493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Utility routine to adjust the inode counts on an inode. 5503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 551b0700a1b6083f2f0c19c349f07ca80e70ec456beTheodore Ts'oerrcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj) 5523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 5531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 5543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 5553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 556efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 5573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!ino) 5583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_inode(fs, ino, &inode); 5613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 5623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 5633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 565f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj, 5663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count); 5673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 5683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 56921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (adj == 1) { 5701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_increment(ctx->inode_count, ino, 0); 571c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o if (inode.i_links_count == (__u16) ~0) 572c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o return 0; 5731b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_increment(ctx->inode_link_info, ino, 0); 574c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o inode.i_links_count++; 575c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o } else if (adj == -1) { 5761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_decrement(ctx->inode_count, ino, 0); 577c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o if (inode.i_links_count == 0) 578c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o return 0; 5791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_decrement(ctx->inode_link_info, ino, 0); 580c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o inode.i_links_count--; 58121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 582efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 5833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_write_inode(fs, ino, &inode); 5843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 5853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 5863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 5913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Fix parent --- this routine fixes up the parent of a directory. 5923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 5933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct fix_dotdot_struct { 5943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2_filsys fs; 59586c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t parent; 5963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int done; 5971b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 5983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 5993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int fix_dotdot_proc(struct ext2_dir_entry *dirent, 601544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int offset EXT2FS_ATTR((unused)), 602544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int blocksize EXT2FS_ATTR((unused)), 603544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o char *buf EXT2FS_ATTR((unused)), 60454dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 6053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 60654dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data; 6073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 6081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 6093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 610b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o if ((dirent->name_len & 0xFF) != 2) 6113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 6123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (strncmp(dirent->name, "..", 2)) 6133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 6143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 616efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 617b0700a1b6083f2f0c19c349f07ca80e70ec456beTheodore Ts'o retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1); 6181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (retval) { 6191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 6201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); 6211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 622b0700a1b6083f2f0c19c349f07ca80e70ec456beTheodore Ts'o retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1); 6231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (retval) { 6241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 6251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); 6261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 6273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = fp->parent; 62856c8c592ac48c0fc9772153bb7bdf621b1de0ab9Theodore Ts'o if (fp->ctx->fs->super->s_feature_incompat & 62956c8c592ac48c0fc9772153bb7bdf621b1de0ab9Theodore Ts'o EXT2_FEATURE_INCOMPAT_FILETYPE) 630efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o dirent->name_len = (dirent->name_len & 0xFF) | 63156c8c592ac48c0fc9772153bb7bdf621b1de0ab9Theodore Ts'o (EXT2_FT_DIR << 8); 63256c8c592ac48c0fc9772153bb7bdf621b1de0ab9Theodore Ts'o else 63356c8c592ac48c0fc9772153bb7bdf621b1de0ab9Theodore Ts'o dirent->name_len = dirent->name_len & 0xFF; 6343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fp->done++; 6363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return DIRENT_ABORT | DIRENT_CHANGED; 6373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 63928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'ostatic void fix_dotdot(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent) 6403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 6411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 6423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 6433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct fix_dotdot_struct fp; 6441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 6453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fp.fs = fs; 6473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fp.parent = parent; 6483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fp.done = 0; 6491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fp.ctx = ctx; 6503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 65228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o printf("Fixing '..' of inode %lu to be %lu...\n", ino, parent); 6533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 654efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 65528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o clear_problem_context(&pctx); 65628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o pctx.ino = ino; 65728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o retval = ext2fs_dir_iterate(fs, ino, DIRENT_FLAG_INCLUDE_EMPTY, 6583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 0, fix_dotdot_proc, &fp); 6593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval || !fp.done) { 6601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 6611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR : 6621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o PR_3_FIX_PARENT_NOFIND, &pctx); 6633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_unmark_valid(fs); 6643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 66528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o (void) e2fsck_dir_info_set_dotdot(ctx, ino, parent); 66628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_set_parent(ctx, ino, ctx->lost_and_found)) 66728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o fix_problem(ctx, PR_3_NO_DIRINFO, &pctx); 66828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o 6693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 6703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 6733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * These routines are responsible for expanding a /lost+found if it is 6743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * too small. 6753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 6763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct expand_dir_struct { 678b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o int num; 679b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o int guaranteed_size; 680c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o int newblocks; 681b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o int last_block; 682c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o errcode_t err; 683c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o e2fsck_t ctx; 6843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 6853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int expand_dir_proc(ext2_filsys fs, 6873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t *blocknr, 688133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o e2_blkcnt_t blockcnt, 689544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o blk_t ref_block EXT2FS_ATTR((unused)), 690544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 69154dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 6923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 69354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; 6943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t new_blk; 6953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o static blk_t last_blk = 0; 6963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *block; 6973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 6981b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 6991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 7001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx = es->ctx; 701efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 702b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o if (es->guaranteed_size && blockcnt >= es->guaranteed_size) 703b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o return BLOCK_ABORT; 704b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o 705b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o if (blockcnt > 0) 706b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o es->last_block = blockcnt; 7073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*blocknr) { 7083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o last_blk = *blocknr; 7093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 7103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map, 7121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &new_blk); 7133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 7143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 7153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 7163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (blockcnt > 0) { 7183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_dir_block(fs, 0, 0, &block); 7193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 7203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 7213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 7223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 723b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o es->num--; 724b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o retval = ext2fs_write_dir_block(fs, new_blk, block); 7253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } else { 726c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(fs->blocksize, &block); 72708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (retval) { 72808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o es->err = retval; 7293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 7303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(block, 0, fs->blocksize); 732b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o retval = io_channel_write_blk(fs->io, new_blk, 1, block); 733efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o } 7343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 7353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 7363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 7373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 738c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 7393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *blocknr = new_blk; 7401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk); 741b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o ext2fs_block_alloc_stats(fs, new_blk, +1); 742c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o es->newblocks++; 743efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 744b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o if (es->num == 0) 7453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return (BLOCK_CHANGED | BLOCK_ABORT); 7463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 7473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_CHANGED; 7483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 7493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 750b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'oerrcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir, 751b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o int num, int guaranteed_size) 7523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 7531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 7543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 7553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct expand_dir_struct es; 7563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 757efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 7583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!(fs->flags & EXT2_FLAG_RW)) 7593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return EXT2_ET_RO_FILSYS; 7603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 761b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o /* 762b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o * Read the inode and block bitmaps in; we'll be messing with 763b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o * them. 764b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o */ 765b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o e2fsck_read_bitmaps(ctx); 766c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o 7673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_check_directory(fs, dir); 7683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 7693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 770efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 771b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o es.num = num; 772b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o es.guaranteed_size = guaranteed_size; 773b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o es.last_block = 0; 7743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es.err = 0; 775c1faf9cc3a2418c536eee472f054c9604ad3f213Theodore Ts'o es.newblocks = 0; 7761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o es.ctx = ctx; 777efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 778133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND, 779133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o 0, expand_dir_proc, &es); 7803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (es.err) 7823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return es.err; 7833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 7853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Update the size and block count fields in the inode. 7863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 7873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_inode(fs, dir, &inode); 7883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 7893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 790efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 791b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o inode.i_size = (es.last_block + 1) * fs->blocksize; 7921ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); 7933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 79408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, dir, &inode, "expand_directory"); 7953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 7973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 798b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o 799