From patchwork Fri Apr 17 18:02:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 6234971 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A6CDCBF4A6 for ; Fri, 17 Apr 2015 18:02:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7BA4F20397 for ; Fri, 17 Apr 2015 18:02:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7C1AC20394 for ; Fri, 17 Apr 2015 18:02:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754977AbbDQSCU (ORCPT ); Fri, 17 Apr 2015 14:02:20 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:19775 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754115AbbDQSCS (ORCPT ); Fri, 17 Apr 2015 14:02:18 -0400 Received: from pps.filterd (m0044012 [127.0.0.1]) by mx0a-00082601.pphosted.com (8.14.5/8.14.5) with SMTP id t3HI0gv6026102 for ; Fri, 17 Apr 2015 11:02:18 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=fb.com; h=from : to : subject : date : message-id : mime-version : content-type; s=facebook; bh=bYDH5lBo9pJk30yiZbjHJXtY2Eh6g4F83t/TwMLfjEE=; b=DcZe9ZJMoWVr/IELk+XSTVRHQ5XFs8KwDyP16bdA4ANuUr5/FTEXuz2KAHtZzpgHg/jR P2aBDyqr6nY1280UzeuTO+XpHA8eOhfaJMo+Of5Cnu0iSSWDkbAxR6vPe8Jd5N24+2ah DbLBSSZEj8q3auHjjk0pZrYZv2mcPTavTdY= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 1tu6ang2vc-1 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT) for ; Fri, 17 Apr 2015 11:02:18 -0700 Received: from localhost (192.168.54.13) by mail.thefacebook.com (192.168.16.16) with Microsoft SMTP Server (TLS) id 14.3.195.1; Fri, 17 Apr 2015 11:02:16 -0700 From: Josef Bacik To: Subject: [PATCH V2] Btrfs-progs: check for matchin free space in cache Date: Fri, 17 Apr 2015 14:02:15 -0400 Message-ID: <1429293735-31351-1-git-send-email-jbacik@fb.com> X-Mailer: git-send-email 1.8.3.1 MIME-Version: 1.0 X-Originating-IP: [192.168.54.13] X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.13.68, 1.0.33, 0.0.0000 definitions=2015-04-17_07:2015-04-17, 2015-04-17, 1970-01-01 signatures=0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We have this check in the kernel but not in userspace, which makes fsck fail when we wouldn't have a problem in the kernel. This was meant to catch this case because it really isn't good, unfortunately it will require a design change to fix in the kernel so in the meantime add this check so we can be sure our tests only catch real problems. Thanks, Signed-off-by: Josef Bacik --- V1->V2: - only check matched if __load_free_space_cache is successful ctree.h | 1 + extent-tree.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ free-space-cache.c | 11 +++++++++++ 3 files changed, 63 insertions(+) diff --git a/ctree.h b/ctree.h index 2042771..10dc838 100644 --- a/ctree.h +++ b/ctree.h @@ -936,6 +936,7 @@ struct btrfs_block_group_cache { struct btrfs_block_group_item item; struct btrfs_space_info *space_info; struct btrfs_free_space_ctl *free_space_ctl; + u64 bytes_super; u64 pinned; u64 flags; int cached; diff --git a/extent-tree.c b/extent-tree.c index e8545ef..c24af6a 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -3140,6 +3140,54 @@ error: return ret; } +static void account_super_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_block_group_cache *cache) +{ + u64 bytenr; + u64 *logical; + int stripe_len; + int i, nr, ret; + + if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) { + stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid; + cache->bytes_super += stripe_len; + } + + for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { + bytenr = btrfs_sb_offset(i); + ret = btrfs_rmap_block(&fs_info->mapping_tree, + cache->key.objectid, bytenr, + 0, &logical, &nr, &stripe_len); + if (ret) + return; + + while (nr--) { + u64 start, len; + + if (logical[nr] > cache->key.objectid + + cache->key.offset) + continue; + + if (logical[nr] + stripe_len <= cache->key.objectid) + continue; + + start = logical[nr]; + if (start < cache->key.objectid) { + start = cache->key.objectid; + len = (logical[nr] + stripe_len) - start; + } else { + len = min_t(u64, stripe_len, + cache->key.objectid + + cache->key.offset - start); + } + + cache->bytes_super += len; + } + + kfree(logical); + } +} + int btrfs_read_block_groups(struct btrfs_root *root) { struct btrfs_path *path; @@ -3201,6 +3249,8 @@ int btrfs_read_block_groups(struct btrfs_root *root) if (btrfs_chunk_readonly(root, cache->key.objectid)) cache->ro = 1; + account_super_bytes(info, cache); + ret = update_space_info(info, cache->flags, found_key.offset, btrfs_block_group_used(&cache->item), &space_info); @@ -3242,6 +3292,7 @@ btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type, cache->flags = type; btrfs_set_block_group_flags(&cache->item, type); + account_super_bytes(fs_info, cache); ret = update_space_info(fs_info, cache->flags, size, bytes_used, &cache->space_info); BUG_ON(ret); diff --git a/free-space-cache.c b/free-space-cache.c index 99ad420..84a50e3 100644 --- a/free-space-cache.c +++ b/free-space-cache.c @@ -428,7 +428,9 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_path *path; + u64 used = btrfs_block_group_used(&block_group->item); int ret = 0; + int matched; path = btrfs_alloc_path(); if (!path) @@ -438,6 +440,15 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, block_group->key.objectid); btrfs_free_path(path); + matched = (ctl->free_space == (block_group->key.offset - used - + block_group->bytes_super)); + if (ret == 1 && !matched) { + __btrfs_remove_free_space_cache(ctl); + printf("block group %llu has wrong abount of free space", + block_group->key.objectid); + ret = -1; + } + if (ret < 0) { ret = 0;