diff options
-rw-r--r-- | fs/ntfs/ChangeLog | 4 | ||||
-rw-r--r-- | fs/ntfs/inode.c | 344 |
2 files changed, 174 insertions, 174 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 53bb6c1404f2..ad2c4e88f053 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -76,6 +76,10 @@ ToDo/Notes: | |||
76 | warning in the do_div() call on sparc32. Thanks to Meelis Roos for | 76 | warning in the do_div() call on sparc32. Thanks to Meelis Roos for |
77 | the report and analysis of the warning. | 77 | the report and analysis of the warning. |
78 | - Fix a nasty runlist merge bug when merging two holes. | 78 | - Fix a nasty runlist merge bug when merging two holes. |
79 | - Set the ntfs_inode->allocated_size to the real allocated size in the | ||
80 | mft record for resident attributes (fs/ntfs/inode.c). | ||
81 | - Small readability cleanup to use "a" instead of "ctx->attr" | ||
82 | everywhere (fs/ntfs/inode.c). | ||
79 | 83 | ||
80 | 2.1.22 - Many bug and race fixes and error handling improvements. | 84 | 2.1.22 - Many bug and race fixes and error handling improvements. |
81 | 85 | ||
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 372c7fcdc068..cfca17384115 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -525,6 +525,7 @@ static int ntfs_read_locked_inode(struct inode *vi) | |||
525 | ntfs_volume *vol = NTFS_SB(vi->i_sb); | 525 | ntfs_volume *vol = NTFS_SB(vi->i_sb); |
526 | ntfs_inode *ni; | 526 | ntfs_inode *ni; |
527 | MFT_RECORD *m; | 527 | MFT_RECORD *m; |
528 | ATTR_RECORD *a; | ||
528 | STANDARD_INFORMATION *si; | 529 | STANDARD_INFORMATION *si; |
529 | ntfs_attr_search_ctx *ctx; | 530 | ntfs_attr_search_ctx *ctx; |
530 | int err = 0; | 531 | int err = 0; |
@@ -633,9 +634,10 @@ static int ntfs_read_locked_inode(struct inode *vi) | |||
633 | } | 634 | } |
634 | goto unm_err_out; | 635 | goto unm_err_out; |
635 | } | 636 | } |
637 | a = ctx->attr; | ||
636 | /* Get the standard information attribute value. */ | 638 | /* Get the standard information attribute value. */ |
637 | si = (STANDARD_INFORMATION*)((char*)ctx->attr + | 639 | si = (STANDARD_INFORMATION*)((u8*)a + |
638 | le16_to_cpu(ctx->attr->data.resident.value_offset)); | 640 | le16_to_cpu(a->data.resident.value_offset)); |
639 | 641 | ||
640 | /* Transfer information from the standard information into vi. */ | 642 | /* Transfer information from the standard information into vi. */ |
641 | /* | 643 | /* |
@@ -674,15 +676,16 @@ static int ntfs_read_locked_inode(struct inode *vi) | |||
674 | goto skip_attr_list_load; | 676 | goto skip_attr_list_load; |
675 | ntfs_debug("Attribute list found in inode 0x%lx.", vi->i_ino); | 677 | ntfs_debug("Attribute list found in inode 0x%lx.", vi->i_ino); |
676 | NInoSetAttrList(ni); | 678 | NInoSetAttrList(ni); |
677 | if (ctx->attr->flags & ATTR_IS_ENCRYPTED || | 679 | a = ctx->attr; |
678 | ctx->attr->flags & ATTR_COMPRESSION_MASK || | 680 | if (a->flags & ATTR_IS_ENCRYPTED || |
679 | ctx->attr->flags & ATTR_IS_SPARSE) { | 681 | a->flags & ATTR_COMPRESSION_MASK || |
682 | a->flags & ATTR_IS_SPARSE) { | ||
680 | ntfs_error(vi->i_sb, "Attribute list attribute is " | 683 | ntfs_error(vi->i_sb, "Attribute list attribute is " |
681 | "compressed/encrypted/sparse."); | 684 | "compressed/encrypted/sparse."); |
682 | goto unm_err_out; | 685 | goto unm_err_out; |
683 | } | 686 | } |
684 | /* Now allocate memory for the attribute list. */ | 687 | /* Now allocate memory for the attribute list. */ |
685 | ni->attr_list_size = (u32)ntfs_attr_size(ctx->attr); | 688 | ni->attr_list_size = (u32)ntfs_attr_size(a); |
686 | ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size); | 689 | ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size); |
687 | if (!ni->attr_list) { | 690 | if (!ni->attr_list) { |
688 | ntfs_error(vi->i_sb, "Not enough memory to allocate " | 691 | ntfs_error(vi->i_sb, "Not enough memory to allocate " |
@@ -690,9 +693,9 @@ static int ntfs_read_locked_inode(struct inode *vi) | |||
690 | err = -ENOMEM; | 693 | err = -ENOMEM; |
691 | goto unm_err_out; | 694 | goto unm_err_out; |
692 | } | 695 | } |
693 | if (ctx->attr->non_resident) { | 696 | if (a->non_resident) { |
694 | NInoSetAttrListNonResident(ni); | 697 | NInoSetAttrListNonResident(ni); |
695 | if (ctx->attr->data.non_resident.lowest_vcn) { | 698 | if (a->data.non_resident.lowest_vcn) { |
696 | ntfs_error(vi->i_sb, "Attribute list has non " | 699 | ntfs_error(vi->i_sb, "Attribute list has non " |
697 | "zero lowest_vcn."); | 700 | "zero lowest_vcn."); |
698 | goto unm_err_out; | 701 | goto unm_err_out; |
@@ -702,7 +705,7 @@ static int ntfs_read_locked_inode(struct inode *vi) | |||
702 | * exclusive access to the inode at this time. | 705 | * exclusive access to the inode at this time. |
703 | */ | 706 | */ |
704 | ni->attr_list_rl.rl = ntfs_mapping_pairs_decompress(vol, | 707 | ni->attr_list_rl.rl = ntfs_mapping_pairs_decompress(vol, |
705 | ctx->attr, NULL); | 708 | a, NULL); |
706 | if (IS_ERR(ni->attr_list_rl.rl)) { | 709 | if (IS_ERR(ni->attr_list_rl.rl)) { |
707 | err = PTR_ERR(ni->attr_list_rl.rl); | 710 | err = PTR_ERR(ni->attr_list_rl.rl); |
708 | ni->attr_list_rl.rl = NULL; | 711 | ni->attr_list_rl.rl = NULL; |
@@ -713,27 +716,26 @@ static int ntfs_read_locked_inode(struct inode *vi) | |||
713 | /* Now load the attribute list. */ | 716 | /* Now load the attribute list. */ |
714 | if ((err = load_attribute_list(vol, &ni->attr_list_rl, | 717 | if ((err = load_attribute_list(vol, &ni->attr_list_rl, |
715 | ni->attr_list, ni->attr_list_size, | 718 | ni->attr_list, ni->attr_list_size, |
716 | sle64_to_cpu(ctx->attr->data. | 719 | sle64_to_cpu(a->data.non_resident. |
717 | non_resident.initialized_size)))) { | 720 | initialized_size)))) { |
718 | ntfs_error(vi->i_sb, "Failed to load " | 721 | ntfs_error(vi->i_sb, "Failed to load " |
719 | "attribute list attribute."); | 722 | "attribute list attribute."); |
720 | goto unm_err_out; | 723 | goto unm_err_out; |
721 | } | 724 | } |
722 | } else /* if (!ctx.attr->non_resident) */ { | 725 | } else /* if (!a->non_resident) */ { |
723 | if ((u8*)ctx->attr + le16_to_cpu( | 726 | if ((u8*)a + le16_to_cpu(a->data.resident.value_offset) |
724 | ctx->attr->data.resident.value_offset) + | 727 | + le32_to_cpu( |
725 | le32_to_cpu( | 728 | a->data.resident.value_length) > |
726 | ctx->attr->data.resident.value_length) > | ||
727 | (u8*)ctx->mrec + vol->mft_record_size) { | 729 | (u8*)ctx->mrec + vol->mft_record_size) { |
728 | ntfs_error(vi->i_sb, "Corrupt attribute list " | 730 | ntfs_error(vi->i_sb, "Corrupt attribute list " |
729 | "in inode."); | 731 | "in inode."); |
730 | goto unm_err_out; | 732 | goto unm_err_out; |
731 | } | 733 | } |
732 | /* Now copy the attribute list. */ | 734 | /* Now copy the attribute list. */ |
733 | memcpy(ni->attr_list, (u8*)ctx->attr + le16_to_cpu( | 735 | memcpy(ni->attr_list, (u8*)a + le16_to_cpu( |
734 | ctx->attr->data.resident.value_offset), | 736 | a->data.resident.value_offset), |
735 | le32_to_cpu( | 737 | le32_to_cpu( |
736 | ctx->attr->data.resident.value_length)); | 738 | a->data.resident.value_length)); |
737 | } | 739 | } |
738 | } | 740 | } |
739 | skip_attr_list_load: | 741 | skip_attr_list_load: |
@@ -746,7 +748,7 @@ skip_attr_list_load: | |||
746 | struct inode *bvi; | 748 | struct inode *bvi; |
747 | ntfs_inode *bni; | 749 | ntfs_inode *bni; |
748 | INDEX_ROOT *ir; | 750 | INDEX_ROOT *ir; |
749 | char *ir_end, *index_end; | 751 | u8 *ir_end, *index_end; |
750 | 752 | ||
751 | /* It is a directory, find index root attribute. */ | 753 | /* It is a directory, find index root attribute. */ |
752 | ntfs_attr_reinit_search_ctx(ctx); | 754 | ntfs_attr_reinit_search_ctx(ctx); |
@@ -762,17 +764,16 @@ skip_attr_list_load: | |||
762 | } | 764 | } |
763 | goto unm_err_out; | 765 | goto unm_err_out; |
764 | } | 766 | } |
767 | a = ctx->attr; | ||
765 | /* Set up the state. */ | 768 | /* Set up the state. */ |
766 | if (unlikely(ctx->attr->non_resident)) { | 769 | if (unlikely(a->non_resident)) { |
767 | ntfs_error(vol->sb, "$INDEX_ROOT attribute is not " | 770 | ntfs_error(vol->sb, "$INDEX_ROOT attribute is not " |
768 | "resident."); | 771 | "resident."); |
769 | goto unm_err_out; | 772 | goto unm_err_out; |
770 | } | 773 | } |
771 | /* Ensure the attribute name is placed before the value. */ | 774 | /* Ensure the attribute name is placed before the value. */ |
772 | if (unlikely(ctx->attr->name_length && | 775 | if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= |
773 | (le16_to_cpu(ctx->attr->name_offset) >= | 776 | le16_to_cpu(a->data.resident.value_offset)))) { |
774 | le16_to_cpu(ctx->attr->data.resident. | ||
775 | value_offset)))) { | ||
776 | ntfs_error(vol->sb, "$INDEX_ROOT attribute name is " | 777 | ntfs_error(vol->sb, "$INDEX_ROOT attribute name is " |
777 | "placed after the attribute value."); | 778 | "placed after the attribute value."); |
778 | goto unm_err_out; | 779 | goto unm_err_out; |
@@ -783,28 +784,27 @@ skip_attr_list_load: | |||
783 | * encrypted. However index root cannot be both compressed and | 784 | * encrypted. However index root cannot be both compressed and |
784 | * encrypted. | 785 | * encrypted. |
785 | */ | 786 | */ |
786 | if (ctx->attr->flags & ATTR_COMPRESSION_MASK) | 787 | if (a->flags & ATTR_COMPRESSION_MASK) |
787 | NInoSetCompressed(ni); | 788 | NInoSetCompressed(ni); |
788 | if (ctx->attr->flags & ATTR_IS_ENCRYPTED) { | 789 | if (a->flags & ATTR_IS_ENCRYPTED) { |
789 | if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { | 790 | if (a->flags & ATTR_COMPRESSION_MASK) { |
790 | ntfs_error(vi->i_sb, "Found encrypted and " | 791 | ntfs_error(vi->i_sb, "Found encrypted and " |
791 | "compressed attribute."); | 792 | "compressed attribute."); |
792 | goto unm_err_out; | 793 | goto unm_err_out; |
793 | } | 794 | } |
794 | NInoSetEncrypted(ni); | 795 | NInoSetEncrypted(ni); |
795 | } | 796 | } |
796 | if (ctx->attr->flags & ATTR_IS_SPARSE) | 797 | if (a->flags & ATTR_IS_SPARSE) |
797 | NInoSetSparse(ni); | 798 | NInoSetSparse(ni); |
798 | ir = (INDEX_ROOT*)((char*)ctx->attr + le16_to_cpu( | 799 | ir = (INDEX_ROOT*)((u8*)a + |
799 | ctx->attr->data.resident.value_offset)); | 800 | le16_to_cpu(a->data.resident.value_offset)); |
800 | ir_end = (char*)ir + le32_to_cpu( | 801 | ir_end = (u8*)ir + le32_to_cpu(a->data.resident.value_length); |
801 | ctx->attr->data.resident.value_length); | 802 | if (ir_end > (u8*)ctx->mrec + vol->mft_record_size) { |
802 | if (ir_end > (char*)ctx->mrec + vol->mft_record_size) { | ||
803 | ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is " | 803 | ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is " |
804 | "corrupt."); | 804 | "corrupt."); |
805 | goto unm_err_out; | 805 | goto unm_err_out; |
806 | } | 806 | } |
807 | index_end = (char*)&ir->index + | 807 | index_end = (u8*)&ir->index + |
808 | le32_to_cpu(ir->index.index_length); | 808 | le32_to_cpu(ir->index.index_length); |
809 | if (index_end > ir_end) { | 809 | if (index_end > ir_end) { |
810 | ntfs_error(vi->i_sb, "Directory index is corrupt."); | 810 | ntfs_error(vi->i_sb, "Directory index is corrupt."); |
@@ -891,7 +891,8 @@ skip_attr_list_load: | |||
891 | "attribute."); | 891 | "attribute."); |
892 | goto unm_err_out; | 892 | goto unm_err_out; |
893 | } | 893 | } |
894 | if (!ctx->attr->non_resident) { | 894 | a = ctx->attr; |
895 | if (!a->non_resident) { | ||
895 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " | 896 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " |
896 | "is resident."); | 897 | "is resident."); |
897 | goto unm_err_out; | 898 | goto unm_err_out; |
@@ -900,42 +901,40 @@ skip_attr_list_load: | |||
900 | * Ensure the attribute name is placed before the mapping pairs | 901 | * Ensure the attribute name is placed before the mapping pairs |
901 | * array. | 902 | * array. |
902 | */ | 903 | */ |
903 | if (unlikely(ctx->attr->name_length && | 904 | if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= |
904 | (le16_to_cpu(ctx->attr->name_offset) >= | 905 | le16_to_cpu( |
905 | le16_to_cpu(ctx->attr->data.non_resident. | 906 | a->data.non_resident.mapping_pairs_offset)))) { |
906 | mapping_pairs_offset)))) { | ||
907 | ntfs_error(vol->sb, "$INDEX_ALLOCATION attribute name " | 907 | ntfs_error(vol->sb, "$INDEX_ALLOCATION attribute name " |
908 | "is placed after the mapping pairs " | 908 | "is placed after the mapping pairs " |
909 | "array."); | 909 | "array."); |
910 | goto unm_err_out; | 910 | goto unm_err_out; |
911 | } | 911 | } |
912 | if (ctx->attr->flags & ATTR_IS_ENCRYPTED) { | 912 | if (a->flags & ATTR_IS_ENCRYPTED) { |
913 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " | 913 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " |
914 | "is encrypted."); | 914 | "is encrypted."); |
915 | goto unm_err_out; | 915 | goto unm_err_out; |
916 | } | 916 | } |
917 | if (ctx->attr->flags & ATTR_IS_SPARSE) { | 917 | if (a->flags & ATTR_IS_SPARSE) { |
918 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " | 918 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " |
919 | "is sparse."); | 919 | "is sparse."); |
920 | goto unm_err_out; | 920 | goto unm_err_out; |
921 | } | 921 | } |
922 | if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { | 922 | if (a->flags & ATTR_COMPRESSION_MASK) { |
923 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " | 923 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute " |
924 | "is compressed."); | 924 | "is compressed."); |
925 | goto unm_err_out; | 925 | goto unm_err_out; |
926 | } | 926 | } |
927 | if (ctx->attr->data.non_resident.lowest_vcn) { | 927 | if (a->data.non_resident.lowest_vcn) { |
928 | ntfs_error(vi->i_sb, "First extent of " | 928 | ntfs_error(vi->i_sb, "First extent of " |
929 | "$INDEX_ALLOCATION attribute has non " | 929 | "$INDEX_ALLOCATION attribute has non " |
930 | "zero lowest_vcn."); | 930 | "zero lowest_vcn."); |
931 | goto unm_err_out; | 931 | goto unm_err_out; |
932 | } | 932 | } |
933 | vi->i_size = sle64_to_cpu( | 933 | vi->i_size = sle64_to_cpu(a->data.non_resident.data_size); |
934 | ctx->attr->data.non_resident.data_size); | ||
935 | ni->initialized_size = sle64_to_cpu( | 934 | ni->initialized_size = sle64_to_cpu( |
936 | ctx->attr->data.non_resident.initialized_size); | 935 | a->data.non_resident.initialized_size); |
937 | ni->allocated_size = sle64_to_cpu( | 936 | ni->allocated_size = sle64_to_cpu( |
938 | ctx->attr->data.non_resident.allocated_size); | 937 | a->data.non_resident.allocated_size); |
939 | /* | 938 | /* |
940 | * We are done with the mft record, so we release it. Otherwise | 939 | * We are done with the mft record, so we release it. Otherwise |
941 | * we would deadlock in ntfs_attr_iget(). | 940 | * we would deadlock in ntfs_attr_iget(). |
@@ -1013,10 +1012,11 @@ skip_large_dir_stuff: | |||
1013 | ntfs_error(vi->i_sb, "$DATA attribute is missing."); | 1012 | ntfs_error(vi->i_sb, "$DATA attribute is missing."); |
1014 | goto unm_err_out; | 1013 | goto unm_err_out; |
1015 | } | 1014 | } |
1015 | a = ctx->attr; | ||
1016 | /* Setup the state. */ | 1016 | /* Setup the state. */ |
1017 | if (ctx->attr->non_resident) { | 1017 | if (a->non_resident) { |
1018 | NInoSetNonResident(ni); | 1018 | NInoSetNonResident(ni); |
1019 | if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { | 1019 | if (a->flags & ATTR_COMPRESSION_MASK) { |
1020 | NInoSetCompressed(ni); | 1020 | NInoSetCompressed(ni); |
1021 | if (vol->cluster_size > 4096) { | 1021 | if (vol->cluster_size > 4096) { |
1022 | ntfs_error(vi->i_sb, "Found " | 1022 | ntfs_error(vi->i_sb, "Found " |
@@ -1026,7 +1026,7 @@ skip_large_dir_stuff: | |||
1026 | vol->cluster_size); | 1026 | vol->cluster_size); |
1027 | goto unm_err_out; | 1027 | goto unm_err_out; |
1028 | } | 1028 | } |
1029 | if ((ctx->attr->flags & ATTR_COMPRESSION_MASK) | 1029 | if ((a->flags & ATTR_COMPRESSION_MASK) |
1030 | != ATTR_IS_COMPRESSED) { | 1030 | != ATTR_IS_COMPRESSED) { |
1031 | ntfs_error(vi->i_sb, "Found " | 1031 | ntfs_error(vi->i_sb, "Found " |
1032 | "unknown compression method or " | 1032 | "unknown compression method or " |
@@ -1034,37 +1034,37 @@ skip_large_dir_stuff: | |||
1034 | goto unm_err_out; | 1034 | goto unm_err_out; |
1035 | } | 1035 | } |
1036 | ni->itype.compressed.block_clusters = 1U << | 1036 | ni->itype.compressed.block_clusters = 1U << |
1037 | ctx->attr->data.non_resident. | 1037 | a->data.non_resident. |
1038 | compression_unit; | 1038 | compression_unit; |
1039 | if (ctx->attr->data.non_resident. | 1039 | if (a->data.non_resident.compression_unit != |
1040 | compression_unit != 4) { | 1040 | 4) { |
1041 | ntfs_error(vi->i_sb, "Found " | 1041 | ntfs_error(vi->i_sb, "Found " |
1042 | "nonstandard compression unit " | 1042 | "nonstandard compression unit " |
1043 | "(%u instead of 4). Cannot " | 1043 | "(%u instead of 4). Cannot " |
1044 | "handle this.", | 1044 | "handle this.", |
1045 | ctx->attr->data.non_resident. | 1045 | a->data.non_resident. |
1046 | compression_unit); | 1046 | compression_unit); |
1047 | err = -EOPNOTSUPP; | 1047 | err = -EOPNOTSUPP; |
1048 | goto unm_err_out; | 1048 | goto unm_err_out; |
1049 | } | 1049 | } |
1050 | ni->itype.compressed.block_size = 1U << ( | 1050 | ni->itype.compressed.block_size = 1U << ( |
1051 | ctx->attr->data.non_resident. | 1051 | a->data.non_resident. |
1052 | compression_unit + | 1052 | compression_unit + |
1053 | vol->cluster_size_bits); | 1053 | vol->cluster_size_bits); |
1054 | ni->itype.compressed.block_size_bits = ffs( | 1054 | ni->itype.compressed.block_size_bits = ffs( |
1055 | ni->itype.compressed.block_size) - 1; | 1055 | ni->itype.compressed.block_size) - 1; |
1056 | } | 1056 | } |
1057 | if (ctx->attr->flags & ATTR_IS_ENCRYPTED) { | 1057 | if (a->flags & ATTR_IS_ENCRYPTED) { |
1058 | if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { | 1058 | if (a->flags & ATTR_COMPRESSION_MASK) { |
1059 | ntfs_error(vi->i_sb, "Found encrypted " | 1059 | ntfs_error(vi->i_sb, "Found encrypted " |
1060 | "and compressed data."); | 1060 | "and compressed data."); |
1061 | goto unm_err_out; | 1061 | goto unm_err_out; |
1062 | } | 1062 | } |
1063 | NInoSetEncrypted(ni); | 1063 | NInoSetEncrypted(ni); |
1064 | } | 1064 | } |
1065 | if (ctx->attr->flags & ATTR_IS_SPARSE) | 1065 | if (a->flags & ATTR_IS_SPARSE) |
1066 | NInoSetSparse(ni); | 1066 | NInoSetSparse(ni); |
1067 | if (ctx->attr->data.non_resident.lowest_vcn) { | 1067 | if (a->data.non_resident.lowest_vcn) { |
1068 | ntfs_error(vi->i_sb, "First extent of $DATA " | 1068 | ntfs_error(vi->i_sb, "First extent of $DATA " |
1069 | "attribute has non zero " | 1069 | "attribute has non zero " |
1070 | "lowest_vcn."); | 1070 | "lowest_vcn."); |
@@ -1072,28 +1072,28 @@ skip_large_dir_stuff: | |||
1072 | } | 1072 | } |
1073 | /* Setup all the sizes. */ | 1073 | /* Setup all the sizes. */ |
1074 | vi->i_size = sle64_to_cpu( | 1074 | vi->i_size = sle64_to_cpu( |
1075 | ctx->attr->data.non_resident.data_size); | 1075 | a->data.non_resident.data_size); |
1076 | ni->initialized_size = sle64_to_cpu( | 1076 | ni->initialized_size = sle64_to_cpu( |
1077 | ctx->attr->data.non_resident. | 1077 | a->data.non_resident.initialized_size); |
1078 | initialized_size); | ||
1079 | ni->allocated_size = sle64_to_cpu( | 1078 | ni->allocated_size = sle64_to_cpu( |
1080 | ctx->attr->data.non_resident. | 1079 | a->data.non_resident.allocated_size); |
1081 | allocated_size); | 1080 | if (NInoCompressed(ni)) |
1082 | if (NInoCompressed(ni)) { | ||
1083 | ni->itype.compressed.size = sle64_to_cpu( | 1081 | ni->itype.compressed.size = sle64_to_cpu( |
1084 | ctx->attr->data.non_resident. | 1082 | a->data.non_resident. |
1085 | compressed_size); | 1083 | compressed_size); |
1086 | } | ||
1087 | } else { /* Resident attribute. */ | 1084 | } else { /* Resident attribute. */ |
1088 | /* | 1085 | /* Setup all the sizes. */ |
1089 | * Make all sizes equal for simplicity in read code | 1086 | vi->i_size = ni->initialized_size = le32_to_cpu( |
1090 | * paths. FIXME: Need to keep this in mind when | 1087 | a->data.resident.value_length); |
1091 | * converting to non-resident attribute in write code | 1088 | ni->allocated_size = le32_to_cpu(a->length) - |
1092 | * path. (Probably only affects truncate().) | 1089 | le16_to_cpu( |
1093 | */ | 1090 | a->data.resident.value_offset); |
1094 | vi->i_size = ni->initialized_size = ni->allocated_size = | 1091 | if (vi->i_size > ni->allocated_size) { |
1095 | le32_to_cpu( | 1092 | ntfs_error(vi->i_sb, "Resident data attribute " |
1096 | ctx->attr->data.resident.value_length); | 1093 | "is corrupt (size exceeds " |
1094 | "allocation)."); | ||
1095 | goto unm_err_out; | ||
1096 | } | ||
1097 | } | 1097 | } |
1098 | no_data_attr_special_case: | 1098 | no_data_attr_special_case: |
1099 | /* We are done with the mft record, so we release it. */ | 1099 | /* We are done with the mft record, so we release it. */ |
@@ -1169,6 +1169,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1169 | ntfs_volume *vol = NTFS_SB(vi->i_sb); | 1169 | ntfs_volume *vol = NTFS_SB(vi->i_sb); |
1170 | ntfs_inode *ni, *base_ni; | 1170 | ntfs_inode *ni, *base_ni; |
1171 | MFT_RECORD *m; | 1171 | MFT_RECORD *m; |
1172 | ATTR_RECORD *a; | ||
1172 | ntfs_attr_search_ctx *ctx; | 1173 | ntfs_attr_search_ctx *ctx; |
1173 | int err = 0; | 1174 | int err = 0; |
1174 | 1175 | ||
@@ -1203,24 +1204,21 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1203 | err = -ENOMEM; | 1204 | err = -ENOMEM; |
1204 | goto unm_err_out; | 1205 | goto unm_err_out; |
1205 | } | 1206 | } |
1206 | |||
1207 | /* Find the attribute. */ | 1207 | /* Find the attribute. */ |
1208 | err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, | 1208 | err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, |
1209 | CASE_SENSITIVE, 0, NULL, 0, ctx); | 1209 | CASE_SENSITIVE, 0, NULL, 0, ctx); |
1210 | if (unlikely(err)) | 1210 | if (unlikely(err)) |
1211 | goto unm_err_out; | 1211 | goto unm_err_out; |
1212 | 1212 | a = ctx->attr; | |
1213 | if (!ctx->attr->non_resident) { | 1213 | if (!a->non_resident) { |
1214 | /* Ensure the attribute name is placed before the value. */ | 1214 | /* Ensure the attribute name is placed before the value. */ |
1215 | if (unlikely(ctx->attr->name_length && | 1215 | if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= |
1216 | (le16_to_cpu(ctx->attr->name_offset) >= | 1216 | le16_to_cpu(a->data.resident.value_offset)))) { |
1217 | le16_to_cpu(ctx->attr->data.resident. | ||
1218 | value_offset)))) { | ||
1219 | ntfs_error(vol->sb, "Attribute name is placed after " | 1217 | ntfs_error(vol->sb, "Attribute name is placed after " |
1220 | "the attribute value."); | 1218 | "the attribute value."); |
1221 | goto unm_err_out; | 1219 | goto unm_err_out; |
1222 | } | 1220 | } |
1223 | if (NInoMstProtected(ni) || ctx->attr->flags) { | 1221 | if (NInoMstProtected(ni) || a->flags) { |
1224 | ntfs_error(vi->i_sb, "Found mst protected attribute " | 1222 | ntfs_error(vi->i_sb, "Found mst protected attribute " |
1225 | "or attribute with non-zero flags but " | 1223 | "or attribute with non-zero flags but " |
1226 | "the attribute is resident. Please " | 1224 | "the attribute is resident. Please " |
@@ -1228,27 +1226,30 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1228 | "linux-ntfs-dev@lists.sourceforge.net"); | 1226 | "linux-ntfs-dev@lists.sourceforge.net"); |
1229 | goto unm_err_out; | 1227 | goto unm_err_out; |
1230 | } | 1228 | } |
1231 | /* | 1229 | /* Resident attribute. Setup all the sizes. */ |
1232 | * Resident attribute. Make all sizes equal for simplicity in | 1230 | vi->i_size = ni->initialized_size = le32_to_cpu( |
1233 | * read code paths. | 1231 | a->data.resident.value_length); |
1234 | */ | 1232 | ni->allocated_size = le32_to_cpu(a->length) - |
1235 | vi->i_size = ni->initialized_size = ni->allocated_size = | 1233 | le16_to_cpu(a->data.resident.value_offset); |
1236 | le32_to_cpu(ctx->attr->data.resident.value_length); | 1234 | if (vi->i_size > ni->allocated_size) { |
1235 | ntfs_error(vi->i_sb, "Resident data attribute is " | ||
1236 | "corrupt (size exceeds allocation)."); | ||
1237 | goto unm_err_out; | ||
1238 | } | ||
1237 | } else { | 1239 | } else { |
1238 | NInoSetNonResident(ni); | 1240 | NInoSetNonResident(ni); |
1239 | /* | 1241 | /* |
1240 | * Ensure the attribute name is placed before the mapping pairs | 1242 | * Ensure the attribute name is placed before the mapping pairs |
1241 | * array. | 1243 | * array. |
1242 | */ | 1244 | */ |
1243 | if (unlikely(ctx->attr->name_length && | 1245 | if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= |
1244 | (le16_to_cpu(ctx->attr->name_offset) >= | 1246 | le16_to_cpu( |
1245 | le16_to_cpu(ctx->attr->data.non_resident. | 1247 | a->data.non_resident.mapping_pairs_offset)))) { |
1246 | mapping_pairs_offset)))) { | ||
1247 | ntfs_error(vol->sb, "Attribute name is placed after " | 1248 | ntfs_error(vol->sb, "Attribute name is placed after " |
1248 | "the mapping pairs array."); | 1249 | "the mapping pairs array."); |
1249 | goto unm_err_out; | 1250 | goto unm_err_out; |
1250 | } | 1251 | } |
1251 | if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { | 1252 | if (a->flags & ATTR_COMPRESSION_MASK) { |
1252 | if (NInoMstProtected(ni)) { | 1253 | if (NInoMstProtected(ni)) { |
1253 | ntfs_error(vi->i_sb, "Found mst protected " | 1254 | ntfs_error(vi->i_sb, "Found mst protected " |
1254 | "attribute but the attribute " | 1255 | "attribute but the attribute " |
@@ -1277,36 +1278,33 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1277 | vol->cluster_size); | 1278 | vol->cluster_size); |
1278 | goto unm_err_out; | 1279 | goto unm_err_out; |
1279 | } | 1280 | } |
1280 | if ((ctx->attr->flags & ATTR_COMPRESSION_MASK) | 1281 | if ((a->flags & ATTR_COMPRESSION_MASK) != |
1281 | != ATTR_IS_COMPRESSED) { | 1282 | ATTR_IS_COMPRESSED) { |
1282 | ntfs_error(vi->i_sb, "Found unknown " | 1283 | ntfs_error(vi->i_sb, "Found unknown " |
1283 | "compression method."); | 1284 | "compression method."); |
1284 | goto unm_err_out; | 1285 | goto unm_err_out; |
1285 | } | 1286 | } |
1286 | ni->itype.compressed.block_clusters = 1U << | 1287 | ni->itype.compressed.block_clusters = 1U << |
1287 | ctx->attr->data.non_resident. | 1288 | a->data.non_resident.compression_unit; |
1288 | compression_unit; | 1289 | if (a->data.non_resident.compression_unit != 4) { |
1289 | if (ctx->attr->data.non_resident.compression_unit != | ||
1290 | 4) { | ||
1291 | ntfs_error(vi->i_sb, "Found nonstandard " | 1290 | ntfs_error(vi->i_sb, "Found nonstandard " |
1292 | "compression unit (%u instead " | 1291 | "compression unit (%u instead " |
1293 | "of 4). Cannot handle this.", | 1292 | "of 4). Cannot handle this.", |
1294 | ctx->attr->data.non_resident. | 1293 | a->data.non_resident. |
1295 | compression_unit); | 1294 | compression_unit); |
1296 | err = -EOPNOTSUPP; | 1295 | err = -EOPNOTSUPP; |
1297 | goto unm_err_out; | 1296 | goto unm_err_out; |
1298 | } | 1297 | } |
1299 | ni->itype.compressed.block_size = 1U << ( | 1298 | ni->itype.compressed.block_size = 1U << ( |
1300 | ctx->attr->data.non_resident. | 1299 | a->data.non_resident.compression_unit + |
1301 | compression_unit + | ||
1302 | vol->cluster_size_bits); | 1300 | vol->cluster_size_bits); |
1303 | ni->itype.compressed.block_size_bits = ffs( | 1301 | ni->itype.compressed.block_size_bits = ffs( |
1304 | ni->itype.compressed.block_size) - 1; | 1302 | ni->itype.compressed.block_size) - 1; |
1305 | } | 1303 | } |
1306 | if (ctx->attr->flags & ATTR_IS_ENCRYPTED) { | 1304 | if (a->flags & ATTR_IS_ENCRYPTED) { |
1307 | if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { | 1305 | if (a->flags & ATTR_COMPRESSION_MASK) { |
1308 | ntfs_error(vi->i_sb, "Found encrypted " | 1306 | ntfs_error(vi->i_sb, "Found encrypted and " |
1309 | "and compressed data."); | 1307 | "compressed data."); |
1310 | goto unm_err_out; | 1308 | goto unm_err_out; |
1311 | } | 1309 | } |
1312 | if (NInoMstProtected(ni)) { | 1310 | if (NInoMstProtected(ni)) { |
@@ -1320,7 +1318,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1320 | } | 1318 | } |
1321 | NInoSetEncrypted(ni); | 1319 | NInoSetEncrypted(ni); |
1322 | } | 1320 | } |
1323 | if (ctx->attr->flags & ATTR_IS_SPARSE) { | 1321 | if (a->flags & ATTR_IS_SPARSE) { |
1324 | if (NInoMstProtected(ni)) { | 1322 | if (NInoMstProtected(ni)) { |
1325 | ntfs_error(vi->i_sb, "Found mst protected " | 1323 | ntfs_error(vi->i_sb, "Found mst protected " |
1326 | "attribute but the attribute " | 1324 | "attribute but the attribute " |
@@ -1332,23 +1330,20 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1332 | } | 1330 | } |
1333 | NInoSetSparse(ni); | 1331 | NInoSetSparse(ni); |
1334 | } | 1332 | } |
1335 | if (ctx->attr->data.non_resident.lowest_vcn) { | 1333 | if (a->data.non_resident.lowest_vcn) { |
1336 | ntfs_error(vi->i_sb, "First extent of attribute has " | 1334 | ntfs_error(vi->i_sb, "First extent of attribute has " |
1337 | "non-zero lowest_vcn."); | 1335 | "non-zero lowest_vcn."); |
1338 | goto unm_err_out; | 1336 | goto unm_err_out; |
1339 | } | 1337 | } |
1340 | /* Setup all the sizes. */ | 1338 | /* Setup all the sizes. */ |
1341 | vi->i_size = sle64_to_cpu( | 1339 | vi->i_size = sle64_to_cpu(a->data.non_resident.data_size); |
1342 | ctx->attr->data.non_resident.data_size); | ||
1343 | ni->initialized_size = sle64_to_cpu( | 1340 | ni->initialized_size = sle64_to_cpu( |
1344 | ctx->attr->data.non_resident.initialized_size); | 1341 | a->data.non_resident.initialized_size); |
1345 | ni->allocated_size = sle64_to_cpu( | 1342 | ni->allocated_size = sle64_to_cpu( |
1346 | ctx->attr->data.non_resident.allocated_size); | 1343 | a->data.non_resident.allocated_size); |
1347 | if (NInoCompressed(ni)) { | 1344 | if (NInoCompressed(ni)) |
1348 | ni->itype.compressed.size = sle64_to_cpu( | 1345 | ni->itype.compressed.size = sle64_to_cpu( |
1349 | ctx->attr->data.non_resident. | 1346 | a->data.non_resident.compressed_size); |
1350 | compressed_size); | ||
1351 | } | ||
1352 | } | 1347 | } |
1353 | 1348 | ||
1354 | /* Setup the operations for this attribute inode. */ | 1349 | /* Setup the operations for this attribute inode. */ |
@@ -1437,6 +1432,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) | |||
1437 | ntfs_inode *ni, *base_ni, *bni; | 1432 | ntfs_inode *ni, *base_ni, *bni; |
1438 | struct inode *bvi; | 1433 | struct inode *bvi; |
1439 | MFT_RECORD *m; | 1434 | MFT_RECORD *m; |
1435 | ATTR_RECORD *a; | ||
1440 | ntfs_attr_search_ctx *ctx; | 1436 | ntfs_attr_search_ctx *ctx; |
1441 | INDEX_ROOT *ir; | 1437 | INDEX_ROOT *ir; |
1442 | u8 *ir_end, *index_end; | 1438 | u8 *ir_end, *index_end; |
@@ -1478,30 +1474,28 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) | |||
1478 | "missing."); | 1474 | "missing."); |
1479 | goto unm_err_out; | 1475 | goto unm_err_out; |
1480 | } | 1476 | } |
1477 | a = ctx->attr; | ||
1481 | /* Set up the state. */ | 1478 | /* Set up the state. */ |
1482 | if (unlikely(ctx->attr->non_resident)) { | 1479 | if (unlikely(a->non_resident)) { |
1483 | ntfs_error(vol->sb, "$INDEX_ROOT attribute is not resident."); | 1480 | ntfs_error(vol->sb, "$INDEX_ROOT attribute is not resident."); |
1484 | goto unm_err_out; | 1481 | goto unm_err_out; |
1485 | } | 1482 | } |
1486 | /* Ensure the attribute name is placed before the value. */ | 1483 | /* Ensure the attribute name is placed before the value. */ |
1487 | if (unlikely(ctx->attr->name_length && | 1484 | if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= |
1488 | (le16_to_cpu(ctx->attr->name_offset) >= | 1485 | le16_to_cpu(a->data.resident.value_offset)))) { |
1489 | le16_to_cpu(ctx->attr->data.resident. | ||
1490 | value_offset)))) { | ||
1491 | ntfs_error(vol->sb, "$INDEX_ROOT attribute name is placed " | 1486 | ntfs_error(vol->sb, "$INDEX_ROOT attribute name is placed " |
1492 | "after the attribute value."); | 1487 | "after the attribute value."); |
1493 | goto unm_err_out; | 1488 | goto unm_err_out; |
1494 | } | 1489 | } |
1495 | /* Compressed/encrypted/sparse index root is not allowed. */ | 1490 | /* Compressed/encrypted/sparse index root is not allowed. */ |
1496 | if (ctx->attr->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED | | 1491 | if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED | |
1497 | ATTR_IS_SPARSE)) { | 1492 | ATTR_IS_SPARSE)) { |
1498 | ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index " | 1493 | ntfs_error(vi->i_sb, "Found compressed/encrypted/sparse index " |
1499 | "root attribute."); | 1494 | "root attribute."); |
1500 | goto unm_err_out; | 1495 | goto unm_err_out; |
1501 | } | 1496 | } |
1502 | ir = (INDEX_ROOT*)((u8*)ctx->attr + | 1497 | ir = (INDEX_ROOT*)((u8*)a + le16_to_cpu(a->data.resident.value_offset)); |
1503 | le16_to_cpu(ctx->attr->data.resident.value_offset)); | 1498 | ir_end = (u8*)ir + le32_to_cpu(a->data.resident.value_length); |
1504 | ir_end = (u8*)ir + le32_to_cpu(ctx->attr->data.resident.value_length); | ||
1505 | if (ir_end > (u8*)ctx->mrec + vol->mft_record_size) { | 1499 | if (ir_end > (u8*)ctx->mrec + vol->mft_record_size) { |
1506 | ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is corrupt."); | 1500 | ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is corrupt."); |
1507 | goto unm_err_out; | 1501 | goto unm_err_out; |
@@ -1574,7 +1568,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) | |||
1574 | "$INDEX_ALLOCATION attribute."); | 1568 | "$INDEX_ALLOCATION attribute."); |
1575 | goto unm_err_out; | 1569 | goto unm_err_out; |
1576 | } | 1570 | } |
1577 | if (!ctx->attr->non_resident) { | 1571 | if (!a->non_resident) { |
1578 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " | 1572 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " |
1579 | "resident."); | 1573 | "resident."); |
1580 | goto unm_err_out; | 1574 | goto unm_err_out; |
@@ -1582,37 +1576,36 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) | |||
1582 | /* | 1576 | /* |
1583 | * Ensure the attribute name is placed before the mapping pairs array. | 1577 | * Ensure the attribute name is placed before the mapping pairs array. |
1584 | */ | 1578 | */ |
1585 | if (unlikely(ctx->attr->name_length && (le16_to_cpu( | 1579 | if (unlikely(a->name_length && (le16_to_cpu(a->name_offset) >= |
1586 | ctx->attr->name_offset) >= le16_to_cpu( | 1580 | le16_to_cpu( |
1587 | ctx->attr->data.non_resident.mapping_pairs_offset)))) { | 1581 | a->data.non_resident.mapping_pairs_offset)))) { |
1588 | ntfs_error(vol->sb, "$INDEX_ALLOCATION attribute name is " | 1582 | ntfs_error(vol->sb, "$INDEX_ALLOCATION attribute name is " |
1589 | "placed after the mapping pairs array."); | 1583 | "placed after the mapping pairs array."); |
1590 | goto unm_err_out; | 1584 | goto unm_err_out; |
1591 | } | 1585 | } |
1592 | if (ctx->attr->flags & ATTR_IS_ENCRYPTED) { | 1586 | if (a->flags & ATTR_IS_ENCRYPTED) { |
1593 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " | 1587 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " |
1594 | "encrypted."); | 1588 | "encrypted."); |
1595 | goto unm_err_out; | 1589 | goto unm_err_out; |
1596 | } | 1590 | } |
1597 | if (ctx->attr->flags & ATTR_IS_SPARSE) { | 1591 | if (a->flags & ATTR_IS_SPARSE) { |
1598 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is sparse."); | 1592 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is sparse."); |
1599 | goto unm_err_out; | 1593 | goto unm_err_out; |
1600 | } | 1594 | } |
1601 | if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { | 1595 | if (a->flags & ATTR_COMPRESSION_MASK) { |
1602 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " | 1596 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " |
1603 | "compressed."); | 1597 | "compressed."); |
1604 | goto unm_err_out; | 1598 | goto unm_err_out; |
1605 | } | 1599 | } |
1606 | if (ctx->attr->data.non_resident.lowest_vcn) { | 1600 | if (a->data.non_resident.lowest_vcn) { |
1607 | ntfs_error(vi->i_sb, "First extent of $INDEX_ALLOCATION " | 1601 | ntfs_error(vi->i_sb, "First extent of $INDEX_ALLOCATION " |
1608 | "attribute has non zero lowest_vcn."); | 1602 | "attribute has non zero lowest_vcn."); |
1609 | goto unm_err_out; | 1603 | goto unm_err_out; |
1610 | } | 1604 | } |
1611 | vi->i_size = sle64_to_cpu(ctx->attr->data.non_resident.data_size); | 1605 | vi->i_size = sle64_to_cpu(a->data.non_resident.data_size); |
1612 | ni->initialized_size = sle64_to_cpu( | 1606 | ni->initialized_size = sle64_to_cpu( |
1613 | ctx->attr->data.non_resident.initialized_size); | 1607 | a->data.non_resident.initialized_size); |
1614 | ni->allocated_size = sle64_to_cpu( | 1608 | ni->allocated_size = sle64_to_cpu(a->data.non_resident.allocated_size); |
1615 | ctx->attr->data.non_resident.allocated_size); | ||
1616 | /* | 1609 | /* |
1617 | * We are done with the mft record, so we release it. Otherwise | 1610 | * We are done with the mft record, so we release it. Otherwise |
1618 | * we would deadlock in ntfs_attr_iget(). | 1611 | * we would deadlock in ntfs_attr_iget(). |
@@ -1716,7 +1709,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1716 | struct buffer_head *bh; | 1709 | struct buffer_head *bh; |
1717 | ntfs_inode *ni; | 1710 | ntfs_inode *ni; |
1718 | MFT_RECORD *m = NULL; | 1711 | MFT_RECORD *m = NULL; |
1719 | ATTR_RECORD *attr; | 1712 | ATTR_RECORD *a; |
1720 | ntfs_attr_search_ctx *ctx; | 1713 | ntfs_attr_search_ctx *ctx; |
1721 | unsigned int i, nr_blocks; | 1714 | unsigned int i, nr_blocks; |
1722 | int err; | 1715 | int err; |
@@ -1813,9 +1806,10 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1813 | 1806 | ||
1814 | ntfs_debug("Attribute list attribute found in $MFT."); | 1807 | ntfs_debug("Attribute list attribute found in $MFT."); |
1815 | NInoSetAttrList(ni); | 1808 | NInoSetAttrList(ni); |
1816 | if (ctx->attr->flags & ATTR_IS_ENCRYPTED || | 1809 | a = ctx->attr; |
1817 | ctx->attr->flags & ATTR_COMPRESSION_MASK || | 1810 | if (a->flags & ATTR_IS_ENCRYPTED || |
1818 | ctx->attr->flags & ATTR_IS_SPARSE) { | 1811 | a->flags & ATTR_COMPRESSION_MASK || |
1812 | a->flags & ATTR_IS_SPARSE) { | ||
1819 | ntfs_error(sb, "Attribute list attribute is " | 1813 | ntfs_error(sb, "Attribute list attribute is " |
1820 | "compressed/encrypted/sparse. Not " | 1814 | "compressed/encrypted/sparse. Not " |
1821 | "allowed. $MFT is corrupt. You should " | 1815 | "allowed. $MFT is corrupt. You should " |
@@ -1823,16 +1817,16 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1823 | goto put_err_out; | 1817 | goto put_err_out; |
1824 | } | 1818 | } |
1825 | /* Now allocate memory for the attribute list. */ | 1819 | /* Now allocate memory for the attribute list. */ |
1826 | ni->attr_list_size = (u32)ntfs_attr_size(ctx->attr); | 1820 | ni->attr_list_size = (u32)ntfs_attr_size(a); |
1827 | ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size); | 1821 | ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size); |
1828 | if (!ni->attr_list) { | 1822 | if (!ni->attr_list) { |
1829 | ntfs_error(sb, "Not enough memory to allocate buffer " | 1823 | ntfs_error(sb, "Not enough memory to allocate buffer " |
1830 | "for attribute list."); | 1824 | "for attribute list."); |
1831 | goto put_err_out; | 1825 | goto put_err_out; |
1832 | } | 1826 | } |
1833 | if (ctx->attr->non_resident) { | 1827 | if (a->non_resident) { |
1834 | NInoSetAttrListNonResident(ni); | 1828 | NInoSetAttrListNonResident(ni); |
1835 | if (ctx->attr->data.non_resident.lowest_vcn) { | 1829 | if (a->data.non_resident.lowest_vcn) { |
1836 | ntfs_error(sb, "Attribute list has non zero " | 1830 | ntfs_error(sb, "Attribute list has non zero " |
1837 | "lowest_vcn. $MFT is corrupt. " | 1831 | "lowest_vcn. $MFT is corrupt. " |
1838 | "You should run chkdsk."); | 1832 | "You should run chkdsk."); |
@@ -1840,7 +1834,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1840 | } | 1834 | } |
1841 | /* Setup the runlist. */ | 1835 | /* Setup the runlist. */ |
1842 | ni->attr_list_rl.rl = ntfs_mapping_pairs_decompress(vol, | 1836 | ni->attr_list_rl.rl = ntfs_mapping_pairs_decompress(vol, |
1843 | ctx->attr, NULL); | 1837 | a, NULL); |
1844 | if (IS_ERR(ni->attr_list_rl.rl)) { | 1838 | if (IS_ERR(ni->attr_list_rl.rl)) { |
1845 | err = PTR_ERR(ni->attr_list_rl.rl); | 1839 | err = PTR_ERR(ni->attr_list_rl.rl); |
1846 | ni->attr_list_rl.rl = NULL; | 1840 | ni->attr_list_rl.rl = NULL; |
@@ -1852,7 +1846,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1852 | /* Now load the attribute list. */ | 1846 | /* Now load the attribute list. */ |
1853 | if ((err = load_attribute_list(vol, &ni->attr_list_rl, | 1847 | if ((err = load_attribute_list(vol, &ni->attr_list_rl, |
1854 | ni->attr_list, ni->attr_list_size, | 1848 | ni->attr_list, ni->attr_list_size, |
1855 | sle64_to_cpu(ctx->attr->data. | 1849 | sle64_to_cpu(a->data. |
1856 | non_resident.initialized_size)))) { | 1850 | non_resident.initialized_size)))) { |
1857 | ntfs_error(sb, "Failed to load attribute list " | 1851 | ntfs_error(sb, "Failed to load attribute list " |
1858 | "attribute with error code %i.", | 1852 | "attribute with error code %i.", |
@@ -1860,20 +1854,20 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1860 | goto put_err_out; | 1854 | goto put_err_out; |
1861 | } | 1855 | } |
1862 | } else /* if (!ctx.attr->non_resident) */ { | 1856 | } else /* if (!ctx.attr->non_resident) */ { |
1863 | if ((u8*)ctx->attr + le16_to_cpu( | 1857 | if ((u8*)a + le16_to_cpu( |
1864 | ctx->attr->data.resident.value_offset) + | 1858 | a->data.resident.value_offset) + |
1865 | le32_to_cpu( | 1859 | le32_to_cpu( |
1866 | ctx->attr->data.resident.value_length) > | 1860 | a->data.resident.value_length) > |
1867 | (u8*)ctx->mrec + vol->mft_record_size) { | 1861 | (u8*)ctx->mrec + vol->mft_record_size) { |
1868 | ntfs_error(sb, "Corrupt attribute list " | 1862 | ntfs_error(sb, "Corrupt attribute list " |
1869 | "attribute."); | 1863 | "attribute."); |
1870 | goto put_err_out; | 1864 | goto put_err_out; |
1871 | } | 1865 | } |
1872 | /* Now copy the attribute list. */ | 1866 | /* Now copy the attribute list. */ |
1873 | memcpy(ni->attr_list, (u8*)ctx->attr + le16_to_cpu( | 1867 | memcpy(ni->attr_list, (u8*)a + le16_to_cpu( |
1874 | ctx->attr->data.resident.value_offset), | 1868 | a->data.resident.value_offset), |
1875 | le32_to_cpu( | 1869 | le32_to_cpu( |
1876 | ctx->attr->data.resident.value_length)); | 1870 | a->data.resident.value_length)); |
1877 | } | 1871 | } |
1878 | /* The attribute list is now setup in memory. */ | 1872 | /* The attribute list is now setup in memory. */ |
1879 | /* | 1873 | /* |
@@ -1939,25 +1933,25 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1939 | ntfs_attr_reinit_search_ctx(ctx); | 1933 | ntfs_attr_reinit_search_ctx(ctx); |
1940 | 1934 | ||
1941 | /* Now load all attribute extents. */ | 1935 | /* Now load all attribute extents. */ |
1942 | attr = NULL; | 1936 | a = NULL; |
1943 | next_vcn = last_vcn = highest_vcn = 0; | 1937 | next_vcn = last_vcn = highest_vcn = 0; |
1944 | while (!(err = ntfs_attr_lookup(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0, | 1938 | while (!(err = ntfs_attr_lookup(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0, |
1945 | ctx))) { | 1939 | ctx))) { |
1946 | runlist_element *nrl; | 1940 | runlist_element *nrl; |
1947 | 1941 | ||
1948 | /* Cache the current attribute. */ | 1942 | /* Cache the current attribute. */ |
1949 | attr = ctx->attr; | 1943 | a = ctx->attr; |
1950 | /* $MFT must be non-resident. */ | 1944 | /* $MFT must be non-resident. */ |
1951 | if (!attr->non_resident) { | 1945 | if (!a->non_resident) { |
1952 | ntfs_error(sb, "$MFT must be non-resident but a " | 1946 | ntfs_error(sb, "$MFT must be non-resident but a " |
1953 | "resident extent was found. $MFT is " | 1947 | "resident extent was found. $MFT is " |
1954 | "corrupt. Run chkdsk."); | 1948 | "corrupt. Run chkdsk."); |
1955 | goto put_err_out; | 1949 | goto put_err_out; |
1956 | } | 1950 | } |
1957 | /* $MFT must be uncompressed and unencrypted. */ | 1951 | /* $MFT must be uncompressed and unencrypted. */ |
1958 | if (attr->flags & ATTR_COMPRESSION_MASK || | 1952 | if (a->flags & ATTR_COMPRESSION_MASK || |
1959 | attr->flags & ATTR_IS_ENCRYPTED || | 1953 | a->flags & ATTR_IS_ENCRYPTED || |
1960 | attr->flags & ATTR_IS_SPARSE) { | 1954 | a->flags & ATTR_IS_SPARSE) { |
1961 | ntfs_error(sb, "$MFT must be uncompressed, " | 1955 | ntfs_error(sb, "$MFT must be uncompressed, " |
1962 | "non-sparse, and unencrypted but a " | 1956 | "non-sparse, and unencrypted but a " |
1963 | "compressed/sparse/encrypted extent " | 1957 | "compressed/sparse/encrypted extent " |
@@ -1971,7 +1965,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1971 | * as we have exclusive access to the inode at this time and we | 1965 | * as we have exclusive access to the inode at this time and we |
1972 | * are a mount in progress task, too. | 1966 | * are a mount in progress task, too. |
1973 | */ | 1967 | */ |
1974 | nrl = ntfs_mapping_pairs_decompress(vol, attr, ni->runlist.rl); | 1968 | nrl = ntfs_mapping_pairs_decompress(vol, a, ni->runlist.rl); |
1975 | if (IS_ERR(nrl)) { | 1969 | if (IS_ERR(nrl)) { |
1976 | ntfs_error(sb, "ntfs_mapping_pairs_decompress() " | 1970 | ntfs_error(sb, "ntfs_mapping_pairs_decompress() " |
1977 | "failed with error code %ld. $MFT is " | 1971 | "failed with error code %ld. $MFT is " |
@@ -1982,7 +1976,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1982 | 1976 | ||
1983 | /* Are we in the first extent? */ | 1977 | /* Are we in the first extent? */ |
1984 | if (!next_vcn) { | 1978 | if (!next_vcn) { |
1985 | if (attr->data.non_resident.lowest_vcn) { | 1979 | if (a->data.non_resident.lowest_vcn) { |
1986 | ntfs_error(sb, "First extent of $DATA " | 1980 | ntfs_error(sb, "First extent of $DATA " |
1987 | "attribute has non zero " | 1981 | "attribute has non zero " |
1988 | "lowest_vcn. $MFT is corrupt. " | 1982 | "lowest_vcn. $MFT is corrupt. " |
@@ -1991,15 +1985,15 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1991 | } | 1985 | } |
1992 | /* Get the last vcn in the $DATA attribute. */ | 1986 | /* Get the last vcn in the $DATA attribute. */ |
1993 | last_vcn = sle64_to_cpu( | 1987 | last_vcn = sle64_to_cpu( |
1994 | attr->data.non_resident.allocated_size) | 1988 | a->data.non_resident.allocated_size) |
1995 | >> vol->cluster_size_bits; | 1989 | >> vol->cluster_size_bits; |
1996 | /* Fill in the inode size. */ | 1990 | /* Fill in the inode size. */ |
1997 | vi->i_size = sle64_to_cpu( | 1991 | vi->i_size = sle64_to_cpu( |
1998 | attr->data.non_resident.data_size); | 1992 | a->data.non_resident.data_size); |
1999 | ni->initialized_size = sle64_to_cpu(attr->data. | 1993 | ni->initialized_size = sle64_to_cpu( |
2000 | non_resident.initialized_size); | 1994 | a->data.non_resident.initialized_size); |
2001 | ni->allocated_size = sle64_to_cpu( | 1995 | ni->allocated_size = sle64_to_cpu( |
2002 | attr->data.non_resident.allocated_size); | 1996 | a->data.non_resident.allocated_size); |
2003 | /* | 1997 | /* |
2004 | * Verify the number of mft records does not exceed | 1998 | * Verify the number of mft records does not exceed |
2005 | * 2^32 - 1. | 1999 | * 2^32 - 1. |
@@ -2056,7 +2050,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
2056 | } | 2050 | } |
2057 | 2051 | ||
2058 | /* Get the lowest vcn for the next extent. */ | 2052 | /* Get the lowest vcn for the next extent. */ |
2059 | highest_vcn = sle64_to_cpu(attr->data.non_resident.highest_vcn); | 2053 | highest_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn); |
2060 | next_vcn = highest_vcn + 1; | 2054 | next_vcn = highest_vcn + 1; |
2061 | 2055 | ||
2062 | /* Only one extent or error, which we catch below. */ | 2056 | /* Only one extent or error, which we catch below. */ |
@@ -2065,7 +2059,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
2065 | 2059 | ||
2066 | /* Avoid endless loops due to corruption. */ | 2060 | /* Avoid endless loops due to corruption. */ |
2067 | if (next_vcn < sle64_to_cpu( | 2061 | if (next_vcn < sle64_to_cpu( |
2068 | attr->data.non_resident.lowest_vcn)) { | 2062 | a->data.non_resident.lowest_vcn)) { |
2069 | ntfs_error(sb, "$MFT has corrupt attribute list " | 2063 | ntfs_error(sb, "$MFT has corrupt attribute list " |
2070 | "attribute. Run chkdsk."); | 2064 | "attribute. Run chkdsk."); |
2071 | goto put_err_out; | 2065 | goto put_err_out; |
@@ -2076,7 +2070,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
2076 | "$MFT is corrupt. Run chkdsk."); | 2070 | "$MFT is corrupt. Run chkdsk."); |
2077 | goto put_err_out; | 2071 | goto put_err_out; |
2078 | } | 2072 | } |
2079 | if (!attr) { | 2073 | if (!a) { |
2080 | ntfs_error(sb, "$MFT/$DATA attribute not found. $MFT is " | 2074 | ntfs_error(sb, "$MFT/$DATA attribute not found. $MFT is " |
2081 | "corrupt. Run chkdsk."); | 2075 | "corrupt. Run chkdsk."); |
2082 | goto put_err_out; | 2076 | goto put_err_out; |
@@ -2318,6 +2312,7 @@ int ntfs_truncate(struct inode *vi) | |||
2318 | ntfs_volume *vol = ni->vol; | 2312 | ntfs_volume *vol = ni->vol; |
2319 | ntfs_attr_search_ctx *ctx; | 2313 | ntfs_attr_search_ctx *ctx; |
2320 | MFT_RECORD *m; | 2314 | MFT_RECORD *m; |
2315 | ATTR_RECORD *a; | ||
2321 | const char *te = " Leaving file length out of sync with i_size."; | 2316 | const char *te = " Leaving file length out of sync with i_size."; |
2322 | int err; | 2317 | int err; |
2323 | 2318 | ||
@@ -2354,14 +2349,15 @@ int ntfs_truncate(struct inode *vi) | |||
2354 | vi->i_ino, err); | 2349 | vi->i_ino, err); |
2355 | goto err_out; | 2350 | goto err_out; |
2356 | } | 2351 | } |
2352 | a = ctx->attr; | ||
2357 | /* If the size has not changed there is nothing to do. */ | 2353 | /* If the size has not changed there is nothing to do. */ |
2358 | if (ntfs_attr_size(ctx->attr) == i_size_read(vi)) | 2354 | if (ntfs_attr_size(a) == i_size_read(vi)) |
2359 | goto done; | 2355 | goto done; |
2360 | // TODO: Implement the truncate... | 2356 | // TODO: Implement the truncate... |
2361 | ntfs_error(vi->i_sb, "Inode size has changed but this is not " | 2357 | ntfs_error(vi->i_sb, "Inode size has changed but this is not " |
2362 | "implemented yet. Resetting inode size to old value. " | 2358 | "implemented yet. Resetting inode size to old value. " |
2363 | " This is most likely a bug in the ntfs driver!"); | 2359 | " This is most likely a bug in the ntfs driver!"); |
2364 | i_size_write(vi, ntfs_attr_size(ctx->attr)); | 2360 | i_size_write(vi, ntfs_attr_size(a)); |
2365 | done: | 2361 | done: |
2366 | ntfs_attr_put_search_ctx(ctx); | 2362 | ntfs_attr_put_search_ctx(ctx); |
2367 | unmap_mft_record(ni); | 2363 | unmap_mft_record(ni); |