From patchwork Fri Apr 21 22:12:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 13220742 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 4672AC7618E for ; Fri, 21 Apr 2023 22:13:26 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id BC27D6B0072; Fri, 21 Apr 2023 18:13:25 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id B72F36B0074; Fri, 21 Apr 2023 18:13:25 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9EC5A6B0075; Fri, 21 Apr 2023 18:13:25 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 8F4246B0072 for ; Fri, 21 Apr 2023 18:13:25 -0400 (EDT) Received: from smtpin28.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 5CB8F1C6785 for ; Fri, 21 Apr 2023 22:13:25 +0000 (UTC) X-FDA: 80706800370.28.F1F4EE8 Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) by imf26.hostedemail.com (Postfix) with ESMTP id 886CD140014 for ; Fri, 21 Apr 2023 22:13:23 +0000 (UTC) Authentication-Results: imf26.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b="gWPYUh/q"; spf=pass (imf26.hostedemail.com: domain of dianders@chromium.org designates 209.85.210.174 as permitted sender) smtp.mailfrom=dianders@chromium.org; dmarc=pass (policy=none) header.from=chromium.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1682115203; 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=u/AkHMm2p+EP+a6U0DbEFYOuvSo1i83VDzuubdv1yU4=; b=OXR7aqaTKMfxJpoECgmc87x7qLecj+eW6YGGmkAlpFHOLoliOipWbl5yp0p/yQs02Moz6C NTdN/BqrmPXD4GIpYT/oSX9+nX+wd7uBoIdIYIJpBfAawlse7dhhErD+mpollUKFHSXOhF hygflRxltR6SAuSe/SLSb17LYX0YARY= ARC-Authentication-Results: i=1; imf26.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b="gWPYUh/q"; spf=pass (imf26.hostedemail.com: domain of dianders@chromium.org designates 209.85.210.174 as permitted sender) smtp.mailfrom=dianders@chromium.org; dmarc=pass (policy=none) header.from=chromium.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1682115203; a=rsa-sha256; cv=none; b=2i8p+kbVmokgJlqpVXGx4L7UaA9HfUT5lnuzHJX92ys3OUybiIymJFlTACqM1y3568cHVE k/gbQ96JNgW++kY/CtoMJljiDNorl2BPQCtDckBTY4vru8V6bWP2WA6VxUiOnpKXRf9sLQ 8dk+CFzo6v73/rZAjTqLdYxqqbvTnEQ= Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-63b73203e0aso17102409b3a.1 for ; Fri, 21 Apr 2023 15:13:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1682115202; x=1684707202; 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=u/AkHMm2p+EP+a6U0DbEFYOuvSo1i83VDzuubdv1yU4=; b=gWPYUh/qJS3hKUZOK+9h4MWoL8QjpqBENZF1/R77mtm+LeEDasMRdSowMwEpPxxS78 EP2q9aDYBJHna1dXO/vRjzhgMH3xXjajRzj+Gem3tqcctYYdBwGqaQ29Kog5RyRfy0yp UjVmuXQ923zKnlvwr5/ZYrwLOML+t858ymiAc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682115202; x=1684707202; 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=u/AkHMm2p+EP+a6U0DbEFYOuvSo1i83VDzuubdv1yU4=; b=it2w4HnQ1JWsZGHoAMIFGe2LLRSYuoIaaT7qTcBwVZhrVZZ8zPL/D+kzf+nma6o6MA ueZXrbS/UtCijFXZqLSRGePebo6wrDIojQvf8XqswNrLyl5vOo7q3obImmAOV22daa0g W+zo6jSw4Ol6boFAiABvxy5Pa0/N9ea/CaQADsPCqZhsJg1teQaSCLCon8BpPXN5jYj8 YMDtQBAYV36Oc8xvKahPrl8hnbRgZWwp3hovDV6DxGUNtpBJCSLWzka9VEGOf8nNZ/pl z3F7YUeGLYyKcfdvIO20oZ6UFocCe5ISYPnN9dxflxhNOf2Hu94V4XJVkyekJPp1ZKr3 lW0Q== X-Gm-Message-State: AAQBX9eCKpiLPLJLOwStd0zI0neD6POx5DDeIUm1MZmuWvs9mCohbha8 zgM8eMMtTI2c55H5eSgpcx+BiQ== X-Google-Smtp-Source: AKy350bcHsIIY4k+lLMfZH1OxrXb0oxc9pTN/Ivx+wmbrGQA//e/eiBuiaIqWiD0BPfrEISD1XsY2A== X-Received: by 2002:a05:6a20:8426:b0:f0:8708:2341 with SMTP id c38-20020a056a20842600b000f087082341mr7837599pzd.26.1682115202268; Fri, 21 Apr 2023 15:13:22 -0700 (PDT) Received: from tictac2.mtv.corp.google.com ([2620:15c:9d:2:87cc:9018:e569:4a27]) by smtp.gmail.com with ESMTPSA id y72-20020a62644b000000b006372791d708sm3424715pfb.104.2023.04.21.15.13.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 Apr 2023 15:13:21 -0700 (PDT) From: Douglas Anderson To: Andrew Morton , Mel Gorman , Vlastimil Babka , Ying , Alexander Viro , Christian Brauner Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, Yu Zhao , linux-fsdevel@vger.kernel.org, Matthew Wilcox , Douglas Anderson Subject: [PATCH v2 1/4] mm/filemap: Add folio_lock_timeout() Date: Fri, 21 Apr 2023 15:12:45 -0700 Message-ID: <20230421151135.v2.1.I2b71e11264c5c214bc59744b9e13e4c353bc5714@changeid> X-Mailer: git-send-email 2.40.0.634.g4ca3ef3211-goog In-Reply-To: <20230421221249.1616168-1-dianders@chromium.org> References: <20230421221249.1616168-1-dianders@chromium.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 886CD140014 X-Stat-Signature: oee6ocwris8xj631thzrknffanf7wf77 X-Rspam-User: X-Rspamd-Server: rspam08 X-HE-Tag: 1682115203-336291 X-HE-Meta: U2FsdGVkX1+1vh7bszILVlOoMm3jZe/mGvrLIhmoNcYP9tUznXFiC9sW46g4jGSrupFjhAjlmu5zIhJb5VwwzlTwqUU8q6oCmoy77MUZhI0AArEd4WiusEt7xpI5e2e/hP2Z3HFWf1RAehxWDgPkoy5hn/M3tS9XTD2RZefcSq6GQncgvVaHmEb/iSO77WpRhvZLMIYosayy5eqQpn5KghkXj5DV1T2S3SWFJJANU5ksigiXgN/D/yYXssOR1lNGaJB9pF0vhZJiK1/idvHanmnJ0dEilL0D7JA+cRvsnMRhoXEyofBNQnz/T3y2lG9TwOhIash6pkKVmQcKcFhlqYA9V3kwfkAM+mNZrHLHuMrQiYl+xp4hR6PqWLHq0KuoJToDUvWYoJwcKvNlEVrfZcyEw5IhA8DghTXktxGichII4FRVf39kB0TYZLMvIm4DQUWG8zAwBqrvXUr0nJXYE2r6KH8W/ft/iK3cL3uHFv7PQLI1biH2jX12CX4YJGM0XXFVyzDyYjrsVFIpiVoIJFsCJYXWYE4OgDpb40dtt3svF/aRg4uVyoNQrNAaEfYdQWCxHFkkooDWnc36XOtI8TpymHAtg3ZJ64HrGHDlEFL3syWdKAG9KEPWatYnokGe2/loGmtRCR9qUWvQ7hDz1at35wtFZmjYY4y6iohz5Q5Bua+QrKhC+uCkwLau8yiUmVMLVEZDQujbbm6X/IED/l/PJZ/mffig/MlloRszdUKLNecDhpUWb6Z4X362kMdS+M2XQAl6298OZRIEA2x4DOG2oD3ax1upI8CIGJV4F4r3m+Hinc+zdtBi+YfrcE7CoNiM+jGrgw9jT6ycDjDo8EVPq1OPfjWv2bqUAkv69gUNJ7MbqFAkjAuR2szG+g/XxDp5sdp6YWXg/UNdvNWl5QHeveohEaIB5hri46n09vME5bKUUi6JrInNeTIm3Pd8xHiHcOL0CQndkMoyMpg 0DS4BdQL uq0Nsu8cYc7vpX3J8j3iKCOJhLRyZU8CKt272e9Ub7opDxJfuc4Nmez+fy+L4xYVofbzKl150QHsHKJhsVok6j2yOEGGM3gfNGR+cWFI/NRKsyNFZmdclq+91lpCwh97M0PAV4jMiux/LmyJ4dp+Z/271dCMBfw92mF5RA1Xfh7BA1stFb68LEyFaxp38QgvLMU21YISdcyJXxsPOEVvYWou8lVN01kVhlIS+nsuZk7jC/q0FzwchT5jTqzQTRa4wlLRUFAIm57PJlL5LwOWGNPKCYoPAPLEh31JIqB/2GeCFmm3sxkxzd3sudAShtYKd06iJ4OJYqDczu+Z695Mm1x6uvq+wIMr+JbP4NTkum/FIyHkTJ8uzXs83XUA5n97x/Zz5ux3enC+fx79P5C+HsXljYcHNw0OhuwI4tci9JMKnC+ERY4jqC1eO7z9Pp59dReqT2j2HbW3InCQ= 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: Add a variant of folio_lock() that can timeout. This is useful to avoid unbounded waits for the page lock in kcompactd. Signed-off-by: Douglas Anderson --- Changes in v2: - "Add folio_lock_timeout()" new for v2. include/linux/pagemap.h | 16 ++++++++++++++ mm/filemap.c | 47 +++++++++++++++++++++++++++++------------ 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 0acb8e1fb7af..0f3ef9f79300 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -892,6 +892,7 @@ static inline bool wake_page_match(struct wait_page_queue *wait_page, } void __folio_lock(struct folio *folio); +int __folio_lock_timeout(struct folio *folio, long timeout); int __folio_lock_killable(struct folio *folio); bool __folio_lock_or_retry(struct folio *folio, struct mm_struct *mm, unsigned int flags); @@ -952,6 +953,21 @@ static inline void folio_lock(struct folio *folio) __folio_lock(folio); } +/** + * folio_lock_timeout() - Lock this folio, with a timeout. + * @folio: The folio to lock. + * @timeout: The timeout in jiffies; %MAX_SCHEDULE_TIMEOUT means wait forever. + * + * Return: 0 upon success; -ETIMEDOUT upon failure. + */ +static inline int folio_lock_timeout(struct folio *folio, long timeout) +{ + might_sleep(); + if (!folio_trylock(folio)) + return __folio_lock_timeout(folio, timeout); + return 0; +} + /** * lock_page() - Lock the folio containing this page. * @page: The page to lock. diff --git a/mm/filemap.c b/mm/filemap.c index 2723104cc06a..c6056ec41284 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1220,7 +1220,7 @@ static inline bool folio_trylock_flag(struct folio *folio, int bit_nr, int sysctl_page_lock_unfairness = 5; static inline int folio_wait_bit_common(struct folio *folio, int bit_nr, - int state, enum behavior behavior) + int state, enum behavior behavior, long timeout) { wait_queue_head_t *q = folio_waitqueue(folio); int unfairness = sysctl_page_lock_unfairness; @@ -1229,6 +1229,7 @@ static inline int folio_wait_bit_common(struct folio *folio, int bit_nr, bool thrashing = false; unsigned long pflags; bool in_thrashing; + int err; if (bit_nr == PG_locked && !folio_test_uptodate(folio) && folio_test_workingset(folio)) { @@ -1295,10 +1296,13 @@ static inline int folio_wait_bit_common(struct folio *folio, int bit_nr, /* Loop until we've been woken or interrupted */ flags = smp_load_acquire(&wait->flags); if (!(flags & WQ_FLAG_WOKEN)) { + if (!timeout) + break; + if (signal_pending_state(state, current)) break; - io_schedule(); + timeout = io_schedule_timeout(timeout); continue; } @@ -1324,10 +1328,10 @@ static inline int folio_wait_bit_common(struct folio *folio, int bit_nr, } /* - * If a signal happened, this 'finish_wait()' may remove the last - * waiter from the wait-queues, but the folio waiters bit will remain - * set. That's ok. The next wakeup will take care of it, and trying - * to do it here would be difficult and prone to races. + * If a signal/timeout happened, this 'finish_wait()' may remove the + * last waiter from the wait-queues, but the folio waiters bit will + * remain set. That's ok. The next wakeup will take care of it, and + * trying to do it here would be difficult and prone to races. */ finish_wait(q, wait); @@ -1336,6 +1340,13 @@ static inline int folio_wait_bit_common(struct folio *folio, int bit_nr, psi_memstall_leave(&pflags); } + /* + * If we don't meet the success criteria below then we've got an error + * of some sort. Differentiate between the two error cases. If there's + * no time left it must have been a timeout. + */ + err = !timeout ? -ETIMEDOUT : -EINTR; + /* * NOTE! The wait->flags weren't stable until we've done the * 'finish_wait()', and we could have exited the loop above due @@ -1350,9 +1361,9 @@ static inline int folio_wait_bit_common(struct folio *folio, int bit_nr, * waiter, but an exclusive one requires WQ_FLAG_DONE. */ if (behavior == EXCLUSIVE) - return wait->flags & WQ_FLAG_DONE ? 0 : -EINTR; + return wait->flags & WQ_FLAG_DONE ? 0 : err; - return wait->flags & WQ_FLAG_WOKEN ? 0 : -EINTR; + return wait->flags & WQ_FLAG_WOKEN ? 0 : err; } #ifdef CONFIG_MIGRATION @@ -1442,13 +1453,15 @@ void migration_entry_wait_on_locked(swp_entry_t entry, pte_t *ptep, void folio_wait_bit(struct folio *folio, int bit_nr) { - folio_wait_bit_common(folio, bit_nr, TASK_UNINTERRUPTIBLE, SHARED); + folio_wait_bit_common(folio, bit_nr, TASK_UNINTERRUPTIBLE, SHARED, + MAX_SCHEDULE_TIMEOUT); } EXPORT_SYMBOL(folio_wait_bit); int folio_wait_bit_killable(struct folio *folio, int bit_nr) { - return folio_wait_bit_common(folio, bit_nr, TASK_KILLABLE, SHARED); + return folio_wait_bit_common(folio, bit_nr, TASK_KILLABLE, SHARED, + MAX_SCHEDULE_TIMEOUT); } EXPORT_SYMBOL(folio_wait_bit_killable); @@ -1467,7 +1480,8 @@ EXPORT_SYMBOL(folio_wait_bit_killable); */ static int folio_put_wait_locked(struct folio *folio, int state) { - return folio_wait_bit_common(folio, PG_locked, state, DROP); + return folio_wait_bit_common(folio, PG_locked, state, DROP, + MAX_SCHEDULE_TIMEOUT); } /** @@ -1662,17 +1676,24 @@ EXPORT_SYMBOL_GPL(page_endio); void __folio_lock(struct folio *folio) { folio_wait_bit_common(folio, PG_locked, TASK_UNINTERRUPTIBLE, - EXCLUSIVE); + EXCLUSIVE, MAX_SCHEDULE_TIMEOUT); } EXPORT_SYMBOL(__folio_lock); int __folio_lock_killable(struct folio *folio) { return folio_wait_bit_common(folio, PG_locked, TASK_KILLABLE, - EXCLUSIVE); + EXCLUSIVE, MAX_SCHEDULE_TIMEOUT); } EXPORT_SYMBOL_GPL(__folio_lock_killable); +int __folio_lock_timeout(struct folio *folio, long timeout) +{ + return folio_wait_bit_common(folio, PG_locked, TASK_KILLABLE, + EXCLUSIVE, timeout); +} +EXPORT_SYMBOL_GPL(__folio_lock_timeout); + static int __folio_lock_async(struct folio *folio, struct wait_page_queue *wait) { struct wait_queue_head *q = folio_waitqueue(folio);