From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0E84AC11F6C for ; Tue, 29 Jun 2021 13:59:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EAB9261DAD for ; Tue, 29 Jun 2021 13:59:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234296AbhF2OCG (ORCPT ); Tue, 29 Jun 2021 10:02:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234275AbhF2OCD (ORCPT ); Tue, 29 Jun 2021 10:02:03 -0400 Received: from mail-qt1-x836.google.com (mail-qt1-x836.google.com [IPv6:2607:f8b0:4864:20::836]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A0D9AC061787 for ; Tue, 29 Jun 2021 06:59:35 -0700 (PDT) Received: by mail-qt1-x836.google.com with SMTP id g3so11868551qth.11 for ; Tue, 29 Jun 2021 06:59:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=2uFn6PKotRyoL/EKvc9hZ16Pkk9IJiulS9AMGBGQqf0=; b=La0ktyq8ut/I4zTJmlU9AODAv7RgJ+QBSGCq1XtTKYB4oYTFM8iYSQm38B04EKyqV+ +U1bDk4OJO05Ix6tYjUKlKMBG5PjEYxi20Ol0yBWp91kbjU7KZjlrQX7J6ETDHNY8y3K JGvSuLiWmdC7IlhdeLryxSKrYIz9eYP+j+HgvyK0q99g6/0L2smkn/nsjwtkyBJ87bVe Rsjq/hDMViMdV9FIgfAX02Z053RhLvLl/PogVK9TdnSJkkjNpjm9IaTQT6abfErFe1DA 5gFhqKcmMjMYfVV4+YsVKtYfLvrvYubEDAXQps4SiPrjI96S6yIYUAfZVxUcdjpNhw+m k6pA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2uFn6PKotRyoL/EKvc9hZ16Pkk9IJiulS9AMGBGQqf0=; b=j1OWrsuIX4gYvhpmFYC1CNOurSE9lEzeuDB9zRtyzJHDyS0PxV6ZTM6Hhr02f44edW sRur1L23UJLmUjG70ZaHSlMqIiw5ieAhE5KCHGKoPL4h1JwgWAYdRNRiuF/4A78vlfpp sH4KVXX3I11BoS+5+dciedIFAbALoC/ROwbEduUERcrTIWL2eMKNx1+UJ37/ZbUD/vuz PvoCQZuS6sb2xtEzgpLeGu7ja14NBy/4UV20XFUVM+5BCL9PMOTxuFNYVVAKOeBZaGBw H5KOE57c9qOVOimMGrAfrphKBw8s4s4ErAxFjg4awdWiYLXPNsYkplIXWQC9PXJy6S/Q hVqg== X-Gm-Message-State: AOAM532Uej8FQgPr01/BuXlJev6G0kP6z4Pb4WcDHgBImRzvdE/l0ypP RFf8KBMTeQEtTPUGP+AR0U3O7qisJ0hGEg== X-Google-Smtp-Source: ABdhPJzB3kjb1w+C0PCwYbRhbV1AeLxzp1l6rfNcvXs+p7qC+IhH8whbCnC5xwrtqTQwn5QzB3Kr4A== X-Received: by 2002:ac8:7dc9:: with SMTP id c9mr26612481qte.169.1624975174387; Tue, 29 Jun 2021 06:59:34 -0700 (PDT) Received: from localhost (cpe-174-109-172-136.nc.res.rr.com. [174.109.172.136]) by smtp.gmail.com with ESMTPSA id y7sm12201170qkp.103.2021.06.29.06.59.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Jun 2021 06:59:33 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 5/8] fs: add a filemap_fdatawrite_wbc helper Date: Tue, 29 Jun 2021 09:59:21 -0400 Message-Id: X-Mailer: git-send-email 2.26.3 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Btrfs sometimes needs to flush dirty pages on a bunch of dirty inodes in order to reclaim metadata reservations. Unfortunately most helpers in this area are too smart for us 1) The normal filemap_fdata* helpers only take range and sync modes, and don't give any indication of how much was written, so we can only flush full inodes, which isn't what we want in most cases. 2) The normal writeback path requires us to have the s_umount sem held, but we can't unconditionally take it in this path because we could deadlock. 3) The normal writeback path also skips inodes with I_SYNC set if we write with WB_SYNC_NONE. This isn't the behavior we want under heavy ENOSPC pressure, we want to actually make sure the pages are under writeback before returning, and if another thread is in the middle of writing the file we may return before they're under writeback and miss our ordered extents and not properly wait for completion. 4) sync_inode() uses the normal writeback path and has the same problem as #3. What we really want is to call do_writepages() with our wbc. This way we can make sure that writeback is actually started on the pages, and we can control how many pages are written as a whole as we write many inodes using the same wbc. Accomplish this with a new helper that does just that so we can use it for our ENOSPC flushing infrastructure. Signed-off-by: Josef Bacik --- include/linux/fs.h | 2 ++ mm/filemap.c | 35 ++++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index c3c88fdb9b2a..aace07f88b73 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2886,6 +2886,8 @@ extern int filemap_fdatawrite_range(struct address_space *mapping, loff_t start, loff_t end); extern int filemap_check_errors(struct address_space *mapping); extern void __filemap_set_wb_err(struct address_space *mapping, int err); +extern int filemap_fdatawrite_wbc(struct address_space *mapping, + struct writeback_control *wbc); static inline int filemap_write_and_wait(struct address_space *mapping) { diff --git a/mm/filemap.c b/mm/filemap.c index 66f7e9fdfbc4..8395eafc178b 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -376,6 +376,31 @@ static int filemap_check_and_keep_errors(struct address_space *mapping) return -ENOSPC; return 0; } +/** + * filemap_fdatawrite_wbc - start writeback on mapping dirty pages in range + * @mapping: address space structure to write + * @wbc: the writeback_control controlling the writeout + * + * Call writepages on the mapping using the provided wbc to control the + * writeout. + * + * Return: %0 on success, negative error code otherwise. + */ +int filemap_fdatawrite_wbc(struct address_space *mapping, + struct writeback_control *wbc) +{ + int ret; + + if (!mapping_can_writeback(mapping) || + !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) + return 0; + + wbc_attach_fdatawrite_inode(wbc, mapping->host); + ret = do_writepages(mapping, wbc); + wbc_detach_inode(wbc); + return ret; +} +EXPORT_SYMBOL(filemap_fdatawrite_wbc); /** * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range @@ -397,7 +422,6 @@ static int filemap_check_and_keep_errors(struct address_space *mapping) int __filemap_fdatawrite_range(struct address_space *mapping, loff_t start, loff_t end, int sync_mode) { - int ret; struct writeback_control wbc = { .sync_mode = sync_mode, .nr_to_write = LONG_MAX, @@ -405,14 +429,7 @@ int __filemap_fdatawrite_range(struct address_space *mapping, loff_t start, .range_end = end, }; - if (!mapping_can_writeback(mapping) || - !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) - return 0; - - wbc_attach_fdatawrite_inode(&wbc, mapping->host); - ret = do_writepages(mapping, &wbc); - wbc_detach_inode(&wbc); - return ret; + return filemap_fdatawrite_wbc(mapping, &wbc); } static inline int __filemap_fdatawrite(struct address_space *mapping, -- 2.26.3