From patchwork Thu Feb 22 12:18:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Yu X-Patchwork-Id: 204738 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:aa16:b0:108:e6aa:91d0 with SMTP id by22csp211512dyb; Thu, 22 Feb 2024 04:19:39 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCXD3I2Yqs2kpmXFh/UjItk8EjZOTw8WaDDFAOerMJYOGHcgBr8lT9vhM/HOJzjU/E90nl8PTc7YU4gFF9QEQpCL+DfXgA== X-Google-Smtp-Source: AGHT+IGkTboMYGM0XsyTcubR+tTrYH4/n+j0yFc3BzlIK1GG52G3Nm9QzDz113/XvHY5mNVFs7RD X-Received: by 2002:a05:620a:1a94:b0:787:9b19:80f3 with SMTP id bl20-20020a05620a1a9400b007879b1980f3mr2277863qkb.24.1708604379005; Thu, 22 Feb 2024 04:19:39 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708604378; cv=pass; d=google.com; s=arc-20160816; b=TxHyfOcq2x4wSmpx/rGby7EPb1txbefhzn0XHtq1WivMqK71i4HI8yOvG/qNgAUcJv 1G3JgK1AAbD4AHzGcNW5JFdbgXHccRoAE34Qod/loNO09vp9wM1IJlvBkj0nYAiUgMWH X6MUs257doEdMJH+cGW2Sy3MgmHkjEtSdNHcDYYm2qWvtt+OJvmr9qxWZ1vknLbmWdC6 0yILZRtWE+JqLPsHWF7fQnF1XfNw0zwzyTtVEeII20pybLQgEgT2etlvPfidPQq6HACU ImdQH+J5kncnVcIYPskFsholGfmuznUIskFbY1eBldTF0HkQWOl5jh4ccKlcHltveqbZ 9Nsg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=5XxDLe1c6Dl0sB8fQLg6jo+WW+90//w1xGF2UrA+ddU=; fh=X1/oBJvTGJUQ0YtRp03u+3tPfRw/dXXALWynfOSlfQQ=; b=If7zdwvMMZd2vp9PRo1/OhBadEX6oKc65Csvon/2D5i3c8CpUkRIOwFjnKdp4Df/nj 5v+QBO+dgU4hiUOMjf2qOGZB2mOFx72dm070VdbDThRIRRd0qs3jj3/opD3WIji3q/fd owi5uxor7WoXhPdmDkAjf6A3vp8fW2nAz1O4AI9n5OmqMNMWl84ROoG+hzLGVnmfSxUl JIoxt0Dl3ff/bDDqZmMV1ZQg29J6/EGmdGvlDLvLvGOhnK3HBi4LkYsm80uIyeGq4wGM GC5pheeMG2v6ed4abmlV0htBJP6Y0OKQsO7z0I/DXGnZgShXin6maGrcsSILhgt7RhIl OTkg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=StLUxsYE; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-76497-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-76497-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id m18-20020a05620a24d200b00787354bed11si14207373qkn.413.2024.02.22.04.19.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Feb 2024 04:19:38 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-76497-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=StLUxsYE; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-76497-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-76497-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id BB3B51C2239E for ; Thu, 22 Feb 2024 12:19:38 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 71AB16166F; Thu, 22 Feb 2024 12:19:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="StLUxsYE" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 772AD60DDB for ; Thu, 22 Feb 2024 12:19:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708604341; cv=none; b=C1/19mRgKZizrtVNEn/W2C5NytIvjD1SwE+d2ZC+NjlWR+aodE4OY7XcNlFwL45ySwTeubp6fiDIR8SYuDlP+nqiD4M1oimFM+tVQAQnC+q1CJxhwOSRP0aaIAeDLfi9BMKZejbeUcgOeIT0bJJKYG15arSxT9kDNPPLHlYNS40= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708604341; c=relaxed/simple; bh=JScqMUmhnumYR16/rHyzcKV1L1sOSHfgCbEcWtK9OnY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gsTVTfu8T6RGJ2Z9vCMs9Vhw/QgrDbXwhkcLVyCYpYy/UMsWZ3s4xXXxZHYN7JwK6T0vuu/hciqQqRJekeBqouTfDn07eOD6JqORa+SMPKPSC//Ao2gkezIvcVPkepSIPHAZSxQYGNO9eTjkVOcmTzMd8v9anJ+MKL0NxPbS9i0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=StLUxsYE; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0FF7DC433F1; Thu, 22 Feb 2024 12:18:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708604341; bh=JScqMUmhnumYR16/rHyzcKV1L1sOSHfgCbEcWtK9OnY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=StLUxsYEGp6qFUHyiSGOtJrfIfpajgNSWYrhEGA2mW/GqMuJq3Mz7Nph1WwW83zgN z2UZeOxs0Q+vEFZ2XsTSVLoTQ82faFpVudcCVVqg9Tc+zRIorhL7WM1ENRpJegUErt Ki/5+wbdTH2iTbfIb+Ro2h49U/pgsmFIvThpZW+1H/3E0gQGiL4W7urwAIPGteNCJt D/FmM+rV1NhQpZat5UT4pZX1c74GW2BpF9m2V8G8u27/jhaWc+/LAZC/iYYpHMTuxh tQ0iERkfaEo6qx5Pji9BYTqKpb7rvoHHknnR4H42xGYOazoO8AMFhB2rMyVOaBnuII ImBjWddAmuITQ== From: Chao Yu To: jaegeuk@kernel.org Cc: linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, Chao Yu Subject: [PATCH 3/4] f2fs: fix to handle segment allocation failure correctly Date: Thu, 22 Feb 2024 20:18:50 +0800 Message-Id: <20240222121851.883141-3-chao@kernel.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240222121851.883141-1-chao@kernel.org> References: <20240222121851.883141-1-chao@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791601545083506823 X-GMAIL-MSGID: 1791601545083506823 If CONFIG_F2FS_CHECK_FS is off, and for very rare corner case that we run out of free segment, we should not panic kernel, instead, let's handle such error correctly in its caller. Signed-off-by: Chao Yu Tested-by: Zhiguo Niu --- fs/f2fs/data.c | 7 +++++-- fs/f2fs/f2fs.h | 2 +- fs/f2fs/file.c | 7 ++++++- fs/f2fs/gc.c | 7 ++++++- fs/f2fs/segment.c | 46 +++++++++++++++++++++++++++++++++++++++------- 5 files changed, 57 insertions(+), 12 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 0c9aa3082fcf..c21b92f18463 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1416,8 +1416,11 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type) set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); old_blkaddr = dn->data_blkaddr; - f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr, - &sum, seg_type, NULL); + err = f2fs_allocate_data_block(sbi, NULL, old_blkaddr, + &dn->data_blkaddr, &sum, seg_type, NULL); + if (err) + return err; + if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) f2fs_invalidate_internal_cache(sbi, old_blkaddr); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index fbbe9a0a4221..6390c3d551cb 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3726,7 +3726,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn, block_t old_addr, block_t new_addr, unsigned char version, bool recover_curseg, bool recover_newaddr); -void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, +int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, block_t old_blkaddr, block_t *new_blkaddr, struct f2fs_summary *sum, int type, struct f2fs_io_info *fio); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 088d0e79fbbc..d6ec744f1545 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2262,8 +2262,11 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) case F2FS_GOING_DOWN_METASYNC: /* do checkpoint only */ ret = f2fs_sync_fs(sb, 1); - if (ret) + if (ret) { + if (ret == -EIO) + ret = 0; goto out; + } f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN); break; case F2FS_GOING_DOWN_NOSYNC: @@ -2279,6 +2282,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) set_sbi_flag(sbi, SBI_IS_DIRTY); /* do checkpoint only */ ret = f2fs_sync_fs(sb, 1); + if (ret == -EIO) + ret = 0; goto out; default: ret = -EINVAL; diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 6d160d50e14e..42e75e9b8b6b 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1358,8 +1358,13 @@ static int move_data_block(struct inode *inode, block_t bidx, set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version); /* allocate block address */ - f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr, + err = f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr, &sum, type, NULL); + if (err) { + f2fs_put_page(mpage, 1); + /* filesystem should shutdown, no need to recovery block */ + goto up_out; + } fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi), newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 8edc42071e6f..71f523431e87 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -400,6 +400,9 @@ int f2fs_commit_atomic_write(struct inode *inode) */ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) { + if (f2fs_cp_error(sbi)) + return; + if (time_to_inject(sbi, FAULT_CHECKPOINT)) f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT); @@ -2636,7 +2639,7 @@ static int is_next_segment_free(struct f2fs_sb_info *sbi, * Find a new segment from the free segments bitmap to right order * This function should be returned with success, otherwise BUG */ -static void get_new_segment(struct f2fs_sb_info *sbi, +static int get_new_segment(struct f2fs_sb_info *sbi, unsigned int *newseg, bool new_sec, bool pinning) { struct free_segmap_info *free_i = FREE_I(sbi); @@ -2711,6 +2714,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi, f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT); f2fs_bug_on(sbi, 1); } + return ret; } static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified) @@ -2719,6 +2723,10 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified) struct summary_footer *sum_footer; unsigned short seg_type = curseg->seg_type; + /* only happen when get_new_segment() fails */ + if (curseg->next_segno == NULL_SEGNO) + return; + curseg->inited = true; curseg->segno = curseg->next_segno; curseg->zone = GET_ZONE_FROM_SEG(sbi, curseg->segno); @@ -2783,7 +2791,10 @@ static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec) write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno)); segno = __get_next_segno(sbi, type); - get_new_segment(sbi, &segno, new_sec, pinning); + if (get_new_segment(sbi, &segno, new_sec, pinning)) { + curseg->segno = NULL_SEGNO; + return -ENOSPC; + } if (new_sec && pinning && !f2fs_valid_pinned_area(sbi, START_BLOCK(sbi, segno))) { __set_free(sbi, segno); @@ -3425,7 +3436,7 @@ static void f2fs_randomize_chunk(struct f2fs_sb_info *sbi, get_random_u32_inclusive(1, sbi->max_fragment_hole); } -void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, +int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, block_t old_blkaddr, block_t *new_blkaddr, struct f2fs_summary *sum, int type, struct f2fs_io_info *fio) @@ -3442,6 +3453,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, mutex_lock(&curseg->curseg_mutex); down_write(&sit_i->sentry_lock); + if (curseg->segno == NULL_SEGNO) + goto out_err; + if (from_gc) { f2fs_bug_on(sbi, GET_SEGNO(sbi, old_blkaddr) == NULL_SEGNO); se = get_seg_entry(sbi, GET_SEGNO(sbi, old_blkaddr)); @@ -3500,6 +3514,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, change_curseg(sbi, type); stat_inc_seg_type(sbi, curseg); } + + if (curseg->segno == NULL_SEGNO) + goto out_err; } skip_new_segment: @@ -3534,8 +3551,15 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, } mutex_unlock(&curseg->curseg_mutex); - f2fs_up_read(&SM_I(sbi)->curseg_lock); + return 0; +out_err: + *new_blkaddr = NULL_ADDR; + up_write(&sit_i->sentry_lock); + mutex_unlock(&curseg->curseg_mutex); + f2fs_up_read(&SM_I(sbi)->curseg_lock); + return -ENOSPC; + } void f2fs_update_device_state(struct f2fs_sb_info *sbi, nid_t ino, @@ -3573,8 +3597,16 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) if (keep_order) f2fs_down_read(&fio->sbi->io_order_lock); - f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr, - &fio->new_blkaddr, sum, type, fio); + if (f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr, + &fio->new_blkaddr, sum, type, fio)) { + if (fscrypt_inode_uses_fs_layer_crypto(fio->page->mapping->host)) + fscrypt_finalize_bounce_page(&fio->encrypted_page); + if (PageWriteback(fio->page)) + end_page_writeback(fio->page); + if (f2fs_in_warm_node_list(fio->sbi, fio->page)) + f2fs_del_fsync_node_entry(fio->sbi, fio->page); + goto out; + } if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO) f2fs_invalidate_internal_cache(fio->sbi, fio->old_blkaddr); @@ -3582,7 +3614,7 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) f2fs_submit_page_write(fio); f2fs_update_device_state(fio->sbi, fio->ino, fio->new_blkaddr, 1); - +out: if (keep_order) f2fs_up_read(&fio->sbi->io_order_lock); }