diff options
Diffstat (limited to 'fs/udf/balloc.c')
-rw-r--r-- | fs/udf/balloc.c | 172 |
1 files changed, 83 insertions, 89 deletions
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index ea521f846d97..756dbbf0eafd 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c | |||
@@ -427,9 +427,9 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
427 | { | 427 | { |
428 | struct udf_sb_info *sbi = UDF_SB(sb); | 428 | struct udf_sb_info *sbi = UDF_SB(sb); |
429 | uint32_t start, end; | 429 | uint32_t start, end; |
430 | uint32_t nextoffset, oextoffset, elen; | 430 | uint32_t elen; |
431 | kernel_lb_addr nbloc, obloc, eloc; | 431 | kernel_lb_addr eloc; |
432 | struct buffer_head *obh, *nbh; | 432 | struct extent_position oepos, epos; |
433 | int8_t etype; | 433 | int8_t etype; |
434 | int i; | 434 | int i; |
435 | 435 | ||
@@ -457,14 +457,13 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
457 | start = bloc.logicalBlockNum + offset; | 457 | start = bloc.logicalBlockNum + offset; |
458 | end = bloc.logicalBlockNum + offset + count - 1; | 458 | end = bloc.logicalBlockNum + offset + count - 1; |
459 | 459 | ||
460 | oextoffset = nextoffset = sizeof(struct unallocSpaceEntry); | 460 | epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry); |
461 | elen = 0; | 461 | elen = 0; |
462 | obloc = nbloc = UDF_I_LOCATION(table); | 462 | epos.block = oepos.block = UDF_I_LOCATION(table); |
463 | 463 | epos.bh = oepos.bh = NULL; | |
464 | obh = nbh = NULL; | ||
465 | 464 | ||
466 | while (count && (etype = | 465 | while (count && (etype = |
467 | udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1) | 466 | udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) |
468 | { | 467 | { |
469 | if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) == | 468 | if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) == |
470 | start)) | 469 | start)) |
@@ -482,7 +481,7 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
482 | start += count; | 481 | start += count; |
483 | count = 0; | 482 | count = 0; |
484 | } | 483 | } |
485 | udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1); | 484 | udf_write_aext(table, &oepos, eloc, elen, 1); |
486 | } | 485 | } |
487 | else if (eloc.logicalBlockNum == (end + 1)) | 486 | else if (eloc.logicalBlockNum == (end + 1)) |
488 | { | 487 | { |
@@ -502,20 +501,20 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
502 | end -= count; | 501 | end -= count; |
503 | count = 0; | 502 | count = 0; |
504 | } | 503 | } |
505 | udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1); | 504 | udf_write_aext(table, &oepos, eloc, elen, 1); |
506 | } | 505 | } |
507 | 506 | ||
508 | if (nbh != obh) | 507 | if (epos.bh != oepos.bh) |
509 | { | 508 | { |
510 | i = -1; | 509 | i = -1; |
511 | obloc = nbloc; | 510 | oepos.block = epos.block; |
512 | udf_release_data(obh); | 511 | udf_release_data(oepos.bh); |
513 | atomic_inc(&nbh->b_count); | 512 | atomic_inc(&epos.bh->b_count); |
514 | obh = nbh; | 513 | oepos.bh = epos.bh; |
515 | oextoffset = 0; | 514 | oepos.offset = 0; |
516 | } | 515 | } |
517 | else | 516 | else |
518 | oextoffset = nextoffset; | 517 | oepos.offset = epos.offset; |
519 | } | 518 | } |
520 | 519 | ||
521 | if (count) | 520 | if (count) |
@@ -547,55 +546,53 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
547 | adsize = sizeof(long_ad); | 546 | adsize = sizeof(long_ad); |
548 | else | 547 | else |
549 | { | 548 | { |
550 | udf_release_data(obh); | 549 | udf_release_data(oepos.bh); |
551 | udf_release_data(nbh); | 550 | udf_release_data(epos.bh); |
552 | goto error_return; | 551 | goto error_return; |
553 | } | 552 | } |
554 | 553 | ||
555 | if (nextoffset + (2 * adsize) > sb->s_blocksize) | 554 | if (epos.offset + (2 * adsize) > sb->s_blocksize) |
556 | { | 555 | { |
557 | char *sptr, *dptr; | 556 | char *sptr, *dptr; |
558 | int loffset; | 557 | int loffset; |
559 | 558 | ||
560 | udf_release_data(obh); | 559 | udf_release_data(oepos.bh); |
561 | obh = nbh; | 560 | oepos = epos; |
562 | obloc = nbloc; | ||
563 | oextoffset = nextoffset; | ||
564 | 561 | ||
565 | /* Steal a block from the extent being free'd */ | 562 | /* Steal a block from the extent being free'd */ |
566 | nbloc.logicalBlockNum = eloc.logicalBlockNum; | 563 | epos.block.logicalBlockNum = eloc.logicalBlockNum; |
567 | eloc.logicalBlockNum ++; | 564 | eloc.logicalBlockNum ++; |
568 | elen -= sb->s_blocksize; | 565 | elen -= sb->s_blocksize; |
569 | 566 | ||
570 | if (!(nbh = udf_tread(sb, | 567 | if (!(epos.bh = udf_tread(sb, |
571 | udf_get_lb_pblock(sb, nbloc, 0)))) | 568 | udf_get_lb_pblock(sb, epos.block, 0)))) |
572 | { | 569 | { |
573 | udf_release_data(obh); | 570 | udf_release_data(oepos.bh); |
574 | goto error_return; | 571 | goto error_return; |
575 | } | 572 | } |
576 | aed = (struct allocExtDesc *)(nbh->b_data); | 573 | aed = (struct allocExtDesc *)(epos.bh->b_data); |
577 | aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum); | 574 | aed->previousAllocExtLocation = cpu_to_le32(oepos.block.logicalBlockNum); |
578 | if (nextoffset + adsize > sb->s_blocksize) | 575 | if (epos.offset + adsize > sb->s_blocksize) |
579 | { | 576 | { |
580 | loffset = nextoffset; | 577 | loffset = epos.offset; |
581 | aed->lengthAllocDescs = cpu_to_le32(adsize); | 578 | aed->lengthAllocDescs = cpu_to_le32(adsize); |
582 | sptr = UDF_I_DATA(inode) + nextoffset - | 579 | sptr = UDF_I_DATA(inode) + epos.offset - |
583 | udf_file_entry_alloc_offset(inode) + | 580 | udf_file_entry_alloc_offset(inode) + |
584 | UDF_I_LENEATTR(inode) - adsize; | 581 | UDF_I_LENEATTR(inode) - adsize; |
585 | dptr = nbh->b_data + sizeof(struct allocExtDesc); | 582 | dptr = epos.bh->b_data + sizeof(struct allocExtDesc); |
586 | memcpy(dptr, sptr, adsize); | 583 | memcpy(dptr, sptr, adsize); |
587 | nextoffset = sizeof(struct allocExtDesc) + adsize; | 584 | epos.offset = sizeof(struct allocExtDesc) + adsize; |
588 | } | 585 | } |
589 | else | 586 | else |
590 | { | 587 | { |
591 | loffset = nextoffset + adsize; | 588 | loffset = epos.offset + adsize; |
592 | aed->lengthAllocDescs = cpu_to_le32(0); | 589 | aed->lengthAllocDescs = cpu_to_le32(0); |
593 | sptr = (obh)->b_data + nextoffset; | 590 | sptr = oepos.bh->b_data + epos.offset; |
594 | nextoffset = sizeof(struct allocExtDesc); | 591 | epos.offset = sizeof(struct allocExtDesc); |
595 | 592 | ||
596 | if (obh) | 593 | if (oepos.bh) |
597 | { | 594 | { |
598 | aed = (struct allocExtDesc *)(obh)->b_data; | 595 | aed = (struct allocExtDesc *)oepos.bh->b_data; |
599 | aed->lengthAllocDescs = | 596 | aed->lengthAllocDescs = |
600 | cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); | 597 | cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); |
601 | } | 598 | } |
@@ -606,11 +603,11 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
606 | } | 603 | } |
607 | } | 604 | } |
608 | if (UDF_SB_UDFREV(sb) >= 0x0200) | 605 | if (UDF_SB_UDFREV(sb) >= 0x0200) |
609 | udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1, | 606 | udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 3, 1, |
610 | nbloc.logicalBlockNum, sizeof(tag)); | 607 | epos.block.logicalBlockNum, sizeof(tag)); |
611 | else | 608 | else |
612 | udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1, | 609 | udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 2, 1, |
613 | nbloc.logicalBlockNum, sizeof(tag)); | 610 | epos.block.logicalBlockNum, sizeof(tag)); |
614 | switch (UDF_I_ALLOCTYPE(table)) | 611 | switch (UDF_I_ALLOCTYPE(table)) |
615 | { | 612 | { |
616 | case ICBTAG_FLAG_AD_SHORT: | 613 | case ICBTAG_FLAG_AD_SHORT: |
@@ -619,7 +616,7 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
619 | sad->extLength = cpu_to_le32( | 616 | sad->extLength = cpu_to_le32( |
620 | EXT_NEXT_EXTENT_ALLOCDECS | | 617 | EXT_NEXT_EXTENT_ALLOCDECS | |
621 | sb->s_blocksize); | 618 | sb->s_blocksize); |
622 | sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum); | 619 | sad->extPosition = cpu_to_le32(epos.block.logicalBlockNum); |
623 | break; | 620 | break; |
624 | } | 621 | } |
625 | case ICBTAG_FLAG_AD_LONG: | 622 | case ICBTAG_FLAG_AD_LONG: |
@@ -628,14 +625,14 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
628 | lad->extLength = cpu_to_le32( | 625 | lad->extLength = cpu_to_le32( |
629 | EXT_NEXT_EXTENT_ALLOCDECS | | 626 | EXT_NEXT_EXTENT_ALLOCDECS | |
630 | sb->s_blocksize); | 627 | sb->s_blocksize); |
631 | lad->extLocation = cpu_to_lelb(nbloc); | 628 | lad->extLocation = cpu_to_lelb(epos.block); |
632 | break; | 629 | break; |
633 | } | 630 | } |
634 | } | 631 | } |
635 | if (obh) | 632 | if (oepos.bh) |
636 | { | 633 | { |
637 | udf_update_tag(obh->b_data, loffset); | 634 | udf_update_tag(oepos.bh->b_data, loffset); |
638 | mark_buffer_dirty(obh); | 635 | mark_buffer_dirty(oepos.bh); |
639 | } | 636 | } |
640 | else | 637 | else |
641 | mark_inode_dirty(table); | 638 | mark_inode_dirty(table); |
@@ -643,26 +640,26 @@ static void udf_table_free_blocks(struct super_block * sb, | |||
643 | 640 | ||
644 | if (elen) /* It's possible that stealing the block emptied the extent */ | 641 | if (elen) /* It's possible that stealing the block emptied the extent */ |
645 | { | 642 | { |
646 | udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1); | 643 | udf_write_aext(table, &epos, eloc, elen, 1); |
647 | 644 | ||
648 | if (!nbh) | 645 | if (!epos.bh) |
649 | { | 646 | { |
650 | UDF_I_LENALLOC(table) += adsize; | 647 | UDF_I_LENALLOC(table) += adsize; |
651 | mark_inode_dirty(table); | 648 | mark_inode_dirty(table); |
652 | } | 649 | } |
653 | else | 650 | else |
654 | { | 651 | { |
655 | aed = (struct allocExtDesc *)nbh->b_data; | 652 | aed = (struct allocExtDesc *)epos.bh->b_data; |
656 | aed->lengthAllocDescs = | 653 | aed->lengthAllocDescs = |
657 | cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); | 654 | cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); |
658 | udf_update_tag(nbh->b_data, nextoffset); | 655 | udf_update_tag(epos.bh->b_data, epos.offset); |
659 | mark_buffer_dirty(nbh); | 656 | mark_buffer_dirty(epos.bh); |
660 | } | 657 | } |
661 | } | 658 | } |
662 | } | 659 | } |
663 | 660 | ||
664 | udf_release_data(nbh); | 661 | udf_release_data(epos.bh); |
665 | udf_release_data(obh); | 662 | udf_release_data(oepos.bh); |
666 | 663 | ||
667 | error_return: | 664 | error_return: |
668 | sb->s_dirt = 1; | 665 | sb->s_dirt = 1; |
@@ -677,9 +674,9 @@ static int udf_table_prealloc_blocks(struct super_block * sb, | |||
677 | { | 674 | { |
678 | struct udf_sb_info *sbi = UDF_SB(sb); | 675 | struct udf_sb_info *sbi = UDF_SB(sb); |
679 | int alloc_count = 0; | 676 | int alloc_count = 0; |
680 | uint32_t extoffset, elen, adsize; | 677 | uint32_t elen, adsize; |
681 | kernel_lb_addr bloc, eloc; | 678 | kernel_lb_addr eloc; |
682 | struct buffer_head *bh; | 679 | struct extent_position epos; |
683 | int8_t etype = -1; | 680 | int8_t etype = -1; |
684 | 681 | ||
685 | if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition)) | 682 | if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition)) |
@@ -693,14 +690,13 @@ static int udf_table_prealloc_blocks(struct super_block * sb, | |||
693 | return 0; | 690 | return 0; |
694 | 691 | ||
695 | mutex_lock(&sbi->s_alloc_mutex); | 692 | mutex_lock(&sbi->s_alloc_mutex); |
696 | extoffset = sizeof(struct unallocSpaceEntry); | 693 | epos.offset = sizeof(struct unallocSpaceEntry); |
697 | bloc = UDF_I_LOCATION(table); | 694 | epos.block = UDF_I_LOCATION(table); |
698 | 695 | epos.bh = NULL; | |
699 | bh = NULL; | ||
700 | eloc.logicalBlockNum = 0xFFFFFFFF; | 696 | eloc.logicalBlockNum = 0xFFFFFFFF; |
701 | 697 | ||
702 | while (first_block != eloc.logicalBlockNum && (etype = | 698 | while (first_block != eloc.logicalBlockNum && (etype = |
703 | udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) | 699 | udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) |
704 | { | 700 | { |
705 | udf_debug("eloc=%d, elen=%d, first_block=%d\n", | 701 | udf_debug("eloc=%d, elen=%d, first_block=%d\n", |
706 | eloc.logicalBlockNum, elen, first_block); | 702 | eloc.logicalBlockNum, elen, first_block); |
@@ -709,7 +705,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb, | |||
709 | 705 | ||
710 | if (first_block == eloc.logicalBlockNum) | 706 | if (first_block == eloc.logicalBlockNum) |
711 | { | 707 | { |
712 | extoffset -= adsize; | 708 | epos.offset -= adsize; |
713 | 709 | ||
714 | alloc_count = (elen >> sb->s_blocksize_bits); | 710 | alloc_count = (elen >> sb->s_blocksize_bits); |
715 | if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count)) | 711 | if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count)) |
@@ -719,15 +715,15 @@ static int udf_table_prealloc_blocks(struct super_block * sb, | |||
719 | alloc_count = block_count; | 715 | alloc_count = block_count; |
720 | eloc.logicalBlockNum += alloc_count; | 716 | eloc.logicalBlockNum += alloc_count; |
721 | elen -= (alloc_count << sb->s_blocksize_bits); | 717 | elen -= (alloc_count << sb->s_blocksize_bits); |
722 | udf_write_aext(table, bloc, &extoffset, eloc, (etype << 30) | elen, bh, 1); | 718 | udf_write_aext(table, &epos, eloc, (etype << 30) | elen, 1); |
723 | } | 719 | } |
724 | else | 720 | else |
725 | udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh); | 721 | udf_delete_aext(table, epos, eloc, (etype << 30) | elen); |
726 | } | 722 | } |
727 | else | 723 | else |
728 | alloc_count = 0; | 724 | alloc_count = 0; |
729 | 725 | ||
730 | udf_release_data(bh); | 726 | udf_release_data(epos.bh); |
731 | 727 | ||
732 | if (alloc_count && UDF_SB_LVIDBH(sb)) | 728 | if (alloc_count && UDF_SB_LVIDBH(sb)) |
733 | { | 729 | { |
@@ -747,9 +743,9 @@ static int udf_table_new_block(struct super_block * sb, | |||
747 | struct udf_sb_info *sbi = UDF_SB(sb); | 743 | struct udf_sb_info *sbi = UDF_SB(sb); |
748 | uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; | 744 | uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; |
749 | uint32_t newblock = 0, adsize; | 745 | uint32_t newblock = 0, adsize; |
750 | uint32_t extoffset, goal_extoffset, elen, goal_elen = 0; | 746 | uint32_t elen, goal_elen = 0; |
751 | kernel_lb_addr bloc, goal_bloc, eloc, goal_eloc; | 747 | kernel_lb_addr eloc, goal_eloc; |
752 | struct buffer_head *bh, *goal_bh; | 748 | struct extent_position epos, goal_epos; |
753 | int8_t etype; | 749 | int8_t etype; |
754 | 750 | ||
755 | *err = -ENOSPC; | 751 | *err = -ENOSPC; |
@@ -770,14 +766,12 @@ static int udf_table_new_block(struct super_block * sb, | |||
770 | We store the buffer_head, bloc, and extoffset of the current closest | 766 | We store the buffer_head, bloc, and extoffset of the current closest |
771 | match and use that when we are done. | 767 | match and use that when we are done. |
772 | */ | 768 | */ |
773 | 769 | epos.offset = sizeof(struct unallocSpaceEntry); | |
774 | extoffset = sizeof(struct unallocSpaceEntry); | 770 | epos.block = UDF_I_LOCATION(table); |
775 | bloc = UDF_I_LOCATION(table); | 771 | epos.bh = goal_epos.bh = NULL; |
776 | |||
777 | goal_bh = bh = NULL; | ||
778 | 772 | ||
779 | while (spread && (etype = | 773 | while (spread && (etype = |
780 | udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) | 774 | udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) |
781 | { | 775 | { |
782 | if (goal >= eloc.logicalBlockNum) | 776 | if (goal >= eloc.logicalBlockNum) |
783 | { | 777 | { |
@@ -793,24 +787,24 @@ static int udf_table_new_block(struct super_block * sb, | |||
793 | if (nspread < spread) | 787 | if (nspread < spread) |
794 | { | 788 | { |
795 | spread = nspread; | 789 | spread = nspread; |
796 | if (goal_bh != bh) | 790 | if (goal_epos.bh != epos.bh) |
797 | { | 791 | { |
798 | udf_release_data(goal_bh); | 792 | udf_release_data(goal_epos.bh); |
799 | goal_bh = bh; | 793 | goal_epos.bh = epos.bh; |
800 | atomic_inc(&goal_bh->b_count); | 794 | atomic_inc(&goal_epos.bh->b_count); |
801 | } | 795 | } |
802 | goal_bloc = bloc; | 796 | goal_epos.block = epos.block; |
803 | goal_extoffset = extoffset - adsize; | 797 | goal_epos.offset = epos.offset - adsize; |
804 | goal_eloc = eloc; | 798 | goal_eloc = eloc; |
805 | goal_elen = (etype << 30) | elen; | 799 | goal_elen = (etype << 30) | elen; |
806 | } | 800 | } |
807 | } | 801 | } |
808 | 802 | ||
809 | udf_release_data(bh); | 803 | udf_release_data(epos.bh); |
810 | 804 | ||
811 | if (spread == 0xFFFFFFFF) | 805 | if (spread == 0xFFFFFFFF) |
812 | { | 806 | { |
813 | udf_release_data(goal_bh); | 807 | udf_release_data(goal_epos.bh); |
814 | mutex_unlock(&sbi->s_alloc_mutex); | 808 | mutex_unlock(&sbi->s_alloc_mutex); |
815 | return 0; | 809 | return 0; |
816 | } | 810 | } |
@@ -826,17 +820,17 @@ static int udf_table_new_block(struct super_block * sb, | |||
826 | 820 | ||
827 | if (inode && DQUOT_ALLOC_BLOCK(inode, 1)) | 821 | if (inode && DQUOT_ALLOC_BLOCK(inode, 1)) |
828 | { | 822 | { |
829 | udf_release_data(goal_bh); | 823 | udf_release_data(goal_epos.bh); |
830 | mutex_unlock(&sbi->s_alloc_mutex); | 824 | mutex_unlock(&sbi->s_alloc_mutex); |
831 | *err = -EDQUOT; | 825 | *err = -EDQUOT; |
832 | return 0; | 826 | return 0; |
833 | } | 827 | } |
834 | 828 | ||
835 | if (goal_elen) | 829 | if (goal_elen) |
836 | udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1); | 830 | udf_write_aext(table, &goal_epos, goal_eloc, goal_elen, 1); |
837 | else | 831 | else |
838 | udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh); | 832 | udf_delete_aext(table, goal_epos, goal_eloc, goal_elen); |
839 | udf_release_data(goal_bh); | 833 | udf_release_data(goal_epos.bh); |
840 | 834 | ||
841 | if (UDF_SB_LVIDBH(sb)) | 835 | if (UDF_SB_LVIDBH(sb)) |
842 | { | 836 | { |