Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp1599878pxb; Sun, 22 Aug 2021 23:14:52 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw3GDwn0ISEvRqMjAkm2hxIcTxzBNBExEXJrp2r2j4G2JXLWli1rDuF922UooOc1c8s8GWb X-Received: by 2002:a17:906:25db:: with SMTP id n27mr33217718ejb.108.1629699291952; Sun, 22 Aug 2021 23:14:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629699291; cv=none; d=google.com; s=arc-20160816; b=hjCcSr120MPwFnj9iNoCjdbuD1GuIqlvZtyT3lB/gTzBdnJYkkYiRKcAMOZhBg4yDX hzWKercYGPC3MPqazdMb0ahpEfb5sYnpRTS7L9c4z1tPqSs5t1gzUbB5QbiqdbMvn3ia 7+8Up0TRGd/7uOVc0wZ5g/sLLSRZzPHCq8kv317afLTK+iOOGweZKUW8878T34f78VS9 HgwkOU/jjGpSGVLk4U9yJFhINGAISK27+eXBZpw1Vwpl5QWPEeaZ/dLpTrBiMC5P+ZIe QAQcDstYZtXwNLbogLKL/KVyvXvp89lPpPqiCZFvy3vJb6J0LdKnTlNwdogjRc6M7lWT hy+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=fuT+jDq/fR5CVwFXJqhysOnHBkOFwEXLNdmKI4VrTzU=; b=G6uk6rQb8ZDT+wMDwbpM3v+DkH5NoFr5Uq7aQw+C3OPFbP5Xz9ctsyUm+Qj8kX2psu emHZUODYaLNyobHPfKp5iabAJJrRxYDk91AcAVP3vEoQdFgfADtDG9ygYNXcacnF7o5G 6fYWkrqpW8XXmeHzqSu1Wl+/u7UdhYAlwj7y2Osy7dehgFyDAePySeuGK5M6KLRjaVEO D9VGktFaL5vVKhWfCrIpbUIrwhA59Z2zud7MEymx/H6t6tAAGer2+kW8IURYS20IVcct AWeH3lpcEtN1vuk72M3XmwT8BoX/lrByd1DbxtBAMM7eVAQ8qSmTDrH4GxQ3VpAiv6UT DiAg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id k2si14072213ejo.293.2021.08.22.23.14.16; Sun, 22 Aug 2021 23:14:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232501AbhHWGOm (ORCPT + 99 others); Mon, 23 Aug 2021 02:14:42 -0400 Received: from out30-130.freemail.mail.aliyun.com ([115.124.30.130]:53683 "EHLO out30-130.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231267AbhHWGOl (ORCPT ); Mon, 23 Aug 2021 02:14:41 -0400 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R451e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e01424;MF=jefflexu@linux.alibaba.com;NM=1;PH=DS;RN=6;SR=0;TI=SMTPD_---0UlCK-Sz_1629699238; Received: from localhost(mailfrom:jefflexu@linux.alibaba.com fp:SMTPD_---0UlCK-Sz_1629699238) by smtp.aliyun-inc.com(127.0.0.1); Mon, 23 Aug 2021 14:13:58 +0800 From: Jeffle Xu To: tytso@mit.edu, adilger.kernel@dilger.ca Cc: linux-ext4@vger.kernel.org, joseph.qi@linux.alibaba.com, enwlinux@gmail.com, hsiangkao@linux.alibaba.com Subject: [PATCH v2] ext4: fix reserved space counter leakage Date: Mon, 23 Aug 2021 14:13:58 +0800 Message-Id: <20210823061358.84473-1-jefflexu@linux.alibaba.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org When ext4_insert_delayed block receives and recovers from an error from ext4_es_insert_delayed_block(), e.g., ENOMEM, it does not release the space it has reserved for that block insertion as it should. One effect of this bug is that s_dirtyclusters_counter is not decremented and remains incorrectly elevated until the file system has been unmounted. This can result in premature ENOSPC returns and apparent loss of free space. Another effect of this bug is that /sys/fs/ext4//delayed_allocation_blocks can remain non-zero even after syncfs has been executed on the filesystem. Besides, add check for s_dirtyclusters_counter when inode is going to be evicted and freed. s_dirtyclusters_counter can still keep non-zero until inode is written back in .evict_inode(), and thus the check is delayed to .destroy_inode(). Fixes: 51865fda28e5 ("ext4: let ext4 maintain extent status tree") Cc: Suggested-by: Gao Xiang Signed-off-by: Jeffle Xu --- changes since v1: - improve commit log suggested by Eric Whitney - update "Suggested-by" title for Gao Xian, who actually found this bug code - add check for s_dirtyclusters_counter in .destroy_inode() --- fs/ext4/inode.c | 5 +++++ fs/ext4/super.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index d8de607849df..73daf9443e5e 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1640,6 +1640,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); int ret; bool allocated = false; + bool reserved = false; /* * If the cluster containing lblk is shared with a delayed, @@ -1656,6 +1657,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) ret = ext4_da_reserve_space(inode); if (ret != 0) /* ENOSPC */ goto errout; + reserved = true; } else { /* bigalloc */ if (!ext4_es_scan_clu(inode, &ext4_es_is_delonly, lblk)) { if (!ext4_es_scan_clu(inode, @@ -1668,6 +1670,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) ret = ext4_da_reserve_space(inode); if (ret != 0) /* ENOSPC */ goto errout; + reserved = true; } else { allocated = true; } @@ -1678,6 +1681,8 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) } ret = ext4_es_insert_delayed_block(inode, lblk, allocated); + if (ret && reserved) + ext4_da_release_space(inode, 1); errout: return ret; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index dfa09a277b56..61bf52b58fca 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1351,6 +1351,12 @@ static void ext4_destroy_inode(struct inode *inode) true); dump_stack(); } + + if (EXT4_I(inode)->i_reserved_data_blocks) + ext4_msg(inode->i_sb, KERN_ERR, + "Inode %lu (%p): i_reserved_data_blocks (%u) not cleared!", + inode->i_ino, EXT4_I(inode), + EXT4_I(inode)->i_reserved_data_blocks); } static void init_once(void *foo) -- 2.27.0