From patchwork Mon Apr 1 05:55:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10879163 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6E6B815AC for ; Mon, 1 Apr 2019 05:56:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 59563286D9 for ; Mon, 1 Apr 2019 05:56:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4DFF4286DE; Mon, 1 Apr 2019 05:56:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E262C286D9 for ; Mon, 1 Apr 2019 05:55:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726752AbfDAFz6 (ORCPT ); Mon, 1 Apr 2019 01:55:58 -0400 Received: from mx2.suse.de ([195.135.220.15]:54324 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725860AbfDAFz6 (ORCPT ); Mon, 1 Apr 2019 01:55:58 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 907C1ACBF; Mon, 1 Apr 2019 05:55:57 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Thorsten Hirsch Subject: [PATCH v2 1/7] btrfs-progs: check/lowmem: Add inode mode check Date: Mon, 1 Apr 2019 13:55:45 +0800 Message-Id: <20190401055551.6837-2-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401055551.6837-1-wqu@suse.com> References: <20190401055551.6837-1-wqu@suse.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There is one report about invalid free space cache inode mode. Normally free space cache inode should have mode 100600 (regular file, no uid/gid/sticky bit, rw------ bit). But in that report, we have free space cache inode mode as 0. So at least btrfs check should report invalid inode mode. This patch will at least make btrfs check lowmem mode to detect this problem. Please note that, this check only applies to inodes in fs/subvol trees. It doesn't apply to free space cache inodes. Reported-by: Thorsten Hirsch Signed-off-by: Qu Wenruo --- check/mode-common.h | 24 ++++++++++++++++++++++++ check/mode-lowmem.c | 5 +++++ check/mode-lowmem.h | 1 + 3 files changed, 30 insertions(+) diff --git a/check/mode-common.h b/check/mode-common.h index 1fb3cda7d89d..4c88365abbcc 100644 --- a/check/mode-common.h +++ b/check/mode-common.h @@ -126,4 +126,28 @@ int delete_corrupted_dir_item(struct btrfs_trans_handle *trans, struct btrfs_key *di_key, char *namebuf, u32 namelen); +/* + * Check if the inode mode @imode is valid + * + * This check focuses on S_FTMT bits and unused bits. + * Sticky/setuid/setgid and regular owner/group/other bits won't cause + * any problem. + */ +static inline bool is_valid_imode(u32 imode) +{ + if (imode & ~(S_IFMT | 07777)) + return false; + + /* + * S_IFMT is not bitmap, nor pure numbering sequence. Need per valid + * number check. + */ + imode &= S_IFMT; + if (imode != S_IFDIR && imode != S_IFCHR && imode != S_IFBLK && + imode != S_IFREG && imode != S_IFIFO && imode != S_IFLNK && + imode != S_IFSOCK) + return false; + return true; +} + #endif diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index fc6228a05a1b..1553a4a5d2c1 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -2452,6 +2452,11 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path) nlink = btrfs_inode_nlink(node, ii); nodatasum = btrfs_inode_flags(node, ii) & BTRFS_INODE_NODATASUM; + if (!is_valid_imode(mode)) { + error("invalid imode mode bits: 0%o", mode); + err |= INODE_MODE_ERROR; + } + if (S_ISLNK(mode) && flags & (BTRFS_INODE_IMMUTABLE | BTRFS_INODE_APPEND)) { err |= INODE_FLAGS_ERROR; diff --git a/check/mode-lowmem.h b/check/mode-lowmem.h index 46b9b191ce24..e0ab30b770d5 100644 --- a/check/mode-lowmem.h +++ b/check/mode-lowmem.h @@ -46,6 +46,7 @@ #define FATAL_ERROR (1<<22) /* Fatal bit for errno */ #define INODE_FLAGS_ERROR (1<<23) /* Invalid inode flags */ #define DIR_ITEM_HASH_MISMATCH (1<<24) /* Dir item hash mismatch */ +#define INODE_MODE_ERROR (1<<25) /* Bad inode mode */ /* * Error bit for low memory mode check. From patchwork Mon Apr 1 05:55:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10879165 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 06C011708 for ; Mon, 1 Apr 2019 05:56:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E5C96286D9 for ; Mon, 1 Apr 2019 05:56:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D9162286DE; Mon, 1 Apr 2019 05:56:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 83781286D9 for ; Mon, 1 Apr 2019 05:56:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726865AbfDAF4B (ORCPT ); Mon, 1 Apr 2019 01:56:01 -0400 Received: from mx2.suse.de ([195.135.220.15]:54340 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725860AbfDAF4B (ORCPT ); Mon, 1 Apr 2019 01:56:01 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 232F6ACBF; Mon, 1 Apr 2019 05:56:00 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Thorsten Hirsch Subject: [PATCH v2 2/7] btrfs-progs: check/original: Add inode mode check Date: Mon, 1 Apr 2019 13:55:46 +0800 Message-Id: <20190401055551.6837-3-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401055551.6837-1-wqu@suse.com> References: <20190401055551.6837-1-wqu@suse.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Just like lowmem mode, check inode mode, specially for S_IFMT bits and beyond. Please note that, this check only applies to inodes in fs/subvol trees. It doesn't apply to free space cache inodes. Reported-by: Thorsten Hirsch Signed-off-by: Qu Wenruo --- check/main.c | 5 +++++ check/mode-original.h | 1 + 2 files changed, 6 insertions(+) diff --git a/check/main.c b/check/main.c index 7547209c5604..553c93caa2c9 100644 --- a/check/main.c +++ b/check/main.c @@ -616,6 +616,9 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec) fprintf(stderr, ", odd inode flags"); if (errors & I_ERR_INLINE_RAM_BYTES_WRONG) fprintf(stderr, ", invalid inline ram bytes"); + if (errors & I_ERR_INVALID_IMODE) + fprintf(stderr, ", invalid inode mode bit 0%o", + rec->imode & ~07777); fprintf(stderr, "\n"); /* Print the orphan extents if needed */ if (errors & I_ERR_FILE_EXTENT_ORPHAN) @@ -811,6 +814,8 @@ static void maybe_free_inode_rec(struct cache_tree *inode_cache, if (!rec->checked || rec->merging) return; + if (!is_valid_imode(rec->imode)) + rec->errors |= I_ERR_INVALID_IMODE; if (S_ISDIR(rec->imode)) { if (rec->found_size != rec->isize) rec->errors |= I_ERR_DIR_ISIZE_WRONG; diff --git a/check/mode-original.h b/check/mode-original.h index 25ca274118a7..e40a12930a6f 100644 --- a/check/mode-original.h +++ b/check/mode-original.h @@ -189,6 +189,7 @@ struct file_extent_hole { #define I_ERR_ODD_INODE_FLAGS (1 << 16) #define I_ERR_INLINE_RAM_BYTES_WRONG (1 << 17) #define I_ERR_MISMATCH_DIR_HASH (1 << 18) +#define I_ERR_INVALID_IMODE (1 << 19) struct inode_record { struct list_head backrefs; From patchwork Mon Apr 1 05:55:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10879167 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EB5BD1708 for ; Mon, 1 Apr 2019 05:56:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D6616286D9 for ; Mon, 1 Apr 2019 05:56:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CAB8D286DE; Mon, 1 Apr 2019 05:56:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 53671286D9 for ; Mon, 1 Apr 2019 05:56:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727097AbfDAF4E (ORCPT ); Mon, 1 Apr 2019 01:56:04 -0400 Received: from mx2.suse.de ([195.135.220.15]:54348 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725860AbfDAF4E (ORCPT ); Mon, 1 Apr 2019 01:56:04 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 1043DACBF for ; Mon, 1 Apr 2019 05:56:02 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 3/7] btrfs-progs: check/lowmem: Repair invalid inode mode in root tree Date: Mon, 1 Apr 2019 13:55:47 +0800 Message-Id: <20190401055551.6837-4-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401055551.6837-1-wqu@suse.com> References: <20190401055551.6837-1-wqu@suse.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In root tree, we only have 2 types of inodes: - ROOT_TREE_DIR inode Its mode is fixed to 40755 - free space cache inodes Its mode is fixed to 100600 This patch will add the ability to repair such inodes to lowmem mode. For fs/subvolume tree error, at least we haven't see such corruption yet, so we don't need to rush to fix corruption in fs trees yet. The repair function, reset_imode() and repair_imode_common() can be reused by later original mode patch, so it's placed in check/mode-common.c. Signed-off-by: Qu Wenruo --- check/mode-common.c | 94 +++++++++++++++++++++++++++++++++++++++++++++ check/mode-common.h | 3 ++ check/mode-lowmem.c | 8 +++- 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/check/mode-common.c b/check/mode-common.c index fed102b0ce7a..466e7a8d09a7 100644 --- a/check/mode-common.c +++ b/check/mode-common.c @@ -795,3 +795,97 @@ out: btrfs_release_path(&path); return ret; } + +/* + * Reset the mode of inode (specified by @root and @ino) to @mode. + * + * Caller should ensure @path is not populated, the @path is mainly for caller + * to grab the correct new path of the inode. + * + * Return 0 if repair is done, @path will point to the correct inode item. + * Return <0 for errors. + */ +int reset_imode(struct btrfs_trans_handle *trans, struct btrfs_root *root, + struct btrfs_path *path, u64 ino, u32 mode) +{ + struct btrfs_inode_item *iitem; + struct extent_buffer *leaf; + struct btrfs_key key; + int slot; + int ret; + + key.objectid = ino; + key.type = BTRFS_INODE_ITEM_KEY; + key.offset = 0; + + ret = btrfs_search_slot(trans, root, &key, path, 0, 1); + if (ret > 0) + ret = -ENOENT; + if (ret < 0) { + errno = -ret; + error("failed to search tree %llu: %m", + root->root_key.objectid); + return ret; + } + leaf = path->nodes[0]; + slot = path->slots[0]; + iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); + btrfs_set_inode_mode(leaf, iitem, mode); + btrfs_mark_buffer_dirty(leaf); + return ret; +} + +/* + * Reset the inode mode of the inode specified by @path. + * + * Caller should ensure the @path is pointing to an INODE_ITEM and root is tree + * root. Repair imode for other trees is not supported yet. + * + * Return 0 if repair is successful. + * Return <0 if error happens. + */ +int repair_imode_common(struct btrfs_root *root, struct btrfs_path *path) +{ + struct btrfs_trans_handle *trans; + struct btrfs_key key; + u32 imode; + int ret; + + if (root->root_key.objectid != BTRFS_ROOT_TREE_OBJECTID) { + error( + "repair inode mode outside of root tree is not supported yet"); + return -ENOTTY; + } + btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); + ASSERT(key.type == BTRFS_INODE_ITEM_KEY); + if (key.objectid != BTRFS_ROOT_TREE_DIR_OBJECTID && + !is_fstree(key.objectid)) { + error("unsupported ino %llu", key.objectid); + return -ENOTTY; + } + if (key.objectid == BTRFS_ROOT_TREE_DIR_OBJECTID) + imode = 040755; + else + imode = 0100600; + + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + errno = -ret; + error("failed to start transaction: %m"); + return ret; + } + btrfs_release_path(path); + + ret = reset_imode(trans, root, path, key.objectid, imode); + if (ret < 0) + goto abort; + ret = btrfs_commit_transaction(trans, root); + if (!ret) + printf("reset mode for inode %llu root %llu\n", + key.objectid, root->root_key.objectid); + return ret; +abort: + btrfs_abort_transaction(trans, ret); + return ret; +} diff --git a/check/mode-common.h b/check/mode-common.h index 4c88365abbcc..5aaf3aaa389b 100644 --- a/check/mode-common.h +++ b/check/mode-common.h @@ -125,6 +125,9 @@ int delete_corrupted_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *di_key, char *namebuf, u32 namelen); +int reset_imode(struct btrfs_trans_handle *trans, struct btrfs_root *root, + struct btrfs_path *path, u64 ino, u32 mode); +int repair_imode_common(struct btrfs_root *root, struct btrfs_path *path); /* * Check if the inode mode @imode is valid diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 1553a4a5d2c1..8ecf27795c36 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -2454,7 +2454,13 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path) if (!is_valid_imode(mode)) { error("invalid imode mode bits: 0%o", mode); - err |= INODE_MODE_ERROR; + if (repair) { + ret = repair_imode_common(root, path); + if (ret < 0) + err |= INODE_MODE_ERROR; + } else { + err |= INODE_MODE_ERROR; + } } if (S_ISLNK(mode) && From patchwork Mon Apr 1 05:55:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10879169 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D813A15AC for ; Mon, 1 Apr 2019 05:56:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C196D286D9 for ; Mon, 1 Apr 2019 05:56:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B09D0286DE; Mon, 1 Apr 2019 05:56:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 63DD5286D9 for ; Mon, 1 Apr 2019 05:56:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727377AbfDAF4G (ORCPT ); Mon, 1 Apr 2019 01:56:06 -0400 Received: from mx2.suse.de ([195.135.220.15]:54362 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725860AbfDAF4F (ORCPT ); Mon, 1 Apr 2019 01:56:05 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id CBEF9ACBF for ; Mon, 1 Apr 2019 05:56:04 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 4/7] btrfs-progs: check/original: Repair invalid inode mode in root tree Date: Mon, 1 Apr 2019 13:55:48 +0800 Message-Id: <20190401055551.6837-5-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401055551.6837-1-wqu@suse.com> References: <20190401055551.6837-1-wqu@suse.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch will reuse the mode independent repair_imode() function, to repair invalid inode mode. Signed-off-by: Qu Wenruo --- check/main.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/check/main.c b/check/main.c index 553c93caa2c9..608fe7bb02fb 100644 --- a/check/main.c +++ b/check/main.c @@ -2698,6 +2698,30 @@ static int repair_mismatch_dir_hash(struct btrfs_trans_handle *trans, return ret; } +static int repair_imode_original(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + struct inode_record *rec) +{ + int ret; + u32 imode; + + if (root->root_key.objectid != BTRFS_ROOT_TREE_OBJECTID) + return -ENOTTY; + if (rec->ino != BTRFS_ROOT_TREE_DIR_OBJECTID || !is_fstree(rec->ino)) + return -ENOTTY; + + if (rec->ino == BTRFS_ROOT_TREE_DIR_OBJECTID) + imode = 040755; + else + imode = 0100600; + ret = reset_imode(trans, root, path, rec->ino, imode); + if (ret < 0) + return ret; + rec->errors &= ~I_ERR_INVALID_IMODE; + return ret; +} + static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) { struct btrfs_trans_handle *trans; @@ -2745,6 +2769,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) ret = repair_inode_nbytes(trans, root, &path, rec); if (!ret && rec->errors & I_ERR_INLINE_RAM_BYTES_WRONG) ret = repair_inline_ram_bytes(trans, root, &path, rec); + if (!ret && rec->errors & I_ERR_INVALID_IMODE) + ret = repair_imode_original(trans, root, &path, rec); btrfs_commit_transaction(trans, root); btrfs_release_path(&path); return ret; From patchwork Mon Apr 1 05:55:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10879171 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 836DB15AC for ; Mon, 1 Apr 2019 05:56:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6E1F6286D9 for ; Mon, 1 Apr 2019 05:56:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 62748286DE; Mon, 1 Apr 2019 05:56:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E0C5D286D9 for ; Mon, 1 Apr 2019 05:56:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727489AbfDAF4I (ORCPT ); Mon, 1 Apr 2019 01:56:08 -0400 Received: from mx2.suse.de ([195.135.220.15]:54368 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725860AbfDAF4I (ORCPT ); Mon, 1 Apr 2019 01:56:08 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 9A5FAACBF for ; Mon, 1 Apr 2019 05:56:06 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 5/7] btrfs: check/lowmem: Check and repair free space cache inode mode Date: Mon, 1 Apr 2019 13:55:49 +0800 Message-Id: <20190401055551.6837-6-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401055551.6837-1-wqu@suse.com> References: <20190401055551.6837-1-wqu@suse.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Unlike inodes in fs roots, we don't really check the inode items in root tree, in fact we just skip everything other than ROOT_ITEM and ROOT_REF. This makes invalid inode items sneak into root tree. For example: item 9 key (256 INODE_ITEM 0) itemoff 13702 itemsize 160 generation 30 transid 30 size 65536 nbytes 1507328 block group 0 mode 0 links 1 uid 0 gid 0 rdev 0 ^ Should be 100600 sequence 23 flags 0x1b(NODATASUM|NODATACOW|NOCOMPRESS|PREALLOC) atime 0.0 (1970-01-01 08:00:00) ctime 1553491158.189771625 (2019-03-25 13:19:18) mtime 0.0 (1970-01-01 08:00:00) otime 0.0 (1970-01-01 08:00:00) There is a report of such problem in the mail list. This patch will check and repair inode items of free space cache inodes in lowmem mode. Since free space cache inodes doesn't have INODE_REF but still has 1 link, we can't use check_inode_item() directly. Instead we only check the inode mode, as that's the important part. The check and repair function: check_repair_free_space_inode() is also exported for original mode. Signed-off-by: Qu Wenruo --- check/mode-common.c | 35 +++++++++++++++++++++++++++++++++++ check/mode-common.h | 4 +++- check/mode-lowmem.c | 11 +++++++++++ check/mode-lowmem.h | 2 ++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/check/mode-common.c b/check/mode-common.c index 466e7a8d09a7..95dc32d875e6 100644 --- a/check/mode-common.c +++ b/check/mode-common.c @@ -21,6 +21,7 @@ #include "transaction.h" #include "utils.h" #include "disk-io.h" +#include "repair.h" #include "check/mode-common.h" /* @@ -889,3 +890,37 @@ abort: btrfs_abort_transaction(trans, ret); return ret; } + +/* + * For free space inodes, we can't call check_inode_item() as free space + * cache inode doesn't have INODE_REF. + * We just check its inode mode. + */ +int check_repair_free_space_inode(struct btrfs_fs_info *fs_info, + struct btrfs_path *path) +{ + struct btrfs_inode_item *iitem; + struct btrfs_key key; + u32 mode; + int ret = 0; + + btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); + ASSERT(key.type == BTRFS_INODE_ITEM_KEY && is_fstree(key.objectid)); + iitem = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_inode_item); + mode = btrfs_inode_mode(path->nodes[0], iitem); + if (mode != FREE_SPACE_CACHE_INODE_MODE) { + error( + "free space cache inode %llu has invalid mode: has 0%o expect 0%o", + key.objectid, mode, FREE_SPACE_CACHE_INODE_MODE); + ret = -EUCLEAN; + if (repair) { + ret = repair_imode_common(fs_info->tree_root, + path); + if (ret < 0) + return ret; + return ret; + } + } + return ret; +} diff --git a/check/mode-common.h b/check/mode-common.h index 5aaf3aaa389b..4c169c6e3b29 100644 --- a/check/mode-common.h +++ b/check/mode-common.h @@ -24,6 +24,7 @@ #include #include "ctree.h" +#define FREE_SPACE_CACHE_INODE_MODE (0100600) /* * Use for tree walk to walk through trees whose leaves/nodes can be shared * between different trees. (Namely subvolume/fs trees) @@ -128,7 +129,8 @@ int delete_corrupted_dir_item(struct btrfs_trans_handle *trans, int reset_imode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 ino, u32 mode); int repair_imode_common(struct btrfs_root *root, struct btrfs_path *path); - +int check_repair_free_space_inode(struct btrfs_fs_info *fs_info, + struct btrfs_path *path); /* * Check if the inode mode @imode is valid * diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 8ecf27795c36..6665a7b07e0f 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -5088,6 +5088,17 @@ int check_fs_roots_lowmem(struct btrfs_fs_info *fs_info) btrfs_item_key_to_cpu(node, &key, slot); if (key.objectid > BTRFS_LAST_FREE_OBJECTID) goto out; + if (key.type == BTRFS_INODE_ITEM_KEY && + is_fstree(key.objectid)) { + ret = check_repair_free_space_inode(fs_info, &path); + /* Check if we still have a valid path to continue */ + if (ret < 0 && path.nodes[0]) { + err |= ret; + goto next; + } + if (ret < 0 && !path.nodes[0]) + goto out; + } if (key.type == BTRFS_ROOT_ITEM_KEY && fs_root_objectid(key.objectid)) { if (key.objectid == BTRFS_TREE_RELOC_OBJECTID) { diff --git a/check/mode-lowmem.h b/check/mode-lowmem.h index e0ab30b770d5..d2983fd12eb4 100644 --- a/check/mode-lowmem.h +++ b/check/mode-lowmem.h @@ -67,5 +67,7 @@ int check_fs_roots_lowmem(struct btrfs_fs_info *fs_info); int check_chunks_and_extents_lowmem(struct btrfs_fs_info *fs_info); +int check_repair_free_space_inode(struct btrfs_fs_info *fs_info, + struct btrfs_path *path); #endif From patchwork Mon Apr 1 05:55:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 10879173 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D786C1708 for ; Mon, 1 Apr 2019 05:56:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C3C5B286D9 for ; Mon, 1 Apr 2019 05:56:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B89B0286DE; Mon, 1 Apr 2019 05:56:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 659BB286D9 for ; Mon, 1 Apr 2019 05:56:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728109AbfDAF4K (ORCPT ); Mon, 1 Apr 2019 01:56:10 -0400 Received: from mx2.suse.de ([195.135.220.15]:54374 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725860AbfDAF4J (ORCPT ); Mon, 1 Apr 2019 01:56:09 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id B4ADDADC8 for ; Mon, 1 Apr 2019 05:56:08 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 6/7] btrfs: check/original: Check and repair free space cache inode item Date: Mon, 1 Apr 2019 13:55:50 +0800 Message-Id: <20190401055551.6837-7-wqu@suse.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401055551.6837-1-wqu@suse.com> References: <20190401055551.6837-1-wqu@suse.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Just like lowmem mode, also check and repair free space cache inode item. And since we don't really have a good timing/function to check free space chace inodes, we use the same common mode check_repair_free_space_inode() when iterating root tree. Signed-off-by: Qu Wenruo --- check/main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/check/main.c b/check/main.c index 608fe7bb02fb..7466d5d00858 100644 --- a/check/main.c +++ b/check/main.c @@ -3626,6 +3626,17 @@ again: key.type == BTRFS_ROOT_BACKREF_KEY) { process_root_ref(leaf, path.slots[0], &key, root_cache); + } else if (key.type == BTRFS_INODE_ITEM_KEY && + is_fstree(key.objectid)) { + ret = check_repair_free_space_inode(fs_info, &path); + if (ret < 0 && !path.nodes[0]) { + err = 1; + goto out; + } + if (ret < 0 && path.nodes[0]) { + err = 1; + goto next; + } } next: path.slots[0]++;