Received: by 2002:a05:6358:d09b:b0:dc:cd0c:909e with SMTP id jc27csp2837743rwb; Fri, 16 Dec 2022 07:08:26 -0800 (PST) X-Google-Smtp-Source: AMrXdXus79Crbs3SwgIN1lSXujoNZ3tkwfVfg6276muDF/kIADr5CQPO/KrN1TNGJOt0GjsBbxQr X-Received: by 2002:a05:6a20:cd42:b0:af:d0d7:9f38 with SMTP id hn2-20020a056a20cd4200b000afd0d79f38mr2020767pzb.2.1671203306419; Fri, 16 Dec 2022 07:08:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671203306; cv=none; d=google.com; s=arc-20160816; b=Z0LjI3qoFT5SxeuJxzfMHHFy98KgA3fWY1hgVqw2Xm2f8igbqeVBfqevltH2DzpXgu 27tIp7FQEtibf+QkdTnDCYsODGgoX5N8M1RsE8vN6usGhJ6KIckD6F3fDrwMuTlqpGlu 2RGD8Awgzbuis+oLrX5FNnI18ZCR3fP1KXSEiCpLVybuxT2uFHqZEuBI9efUd3jQ/tOG 1litho/JymtgY/puSIkwB16kwzsrg8WvfZx0R+dqiQUctfo8raL2ikGDSn9L9WPTk32a kjtBVPWAtxICaEfcWimzW24X6bs5b9ibH6a9zykMVgCDBlTtZ78RV5zwfH6rEZU+LK5c cpAw== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=/nz1ABIr9FX4nrBYSQ3w8yAlDY1zba1m15vCTBuzyx8=; b=IJ3RgLbYPrFzxMrSjSue9gCQFQjDTtbm83mHtcgcT10b9ohskO1jHmNB+BCSpOSCkD 4BlFzVoDqx6CpSUH7LB2eSdcWNwcDoRjqbk1n7HfCsIH5uFu5lagX0uZ++35A5qFca9X EdQG2GYDy2CIqg8R+53ivH3KWf/0cLRkmKDTopSP/UOFk4AQKe8ftczNG88HR2Evf9qv 3lHCX1UjDYYlXOwYXtgXRlhLI1bfZsSLCVCuvkUAs/Z5RNlJrxr0IWEZC3YySOQgqi+T 0T3Hy8HdymptTB4WIJHXD2OxkVcldQ82eIRFkos45SfYQjgbz0QDLZmHj5rNyj4WSNyM 7hfg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=EuNl6i7e; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x18-20020a056a00189200b005783f1bf8dasi2940563pfh.95.2022.12.16.07.08.13; Fri, 16 Dec 2022 07:08:26 -0800 (PST) Received-SPF: pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=EuNl6i7e; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231289AbiLPPH4 (ORCPT + 99 others); Fri, 16 Dec 2022 10:07:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231338AbiLPPHZ (ORCPT ); Fri, 16 Dec 2022 10:07:25 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2185012639 for ; Fri, 16 Dec 2022 07:06:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1671203201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/nz1ABIr9FX4nrBYSQ3w8yAlDY1zba1m15vCTBuzyx8=; b=EuNl6i7eqKOHE/FjLPFfJeXIOMWNktyVqY5w9QZtqBU6cxx3IS1ATSmKeC3Uv2G4tfOOKJ 8KM0Y1HNefbdxNtbMsgm4m36M9V31kTJfLlwTk9IyJ1nJmwLm1V78Itxe9nsEIUo/d/wi+ +XhnWq9AXOmbSd63QpvUvS1MMGJQL08= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-190-oWHbi9_dOZOOPCoLKPZyzg-1; Fri, 16 Dec 2022 10:06:37 -0500 X-MC-Unique: oWHbi9_dOZOOPCoLKPZyzg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 7A83829AB3E9; Fri, 16 Dec 2022 15:06:37 +0000 (UTC) Received: from pasta.redhat.com (ovpn-192-182.brq.redhat.com [10.40.192.182]) by smtp.corp.redhat.com (Postfix) with ESMTP id 139B614171BE; Fri, 16 Dec 2022 15:06:34 +0000 (UTC) From: Andreas Gruenbacher To: Christoph Hellwig , "Darrick J . Wong" , Alexander Viro , Matthew Wilcox Cc: Andreas Gruenbacher , linux-xfs@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org, cluster-devel@redhat.com Subject: [RFC v3 3/7] iomap/gfs2: Unlock and put folio in page_done handler Date: Fri, 16 Dec 2022 16:06:22 +0100 Message-Id: <20221216150626.670312-4-agruenba@redhat.com> In-Reply-To: <20221216150626.670312-1-agruenba@redhat.com> References: <20221216150626.670312-1-agruenba@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org When an iomap defines a ->page_done() handler in its page_ops, delegate unlocking the folio and putting the folio reference to that handler. This allows to fix a race between journaled data writes and folio writeback in gfs2: before this change, gfs2_iomap_page_done() was called after unlocking the folio, so writeback could start writing the folio's buffers back before they could be marked for writing to the journal. Also, try_to_free_buffers() could free the buffers before gfs2_iomap_page_done() was done adding the buffers to the current current transaction. With this change, gfs2_iomap_page_done() can add the buffers to the current transaction while the folio is still locked. It can then unlock the folio and complete the current transaction. (If we just moved the entire ->page_done() handler under the folio lock, dirtying the inode could deadlock with the locked folio on filesystems with a block size smaller than the page size.) The only current user of ->page_done() is gfs2, so other filesystems are not affected. Still, to catch out any new users, switch from a page to a folio in ->page_done(). Signed-off-by: Andreas Gruenbacher --- fs/gfs2/bmap.c | 15 ++++++++++++--- fs/iomap/buffered-io.c | 8 ++++---- include/linux/iomap.h | 7 ++++--- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 3bdb2c668a71..11115fce68cb 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -971,14 +971,23 @@ static int gfs2_iomap_page_prepare(struct inode *inode, loff_t pos, } static void gfs2_iomap_page_done(struct inode *inode, loff_t pos, - unsigned copied, struct page *page) + unsigned copied, struct folio *folio) { struct gfs2_trans *tr = current->journal_info; struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); - if (page && !gfs2_is_stuffed(ip)) - gfs2_page_add_databufs(ip, page, offset_in_page(pos), copied); + if (!folio) { + gfs2_trans_end(sdp); + return; + } + + if (!gfs2_is_stuffed(ip)) + gfs2_page_add_databufs(ip, &folio->page, offset_in_page(pos), + copied); + + folio_unlock(folio); + folio_put(folio); if (tr->tr_num_buf_new) __mark_inode_dirty(inode, I_DIRTY_DATASYNC); diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 8ce9abb29d46..517ad5380a62 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -580,12 +580,12 @@ static void iomap_folio_done(struct iomap_iter *iter, loff_t pos, size_t ret, { const struct iomap_page_ops *page_ops = iter->iomap.page_ops; - if (folio) + if (page_ops && page_ops->page_done) { + page_ops->page_done(iter->inode, pos, ret, folio); + } else if (folio) { folio_unlock(folio); - if (page_ops && page_ops->page_done) - page_ops->page_done(iter->inode, pos, ret, &folio->page); - if (folio) folio_put(folio); + } } static int iomap_write_begin_inline(const struct iomap_iter *iter, diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 0983dfc9a203..743e2a909162 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -131,13 +131,14 @@ static inline bool iomap_inline_data_valid(const struct iomap *iomap) * associated with them. * * When page_prepare succeeds, page_done will always be called to do any - * cleanup work necessary. In that page_done call, @page will be NULL if the - * associated page could not be obtained. + * cleanup work necessary. In that page_done call, @folio will be NULL if the + * associated folio could not be obtained. When folio is not NULL, page_done + * is responsible for unlocking and putting the folio. */ struct iomap_page_ops { int (*page_prepare)(struct inode *inode, loff_t pos, unsigned len); void (*page_done)(struct inode *inode, loff_t pos, unsigned copied, - struct page *page); + struct folio *folio); /* * Check that the cached iomap still maps correctly to the filesystem's -- 2.38.1