From patchwork Fri Apr 4 18:14:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joanne Koong X-Patchwork-Id: 14038728 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id B742BC369A1 for ; Fri, 4 Apr 2025 18:14:57 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id B77586B000C; Fri, 4 Apr 2025 14:14:55 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id AF9F76B000E; Fri, 4 Apr 2025 14:14:55 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 973BC6B0010; Fri, 4 Apr 2025 14:14:55 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 765E86B000C for ; Fri, 4 Apr 2025 14:14:55 -0400 (EDT) Received: from smtpin26.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 9855B8014C for ; Fri, 4 Apr 2025 18:14:56 +0000 (UTC) X-FDA: 83297162592.26.1331162 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) by imf19.hostedemail.com (Postfix) with ESMTP id AD8861A0004 for ; Fri, 4 Apr 2025 18:14:54 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=jc91jFfU; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf19.hostedemail.com: domain of joannelkoong@gmail.com designates 209.85.214.180 as permitted sender) smtp.mailfrom=joannelkoong@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1743790494; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=fl8QoDkWZfm8DTTKNPo/wCbrE6y7cAAPOUh+ANXI66Q=; b=pGGsWxesKavrS/RFifuEgyXSm6gh2i5BFsLRs5JILwRYjnoNBKQKRpHFIY5RYIeaPKxFCr NvGds1mZOpE99+8nPrhAVF2WkK4aSTibXOBHW0TrwWp+9vN7ZEMN8vx+sv+XmzQYF44/Mg vdCOHzGlLL9S0/fPGfIiomk/nmr3aRI= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1743790494; a=rsa-sha256; cv=none; b=Nr5BZ9VbyLP/r/JhkJTnrx1Ufgl9KYX6XFIfUhuE8tbUBn4rT8tPuchUdnT8VfqkWMp6Fr p1LSUPp90ajcYeW6+zErxM24qF2SPsm7J+XHlfI2OU1oy5jGRFEtPCha9jEt1Cf1yrkizx lf/LPnrhzKD3hRO2Tde8XffeXch3MJ4= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=jc91jFfU; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf19.hostedemail.com: domain of joannelkoong@gmail.com designates 209.85.214.180 as permitted sender) smtp.mailfrom=joannelkoong@gmail.com Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2243803b776so34401185ad.0 for ; Fri, 04 Apr 2025 11:14:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1743790493; x=1744395293; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fl8QoDkWZfm8DTTKNPo/wCbrE6y7cAAPOUh+ANXI66Q=; b=jc91jFfUBKoWqezp6jm2flAcz55lTQ7DXu+mcpghmTbzgzoUMWexihpLgUda3np/Jq Z4g3l84NmFLCFhe6EdBvAjH86MEcfbNOcUXn3T9CAD1yLYN7LaQBr2zXBNDJZ+Rcxcte /Rw1zfwm4Pbf2NLFHc8aww81iUHqPGDyPXLDe8K/QteoV3X5bMmljERJJMesBm/pZzf7 McXHhzHy0CpcCgur4zSu5nulAcTsA1JyeSbeXLah5ONuRZ60iEs3SEhfmvK2hWnywc7y B13FtiiYCDA8SYtA66Q72yRo5UPKmKvWew1DMAuivy593V0g/3bl/Bo9ey0EUbVLnY1G A9qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743790493; x=1744395293; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fl8QoDkWZfm8DTTKNPo/wCbrE6y7cAAPOUh+ANXI66Q=; b=Qac/2sU4phRG9AsriJlDpDGqwf+XuV3uvKuWQ+pgblRve94/GEr0yzOrVFhx4tjdnS rk5fGwbkpQXTrq32+NuSO0NytkRjvnKZvzuZaoNFPlUDpre2fKRT3lRH6P+580Exoesp h1UG+SMe+5GNHN8qXPZO7GR3oREsdCGA9PZ6/1cBK+pDGkIWXfAdWbKpe4kajsNl6ZmV s5jUihEuVT8gsGgk/HOpl3yd6gFYudV/4Rzny/LWHeXnXqxAvV8tbBATrCeN7CNMMjha RJdRkFE1b08/V5w5gQWEN8W+RkrPW7nx8iMpENlO4/Fio9ZLt8+DW8NarwFkXpCeMnDT SQ0Q== X-Forwarded-Encrypted: i=1; AJvYcCXEr6bOYCSMRec1FsbjDOi0Hxe2p6YqX1DGBSyBzepcDXwRZhk1YnqDnA18HDVcAaIEZjeKlUrnyg==@kvack.org X-Gm-Message-State: AOJu0Ywa7zzR2oGibjyxFVOsP2z9YFgRWbj6fLhGmVbXlcAtkfLVTKCm 8OCSapCaGeZsGf8w2igTaxJyA3wYKzudXiEnPoBDnDx+HhvoARmu X-Gm-Gg: ASbGncsqsaDcJybt7cBU0ll2OsTEzu9ow+UXManHCjoGda/RPXEA7xsE2FljuMjZho3 Er/E2i4YejDyJWOaISUNiQG7POl32rpEGebL3e/wADSkzDJ3Pt4t16DTx8KjbGsXDMulKXA3JJQ 8GJcJHTLUWQUCswpybHKgtD3y4mhzHJEUwEqgViTXuqv59Iq7vYp/vI2BO+f4WHSBW97N03dUa4 U5+a0IHtIlzynEsXdgtHrf7+SnJJNFgnlunIqTLWWR4dnL7E3jAGaA0rXYfcmfKJI6FX4zir/WJ 5RpAA53XTKsNP+WmRui0T2EGd+Cr3C1VJ5i2+94= X-Google-Smtp-Source: AGHT+IFQWuRUYtqQ9PYQeKB91kmnnsp+MBvvTBYSFVfsYjy2EJYrTFwForkG0Fjr8XsdVucFtVIK+w== X-Received: by 2002:a17:902:ce84:b0:223:397f:46be with SMTP id d9443c01a7336-22a955881b8mr5396015ad.47.1743790493629; Fri, 04 Apr 2025 11:14:53 -0700 (PDT) Received: from localhost ([2a03:2880:ff:5::]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2297866e173sm35372415ad.192.2025.04.04.11.14.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Apr 2025 11:14:53 -0700 (PDT) From: Joanne Koong To: miklos@szeredi.hu, akpm@linux-foundation.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Cc: jefflexu@linux.alibaba.com, shakeel.butt@linux.dev, david@redhat.com, bernd.schubert@fastmail.fm, ziy@nvidia.com, jlayton@kernel.org, kernel-team@meta.com, Miklos Szeredi Subject: [PATCH v7 1/3] mm: add AS_WRITEBACK_INDETERMINATE mapping flag Date: Fri, 4 Apr 2025 11:14:41 -0700 Message-ID: <20250404181443.1363005-2-joannelkoong@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250404181443.1363005-1-joannelkoong@gmail.com> References: <20250404181443.1363005-1-joannelkoong@gmail.com> MIME-Version: 1.0 X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: AD8861A0004 X-Stat-Signature: a5gjk38xs4p7bpdrcesodk517np6cz4u X-Rspam-User: X-HE-Tag: 1743790494-86425 X-HE-Meta: U2FsdGVkX1/FgdADbYfnZ5H/j2LE07nnhDQEjg2x8VEjw2M3dc5NyWqZpBQ2XsWJCUOt8B3V/Vf2V67smoDKsrszviqDFO7fQ7W0YG9ZyWaweJdP0JEGXeMliPiKnwScRHUmtOuEumnd4/AaxKzLfukFGLiZHCieZZe+48a9HTyUvVrNGyLgoV4rg+qv82f2Y6I2xSpF/WEs5oHWNCCr1OszPxB+Q9OpmjUWfVrhVkdsAJE62qZK9EAigQ2L4L47tlW0m9/JG0rOSxMk5X2hZ4KLaR23pVkHh/MYgaC14bHT9z1vEOA2THEqfFMQinnlKl3JtzYcf+Eahtus+FzL9WRGiJMrEieEwbgP+M7MsHI4/PtL0hfkrG9AmkTWjYEoab/lLIqgmlLe1LjnIxocVzJRfmnAGQjrweDZCe6DbEtH88lagRRYQ7ZRN+axWF76Dnp0zr6FiJOq8ZmEMnZ15NrHS1J+reJZprFDfvvP/uWdZwrRCcQPfQW7HJk25NkPFtZl59C/oG9CiAZlHEyc32NZRFWZmU7ui2pz8kfQZ1zKDpLFMaVp1YbAicRktd9Hom78l6Eaf0HPGlht312YQaSaTmxbxcoPobWYU4g8bm0z8iBEKv3QgTqtvdLXShNOyU9eNjoALRfMEBWtfWhwNHA0hJxWM96o8D5s6jaB1mFU9wRXC7+AAdtnrfhusqBWIwwLfrrn7XvXuUXvsCg9XCdlzFGTQFBxwsl8G7GESJIn/lsBgbz8WuP1ldBxC/bp3XSlYztp+yDMBwdSMzWv7R1KaeWd6kXIpj1vstxTTPNIvBKDUy1k9B/JbCYESgY+4OoDWkmcIAyXr4g2UWNHWejNMxIA3u1lv8fcDCW2k/AklNZ2UmliteVNVXg7DxTB6N5Wl6GKXV3xnbfPoR342I9npzTH+8xRUlxTt0wEAlIT6uLlSRMhr1xRe4j8ceCaZdPomPar1WcA97qdyWT Ak9Q+cNJ LRhSNpjYzI0L/NKmqX+H/0HXgTC+9F7vOaMVXUI7HuFNkCE/m0qoACCE+OZuj4uL95kViSpCF7nouCUP9PdV6NEEdGS6BWfUcehUSwdxvJIXqkvKnT5L9KEzirLYYClnOM+FkpQlmeX5u7Iz+3NHFWa+K5FYwYAN5o+Wdj2/PBSTSLxMVm9NVwTHV98jDser3/WiX1R+/sHwKFxL8aLFqBdj7wxqbOvxkppuUQZusgaLSm2LVClCtVPWo6CLXxdiaLtIo9u7Ok9jMMK8lps6XPIufRpsRYIC7gtc32ZW8UBKrNhUHoi1ErDVQ8Ib2ceLqnNk9iomaPtezJcXcU6SjjVj/YZ0rJlEWK+44vaMHihwJHiBSxPwPCw5ey1//7TMDsBwWMxrvrp94vHSSONfChij/OVvn8CpkR4202Gz1GGIPwkAmmBHN7SM+cmfS4yKKzomcrvDknLBxnYYq4DR0kKm5Y1Q6SgR5jUl+4D2inJCoq5PFKY9CyDImQ6pBmQI2Zxe3 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add a new mapping flag AS_WRITEBACK_INDETERMINATE which filesystems may set to indicate that writing back to disk may take an indeterminate amount of time to complete. Extra caution should be taken when waiting on writeback for folios belonging to mappings where this flag is set. Signed-off-by: Joanne Koong Reviewed-by: Shakeel Butt Acked-by: Miklos Szeredi --- include/linux/pagemap.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 26baa78f1ca7..762575f1d195 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -210,6 +210,7 @@ enum mapping_flags { AS_STABLE_WRITES = 7, /* must wait for writeback before modifying folio contents */ AS_INACCESSIBLE = 8, /* Do not attempt direct R/W access to the mapping */ + AS_WRITEBACK_INDETERMINATE = 9, /* Use caution when waiting on writeback */ /* Bits 16-25 are used for FOLIO_ORDER */ AS_FOLIO_ORDER_BITS = 5, AS_FOLIO_ORDER_MIN = 16, @@ -335,6 +336,16 @@ static inline bool mapping_inaccessible(struct address_space *mapping) return test_bit(AS_INACCESSIBLE, &mapping->flags); } +static inline void mapping_set_writeback_indeterminate(struct address_space *mapping) +{ + set_bit(AS_WRITEBACK_INDETERMINATE, &mapping->flags); +} + +static inline bool mapping_writeback_indeterminate(struct address_space *mapping) +{ + return test_bit(AS_WRITEBACK_INDETERMINATE, &mapping->flags); +} + static inline gfp_t mapping_gfp_mask(struct address_space * mapping) { return mapping->gfp_mask; From patchwork Fri Apr 4 18:14:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joanne Koong X-Patchwork-Id: 14038729 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5EE57C3601A for ; Fri, 4 Apr 2025 18:15:00 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 5D17F6B000E; Fri, 4 Apr 2025 14:14:58 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 57FD16B0010; Fri, 4 Apr 2025 14:14:58 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 3D5C56B0011; Fri, 4 Apr 2025 14:14:58 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 1F4BB6B000E for ; Fri, 4 Apr 2025 14:14:58 -0400 (EDT) Received: from smtpin01.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 513C9B7F94 for ; Fri, 4 Apr 2025 18:14:59 +0000 (UTC) X-FDA: 83297162718.01.E1B8AB1 Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) by imf24.hostedemail.com (Postfix) with ESMTP id 63548180003 for ; Fri, 4 Apr 2025 18:14:57 +0000 (UTC) Authentication-Results: imf24.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=DIJDPoKj; spf=pass (imf24.hostedemail.com: domain of joannelkoong@gmail.com designates 209.85.214.169 as permitted sender) smtp.mailfrom=joannelkoong@gmail.com; dmarc=pass (policy=none) header.from=gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1743790497; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=j3pkaibd9TvSbeaSTyou9b7M9WsE2MzhKDeNIDnWjds=; b=zAOHelAhWICZAtUpnqJTVVbRyBInHpM0pvjHyvq86XQbFi49KYwGn/uvZfQF+LDyDNakMc ymX9zmBaEE1+2WvBg2rqeV3UghN8H4m1HwXkZFyGJL+yT+XhX/94OWzZ91FyQJccgFQkrc WVzbpWp22jgkn5f5m5LemRIsEnjyZ6E= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1743790497; a=rsa-sha256; cv=none; b=3BTxWJ3a9ivmydZuC56tn5rROtK0rZc4Jb+peuGd6C7FkF6saP4mcp9o8AorglVMgAje74 b0TBHAyfAxGfxwgdZzUq4yHFIXkQBRIE2D/sShtIxaXBLgeiYlFJWMTv0+zR6datf924ao I4iMcXgFbPmFIakir2LcBTthOBKHh/0= ARC-Authentication-Results: i=1; imf24.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=DIJDPoKj; spf=pass (imf24.hostedemail.com: domain of joannelkoong@gmail.com designates 209.85.214.169 as permitted sender) smtp.mailfrom=joannelkoong@gmail.com; dmarc=pass (policy=none) header.from=gmail.com Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-223f4c06e9fso22196105ad.1 for ; Fri, 04 Apr 2025 11:14:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1743790496; x=1744395296; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=j3pkaibd9TvSbeaSTyou9b7M9WsE2MzhKDeNIDnWjds=; b=DIJDPoKjFvbfWp+TX/vzAXWM4nXWqHan6hqERwkt9XmZZ9hXYVmsdFfmoeJdD3R3eI Oxj4FSqbh12mZMU/PYfW1rg6zTGITB9NU4P2mMIk94eJidYp2HZFRRLHenxk/EGiZxOU ++VNGulMOe5oVTygF78C89p0ZMxpgX1zG+vPaLGsSzA+/ypQhitwqkNkggehjXe0uvyf /NcyG1F+20pfgP3sc+ZVGPH+T2Q9TeTTyVGd7Hz8NQDyEU0VMfaqpay6/MOCEx6a1XqR 0TZiyYVZkOkSyNkGk5/JDVkbM+LqjPk6XdXk3mwCGSUf7pZeHYwJaHY1OTWVzceRn5a7 KRHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743790496; x=1744395296; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=j3pkaibd9TvSbeaSTyou9b7M9WsE2MzhKDeNIDnWjds=; b=WOYspWBJIiCI41Tp0s0qV4XnqzJjLZNOdcfJR5tX2T3PiWOsNhTfPFrbxLgXfFD9JV Wm5G9Yihe7oKF1Jsfo+DaUnRTetJJ+CEzCxdXXmHzE7jqRfOS5ePlnqq87Ua2msR3V8N mB8VwVy/ltNIqtF4O1q0kQcEVcM+SlGqO+3rPLHTC44SBK+qdoPbGlKGimwrniJKiHJO 2NC2/tLdg4FOwEq9qfPUldtByj6Q0uxVPiFn0srE8RKnaAPnDBOiplNnbTsaFLNI9TpA jiIqnz58ZRC6UAhiuwqKkj5x3j10By2zvxJlqU+5jceunYFIriyVet5pkaDfFXwHEwoD ihcQ== X-Forwarded-Encrypted: i=1; AJvYcCU5crj6swuFHQScgzbzwzFgIXoXEsK0qL8IqE8JclG2yqluyH7Vl02OnbcyYi5nZYBOJDs2Zzctwg==@kvack.org X-Gm-Message-State: AOJu0YzS+PMBHMYihFNacGfv5byeRu4Ljb1V6Ft6vscehRm/b9VBasU3 52drGhcR60dtm/IUfEj9sQFZEmW+muDPHePtwAqODVHuCJVUqfH1 X-Gm-Gg: ASbGncueu5EwNDsqHa3XfehkkWRUxdSHaRKOmYG+KYZ/VkYsP6FuNf8oIOrflt8nH0J pW8n+AESTS+9t1PJ4H00tlfNUKnVu1gDCbFgV7lKwfIha+3oKNPnZ3Hl1gzH8vwEi9vdGnpDpiD chOnO/2oKt61rtyir3ghsoBXGy6kFnrbeBqhn3mvtqzcoUrbcEdKX4x3DFHPchuQwBeL5mCXdwF oiS0vAaTK2Fkm5IZVKax7laLj+PJOGdcipi8oQEMbVdqAuq4RMf4hrIPNGQSwsnKotoLqw5aHNC M/0qIjQDZIcH1lnxeltsErbXn20Vi62ZKK1HmxF7 X-Google-Smtp-Source: AGHT+IHGa8Y8SuMd3n9iFFlNcrZys9TGj4hZu9tApDIQ/6HUQ+OVxypeR21UpAV43u4nzDqgfgcvCA== X-Received: by 2002:a17:902:d54f:b0:21f:58fd:d215 with SMTP id d9443c01a7336-229765d1b7bmr123372805ad.11.1743790496199; Fri, 04 Apr 2025 11:14:56 -0700 (PDT) Received: from localhost ([2a03:2880:ff:49::]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-229785ad943sm35587075ad.23.2025.04.04.11.14.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Apr 2025 11:14:55 -0700 (PDT) From: Joanne Koong To: miklos@szeredi.hu, akpm@linux-foundation.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Cc: jefflexu@linux.alibaba.com, shakeel.butt@linux.dev, david@redhat.com, bernd.schubert@fastmail.fm, ziy@nvidia.com, jlayton@kernel.org, kernel-team@meta.com, Miklos Szeredi Subject: [PATCH v7 2/3] mm: skip reclaiming folios in legacy memcg writeback indeterminate contexts Date: Fri, 4 Apr 2025 11:14:42 -0700 Message-ID: <20250404181443.1363005-3-joannelkoong@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250404181443.1363005-1-joannelkoong@gmail.com> References: <20250404181443.1363005-1-joannelkoong@gmail.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: 63548180003 X-Stat-Signature: t44ccwfy9co9sxjscuuuax9th4e4wfyy X-HE-Tag: 1743790497-839069 X-HE-Meta: U2FsdGVkX1+QcW+DE4a4Nwep0lvU5tsAbrncwluKW0pICIgIrWC5MMqMYKZxgIng/ASkZwEOqjsH34aaXOCnFyCARn0y/A0l5gaJjTi5H667lY28A7YDJ1umQFscw4IwfzSjrSeYJm8hh0EOe3pCQMNz7bhwMIsN3Ww9/wj0ktslKX8/2nZ83NFpQinu8QoI/dHxcA+Zp7B8znMriZP3EwsdfGbH4LzwkIrU1f4P/oLThIB1nKa/uyb4vU2ySiUBdcG+/7/DF46lDoUDothhI/XlpDGwa4mNFndhcxFYVjYUgdjSb7CkL8G7Y4oeVEFYLXL4pPHhKR/RoF6QxZDYDd13r4blW9TxhGlKLri/2DYBYp/izKsi1IAERPJUEQgFXJleHZ+8uC5QCMwbDxm3qZ4JKqSn9zU1M0IGbB9GB+/LbLCHrKzxkpXzhSYUAj/Xb+etU6fGI+VQnYeXfr+0877POesjgXa0gRapyQ9aXwSdZRUwfqoPf1WD+8+CWDMaMXfEdTBOWhnhy7BZeeSE89vF67GoTwdonSVz4Yw6iuZi+MLa54MSDnvaPuW5wtn9mOoU+bM05gJpTWeNUMpkG0JoDkwerZF9SrRSQ/J4OQnID72BKD7baEbpR/9EC62YxxOpE155EBfNgBv7h47PHJ1rfovbGjoPxArdOwSULBQsw3qlF9LOEKGnSnrY2Gvr6BzVt5zVGt8EqdEaKempJ0rK0pcg2y1ewiuMpOFeI1O6gTpr754SvH8mzeV+FpvMqD6khKVA6ULMzGoPctWdfxuM0BxvSsjx67yNpCn4XTlicg+KJKXiXj6QPoE4LbByFOrsBSv4YCDsaHutZUN2QvVe0S5jbvmyj2PHiTzhHUWAZyWJdbxti3TVQAvLislwW3xX8OuDX1lVz8ZSzV5fi3nq1iV3Gd9OV0dRC5mzcnHDjMd/shBrAYpEVfLdrxngiVASVabOTh98kZmPjFE M2dPZrKw HNwfOm2xyDKMWzM9zE184BBgYnYuoD2HfXkLReFbU3Wh9g/z6EXz8+mlNx9oTukGnTnVRqfOpxSfFJyOXVSfdOZ6abA46H/rOW5GNKldEpL3qZvnHjDCWBSwZsIYlfeqerFwRZ1FntSu7iCvYZ6DefQcuVCDJfDeVIucx41ba+ULiG1BC6MBHGvOn8VOGQj4rtXyUtGl9x3WmSA8+yRgRR3/OjTfmig9byBhbRYrNF+/MMAuiMQs2kpBVXJRRRDZf3fbYONrSZNRG65PJM/pAx5pd5K4OL2zZnQN0h7Kc8/dTydBGLQlREPJanuO8qlmeV3P++mcBovuTrXAiMDxNwNeUY1Z9nOhW2H6rVuG560Eb4AM3FeE828cO7EiQ76JxRsbpCAzQPXvW9/L1CroZXJpBP3yhECpLUj6s3JwtEYIJ8nfURioEZBlTNT4rnYyzNXeAPcE2YTvoB68= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Currently in shrink_folio_list(), reclaim for folios under writeback falls into 3 different cases: 1) Reclaim is encountering an excessive number of folios under writeback and this folio has both the writeback and reclaim flags set 2) Dirty throttling is enabled (this happens if reclaim through cgroup is not enabled, if reclaim through cgroupv2 memcg is enabled, or if reclaim is on the root cgroup), or if the folio is not marked for immediate reclaim, or if the caller does not have __GFP_FS (or __GFP_IO if it's going to swap) set 3) Legacy cgroupv1 encounters a folio that already has the reclaim flag set and the caller did not have __GFP_FS (or __GFP_IO if swap) set In cases 1) and 2), we activate the folio and skip reclaiming it while in case 3), we wait for writeback to finish on the folio and then try to reclaim the folio again. In case 3, we wait on writeback because cgroupv1 does not have dirty folio throttling, as such this is a mitigation against the case where there are too many folios in writeback with nothing else to reclaim. For filesystems where writeback may take an indeterminate amount of time to write to disk, this has the possibility of stalling reclaim. In this commit, if legacy memcg encounters a folio with the reclaim flag set (eg case 3) and the folio belongs to a mapping that has the AS_WRITEBACK_INDETERMINATE flag set, the folio will be activated and skip reclaim (eg default to behavior in case 2) instead. Signed-off-by: Joanne Koong Reviewed-by: Shakeel Butt Acked-by: Miklos Szeredi --- mm/vmscan.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index b620d74b0f66..d37843b2e621 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1187,8 +1187,9 @@ static unsigned int shrink_folio_list(struct list_head *folio_list, * 2) Global or new memcg reclaim encounters a folio that is * not marked for immediate reclaim, or the caller does not * have __GFP_FS (or __GFP_IO if it's simply going to swap, - * not to fs). In this case mark the folio for immediate - * reclaim and continue scanning. + * not to fs), or the writeback may take an indeterminate + * amount of time to complete. In this case mark the folio + * for immediate reclaim and continue scanning. * * Require may_enter_fs() because we would wait on fs, which * may not have submitted I/O yet. And the loop driver might @@ -1213,6 +1214,8 @@ static unsigned int shrink_folio_list(struct list_head *folio_list, * takes to write them to disk. */ if (folio_test_writeback(folio)) { + mapping = folio_mapping(folio); + /* Case 1 above */ if (current_is_kswapd() && folio_test_reclaim(folio) && @@ -1223,7 +1226,8 @@ static unsigned int shrink_folio_list(struct list_head *folio_list, /* Case 2 above */ } else if (writeback_throttling_sane(sc) || !folio_test_reclaim(folio) || - !may_enter_fs(folio, sc->gfp_mask)) { + !may_enter_fs(folio, sc->gfp_mask) || + (mapping && mapping_writeback_indeterminate(mapping))) { /* * This is slightly racy - * folio_end_writeback() might have From patchwork Fri Apr 4 18:14:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joanne Koong X-Patchwork-Id: 14038730 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B635C36010 for ; Fri, 4 Apr 2025 18:15:02 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 47A0F6B0010; Fri, 4 Apr 2025 14:15:00 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 3B5516B0011; Fri, 4 Apr 2025 14:15:00 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 1E13D6B0012; Fri, 4 Apr 2025 14:15:00 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id E92986B0010 for ; Fri, 4 Apr 2025 14:14:59 -0400 (EDT) Received: from smtpin10.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id 24EAA579A4 for ; Fri, 4 Apr 2025 18:15:01 +0000 (UTC) X-FDA: 83297162802.10.F5B60B7 Received: from mail-pl1-f177.google.com (mail-pl1-f177.google.com [209.85.214.177]) by imf15.hostedemail.com (Postfix) with ESMTP id 33D83A0008 for ; Fri, 4 Apr 2025 18:14:59 +0000 (UTC) Authentication-Results: imf15.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=PhrWraYa; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf15.hostedemail.com: domain of joannelkoong@gmail.com designates 209.85.214.177 as permitted sender) smtp.mailfrom=joannelkoong@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1743790499; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=Ro6dJ4GoZF5GCiGEcpg9UJuR608idQkDGAMhopK9Xk8=; b=voJP9NgTHPwu9gUzHlSax2SGRyuuk7fhFseX7qknU1X2Y39jmH9Og7iRAor3k8/foLaqLJ OWQOeq+UEKgPk+5I96wytiHdacTooWSu0lsjqpW+qhvborXSNRFpERE1eynZYDytgwnGa2 sV/bauxFot4GJ1jwZ/L8gvFPNkym94s= ARC-Authentication-Results: i=1; imf15.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=PhrWraYa; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf15.hostedemail.com: domain of joannelkoong@gmail.com designates 209.85.214.177 as permitted sender) smtp.mailfrom=joannelkoong@gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1743790499; a=rsa-sha256; cv=none; b=AgmkkU42ieNo0mIOkh3Vj7Am+z7N0WvwT48Jnx9ZWz8j1We/W0LaGTWaaLn0VpmP1eCt6M hi3tGs0hc93VqpHZ2RXaWj7I5QX2QcioXVFt+5eBkHj/MeFd/l5uuSp/2o4plFtCnh9J5A xNj85onNLRaz5K2EijxUPhe1IF3svWA= Received: by mail-pl1-f177.google.com with SMTP id d9443c01a7336-2240b4de12bso32739825ad.2 for ; Fri, 04 Apr 2025 11:14:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1743790498; x=1744395298; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ro6dJ4GoZF5GCiGEcpg9UJuR608idQkDGAMhopK9Xk8=; b=PhrWraYa5IiZQ4OTRyndX7z74rf8xkiw001HM3ZTPbbf705AY2IgiQOFf/IhBs3U3/ 0D73pYrFlEOOXmqRqFHcANEpTFogutkGM1KKqiRfPeEQ5IAQf5xGkOCJ7wEs2mfb9wpY HNZAbdl0/KYau27JJwlQAWLpy5yvd2Y25wInNy9nMJjdY7wIdjh28Q3NYc1M/FDTXhtR SYPuB/+UZQinddo9ThhHYa15S2dUpFq2b29niMndHTXv8dA0LhHrzPHJEdzYpv+bSfZG lZiT5tBz546fTwKndkDwpR1gwniyLrrJkqrp43ILVZXRTxY4kLUaasD0ctTE6uEz7yvO hF9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743790498; x=1744395298; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ro6dJ4GoZF5GCiGEcpg9UJuR608idQkDGAMhopK9Xk8=; b=A4j93Vi+/YFg26k29hboOU71pJLEag68Muh/BcI6QV6Jtrsf00e/DkUf5pZaVbxwci kWevmCIZC7D+Qx0Tjd3oWwHUIOShATBvglTe9+TeKDHWI8O5pttST4j6v/YHRuo0bAPU xUsKBMlEXXsoe+NxC2L9xyAypFCURETmycHyny5dM6+vwVttq6i86LYgXHR1tgtR9mgI vip4e/E2pBRg231AGlGvx8LHo8Kr8ACK2NIa0KgLJV3yYP7VVof1jgxpuOuzFQLW+M7e a2ISrhCZsFVP/Ij8z6UXU3hvtF5Tafw0w9gkNl9qjQji9NJLQD0kbus7MGx5DUcW/hYX fAkA== X-Forwarded-Encrypted: i=1; AJvYcCUseUl1uYrq2Vcu2ea7VzCtj/ysNq/MbuCRfw/+kIiTPBixyLp7SnSgDQBXd2m0AJ6HY41f+bapJQ==@kvack.org X-Gm-Message-State: AOJu0Yz1/hBwsFW5a/228mD+/gl4KOsT3sN6eGQN1XVka3++ZTH9C5kx Tm3TB1ZtdMMMzj4D8fjVmKAVLuBZawyDZT3OJ2GlfI29Pq0sX6Ue X-Gm-Gg: ASbGncsZH0k/R/r8qlFPLPUpxS0+BihfaxJCv+rQuiOmNIrtLeKADkAKG+t49DDtCBD 1KDzGim9FK79tjq6xRUCHL9Mo9P4eSYW5wnPKv0AQx+gdDSj87ef8PJAUQEAvu8Fqd0McRhGq6O f7gLed8f1olwE5fqzII/QSOwgnebJiz6OLI9jEVudHGl8S9UD81gEufzOyvgByWazyczRrDaGgQ wMiPtKFHI0zWaaKLXyvlvQbgD11PpI01wvhyH2hMjIR/lq2UgRt5GOUc2vvzgsCQnKaUCZ0YqBz qvll5M9SjUPV6ZyIH7XqddjsUKpQDV6FB/JH22s= X-Google-Smtp-Source: AGHT+IGkN0PRjt/OSbDEHn8IomnvUJ855I+Gfmi28p8+UH+Wi59dJqBErOB3hRXspe1aOB+8PEZLGw== X-Received: by 2002:a17:902:c94e:b0:224:5a8:ba29 with SMTP id d9443c01a7336-22a8a0b38bdmr46533995ad.43.1743790497957; Fri, 04 Apr 2025 11:14:57 -0700 (PDT) Received: from localhost ([2a03:2880:ff:3::]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-229785bffedsm35700125ad.63.2025.04.04.11.14.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Apr 2025 11:14:57 -0700 (PDT) From: Joanne Koong To: miklos@szeredi.hu, akpm@linux-foundation.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Cc: jefflexu@linux.alibaba.com, shakeel.butt@linux.dev, david@redhat.com, bernd.schubert@fastmail.fm, ziy@nvidia.com, jlayton@kernel.org, kernel-team@meta.com, Miklos Szeredi Subject: [PATCH v7 3/3] fuse: remove tmp folio for writebacks and internal rb tree Date: Fri, 4 Apr 2025 11:14:43 -0700 Message-ID: <20250404181443.1363005-4-joannelkoong@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250404181443.1363005-1-joannelkoong@gmail.com> References: <20250404181443.1363005-1-joannelkoong@gmail.com> MIME-Version: 1.0 X-Rspamd-Server: rspam01 X-Stat-Signature: u7gzn63j44upt6betuxnss1o9kncorke X-Rspam-User: X-Rspamd-Queue-Id: 33D83A0008 X-HE-Tag: 1743790499-558343 X-HE-Meta: U2FsdGVkX198I1kk2Y2bigxvgBtut3FeFybglSKN+PQwni9wpiZhP2WYDTRzxDbtWdq9bHA9Te9q+xZccnCGDyx7Sc1Ptci0E/B2EKjnFmd1FBZRWkVvjNXSTgH4jLC9AogCNKreVRSgG2tQ64Wbg7VZ0owSroEiCfFfWpmM4H0I6oN5yditazD4UhdKRUv+wVeH7dYgAo18gaIaQ71ozsdWeeQymhHj9Q4e6SwAbpnu8sJhdi/PcKO2qzk83h7SAynBb9ucqlVXg9bWqBO57DNXTBDTkNBNGSvlgwrjvxvCMkILuDPv7e1z4J29n0o4Fj9hX4BGFVZcxMP8dFC4/gRwD7isnSqqOpaKFAgoXa8FfQGOZoP1P5kpsTD7Nc/y+6HVvuHk/YX7VbbVBndKXYIHzkHTQPMfWoQg/H8RuPVisOMQtSaRYT9SZtloWBcszuqSnVR2G8lk99u5J4xnaJD3ZX5QIx9qmP3vt3c0R8C1MC1APK9y3AtE4iVJIxpmorAz+HEnn4CnZKq1rVL3NTWoNRrvJ3rJYo7jXN5EITOOUocbAeq6BZNyA67TbFyu6/ZBGvEd4sm++8Ou4U99p1/68Ket2NjmGjo6w4HhNb5CLEm2LQr9mQaqsgddhO/sfx8QwwN1rIvPDBOD8CfLpFFrDf5Sq515XCZRVyrTzrvMmnUedj9OC1eph1CS4b8dJDPih2MReXgK7S1jBF2qELmvxxFAe/Iwf3liQHL3bOZ2Oes6HwiNm1XiYECTzoUDCYTky/lYJxNQ3z2/KoMFQfgzKPJIMHB6jiA4YJaMM+IvVCRbM3gpi0chn4SWq2vdmxFyJVUWRlxGnl0cpYkuku8u/dKlMW2gUFMZcjCQcsCcJyw3kZwZyV5eXzXiHqtGZxeirAq/9dJbNFRyIfjjcYW12ZAH7iRmXafx+Ce/RBRUxxB7XtT9fAJOdVgjBedyAZPEG0tMtGgnIqsuasG MQQRF2Ix wp3InKICb+UJxXK52gdAiP1H5Hx6IG+cQRtqEV15rQlZfJ9eaQeP6cEZBw+K0aIL7GaYAXL9eSMdYWbwZvO2SkEn4b77cQXGZEVm25S0r0RS/hXraYLl1B3uNsST/RfQ/13EQuQ/OTKzfF5/uJaeUgpUOdSFEYz2taRx23IRF3pg58VUTu0tWmza+eLCxfCQo93VrAWIP7QSK0dUyGCVgRZsUXpzqKa9kQioYsDBlhGQJl0qUcvjm+dEW+017tisbktUhuINlvgpr1JlNj4wOo5QMFdMfspsQ3xC2W4NACek0SJHZA55arnV502ZEJQpPnDVZ4Qei4dY1Y3CNFWL/2KE49n5EykWiHLdft2UvNVFhrr6td5wxDNiIKqRCtgYBRVzeqjIwAWuamlnq+e+mkwUbW9iiQbOZNcrluqN2nOIrUTQo6C1bI2p+fC3bIWgDkJT6ZN2yg87X6FU6NGF8rdaM7E1xyaxtuPl8 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: In the current FUSE writeback design (see commit 3be5a52b30aa ("fuse: support writable mmap")), a temp page is allocated for every dirty page to be written back, the contents of the dirty page are copied over to the temp page, and the temp page gets handed to the server to write back. This is done so that writeback may be immediately cleared on the dirty page, and this in turn is done in order to mitigate the following deadlock scenario that may arise if reclaim waits on writeback on the dirty page to complete: * single-threaded FUSE server is in the middle of handling a request that needs a memory allocation * memory allocation triggers direct reclaim * direct reclaim waits on a folio under writeback * the FUSE server can't write back the folio since it's stuck in direct reclaim With a recent change that added AS_WRITEBACK_INDETERMINATE and mitigates the situations described above, FUSE writeback does not need to use temp pages if it sets AS_WRITEBACK_INDETERMINATE on its inode mappings. This commit sets AS_WRITEBACK_INDETERMINATE on the inode mappings and removes the temporary pages + extra copying and the internal rb tree. fio benchmarks -- (using averages observed from 10 runs, throwing away outliers) Setup: sudo mount -t tmpfs -o size=30G tmpfs ~/tmp_mount ./libfuse/build/example/passthrough_ll -o writeback -o max_threads=4 -o source=~/tmp_mount ~/fuse_mount fio --name=writeback --ioengine=sync --rw=write --bs={1k,4k,1M} --size=2G --numjobs=2 --ramp_time=30 --group_reporting=1 --directory=/root/fuse_mount bs = 1k 4k 1M Before 351 MiB/s 1818 MiB/s 1851 MiB/s After 341 MiB/s 2246 MiB/s 2685 MiB/s % diff -3% 23% 45% Signed-off-by: Joanne Koong Reviewed-by: Jingbo Xu Acked-by: Miklos Szeredi --- fs/fuse/file.c | 360 ++++------------------------------------------- fs/fuse/fuse_i.h | 3 - 2 files changed, 28 insertions(+), 335 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 754378dd9f71..91ada0208863 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -415,89 +415,11 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) struct fuse_writepage_args { struct fuse_io_args ia; - struct rb_node writepages_entry; struct list_head queue_entry; - struct fuse_writepage_args *next; struct inode *inode; struct fuse_sync_bucket *bucket; }; -static struct fuse_writepage_args *fuse_find_writeback(struct fuse_inode *fi, - pgoff_t idx_from, pgoff_t idx_to) -{ - struct rb_node *n; - - n = fi->writepages.rb_node; - - while (n) { - struct fuse_writepage_args *wpa; - pgoff_t curr_index; - - wpa = rb_entry(n, struct fuse_writepage_args, writepages_entry); - WARN_ON(get_fuse_inode(wpa->inode) != fi); - curr_index = wpa->ia.write.in.offset >> PAGE_SHIFT; - if (idx_from >= curr_index + wpa->ia.ap.num_folios) - n = n->rb_right; - else if (idx_to < curr_index) - n = n->rb_left; - else - return wpa; - } - return NULL; -} - -/* - * Check if any page in a range is under writeback - */ -static bool fuse_range_is_writeback(struct inode *inode, pgoff_t idx_from, - pgoff_t idx_to) -{ - struct fuse_inode *fi = get_fuse_inode(inode); - bool found; - - if (RB_EMPTY_ROOT(&fi->writepages)) - return false; - - spin_lock(&fi->lock); - found = fuse_find_writeback(fi, idx_from, idx_to); - spin_unlock(&fi->lock); - - return found; -} - -static inline bool fuse_page_is_writeback(struct inode *inode, pgoff_t index) -{ - return fuse_range_is_writeback(inode, index, index); -} - -/* - * Wait for page writeback to be completed. - * - * Since fuse doesn't rely on the VM writeback tracking, this has to - * use some other means. - */ -static void fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index) -{ - struct fuse_inode *fi = get_fuse_inode(inode); - - wait_event(fi->page_waitq, !fuse_page_is_writeback(inode, index)); -} - -static inline bool fuse_folio_is_writeback(struct inode *inode, - struct folio *folio) -{ - pgoff_t last = folio_next_index(folio) - 1; - return fuse_range_is_writeback(inode, folio_index(folio), last); -} - -static void fuse_wait_on_folio_writeback(struct inode *inode, - struct folio *folio) -{ - struct fuse_inode *fi = get_fuse_inode(inode); - - wait_event(fi->page_waitq, !fuse_folio_is_writeback(inode, folio)); -} - /* * Wait for all pending writepages on the inode to finish. * @@ -886,13 +808,6 @@ static int fuse_do_readfolio(struct file *file, struct folio *folio) ssize_t res; u64 attr_ver; - /* - * With the temporary pages that are used to complete writeback, we can - * have writeback that extends beyond the lifetime of the folio. So - * make sure we read a properly synced folio. - */ - fuse_wait_on_folio_writeback(inode, folio); - attr_ver = fuse_get_attr_version(fm->fc); /* Don't overflow end offset */ @@ -1005,17 +920,12 @@ static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file) static void fuse_readahead(struct readahead_control *rac) { struct inode *inode = rac->mapping->host; - struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_conn *fc = get_fuse_conn(inode); unsigned int max_pages, nr_pages; - pgoff_t first = readahead_index(rac); - pgoff_t last = first + readahead_count(rac) - 1; if (fuse_is_bad(inode)) return; - wait_event(fi->page_waitq, !fuse_range_is_writeback(inode, first, last)); - max_pages = min_t(unsigned int, fc->max_pages, fc->max_read / PAGE_SIZE); @@ -1181,7 +1091,7 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia, int err; for (i = 0; i < ap->num_folios; i++) - fuse_wait_on_folio_writeback(inode, ap->folios[i]); + folio_wait_writeback(ap->folios[i]); fuse_write_args_fill(ia, ff, pos, count); ia->write.in.flags = fuse_write_flags(iocb); @@ -1638,7 +1548,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, return res; } } - if (!cuse && fuse_range_is_writeback(inode, idx_from, idx_to)) { + if (!cuse && filemap_range_has_writeback(mapping, pos, (pos + count - 1))) { if (!write) inode_lock(inode); fuse_sync_writes(inode); @@ -1835,38 +1745,34 @@ static ssize_t fuse_splice_write(struct pipe_inode_info *pipe, struct file *out, static void fuse_writepage_free(struct fuse_writepage_args *wpa) { struct fuse_args_pages *ap = &wpa->ia.ap; - int i; if (wpa->bucket) fuse_sync_bucket_dec(wpa->bucket); - for (i = 0; i < ap->num_folios; i++) - folio_put(ap->folios[i]); - fuse_file_put(wpa->ia.ff, false); kfree(ap->folios); kfree(wpa); } -static void fuse_writepage_finish_stat(struct inode *inode, struct folio *folio) -{ - struct backing_dev_info *bdi = inode_to_bdi(inode); - - dec_wb_stat(&bdi->wb, WB_WRITEBACK); - node_stat_sub_folio(folio, NR_WRITEBACK_TEMP); - wb_writeout_inc(&bdi->wb); -} - static void fuse_writepage_finish(struct fuse_writepage_args *wpa) { struct fuse_args_pages *ap = &wpa->ia.ap; struct inode *inode = wpa->inode; struct fuse_inode *fi = get_fuse_inode(inode); + struct backing_dev_info *bdi = inode_to_bdi(inode); int i; - for (i = 0; i < ap->num_folios; i++) - fuse_writepage_finish_stat(inode, ap->folios[i]); + for (i = 0; i < ap->num_folios; i++) { + /* + * Benchmarks showed that ending writeback within the + * scope of the fi->lock alleviates xarray lock + * contention and noticeably improves performance. + */ + folio_end_writeback(ap->folios[i]); + dec_wb_stat(&bdi->wb, WB_WRITEBACK); + wb_writeout_inc(&bdi->wb); + } wake_up(&fi->page_waitq); } @@ -1877,7 +1783,6 @@ static void fuse_send_writepage(struct fuse_mount *fm, __releases(fi->lock) __acquires(fi->lock) { - struct fuse_writepage_args *aux, *next; struct fuse_inode *fi = get_fuse_inode(wpa->inode); struct fuse_write_in *inarg = &wpa->ia.write.in; struct fuse_args *args = &wpa->ia.ap.args; @@ -1914,19 +1819,8 @@ __acquires(fi->lock) out_free: fi->writectr--; - rb_erase(&wpa->writepages_entry, &fi->writepages); fuse_writepage_finish(wpa); spin_unlock(&fi->lock); - - /* After rb_erase() aux request list is private */ - for (aux = wpa->next; aux; aux = next) { - next = aux->next; - aux->next = NULL; - fuse_writepage_finish_stat(aux->inode, - aux->ia.ap.folios[0]); - fuse_writepage_free(aux); - } - fuse_writepage_free(wpa); spin_lock(&fi->lock); } @@ -1954,43 +1848,6 @@ __acquires(fi->lock) } } -static struct fuse_writepage_args *fuse_insert_writeback(struct rb_root *root, - struct fuse_writepage_args *wpa) -{ - pgoff_t idx_from = wpa->ia.write.in.offset >> PAGE_SHIFT; - pgoff_t idx_to = idx_from + wpa->ia.ap.num_folios - 1; - struct rb_node **p = &root->rb_node; - struct rb_node *parent = NULL; - - WARN_ON(!wpa->ia.ap.num_folios); - while (*p) { - struct fuse_writepage_args *curr; - pgoff_t curr_index; - - parent = *p; - curr = rb_entry(parent, struct fuse_writepage_args, - writepages_entry); - WARN_ON(curr->inode != wpa->inode); - curr_index = curr->ia.write.in.offset >> PAGE_SHIFT; - - if (idx_from >= curr_index + curr->ia.ap.num_folios) - p = &(*p)->rb_right; - else if (idx_to < curr_index) - p = &(*p)->rb_left; - else - return curr; - } - - rb_link_node(&wpa->writepages_entry, parent, p); - rb_insert_color(&wpa->writepages_entry, root); - return NULL; -} - -static void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa) -{ - WARN_ON(fuse_insert_writeback(root, wpa)); -} - static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args, int error) { @@ -2010,41 +1867,6 @@ static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args, if (!fc->writeback_cache) fuse_invalidate_attr_mask(inode, FUSE_STATX_MODIFY); spin_lock(&fi->lock); - rb_erase(&wpa->writepages_entry, &fi->writepages); - while (wpa->next) { - struct fuse_mount *fm = get_fuse_mount(inode); - struct fuse_write_in *inarg = &wpa->ia.write.in; - struct fuse_writepage_args *next = wpa->next; - - wpa->next = next->next; - next->next = NULL; - tree_insert(&fi->writepages, next); - - /* - * Skip fuse_flush_writepages() to make it easy to crop requests - * based on primary request size. - * - * 1st case (trivial): there are no concurrent activities using - * fuse_set/release_nowrite. Then we're on safe side because - * fuse_flush_writepages() would call fuse_send_writepage() - * anyway. - * - * 2nd case: someone called fuse_set_nowrite and it is waiting - * now for completion of all in-flight requests. This happens - * rarely and no more than once per page, so this should be - * okay. - * - * 3rd case: someone (e.g. fuse_do_setattr()) is in the middle - * of fuse_set_nowrite..fuse_release_nowrite section. The fact - * that fuse_set_nowrite returned implies that all in-flight - * requests were completed along with all of their secondary - * requests. Further primary requests are blocked by negative - * writectr. Hence there cannot be any in-flight requests and - * no invocations of fuse_writepage_end() while we're in - * fuse_set_nowrite..fuse_release_nowrite section. - */ - fuse_send_writepage(fm, next, inarg->offset + inarg->size); - } fi->writectr--; fuse_writepage_finish(wpa); spin_unlock(&fi->lock); @@ -2131,19 +1953,16 @@ static void fuse_writepage_add_to_bucket(struct fuse_conn *fc, } static void fuse_writepage_args_page_fill(struct fuse_writepage_args *wpa, struct folio *folio, - struct folio *tmp_folio, uint32_t folio_index) + uint32_t folio_index) { struct inode *inode = folio->mapping->host; struct fuse_args_pages *ap = &wpa->ia.ap; - folio_copy(tmp_folio, folio); - - ap->folios[folio_index] = tmp_folio; + ap->folios[folio_index] = folio; ap->descs[folio_index].offset = 0; ap->descs[folio_index].length = PAGE_SIZE; inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK); - node_stat_add_folio(tmp_folio, NR_WRITEBACK_TEMP); } static struct fuse_writepage_args *fuse_writepage_args_setup(struct folio *folio, @@ -2178,18 +1997,12 @@ static int fuse_writepage_locked(struct folio *folio) struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_writepage_args *wpa; struct fuse_args_pages *ap; - struct folio *tmp_folio; struct fuse_file *ff; - int error = -ENOMEM; - - tmp_folio = folio_alloc(GFP_NOFS | __GFP_HIGHMEM, 0); - if (!tmp_folio) - goto err; + int error = -EIO; - error = -EIO; ff = fuse_write_file_get(fi); if (!ff) - goto err_nofile; + goto err; wpa = fuse_writepage_args_setup(folio, ff); error = -ENOMEM; @@ -2200,22 +2013,17 @@ static int fuse_writepage_locked(struct folio *folio) ap->num_folios = 1; folio_start_writeback(folio); - fuse_writepage_args_page_fill(wpa, folio, tmp_folio, 0); + fuse_writepage_args_page_fill(wpa, folio, 0); spin_lock(&fi->lock); - tree_insert(&fi->writepages, wpa); list_add_tail(&wpa->queue_entry, &fi->queued_writes); fuse_flush_writepages(inode); spin_unlock(&fi->lock); - folio_end_writeback(folio); - return 0; err_writepage_args: fuse_file_put(ff, false); -err_nofile: - folio_put(tmp_folio); err: mapping_set_error(folio->mapping, error); return error; @@ -2225,7 +2033,6 @@ struct fuse_fill_wb_data { struct fuse_writepage_args *wpa; struct fuse_file *ff; struct inode *inode; - struct folio **orig_folios; unsigned int max_folios; }; @@ -2260,69 +2067,11 @@ static void fuse_writepages_send(struct fuse_fill_wb_data *data) struct fuse_writepage_args *wpa = data->wpa; struct inode *inode = data->inode; struct fuse_inode *fi = get_fuse_inode(inode); - int num_folios = wpa->ia.ap.num_folios; - int i; spin_lock(&fi->lock); list_add_tail(&wpa->queue_entry, &fi->queued_writes); fuse_flush_writepages(inode); spin_unlock(&fi->lock); - - for (i = 0; i < num_folios; i++) - folio_end_writeback(data->orig_folios[i]); -} - -/* - * Check under fi->lock if the page is under writeback, and insert it onto the - * rb_tree if not. Otherwise iterate auxiliary write requests, to see if there's - * one already added for a page at this offset. If there's none, then insert - * this new request onto the auxiliary list, otherwise reuse the existing one by - * swapping the new temp page with the old one. - */ -static bool fuse_writepage_add(struct fuse_writepage_args *new_wpa, - struct folio *folio) -{ - struct fuse_inode *fi = get_fuse_inode(new_wpa->inode); - struct fuse_writepage_args *tmp; - struct fuse_writepage_args *old_wpa; - struct fuse_args_pages *new_ap = &new_wpa->ia.ap; - - WARN_ON(new_ap->num_folios != 0); - new_ap->num_folios = 1; - - spin_lock(&fi->lock); - old_wpa = fuse_insert_writeback(&fi->writepages, new_wpa); - if (!old_wpa) { - spin_unlock(&fi->lock); - return true; - } - - for (tmp = old_wpa->next; tmp; tmp = tmp->next) { - pgoff_t curr_index; - - WARN_ON(tmp->inode != new_wpa->inode); - curr_index = tmp->ia.write.in.offset >> PAGE_SHIFT; - if (curr_index == folio->index) { - WARN_ON(tmp->ia.ap.num_folios != 1); - swap(tmp->ia.ap.folios[0], new_ap->folios[0]); - break; - } - } - - if (!tmp) { - new_wpa->next = old_wpa->next; - old_wpa->next = new_wpa; - } - - spin_unlock(&fi->lock); - - if (tmp) { - fuse_writepage_finish_stat(new_wpa->inode, - folio); - fuse_writepage_free(new_wpa); - } - - return false; } static bool fuse_writepage_need_send(struct fuse_conn *fc, struct folio *folio, @@ -2331,15 +2080,6 @@ static bool fuse_writepage_need_send(struct fuse_conn *fc, struct folio *folio, { WARN_ON(!ap->num_folios); - /* - * Being under writeback is unlikely but possible. For example direct - * read to an mmaped fuse file will set the page dirty twice; once when - * the pages are faulted with get_user_pages(), and then after the read - * completed. - */ - if (fuse_folio_is_writeback(data->inode, folio)) - return true; - /* Reached max pages */ if (ap->num_folios == fc->max_pages) return true; @@ -2349,7 +2089,7 @@ static bool fuse_writepage_need_send(struct fuse_conn *fc, struct folio *folio, return true; /* Discontinuity */ - if (data->orig_folios[ap->num_folios - 1]->index + 1 != folio_index(folio)) + if (ap->folios[ap->num_folios - 1]->index + 1 != folio_index(folio)) return true; /* Need to grow the pages array? If so, did the expansion fail? */ @@ -2368,7 +2108,6 @@ static int fuse_writepages_fill(struct folio *folio, struct inode *inode = data->inode; struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_conn *fc = get_fuse_conn(inode); - struct folio *tmp_folio; int err; if (!data->ff) { @@ -2383,54 +2122,23 @@ static int fuse_writepages_fill(struct folio *folio, data->wpa = NULL; } - err = -ENOMEM; - tmp_folio = folio_alloc(GFP_NOFS | __GFP_HIGHMEM, 0); - if (!tmp_folio) - goto out_unlock; - - /* - * The page must not be redirtied until the writeout is completed - * (i.e. userspace has sent a reply to the write request). Otherwise - * there could be more than one temporary page instance for each real - * page. - * - * This is ensured by holding the page lock in page_mkwrite() while - * checking fuse_page_is_writeback(). We already hold the page lock - * since clear_page_dirty_for_io() and keep it held until we add the - * request to the fi->writepages list and increment ap->num_folios. - * After this fuse_page_is_writeback() will indicate that the page is - * under writeback, so we can release the page lock. - */ if (data->wpa == NULL) { err = -ENOMEM; wpa = fuse_writepage_args_setup(folio, data->ff); - if (!wpa) { - folio_put(tmp_folio); + if (!wpa) goto out_unlock; - } fuse_file_get(wpa->ia.ff); data->max_folios = 1; ap = &wpa->ia.ap; } folio_start_writeback(folio); - fuse_writepage_args_page_fill(wpa, folio, tmp_folio, ap->num_folios); - data->orig_folios[ap->num_folios] = folio; + fuse_writepage_args_page_fill(wpa, folio, ap->num_folios); err = 0; - if (data->wpa) { - /* - * Protected by fi->lock against concurrent access by - * fuse_page_is_writeback(). - */ - spin_lock(&fi->lock); - ap->num_folios++; - spin_unlock(&fi->lock); - } else if (fuse_writepage_add(wpa, folio)) { + ap->num_folios++; + if (!data->wpa) data->wpa = wpa; - } else { - folio_end_writeback(folio); - } out_unlock: folio_unlock(folio); @@ -2457,13 +2165,6 @@ static int fuse_writepages(struct address_space *mapping, data.wpa = NULL; data.ff = NULL; - err = -ENOMEM; - data.orig_folios = kcalloc(fc->max_pages, - sizeof(struct folio *), - GFP_NOFS); - if (!data.orig_folios) - goto out; - err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data); if (data.wpa) { WARN_ON(!data.wpa->ia.ap.num_folios); @@ -2472,7 +2173,6 @@ static int fuse_writepages(struct address_space *mapping, if (data.ff) fuse_file_put(data.ff, false); - kfree(data.orig_folios); out: return err; } @@ -2497,8 +2197,6 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping, if (IS_ERR(folio)) goto error; - fuse_wait_on_page_writeback(mapping->host, folio->index); - if (folio_test_uptodate(folio) || len >= folio_size(folio)) goto success; /* @@ -2561,13 +2259,9 @@ static int fuse_launder_folio(struct folio *folio) { int err = 0; if (folio_clear_dirty_for_io(folio)) { - struct inode *inode = folio->mapping->host; - - /* Serialize with pending writeback for the same page */ - fuse_wait_on_page_writeback(inode, folio->index); err = fuse_writepage_locked(folio); if (!err) - fuse_wait_on_page_writeback(inode, folio->index); + folio_wait_writeback(folio); } return err; } @@ -2611,7 +2305,7 @@ static vm_fault_t fuse_page_mkwrite(struct vm_fault *vmf) return VM_FAULT_NOPAGE; } - fuse_wait_on_folio_writeback(inode, folio); + folio_wait_writeback(folio); return VM_FAULT_LOCKED; } @@ -3429,9 +3123,12 @@ static const struct address_space_operations fuse_file_aops = { void fuse_init_file_inode(struct inode *inode, unsigned int flags) { struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_conn *fc = get_fuse_conn(inode); inode->i_fop = &fuse_file_operations; inode->i_data.a_ops = &fuse_file_aops; + if (fc->writeback_cache) + mapping_set_writeback_indeterminate(&inode->i_data); INIT_LIST_HEAD(&fi->write_files); INIT_LIST_HEAD(&fi->queued_writes); @@ -3439,7 +3136,6 @@ void fuse_init_file_inode(struct inode *inode, unsigned int flags) fi->iocachectr = 0; init_waitqueue_head(&fi->page_waitq); init_waitqueue_head(&fi->direct_io_waitq); - fi->writepages = RB_ROOT; if (IS_ENABLED(CONFIG_FUSE_DAX)) fuse_dax_inode_init(inode, flags); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index fee96fe7887b..28a101a5c558 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -141,9 +141,6 @@ struct fuse_inode { /* waitq for direct-io completion */ wait_queue_head_t direct_io_waitq; - - /* List of writepage requestst (pending or sent) */ - struct rb_root writepages; }; /* readdir cache (directory only) */