From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756655AbbIUMTF (ORCPT ); Mon, 21 Sep 2015 08:19:05 -0400 Received: from mailout2.samsung.com ([203.254.224.25]:36726 "EHLO mailout2.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756132AbbIUMTC (ORCPT ); Mon, 21 Sep 2015 08:19:02 -0400 X-AuditID: cbfee61b-f79d56d0000048c5-66-55fff5a1eb41 From: Chao Yu To: Jaegeuk Kim Cc: linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org Subject: [PATCH] f2fs: fix to handle io error in ->direct_IO Date: Mon, 21 Sep 2015 20:17:52 +0800 Message-id: <005f01d0f467$a71626c0$f5427440$@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7bit X-Mailer: Microsoft Outlook 14.0 Thread-index: AdD0V8TfBOfovj6RTpu4Hd2XIIGLww== Content-language: zh-cn X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrDLMWRmVeSWpSXmKPExsVy+t9jQd2FX/+HGux9oWPxZP0sZotLi9wt Lu+aw+bA7LFpVSebx+4Fn5k8Pm+SC2CO4rJJSc3JLEst0rdL4MqY8eoxa8EtrYqPt1YwNjAu Ve5i5OSQEDCR+Hb7HjuELSZx4d56ti5GLg4hgVmMEjtvtTBCOK8YJV4sWMoEUsUmoCKxvOM/ mC0CZB9adBmsm1nAQ6Kx4zsriC0sYCPRuOEGWA2LgKrE1/UfmEFsXgFLiUNrn7BA2IISPybf Y4Ho1ZJYv/M4E4QtL7F5zVtmiIsUJHacfc0IsUtP4vPlLmaIGnGJjUdusUxgBDoTYdQsJKNm IRk1C0nLAkaWVYwSqQXJBcVJ6blGeanlesWJucWleel6yfm5mxjBYfxMegfj4V3uhxgFOBiV eHgdBP6HCrEmlhVX5h5ilOBgVhLh1ZkFFOJNSaysSi3Kjy8qzUktPsQozcGiJM4ru/JZqJBA emJJanZqakFqEUyWiYNTqoEx9L/RmtTNdxy22Whdfnm+ff2xN5kB02em19XMLZyyofT+bK86 20Wr7+mUWxmx3HguP//H7PseTe+nruRre79+zmLzSIXFx8S2ejzIuFFbwipSKtV1sfP7WQnt 1p11fsLas+skvkz4dPmb04HNurPcGlXe5VzKdkj14DmsaiKjnv1mzuow2Yl2SizFGYmGWsxF xYkAzpuFHF8CAAA= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Here is a oops reported as following message when testing generic/019 of xfstest: ------------[ cut here ]------------ kernel BUG at /home/yuchao/git/f2fs-dev/segment.c:882! invalid opcode: 0000 [#1] SMP Modules linked in: zram lz4_compress lz4_decompress f2fs(O) ip6table_filter ip6_tables ebtable_nat ebtables nf_conntrack_ipv4 nf_def CPU: 2 PID: 25441 Comm: fio Tainted: G O 4.3.0-rc1+ #6 Hardware name: Hewlett-Packard HP Z220 CMT Workstation/1790, BIOS K51 v01.61 05/16/2013 task: ffff8803f4e85580 ti: ffff8803fd61c000 task.ti: ffff8803fd61c000 RIP: 0010:[] [] new_curseg+0x321/0x330 [f2fs] RSP: 0018:ffff8803fd61f918 EFLAGS: 00010246 RAX: 00000000000007ed RBX: 0000000000000224 RCX: 000000000000001f RDX: 0000000000000800 RSI: ffffffffffffffff RDI: ffff8803f56f4300 RBP: ffff8803fd61f978 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000024 R11: ffff8800d23bbd78 R12: ffff8800d0ef0000 R13: 0000000000000224 R14: 0000000000000000 R15: 0000000000000001 FS: 00007f827ff85700(0000) GS:ffff88041ea80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffff600000 CR3: 00000003fef17000 CR4: 00000000001406e0 Stack: 000007ea00000002 0000000100000001 ffff8803f6456248 000007ed0000002b 0000000000000224 ffff880404d1aa20 ffff8803fd61f9c8 ffff8800d0ef0000 ffff8803f6456248 0000000000000001 00000000ffffffff ffffffffa078f358 Call Trace: [] allocate_segment_by_default+0x1a7/0x1f0 [f2fs] [] allocate_data_block+0x17c/0x360 [f2fs] [] __allocate_data_block+0x131/0x1d0 [f2fs] [] f2fs_direct_IO+0x4b5/0x580 [f2fs] [] generic_file_direct_write+0xae/0x160 [] __generic_file_write_iter+0xd5/0x1f0 [] generic_file_write_iter+0xf7/0x200 [] ? apparmor_file_permission+0x18/0x20 [] ? f2fs_fallocate+0x1190/0x1190 [f2fs] [] f2fs_file_write_iter+0x46/0x90 [f2fs] [] aio_run_iocb+0x1ee/0x290 [] ? mutex_lock+0x1e/0x50 [] ? aio_read_events+0x207/0x2b0 [] do_io_submit+0x373/0x630 [] ? SyS_io_getevents+0x56/0xb0 [] SyS_io_submit+0x10/0x20 [] entry_SYSCALL_64_fastpath+0x12/0x6a Code: 45 c8 48 8b 78 10 e8 9f 23 bf e0 41 8b 8c 24 cc 03 00 00 89 c7 31 d2 89 c6 89 d8 29 df f7 f1 29 d1 39 cf 0f 83 be fd ff ff eb RIP [] new_curseg+0x321/0x330 [f2fs] RSP ---[ end trace 2e577d7f711ddb86 ]--- The reason is that: in the test of generic/019, we will trigger a manmade IO error in block layer through debugfs, after that, prefree segment will no longer be freed, because we always skip doing gc or checkpoint when there occurs an IO error. Meanwhile fio with aio engine generated a large number of direct IOs, which continue allocating spaces in free segment until we run out of them, eventually, results in panic in new_curseg as no more free segment was found. So, this patch changes to return EIO in direct_IO for this condition. Signed-off-by: Chao Yu --- fs/f2fs/data.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 8b86d02..a0ea1f8 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -524,6 +524,9 @@ static void __allocate_data_blocks(struct inode *inode, loff_t offset, while (dn.ofs_in_node < end_offset && len) { block_t blkaddr; + if (unlikely(f2fs_cp_error(sbi))) + goto sync_out; + blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node); if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) { if (__allocate_data_block(&dn)) @@ -566,6 +569,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, { unsigned int maxblocks = map->m_len; struct dnode_of_data dn; + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); int mode = create ? ALLOC_NODE : LOOKUP_NODE_RA; pgoff_t pgofs, end_offset; int err = 0, ofs = 1; @@ -599,6 +603,10 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, if (dn.data_blkaddr == NEW_ADDR || dn.data_blkaddr == NULL_ADDR) { if (create) { + if (unlikely(f2fs_cp_error(sbi))) { + err = -EIO; + goto put_out; + } err = __allocate_data_block(&dn); if (err) goto put_out; @@ -652,6 +660,10 @@ get_next: if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR) { if (create) { + if (unlikely(f2fs_cp_error(sbi))) { + err = -EIO; + goto sync_out; + } err = __allocate_data_block(&dn); if (err) goto sync_out; @@ -1569,10 +1581,16 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter)); - if (iov_iter_rw(iter) == WRITE) + if (iov_iter_rw(iter) == WRITE) { __allocate_data_blocks(inode, offset, count); + if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) { + err = -EIO; + goto out; + } + } err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio); +out: if (err < 0 && iov_iter_rw(iter) == WRITE) f2fs_write_failed(mapping, offset + count); -- 2.5.2