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