diff options
Diffstat (limited to 'fs/udf/super.c')
| -rw-r--r-- | fs/udf/super.c | 57 |
1 files changed, 23 insertions, 34 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index 7a5f69be6ac2..44cc702f96cc 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -682,38 +682,26 @@ static int udf_vrs(struct super_block *sb, int silent) | |||
| 682 | /* | 682 | /* |
| 683 | * Check whether there is an anchor block in the given block | 683 | * Check whether there is an anchor block in the given block |
| 684 | */ | 684 | */ |
| 685 | static int udf_check_anchor_block(struct super_block *sb, sector_t block, | 685 | static int udf_check_anchor_block(struct super_block *sb, sector_t block) |
| 686 | bool varconv) | ||
| 687 | { | 686 | { |
| 688 | struct buffer_head *bh = NULL; | 687 | struct buffer_head *bh; |
| 689 | tag *t; | ||
| 690 | uint16_t ident; | 688 | uint16_t ident; |
| 691 | uint32_t location; | ||
| 692 | 689 | ||
| 693 | if (varconv) { | 690 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) && |
| 694 | if (udf_fixed_to_variable(block) >= | 691 | udf_fixed_to_variable(block) >= |
| 695 | sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) | 692 | sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) |
| 696 | return 0; | 693 | return 0; |
| 697 | bh = sb_bread(sb, udf_fixed_to_variable(block)); | ||
| 698 | } | ||
| 699 | else | ||
| 700 | bh = sb_bread(sb, block); | ||
| 701 | 694 | ||
| 695 | bh = udf_read_tagged(sb, block, block, &ident); | ||
| 702 | if (!bh) | 696 | if (!bh) |
| 703 | return 0; | 697 | return 0; |
| 704 | |||
| 705 | t = (tag *)bh->b_data; | ||
| 706 | ident = le16_to_cpu(t->tagIdent); | ||
| 707 | location = le32_to_cpu(t->tagLocation); | ||
| 708 | brelse(bh); | 698 | brelse(bh); |
| 709 | if (ident != TAG_IDENT_AVDP) | 699 | |
| 710 | return 0; | 700 | return ident == TAG_IDENT_AVDP; |
| 711 | return location == block; | ||
| 712 | } | 701 | } |
| 713 | 702 | ||
| 714 | /* Search for an anchor volume descriptor pointer */ | 703 | /* Search for an anchor volume descriptor pointer */ |
| 715 | static sector_t udf_scan_anchors(struct super_block *sb, bool varconv, | 704 | static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock) |
| 716 | sector_t lastblock) | ||
| 717 | { | 705 | { |
| 718 | sector_t last[6]; | 706 | sector_t last[6]; |
| 719 | int i; | 707 | int i; |
| @@ -739,7 +727,7 @@ static sector_t udf_scan_anchors(struct super_block *sb, bool varconv, | |||
| 739 | sb->s_blocksize_bits) | 727 | sb->s_blocksize_bits) |
| 740 | continue; | 728 | continue; |
| 741 | 729 | ||
| 742 | if (udf_check_anchor_block(sb, last[i], varconv)) { | 730 | if (udf_check_anchor_block(sb, last[i])) { |
| 743 | sbi->s_anchor[0] = last[i]; | 731 | sbi->s_anchor[0] = last[i]; |
| 744 | sbi->s_anchor[1] = last[i] - 256; | 732 | sbi->s_anchor[1] = last[i] - 256; |
| 745 | return last[i]; | 733 | return last[i]; |
| @@ -748,17 +736,17 @@ static sector_t udf_scan_anchors(struct super_block *sb, bool varconv, | |||
| 748 | if (last[i] < 256) | 736 | if (last[i] < 256) |
| 749 | continue; | 737 | continue; |
| 750 | 738 | ||
| 751 | if (udf_check_anchor_block(sb, last[i] - 256, varconv)) { | 739 | if (udf_check_anchor_block(sb, last[i] - 256)) { |
| 752 | sbi->s_anchor[1] = last[i] - 256; | 740 | sbi->s_anchor[1] = last[i] - 256; |
| 753 | return last[i]; | 741 | return last[i]; |
| 754 | } | 742 | } |
| 755 | } | 743 | } |
| 756 | 744 | ||
| 757 | if (udf_check_anchor_block(sb, sbi->s_session + 256, varconv)) { | 745 | if (udf_check_anchor_block(sb, sbi->s_session + 256)) { |
| 758 | sbi->s_anchor[0] = sbi->s_session + 256; | 746 | sbi->s_anchor[0] = sbi->s_session + 256; |
| 759 | return last[0]; | 747 | return last[0]; |
| 760 | } | 748 | } |
| 761 | if (udf_check_anchor_block(sb, sbi->s_session + 512, varconv)) { | 749 | if (udf_check_anchor_block(sb, sbi->s_session + 512)) { |
| 762 | sbi->s_anchor[0] = sbi->s_session + 512; | 750 | sbi->s_anchor[0] = sbi->s_session + 512; |
| 763 | return last[0]; | 751 | return last[0]; |
| 764 | } | 752 | } |
| @@ -780,23 +768,24 @@ static void udf_find_anchor(struct super_block *sb) | |||
| 780 | int i; | 768 | int i; |
| 781 | struct udf_sb_info *sbi = UDF_SB(sb); | 769 | struct udf_sb_info *sbi = UDF_SB(sb); |
| 782 | 770 | ||
| 783 | lastblock = udf_scan_anchors(sb, 0, sbi->s_last_block); | 771 | lastblock = udf_scan_anchors(sb, sbi->s_last_block); |
| 784 | if (lastblock) | 772 | if (lastblock) |
| 785 | goto check_anchor; | 773 | goto check_anchor; |
| 786 | 774 | ||
| 787 | /* No anchor found? Try VARCONV conversion of block numbers */ | 775 | /* No anchor found? Try VARCONV conversion of block numbers */ |
| 776 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | ||
| 788 | /* Firstly, we try to not convert number of the last block */ | 777 | /* Firstly, we try to not convert number of the last block */ |
| 789 | lastblock = udf_scan_anchors(sb, 1, | 778 | lastblock = udf_scan_anchors(sb, |
| 790 | udf_variable_to_fixed(sbi->s_last_block)); | 779 | udf_variable_to_fixed(sbi->s_last_block)); |
| 791 | if (lastblock) { | 780 | if (lastblock) |
| 792 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | ||
| 793 | goto check_anchor; | 781 | goto check_anchor; |
| 794 | } | ||
| 795 | 782 | ||
| 796 | /* Secondly, we try with converted number of the last block */ | 783 | /* Secondly, we try with converted number of the last block */ |
| 797 | lastblock = udf_scan_anchors(sb, 1, sbi->s_last_block); | 784 | lastblock = udf_scan_anchors(sb, sbi->s_last_block); |
| 798 | if (lastblock) | 785 | if (!lastblock) { |
| 799 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | 786 | /* VARCONV didn't help. Clear it. */ |
| 787 | UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV); | ||
| 788 | } | ||
| 800 | 789 | ||
| 801 | check_anchor: | 790 | check_anchor: |
| 802 | /* | 791 | /* |
