aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/ialloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/ialloc.c')
-rw-r--r--fs/ext4/ialloc.c81
1 files changed, 62 insertions, 19 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 9f9acac6c43f..d48e8b14928c 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -70,24 +70,27 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
70 ext4_group_t block_group, 70 ext4_group_t block_group,
71 struct ext4_group_desc *gdp) 71 struct ext4_group_desc *gdp)
72{ 72{
73 struct ext4_sb_info *sbi = EXT4_SB(sb);
74
75 J_ASSERT_BH(bh, buffer_locked(bh)); 73 J_ASSERT_BH(bh, buffer_locked(bh));
76 74
77 /* If checksum is bad mark all blocks and inodes use to prevent 75 /* If checksum is bad mark all blocks and inodes use to prevent
78 * allocation, essentially implementing a per-group read-only flag. */ 76 * allocation, essentially implementing a per-group read-only flag. */
79 if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { 77 if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
80 ext4_error(sb, "Checksum bad for group %u", block_group); 78 ext4_error(sb, "Checksum bad for group %u", block_group);
81 ext4_free_group_clusters_set(sb, gdp, 0); 79 ext4_free_group_clusters_set(sb, gdp, 0);
82 ext4_free_inodes_set(sb, gdp, 0); 80 ext4_free_inodes_set(sb, gdp, 0);
83 ext4_itable_unused_set(sb, gdp, 0); 81 ext4_itable_unused_set(sb, gdp, 0);
84 memset(bh->b_data, 0xff, sb->s_blocksize); 82 memset(bh->b_data, 0xff, sb->s_blocksize);
83 ext4_inode_bitmap_csum_set(sb, block_group, gdp, bh,
84 EXT4_INODES_PER_GROUP(sb) / 8);
85 return 0; 85 return 0;
86 } 86 }
87 87
88 memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); 88 memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
89 ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, 89 ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
90 bh->b_data); 90 bh->b_data);
91 ext4_inode_bitmap_csum_set(sb, block_group, gdp, bh,
92 EXT4_INODES_PER_GROUP(sb) / 8);
93 ext4_group_desc_csum_set(sb, block_group, gdp);
91 94
92 return EXT4_INODES_PER_GROUP(sb); 95 return EXT4_INODES_PER_GROUP(sb);
93} 96}
@@ -128,12 +131,12 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
128 return NULL; 131 return NULL;
129 } 132 }
130 if (bitmap_uptodate(bh)) 133 if (bitmap_uptodate(bh))
131 return bh; 134 goto verify;
132 135
133 lock_buffer(bh); 136 lock_buffer(bh);
134 if (bitmap_uptodate(bh)) { 137 if (bitmap_uptodate(bh)) {
135 unlock_buffer(bh); 138 unlock_buffer(bh);
136 return bh; 139 goto verify;
137 } 140 }
138 141
139 ext4_lock_group(sb, block_group); 142 ext4_lock_group(sb, block_group);
@@ -141,6 +144,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
141 ext4_init_inode_bitmap(sb, bh, block_group, desc); 144 ext4_init_inode_bitmap(sb, bh, block_group, desc);
142 set_bitmap_uptodate(bh); 145 set_bitmap_uptodate(bh);
143 set_buffer_uptodate(bh); 146 set_buffer_uptodate(bh);
147 set_buffer_verified(bh);
144 ext4_unlock_group(sb, block_group); 148 ext4_unlock_group(sb, block_group);
145 unlock_buffer(bh); 149 unlock_buffer(bh);
146 return bh; 150 return bh;
@@ -154,7 +158,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
154 */ 158 */
155 set_bitmap_uptodate(bh); 159 set_bitmap_uptodate(bh);
156 unlock_buffer(bh); 160 unlock_buffer(bh);
157 return bh; 161 goto verify;
158 } 162 }
159 /* 163 /*
160 * submit the buffer_head for reading 164 * submit the buffer_head for reading
@@ -171,6 +175,20 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
171 block_group, bitmap_blk); 175 block_group, bitmap_blk);
172 return NULL; 176 return NULL;
173 } 177 }
178
179verify:
180 ext4_lock_group(sb, block_group);
181 if (!buffer_verified(bh) &&
182 !ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh,
183 EXT4_INODES_PER_GROUP(sb) / 8)) {
184 ext4_unlock_group(sb, block_group);
185 put_bh(bh);
186 ext4_error(sb, "Corrupt inode bitmap - block_group = %u, "
187 "inode_bitmap = %llu", block_group, bitmap_blk);
188 return NULL;
189 }
190 ext4_unlock_group(sb, block_group);
191 set_buffer_verified(bh);
174 return bh; 192 return bh;
175} 193}
176 194
@@ -276,7 +294,9 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
276 ext4_used_dirs_set(sb, gdp, count); 294 ext4_used_dirs_set(sb, gdp, count);
277 percpu_counter_dec(&sbi->s_dirs_counter); 295 percpu_counter_dec(&sbi->s_dirs_counter);
278 } 296 }
279 gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp); 297 ext4_inode_bitmap_csum_set(sb, block_group, gdp, bitmap_bh,
298 EXT4_INODES_PER_GROUP(sb) / 8);
299 ext4_group_desc_csum_set(sb, block_group, gdp);
280 ext4_unlock_group(sb, block_group); 300 ext4_unlock_group(sb, block_group);
281 301
282 percpu_counter_inc(&sbi->s_freeinodes_counter); 302 percpu_counter_inc(&sbi->s_freeinodes_counter);
@@ -488,10 +508,12 @@ fallback_retry:
488 for (i = 0; i < ngroups; i++) { 508 for (i = 0; i < ngroups; i++) {
489 grp = (parent_group + i) % ngroups; 509 grp = (parent_group + i) % ngroups;
490 desc = ext4_get_group_desc(sb, grp, NULL); 510 desc = ext4_get_group_desc(sb, grp, NULL);
491 grp_free = ext4_free_inodes_count(sb, desc); 511 if (desc) {
492 if (desc && grp_free && grp_free >= avefreei) { 512 grp_free = ext4_free_inodes_count(sb, desc);
493 *group = grp; 513 if (grp_free && grp_free >= avefreei) {
494 return 0; 514 *group = grp;
515 return 0;
516 }
495 } 517 }
496 } 518 }
497 519
@@ -709,7 +731,7 @@ repeat_in_this_group:
709 731
710got: 732got:
711 /* We may have to initialize the block bitmap if it isn't already */ 733 /* We may have to initialize the block bitmap if it isn't already */
712 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && 734 if (ext4_has_group_desc_csum(sb) &&
713 gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { 735 gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
714 struct buffer_head *block_bitmap_bh; 736 struct buffer_head *block_bitmap_bh;
715 737
@@ -731,8 +753,11 @@ got:
731 gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); 753 gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
732 ext4_free_group_clusters_set(sb, gdp, 754 ext4_free_group_clusters_set(sb, gdp,
733 ext4_free_clusters_after_init(sb, group, gdp)); 755 ext4_free_clusters_after_init(sb, group, gdp));
734 gdp->bg_checksum = ext4_group_desc_csum(sbi, group, 756 ext4_block_bitmap_csum_set(sb, group, gdp,
735 gdp); 757 block_bitmap_bh,
758 EXT4_BLOCKS_PER_GROUP(sb) /
759 8);
760 ext4_group_desc_csum_set(sb, group, gdp);
736 } 761 }
737 ext4_unlock_group(sb, group); 762 ext4_unlock_group(sb, group);
738 763
@@ -751,7 +776,7 @@ got:
751 goto fail; 776 goto fail;
752 777
753 /* Update the relevant bg descriptor fields */ 778 /* Update the relevant bg descriptor fields */
754 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 779 if (ext4_has_group_desc_csum(sb)) {
755 int free; 780 int free;
756 struct ext4_group_info *grp = ext4_get_group_info(sb, group); 781 struct ext4_group_info *grp = ext4_get_group_info(sb, group);
757 782
@@ -772,7 +797,10 @@ got:
772 ext4_itable_unused_set(sb, gdp, 797 ext4_itable_unused_set(sb, gdp,
773 (EXT4_INODES_PER_GROUP(sb) - ino)); 798 (EXT4_INODES_PER_GROUP(sb) - ino));
774 up_read(&grp->alloc_sem); 799 up_read(&grp->alloc_sem);
800 } else {
801 ext4_lock_group(sb, group);
775 } 802 }
803
776 ext4_free_inodes_set(sb, gdp, ext4_free_inodes_count(sb, gdp) - 1); 804 ext4_free_inodes_set(sb, gdp, ext4_free_inodes_count(sb, gdp) - 1);
777 if (S_ISDIR(mode)) { 805 if (S_ISDIR(mode)) {
778 ext4_used_dirs_set(sb, gdp, ext4_used_dirs_count(sb, gdp) + 1); 806 ext4_used_dirs_set(sb, gdp, ext4_used_dirs_count(sb, gdp) + 1);
@@ -782,10 +810,12 @@ got:
782 atomic_inc(&sbi->s_flex_groups[f].used_dirs); 810 atomic_inc(&sbi->s_flex_groups[f].used_dirs);
783 } 811 }
784 } 812 }
785 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 813 if (ext4_has_group_desc_csum(sb)) {
786 gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); 814 ext4_inode_bitmap_csum_set(sb, group, gdp, inode_bitmap_bh,
787 ext4_unlock_group(sb, group); 815 EXT4_INODES_PER_GROUP(sb) / 8);
816 ext4_group_desc_csum_set(sb, group, gdp);
788 } 817 }
818 ext4_unlock_group(sb, group);
789 819
790 BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); 820 BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
791 err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); 821 err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
@@ -850,6 +880,19 @@ got:
850 inode->i_generation = sbi->s_next_generation++; 880 inode->i_generation = sbi->s_next_generation++;
851 spin_unlock(&sbi->s_next_gen_lock); 881 spin_unlock(&sbi->s_next_gen_lock);
852 882
883 /* Precompute checksum seed for inode metadata */
884 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
885 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
886 __u32 csum;
887 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
888 __le32 inum = cpu_to_le32(inode->i_ino);
889 __le32 gen = cpu_to_le32(inode->i_generation);
890 csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&inum,
891 sizeof(inum));
892 ei->i_csum_seed = ext4_chksum(sbi, csum, (__u8 *)&gen,
893 sizeof(gen));
894 }
895
853 ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */ 896 ext4_clear_state_flags(ei); /* Only relevant on 32-bit archs */
854 ext4_set_inode_state(inode, EXT4_STATE_NEW); 897 ext4_set_inode_state(inode, EXT4_STATE_NEW);
855 898
@@ -1140,7 +1183,7 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
1140skip_zeroout: 1183skip_zeroout:
1141 ext4_lock_group(sb, group); 1184 ext4_lock_group(sb, group);
1142 gdp->bg_flags |= cpu_to_le16(EXT4_BG_INODE_ZEROED); 1185 gdp->bg_flags |= cpu_to_le16(EXT4_BG_INODE_ZEROED);
1143 gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); 1186 ext4_group_desc_csum_set(sb, group, gdp);
1144 ext4_unlock_group(sb, group); 1187 ext4_unlock_group(sb, group);
1145 1188
1146 BUFFER_TRACE(group_desc_bh, 1189 BUFFER_TRACE(group_desc_bh,