Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1 | /* |
| 2 | * pass4.c -- pass #4 of e2fsck: Check reference counts |
| 3 | * |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 4 | * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. |
| 5 | * |
| 6 | * %Begin-Header% |
| 7 | * This file may be redistributed under the terms of the GNU Public |
| 8 | * License. |
| 9 | * %End-Header% |
| 10 | * |
| 11 | * Pass 4 frees the following data structures: |
| 12 | * - A bitmap of which inodes are in bad blocks. (inode_bb_map) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 13 | */ |
| 14 | |
| 15 | #include "e2fsck.h" |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 16 | #include "problem.h" |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 17 | |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 18 | /* |
| 19 | * This routine is called when an inode is not connected to the |
| 20 | * directory tree. |
| 21 | * |
| 22 | * This subroutine returns 1 then the caller shouldn't bother with the |
| 23 | * rest of the pass 4 tests. |
| 24 | */ |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 25 | static int disconnect_inode(ext2_filsys fs, ino_t i) |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 26 | { |
| 27 | struct ext2_inode inode; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 28 | struct problem_context pctx; |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 29 | |
| 30 | e2fsck_read_inode(fs, i, &inode, "pass4: disconnect_inode"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 31 | clear_problem_context(&pctx); |
| 32 | pctx.ino = i; |
| 33 | pctx.inode = &inode; |
| 34 | |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 35 | if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) || |
| 36 | LINUX_S_ISDIR(inode.i_mode))) { |
| 37 | /* |
| 38 | * This is a zero-length file; prompt to delete it... |
| 39 | */ |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 40 | if (fix_problem(fs, PR_4_ZERO_LEN_INODE, &pctx)) { |
| 41 | ext2fs_icount_store(inode_link_info, i, 0); |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 42 | inode.i_links_count = 0; |
| 43 | inode.i_dtime = time(0); |
| 44 | e2fsck_write_inode(fs, i, &inode, |
| 45 | "disconnect_inode"); |
| 46 | /* |
| 47 | * Fix up the bitmaps... |
| 48 | */ |
| 49 | read_bitmaps(fs); |
| 50 | ext2fs_unmark_inode_bitmap(inode_used_map, i); |
| 51 | ext2fs_unmark_inode_bitmap(inode_dir_map, i); |
| 52 | ext2fs_unmark_inode_bitmap(fs->inode_map, i); |
| 53 | ext2fs_mark_ib_dirty(fs); |
| 54 | return 0; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | /* |
| 59 | * Prompt to reconnect. |
| 60 | */ |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 61 | if (fix_problem(fs, PR_4_UNATTACHED_INODE, &pctx)) { |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 62 | if (reconnect_file(fs, i)) |
| 63 | ext2fs_unmark_valid(fs); |
| 64 | } else { |
| 65 | /* |
| 66 | * If we don't attach the inode, then skip the |
| 67 | * i_links_test since there's no point in trying to |
| 68 | * force i_links_count to zero. |
| 69 | */ |
| 70 | ext2fs_unmark_valid(fs); |
| 71 | return 1; |
| 72 | } |
| 73 | return 0; |
| 74 | } |
| 75 | |
| 76 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 77 | void pass4(ext2_filsys fs) |
| 78 | { |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 79 | ino_t i; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 80 | struct ext2_inode inode; |
| 81 | struct resource_track rtrack; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 82 | struct problem_context pctx; |
| 83 | __u16 link_count, link_counted; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 84 | |
| 85 | init_resource_track(&rtrack); |
| 86 | |
| 87 | #ifdef MTRACE |
| 88 | mtrace_print("Pass 4"); |
| 89 | #endif |
| 90 | |
| 91 | if (!preen) |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 92 | printf("Pass 4: Checking reference counts\n"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 93 | clear_problem_context(&pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 94 | for (i=1; i <= fs->super->s_inodes_count; i++) { |
| 95 | if (i == EXT2_BAD_INO || |
Theodore Ts'o | 7f88b04 | 1997-04-26 14:48:50 +0000 | [diff] [blame] | 96 | (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super))) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 97 | continue; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 98 | if (!(ext2fs_test_inode_bitmap(inode_used_map, i)) || |
| 99 | (inode_bb_map && |
| 100 | ext2fs_test_inode_bitmap(inode_bb_map, i))) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 101 | continue; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 102 | ext2fs_icount_fetch(inode_link_info, i, &link_count); |
| 103 | ext2fs_icount_fetch(inode_count, i, &link_counted); |
| 104 | if (link_counted == 0) { |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 105 | if (disconnect_inode(fs, i)) |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 106 | continue; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 107 | ext2fs_icount_fetch(inode_link_info, i, &link_count); |
| 108 | ext2fs_icount_fetch(inode_count, i, &link_counted); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 109 | } |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 110 | if (link_counted != link_count) { |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 111 | e2fsck_read_inode(fs, i, &inode, "pass4"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 112 | pctx.ino = i; |
| 113 | pctx.inode = &inode; |
| 114 | if (link_count != inode.i_links_count) { |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 115 | printf("WARNING: PROGRAMMING BUG IN E2FSCK!\n"); |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 116 | printf("\tOR SOME BONEHEAD (YOU) IS CHECKING " |
| 117 | "A MOUNTED (LIVE) FILESYSTEM.\n"); |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 118 | printf("inode_link_info[%ld] is %u, " |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 119 | "inode.i_links_count is %d. " |
| 120 | "They should be the same!\n", |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 121 | i, link_count, |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 122 | inode.i_links_count); |
| 123 | } |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 124 | pctx.num = link_counted; |
| 125 | if (fix_problem(fs, PR_4_BAD_REF_COUNT, &pctx)) { |
| 126 | inode.i_links_count = link_counted; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 127 | e2fsck_write_inode(fs, i, &inode, "pass4"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 128 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 129 | } |
| 130 | } |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 131 | ext2fs_free_icount(inode_link_info); inode_link_info = 0; |
| 132 | ext2fs_free_icount(inode_count); inode_count = 0; |
| 133 | ext2fs_free_inode_bitmap(inode_bb_map); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 134 | if (tflag > 1) { |
| 135 | printf("Pass 4: "); |
| 136 | print_resource_track(&rtrack); |
| 137 | } |
| 138 | } |
| 139 | |