{"id":2220420,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2220420/?format=json","web_url":"http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260407083248.102440187@kernel.org/","project":{"id":26,"url":"http://patchwork.ozlabs.org/api/1.1/projects/26/?format=json","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":"<20260407083248.102440187@kernel.org>","date":"2026-04-07T08:54:58","name":"[09/12] fs/timerfd: Use the new alarm/hrtimer functions","commit_ref":null,"pull_url":null,"state":"accepted","archived":true,"hash":"82932c390dac6a10713a5c0acc7b5689751759e0","submitter":{"id":92397,"url":"http://patchwork.ozlabs.org/api/1.1/people/92397/?format=json","name":"Thomas Gleixner","email":"tglx@kernel.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260407083248.102440187@kernel.org/mbox/","series":[{"id":498944,"url":"http://patchwork.ozlabs.org/api/1.1/series/498944/?format=json","web_url":"http://patchwork.ozlabs.org/project/netfilter-devel/list/?series=498944","date":"2026-04-07T08:54:12","name":"hrtimers: Prevent hrtimer interrupt starvation","version":1,"mbox":"http://patchwork.ozlabs.org/series/498944/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2220420/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2220420/checks/","tags":{},"headers":{"Return-Path":"\n <netfilter-devel+bounces-11651-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=rExZgWkb;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c09:e001:a7::12fc:5321; helo=sto.lore.kernel.org;\n envelope-from=netfilter-devel+bounces-11651-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=\"rExZgWkb\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"],"Received":["from sto.lore.kernel.org (sto.lore.kernel.org\n [IPv6:2600:3c09:e001:a7::12fc:5321])\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 4fqg4s1BNkz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 07 Apr 2026 18:55:09 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sto.lore.kernel.org (Postfix) with ESMTP id CF852300BBA8\n\tfor <incoming@patchwork.ozlabs.org>; Tue,  7 Apr 2026 08:55:04 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 429B239B96D;\n\tTue,  7 Apr 2026 08:55:02 +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 B62F039B49D;\n\tTue,  7 Apr 2026 08:55:01 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id C79D6C2BC9E;\n\tTue,  7 Apr 2026 08:55:00 +0000 (UTC)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775552101; cv=none;\n b=Ev8lGfpFK+EkHPgWV7Bd6Ux0QEF29b7pem5ZqatwcH/ZeZHoFiPh6cl/JXBG6XZoXEwsFcDT2eB0kfM1AHyID6GXhNgRzItuU/7IVaHgyWjBoUPqn7lAE+YLoi8ywi5mTITw3tYGK56mVV+9dBJH8TnpbYum9+ub9LtJLop25rI=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775552101; c=relaxed/simple;\n\tbh=u8AI8RDvRZGzX0Utt+A54oYb3DpD5J4mYOgVVmHoy9M=;\n\th=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version:\n\t Content-Type;\n b=Oqqryc4YLJkRpqoqJ6hqdUx5GN8FeqAaVn9xh1BMcq85PJ26E/7anEZ3P7m2CvvE4oW0cAeKHS0GdmxVNb+wdFuOukvgdePWLgKNh7y5zc09u2NbxS89AP5vfLoW3UUwxvin1bCpdvlE6paRqvTc3jHwEaEQ4ggdHYYGksYj8Ss=","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=rExZgWkb; 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=1775552101;\n\tbh=u8AI8RDvRZGzX0Utt+A54oYb3DpD5J4mYOgVVmHoy9M=;\n\th=Date:From:To:Cc:Subject:References:From;\n\tb=rExZgWkbXR9kwaADPjSXATWJ03G725leNaOke/D/1liXugoBCuhBR7WJMwgUgTBj6\n\t PgWILOByVuqvSS81yZjMVolMM2Q47l2SbQIcC9HMKtTst9co/63RhTsHoqV215xnr7\n\t ZGmQQ/qEhtTdkY9AZYNGEqKsDwiEbmqAop2htdmPIWZTIJZa1myM1Eg51kCjLOSeZ4\n\t OT2VzHlzS93usQN2/rpc4q2gGgXJpTKcb+aMSUtgUFSV1LE/W3tFAXu5TK9RgGCjvS\n\t lUESNI9jmO5HhlmPtFQBuEY+8B/hn++K+o/IhXr4bJ0O0f0yE3JZSBFeYmqj2wPAHT\n\t BXBugYBQPJ4kQ==","Date":"Tue, 07 Apr 2026 10:54:58 +0200","Message-ID":"<20260407083248.102440187@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 <peterz@infradead.org>,\n Ingo Molnar <mingo@kernel.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 09/12] fs/timerfd: Use the new alarm/hrtimer functions","References":"<20260407083219.478203185@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: Thomas Gleixner <tglx@kernel.org>\nCc: linux-fsdevel@vger.kernel.org\n---\n fs/timerfd.c |  115 +++++++++++++++++++++++++++++++++--------------------------\n 1 file changed, 66 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,52 @@ 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 (!alarmtimer_start(&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+\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+\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 +247,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 +323,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 +554,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":["09/12"]}