2 * pass1b.c --- Pass #1b of e2fsck
4 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
5 * only invoked if pass 1 discovered blocks which are in use by more
8 * Pass1B scans the data blocks of all the inodes again, generating a
9 * complete list of duplicate blocks and which inodes have claimed
12 * Pass1C does a tree-traversal of the filesystem, to determine the
13 * parent directories of these inodes. This step is necessary so that
14 * e2fsck can print out the pathnames of affected inodes.
16 * Pass1D is a reconciliation pass. For each inode with duplicate
17 * blocks, the user is prompted if s/he would like to clone the file
18 * (so that the file gets a fresh copy of the duplicated blocks) or
19 * simply to delete the file.
21 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
24 * This file may be redistributed under the terms of the GNU Public
35 #ifdef HAVE_INTTYPES_H
40 typedef long intptr_t;
43 /* Needed for architectures where sizeof(int) != sizeof(void *) */
44 #define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val))
45 #define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr))
47 #include <et/com_err.h>
53 /* Define an extension to the ext2 library's block count information */
54 #define BLOCK_COUNT_EXTATTR (-5)
58 struct block_el
*next
;
63 struct inode_el
*next
;
68 struct inode_el
*inode_list
;
72 * This structure stores information about a particular inode which
73 * is sharing blocks with other inodes. This information is collected
74 * to display to the user, so that the user knows what files he or she
75 * is dealing with, when trying to decide how to resolve the conflict
76 * of multiply-claimed blocks.
81 struct ext2_inode inode
;
82 struct block_el
*block_list
;
85 static int process_pass1b_block(ext2_filsys fs
, blk64_t
*blocknr
,
86 e2_blkcnt_t blockcnt
, blk64_t ref_blk
,
87 int ref_offset
, void *priv_data
);
88 static void delete_file(e2fsck_t ctx
, ext2_ino_t ino
,
89 struct dup_inode
*dp
, char *block_buf
);
90 static int clone_file(e2fsck_t ctx
, ext2_ino_t ino
,
91 struct dup_inode
*dp
, char* block_buf
);
92 static int check_if_fs_block(e2fsck_t ctx
, blk64_t test_blk
);
94 static void pass1b(e2fsck_t ctx
, char *block_buf
);
95 static void pass1c(e2fsck_t ctx
, char *block_buf
);
96 static void pass1d(e2fsck_t ctx
, char *block_buf
);
98 static int dup_inode_count
= 0;
99 static int dup_inode_founddir
= 0;
101 static dict_t blk_dict
, ino_dict
;
103 static ext2fs_inode_bitmap inode_dup_map
;
105 static int dict_int_cmp(const void *a
, const void *b
)
116 * Add a duplicate block record
118 static void add_dupe(e2fsck_t ctx
, ext2_ino_t ino
, blk64_t blk
,
119 struct ext2_inode
*inode
)
122 struct dup_block
*db
;
123 struct dup_inode
*di
;
124 struct block_el
*blk_el
;
125 struct inode_el
*ino_el
;
127 n
= dict_lookup(&blk_dict
, INT_TO_VOIDPTR(blk
));
129 db
= (struct dup_block
*) dnode_get(n
);
131 db
= (struct dup_block
*) e2fsck_allocate_memory(ctx
,
132 sizeof(struct dup_block
), "duplicate block header");
135 dict_alloc_insert(&blk_dict
, INT_TO_VOIDPTR(blk
), db
);
137 ino_el
= (struct inode_el
*) e2fsck_allocate_memory(ctx
,
138 sizeof(struct inode_el
), "inode element");
140 ino_el
->next
= db
->inode_list
;
141 db
->inode_list
= ino_el
;
144 n
= dict_lookup(&ino_dict
, INT_TO_VOIDPTR(ino
));
146 di
= (struct dup_inode
*) dnode_get(n
);
148 di
= (struct dup_inode
*) e2fsck_allocate_memory(ctx
,
149 sizeof(struct dup_inode
), "duplicate inode header");
150 if (ino
== EXT2_ROOT_INO
) {
151 di
->dir
= EXT2_ROOT_INO
;
152 dup_inode_founddir
++;
156 di
->num_dupblocks
= 0;
159 dict_alloc_insert(&ino_dict
, INT_TO_VOIDPTR(ino
), di
);
161 blk_el
= (struct block_el
*) e2fsck_allocate_memory(ctx
,
162 sizeof(struct block_el
), "block element");
164 blk_el
->next
= di
->block_list
;
165 di
->block_list
= blk_el
;
170 * Free a duplicate inode record
172 static void inode_dnode_free(dnode_t
*node
,
173 void *context
EXT2FS_ATTR((unused
)))
175 struct dup_inode
*di
;
176 struct block_el
*p
, *next
;
178 di
= (struct dup_inode
*) dnode_get(node
);
179 for (p
= di
->block_list
; p
; p
= next
) {
188 * Free a duplicate block record
190 static void block_dnode_free(dnode_t
*node
,
191 void *context
EXT2FS_ATTR((unused
)))
193 struct dup_block
*db
;
194 struct inode_el
*p
, *next
;
196 db
= (struct dup_block
*) dnode_get(node
);
197 for (p
= db
->inode_list
; p
; p
= next
) {
207 * Main procedure for handling duplicate blocks
209 void e2fsck_pass1_dupblocks(e2fsck_t ctx
, char *block_buf
)
211 ext2_filsys fs
= ctx
->fs
;
212 struct problem_context pctx
;
213 #ifdef RESOURCE_TRACK
214 struct resource_track rtrack
;
217 clear_problem_context(&pctx
);
219 pctx
.errcode
= ext2fs_allocate_inode_bitmap(fs
,
220 _("multiply claimed inode map"), &inode_dup_map
);
222 fix_problem(ctx
, PR_1B_ALLOCATE_IBITMAP_ERROR
, &pctx
);
223 ctx
->flags
|= E2F_FLAG_ABORT
;
227 dict_init(&ino_dict
, DICTCOUNT_T_MAX
, dict_int_cmp
);
228 dict_init(&blk_dict
, DICTCOUNT_T_MAX
, dict_int_cmp
);
229 dict_set_allocator(&ino_dict
, NULL
, inode_dnode_free
, NULL
);
230 dict_set_allocator(&blk_dict
, NULL
, block_dnode_free
, NULL
);
232 init_resource_track(&rtrack
, ctx
->fs
->io
);
233 pass1b(ctx
, block_buf
);
234 print_resource_track(ctx
, "Pass 1b", &rtrack
, ctx
->fs
->io
);
236 init_resource_track(&rtrack
, ctx
->fs
->io
);
237 pass1c(ctx
, block_buf
);
238 print_resource_track(ctx
, "Pass 1c", &rtrack
, ctx
->fs
->io
);
240 init_resource_track(&rtrack
, ctx
->fs
->io
);
241 pass1d(ctx
, block_buf
);
242 print_resource_track(ctx
, "Pass 1d", &rtrack
, ctx
->fs
->io
);
245 * Time to free all of the accumulated data structures that we
246 * don't need anymore.
248 dict_free_nodes(&ino_dict
);
249 dict_free_nodes(&blk_dict
);
250 ext2fs_free_inode_bitmap(inode_dup_map
);
254 * Scan the inodes looking for inodes that contain duplicate blocks.
256 struct process_block_struct
{
260 struct ext2_inode
*inode
;
261 struct problem_context
*pctx
;
264 static void pass1b(e2fsck_t ctx
, char *block_buf
)
266 ext2_filsys fs
= ctx
->fs
;
268 struct ext2_inode inode
;
269 ext2_inode_scan scan
;
270 struct process_block_struct pb
;
271 struct problem_context pctx
;
273 clear_problem_context(&pctx
);
275 if (!(ctx
->options
& E2F_OPT_PREEN
))
276 fix_problem(ctx
, PR_1B_PASS_HEADER
, &pctx
);
277 pctx
.errcode
= ext2fs_open_inode_scan(fs
, ctx
->inode_buffer_blocks
,
280 fix_problem(ctx
, PR_1B_ISCAN_ERROR
, &pctx
);
281 ctx
->flags
|= E2F_FLAG_ABORT
;
284 ctx
->stashed_inode
= &inode
;
289 pctx
.errcode
= ext2fs_get_next_inode(scan
, &ino
, &inode
);
290 if (pctx
.errcode
== EXT2_ET_BAD_BLOCK_IN_INODE_TABLE
)
293 fix_problem(ctx
, PR_1B_ISCAN_ERROR
, &pctx
);
294 ctx
->flags
|= E2F_FLAG_ABORT
;
299 pctx
.ino
= ctx
->stashed_ino
= ino
;
300 if ((ino
!= EXT2_BAD_INO
) &&
301 !ext2fs_test_inode_bitmap2(ctx
->inode_used_map
, ino
))
308 if (ext2fs_inode_has_valid_blocks(&inode
) ||
309 (ino
== EXT2_BAD_INO
))
310 pctx
.errcode
= ext2fs_block_iterate3(fs
, ino
,
311 BLOCK_FLAG_READ_ONLY
, block_buf
,
312 process_pass1b_block
, &pb
);
313 if (ext2fs_file_acl_block(&inode
)) {
314 blk64_t blk
= ext2fs_file_acl_block(&inode
);
315 process_pass1b_block(fs
, &blk
,
316 BLOCK_COUNT_EXTATTR
, 0, 0, &pb
);
317 ext2fs_file_acl_block_set(&inode
, blk
);
320 end_problem_latch(ctx
, PR_LATCH_DBLOCK
);
321 if (ino
>= EXT2_FIRST_INODE(fs
->super
) ||
322 ino
== EXT2_ROOT_INO
)
326 fix_problem(ctx
, PR_1B_BLOCK_ITERATE
, &pctx
);
328 ext2fs_close_inode_scan(scan
);
329 e2fsck_use_inode_shortcuts(ctx
, 0);
332 static int process_pass1b_block(ext2_filsys fs
EXT2FS_ATTR((unused
)),
334 e2_blkcnt_t blockcnt
EXT2FS_ATTR((unused
)),
335 blk64_t ref_blk
EXT2FS_ATTR((unused
)),
336 int ref_offset
EXT2FS_ATTR((unused
)),
339 struct process_block_struct
*p
;
342 if (HOLE_BLKADDR(*block_nr
))
344 p
= (struct process_block_struct
*) priv_data
;
347 if (!ext2fs_test_block_bitmap2(ctx
->block_dup_map
, *block_nr
))
350 /* OK, this is a duplicate block */
351 if (p
->ino
!= EXT2_BAD_INO
) {
352 p
->pctx
->blk
= *block_nr
;
353 fix_problem(ctx
, PR_1B_DUP_BLOCK
, p
->pctx
);
356 ext2fs_mark_inode_bitmap2(inode_dup_map
, p
->ino
);
358 add_dupe(ctx
, p
->ino
, *block_nr
, p
->inode
);
364 * Pass 1c: Scan directories for inodes with duplicate blocks. This
365 * is used so that we can print pathnames when prompting the user for
368 struct search_dir_struct
{
370 ext2_ino_t first_inode
;
371 ext2_ino_t max_inode
;
374 static int search_dirent_proc(ext2_ino_t dir
, int entry
,
375 struct ext2_dir_entry
*dirent
,
376 int offset
EXT2FS_ATTR((unused
)),
377 int blocksize
EXT2FS_ATTR((unused
)),
378 char *buf
EXT2FS_ATTR((unused
)),
381 struct search_dir_struct
*sd
;
385 sd
= (struct search_dir_struct
*) priv_data
;
387 if (dirent
->inode
> sd
->max_inode
)
388 /* Should abort this inode, but not everything */
391 if ((dirent
->inode
< sd
->first_inode
) || (entry
< DIRENT_OTHER_FILE
) ||
392 !ext2fs_test_inode_bitmap2(inode_dup_map
, dirent
->inode
))
395 n
= dict_lookup(&ino_dict
, INT_TO_VOIDPTR(dirent
->inode
));
398 p
= (struct dup_inode
*) dnode_get(n
);
404 return(sd
->count
? 0 : DIRENT_ABORT
);
408 static void pass1c(e2fsck_t ctx
, char *block_buf
)
410 ext2_filsys fs
= ctx
->fs
;
411 struct search_dir_struct sd
;
412 struct problem_context pctx
;
414 clear_problem_context(&pctx
);
416 if (!(ctx
->options
& E2F_OPT_PREEN
))
417 fix_problem(ctx
, PR_1C_PASS_HEADER
, &pctx
);
420 * Search through all directories to translate inodes to names
421 * (by searching for the containing directory for that inode.)
423 sd
.count
= dup_inode_count
- dup_inode_founddir
;
424 sd
.first_inode
= EXT2_FIRST_INODE(fs
->super
);
425 sd
.max_inode
= fs
->super
->s_inodes_count
;
426 ext2fs_dblist_dir_iterate(fs
->dblist
, 0, block_buf
,
427 search_dirent_proc
, &sd
);
430 static void pass1d(e2fsck_t ctx
, char *block_buf
)
432 ext2_filsys fs
= ctx
->fs
;
433 struct dup_inode
*p
, *t
;
435 ext2_ino_t
*shared
, ino
;
440 struct problem_context pctx
;
445 clear_problem_context(&pctx
);
447 if (!(ctx
->options
& E2F_OPT_PREEN
))
448 fix_problem(ctx
, PR_1D_PASS_HEADER
, &pctx
);
449 e2fsck_read_bitmaps(ctx
);
451 pctx
.num
= dup_inode_count
; /* dict_count(&ino_dict); */
452 fix_problem(ctx
, PR_1D_NUM_DUP_INODES
, &pctx
);
453 shared
= (ext2_ino_t
*) e2fsck_allocate_memory(ctx
,
454 sizeof(ext2_ino_t
) * dict_count(&ino_dict
),
455 "Shared inode list");
456 for (n
= dict_first(&ino_dict
); n
; n
= dict_next(&ino_dict
, n
)) {
457 p
= (struct dup_inode
*) dnode_get(n
);
460 ino
= (ext2_ino_t
)VOIDPTR_TO_INT(dnode_getkey(n
));
461 if (ino
== EXT2_BAD_INO
|| ino
== EXT2_RESIZE_INO
)
465 * Find all of the inodes which share blocks with this
466 * one. First we find all of the duplicate blocks
467 * belonging to this inode, and then search each block
468 * get the list of inodes, and merge them together.
470 for (s
= p
->block_list
; s
; s
= s
->next
) {
471 m
= dict_lookup(&blk_dict
, INT_TO_VOIDPTR(s
->block
));
473 continue; /* Should never happen... */
474 q
= (struct dup_block
*) dnode_get(m
);
477 if (check_if_fs_block(ctx
, s
->block
)) {
483 * Add all inodes used by this block to the
484 * shared[] --- which is a unique list, so
485 * if an inode is already in shared[], don't
488 for (r
= q
->inode_list
; r
; r
= r
->next
) {
491 for (i
= 0; i
< shared_len
; i
++)
492 if (shared
[i
] == r
->inode
)
494 if (i
== shared_len
) {
495 shared
[shared_len
++] = r
->inode
;
501 * Report the inode that we are working on
503 pctx
.inode
= &p
->inode
;
506 pctx
.blkcount
= p
->num_dupblocks
;
507 pctx
.num
= meta_data
? shared_len
+1 : shared_len
;
508 fix_problem(ctx
, PR_1D_DUP_FILE
, &pctx
);
513 fix_problem(ctx
, PR_1D_SHARE_METADATA
, &pctx
);
515 for (i
= 0; i
< shared_len
; i
++) {
516 m
= dict_lookup(&ino_dict
, INT_TO_VOIDPTR(shared
[i
]));
518 continue; /* should never happen */
519 t
= (struct dup_inode
*) dnode_get(m
);
521 * Report the inode that we are sharing with
523 pctx
.inode
= &t
->inode
;
524 pctx
.ino
= shared
[i
];
526 fix_problem(ctx
, PR_1D_DUP_FILE_LIST
, &pctx
);
529 fix_problem(ctx
, PR_1D_DUP_BLOCKS_DEALT
, &pctx
);
532 if (fix_problem(ctx
, PR_1D_CLONE_QUESTION
, &pctx
)) {
533 pctx
.errcode
= clone_file(ctx
, ino
, p
, block_buf
);
535 fix_problem(ctx
, PR_1D_CLONE_ERROR
, &pctx
);
539 if (fix_problem(ctx
, PR_1D_DELETE_QUESTION
, &pctx
))
540 delete_file(ctx
, ino
, p
, block_buf
);
542 ext2fs_unmark_valid(fs
);
544 ext2fs_free_mem(&shared
);
548 * Drop the refcount on the dup_block structure, and clear the entry
549 * in the block_dup_map if appropriate.
551 static void decrement_badcount(e2fsck_t ctx
, blk64_t block
, struct dup_block
*p
)
554 if (p
->num_bad
<= 0 ||
555 (p
->num_bad
== 1 && !check_if_fs_block(ctx
, block
)))
556 ext2fs_unmark_block_bitmap2(ctx
->block_dup_map
, block
);
559 static int delete_file_block(ext2_filsys fs
,
561 e2_blkcnt_t blockcnt
EXT2FS_ATTR((unused
)),
562 blk64_t ref_block
EXT2FS_ATTR((unused
)),
563 int ref_offset
EXT2FS_ATTR((unused
)),
566 struct process_block_struct
*pb
;
571 pb
= (struct process_block_struct
*) priv_data
;
574 if (HOLE_BLKADDR(*block_nr
))
577 if (ext2fs_test_block_bitmap2(ctx
->block_dup_map
, *block_nr
)) {
578 n
= dict_lookup(&blk_dict
, INT_TO_VOIDPTR(*block_nr
));
580 p
= (struct dup_block
*) dnode_get(n
);
581 decrement_badcount(ctx
, *block_nr
, p
);
583 com_err("delete_file_block", 0,
584 _("internal error: can't find dup_blk for %llu\n"),
587 ext2fs_unmark_block_bitmap2(ctx
->block_found_map
, *block_nr
);
588 ext2fs_block_alloc_stats2(fs
, *block_nr
, -1);
594 static void delete_file(e2fsck_t ctx
, ext2_ino_t ino
,
595 struct dup_inode
*dp
, char* block_buf
)
597 ext2_filsys fs
= ctx
->fs
;
598 struct process_block_struct pb
;
599 struct ext2_inode inode
;
600 struct problem_context pctx
;
603 clear_problem_context(&pctx
);
604 pctx
.ino
= pb
.ino
= ino
;
605 pb
.dup_blocks
= dp
->num_dupblocks
;
607 pctx
.str
= "delete_file";
609 e2fsck_read_inode(ctx
, ino
, &inode
, "delete_file");
610 if (ext2fs_inode_has_valid_blocks(&inode
))
611 pctx
.errcode
= ext2fs_block_iterate3(fs
, ino
, BLOCK_FLAG_READ_ONLY
,
612 block_buf
, delete_file_block
, &pb
);
614 fix_problem(ctx
, PR_1B_BLOCK_ITERATE
, &pctx
);
615 if (ctx
->inode_bad_map
)
616 ext2fs_unmark_inode_bitmap2(ctx
->inode_bad_map
, ino
);
617 ext2fs_inode_alloc_stats2(fs
, ino
, -1, LINUX_S_ISDIR(inode
.i_mode
));
619 /* Inode may have changed by block_iterate, so reread it */
620 e2fsck_read_inode(ctx
, ino
, &inode
, "delete_file");
621 e2fsck_clear_inode(ctx
, ino
, &inode
, 0, "delete_file");
622 if (ext2fs_file_acl_block(&inode
) &&
623 (fs
->super
->s_feature_compat
& EXT2_FEATURE_COMPAT_EXT_ATTR
)) {
625 pctx
.errcode
= ext2fs_adjust_ea_refcount2(fs
,
626 ext2fs_file_acl_block(&inode
),
627 block_buf
, -1, &count
);
628 if (pctx
.errcode
== EXT2_ET_BAD_EA_BLOCK_NUM
) {
633 pctx
.blk
= ext2fs_file_acl_block(&inode
);
634 fix_problem(ctx
, PR_1B_ADJ_EA_REFCOUNT
, &pctx
);
637 * If the count is zero, then arrange to have the
638 * block deleted. If the block is in the block_dup_map,
639 * also call delete_file_block since it will take care
640 * of keeping the accounting straight.
643 ext2fs_test_block_bitmap2(ctx
->block_dup_map
,
644 ext2fs_file_acl_block(&inode
))) {
645 blk64_t blk
= ext2fs_file_acl_block(&inode
);
646 delete_file_block(fs
, &blk
,
647 BLOCK_COUNT_EXTATTR
, 0, 0, &pb
);
648 ext2fs_file_acl_block_set(&inode
, blk
);
653 struct clone_struct
{
660 static int clone_file_block(ext2_filsys fs
,
662 e2_blkcnt_t blockcnt
,
663 blk64_t ref_block
EXT2FS_ATTR((unused
)),
664 int ref_offset
EXT2FS_ATTR((unused
)),
670 struct clone_struct
*cs
= (struct clone_struct
*) priv_data
;
676 if (HOLE_BLKADDR(*block_nr
))
679 if (ext2fs_test_block_bitmap2(ctx
->block_dup_map
, *block_nr
)) {
680 n
= dict_lookup(&blk_dict
, INT_TO_VOIDPTR(*block_nr
));
682 p
= (struct dup_block
*) dnode_get(n
);
683 retval
= ext2fs_new_block2(fs
, 0, ctx
->block_found_map
,
686 cs
->errcode
= retval
;
689 if (cs
->dir
&& (blockcnt
>= 0)) {
690 retval
= ext2fs_set_dir_block2(fs
->dblist
,
691 cs
->dir
, new_block
, blockcnt
);
693 cs
->errcode
= retval
;
698 printf("Cloning block %u to %u\n", *block_nr
,
701 retval
= io_channel_read_blk64(fs
->io
, *block_nr
, 1,
704 cs
->errcode
= retval
;
707 retval
= io_channel_write_blk64(fs
->io
, new_block
, 1,
710 cs
->errcode
= retval
;
713 decrement_badcount(ctx
, *block_nr
, p
);
714 *block_nr
= new_block
;
715 ext2fs_mark_block_bitmap2(ctx
->block_found_map
,
717 ext2fs_mark_block_bitmap2(fs
->block_map
, new_block
);
718 return BLOCK_CHANGED
;
720 com_err("clone_file_block", 0,
721 _("internal error: can't find dup_blk for %llu\n"),
727 static int clone_file(e2fsck_t ctx
, ext2_ino_t ino
,
728 struct dup_inode
*dp
, char* block_buf
)
730 ext2_filsys fs
= ctx
->fs
;
732 struct clone_struct cs
;
733 struct problem_context pctx
;
734 blk64_t blk
, new_blk
;
736 struct inode_el
*ino_el
;
737 struct dup_block
*db
;
738 struct dup_inode
*di
;
740 clear_problem_context(&pctx
);
744 retval
= ext2fs_get_mem(fs
->blocksize
, &cs
.buf
);
748 if (ext2fs_test_inode_bitmap2(ctx
->inode_dir_map
, ino
))
752 pctx
.str
= "clone_file";
753 if (ext2fs_inode_has_valid_blocks(&dp
->inode
))
754 pctx
.errcode
= ext2fs_block_iterate3(fs
, ino
, 0, block_buf
,
755 clone_file_block
, &cs
);
756 ext2fs_mark_bb_dirty(fs
);
758 fix_problem(ctx
, PR_1B_BLOCK_ITERATE
, &pctx
);
759 retval
= pctx
.errcode
;
763 com_err("clone_file", cs
.errcode
,
764 _("returned from clone_file_block"));
768 /* The inode may have changed on disk, so we have to re-read it */
769 e2fsck_read_inode(ctx
, ino
, &dp
->inode
, "clone file EA");
770 blk
= ext2fs_file_acl_block(&dp
->inode
);
772 if (blk
&& (clone_file_block(fs
, &new_blk
,
773 BLOCK_COUNT_EXTATTR
, 0, 0, &cs
) ==
775 ext2fs_file_acl_block_set(&dp
->inode
, new_blk
);
776 e2fsck_write_inode(ctx
, ino
, &dp
->inode
, "clone file EA");
778 * If we cloned the EA block, find all other inodes
779 * which refered to that EA block, and modify
780 * them to point to the new EA block.
782 n
= dict_lookup(&blk_dict
, INT_TO_VOIDPTR(blk
));
784 com_err("clone_file", 0,
785 _("internal error: couldn't lookup EA "
786 "block record for %llu"), blk
);
787 retval
= 0; /* OK to stumble on... */
790 db
= (struct dup_block
*) dnode_get(n
);
791 for (ino_el
= db
->inode_list
; ino_el
; ino_el
= ino_el
->next
) {
792 if (ino_el
->inode
== ino
)
794 n
= dict_lookup(&ino_dict
, INT_TO_VOIDPTR(ino_el
->inode
));
796 com_err("clone_file", 0,
797 _("internal error: couldn't lookup EA "
798 "inode record for %u"),
800 retval
= 0; /* OK to stumble on... */
803 di
= (struct dup_inode
*) dnode_get(n
);
804 if (ext2fs_file_acl_block(&di
->inode
) == blk
) {
805 ext2fs_file_acl_block_set(&di
->inode
,
806 ext2fs_file_acl_block(&dp
->inode
));
807 e2fsck_write_inode(ctx
, ino_el
->inode
,
808 &di
->inode
, "clone file EA");
809 decrement_badcount(ctx
, blk
, db
);
815 ext2fs_free_mem(&cs
.buf
);
820 * This routine returns 1 if a block overlaps with one of the superblocks,
821 * group descriptors, inode bitmaps, or block bitmaps.
823 static int check_if_fs_block(e2fsck_t ctx
, blk64_t test_block
)
825 ext2_filsys fs
= ctx
->fs
;
829 first_block
= fs
->super
->s_first_data_block
;
830 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
832 /* Check superblocks/block group descriptors */
833 if (ext2fs_bg_has_super(fs
, i
)) {
834 if (test_block
>= first_block
&&
835 (test_block
<= first_block
+ fs
->desc_blocks
))
839 /* Check the inode table */
840 if ((ext2fs_inode_table_loc(fs
, i
)) &&
841 (test_block
>= ext2fs_inode_table_loc(fs
, i
)) &&
842 (test_block
< (ext2fs_inode_table_loc(fs
, i
) +
843 fs
->inode_blocks_per_group
)))
846 /* Check the bitmap blocks */
847 if ((test_block
== ext2fs_block_bitmap_loc(fs
, i
)) ||
848 (test_block
== ext2fs_inode_bitmap_loc(fs
, i
)))
851 first_block
+= fs
->super
->s_blocks_per_group
;