get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2220910/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2220910,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2220910/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260408114952.469141112@kernel.org/",
    "project": {
        "id": 26,
        "url": "http://patchwork.ozlabs.org/api/1.1/projects/26/?format=api",
        "name": "Netfilter Development",
        "link_name": "netfilter-devel",
        "list_id": "netfilter-devel.vger.kernel.org",
        "list_email": "netfilter-devel@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null
    },
    "msgid": "<20260408114952.469141112@kernel.org>",
    "date": "2026-04-08T11:54:20",
    "name": "[V2,08/11] fs/timerfd: Use the new alarm/hrtimer functions",
    "commit_ref": null,
    "pull_url": null,
    "state": "handled-elsewhere",
    "archived": true,
    "hash": "87dd05026023797f220696876ce925994d2677f7",
    "submitter": {
        "id": 92397,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/92397/?format=api",
        "name": "Thomas Gleixner",
        "email": "tglx@kernel.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260408114952.469141112@kernel.org/mbox/",
    "series": [
        {
            "id": 499126,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/499126/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/list/?series=499126",
            "date": "2026-04-08T11:53:41",
            "name": "hrtimers: Prevent hrtimer interrupt starvation",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/499126/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2220910/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2220910/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "\n <netfilter-devel+bounces-11721-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "netfilter-devel@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=hVQIPgcY;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.105.105.114; helo=tor.lore.kernel.org;\n envelope-from=netfilter-devel+bounces-11721-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"hVQIPgcY\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"
        ],
        "Received": [
            "from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4frM9B2pj6z1xv0\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 08 Apr 2026 22:01:18 +1000 (AEST)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 1290D307A7A1\n\tfor <incoming@patchwork.ozlabs.org>; Wed,  8 Apr 2026 11:55:14 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 00B493C13F5;\n\tWed,  8 Apr 2026 11:54:24 +0000 (UTC)",
            "from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D9A93C0637;\n\tWed,  8 Apr 2026 11:54:23 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPSA id 71E19C2BCB1;\n\tWed,  8 Apr 2026 11:54:22 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775649263; cv=none;\n b=ZG/Toh6fP8px6qzj8MkyS43RE1R0fi8amQf0wfzwPidM4fHuOn4O2B9KmGfrVSYOkIib0stubuAnvzrgg3olsnOw3wht2xJbj6U5hOIKiZ229C44oLULDcsdrLAbUJiX3ZjZSCEjhMoF6o153CghUQPiUHqmT44zw1bSI3aiAfg=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775649263; c=relaxed/simple;\n\tbh=AmXtfF4jtxZEbEeyDADO/h7k4NvT+7oGErqgeL3DMs8=;\n\th=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version:\n\t Content-Type;\n b=PXN19xbUV8WHNkqgPOM7LRhZxObpouoEhpQrqFTiNEGvxaJAj7Cg7PMprhzidQ/MfmzQtimopBy07fXU08imqZNgpxd+H0P369wcfAf3EWnG1sQrYSrCBCIfjqowEz/IlWmryAKinW844QfMKpiwVRTaE3tQ+1js65zk/58Jtj0=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=hVQIPgcY; arc=none smtp.client-ip=10.30.226.201",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1775649263;\n\tbh=AmXtfF4jtxZEbEeyDADO/h7k4NvT+7oGErqgeL3DMs8=;\n\th=Date:From:To:Cc:Subject:References:From;\n\tb=hVQIPgcYUlGTF66So4NHJf9DvuRHxOeII9qOniI0mX0lk8qkX8mLbQv5WFlNjnhwP\n\t JH9/ISSRZJdAmx5DChK1qvwUIqUAlMJLvUJhnI2T4jUXWy+BUNMaIYVV5c7fh8LoMh\n\t ULpCl7u/JPmbEmYUHJQv/FVXJX9WgXnB0RZyq+O6dpz3grdO1yafn/Z86433lg3RKq\n\t KPpOZDMZdEzGnk0NiTHO9sDJY4t0lLZ4836yZrD+8o4b1GAsWBjnKTc9uSYNDOF3iW\n\t J3T3eNZKJ3J2WfkX/kJ4bgwKNlc3w3BLDGzFMnVU7WrU8hu5P6BBx5RgDoy5JzMZMN\n\t ZFXKYK48NC8tQ==",
        "Date": "Wed, 08 Apr 2026 13:54:20 +0200",
        "Message-ID": "<20260408114952.469141112@kernel.org>",
        "User-Agent": "quilt/0.68",
        "From": "Thomas Gleixner <tglx@kernel.org>",
        "To": "LKML <linux-kernel@vger.kernel.org>",
        "Cc": "Alexander Viro <viro@zeniv.linux.org.uk>,\n Christian Brauner <brauner@kernel.org>,\n Jan Kara <jack@suse.cz>,\n Anna-Maria Behnsen <anna-maria@linutronix.de>,\n Frederic Weisbecker <frederic@kernel.org>,\n linux-fsdevel@vger.kernel.org,\n Calvin Owens <calvin@wbinvd.org>,\n \"Peter Zijlstra (Intel)\" <peterz@infradead.org>,\n John Stultz <jstultz@google.com>,\n Stephen Boyd <sboyd@kernel.org>,\n Sebastian Reichel <sre@kernel.org>,\n linux-pm@vger.kernel.org,\n Pablo Neira Ayuso <pablo@netfilter.org>,\n Florian Westphal <fw@strlen.de>,\n Phil Sutter <phil@nwl.cc>,\n netfilter-devel@vger.kernel.org,\n coreteam@netfilter.org",
        "Subject": "[patch V2 08/11] fs/timerfd: Use the new alarm/hrtimer functions",
        "References": "<20260408102356.783133335@kernel.org>",
        "Precedence": "bulk",
        "X-Mailing-List": "netfilter-devel@vger.kernel.org",
        "List-Id": "<netfilter-devel.vger.kernel.org>",
        "List-Subscribe": "<mailto:netfilter-devel+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:netfilter-devel+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8"
    },
    "content": "Like any other user controlled interface, timerfd based timers can be\nprogrammed with expiry times in the past or vary small intervals.\n\nBoth hrtimer and alarmtimer provide new interfaces which return the queued\nstate of the timer. If the timer was already expired, then let the callsite\nhandle the timerfd context update so that the full round trip through the\nhrtimer interrupt is avoided.\n\nSigned-off-by: Thomas Gleixner <tglx@kernel.org>\nCc: Alexander Viro <viro@zeniv.linux.org.uk>\nCc: Christian Brauner <brauner@kernel.org>\nCc: Jan Kara <jack@suse.cz>\nCc: Anna-Maria Behnsen <anna-maria@linutronix.de>\nCc: Frederic Weisbecker <frederic@kernel.org>\nCc: linux-fsdevel@vger.kernel.org\n---\nV2: Rename to alarm_timer_start() and add a comment explaining the -1 in\n    the tick accounting. - Peter\n---\n fs/timerfd.c |  117 ++++++++++++++++++++++++++++++++++-------------------------\n 1 file changed, 68 insertions(+), 49 deletions(-)",
    "diff": "--- a/fs/timerfd.c\n+++ b/fs/timerfd.c\n@@ -55,6 +55,15 @@ static inline bool isalarm(struct timerf\n \t\tctx->clockid == CLOCK_BOOTTIME_ALARM;\n }\n \n+static void __timerfd_triggered(struct timerfd_ctx *ctx)\n+{\n+\tlockdep_assert_held(&ctx->wqh.lock);\n+\n+\tctx->expired = 1;\n+\tctx->ticks++;\n+\twake_up_locked_poll(&ctx->wqh, EPOLLIN);\n+}\n+\n /*\n  * This gets called when the timer event triggers. We set the \"expired\"\n  * flag, but we do not re-arm the timer (in case it's necessary,\n@@ -62,13 +71,8 @@ static inline bool isalarm(struct timerf\n  */\n static void timerfd_triggered(struct timerfd_ctx *ctx)\n {\n-\tunsigned long flags;\n-\n-\tspin_lock_irqsave(&ctx->wqh.lock, flags);\n-\tctx->expired = 1;\n-\tctx->ticks++;\n-\twake_up_locked_poll(&ctx->wqh, EPOLLIN);\n-\tspin_unlock_irqrestore(&ctx->wqh.lock, flags);\n+\tguard(spinlock_irqsave)(&ctx->wqh.lock);\n+\t__timerfd_triggered(ctx);\n }\n \n static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)\n@@ -184,15 +188,54 @@ static ktime_t timerfd_get_remaining(str\n \treturn remaining < 0 ? 0: remaining;\n }\n \n+static void timerfd_alarm_start(struct timerfd_ctx *ctx, ktime_t exp, bool relative)\n+{\n+\t/* Start the timer. If it's expired already, handle the callback. */\n+\tif (!alarm_start_timer(&ctx->t.alarm, exp, relative))\n+\t\t__timerfd_triggered(ctx);\n+}\n+\n+static u64 timerfd_alarm_restart(struct timerfd_ctx *ctx)\n+{\n+\t/* -1 to account for ctx->ticks++ in __timerfd_triggered() */\n+\tu64 ticks = alarm_forward_now(&ctx->t.alarm, ctx->tintv) - 1;\n+\n+\ttimerfd_alarm_start(ctx, alarm_get_expires(&ctx->t.alarm), false);\n+\treturn ticks;\n+}\n+\n+static void timerfd_hrtimer_start(struct timerfd_ctx *ctx, ktime_t exp,\n+\t\t\t\t  const enum hrtimer_mode mode)\n+{\n+\t/* Start the timer. If it's expired already, handle the callback. */\n+\tif (!hrtimer_start_range_ns_user(&ctx->t.tmr, exp, 0, mode))\n+\t\t__timerfd_triggered(ctx);\n+}\n+\n+static u64 timerfd_hrtimer_restart(struct timerfd_ctx *ctx)\n+{\n+\t/* -1 to account for ctx->ticks++ in __timerfd_triggered() */\n+\tu64 ticks = hrtimer_forward_now(&ctx->t.tmr, ctx->tintv) - 1;\n+\n+\ttimerfd_hrtimer_start(ctx, hrtimer_get_expires(&ctx->t.tmr), HRTIMER_MODE_ABS);\n+\treturn ticks;\n+}\n+\n+static u64 timerfd_restart(struct timerfd_ctx *ctx)\n+{\n+\tif (isalarm(ctx))\n+\t\treturn timerfd_alarm_restart(ctx);\n+\treturn timerfd_hrtimer_restart(ctx);\n+}\n+\n static int timerfd_setup(struct timerfd_ctx *ctx, int flags,\n \t\t\t const struct itimerspec64 *ktmr)\n {\n+\tint clockid = ctx->clockid;\n \tenum hrtimer_mode htmode;\n \tktime_t texp;\n-\tint clockid = ctx->clockid;\n \n-\thtmode = (flags & TFD_TIMER_ABSTIME) ?\n-\t\tHRTIMER_MODE_ABS: HRTIMER_MODE_REL;\n+\thtmode = (flags & TFD_TIMER_ABSTIME) ? HRTIMER_MODE_ABS: HRTIMER_MODE_REL;\n \n \ttexp = timespec64_to_ktime(ktmr->it_value);\n \tctx->expired = 0;\n@@ -206,20 +249,15 @@ static int timerfd_setup(struct timerfd_\n \t\t\t   timerfd_alarmproc);\n \t} else {\n \t\thrtimer_setup(&ctx->t.tmr, timerfd_tmrproc, clockid, htmode);\n-\t\thrtimer_set_expires(&ctx->t.tmr, texp);\n \t}\n \n \tif (texp != 0) {\n \t\tif (flags & TFD_TIMER_ABSTIME)\n \t\t\ttexp = timens_ktime_to_host(clockid, texp);\n-\t\tif (isalarm(ctx)) {\n-\t\t\tif (flags & TFD_TIMER_ABSTIME)\n-\t\t\t\talarm_start(&ctx->t.alarm, texp);\n-\t\t\telse\n-\t\t\t\talarm_start_relative(&ctx->t.alarm, texp);\n-\t\t} else {\n-\t\t\thrtimer_start(&ctx->t.tmr, texp, htmode);\n-\t\t}\n+\t\tif (isalarm(ctx))\n+\t\t\ttimerfd_alarm_start(ctx, texp, !(flags & TFD_TIMER_ABSTIME));\n+\t\telse\n+\t\t\ttimerfd_hrtimer_start(ctx, texp, htmode);\n \n \t\tif (timerfd_canceled(ctx))\n \t\t\treturn -ECANCELED;\n@@ -287,27 +325,19 @@ static ssize_t timerfd_read_iter(struct\n \t}\n \n \tif (ctx->ticks) {\n-\t\tticks = ctx->ticks;\n+\t\tunsigned int expired = ctx->expired;\n \n-\t\tif (ctx->expired && ctx->tintv) {\n-\t\t\t/*\n-\t\t\t * If tintv != 0, this is a periodic timer that\n-\t\t\t * needs to be re-armed. We avoid doing it in the timer\n-\t\t\t * callback to avoid DoS attacks specifying a very\n-\t\t\t * short timer period.\n-\t\t\t */\n-\t\t\tif (isalarm(ctx)) {\n-\t\t\t\tticks += alarm_forward_now(\n-\t\t\t\t\t&ctx->t.alarm, ctx->tintv) - 1;\n-\t\t\t\talarm_restart(&ctx->t.alarm);\n-\t\t\t} else {\n-\t\t\t\tticks += hrtimer_forward_now(&ctx->t.tmr,\n-\t\t\t\t\t\t\t     ctx->tintv) - 1;\n-\t\t\t\thrtimer_restart(&ctx->t.tmr);\n-\t\t\t}\n-\t\t}\n+\t\tticks = ctx->ticks;\n \t\tctx->expired = 0;\n \t\tctx->ticks = 0;\n+\n+\t\t/*\n+\t\t * If tintv != 0, this is a periodic timer that needs to be\n+\t\t * re-armed. We avoid doing it in the timer callback to avoid\n+\t\t * DoS attacks specifying a very short timer period.\n+\t\t */\n+\t\tif (expired && ctx->tintv)\n+\t\t\tticks += timerfd_restart(ctx);\n \t}\n \tspin_unlock_irq(&ctx->wqh.lock);\n \tif (ticks) {\n@@ -526,18 +556,7 @@ static int do_timerfd_gettime(int ufd, s\n \tspin_lock_irq(&ctx->wqh.lock);\n \tif (ctx->expired && ctx->tintv) {\n \t\tctx->expired = 0;\n-\n-\t\tif (isalarm(ctx)) {\n-\t\t\tctx->ticks +=\n-\t\t\t\talarm_forward_now(\n-\t\t\t\t\t&ctx->t.alarm, ctx->tintv) - 1;\n-\t\t\talarm_restart(&ctx->t.alarm);\n-\t\t} else {\n-\t\t\tctx->ticks +=\n-\t\t\t\thrtimer_forward_now(&ctx->t.tmr, ctx->tintv)\n-\t\t\t\t- 1;\n-\t\t\thrtimer_restart(&ctx->t.tmr);\n-\t\t}\n+\t\tctx->ticks += timerfd_restart(ctx);\n \t}\n \tt->it_value = ktime_to_timespec64(timerfd_get_remaining(ctx));\n \tt->it_interval = ktime_to_timespec64(ctx->tintv);\n",
    "prefixes": [
        "V2",
        "08/11"
    ]
}