From patchwork Mon Feb 14 13:38:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tim Gardner X-Patchwork-Id: 1592544 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=canonical.com header.i=@canonical.com header.a=rsa-sha256 header.s=20210705 header.b=CaIeRQa0; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Jy51B1dtyz9sCD for ; Tue, 15 Feb 2022 00:39:26 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1nJbZX-00066P-57; Mon, 14 Feb 2022 13:39:19 +0000 Received: from smtp-relay-internal-0.internal ([10.131.114.225] helo=smtp-relay-internal-0.canonical.com) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1nJbZT-00063Q-2S for kernel-team@lists.ubuntu.com; Mon, 14 Feb 2022 13:39:15 +0000 Received: from mail-pf1-f200.google.com (mail-pf1-f200.google.com [209.85.210.200]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id E3FF83F071 for ; Mon, 14 Feb 2022 13:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1644845954; bh=v7ixbu8JYaES+MKkV5Hi2W4wfxWo0cIs2H4S/P6/ATo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CaIeRQa07zb7udiMOg0Ni5naeM3ae9yHXSc0mOYMD78P/AuVib0KHWIciwY883kIg 9uJL/pKCJ/3wPFdm2va93OQ8FxRh/Ks5UrXk2FRQfUSAfmxeQ/MK6XZSsqw75EpMNu QVGFJLZFHwMl2FiNItpB9J3g+l0Uhwqj1Tbs2vSq5kW47Dtzs+IMlsbQmWWvh9kWQ+ 5bvgnZlUWLOSFZjUw36zDWGFcS5yiaUGm+PV3Df2qxHXnXvOZWHf+DljSxelnTfbWn 1RuQCn4BKzWdh3PIZu3U/PayXGx40z4XSaFowkr6AB6Gc8BMn2l8R/7bi9GGJUAOe0 Ud85l3xHIQX3g== Received: by mail-pf1-f200.google.com with SMTP id d16-20020a056a0010d000b004e0204c9753so11780602pfu.7 for ; Mon, 14 Feb 2022 05:39:14 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=v7ixbu8JYaES+MKkV5Hi2W4wfxWo0cIs2H4S/P6/ATo=; b=rOqqdHiBp3oNjC7BlROI8hHjzox+aE/rLHyg7P6bLv+qrI0meWC5vtUZjECHmbIvZh v8p2BmaHgE2e+HYnR3ccr0cDd2ofN2iuJFfRApQ59zak77N8wzEVs3wdU6PpmieAA8pm IoU9BAb56XcwQ61fKGerqD0hSBc84CNkvBJrc+ESU29cX6bSGMY4MUP/VYaQsNEhFJki qbhMeUdtzRKxQt+z1MqIXJIbjUNbrhYNhnP7HLjX3TuTg77NdiHg/GNjjVGjNDx6Wfp6 yLLxD50SRVjwjkeHL/MXHrtTV7rH+R65EKkpu1/foRioAtWGcdHLDOGZlc1vh/Y+/eeH YL4g== X-Gm-Message-State: AOAM531KYSZRwT2zWxFAG+Fzmfm+ZOo3JNR79yEjdGNGhIhx1dCr0Gnv HUEi4ZkGP2sqT0ksphan4/j/ERG1Z2es27Qz5df8eEpaHF3t2L5EdFUnvI+ViV3uisqC7XpPlg9 uKUl7WOKx/ncybRjaWDm1+UJ/t4zUYNtl+Di7Z0u6Ug== X-Received: by 2002:a17:902:ba91:: with SMTP id k17mr14250122pls.171.1644845953171; Mon, 14 Feb 2022 05:39:13 -0800 (PST) X-Google-Smtp-Source: ABdhPJx0Qi4tuAf+a73bqPisBlOH+U4T9kh+v67dxA1HiHsK18uFteiQ8/vztoTMvWkqSNNb9gZ1EQ== X-Received: by 2002:a17:902:ba91:: with SMTP id k17mr14250095pls.171.1644845952726; Mon, 14 Feb 2022 05:39:12 -0800 (PST) Received: from localhost.localdomain ([69.163.84.166]) by smtp.gmail.com with ESMTPSA id bd34sm4837071pfb.73.2022.02.14.05.39.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Feb 2022 05:39:12 -0800 (PST) From: Tim Gardner To: kernel-team@lists.ubuntu.com Subject: [PATCH 2/4][focal/linux-azure] ext4: avoid ext4_error()'s caused by ENOMEM in the truncate path Date: Mon, 14 Feb 2022 06:38:59 -0700 Message-Id: <20220214133904.13574-3-tim.gardner@canonical.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220214133904.13574-1-tim.gardner@canonical.com> References: <20220214133904.13574-1-tim.gardner@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Theodore Ts'o BugLink: https://bugs.launchpad.net/bugs/1960820 We can't fail in the truncate path without requiring an fsck. Add work around for this by using a combination of retry loops and the __GFP_NOFAIL flag. From: Theodore Ts'o Signed-off-by: Theodore Ts'o Signed-off-by: Anna Pendleton Reviewed-by: Harshad Shirwadkar Link: https://lore.kernel.org/r/20200507175028.15061-1-pendleton@google.com Signed-off-by: Theodore Ts'o (cherry picked from commit 73c384c0cdaa8ea9ca9ef2d0cff6a25930f1648e) [rtg - scaffolding patch upon which 9c6e071913792d80894cd0be98cc3c4b770e26d3 is dependent] Signed-off-by: Tim Gardner --- fs/ext4/ext4.h | 1 + fs/ext4/extents.c | 43 +++++++++++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index dc3775e36cc76..9ba6be50b193e 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -628,6 +628,7 @@ enum { */ #define EXT4_EX_NOCACHE 0x40000000 #define EXT4_EX_FORCE_CACHE 0x20000000 +#define EXT4_EX_NOFAIL 0x10000000 /* * Flags used by ext4_free_blocks diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index a650ee6a67a12..9bc6b694093d3 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -290,11 +290,14 @@ ext4_force_split_extent_at(handle_t *handle, struct inode *inode, { struct ext4_ext_path *path = *ppath; int unwritten = ext4_ext_is_unwritten(path[path->p_depth].p_ext); + int flags = EXT4_EX_NOCACHE | EXT4_GET_BLOCKS_PRE_IO; + + if (nofail) + flags |= EXT4_GET_BLOCKS_METADATA_NOFAIL | EXT4_EX_NOFAIL; return ext4_split_extent_at(handle, inode, ppath, lblk, unwritten ? EXT4_EXT_MARK_UNWRIT1|EXT4_EXT_MARK_UNWRIT2 : 0, - EXT4_EX_NOCACHE | EXT4_GET_BLOCKS_PRE_IO | - (nofail ? EXT4_GET_BLOCKS_METADATA_NOFAIL:0)); + flags); } /* @@ -534,8 +537,12 @@ __read_extent_tree_block(const char *function, unsigned int line, { struct buffer_head *bh; int err; + gfp_t gfp_flags = __GFP_MOVABLE | GFP_NOFS; + + if (flags & EXT4_EX_NOFAIL) + gfp_flags |= __GFP_NOFAIL; - bh = sb_getblk_gfp(inode->i_sb, pblk, __GFP_MOVABLE | GFP_NOFS); + bh = sb_getblk_gfp(inode->i_sb, pblk, gfp_flags); if (unlikely(!bh)) return ERR_PTR(-ENOMEM); @@ -877,6 +884,10 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, struct ext4_ext_path *path = orig_path ? *orig_path : NULL; short int depth, i, ppos = 0; int ret; + gfp_t gfp_flags = GFP_NOFS; + + if (flags & EXT4_EX_NOFAIL) + gfp_flags |= __GFP_NOFAIL; eh = ext_inode_hdr(inode); depth = ext_depth(inode); @@ -897,7 +908,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, if (!path) { /* account possible depth increase */ path = kcalloc(depth + 2, sizeof(struct ext4_ext_path), - GFP_NOFS); + gfp_flags); if (unlikely(!path)) return ERR_PTR(-ENOMEM); path[0].p_maxdepth = depth + 1; @@ -1047,9 +1058,13 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, ext4_fsblk_t newblock, oldblock; __le32 border; ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */ + gfp_t gfp_flags = GFP_NOFS; int err = 0; size_t ext_size = 0; + if (flags & EXT4_EX_NOFAIL) + gfp_flags |= __GFP_NOFAIL; + /* make decision: where to split? */ /* FIXME: now decision is simplest: at current extent */ @@ -1083,7 +1098,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, * We need this to handle errors and free blocks * upon them. */ - ablocks = kcalloc(depth, sizeof(ext4_fsblk_t), GFP_NOFS); + ablocks = kcalloc(depth, sizeof(ext4_fsblk_t), gfp_flags); if (!ablocks) return -ENOMEM; @@ -2072,7 +2087,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, if (next != EXT_MAX_BLOCKS) { ext_debug("next leaf block - %u\n", next); BUG_ON(npath != NULL); - npath = ext4_find_extent(inode, next, NULL, 0); + npath = ext4_find_extent(inode, next, NULL, gb_flags); if (IS_ERR(npath)) return PTR_ERR(npath); BUG_ON(npath->p_depth != path->p_depth); @@ -2979,7 +2994,8 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, ext4_fsblk_t pblk; /* find extent for or closest extent to this block */ - path = ext4_find_extent(inode, end, NULL, EXT4_EX_NOCACHE); + path = ext4_find_extent(inode, end, NULL, + EXT4_EX_NOCACHE | EXT4_EX_NOFAIL); if (IS_ERR(path)) { ext4_journal_stop(handle); return PTR_ERR(path); @@ -3065,7 +3081,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, le16_to_cpu(path[k].p_hdr->eh_entries)+1; } else { path = kcalloc(depth + 1, sizeof(struct ext4_ext_path), - GFP_NOFS); + GFP_NOFS | __GFP_NOFAIL); if (path == NULL) { ext4_journal_stop(handle); return -ENOMEM; @@ -3489,7 +3505,7 @@ static int ext4_split_extent(handle_t *handle, * Update path is required because previous ext4_split_extent_at() may * result in split of original leaf or extent zeroout. */ - path = ext4_find_extent(inode, map->m_lblk, ppath, 0); + path = ext4_find_extent(inode, map->m_lblk, ppath, flags); if (IS_ERR(path)) return PTR_ERR(path); depth = ext_depth(inode); @@ -4610,7 +4626,14 @@ int ext4_ext_truncate(handle_t *handle, struct inode *inode) } if (err) return err; - return ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); +retry_remove_space: + err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); + if (err == -ENOMEM) { + cond_resched(); + congestion_wait(BLK_RW_ASYNC, HZ/50); + goto retry_remove_space; + } + return err; } static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,