Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752340AbbHEJYz (ORCPT ); Wed, 5 Aug 2015 05:24:55 -0400 Received: from mailout2.samsung.com ([203.254.224.25]:58773 "EHLO mailout2.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751539AbbHEJYg (ORCPT ); Wed, 5 Aug 2015 05:24:36 -0400 X-AuditID: cbfee61b-f79706d000001b96-d2-55c1d6520316 From: Chao Yu To: Jaegeuk Kim Cc: linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org Subject: [PATCH] f2fs: recover invalid/reserved block address for fsynced file Date: Wed, 05 Aug 2015 17:23:54 +0800 Message-id: <009e01d0cf60$8b66bb00$a2343100$@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: AdDPTdnb/yzvT1XUThiHjVwHxUu8Yw== Content-language: zh-cn X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrDLMWRmVeSWpSXmKPExsVy+t9jQd3gawdDDbbfYrN4sn4Ws8WlRe4W l3fNYXNg9ti0qpPNY/eCz0wenzfJBTBHcdmkpOZklqUW6dslcGV0fljFVLBcomJb7zHGBsY7 Ql2MnBwSAiYSm5oPsEDYYhIX7q1n62Lk4hASmMUosWB3FxOE84pR4uWqJWBVbAIqEss7/jOB 2CJA9qFFl9lBbGYBD4nGju+sILawgJ9E66FVbCA2i4CqxPnvr8FqeAUsJdpWXWaFsAUlfky+ xwLRqyWxfudxJghbXmLzmrfMEBcpSOw4+5oRYpeexOk/5xghasQlNh65xTKBEehMhFGzkIya hWTULCQtCxhZVjFKpBYkFxQnpeca5aWW6xUn5haX5qXrJefnbmIEh/Ez6R2Mh3e5H2IU4GBU 4uH94HwwVIg1say4MvcQowQHs5IIb8Z2oBBvSmJlVWpRfnxRaU5q8SFGaQ4WJXFefZNNoUIC 6YklqdmpqQWpRTBZJg5OqQbGnq+NLUdmSwR2GBiwxQaJXNMTf3A5f49W9u8FLDf3XV7W0ryx dQGzlkPuGWOhmCtsP3vCu+eFLo4QMlpS2D3tdQDLmWu5O2YvY5liP/+6rv7s0H3pxh4ixwJ+ Fs7MfffPZV/xiqPzHks+yGH/MnVBYGyXWGjRCkVJaQUtb+df+r47ctqelnEpsRRnJBpqMRcV JwIADTD24V8CAAA= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3259 Lines: 102 When testing with generic/101 in xfstests, error message outputed as below: --- tests/generic/101.out +++ results//generic/101.out.bad @@ -10,10 +10,14 @@ File foo content after log replay: 0000000 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa * -0200000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0200000 bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb * 0372000 ... (Run 'diff -u tests/generic/101.out results/generic/101.out.bad' to see the entire diff) The test flow is like below: 1. pwrite foo -S 0xaa 0 64K 2. pwrite foo -S 0xbb 64K 61K 3. sync 4. truncate foo 64K 5. truncate foo 125K 6. fsync foo 7. flakey drop writes 8. umount After this test, we expect the data of recovered file will have the first 64k of data filling with value 0xaa and the next 61k of data filling with value 0x00 because we have fsynced it before dropping writes in dm. In f2fs, during recovering, we will only recover the valid block address in direct node page if it is marked as a fsynced dnode, but block address which means invalid/reserved (with value NULL_ADDR/NEW_ADDR) will not be recovered. So, the file recovered shows its incorrect data 0xbb in range of [61k, 125k]. In this patch, we fix to recover invalid/reserved block during recover flow. Signed-off-by: Chao Yu --- fs/f2fs/recovery.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 07a36e4..d2ef0c9 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -399,14 +399,35 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, f2fs_bug_on(sbi, ni.ino != ino_of_node(page)); f2fs_bug_on(sbi, ofs_of_node(dn.node_page) != ofs_of_node(page)); - for (; start < end; start++) { + for (; start < end; start++, dn.ofs_in_node++) { block_t src, dest; src = datablock_addr(dn.node_page, dn.ofs_in_node); dest = datablock_addr(page, dn.ofs_in_node); - if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR && - is_valid_blkaddr(sbi, dest, META_POR)) { + /* skip recovering if dest is the same as src */ + if (src == dest) + continue; + + /* dest is invalid, just invalidate src block */ + if (dest == NULL_ADDR) { + truncate_data_blocks_range(&dn, 1); + continue; + } + + /* + * dest is reserved block, invalidate src block + * and then reserve one new block in dnode page. + */ + if (dest == NEW_ADDR) { + truncate_data_blocks_range(&dn, 1); + err = reserve_new_block(&dn); + f2fs_bug_on(sbi, err); + continue; + } + + /* dest is valid block, try to recover from src to dest */ + if (is_valid_blkaddr(sbi, dest, META_POR)) { if (src == NULL_ADDR) { err = reserve_new_block(&dn); @@ -424,7 +445,6 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, ni.version, false); recovered++; } - dn.ofs_in_node++; } if (IS_INODE(dn.node_page)) -- 2.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/