pass1b.c revision f9f3050a0ad9be1c37b00c8478199d286ddcaeda
1/* 2 * pass1b.c --- Pass #1b of e2fsck 3 * 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 6 * than one inode. 7 * 8 * Pass1B scans the data blocks of all the inodes again, generating a 9 * complete list of duplicate blocks and which inodes have claimed 10 * them. 11 * 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. 15 * 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. 20 * 21 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. 22 * 23 * %Begin-Header% 24 * This file may be redistributed under the terms of the GNU Public 25 * License. 26 * %End-Header% 27 * 28 */ 29 30#include "config.h" 31#include <time.h> 32#ifdef HAVE_ERRNO_H 33#include <errno.h> 34#endif 35 36#ifdef HAVE_INTTYPES_H 37#include <inttypes.h> 38#endif 39 40#ifndef HAVE_INTPTR_T 41typedef long intptr_t; 42#endif 43 44/* Needed for architectures where sizeof(int) != sizeof(void *) */ 45#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val)) 46#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr)) 47 48#include <et/com_err.h> 49#include "e2fsck.h" 50 51#include "problem.h" 52#include "dict.h" 53 54/* Define an extension to the ext2 library's block count information */ 55#define BLOCK_COUNT_EXTATTR (-5) 56 57struct cluster_el { 58 blk64_t cluster; 59 struct cluster_el *next; 60}; 61 62struct inode_el { 63 ext2_ino_t inode; 64 struct inode_el *next; 65}; 66 67struct dup_cluster { 68 int num_bad; 69 struct inode_el *inode_list; 70}; 71 72/* 73 * This structure stores information about a particular inode which 74 * is sharing blocks with other inodes. This information is collected 75 * to display to the user, so that the user knows what files he or she 76 * is dealing with, when trying to decide how to resolve the conflict 77 * of multiply-claimed blocks. 78 */ 79struct dup_inode { 80 ext2_ino_t dir; 81 int num_dupblocks; 82 struct ext2_inode inode; 83 struct cluster_el *cluster_list; 84}; 85 86static int process_pass1b_block(ext2_filsys fs, blk64_t *blocknr, 87 e2_blkcnt_t blockcnt, blk64_t ref_blk, 88 int ref_offset, void *priv_data); 89static void delete_file(e2fsck_t ctx, ext2_ino_t ino, 90 struct dup_inode *dp, char *block_buf); 91static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino, 92 struct dup_inode *dp, char* block_buf); 93static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block); 94static int check_if_fs_cluster(e2fsck_t ctx, blk64_t cluster); 95 96static void pass1b(e2fsck_t ctx, char *block_buf); 97static void pass1c(e2fsck_t ctx, char *block_buf); 98static void pass1d(e2fsck_t ctx, char *block_buf); 99 100static int dup_inode_count = 0; 101static int dup_inode_founddir = 0; 102 103static dict_t clstr_dict, ino_dict; 104 105static ext2fs_inode_bitmap inode_dup_map; 106 107static int dict_int_cmp(const void *a, const void *b) 108{ 109 intptr_t ia, ib; 110 111 ia = (intptr_t)a; 112 ib = (intptr_t)b; 113 114 return (ia-ib); 115} 116 117/* 118 * Add a duplicate block record 119 */ 120static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk64_t cluster, 121 struct ext2_inode *inode) 122{ 123 dnode_t *n; 124 struct dup_cluster *db; 125 struct dup_inode *di; 126 struct cluster_el *cluster_el; 127 struct inode_el *ino_el; 128 129 n = dict_lookup(&clstr_dict, INT_TO_VOIDPTR(cluster)); 130 if (n) 131 db = (struct dup_cluster *) dnode_get(n); 132 else { 133 db = (struct dup_cluster *) e2fsck_allocate_memory(ctx, 134 sizeof(struct dup_cluster), "duplicate cluster header"); 135 db->num_bad = 0; 136 db->inode_list = 0; 137 dict_alloc_insert(&clstr_dict, INT_TO_VOIDPTR(cluster), db); 138 } 139 ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx, 140 sizeof(struct inode_el), "inode element"); 141 ino_el->inode = ino; 142 ino_el->next = db->inode_list; 143 db->inode_list = ino_el; 144 db->num_bad++; 145 146 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino)); 147 if (n) 148 di = (struct dup_inode *) dnode_get(n); 149 else { 150 di = (struct dup_inode *) e2fsck_allocate_memory(ctx, 151 sizeof(struct dup_inode), "duplicate inode header"); 152 if (ino == EXT2_ROOT_INO) { 153 di->dir = EXT2_ROOT_INO; 154 dup_inode_founddir++; 155 } else 156 di->dir = 0; 157 158 di->num_dupblocks = 0; 159 di->cluster_list = 0; 160 di->inode = *inode; 161 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di); 162 } 163 cluster_el = (struct cluster_el *) e2fsck_allocate_memory(ctx, 164 sizeof(struct cluster_el), "cluster element"); 165 cluster_el->cluster = cluster; 166 cluster_el->next = di->cluster_list; 167 di->cluster_list = cluster_el; 168 di->num_dupblocks++; 169} 170 171/* 172 * Free a duplicate inode record 173 */ 174static void inode_dnode_free(dnode_t *node, 175 void *context EXT2FS_ATTR((unused))) 176{ 177 struct dup_inode *di; 178 struct cluster_el *p, *next; 179 180 di = (struct dup_inode *) dnode_get(node); 181 for (p = di->cluster_list; p; p = next) { 182 next = p->next; 183 free(p); 184 } 185 free(di); 186 free(node); 187} 188 189/* 190 * Free a duplicate cluster record 191 */ 192static void cluster_dnode_free(dnode_t *node, 193 void *context EXT2FS_ATTR((unused))) 194{ 195 struct dup_cluster *dc; 196 struct inode_el *p, *next; 197 198 dc = (struct dup_cluster *) dnode_get(node); 199 for (p = dc->inode_list; p; p = next) { 200 next = p->next; 201 free(p); 202 } 203 free(dc); 204 free(node); 205} 206 207 208/* 209 * Main procedure for handling duplicate blocks 210 */ 211void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf) 212{ 213 ext2_filsys fs = ctx->fs; 214 struct problem_context pctx; 215#ifdef RESOURCE_TRACK 216 struct resource_track rtrack; 217#endif 218 219 clear_problem_context(&pctx); 220 221 pctx.errcode = e2fsck_allocate_inode_bitmap(fs, 222 _("multiply claimed inode map"), 223 EXT2FS_BMAP64_RBTREE, "inode_dup_map", 224 &inode_dup_map); 225 if (pctx.errcode) { 226 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx); 227 ctx->flags |= E2F_FLAG_ABORT; 228 return; 229 } 230 231 dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp); 232 dict_init(&clstr_dict, DICTCOUNT_T_MAX, dict_int_cmp); 233 dict_set_allocator(&ino_dict, NULL, inode_dnode_free, NULL); 234 dict_set_allocator(&clstr_dict, NULL, cluster_dnode_free, NULL); 235 236 init_resource_track(&rtrack, ctx->fs->io); 237 pass1b(ctx, block_buf); 238 print_resource_track(ctx, "Pass 1b", &rtrack, ctx->fs->io); 239 240 init_resource_track(&rtrack, ctx->fs->io); 241 pass1c(ctx, block_buf); 242 print_resource_track(ctx, "Pass 1c", &rtrack, ctx->fs->io); 243 244 init_resource_track(&rtrack, ctx->fs->io); 245 pass1d(ctx, block_buf); 246 print_resource_track(ctx, "Pass 1d", &rtrack, ctx->fs->io); 247 248 /* 249 * Time to free all of the accumulated data structures that we 250 * don't need anymore. 251 */ 252 dict_free_nodes(&ino_dict); 253 dict_free_nodes(&clstr_dict); 254 ext2fs_free_inode_bitmap(inode_dup_map); 255} 256 257/* 258 * Scan the inodes looking for inodes that contain duplicate blocks. 259 */ 260struct process_block_struct { 261 e2fsck_t ctx; 262 ext2_ino_t ino; 263 int dup_blocks; 264 blk64_t cur_cluster; 265 blk64_t last_blk; 266 struct ext2_inode *inode; 267 struct problem_context *pctx; 268}; 269 270static void pass1b(e2fsck_t ctx, char *block_buf) 271{ 272 ext2_filsys fs = ctx->fs; 273 ext2_ino_t ino = 0; 274 struct ext2_inode inode; 275 ext2_inode_scan scan; 276 struct process_block_struct pb; 277 struct problem_context pctx; 278 problem_t op; 279 280 clear_problem_context(&pctx); 281 282 if (!(ctx->options & E2F_OPT_PREEN)) 283 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx); 284 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks, 285 &scan); 286 if (pctx.errcode) { 287 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); 288 ctx->flags |= E2F_FLAG_ABORT; 289 return; 290 } 291 ctx->stashed_inode = &inode; 292 pb.ctx = ctx; 293 pb.pctx = &pctx; 294 pctx.str = "pass1b"; 295 while (1) { 296 if (ino % (fs->super->s_inodes_per_group * 4) == 1) { 297 if (e2fsck_mmp_update(fs)) 298 fatal_error(ctx, 0); 299 } 300 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode); 301 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) 302 continue; 303 if (pctx.errcode) { 304 pctx.ino = ino; 305 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); 306 ctx->flags |= E2F_FLAG_ABORT; 307 return; 308 } 309 if (!ino) 310 break; 311 pctx.ino = ctx->stashed_ino = ino; 312 if ((ino != EXT2_BAD_INO) && 313 !ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino)) 314 continue; 315 316 pb.ino = ino; 317 pb.dup_blocks = 0; 318 pb.inode = &inode; 319 pb.cur_cluster = ~0; 320 pb.last_blk = 0; 321 pb.pctx->blk = pb.pctx->blk2 = 0; 322 323 if (ext2fs_inode_has_valid_blocks2(fs, &inode) || 324 (ino == EXT2_BAD_INO)) 325 pctx.errcode = ext2fs_block_iterate3(fs, ino, 326 BLOCK_FLAG_READ_ONLY, block_buf, 327 process_pass1b_block, &pb); 328 /* If the feature is not set, attrs will be cleared later anyway */ 329 if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) && 330 ext2fs_file_acl_block(fs, &inode)) { 331 blk64_t blk = ext2fs_file_acl_block(fs, &inode); 332 process_pass1b_block(fs, &blk, 333 BLOCK_COUNT_EXTATTR, 0, 0, &pb); 334 ext2fs_file_acl_block_set(fs, &inode, blk); 335 } 336 if (pb.dup_blocks) { 337 if (ino != EXT2_BAD_INO) { 338 op = pctx.blk == pctx.blk2 ? 339 PR_1B_DUP_BLOCK : PR_1B_DUP_RANGE; 340 fix_problem(ctx, op, pb.pctx); 341 } 342 end_problem_latch(ctx, PR_LATCH_DBLOCK); 343 if (ino >= EXT2_FIRST_INODE(fs->super) || 344 ino == EXT2_ROOT_INO) 345 dup_inode_count++; 346 } 347 if (pctx.errcode) 348 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); 349 } 350 ext2fs_close_inode_scan(scan); 351 e2fsck_use_inode_shortcuts(ctx, 0); 352} 353 354static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)), 355 blk64_t *block_nr, 356 e2_blkcnt_t blockcnt, 357 blk64_t ref_blk EXT2FS_ATTR((unused)), 358 int ref_offset EXT2FS_ATTR((unused)), 359 void *priv_data) 360{ 361 struct process_block_struct *p; 362 e2fsck_t ctx; 363 blk64_t lc; 364 problem_t op; 365 366 if (HOLE_BLKADDR(*block_nr)) 367 return 0; 368 p = (struct process_block_struct *) priv_data; 369 ctx = p->ctx; 370 lc = EXT2FS_B2C(fs, blockcnt); 371 372 if (!ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) 373 goto finish; 374 375 /* OK, this is a duplicate block */ 376 if (p->ino != EXT2_BAD_INO) { 377 if (p->last_blk + 1 != *block_nr) { 378 if (p->last_blk) { 379 op = p->pctx->blk == p->pctx->blk2 ? 380 PR_1B_DUP_BLOCK : 381 PR_1B_DUP_RANGE; 382 fix_problem(ctx, op, p->pctx); 383 } 384 p->pctx->blk = *block_nr; 385 } 386 p->pctx->blk2 = *block_nr; 387 p->last_blk = *block_nr; 388 } 389 p->dup_blocks++; 390 ext2fs_mark_inode_bitmap2(inode_dup_map, p->ino); 391 392 if (lc != p->cur_cluster) 393 add_dupe(ctx, p->ino, EXT2FS_B2C(fs, *block_nr), p->inode); 394 395finish: 396 p->cur_cluster = lc; 397 return 0; 398} 399 400/* 401 * Pass 1c: Scan directories for inodes with duplicate blocks. This 402 * is used so that we can print pathnames when prompting the user for 403 * what to do. 404 */ 405struct search_dir_struct { 406 int count; 407 ext2_ino_t first_inode; 408 ext2_ino_t max_inode; 409}; 410 411static int search_dirent_proc(ext2_ino_t dir, int entry, 412 struct ext2_dir_entry *dirent, 413 int offset EXT2FS_ATTR((unused)), 414 int blocksize EXT2FS_ATTR((unused)), 415 char *buf EXT2FS_ATTR((unused)), 416 void *priv_data) 417{ 418 struct search_dir_struct *sd; 419 struct dup_inode *p; 420 dnode_t *n; 421 422 sd = (struct search_dir_struct *) priv_data; 423 424 if (dirent->inode > sd->max_inode) 425 /* Should abort this inode, but not everything */ 426 return 0; 427 428 if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) || 429 !ext2fs_test_inode_bitmap2(inode_dup_map, dirent->inode)) 430 return 0; 431 432 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode)); 433 if (!n) 434 return 0; 435 p = (struct dup_inode *) dnode_get(n); 436 if (!p->dir) { 437 p->dir = dir; 438 sd->count--; 439 } 440 441 return(sd->count ? 0 : DIRENT_ABORT); 442} 443 444 445static void pass1c(e2fsck_t ctx, char *block_buf) 446{ 447 ext2_filsys fs = ctx->fs; 448 struct search_dir_struct sd; 449 struct problem_context pctx; 450 451 clear_problem_context(&pctx); 452 453 if (!(ctx->options & E2F_OPT_PREEN)) 454 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx); 455 456 /* 457 * Search through all directories to translate inodes to names 458 * (by searching for the containing directory for that inode.) 459 */ 460 sd.count = dup_inode_count - dup_inode_founddir; 461 sd.first_inode = EXT2_FIRST_INODE(fs->super); 462 sd.max_inode = fs->super->s_inodes_count; 463 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf, 464 search_dirent_proc, &sd); 465} 466 467static void pass1d(e2fsck_t ctx, char *block_buf) 468{ 469 ext2_filsys fs = ctx->fs; 470 struct dup_inode *p, *t; 471 struct dup_cluster *q; 472 ext2_ino_t *shared, ino; 473 int shared_len; 474 int i; 475 int file_ok; 476 int meta_data = 0; 477 struct problem_context pctx; 478 dnode_t *n, *m; 479 struct cluster_el *s; 480 struct inode_el *r; 481 482 clear_problem_context(&pctx); 483 484 if (!(ctx->options & E2F_OPT_PREEN)) 485 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx); 486 e2fsck_read_bitmaps(ctx); 487 488 pctx.num = dup_inode_count; /* dict_count(&ino_dict); */ 489 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx); 490 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx, 491 sizeof(ext2_ino_t) * dict_count(&ino_dict), 492 "Shared inode list"); 493 for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) { 494 p = (struct dup_inode *) dnode_get(n); 495 shared_len = 0; 496 file_ok = 1; 497 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n)); 498 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO) 499 continue; 500 501 /* 502 * Find all of the inodes which share blocks with this 503 * one. First we find all of the duplicate blocks 504 * belonging to this inode, and then search each block 505 * get the list of inodes, and merge them together. 506 */ 507 for (s = p->cluster_list; s; s = s->next) { 508 m = dict_lookup(&clstr_dict, 509 INT_TO_VOIDPTR(s->cluster)); 510 if (!m) 511 continue; /* Should never happen... */ 512 q = (struct dup_cluster *) dnode_get(m); 513 if (q->num_bad > 1) 514 file_ok = 0; 515 if (check_if_fs_cluster(ctx, s->cluster)) { 516 file_ok = 0; 517 meta_data = 1; 518 } 519 520 /* 521 * Add all inodes used by this block to the 522 * shared[] --- which is a unique list, so 523 * if an inode is already in shared[], don't 524 * add it again. 525 */ 526 for (r = q->inode_list; r; r = r->next) { 527 if (r->inode == ino) 528 continue; 529 for (i = 0; i < shared_len; i++) 530 if (shared[i] == r->inode) 531 break; 532 if (i == shared_len) { 533 shared[shared_len++] = r->inode; 534 } 535 } 536 } 537 538 /* 539 * Report the inode that we are working on 540 */ 541 pctx.inode = &p->inode; 542 pctx.ino = ino; 543 pctx.dir = p->dir; 544 pctx.blkcount = p->num_dupblocks; 545 pctx.num = meta_data ? shared_len+1 : shared_len; 546 fix_problem(ctx, PR_1D_DUP_FILE, &pctx); 547 pctx.blkcount = 0; 548 pctx.num = 0; 549 550 if (meta_data) 551 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx); 552 553 for (i = 0; i < shared_len; i++) { 554 m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i])); 555 if (!m) 556 continue; /* should never happen */ 557 t = (struct dup_inode *) dnode_get(m); 558 /* 559 * Report the inode that we are sharing with 560 */ 561 pctx.inode = &t->inode; 562 pctx.ino = shared[i]; 563 pctx.dir = t->dir; 564 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx); 565 } 566 if (file_ok) { 567 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx); 568 continue; 569 } 570 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) { 571 pctx.errcode = clone_file(ctx, ino, p, block_buf); 572 if (pctx.errcode) 573 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx); 574 else 575 continue; 576 } 577 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx)) 578 delete_file(ctx, ino, p, block_buf); 579 else 580 ext2fs_unmark_valid(fs); 581 } 582 ext2fs_free_mem(&shared); 583} 584 585/* 586 * Drop the refcount on the dup_block structure, and clear the entry 587 * in the block_dup_map if appropriate. 588 */ 589static void decrement_badcount(e2fsck_t ctx, blk64_t block, 590 struct dup_cluster *p) 591{ 592 p->num_bad--; 593 if (p->num_bad <= 0 || 594 (p->num_bad == 1 && !check_if_fs_block(ctx, block))) { 595 if (check_if_fs_cluster(ctx, EXT2FS_B2C(ctx->fs, block))) 596 return; 597 ext2fs_unmark_block_bitmap2(ctx->block_dup_map, block); 598 } 599} 600 601static int delete_file_block(ext2_filsys fs, 602 blk64_t *block_nr, 603 e2_blkcnt_t blockcnt, 604 blk64_t ref_block EXT2FS_ATTR((unused)), 605 int ref_offset EXT2FS_ATTR((unused)), 606 void *priv_data) 607{ 608 struct process_block_struct *pb; 609 struct dup_cluster *p; 610 dnode_t *n; 611 e2fsck_t ctx; 612 blk64_t c, lc; 613 614 pb = (struct process_block_struct *) priv_data; 615 ctx = pb->ctx; 616 617 if (HOLE_BLKADDR(*block_nr)) 618 return 0; 619 620 c = EXT2FS_B2C(fs, *block_nr); 621 lc = EXT2FS_B2C(fs, blockcnt); 622 if (ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) { 623 n = dict_lookup(&clstr_dict, INT_TO_VOIDPTR(c)); 624 if (n) { 625 p = (struct dup_cluster *) dnode_get(n); 626 if (lc != pb->cur_cluster) 627 decrement_badcount(ctx, *block_nr, p); 628 } else 629 com_err("delete_file_block", 0, 630 _("internal error: can't find dup_blk for %llu\n"), 631 *block_nr); 632 } else { 633 ext2fs_unmark_block_bitmap2(ctx->block_found_map, *block_nr); 634 ext2fs_block_alloc_stats2(fs, *block_nr, -1); 635 pb->dup_blocks++; 636 } 637 pb->cur_cluster = lc; 638 639 return 0; 640} 641 642static void delete_file(e2fsck_t ctx, ext2_ino_t ino, 643 struct dup_inode *dp, char* block_buf) 644{ 645 ext2_filsys fs = ctx->fs; 646 struct process_block_struct pb; 647 struct problem_context pctx; 648 unsigned int count; 649 650 clear_problem_context(&pctx); 651 pctx.ino = pb.ino = ino; 652 pb.dup_blocks = 0; 653 pb.ctx = ctx; 654 pctx.str = "delete_file"; 655 pb.cur_cluster = ~0; 656 657 if (ext2fs_inode_has_valid_blocks2(fs, &dp->inode)) 658 pctx.errcode = ext2fs_block_iterate3(fs, ino, 659 BLOCK_FLAG_READ_ONLY, 660 block_buf, 661 delete_file_block, &pb); 662 if (pctx.errcode) 663 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); 664 if (ctx->inode_bad_map) 665 ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); 666 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(dp->inode.i_mode)); 667 quota_data_sub(ctx->qctx, &dp->inode, ino, 668 pb.dup_blocks * fs->blocksize); 669 quota_data_inodes(ctx->qctx, &dp->inode, ino, -1); 670 671 /* Inode may have changed by block_iterate, so reread it */ 672 e2fsck_read_inode(ctx, ino, &dp->inode, "delete_file"); 673 e2fsck_clear_inode(ctx, ino, &dp->inode, 0, "delete_file"); 674 if (ext2fs_file_acl_block(fs, &dp->inode) && 675 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 676 count = 1; 677 pctx.errcode = ext2fs_adjust_ea_refcount3(fs, 678 ext2fs_file_acl_block(fs, &dp->inode), 679 block_buf, -1, &count, ino); 680 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { 681 pctx.errcode = 0; 682 count = 1; 683 } 684 if (pctx.errcode) { 685 pctx.blk = ext2fs_file_acl_block(fs, &dp->inode); 686 fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx); 687 } 688 /* 689 * If the count is zero, then arrange to have the 690 * block deleted. If the block is in the block_dup_map, 691 * also call delete_file_block since it will take care 692 * of keeping the accounting straight. 693 */ 694 if ((count == 0) || 695 ext2fs_test_block_bitmap2(ctx->block_dup_map, 696 ext2fs_file_acl_block(fs, &dp->inode))) { 697 blk64_t blk = ext2fs_file_acl_block(fs, &dp->inode); 698 delete_file_block(fs, &blk, 699 BLOCK_COUNT_EXTATTR, 0, 0, &pb); 700 ext2fs_file_acl_block_set(fs, &dp->inode, blk); 701 quota_data_sub(ctx->qctx, &dp->inode, ino, fs->blocksize); 702 } 703 } 704} 705 706struct clone_struct { 707 errcode_t errcode; 708 blk64_t dup_cluster; 709 blk64_t alloc_block; 710 ext2_ino_t dir; 711 char *buf; 712 e2fsck_t ctx; 713}; 714 715static int clone_file_block(ext2_filsys fs, 716 blk64_t *block_nr, 717 e2_blkcnt_t blockcnt, 718 blk64_t ref_block EXT2FS_ATTR((unused)), 719 int ref_offset EXT2FS_ATTR((unused)), 720 void *priv_data) 721{ 722 struct dup_cluster *p; 723 blk64_t new_block; 724 errcode_t retval; 725 struct clone_struct *cs = (struct clone_struct *) priv_data; 726 dnode_t *n; 727 e2fsck_t ctx; 728 blk64_t c; 729 int is_meta = 0; 730 731 ctx = cs->ctx; 732 733 if (HOLE_BLKADDR(*block_nr)) 734 return 0; 735 736 c = EXT2FS_B2C(fs, blockcnt); 737 if (check_if_fs_cluster(ctx, EXT2FS_B2C(fs, *block_nr))) 738 is_meta = 1; 739 740 if (c == cs->dup_cluster && cs->alloc_block) { 741 new_block = cs->alloc_block; 742 goto got_block; 743 } 744 745 if (ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) { 746 n = dict_lookup(&clstr_dict, 747 INT_TO_VOIDPTR(EXT2FS_B2C(fs, *block_nr))); 748 if (!n) { 749 com_err("clone_file_block", 0, 750 _("internal error: can't find dup_blk for %llu\n"), 751 *block_nr); 752 return 0; 753 } 754 755 p = (struct dup_cluster *) dnode_get(n); 756 if (!is_meta) 757 decrement_badcount(ctx, *block_nr, p); 758 759 cs->dup_cluster = c; 760 761 retval = ext2fs_new_block2(fs, 0, ctx->block_found_map, 762 &new_block); 763 if (retval) { 764 cs->errcode = retval; 765 return BLOCK_ABORT; 766 } 767 cs->alloc_block = new_block; 768 769 got_block: 770 new_block &= ~EXT2FS_CLUSTER_MASK(fs); 771 new_block += EXT2FS_CLUSTER_MASK(fs) & blockcnt; 772 if (cs->dir && (blockcnt >= 0)) { 773 retval = ext2fs_set_dir_block2(fs->dblist, 774 cs->dir, new_block, blockcnt); 775 if (retval) { 776 cs->errcode = retval; 777 return BLOCK_ABORT; 778 } 779 } 780#if 0 781 printf("Cloning block #%lld from %llu to %llu\n", 782 blockcnt, *block_nr, new_block); 783#endif 784 retval = io_channel_read_blk64(fs->io, *block_nr, 1, cs->buf); 785 if (retval) { 786 cs->errcode = retval; 787 return BLOCK_ABORT; 788 } 789 retval = io_channel_write_blk64(fs->io, new_block, 1, cs->buf); 790 if (retval) { 791 cs->errcode = retval; 792 return BLOCK_ABORT; 793 } 794 *block_nr = new_block; 795 ext2fs_mark_block_bitmap2(ctx->block_found_map, new_block); 796 ext2fs_mark_block_bitmap2(fs->block_map, new_block); 797 return BLOCK_CHANGED; 798 } 799 return 0; 800} 801 802static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino, 803 struct dup_inode *dp, char* block_buf) 804{ 805 ext2_filsys fs = ctx->fs; 806 errcode_t retval; 807 struct clone_struct cs; 808 struct problem_context pctx; 809 blk64_t blk, new_blk; 810 dnode_t *n; 811 struct inode_el *ino_el; 812 struct dup_cluster *dc; 813 struct dup_inode *di; 814 815 clear_problem_context(&pctx); 816 cs.errcode = 0; 817 cs.dir = 0; 818 cs.dup_cluster = ~0; 819 cs.alloc_block = 0; 820 cs.ctx = ctx; 821 retval = ext2fs_get_mem(fs->blocksize, &cs.buf); 822 if (retval) 823 return retval; 824 825 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, ino)) 826 cs.dir = ino; 827 828 pctx.ino = ino; 829 pctx.str = "clone_file"; 830 if (ext2fs_inode_has_valid_blocks2(fs, &dp->inode)) 831 pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, 832 clone_file_block, &cs); 833 ext2fs_mark_bb_dirty(fs); 834 if (pctx.errcode) { 835 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); 836 retval = pctx.errcode; 837 goto errout; 838 } 839 if (cs.errcode) { 840 com_err("clone_file", cs.errcode, "%s", 841 _("returned from clone_file_block")); 842 retval = cs.errcode; 843 goto errout; 844 } 845 /* The inode may have changed on disk, so we have to re-read it */ 846 e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA"); 847 blk = ext2fs_file_acl_block(fs, &dp->inode); 848 new_blk = blk; 849 if (blk && (clone_file_block(fs, &new_blk, 850 BLOCK_COUNT_EXTATTR, 0, 0, &cs) == 851 BLOCK_CHANGED)) { 852 ext2fs_file_acl_block_set(fs, &dp->inode, new_blk); 853 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA"); 854 /* 855 * If we cloned the EA block, find all other inodes 856 * which refered to that EA block, and modify 857 * them to point to the new EA block. 858 */ 859 n = dict_lookup(&clstr_dict, 860 INT_TO_VOIDPTR(EXT2FS_B2C(fs, blk))); 861 if (!n) { 862 com_err("clone_file", 0, 863 _("internal error: couldn't lookup EA " 864 "block record for %llu"), blk); 865 retval = 0; /* OK to stumble on... */ 866 goto errout; 867 } 868 dc = (struct dup_cluster *) dnode_get(n); 869 for (ino_el = dc->inode_list; ino_el; ino_el = ino_el->next) { 870 if (ino_el->inode == ino) 871 continue; 872 n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode)); 873 if (!n) { 874 com_err("clone_file", 0, 875 _("internal error: couldn't lookup EA " 876 "inode record for %u"), 877 ino_el->inode); 878 retval = 0; /* OK to stumble on... */ 879 goto errout; 880 } 881 di = (struct dup_inode *) dnode_get(n); 882 if (ext2fs_file_acl_block(fs, &di->inode) == blk) { 883 ext2fs_file_acl_block_set(fs, &di->inode, 884 ext2fs_file_acl_block(fs, &dp->inode)); 885 e2fsck_write_inode(ctx, ino_el->inode, 886 &di->inode, "clone file EA"); 887 decrement_badcount(ctx, blk, dc); 888 } 889 } 890 } 891 retval = 0; 892errout: 893 ext2fs_free_mem(&cs.buf); 894 return retval; 895} 896 897/* 898 * This routine returns 1 if a block overlaps with one of the superblocks, 899 * group descriptors, inode bitmaps, or block bitmaps. 900 */ 901static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block) 902{ 903 ext2_filsys fs = ctx->fs; 904 blk64_t first_block; 905 dgrp_t i; 906 907 first_block = fs->super->s_first_data_block; 908 for (i = 0; i < fs->group_desc_count; i++) { 909 910 /* Check superblocks/block group descriptors */ 911 if (ext2fs_bg_has_super(fs, i)) { 912 if (test_block >= first_block && 913 (test_block <= first_block + fs->desc_blocks)) 914 return 1; 915 } 916 917 /* Check the inode table */ 918 if ((ext2fs_inode_table_loc(fs, i)) && 919 (test_block >= ext2fs_inode_table_loc(fs, i)) && 920 (test_block < (ext2fs_inode_table_loc(fs, i) + 921 fs->inode_blocks_per_group))) 922 return 1; 923 924 /* Check the bitmap blocks */ 925 if ((test_block == ext2fs_block_bitmap_loc(fs, i)) || 926 (test_block == ext2fs_inode_bitmap_loc(fs, i))) 927 return 1; 928 929 first_block += fs->super->s_blocks_per_group; 930 } 931 return 0; 932} 933 934/* 935 * This routine returns 1 if a cluster overlaps with one of the superblocks, 936 * group descriptors, inode bitmaps, or block bitmaps. 937 */ 938static int check_if_fs_cluster(e2fsck_t ctx, blk64_t cluster) 939{ 940 ext2_filsys fs = ctx->fs; 941 blk64_t first_block; 942 dgrp_t i; 943 944 first_block = fs->super->s_first_data_block; 945 for (i = 0; i < fs->group_desc_count; i++) { 946 947 /* Check superblocks/block group descriptors */ 948 if (ext2fs_bg_has_super(fs, i)) { 949 if (cluster >= EXT2FS_B2C(fs, first_block) && 950 (cluster <= EXT2FS_B2C(fs, first_block + 951 fs->desc_blocks))) 952 return 1; 953 } 954 955 /* Check the inode table */ 956 if ((ext2fs_inode_table_loc(fs, i)) && 957 (cluster >= EXT2FS_B2C(fs, 958 ext2fs_inode_table_loc(fs, i))) && 959 (cluster <= EXT2FS_B2C(fs, 960 ext2fs_inode_table_loc(fs, i) + 961 fs->inode_blocks_per_group - 1))) 962 return 1; 963 964 /* Check the bitmap blocks */ 965 if ((cluster == EXT2FS_B2C(fs, 966 ext2fs_block_bitmap_loc(fs, i))) || 967 (cluster == EXT2FS_B2C(fs, 968 ext2fs_inode_bitmap_loc(fs, i)))) 969 return 1; 970 971 first_block += fs->super->s_blocks_per_group; 972 } 973 return 0; 974} 975