| From gnehzuil.liu@gmail.com Thu Nov 3 10:42:14 2011 |
| From: Zheng Liu <gnehzuil.liu@gmail.com> |
| Date: Fri, 28 Oct 2011 20:34:02 +0800 |
| Subject: ext4: fix BUG_ON() in ext4_ext_insert_extent() |
| To: Greg KH <greg@kroah.com> |
| Cc: Ted Ts'o <tytso@mit.edu>, Tao Ma <tm@tao.ma>, linux-ext4@vger.kernel.org, Xiaoyun Mao <xiaoyun.maoxy@aliyun-inc.com>, Yingbin Wang <yingbin.wangyb@aliyun-inc.com>, Jia Wan <jia.wanj@aliyun-inc.com> |
| Message-ID: <20111028123402.GA26003@gmail.com> |
| |
| |
| From: Zheng Liu <wenqing.lz@taobao.com> |
| |
| Does not corrispond with a direct commit in Linus's tree as it was fixed |
| differently in the 3.0 release. |
| |
| |
| We will meet with a BUG_ON() if following script is run. |
| |
| mkfs.ext4 -b 4096 /dev/sdb1 1000000 |
| mount -t ext4 /dev/sdb1 /mnt/sdb1 |
| fallocate -l 100M /mnt/sdb1/test |
| sync |
| for((i=0;i<170;i++)) |
| do |
| dd if=/dev/zero of=/mnt/sdb1/test conv=notrunc bs=256k count=1 |
| seek=`expr $i \* 2` |
| done |
| umount /mnt/sdb1 |
| mount -t ext4 /dev/sdb1 /mnt/sdb1 |
| dd if=/dev/zero of=/mnt/sdb1/test conv=notrunc bs=256k count=1 seek=341 |
| umount /mnt/sdb1 |
| mount /dev/sdb1 /mnt/sdb1 |
| dd if=/dev/zero of=/mnt/sdb1/test conv=notrunc bs=256k count=1 seek=340 |
| sync |
| |
| The reason is that it forgot to mark dirty when splitting two extents in |
| ext4_ext_convert_to_initialized(). Althrough ex has been updated in |
| memory, it is not dirtied both in ext4_ext_convert_to_initialized() and |
| ext4_ext_insert_extent(). The disk layout is corrupted. Then it will |
| meet with a BUG_ON() when writting at the start of that extent again. |
| |
| Cc: "Theodore Ts'o" <tytso@mit.edu> |
| Cc: Xiaoyun Mao <xiaoyun.maoxy@aliyun-inc.com> |
| Cc: Yingbin Wang <yingbin.wangyb@aliyun-inc.com> |
| Cc: Jia Wan <jia.wanj@aliyun-inc.com> |
| Signed-off-by: Zheng Liu <wenqing.lz@taobao.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/ext4/extents.c | 1 + |
| 1 file changed, 1 insertion(+) |
| |
| --- a/fs/ext4/extents.c |
| +++ b/fs/ext4/extents.c |
| @@ -2592,6 +2592,7 @@ static int ext4_ext_convert_to_initializ |
| ex1 = ex; |
| ex1->ee_len = cpu_to_le16(iblock - ee_block); |
| ext4_ext_mark_uninitialized(ex1); |
| + ext4_ext_dirty(handle, inode, path + depth); |
| ex2 = &newex; |
| } |
| /* |