--- linux-2.6.8.1-mm1/fs/ext3/balloc.c.=K0005=.orig +++ linux-2.6.8.1-mm1/fs/ext3/balloc.c @@ -250,7 +250,7 @@ static void rsv_window_remove(struct sup { rsv->rsv_start = 0; rsv->rsv_end = 0; - rsv->rsv_alloc_hit = 0; + atomic_set(&rsv->rsv_alloc_hit, 0); rb_erase(&rsv->rsv_node, &EXT3_SB(sb)->s_rsv_window_root); } @@ -856,7 +856,8 @@ static int alloc_new_reservation(struct if (my_rsv->rsv_end + 1 > start_block) start_block = my_rsv->rsv_end + 1; search_head = my_rsv; - if ((my_rsv->rsv_alloc_hit > (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) { + if ((atomic_read(&my_rsv->rsv_alloc_hit) > + (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) { /* * if we previously allocation hit ration is greater than half * we double the size of reservation window next time @@ -1035,27 +1036,39 @@ ext3_try_to_allocate_with_rsv(struct sup * then we could go to allocate from the reservation window directly. */ while (1) { - if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) || - !goal_in_my_reservation(&my_rsv->rsv_window, - goal, group, sb)) { + struct reserve_window rsv_copy; + unsigned int seq; + + do { + seq = read_seqbegin(&my_rsv->rsv_seqlock); + rsv_copy._rsv_start = my_rsv->rsv_start; + rsv_copy._rsv_end = my_rsv->rsv_end; + } while (read_seqretry(&my_rsv->rsv_seqlock, seq)); + + if (rsv_is_empty(&rsv_copy) || (ret < 0) || + !goal_in_my_reservation(&rsv_copy, goal, group, sb)) { spin_lock(rsv_lock); + write_seqlock(&my_rsv->rsv_seqlock); ret = alloc_new_reservation(my_rsv, goal, sb, group, bitmap_bh); + rsv_copy._rsv_start = my_rsv->rsv_start; + rsv_copy._rsv_end = my_rsv->rsv_end; + write_sequnlock(&my_rsv->rsv_seqlock); spin_unlock(rsv_lock); if (ret < 0) break; /* failed */ - if (!goal_in_my_reservation(&my_rsv->rsv_window, - goal, group, sb)) + if (!goal_in_my_reservation(&rsv_copy, goal, group, sb)) goal = -1; } - if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) - || (my_rsv->rsv_end < group_first_block)) + if ((rsv_copy._rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) + || (rsv_copy._rsv_end < group_first_block)) BUG(); ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, - &my_rsv->rsv_window); + &rsv_copy); if (ret >= 0) { - my_rsv->rsv_alloc_hit++; + if (!read_seqretry(&my_rsv->rsv_seqlock, seq)) + atomic_inc(&my_rsv->rsv_alloc_hit); break; /* succeed */ } } --- linux-2.6.8.1-mm1/fs/ext3/ialloc.c.=K0005=.orig +++ linux-2.6.8.1-mm1/fs/ext3/ialloc.c @@ -584,7 +584,7 @@ got: ei->i_rsv_window.rsv_start = 0; ei->i_rsv_window.rsv_end = 0; atomic_set(&ei->i_rsv_window.rsv_goal_size, EXT3_DEFAULT_RESERVE_BLOCKS); - ei->i_rsv_window.rsv_alloc_hit = 0; + atomic_set(&ei->i_rsv_window.rsv_alloc_hit, 0); ei->i_block_group = group; ext3_set_inode_flags(inode); --- linux-2.6.8.1-mm1/fs/ext3/super.c.=K0005=.orig +++ linux-2.6.8.1-mm1/fs/ext3/super.c @@ -1495,7 +1495,7 @@ static int ext3_fill_super (struct super * _much_ simpler. */ sbi->s_rsv_window_head.rsv_start = 0; sbi->s_rsv_window_head.rsv_end = 0; - sbi->s_rsv_window_head.rsv_alloc_hit = 0; + atomic_set(&sbi->s_rsv_window_head.rsv_alloc_hit, 0); atomic_set(&sbi->s_rsv_window_head.rsv_goal_size, 0); rsv_window_add(sb, &sbi->s_rsv_window_head); --- linux-2.6.8.1-mm1/include/linux/ext3_fs_i.h.=K0005=.orig +++ linux-2.6.8.1-mm1/include/linux/ext3_fs_i.h @@ -18,6 +18,7 @@ #include #include +#include struct reserve_window { __u32 _rsv_start; /* First byte reserved */ @@ -27,7 +28,8 @@ struct reserve_window { struct reserve_window_node { struct rb_node rsv_node; atomic_t rsv_goal_size; - __u32 rsv_alloc_hit; + atomic_t rsv_alloc_hit; + seqlock_t rsv_seqlock; struct reserve_window rsv_window; };