From patchwork Mon Mar 3 14:00:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maurizio Lombardi X-Patchwork-Id: 325843 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 9E6002C014B for ; Tue, 4 Mar 2014 01:00:45 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754182AbaCCOAk (ORCPT ); Mon, 3 Mar 2014 09:00:40 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46374 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754008AbaCCOAi (ORCPT ); Mon, 3 Mar 2014 09:00:38 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s23E0Yan004221 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 3 Mar 2014 09:00:35 -0500 Received: from dhcp-27-189.brq.redhat.com (dhcp-1-153.brq.redhat.com [10.34.1.153]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id s23E0U1a022763; Mon, 3 Mar 2014 09:00:33 -0500 From: Maurizio Lombardi To: linux-ext4@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, tytso@mit.edu, adilger.kernel@dilger.ca Subject: [PATCH 2/2] ext4: fix bug in ext4_mb_normalize_request() Date: Mon, 3 Mar 2014 15:00:28 +0100 Message-Id: <1393855228-13592-3-git-send-email-mlombard@redhat.com> In-Reply-To: <1393855228-13592-1-git-send-email-mlombard@redhat.com> References: <1393855228-13592-1-git-send-email-mlombard@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org When normalizing the data requests, the number of blocks to allocate must not be higher than the number of blocks per group. The current implementation does not take care of that and it may hit a kernel panic if the number of blocks per group is very low. This patch fixes the bug by ensuring that the number of blocks to allocate is always less or equal to the number of blocks per group. How to reproduce the bug: #mkfs.ext4 -g 1024 /dev/sdX #mount /dev/sdX /mnt #dd if=/dev/zero of=/mnt/test bs=1M count=10 [ 147.779177] ------------[ cut here ]------------ [ 147.780015] kernel BUG at fs/ext4/mballoc.c:3145! [ 147.780015] invalid opcode: 0000 [#1] SMP [ 147.780015] Modules linked in: nfsd auth_rpcgss nfs_acl nfs lockd fscache sunrpc loop snd_pcm cirrus snd_timer ttm snd drm_kms_helper soundcore drm parport_pc parport i2c_piix4 pcspkr i2c_core xfs libcrc32c e1000 floppy [ 147.780015] CPU: 0 PID: 66 Comm: kworker/u8:3 Not tainted 3.14.0-rc4+ #12 [ 147.780015] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 147.780015] Workqueue: writeback bdi_writeback_workfn (flush-7:0) [ 147.780015] task: ffff88002ec16300 ti: ffff88002ed20000 task.ti: ffff88002ed20000 [ 147.780015] RIP: 0010:[] [] ext4_mb_normalize_request+0x60c/0x660 [ 147.780015] RSP: 0018:ffff88002ed21778 EFLAGS: 00010206 [ 147.780015] RAX: ffff88002e3bb000 RBX: 0000000000000800 RCX: 0000000000000006 [ 147.780015] RDX: 0000000000000800 RSI: 0000000000000046 RDI: ffff88002e3bb800 [ 147.780015] RBP: ffff88002ed217e8 R08: 000000000000000a R09: 00000000000003a2 [ 147.780015] R10: 0000000000000000 R11: 00000000000003a1 R12: ffff880000c17000 [ 147.780015] R13: 0000000000000000 R14: 0000000000000800 R15: ffff88003d1fc2f8 [ 147.780015] FS: 0000000000000000(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000 [ 147.780015] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 147.780015] CR2: ffffffffff600400 CR3: 000000001c218000 CR4: 00000000000006f0 [ 147.780015] Stack: [ 147.780015] 00000000014ca000 0000000000000800 ffff88002e3bb000 ffff88003d1fc0b0 [ 147.780015] ffff88002ed21980 0000080000000800 ffffffff812bd912 ffff88003d1fc2f8 [ 147.780015] ffff88002ed217f8 ffff88002ed21980 ffff88002e3bb000 ffff88002ed21970 [ 147.780015] Call Trace: [ 147.780015] [] ? ext4_mb_new_blocks+0x122/0x8d0 [ 147.780015] [] ext4_mb_new_blocks+0x3f3/0x8d0 [ 147.780015] [] ? free_hot_cold_page_list+0x4e/0xa0 [ 147.780015] [] ? __kmalloc+0x1ea/0x230 [ 147.780015] [] ? ext4_ext_find_extent+0x228/0x2b0 [ 147.780015] [] ? ext4_ext_find_extent+0x228/0x2b0 [ 147.780015] [] ext4_ext_map_blocks+0x611/0xfd0 [ 147.780015] [] ext4_map_blocks+0x2b5/0x4d0 [ 147.780015] [] ext4_writepages+0x621/0xd00 [ 147.780015] [] do_writepages+0x1e/0x40 [ 147.780015] [] __writeback_single_inode+0x40/0x200 [ 147.780015] [] writeback_sb_inodes+0x1c1/0x410 [ 147.780015] [] wb_writeback+0xf4/0x2c0 [ 147.780015] [] ? set_worker_desc+0x6f/0x80 [ 147.780015] [] bdi_writeback_workfn+0x118/0x440 [ 147.780015] [] process_one_work+0x17a/0x410 [ 147.780015] [] worker_thread+0x11c/0x370 [ 147.780015] [] ? manage_workers.isra.21+0x2b0/0x2b0 [ 147.780015] [] kthread+0xc9/0xe0 [ 147.780015] [] ? ftrace_raw_event_xen_mc_flush+0x50/0x180 [ 147.780015] [] ? flush_kthread_worker+0x80/0x80 [ 147.780015] [] ret_from_fork+0x7c/0xb0 [ 147.780015] [] ? flush_kthread_worker+0x80/0x80 [ 147.780015] Code: 1a a4 81 31 c0 e8 05 50 43 00 49 8b 44 24 08 8b 75 b8 48 c7 c7 c3 1a a4 81 48 8b 80 f8 02 00 00 48 8b 50 18 31 c0 e8 e4 4f 43 00 <0f> 0b 44 89 ee 48 c7 c7 b7 1a a4 81 31 c0 e8 d1 4f 43 00 49 8b [ 147.780015] RIP [] ext4_mb_normalize_request+0x60c/0x660 [ 147.780015] RSP [ 147.830356] ---[ end trace b82d39f39fe4e04a ]--- [ 147.831058] Kernel panic - not syncing: Fatal exception Signed-off-by: Maurizio Lombardi --- fs/ext4/mballoc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 08ddfda..546575a 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3059,6 +3059,21 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, size = ac->ac_o_ex.fe_len << bsbits; } size = size >> bsbits; + + /* In any case, the size cannot be greater than the number + * of maximum free blocks per group. + */ + if (size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)) { + int sz_log2; + + size = EXT4_BLOCKS_PER_GROUP(ac->ac_sb); + + /* Recalculate the start offset */ + sz_log2 = __fls(size << bsbits); + start_off = ((loff_t) ac->ac_o_ex.fe_logical >> + (sz_log2 - bsbits)) << sz_log2; + } + start = start_off >> bsbits; /* don't cover already allocated blocks in selected range */