1 /* 2 * extent.c --- routines to implement extents support 3 * 4 * Copyright (C) 2007 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Library 8 * General Public License, version 2. 9 * %End-Header% 10 */ 11 12 #include <stdio.h> 13 #include <string.h> 14 #if HAVE_UNISTD_H 15 #include <unistd.h> 16 #endif 17 #if HAVE_ERRNO_H 18 #include <errno.h> 19 #endif 20 #if HAVE_SYS_STAT_H 21 #include <sys/stat.h> 22 #endif 23 #if HAVE_SYS_TYPES_H 24 #include <sys/types.h> 25 #endif 26 27 #include "ext2_fs.h" 28 #include "ext2fsP.h" 29 #include "e2image.h" 30 31 /* 32 * Definitions to be dropped in lib/ext2fs/ext2fs.h 33 */ 34 35 /* 36 * Private definitions 37 */ 38 39 struct extent_path { 40 char *buf; 41 int entries; 42 int max_entries; 43 int left; 44 int visit_num; 45 int flags; 46 blk64_t end_blk; 47 void *curr; 48 }; 49 50 51 struct ext2_extent_handle { 52 errcode_t magic; 53 ext2_filsys fs; 54 ext2_ino_t ino; 55 struct ext2_inode *inode; 56 struct ext2_inode inodebuf; 57 int type; 58 int level; 59 int max_depth; 60 struct extent_path *path; 61 }; 62 63 struct ext2_extent_path { 64 errcode_t magic; 65 int leaf_height; 66 blk64_t lblk; 67 }; 68 69 /* 70 * Useful Debugging stuff 71 */ 72 73 #ifdef DEBUG 74 static void dbg_show_header(struct ext3_extent_header *eh) 75 { 76 printf("header: magic=%x entries=%u max=%u depth=%u generation=%u\n", 77 ext2fs_le16_to_cpu(eh->eh_magic), 78 ext2fs_le16_to_cpu(eh->eh_entries), 79 ext2fs_le16_to_cpu(eh->eh_max), 80 ext2fs_le16_to_cpu(eh->eh_depth), 81 ext2fs_le32_to_cpu(eh->eh_generation)); 82 } 83 84 static void dbg_show_index(struct ext3_extent_idx *ix) 85 { 86 printf("index: block=%u leaf=%u leaf_hi=%u unused=%u\n", 87 ext2fs_le32_to_cpu(ix->ei_block), 88 ext2fs_le32_to_cpu(ix->ei_leaf), 89 ext2fs_le16_to_cpu(ix->ei_leaf_hi), 90 ext2fs_le16_to_cpu(ix->ei_unused)); 91 } 92 93 static void dbg_show_extent(struct ext3_extent *ex) 94 { 95 printf("extent: block=%u-%u len=%u start=%u start_hi=%u\n", 96 ext2fs_le32_to_cpu(ex->ee_block), 97 ext2fs_le32_to_cpu(ex->ee_block) + 98 ext2fs_le16_to_cpu(ex->ee_len) - 1, 99 ext2fs_le16_to_cpu(ex->ee_len), 100 ext2fs_le32_to_cpu(ex->ee_start), 101 ext2fs_le16_to_cpu(ex->ee_start_hi)); 102 } 103 104 static void dbg_print_extent(char *desc, struct ext2fs_extent *extent) 105 { 106 if (desc) 107 printf("%s: ", desc); 108 printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ", 109 extent->e_lblk, extent->e_lblk + extent->e_len - 1, 110 extent->e_len, extent->e_pblk); 111 if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF) 112 fputs("LEAF ", stdout); 113 if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) 114 fputs("UNINIT ", stdout); 115 if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) 116 fputs("2ND_VISIT ", stdout); 117 if (!extent->e_flags) 118 fputs("(none)", stdout); 119 fputc('\n', stdout); 120 121 } 122 123 #else 124 #define dbg_show_header(eh) do { } while (0) 125 #define dbg_show_index(ix) do { } while (0) 126 #define dbg_show_extent(ex) do { } while (0) 127 #define dbg_print_extent(desc, ex) do { } while (0) 128 #endif 129 130 /* 131 * Verify the extent header as being sane 132 */ 133 errcode_t ext2fs_extent_header_verify(void *ptr, int size) 134 { 135 int eh_max, entry_size; 136 struct ext3_extent_header *eh = ptr; 137 138 dbg_show_header(eh); 139 if (ext2fs_le16_to_cpu(eh->eh_magic) != EXT3_EXT_MAGIC) 140 return EXT2_ET_EXTENT_HEADER_BAD; 141 if (ext2fs_le16_to_cpu(eh->eh_entries) > ext2fs_le16_to_cpu(eh->eh_max)) 142 return EXT2_ET_EXTENT_HEADER_BAD; 143 if (eh->eh_depth == 0) 144 entry_size = sizeof(struct ext3_extent); 145 else 146 entry_size = sizeof(struct ext3_extent_idx); 147 148 eh_max = (size - sizeof(*eh)) / entry_size; 149 /* Allow two extent-sized items at the end of the block, for 150 * ext4_extent_tail with checksum in the future. */ 151 if ((ext2fs_le16_to_cpu(eh->eh_max) > eh_max) || 152 (ext2fs_le16_to_cpu(eh->eh_max) < (eh_max - 2))) 153 return EXT2_ET_EXTENT_HEADER_BAD; 154 155 return 0; 156 } 157 158 159 /* 160 * Begin functions to handle an inode's extent information 161 */ 162 void ext2fs_extent_free(ext2_extent_handle_t handle) 163 { 164 int i; 165 166 if (!handle) 167 return; 168 169 if (handle->path) { 170 for (i=1; i <= handle->max_depth; i++) { 171 if (handle->path[i].buf) 172 ext2fs_free_mem(&handle->path[i].buf); 173 } 174 ext2fs_free_mem(&handle->path); 175 } 176 ext2fs_free_mem(&handle); 177 } 178 179 errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino, 180 ext2_extent_handle_t *ret_handle) 181 { 182 return ext2fs_extent_open2(fs, ino, NULL, ret_handle); 183 } 184 185 errcode_t ext2fs_extent_open2(ext2_filsys fs, ext2_ino_t ino, 186 struct ext2_inode *inode, 187 ext2_extent_handle_t *ret_handle) 188 { 189 struct ext2_extent_handle *handle; 190 errcode_t retval; 191 int i; 192 struct ext3_extent_header *eh; 193 194 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 195 196 if (!inode) 197 if ((ino == 0) || (ino > fs->super->s_inodes_count)) 198 return EXT2_ET_BAD_INODE_NUM; 199 200 retval = ext2fs_get_mem(sizeof(struct ext2_extent_handle), &handle); 201 if (retval) 202 return retval; 203 memset(handle, 0, sizeof(struct ext2_extent_handle)); 204 205 handle->ino = ino; 206 handle->fs = fs; 207 208 if (inode) { 209 handle->inode = inode; 210 } else { 211 handle->inode = &handle->inodebuf; 212 retval = ext2fs_read_inode(fs, ino, handle->inode); 213 if (retval) 214 goto errout; 215 } 216 217 eh = (struct ext3_extent_header *) &handle->inode->i_block[0]; 218 219 for (i=0; i < EXT2_N_BLOCKS; i++) 220 if (handle->inode->i_block[i]) 221 break; 222 if (i >= EXT2_N_BLOCKS) { 223 eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); 224 eh->eh_depth = 0; 225 eh->eh_entries = 0; 226 i = (sizeof(handle->inode->i_block) - sizeof(*eh)) / 227 sizeof(struct ext3_extent); 228 eh->eh_max = ext2fs_cpu_to_le16(i); 229 handle->inode->i_flags |= EXT4_EXTENTS_FL; 230 } 231 232 if (!(handle->inode->i_flags & EXT4_EXTENTS_FL)) { 233 retval = EXT2_ET_INODE_NOT_EXTENT; 234 goto errout; 235 } 236 237 retval = ext2fs_extent_header_verify(eh, sizeof(handle->inode->i_block)); 238 if (retval) 239 goto errout; 240 241 handle->max_depth = ext2fs_le16_to_cpu(eh->eh_depth); 242 handle->type = ext2fs_le16_to_cpu(eh->eh_magic); 243 244 retval = ext2fs_get_mem(((handle->max_depth+1) * 245 sizeof(struct extent_path)), 246 &handle->path); 247 memset(handle->path, 0, 248 (handle->max_depth+1) * sizeof(struct extent_path)); 249 handle->path[0].buf = (char *) handle->inode->i_block; 250 251 handle->path[0].left = handle->path[0].entries = 252 ext2fs_le16_to_cpu(eh->eh_entries); 253 handle->path[0].max_entries = ext2fs_le16_to_cpu(eh->eh_max); 254 handle->path[0].curr = 0; 255 handle->path[0].end_blk = 256 (EXT2_I_SIZE(handle->inode) + fs->blocksize - 1) >> 257 EXT2_BLOCK_SIZE_BITS(fs->super); 258 handle->path[0].visit_num = 1; 259 handle->level = 0; 260 handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE; 261 262 *ret_handle = handle; 263 return 0; 264 265 errout: 266 ext2fs_extent_free(handle); 267 return retval; 268 } 269 270 /* 271 * This function is responsible for (optionally) moving through the 272 * extent tree and then returning the current extent 273 */ 274 errcode_t ext2fs_extent_get(ext2_extent_handle_t handle, 275 int flags, struct ext2fs_extent *extent) 276 { 277 struct extent_path *path, *newpath; 278 struct ext3_extent_header *eh; 279 struct ext3_extent_idx *ix = 0; 280 struct ext3_extent *ex; 281 errcode_t retval; 282 blk64_t blk; 283 blk64_t end_blk; 284 int orig_op, op; 285 286 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); 287 288 if (!handle->path) 289 return EXT2_ET_NO_CURRENT_NODE; 290 291 orig_op = op = flags & EXT2_EXTENT_MOVE_MASK; 292 293 retry: 294 path = handle->path + handle->level; 295 if ((orig_op == EXT2_EXTENT_NEXT) || 296 (orig_op == EXT2_EXTENT_NEXT_LEAF)) { 297 if (handle->level < handle->max_depth) { 298 /* interior node */ 299 if (path->visit_num == 0) { 300 path->visit_num++; 301 op = EXT2_EXTENT_DOWN; 302 } else if (path->left > 0) 303 op = EXT2_EXTENT_NEXT_SIB; 304 else if (handle->level > 0) 305 op = EXT2_EXTENT_UP; 306 else 307 return EXT2_ET_EXTENT_NO_NEXT; 308 } else { 309 /* leaf node */ 310 if (path->left > 0) 311 op = EXT2_EXTENT_NEXT_SIB; 312 else if (handle->level > 0) 313 op = EXT2_EXTENT_UP; 314 else 315 return EXT2_ET_EXTENT_NO_NEXT; 316 } 317 if (op != EXT2_EXTENT_NEXT_SIB) { 318 #ifdef DEBUG_GET_EXTENT 319 printf("<<<< OP = %s\n", 320 (op == EXT2_EXTENT_DOWN) ? "down" : 321 ((op == EXT2_EXTENT_UP) ? "up" : "unknown")); 322 #endif 323 } 324 } 325 326 if ((orig_op == EXT2_EXTENT_PREV) || 327 (orig_op == EXT2_EXTENT_PREV_LEAF)) { 328 if (handle->level < handle->max_depth) { 329 /* interior node */ 330 if (path->visit_num > 0 ) { 331 /* path->visit_num = 0; */ 332 op = EXT2_EXTENT_DOWN_AND_LAST; 333 } else if (path->left < path->entries-1) 334 op = EXT2_EXTENT_PREV_SIB; 335 else if (handle->level > 0) 336 op = EXT2_EXTENT_UP; 337 else 338 return EXT2_ET_EXTENT_NO_PREV; 339 } else { 340 /* leaf node */ 341 if (path->left < path->entries-1) 342 op = EXT2_EXTENT_PREV_SIB; 343 else if (handle->level > 0) 344 op = EXT2_EXTENT_UP; 345 else 346 return EXT2_ET_EXTENT_NO_PREV; 347 } 348 if (op != EXT2_EXTENT_PREV_SIB) { 349 #ifdef DEBUG_GET_EXTENT 350 printf("<<<< OP = %s\n", 351 (op == EXT2_EXTENT_DOWN_AND_LAST) ? "down/last" : 352 ((op == EXT2_EXTENT_UP) ? "up" : "unknown")); 353 #endif 354 } 355 } 356 357 if (orig_op == EXT2_EXTENT_LAST_LEAF) { 358 if ((handle->level < handle->max_depth) && 359 (path->left == 0)) 360 op = EXT2_EXTENT_DOWN; 361 else 362 op = EXT2_EXTENT_LAST_SIB; 363 #ifdef DEBUG_GET_EXTENT 364 printf("<<<< OP = %s\n", 365 (op == EXT2_EXTENT_DOWN) ? "down" : "last_sib"); 366 #endif 367 } 368 369 switch (op) { 370 case EXT2_EXTENT_CURRENT: 371 ix = path->curr; 372 break; 373 case EXT2_EXTENT_ROOT: 374 handle->level = 0; 375 path = handle->path + handle->level; 376 /* fallthrough */ 377 case EXT2_EXTENT_FIRST_SIB: 378 path->left = path->entries; 379 path->curr = 0; 380 /* fallthrough */ 381 case EXT2_EXTENT_NEXT_SIB: 382 if (path->left <= 0) 383 return EXT2_ET_EXTENT_NO_NEXT; 384 if (path->curr) { 385 ix = path->curr; 386 ix++; 387 } else { 388 eh = (struct ext3_extent_header *) path->buf; 389 ix = EXT_FIRST_INDEX(eh); 390 } 391 path->left--; 392 path->curr = ix; 393 path->visit_num = 0; 394 break; 395 case EXT2_EXTENT_PREV_SIB: 396 if (!path->curr || 397 path->left+1 >= path->entries) 398 return EXT2_ET_EXTENT_NO_PREV; 399 ix = path->curr; 400 ix--; 401 path->curr = ix; 402 path->left++; 403 if (handle->level < handle->max_depth) 404 path->visit_num = 1; 405 break; 406 case EXT2_EXTENT_LAST_SIB: 407 eh = (struct ext3_extent_header *) path->buf; 408 path->curr = EXT_LAST_EXTENT(eh); 409 ix = path->curr; 410 path->left = 0; 411 path->visit_num = 0; 412 break; 413 case EXT2_EXTENT_UP: 414 if (handle->level <= 0) 415 return EXT2_ET_EXTENT_NO_UP; 416 handle->level--; 417 path--; 418 ix = path->curr; 419 if ((orig_op == EXT2_EXTENT_PREV) || 420 (orig_op == EXT2_EXTENT_PREV_LEAF)) 421 path->visit_num = 0; 422 break; 423 case EXT2_EXTENT_DOWN: 424 case EXT2_EXTENT_DOWN_AND_LAST: 425 if (!path->curr ||(handle->level >= handle->max_depth)) 426 return EXT2_ET_EXTENT_NO_DOWN; 427 428 ix = path->curr; 429 newpath = path + 1; 430 if (!newpath->buf) { 431 retval = ext2fs_get_mem(handle->fs->blocksize, 432 &newpath->buf); 433 if (retval) 434 return retval; 435 } 436 blk = ext2fs_le32_to_cpu(ix->ei_leaf) + 437 ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); 438 if ((handle->fs->flags & EXT2_FLAG_IMAGE_FILE) && 439 (handle->fs->io != handle->fs->image_io)) 440 memset(newpath->buf, 0, handle->fs->blocksize); 441 else { 442 retval = io_channel_read_blk64(handle->fs->io, 443 blk, 1, newpath->buf); 444 if (retval) 445 return retval; 446 } 447 handle->level++; 448 449 eh = (struct ext3_extent_header *) newpath->buf; 450 451 retval = ext2fs_extent_header_verify(eh, handle->fs->blocksize); 452 if (retval) { 453 handle->level--; 454 return retval; 455 } 456 457 newpath->left = newpath->entries = 458 ext2fs_le16_to_cpu(eh->eh_entries); 459 newpath->max_entries = ext2fs_le16_to_cpu(eh->eh_max); 460 461 if (path->left > 0) { 462 ix++; 463 newpath->end_blk = ext2fs_le32_to_cpu(ix->ei_block); 464 } else 465 newpath->end_blk = path->end_blk; 466 467 path = newpath; 468 if (op == EXT2_EXTENT_DOWN) { 469 ix = EXT_FIRST_INDEX((struct ext3_extent_header *) eh); 470 path->curr = ix; 471 path->left = path->entries - 1; 472 path->visit_num = 0; 473 } else { 474 ix = EXT_LAST_INDEX((struct ext3_extent_header *) eh); 475 path->curr = ix; 476 path->left = 0; 477 if (handle->level < handle->max_depth) 478 path->visit_num = 1; 479 } 480 #ifdef DEBUG_GET_EXTENT 481 printf("Down to level %d/%d, end_blk=%llu\n", 482 handle->level, handle->max_depth, 483 path->end_blk); 484 #endif 485 break; 486 default: 487 return EXT2_ET_OP_NOT_SUPPORTED; 488 } 489 490 if (!ix) 491 return EXT2_ET_NO_CURRENT_NODE; 492 493 extent->e_flags = 0; 494 #ifdef DEBUG_GET_EXTENT 495 printf("(Left %d)\n", path->left); 496 #endif 497 498 if (handle->level == handle->max_depth) { 499 ex = (struct ext3_extent *) ix; 500 501 extent->e_pblk = ext2fs_le32_to_cpu(ex->ee_start) + 502 ((__u64) ext2fs_le16_to_cpu(ex->ee_start_hi) << 32); 503 extent->e_lblk = ext2fs_le32_to_cpu(ex->ee_block); 504 extent->e_len = ext2fs_le16_to_cpu(ex->ee_len); 505 extent->e_flags |= EXT2_EXTENT_FLAGS_LEAF; 506 if (extent->e_len > EXT_INIT_MAX_LEN) { 507 extent->e_len -= EXT_INIT_MAX_LEN; 508 extent->e_flags |= EXT2_EXTENT_FLAGS_UNINIT; 509 } 510 } else { 511 extent->e_pblk = ext2fs_le32_to_cpu(ix->ei_leaf) + 512 ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); 513 extent->e_lblk = ext2fs_le32_to_cpu(ix->ei_block); 514 if (path->left > 0) { 515 ix++; 516 end_blk = ext2fs_le32_to_cpu(ix->ei_block); 517 } else 518 end_blk = path->end_blk; 519 520 extent->e_len = end_blk - extent->e_lblk; 521 } 522 if (path->visit_num) 523 extent->e_flags |= EXT2_EXTENT_FLAGS_SECOND_VISIT; 524 525 if (((orig_op == EXT2_EXTENT_NEXT_LEAF) || 526 (orig_op == EXT2_EXTENT_PREV_LEAF)) && 527 (handle->level != handle->max_depth)) 528 goto retry; 529 530 if ((orig_op == EXT2_EXTENT_LAST_LEAF) && 531 ((handle->level != handle->max_depth) || 532 (path->left != 0))) 533 goto retry; 534 535 return 0; 536 } 537 538 static errcode_t update_path(ext2_extent_handle_t handle) 539 { 540 blk64_t blk; 541 errcode_t retval; 542 struct ext3_extent_idx *ix; 543 544 if (handle->level == 0) { 545 retval = ext2fs_write_inode(handle->fs, handle->ino, 546 handle->inode); 547 } else { 548 ix = handle->path[handle->level - 1].curr; 549 blk = ext2fs_le32_to_cpu(ix->ei_leaf) + 550 ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); 551 552 retval = io_channel_write_blk64(handle->fs->io, 553 blk, 1, handle->path[handle->level].buf); 554 } 555 return retval; 556 } 557 558 #if 0 559 errcode_t ext2fs_extent_save_path(ext2_extent_handle_t handle, 560 ext2_extent_path_t *ret_path) 561 { 562 ext2_extent_path_t save_path; 563 struct ext2fs_extent extent; 564 struct ext2_extent_info info; 565 errcode_t retval; 566 567 retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); 568 if (retval) 569 return retval; 570 571 retval = ext2fs_extent_get_info(handle, &info); 572 if (retval) 573 return retval; 574 575 retval = ext2fs_get_mem(sizeof(struct ext2_extent_path), &save_path); 576 if (retval) 577 return retval; 578 memset(save_path, 0, sizeof(struct ext2_extent_path)); 579 580 save_path->magic = EXT2_ET_MAGIC_EXTENT_PATH; 581 save_path->leaf_height = info.max_depth - info.curr_level - 1; 582 save_path->lblk = extent.e_lblk; 583 584 *ret_path = save_path; 585 return 0; 586 } 587 588 errcode_t ext2fs_extent_free_path(ext2_extent_path_t path) 589 { 590 EXT2_CHECK_MAGIC(path, EXT2_ET_MAGIC_EXTENT_PATH); 591 592 ext2fs_free_mem(&path); 593 return 0; 594 } 595 #endif 596 597 /* 598 * Go to the node at leaf_level which contains logical block blk. 599 * 600 * leaf_level is height from the leaf node level, i.e. 601 * leaf_level 0 is at leaf node, leaf_level 1 is 1 above etc. 602 * 603 * If "blk" has no mapping (hole) then handle is left at last 604 * extent before blk. 605 */ 606 errcode_t ext2fs_extent_goto2(ext2_extent_handle_t handle, 607 int leaf_level, blk64_t blk) 608 { 609 struct ext2fs_extent extent; 610 errcode_t retval; 611 612 retval = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent); 613 if (retval) { 614 if (retval == EXT2_ET_EXTENT_NO_NEXT) 615 retval = EXT2_ET_EXTENT_NOT_FOUND; 616 return retval; 617 } 618 619 if (leaf_level > handle->max_depth) { 620 #ifdef DEBUG 621 printf("leaf level %d greater than tree depth %d\n", 622 leaf_level, handle->max_depth); 623 #endif 624 return EXT2_ET_OP_NOT_SUPPORTED; 625 } 626 627 #ifdef DEBUG 628 printf("goto extent ino %u, level %d, %llu\n", handle->ino, 629 leaf_level, blk); 630 #endif 631 632 #ifdef DEBUG_GOTO_EXTENTS 633 dbg_print_extent("root", &extent); 634 #endif 635 while (1) { 636 if (handle->max_depth - handle->level == leaf_level) { 637 /* block is in this &extent */ 638 if ((blk >= extent.e_lblk) && 639 (blk < extent.e_lblk + extent.e_len)) 640 return 0; 641 if (blk < extent.e_lblk) { 642 retval = ext2fs_extent_get(handle, 643 EXT2_EXTENT_PREV_SIB, 644 &extent); 645 return EXT2_ET_EXTENT_NOT_FOUND; 646 } 647 retval = ext2fs_extent_get(handle, 648 EXT2_EXTENT_NEXT_SIB, 649 &extent); 650 if (retval == EXT2_ET_EXTENT_NO_NEXT) 651 return EXT2_ET_EXTENT_NOT_FOUND; 652 if (retval) 653 return retval; 654 continue; 655 } 656 657 retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_SIB, 658 &extent); 659 if (retval == EXT2_ET_EXTENT_NO_NEXT) 660 goto go_down; 661 if (retval) 662 return retval; 663 664 #ifdef DEBUG_GOTO_EXTENTS 665 dbg_print_extent("next", &extent); 666 #endif 667 if (blk == extent.e_lblk) 668 goto go_down; 669 if (blk > extent.e_lblk) 670 continue; 671 672 retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_SIB, 673 &extent); 674 if (retval) 675 return retval; 676 677 #ifdef DEBUG_GOTO_EXTENTS 678 dbg_print_extent("prev", &extent); 679 #endif 680 681 go_down: 682 retval = ext2fs_extent_get(handle, EXT2_EXTENT_DOWN, 683 &extent); 684 if (retval) 685 return retval; 686 687 #ifdef DEBUG_GOTO_EXTENTS 688 dbg_print_extent("down", &extent); 689 #endif 690 } 691 } 692 693 errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle, 694 blk64_t blk) 695 { 696 return ext2fs_extent_goto2(handle, 0, blk); 697 } 698 699 /* 700 * Traverse back up to root fixing parents of current node as needed. 701 * 702 * If we changed start of first entry in a node, fix parent index start 703 * and so on. 704 * 705 * Safe to call for any position in node; if not at the first entry, 706 * will simply return. 707 */ 708 errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle) 709 { 710 int retval = 0; 711 int orig_height; 712 blk64_t start; 713 struct extent_path *path; 714 struct ext2fs_extent extent; 715 struct ext2_extent_info info; 716 717 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); 718 719 if (!(handle->fs->flags & EXT2_FLAG_RW)) 720 return EXT2_ET_RO_FILSYS; 721 722 if (!handle->path) 723 return EXT2_ET_NO_CURRENT_NODE; 724 725 path = handle->path + handle->level; 726 if (!path->curr) 727 return EXT2_ET_NO_CURRENT_NODE; 728 729 retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); 730 if (retval) 731 goto done; 732 733 /* modified node's start block */ 734 start = extent.e_lblk; 735 736 if ((retval = ext2fs_extent_get_info(handle, &info))) 737 return retval; 738 orig_height = info.max_depth - info.curr_level; 739 740 /* traverse up until index not first, or startblk matches, or top */ 741 while (handle->level > 0 && 742 (path->left == path->entries - 1)) { 743 retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); 744 if (retval) 745 goto done; 746 if (extent.e_lblk == start) 747 break; 748 path = handle->path + handle->level; 749 extent.e_len += (extent.e_lblk - start); 750 extent.e_lblk = start; 751 retval = ext2fs_extent_replace(handle, 0, &extent); 752 if (retval) 753 goto done; 754 update_path(handle); 755 } 756 757 /* put handle back to where we started */ 758 retval = ext2fs_extent_goto2(handle, orig_height, start); 759 done: 760 return retval; 761 } 762 763 errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle, 764 int flags EXT2FS_ATTR((unused)), 765 struct ext2fs_extent *extent) 766 { 767 struct extent_path *path; 768 struct ext3_extent_idx *ix; 769 struct ext3_extent *ex; 770 771 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); 772 773 if (!(handle->fs->flags & EXT2_FLAG_RW)) 774 return EXT2_ET_RO_FILSYS; 775 776 if (!handle->path) 777 return EXT2_ET_NO_CURRENT_NODE; 778 779 path = handle->path + handle->level; 780 if (!path->curr) 781 return EXT2_ET_NO_CURRENT_NODE; 782 783 #ifdef DEBUG 784 printf("extent replace: %u ", handle->ino); 785 dbg_print_extent(0, extent); 786 #endif 787 788 if (handle->level == handle->max_depth) { 789 ex = path->curr; 790 791 ex->ee_block = ext2fs_cpu_to_le32(extent->e_lblk); 792 ex->ee_start = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF); 793 ex->ee_start_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32); 794 if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) { 795 if (extent->e_len > EXT_UNINIT_MAX_LEN) 796 return EXT2_ET_EXTENT_INVALID_LENGTH; 797 ex->ee_len = ext2fs_cpu_to_le16(extent->e_len + 798 EXT_INIT_MAX_LEN); 799 } else { 800 if (extent->e_len > EXT_INIT_MAX_LEN) 801 return EXT2_ET_EXTENT_INVALID_LENGTH; 802 ex->ee_len = ext2fs_cpu_to_le16(extent->e_len); 803 } 804 } else { 805 ix = path->curr; 806 807 ix->ei_leaf = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF); 808 ix->ei_leaf_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32); 809 ix->ei_block = ext2fs_cpu_to_le32(extent->e_lblk); 810 ix->ei_unused = 0; 811 } 812 update_path(handle); 813 return 0; 814 } 815 816 /* 817 * allocate a new block, move half the current node to it, and update parent 818 * 819 * handle will be left pointing at original record. 820 */ 821 errcode_t ext2fs_extent_node_split(ext2_extent_handle_t handle) 822 { 823 errcode_t retval = 0; 824 blk64_t new_node_pblk; 825 blk64_t new_node_start; 826 blk64_t orig_lblk; 827 blk64_t goal_blk = 0; 828 int orig_height; 829 char *block_buf = NULL; 830 struct ext2fs_extent extent; 831 struct extent_path *path, *newpath = 0; 832 struct ext3_extent_header *eh, *neweh; 833 int tocopy; 834 int new_root = 0; 835 struct ext2_extent_info info; 836 837 /* basic sanity */ 838 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); 839 840 if (!(handle->fs->flags & EXT2_FLAG_RW)) 841 return EXT2_ET_RO_FILSYS; 842 843 if (!handle->path) 844 return EXT2_ET_NO_CURRENT_NODE; 845 846 #ifdef DEBUG 847 printf("splitting node at level %d\n", handle->level); 848 #endif 849 retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); 850 if (retval) 851 goto done; 852 853 retval = ext2fs_extent_get_info(handle, &info); 854 if (retval) 855 goto done; 856 857 /* save the position we were originally splitting... */ 858 orig_height = info.max_depth - info.curr_level; 859 orig_lblk = extent.e_lblk; 860 861 /* Is there room in the parent for a new entry? */ 862 if (handle->level && 863 (handle->path[handle->level - 1].entries >= 864 handle->path[handle->level - 1].max_entries)) { 865 866 #ifdef DEBUG 867 printf("parent level %d full; splitting it too\n", 868 handle->level - 1); 869 #endif 870 /* split the parent */ 871 retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); 872 if (retval) 873 goto done; 874 goal_blk = extent.e_pblk; 875 876 retval = ext2fs_extent_node_split(handle); 877 if (retval) 878 goto done; 879 880 /* get handle back to our original split position */ 881 retval = ext2fs_extent_goto2(handle, orig_height, orig_lblk); 882 if (retval) 883 goto done; 884 } 885 886 /* At this point, parent should have room for this split */ 887 path = handle->path + handle->level; 888 if (!path->curr) 889 return EXT2_ET_NO_CURRENT_NODE; 890 891 /* extent header of the current node we'll split */ 892 eh = (struct ext3_extent_header *)path->buf; 893 894 /* splitting root level means moving them all out */ 895 if (handle->level == 0) { 896 new_root = 1; 897 tocopy = ext2fs_le16_to_cpu(eh->eh_entries); 898 retval = ext2fs_get_mem(((handle->max_depth+2) * 899 sizeof(struct extent_path)), 900 &newpath); 901 if (retval) 902 goto done; 903 memset(newpath, 0, 904 ((handle->max_depth+2) * sizeof(struct extent_path))); 905 } else { 906 tocopy = ext2fs_le16_to_cpu(eh->eh_entries) / 2; 907 } 908 909 #ifdef DEBUG 910 printf("will copy out %d of %d entries at level %d\n", 911 tocopy, ext2fs_le16_to_cpu(eh->eh_entries), 912 handle->level); 913 #endif 914 915 if (!tocopy) { 916 #ifdef DEBUG 917 printf("Nothing to copy to new block!\n"); 918 #endif 919 retval = EXT2_ET_CANT_SPLIT_EXTENT; 920 goto done; 921 } 922 923 /* first we need a new block, or can do nothing. */ 924 block_buf = malloc(handle->fs->blocksize); 925 if (!block_buf) { 926 retval = ENOMEM; 927 goto done; 928 } 929 930 if (!goal_blk) { 931 dgrp_t group = ext2fs_group_of_ino(handle->fs, handle->ino); 932 __u8 log_flex = handle->fs->super->s_log_groups_per_flex; 933 934 if (log_flex) 935 group = group & ~((1 << (log_flex)) - 1); 936 goal_blk = ext2fs_group_first_block2(handle->fs, group); 937 } 938 retval = ext2fs_alloc_block2(handle->fs, goal_blk, block_buf, 939 &new_node_pblk); 940 if (retval) 941 goto done; 942 943 #ifdef DEBUG 944 printf("will copy to new node at block %lu\n", 945 (unsigned long) new_node_pblk); 946 #endif 947 948 /* Copy data into new block buffer */ 949 /* First the header for the new block... */ 950 neweh = (struct ext3_extent_header *) block_buf; 951 memcpy(neweh, eh, sizeof(struct ext3_extent_header)); 952 neweh->eh_entries = ext2fs_cpu_to_le16(tocopy); 953 neweh->eh_max = ext2fs_cpu_to_le16((handle->fs->blocksize - 954 sizeof(struct ext3_extent_header)) / 955 sizeof(struct ext3_extent)); 956 957 /* then the entries for the new block... */ 958 memcpy(EXT_FIRST_INDEX(neweh), 959 EXT_FIRST_INDEX(eh) + 960 (ext2fs_le16_to_cpu(eh->eh_entries) - tocopy), 961 sizeof(struct ext3_extent_idx) * tocopy); 962 963 new_node_start = ext2fs_le32_to_cpu(EXT_FIRST_INDEX(neweh)->ei_block); 964 965 /* ...and write the new node block out to disk. */ 966 retval = io_channel_write_blk64(handle->fs->io, new_node_pblk, 1, 967 block_buf); 968 969 if (retval) 970 goto done; 971 972 /* OK! we've created the new node; now adjust the tree */ 973 974 /* current path now has fewer active entries, we copied some out */ 975 if (handle->level == 0) { 976 memcpy(newpath, path, 977 sizeof(struct extent_path) * (handle->max_depth+1)); 978 handle->path = newpath; 979 newpath = path; 980 path = handle->path; 981 path->entries = 1; 982 path->left = path->max_entries - 1; 983 handle->max_depth++; 984 eh->eh_depth = ext2fs_cpu_to_le16(handle->max_depth); 985 } else { 986 path->entries -= tocopy; 987 path->left -= tocopy; 988 } 989 990 eh->eh_entries = ext2fs_cpu_to_le16(path->entries); 991 /* this writes out the node, incl. the modified header */ 992 retval = update_path(handle); 993 if (retval) 994 goto done; 995 996 /* now go up and insert/replace index for new node we created */ 997 if (new_root) { 998 retval = ext2fs_extent_get(handle, EXT2_EXTENT_FIRST_SIB, &extent); 999 if (retval) 1000 goto done; 1001 1002 extent.e_lblk = new_node_start; 1003 extent.e_pblk = new_node_pblk; 1004 extent.e_len = handle->path[0].end_blk - extent.e_lblk; 1005 retval = ext2fs_extent_replace(handle, 0, &extent); 1006 if (retval) 1007 goto done; 1008 } else { 1009 __u32 new_node_length; 1010 1011 retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); 1012 /* will insert after this one; it's length is shorter now */ 1013 new_node_length = new_node_start - extent.e_lblk; 1014 extent.e_len -= new_node_length; 1015 retval = ext2fs_extent_replace(handle, 0, &extent); 1016 if (retval) 1017 goto done; 1018 1019 /* now set up the new extent and insert it */ 1020 extent.e_lblk = new_node_start; 1021 extent.e_pblk = new_node_pblk; 1022 extent.e_len = new_node_length; 1023 retval = ext2fs_extent_insert(handle, EXT2_EXTENT_INSERT_AFTER, &extent); 1024 if (retval) 1025 goto done; 1026 } 1027 1028 /* get handle back to our original position */ 1029 retval = ext2fs_extent_goto2(handle, orig_height, orig_lblk); 1030 if (retval) 1031 goto done; 1032 1033 /* new node hooked in, so update inode block count (do this here?) */ 1034 handle->inode->i_blocks += (handle->fs->blocksize * 1035 EXT2FS_CLUSTER_RATIO(handle->fs)) / 512; 1036 retval = ext2fs_write_inode(handle->fs, handle->ino, 1037 handle->inode); 1038 if (retval) 1039 goto done; 1040 1041 done: 1042 if (newpath) 1043 ext2fs_free_mem(&newpath); 1044 free(block_buf); 1045 1046 return retval; 1047 } 1048 1049 errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags, 1050 struct ext2fs_extent *extent) 1051 { 1052 struct extent_path *path; 1053 struct ext3_extent_idx *ix; 1054 struct ext3_extent_header *eh; 1055 errcode_t retval; 1056 1057 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); 1058 1059 if (!(handle->fs->flags & EXT2_FLAG_RW)) 1060 return EXT2_ET_RO_FILSYS; 1061 1062 if (!handle->path) 1063 return EXT2_ET_NO_CURRENT_NODE; 1064 1065 #ifdef DEBUG 1066 printf("extent insert: %u ", handle->ino); 1067 dbg_print_extent(0, extent); 1068 #endif 1069 1070 path = handle->path + handle->level; 1071 1072 if (path->entries >= path->max_entries) { 1073 if (flags & EXT2_EXTENT_INSERT_NOSPLIT) { 1074 return EXT2_ET_CANT_INSERT_EXTENT; 1075 } else { 1076 #ifdef DEBUG 1077 printf("node full (level %d) - splitting\n", 1078 handle->level); 1079 #endif 1080 retval = ext2fs_extent_node_split(handle); 1081 if (retval) 1082 return retval; 1083 path = handle->path + handle->level; 1084 } 1085 } 1086 1087 eh = (struct ext3_extent_header *) path->buf; 1088 if (path->curr) { 1089 ix = path->curr; 1090 if (flags & EXT2_EXTENT_INSERT_AFTER) { 1091 ix++; 1092 path->left--; 1093 } 1094 } else 1095 ix = EXT_FIRST_INDEX(eh); 1096 1097 path->curr = ix; 1098 1099 if (path->left >= 0) 1100 memmove(ix + 1, ix, 1101 (path->left+1) * sizeof(struct ext3_extent_idx)); 1102 path->left++; 1103 path->entries++; 1104 1105 eh = (struct ext3_extent_header *) path->buf; 1106 eh->eh_entries = ext2fs_cpu_to_le16(path->entries); 1107 1108 retval = ext2fs_extent_replace(handle, 0, extent); 1109 if (retval) 1110 goto errout; 1111 1112 retval = update_path(handle); 1113 if (retval) 1114 goto errout; 1115 1116 return 0; 1117 1118 errout: 1119 ext2fs_extent_delete(handle, 0); 1120 return retval; 1121 } 1122 1123 /* 1124 * Sets the physical block for a logical file block in the extent tree. 1125 * 1126 * May: map unmapped, unmap mapped, or remap mapped blocks. 1127 * 1128 * Mapping an unmapped block adds a single-block extent. 1129 * 1130 * Unmapping first or last block modifies extent in-place 1131 * - But may need to fix parent's starts too in first-block case 1132 * 1133 * Mapping any unmapped block requires adding a (single-block) extent 1134 * and inserting into proper point in tree. 1135 * 1136 * Modifying (unmapping or remapping) a block in the middle 1137 * of an extent requires splitting the extent. 1138 * - Remapping case requires new single-block extent. 1139 * 1140 * Remapping first or last block adds an extent. 1141 * 1142 * We really need extent adding to be smart about merging. 1143 */ 1144 1145 errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle, 1146 blk64_t logical, blk64_t physical, int flags) 1147 { 1148 errcode_t ec, retval = 0; 1149 int mapped = 1; /* logical is mapped? */ 1150 int orig_height; 1151 int extent_uninit = 0; 1152 int prev_uninit = 0; 1153 int next_uninit = 0; 1154 int new_uninit = 0; 1155 int max_len = EXT_INIT_MAX_LEN; 1156 int has_prev, has_next; 1157 blk64_t orig_lblk; 1158 struct extent_path *path; 1159 struct ext2fs_extent extent, next_extent, prev_extent; 1160 struct ext2fs_extent newextent; 1161 struct ext2_extent_info info; 1162 1163 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); 1164 1165 #ifdef DEBUG 1166 printf("set_bmap ino %u log %lld phys %lld flags %d\n", 1167 handle->ino, logical, physical, flags); 1168 #endif 1169 1170 if (!(handle->fs->flags & EXT2_FLAG_RW)) 1171 return EXT2_ET_RO_FILSYS; 1172 1173 if (!handle->path) 1174 return EXT2_ET_NO_CURRENT_NODE; 1175 1176 path = handle->path + handle->level; 1177 1178 if (flags & EXT2_EXTENT_SET_BMAP_UNINIT) { 1179 new_uninit = 1; 1180 max_len = EXT_UNINIT_MAX_LEN; 1181 } 1182 1183 /* if (re)mapping, set up new extent to insert */ 1184 if (physical) { 1185 newextent.e_len = 1; 1186 newextent.e_pblk = physical; 1187 newextent.e_lblk = logical; 1188 newextent.e_flags = EXT2_EXTENT_FLAGS_LEAF; 1189 if (new_uninit) 1190 newextent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT; 1191 } 1192 1193 /* special case if the extent tree is completely empty */ 1194 if ((handle->max_depth == 0) && (path->entries == 0)) { 1195 retval = ext2fs_extent_insert(handle, 0, &newextent); 1196 return retval; 1197 } 1198 1199 /* save our original location in the extent tree */ 1200 if ((retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, 1201 &extent))) { 1202 if (retval != EXT2_ET_NO_CURRENT_NODE) 1203 return retval; 1204 memset(&extent, 0, sizeof(extent)); 1205 } 1206 if ((retval = ext2fs_extent_get_info(handle, &info))) 1207 return retval; 1208 orig_height = info.max_depth - info.curr_level; 1209 orig_lblk = extent.e_lblk; 1210 1211 /* go to the logical spot we want to (re/un)map */ 1212 retval = ext2fs_extent_goto(handle, logical); 1213 if (retval) { 1214 if (retval == EXT2_ET_EXTENT_NOT_FOUND) { 1215 retval = 0; 1216 mapped = 0; 1217 if (!physical) { 1218 #ifdef DEBUG 1219 printf("block %llu already unmapped\n", 1220 logical); 1221 #endif 1222 goto done; 1223 } 1224 } else 1225 goto done; 1226 } 1227 1228 /* 1229 * This may be the extent *before* the requested logical, 1230 * if it's currently unmapped. 1231 * 1232 * Get the previous and next leaf extents, if they are present. 1233 */ 1234 retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); 1235 if (retval) 1236 goto done; 1237 if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) 1238 extent_uninit = 1; 1239 retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, &next_extent); 1240 if (retval) { 1241 has_next = 0; 1242 if (retval != EXT2_ET_EXTENT_NO_NEXT) 1243 goto done; 1244 } else { 1245 dbg_print_extent("set_bmap: next_extent", 1246 &next_extent); 1247 has_next = 1; 1248 if (next_extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) 1249 next_uninit = 1; 1250 } 1251 retval = ext2fs_extent_goto(handle, logical); 1252 if (retval && retval != EXT2_ET_EXTENT_NOT_FOUND) 1253 goto done; 1254 retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_LEAF, &prev_extent); 1255 if (retval) { 1256 has_prev = 0; 1257 if (retval != EXT2_ET_EXTENT_NO_PREV) 1258 goto done; 1259 } else { 1260 has_prev = 1; 1261 dbg_print_extent("set_bmap: prev_extent", 1262 &prev_extent); 1263 if (prev_extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) 1264 prev_uninit = 1; 1265 } 1266 retval = ext2fs_extent_goto(handle, logical); 1267 if (retval && retval != EXT2_ET_EXTENT_NOT_FOUND) 1268 goto done; 1269 1270 /* check if already pointing to the requested physical */ 1271 if (mapped && (new_uninit == extent_uninit) && 1272 (extent.e_pblk + (logical - extent.e_lblk) == physical)) { 1273 #ifdef DEBUG 1274 printf("physical block (at %llu) unchanged\n", logical); 1275 #endif 1276 goto done; 1277 } 1278 1279 if (!mapped) { 1280 #ifdef DEBUG 1281 printf("mapping unmapped logical block %llu\n", logical); 1282 #endif 1283 if ((logical == extent.e_lblk + extent.e_len) && 1284 (physical == extent.e_pblk + extent.e_len) && 1285 (new_uninit == extent_uninit) && 1286 ((int) extent.e_len < max_len-1)) { 1287 extent.e_len++; 1288 retval = ext2fs_extent_replace(handle, 0, &extent); 1289 } else if ((logical == extent.e_lblk - 1) && 1290 (physical == extent.e_pblk - 1) && 1291 (new_uninit == extent_uninit) && 1292 ((int) extent.e_len < max_len - 1)) { 1293 extent.e_len++; 1294 extent.e_lblk--; 1295 extent.e_pblk--; 1296 retval = ext2fs_extent_replace(handle, 0, &extent); 1297 } else if (has_next && 1298 (logical == next_extent.e_lblk - 1) && 1299 (physical == next_extent.e_pblk - 1) && 1300 (new_uninit == next_uninit) && 1301 ((int) next_extent.e_len < max_len - 1)) { 1302 retval = ext2fs_extent_get(handle, 1303 EXT2_EXTENT_NEXT_LEAF, 1304 &next_extent); 1305 if (retval) 1306 goto done; 1307 next_extent.e_len++; 1308 next_extent.e_lblk--; 1309 next_extent.e_pblk--; 1310 retval = ext2fs_extent_replace(handle, 0, &next_extent); 1311 } else if (logical < extent.e_lblk) 1312 retval = ext2fs_extent_insert(handle, 0, &newextent); 1313 else 1314 retval = ext2fs_extent_insert(handle, 1315 EXT2_EXTENT_INSERT_AFTER, &newextent); 1316 if (retval) 1317 goto done; 1318 retval = ext2fs_extent_fix_parents(handle); 1319 if (retval) 1320 goto done; 1321 } else if ((logical == extent.e_lblk) && (extent.e_len == 1)) { 1322 #ifdef DEBUG 1323 printf("(re/un)mapping only block in extent\n"); 1324 #endif 1325 if (physical) { 1326 retval = ext2fs_extent_replace(handle, 0, &newextent); 1327 } else { 1328 retval = ext2fs_extent_delete(handle, 0); 1329 if (retval) 1330 goto done; 1331 ec = ext2fs_extent_fix_parents(handle); 1332 if (ec != EXT2_ET_NO_CURRENT_NODE) 1333 retval = ec; 1334 } 1335 1336 if (retval) 1337 goto done; 1338 } else if (logical == extent.e_lblk + extent.e_len - 1) { 1339 #ifdef DEBUG 1340 printf("(re/un)mapping last block in extent\n"); 1341 #endif 1342 if (physical) { 1343 if (has_next && 1344 (logical == (next_extent.e_lblk - 1)) && 1345 (physical == (next_extent.e_pblk - 1)) && 1346 (new_uninit == next_uninit) && 1347 ((int) next_extent.e_len < max_len - 1)) { 1348 retval = ext2fs_extent_get(handle, 1349 EXT2_EXTENT_NEXT_LEAF, &next_extent); 1350 if (retval) 1351 goto done; 1352 next_extent.e_len++; 1353 next_extent.e_lblk--; 1354 next_extent.e_pblk--; 1355 retval = ext2fs_extent_replace(handle, 0, 1356 &next_extent); 1357 if (retval) 1358 goto done; 1359 retval = ext2fs_extent_fix_parents(handle); 1360 if (retval) 1361 goto done; 1362 } else 1363 retval = ext2fs_extent_insert(handle, 1364 EXT2_EXTENT_INSERT_AFTER, &newextent); 1365 if (retval) 1366 goto done; 1367 /* Now pointing at inserted extent; move back to prev */ 1368 retval = ext2fs_extent_get(handle, 1369 EXT2_EXTENT_PREV_LEAF, 1370 &extent); 1371 if (retval) 1372 goto done; 1373 } 1374 extent.e_len--; 1375 retval = ext2fs_extent_replace(handle, 0, &extent); 1376 if (retval) 1377 goto done; 1378 } else if (logical == extent.e_lblk) { 1379 #ifdef DEBUG 1380 printf("(re/un)mapping first block in extent\n"); 1381 #endif 1382 if (physical) { 1383 if (has_prev && 1384 (logical == (prev_extent.e_lblk + 1385 prev_extent.e_len)) && 1386 (physical == (prev_extent.e_pblk + 1387 prev_extent.e_len)) && 1388 (new_uninit == prev_uninit) && 1389 ((int) prev_extent.e_len < max_len-1)) { 1390 retval = ext2fs_extent_get(handle, 1391 EXT2_EXTENT_PREV_LEAF, &prev_extent); 1392 if (retval) 1393 goto done; 1394 prev_extent.e_len++; 1395 retval = ext2fs_extent_replace(handle, 0, 1396 &prev_extent); 1397 } else 1398 retval = ext2fs_extent_insert(handle, 1399 0, &newextent); 1400 if (retval) 1401 goto done; 1402 retval = ext2fs_extent_get(handle, 1403 EXT2_EXTENT_NEXT_LEAF, 1404 &extent); 1405 if (retval) 1406 goto done; 1407 } 1408 extent.e_pblk++; 1409 extent.e_lblk++; 1410 extent.e_len--; 1411 retval = ext2fs_extent_replace(handle, 0, &extent); 1412 if (retval) 1413 goto done; 1414 retval = ext2fs_extent_fix_parents(handle); 1415 if (retval) 1416 goto done; 1417 } else { 1418 __u32 orig_length; 1419 1420 #ifdef DEBUG 1421 printf("(re/un)mapping in middle of extent\n"); 1422 #endif 1423 /* need to split this extent; later */ 1424 1425 orig_length = extent.e_len; 1426 1427 /* shorten pre-split extent */ 1428 extent.e_len = (logical - extent.e_lblk); 1429 retval = ext2fs_extent_replace(handle, 0, &extent); 1430 if (retval) 1431 goto done; 1432 /* insert our new extent, if any */ 1433 if (physical) { 1434 /* insert new extent after current */ 1435 retval = ext2fs_extent_insert(handle, 1436 EXT2_EXTENT_INSERT_AFTER, &newextent); 1437 if (retval) 1438 goto done; 1439 } 1440 /* add post-split extent */ 1441 extent.e_pblk += extent.e_len + 1; 1442 extent.e_lblk += extent.e_len + 1; 1443 extent.e_len = orig_length - extent.e_len - 1; 1444 retval = ext2fs_extent_insert(handle, 1445 EXT2_EXTENT_INSERT_AFTER, &extent); 1446 if (retval) 1447 goto done; 1448 } 1449 1450 done: 1451 /* get handle back to its position */ 1452 if (orig_height > handle->max_depth) 1453 orig_height = handle->max_depth; /* In case we shortened the tree */ 1454 ext2fs_extent_goto2(handle, orig_height, orig_lblk); 1455 return retval; 1456 } 1457 1458 errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags) 1459 { 1460 struct extent_path *path; 1461 char *cp; 1462 struct ext3_extent_header *eh; 1463 errcode_t retval = 0; 1464 1465 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); 1466 1467 if (!(handle->fs->flags & EXT2_FLAG_RW)) 1468 return EXT2_ET_RO_FILSYS; 1469 1470 if (!handle->path) 1471 return EXT2_ET_NO_CURRENT_NODE; 1472 1473 #ifdef DEBUG 1474 { 1475 struct ext2fs_extent extent; 1476 1477 retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, 1478 &extent); 1479 if (retval == 0) { 1480 printf("extent delete %u ", handle->ino); 1481 dbg_print_extent(0, &extent); 1482 } 1483 } 1484 #endif 1485 1486 path = handle->path + handle->level; 1487 if (!path->curr) 1488 return EXT2_ET_NO_CURRENT_NODE; 1489 1490 cp = path->curr; 1491 1492 if (path->left) { 1493 memmove(cp, cp + sizeof(struct ext3_extent_idx), 1494 path->left * sizeof(struct ext3_extent_idx)); 1495 path->left--; 1496 } else { 1497 struct ext3_extent_idx *ix = path->curr; 1498 ix--; 1499 path->curr = ix; 1500 } 1501 if (--path->entries == 0) 1502 path->curr = 0; 1503 1504 /* if non-root node has no entries left, remove it & parent ptr to it */ 1505 if (path->entries == 0 && handle->level) { 1506 if (!(flags & EXT2_EXTENT_DELETE_KEEP_EMPTY)) { 1507 struct ext2fs_extent extent; 1508 1509 retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, 1510 &extent); 1511 if (retval) 1512 return retval; 1513 1514 retval = ext2fs_extent_delete(handle, flags); 1515 handle->inode->i_blocks -= 1516 (handle->fs->blocksize * 1517 EXT2FS_CLUSTER_RATIO(handle->fs)) / 512; 1518 retval = ext2fs_write_inode(handle->fs, handle->ino, 1519 handle->inode); 1520 ext2fs_block_alloc_stats2(handle->fs, 1521 extent.e_pblk, -1); 1522 } 1523 } else { 1524 eh = (struct ext3_extent_header *) path->buf; 1525 eh->eh_entries = ext2fs_cpu_to_le16(path->entries); 1526 if ((path->entries == 0) && (handle->level == 0)) 1527 eh->eh_depth = handle->max_depth = 0; 1528 retval = update_path(handle); 1529 } 1530 return retval; 1531 } 1532 1533 errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle, 1534 struct ext2_extent_info *info) 1535 { 1536 struct extent_path *path; 1537 1538 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); 1539 1540 memset(info, 0, sizeof(struct ext2_extent_info)); 1541 1542 path = handle->path + handle->level; 1543 if (path) { 1544 if (path->curr) 1545 info->curr_entry = ((char *) path->curr - path->buf) / 1546 sizeof(struct ext3_extent_idx); 1547 else 1548 info->curr_entry = 0; 1549 info->num_entries = path->entries; 1550 info->max_entries = path->max_entries; 1551 info->bytes_avail = (path->max_entries - path->entries) * 1552 sizeof(struct ext3_extent); 1553 } 1554 1555 info->curr_level = handle->level; 1556 info->max_depth = handle->max_depth; 1557 info->max_lblk = ((__u64) 1 << 32) - 1; 1558 info->max_pblk = ((__u64) 1 << 48) - 1; 1559 info->max_len = (1UL << 15); 1560 info->max_uninit_len = (1UL << 15) - 1; 1561 1562 return 0; 1563 } 1564 1565 #ifdef DEBUG 1566 /* 1567 * Override debugfs's prompt 1568 */ 1569 const char *debug_prog_name = "tst_extents"; 1570 1571 #endif 1572 1573