aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-05-01 08:50:38 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-05-01 08:50:38 -0400
commit8df9675f8b498d0bfa1f0b5b06f56bf1ff366dd5 (patch)
tree38fd56a82049f50b4d774af47b9d39f116071755 /fs/ext4/super.c
parent9ca92389c5312a51e819c15c762f0abdc7f3129b (diff)
ext4: Avoid races caused by on-line resizing and SMP memory reordering
Ext4's on-line resizing adds a new block group and then, only at the last step adjusts s_groups_count. However, it's possible on SMP systems that another CPU could see the updated the s_group_count and not see the newly initialized data structures for the just-added block group. For this reason, it's important to insert a SMP read barrier after reading s_groups_count and before reading any (for example) the new block group descriptors allowed by the increased value of s_groups_count. Unfortunately, we rather blatently violate this locking protocol documented in fs/ext4/resize.c. Fortunately, (1) on-line resizes happen relatively rarely, and (2) it seems rare that the filesystem code will immediately try to use just-added block group before any memory ordering issues resolve themselves. So apparently problems here are relatively hard to hit, since ext3 has been vulnerable to the same issue for years with no one apparently complaining. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c3
1 files changed, 1 insertions, 2 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 68c3a44c4a97..fcd7b24c6df3 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3557,9 +3557,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
3557 if (test_opt(sb, MINIX_DF)) { 3557 if (test_opt(sb, MINIX_DF)) {
3558 sbi->s_overhead_last = 0; 3558 sbi->s_overhead_last = 0;
3559 } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { 3559 } else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
3560 ext4_group_t ngroups = sbi->s_groups_count, i; 3560 ext4_group_t i, ngroups = ext4_get_groups_count(sb);
3561 ext4_fsblk_t overhead = 0; 3561 ext4_fsblk_t overhead = 0;
3562 smp_rmb();
3563 3562
3564 /* 3563 /*
3565 * Compute the overhead (FS structures). This is constant 3564 * Compute the overhead (FS structures). This is constant