Linux Documentation
 help / color / mirror / Atom feed
* Re: [PATCH v5 04/21] nfsd: allow nfsd to get a dir lease with an ignore mask
From: Chuck Lever @ 2026-06-08 16:29 UTC (permalink / raw)
  To: Jeff Layton, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker, Jonathan Corbet,
	Shuah Khan
  Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
	Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
	linux-doc, linux-nfs
In-Reply-To: <20260522-dir-deleg-v5-4-542cddfad576@kernel.org>


On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> When requesting a directory lease, enable the FL_IGN_DIR_* bits that
> correspond to the requested notification types.

> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 67e163ee13a2..2a34ba457b74 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c

> @@ -9642,12 +9657,11 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate,
>  		dp->dl_stid.sc_export =
>  			exp_get(cstate->current_fh.fh_export);
> 
> -	fl = nfs4_alloc_init_lease(dp);
> +	fl = nfs4_alloc_init_lease(dp, gdd->gddr_notification[0]);

Both Sashiko and my own gpt-5.5 review noted the use of a response field
here rather than a request field, but that is a false positive finding.
The commit message needs to explain why the use of gddr_notification[0]
is correct.


>  	if (!fl)
>  		goto out_put_stid;
> 
> -	status = kernel_setlease(nf->nf_file,
> -				 fl->c.flc_type, &fl, NULL);
> +	status = kernel_setlease(nf->nf_file, fl->c.flc_type, &fl, NULL);
>  	if (fl)
>  		locks_free_lease(fl);
>  	if (status)

This last edit appears to be a clean-up that is unrelated to the purpose
of the patch.


-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH v2 2/3] hwmon: Add update_interval_us chip attribute
From: Guenter Roeck @ 2026-06-08 16:34 UTC (permalink / raw)
  To: Ferdinand Schwenk
  Cc: Jonathan Corbet, Shuah Khan, linux-hwmon, linux-kernel, linux-doc,
	richard.leitner
In-Reply-To: <20260608-hwmon-ina238-update-interval-us-v2-v2-2-2d939fbb2ea1@advastore.com>

On Mon, Jun 08, 2026 at 03:03:55PM +0200, Ferdinand Schwenk wrote:
> From: Ferdinand Schwenk <ferdinand.schwenk@advastore.com>
> 
> Some hardware monitoring chips support update intervals below one
> millisecond. The existing update_interval attribute uses millisecond
> granularity, which causes sub-millisecond steps to round to the same
> value and become inaccessible from userspace.
> 
> Introduce update_interval_us, a companion chip-level attribute that
> expresses the same update interval in microseconds. Drivers
> implementing this attribute should also implement update_interval for
> compatibility with millisecond-based userspace interfaces.

Unfortunately, Signed-off-by: is missing. Otherwise looks good.

This also affects the other patches of the series.

Guenter

^ permalink raw reply

* Re: [PATCH v4 03/21] nfs_common: add new NOTIFY4_* flags proposed in RFC8881bis
From: Jeff Layton @ 2026-06-08 16:37 UTC (permalink / raw)
  To: Chuck Lever, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker
  Cc: Alexander Aring, Amir Goldstein, Jan Kara, Alexander Viro,
	Christian Brauner, Calum Mackay, linux-kernel, linux-doc,
	linux-nfs
In-Reply-To: <bf852bf8-2d80-4b12-8d7c-bb0770c8b379@app.fastmail.com>

On Mon, 2026-06-08 at 12:23 -0400, Chuck Lever wrote:
> Unfortunately, reviewing this series slipped off my radar. I'm just now
> getting to it. I'm going to do this in order and some of the earlier
> reviews are cosmetic. But there are some significant changes needed
> later on, so I expect we'll need to redrive this series and punt it to
> v7.3.
> 

That's reasonable. We had some unrelated new bugs crop up near the end
of the cycle that made it hard to get this in and tested properly. I'd
like to propose that we keep the VFS bits

> One thing you might update before you repost is to remove the "Acked-by:
> Chuck Lever" throughout the series.
> 

Ok. I think b4 added that.

> 
> Nit: the Subject: prefix should be "nfsd:" not "nfs_common:"
> 

include/linux/sunrpc/xdrgen/nfs4_1.h is a shared header. Anna will
presumably need this patch as well.

> 
> On Fri, May 22, 2026, at 8:28 AM, Jeff Layton wrote:
> > RFC8881bis adds some new flags to GET_DIR_DELEGATION that we very much
> > need to support.
> 
> Nit: Let's say: "RFC8881bis adds new flags to GET_DIR_DELEGATION
> that later patches consume."
> 
> One recent private comment to me was a question about whether we can
> trust the stability of the specification, which is still a WG document
> and has been for years. This patch's commit message should address
> that.
> 

That's definitely an open question. We are definitely adopting these
changes before the ink is dry. We might have to modify things later,
especially once there is more client-side experience.

I'm open to verbiage suggestions here.


> 
> > diff --git a/Documentation/sunrpc/xdr/nfs4_1.x 
> > b/Documentation/sunrpc/xdr/nfs4_1.x
> > index 632f5b579c39..aa14b590b524 100644
> > --- a/Documentation/sunrpc/xdr/nfs4_1.x
> > +++ b/Documentation/sunrpc/xdr/nfs4_1.x
> > @@ -416,7 +416,21 @@ enum notify_type4 {
> >          NOTIFY4_REMOVE_ENTRY = 2,
> >          NOTIFY4_ADD_ENTRY = 3,
> >          NOTIFY4_RENAME_ENTRY = 4,
> > -        NOTIFY4_CHANGE_COOKIE_VERIFIER = 5
> > +        NOTIFY4_CHANGE_COOKIE_VERIFIER = 5,
> > +        /*
> > +         * Added in NFSv4.1 bis document
> > +         */
> 
> I clarified this comment: "/* Proposed in RFC8881bis */"
> 
> I rebuilt the generated source to confirm that it hasn't been altered
> by recent changes to xdrgen or this comment change. The only thing
> that changed in the output was the header's timestamp.
> 

Sounds good.
-- 
Jeff Layton <jlayton@kernel.org>

^ permalink raw reply

* Re: [PATCH v5 05/21] nfsd: update the fsnotify mark when setting or removing a dir delegation
From: Chuck Lever @ 2026-06-08 16:38 UTC (permalink / raw)
  To: Jeff Layton, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker, Jonathan Corbet,
	Shuah Khan
  Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
	Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
	linux-doc, linux-nfs
In-Reply-To: <20260522-dir-deleg-v5-5-542cddfad576@kernel.org>



On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> Add a new helper function that will update the mask on the nfsd_file's
> fsnotify_mark to be a union of all current directory delegations on an
> inode. Call that when directory delegations are added or removed.

This commit message repeats what the diff below says. Can it instead
explain why this change is necessary?


> Reviewed-by: Jan Kara <jack@suse.cz>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> ---
>  fs/nfsd/nfs4state.c | 34 ++++++++++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
>
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 2a34ba457b74..efbc99f0a965 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -1246,6 +1246,38 @@ static void 
> nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct f
>  	nfsd_update_cmtime_attr(f, ATTR_ATIME);
>  }
> 
> +static void nfsd_fsnotify_recalc_mask(struct nfsd_file *nf)

Since nfsd_fsnotify_recalc_mask() takes a single struct nfsd_file
as an argument, should this function reside in fs/nfsd/filecache.c
instead? The question might reflect my misunderstanding of the
new function's purpose.


> +{
> +	struct inode *inode = file_inode(nf->nf_file);
> +	u32 lease_mask, set = 0, clear = 0;
> +	struct fsnotify_mark *mark;
> +
> +	/* This is only needed when adding or removing dir delegs */
> +	if (!S_ISDIR(inode->i_mode) || !nf->nf_mark)
> +		return;
> +
> +	/* Set up notifications for any ignored delegation events */
> +	lease_mask = inode_lease_ignore_mask(inode);
> +	mark = &nf->nf_mark->nfm_mark;
> +
> +	if (lease_mask & FL_IGN_DIR_CREATE)
> +		set |= FS_CREATE | FS_MOVED_TO;
> +	else
> +		clear |= FS_CREATE | FS_MOVED_TO;
> +
> +	if (lease_mask & FL_IGN_DIR_DELETE)
> +		set |= FS_DELETE | FS_MOVED_FROM;
> +	else
> +		clear |= FS_DELETE | FS_MOVED_FROM;
> +
> +	if (lease_mask & FL_IGN_DIR_RENAME)
> +		set |= FS_RENAME;
> +	else
> +		clear |= FS_RENAME;
> +
> +	fsnotify_modify_mark_mask(mark, set, clear);
> +}
> +
>  static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
>  {
>  	struct nfs4_file *fp = dp->dl_stid.sc_file;
> @@ -1255,6 +1287,7 @@ static void nfs4_unlock_deleg_lease(struct 
> nfs4_delegation *dp)
> 
>  	nfsd4_finalize_deleg_timestamps(dp, nf->nf_file);
>  	kernel_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp);
> +	nfsd_fsnotify_recalc_mask(nf);
>  	put_deleg_file(fp);
>  }
> 

I added the following edit to this patch>

@@ -9597,8 +9629,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry,
  * @nf: nfsd_file opened on the directory
  *
  * Given a GET_DIR_DELEGATION request @gdd, attempt to acquire a delegation
- * on the directory to which @nf refers. Note that this does not set up any
- * sort of async notifications for the delegation.
+ * on the directory to which @nf refers.
  */
 struct nfs4_delegation *
 nfsd_get_dir_deleg

The patch makes the above kerneldoc note ("does not set up any sort of async
notifications") logically obsolete.


> @@ -9682,6 +9715,7 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate,
> 
>  	if (!status) {
>  		put_nfs4_file(fp);
> +		nfsd_fsnotify_recalc_mask(nf);
>  		return dp;
>  	}
> 
>
> -- 
> 2.54.0

-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Yosry Ahmed @ 2026-06-08 16:44 UTC (permalink / raw)
  To: Nhat Pham
  Cc: Hao Jia, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
	chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAKEwX=PF9hfERC_QMq+rjkSc-BsJyawMgTe+EhwR_86HiQKm=Q@mail.gmail.com>

On Mon, Jun 8, 2026 at 9:23 AM Nhat Pham <nphamcs@gmail.com> wrote:
>
> On Mon, Jun 8, 2026 at 5:50 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
> > On 2026/6/5 01:23, Nhat Pham wrote:
> > >
> >
> > Thanks for the suggestion!
> >
> > I ran some tests and found that neither the per-memcg cursor nor
> > different batch sizes have a significant impact on proactive writeback
> > performance. However, exactly as we suspected, without the per-memcg
> > cursor, the writeback distribution among child memcgs is highly unfair.
> >
> > Test Setup:
> >
> >    zswap config: 18G capacity, LZ4 compression.
> >    cgroup hierarchy: 1 parent test memcg with 10 child memcgs.
> >    Allocation: Allocated 1600MB of anonymous pages in each child memcg.
> > To ensure compressibility, the first half of each page was filled with
> > random data and the second half with zeros.
> >    Force to zswap: Ran echo "1600M" > memory.reclaim on each child memcg
> > to squeeze all their memory into zswap.
> >    Trigger writeback: Ran echo "<size> zswap_writeback_only" >
> > memory.reclaim on the parent cgroup 200 times, with a 2-second interval
> > between each run.
> >    Metric: Monitored the zswpwb_proactive metric in memory.stat to
> > observe the writeback volume.
> >    **Note**: The size here refers to the uncompressed memory size. Also,
> > since the second-chance algorithm would cause many writebacks to fall
> > short of the target size, I **bypassed** it during these tests to avoid
> > interference.
> >
> > Without cursor (size: 1M, batch: 32)
> >    child        wb_pages        wb_MB     share%
> >    child0           6368        24.88      12.50
> >    child1           6368        24.88      12.50
> >    child2           6368        24.88      12.50
> >    child3           6368        24.88      12.50
> >    child4           6368        24.88      12.50
> >    child5           6368        24.88      12.50
> >    child6           6368        24.88      12.50
> >    child7           6368        24.88      12.50
> >    child8              0         0.00       0.00
> >    child9              0         0.00       0.00
> > Without cursor (size: 1M, batch: 128)
> >    child        wb_pages        wb_MB     share%
> >    child0          25472        99.50      50.00
> >    child1          25472        99.50      50.00
> >    child2              0         0.00       0.00
> >    child3              0         0.00       0.00
> >    child4              0         0.00       0.00
> >    child5              0         0.00       0.00
> >    child6              0         0.00       0.00
> >    child7              0         0.00       0.00
> >    child8              0         0.00       0.00
> >    child9              0         0.00       0.00
> > Without cursor (size: 6M, batch: 128)
> >    child        wb_pages        wb_MB     share%
> >    child0          51200       200.00      16.67
> >    child1          51200       200.00      16.67
> >    child2          25600       100.00       8.33
> >    child3          25600       100.00       8.33
> >    child4          25600       100.00       8.33
> >    child5          25600       100.00       8.33
> >    child6          25600       100.00       8.33
> >    child7          25600       100.00       8.33
> >    child8          25600       100.00       8.33
> >    child9          25600       100.00       8.33
> >
> >
> > With cursor (size: 1M, batch: 32)
> >    child        wb_pages        wb_MB     share%
> >    child0           5120        20.00      10.00
> >    child1           5120        20.00      10.00
> >    child2           5120        20.00      10.00
> >    child3           5120        20.00      10.00
> >    child4           5120        20.00      10.00
> >    child5           5120        20.00      10.00
> >    child6           5120        20.00      10.00
> >    child7           5120        20.00      10.00
> >    child8           5120        20.00      10.00
> >    child9           5120        20.00      10.00
> > With cursor (size: 1M, batch: 128)
> >    child        wb_pages        wb_MB     share%
> >    child0           5120        20.00      10.00
> >    child1           5120        20.00      10.00
> >    child2           5120        20.00      10.00
> >    child3           5120        20.00      10.00
> >    child4           5120        20.00      10.00
> >    child5           5120        20.00      10.00
> >    child6           5120        20.00      10.00
> >    child7           5120        20.00      10.00
> >    child8           5120        20.00      10.00
> >    child9           5120        20.00      10.00

Yes, the per-memcg cursor is more fair, and you can synthesize
scenarios that show that. However, I don't think this is a problem in
practice:

1. The unfairness is limited to the batch size per-invocation. If the
batch size is 128 pages (your highest one here), that's 0.5 MB (on
x86), which is fairly low? If the batch size is 32, it's even less.

2. Realistically, if you have a parent cgroup with with >10G of
memory, you wouldn't be reclaiming in steps of 1M. If you want to
reclaim 200MB, why are you doing it over 200 invocations? If you do it
in a single one (or over a few retries) the shares should become much
more even.

We're trying to fix a practical use case, not finding reasons why a
simple implementation won't work -- right?

More below (to Nhat's point).

>
> Yeah OTOH, we don't really make fairness an API contract here. When
> you set up a proactive reclaim scheme, if you decide to target a
> cgroup (and not its children separately), everything underneath it is
> fair game to the kernel in any split that we fancy. If you want true
> fairness or a desired split, you have to treat them as independent
> memory domains and set up proactive reclaim to hit each child cgroup
> separately (i.e one "echo > memory.reclaim" for each of them). This is
> necessary for example if each child represents a separate, isolated
> service/container/tenant. And maybe this is actually what you really
> want - hit the ancestor cgroup very lightly for the stuff it owns, but
> then dedidcate most of the reclaim effort at the leaf cgroups
> independently?

I would go a bit farther and claim that ideally fairness shouldn't
even be a factor. If you invoke proactive reclaim on a parent cgroup
with 100MB, you want to reclaim the coldest 100MB in that parent, no
matter what child they reside in. If one child cgroup has 100% hot
memory and one child cgroup has 100% cold memory, ideally you'd
reclaim all the cold memory from the second child.

However, the implementation of the LRUs and the coldness tracking
doesn't allow for doing this, so we "fallback" to reclaiming in
batches from each child because we don't really know where the coldest
pages overall are. If that changes in the future (somehow), I argue
that the correct thing to do is reclaim the absolute coldest memory at
the parent level.

If you want to reclaim evenly among the children, you can do that and
directly reclaim from the children.

>
> But OTOH, this does seem like a recipe for inefficient reclaim. We
> might exhaust hotter memory of a cgroup while sparing colder memory of
> another cgroup... But maybe if they're all cold anyway, then who
> cares, and eventually you'll get to the cold stuff of other child?
>
> Yosry, what's the concern here? Is it space overhead, or overall code
> complexity?

Mostly the complexity (e.g. the zombie memcg cleanup) and a tiny bit
the unnecessary space (8 bytes is not a lot, but these things add up).

^ permalink raw reply

* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Yosry Ahmed @ 2026-06-08 16:48 UTC (permalink / raw)
  To: Nhat Pham
  Cc: Hao Jia, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
	chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAKEwX=PF9hfERC_QMq+rjkSc-BsJyawMgTe+EhwR_86HiQKm=Q@mail.gmail.com>

> But OTOH, this does seem like a recipe for inefficient reclaim. We
> might exhaust hotter memory of a cgroup while sparing colder memory of
> another cgroup... But maybe if they're all cold anyway, then who
> cares, and eventually you'll get to the cold stuff of other child?

Forgot to respond to this part, the unfairness is limited to the batch
size per-invocation, so it should be fine as long as you don't divide
the amount over 100 iterations for some reason. Also yes, all memory
in zswap is cold, the relative coldness is not that important (e.g.
compared to relative coldness during reclaim).

^ permalink raw reply

* Re: [PATCH v3 3/4] cpufreq: Remove driver default policy->min/max init
From: Rafael J. Wysocki @ 2026-06-08 16:50 UTC (permalink / raw)
  To: Pierre Gondois
  Cc: Rafael J. Wysocki, linux-kernel, Jie Zhan, Lifeng Zheng,
	Ionela Voinescu, Sumit Gupta, Zhongqiu Han, Viresh Kumar,
	Jonathan Corbet, Shuah Khan, Huang Rui, Mario Limonciello,
	Perry Yuan, K Prateek Nayak, Srinivas Pandruvada, Len Brown,
	Saravana Kannan, linux-pm, linux-doc
In-Reply-To: <6447f46d-5a60-45a2-b585-9835c9c26893@arm.com>

Hi,

On Wed, Jun 3, 2026 at 9:49 AM Pierre Gondois <pierre.gondois@arm.com> wrote:
>
> Hello Rafael,
>
> On 6/1/26 20:08, Rafael J. Wysocki wrote:
> > On Thu, May 28, 2026 at 11:10 AM Pierre Gondois <pierre.gondois@arm.com> wrote:
> >> Prior to [1], drivers were setting policy->min/max and
> >> the value was used as a QoS constraint. After that change,
> >> the values were only temporarily used: cpufreq_set_policy()
> >> ultimately overriding them through:
> >> cpufreq_policy_online()
> >> \-cpufreq_init_policy()
> >>    \-cpufreq_set_policy()
> >>      \-/* Set policy->min/max */
> >>
> >> This patch reinstate the initial behaviour. This will allow
> >> drivers to request min/max QoS frequencies if desired.
> >> For instance, the cppc driver advertises a lowest non-linear
> >> frequency, which should be used as a min QoS value.
> >>
> >> To avoid having drivers setting policy->min/max to default
> >> values which are considered as QoS values (i.e. the reason
> >> why [1] was introduced), remove the initialization of
> >> policy->min/max in .init() callbacks wherever the
> >> policy->min/max values are identical to the
> >> policy->cpuinfo.min/max_freq.
> >>
> >> Indeed, the previous patch ("cpufreq: Set default
> >> policy->min/max values for all drivers") makes this initialization
> >> redundant.
> >>
> >> The only drivers where these values are different are:
> >> - gx-suspmod.c (min)
> >> - cppc-cpufreq.c (min)
> >> - longrun.c
> >>
> >> [1]
> >> commit 521223d8b3ec ("cpufreq: Fix initialization of min and
> >> max frequency QoS requests")
> >>
> >> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> >> Acked-by: Jie Zhan <zhanjie9@hisilicon.com>
> > sashiko.dev has some feedback on this patch and appears to have a point:
> >
> > https://sashiko.dev/#/patchset/20260528090913.2759118-1-pierre.gondois%40arm.com
> >
> > Can you have a look at it please?
> >
> [sashiko]
>
>  > Does removing the policy->max = max_freq assignment here break UAPI
>  > expectations by exposing the unlisted boost frequency in
> scaling_max_freq?
>  >
>  > Commit 538b0188da4653 intentionally allowed drivers like acpi-cpufreq
> to set
>  > policy->cpuinfo.max_freq to a higher boost frequency while relying on
>  > cpufreq_frequency_table_cpuinfo() to clamp policy->max to the frequency
>  > table's nominal maximum (max_freq). This ensured that user-space
> tools saw
>  > the nominal maximum in scaling_max_freq.
>  >
>  > Although commit 521223d8b3ec temporarily disrupted this by defaulting
> the QoS
>  > max to -1, a subsequent patch in this series changes the core to
> initialize
>  > the QoS request using policy->max.
>
> Effectively PATCH [4/4] cpufreq: Use policy->min/max init as QoS request
> now uses the policy->max value set by the .init() callback to set
> the max_freq_req QoS constraint.
>
>  >
>  > If the policy->max = max_freq assignment were preserved, the subsequent
>  > patch would successfully use the nominal frequency as the QoS max
> request,
>  > restoring the correct clamping behavior.
>
> IIUC this suggests to use the nominal freq. as the QoS max request.
> This was behaving like that prior to 521223d8b3ec. However doing
> that would mean that if boost is enabled and the max_freq_req sysfs
> is not updated, then the frequency would still be clamped by
> the max_freq_req. 521223d8b3ec intended to correct that.
>
> Sashiko seems to suggest modifications to come back to the
> pre-521223d8b3ec behaviour, but I think 521223d8b3ec is correct
> and we should conserve this behaviour.

So there is some confusion in the patch changelogs of this series, but
not in the code, regarding the role of the last argument of
freq_qos_add_request().  Namely, that argument is the initial request
value for the given request object which is subsequently managed by
user space.  User space may in fact change it to whatever value it
wants (either lower or higher) and it is only taken into account along
with the other requests in the given chain.  IMV it is better to
clarify that, so I have updated the changelogs when applying the
patches.

Please see

https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/commit/?h=bleeding-edge&id=8c83947c5dbbd49b36d08bb99e344327c6278781

and its ancestors and let me know if there's anything missing in the
changelogs thereof.

Thanks!

^ permalink raw reply

* Re: [PATCH v5 07/21] nfsd: add callback encoding and decoding linkages for CB_NOTIFY
From: Chuck Lever @ 2026-06-08 16:52 UTC (permalink / raw)
  To: Jeff Layton, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker, Jonathan Corbet,
	Shuah Khan
  Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
	Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
	linux-doc, linux-nfs
In-Reply-To: <20260522-dir-deleg-v5-7-542cddfad576@kernel.org>



On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> Add routines for encoding and decoding CB_NOTIFY messages. These call
> into the code generated by xdrgen to do the actual encoding and
> decoding.

The commit message needs to explain that the encoder is not yet functional.
Something like: "The encoder is a stub; payload encoding (stateid, fh, and
cna_changes) is deferred."


> diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
> index 25bbf5b8814d..ea3e7deb06fa 100644
> --- a/fs/nfsd/nfs4callback.c
> +++ b/fs/nfsd/nfs4callback.c
> @@ -865,6 +865,51 @@ static void encode_stateowner(struct xdr_stream 
> *xdr, struct nfs4_stateowner *so
>  	xdr_encode_opaque(p, so->so_owner.data, so->so_owner.len);
>  }
> 
> +static void nfs4_xdr_enc_cb_notify(struct rpc_rqst *req,
> +				   struct xdr_stream *xdr,
> +				   const void *data)
> +{
> +	const struct nfsd4_callback *cb = data;
> +	struct nfs4_cb_compound_hdr hdr = {
> +		.ident = 0,
> +		.minorversion = cb->cb_clp->cl_minorversion,
> +	};
> +	struct CB_NOTIFY4args args = { };
> +
> +	WARN_ON_ONCE(hdr.minorversion == 0);
> +
> +	encode_cb_compound4args(xdr, &hdr);
> +	encode_cb_sequence4args(xdr, cb, &hdr);
> +
> +	/*
> +	 * FIXME: get stateid and fh from delegation. Inline the cna_changes
> +	 * buffer, and zero it.
> +	 */
> +	WARN_ON_ONCE(!xdrgen_encode_CB_NOTIFY4args(xdr, &args));
> +
> +	hdr.nops++;
> +	encode_cb_nops(&hdr);
> +}

There are a number of problems with this, but since there are no
callers yet, we can let some of those issues stand.

What is problematic in the longer-term is that this is a client-side
encoder (since this is the server's NFSv4 callback client).

xdrgen_encode_CB_NOTIFY4args() is an argument encoder, which is
client-side functionality, but it resides in fs/nfsd/nfs4xdr_gen.c,
which is server-side. Let's not mix these purposes.

I replaced the comment and WARN_ON with this:

+       xdr_stream_encode_u32(xdr, OP_CB_NOTIFY);
+
+       /* FIXME: encode stateid, fh, and cna_changes from delegation */

You can use xdrgen functions for individual data items, but for
full argument and response structures, only server-side is supported
at the moment. In the later patch that completes this code, I'll cover
the other fields, which can be a mix of open code and xdrgen.


> diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
> index e1c40f8b5d01..790282781243 100644
> --- a/fs/nfsd/state.h
> +++ b/fs/nfsd/state.h
> @@ -190,6 +190,13 @@ struct nfs4_cb_fattr {
>  	u64 ncf_cur_fsize;
>  };
> 
> +/*
> + * FIXME: the current backchannel encoder can't handle a send buffer longer
> + *        than a single page (see bc_alloc/bc_free).
> + */

Nit: The allocator function name is bc_malloc


-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH v5 08/21] nfsd: use RCU to protect fi_deleg_file
From: Chuck Lever @ 2026-06-08 17:00 UTC (permalink / raw)
  To: Jeff Layton, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker, Jonathan Corbet,
	Shuah Khan
  Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
	Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
	linux-doc, linux-nfs
In-Reply-To: <20260522-dir-deleg-v5-8-542cddfad576@kernel.org>



On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> fi_deleg_file can be NULLed by put_deleg_file() when fi_delegees drops
> to zero during delegation teardown (e.g. DELEGRETURN). Concurrent
> accesses from workqueue callbacks -- such as CB_NOTIFY -- can
> dereference a NULL pointer if they race with this teardown.

> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 3efc53f0dde6..bd0517dfe881 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -1212,7 +1212,9 @@ static void put_deleg_file(struct nfs4_file *fp)
> 
>  	spin_lock(&fp->fi_lock);
>  	if (--fp->fi_delegees == 0) {
> -		swap(nf, fp->fi_deleg_file);
> +		nf = rcu_dereference_protected(fp->fi_deleg_file,
> +					       lockdep_is_held(&fp->fi_lock));
> +		rcu_assign_pointer(fp->fi_deleg_file, NULL);

Nit: For consistency, the above could be
RCU_INIT_POINTER(fp->fi_deleg_file, NULL);


>  		swap(rnf, fp->fi_rdeleg_file);
>  	}
>  	spin_unlock(&fp->fi_lock);

> @@ -9722,7 +9729,7 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state 
> *cstate,
>  	}
> 
>  	/* Something failed. Drop the lease and clean up the stid */
> -	kernel_setlease(fp->fi_deleg_file->nf_file, F_UNLCK, NULL, (void **)&dp);
> +	kernel_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp);
>  out_put_stid:
>  	nfs4_put_stid(&dp->dl_stid);
>  out_delegees:

We might want:

        kernel_setlease(rcu_dereference_protected(fp->fi_deleg_file, 1)->nf_file,
                  F_UNLCK, NULL, (void **)&dp);

instead, to avoid the Sashiko-reported UAF finding.

-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH v2] hwmon: add a driver for the temp/voltage sensor on PolarFire SoC
From: Guenter Roeck @ 2026-06-08 17:03 UTC (permalink / raw)
  To: Conor Dooley, linux-hwmon
  Cc: Lars Randers, Conor Dooley, Jonathan Corbet, Shuah Khan,
	Daire McNamara, linux-doc, linux-kernel, linux-riscv,
	Valentina.FernandezAlanis
In-Reply-To: <20260603-ongoing-brunette-51e35be6d93e@spud>

On 6/3/26 06:19, Conor Dooley wrote:
> From: Lars Randers <lranders@mail.dk>
> 
> Add a driver for the temperature and voltage sensors on PolarFire SoC.
> The temperature reports how hot the die is, and the voltages are the
> SoC's 1.05, 1.8 and 2.5 volt rails respectively.
> 
> The hardware supports alarms in theory, but there is an erratum that
> prevents clearing them once triggered, so no support is added for them.
> 
> The hardware measures voltage with 16 bits, of which 1 is a sign bit and
> the remainder holds the voltage as a fixed point integer value. It's
> improbable that the hardware will work if the voltages are negative, so
> the driver ignores the sign bits.
> 
> There's no dt support etc here because this is the child of a simple-mfd
> syscon.
> 
> Signed-off-by: Lars Randers <lranders@mail.dk>
> Co-developed-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>

Comments inline.

Thanks,
Guenter


> ---
> 
> v2:
> - Fix some minor things pointed out by Sashiko including inaccurate
>    comments, bounds checking of values read from sysfs and Kconfig
>    dependencies.
> - Make update_interval use milliseconds instead of microseconds
>    (I'll add update_interval_us support when that lands, there's a
>    proposed workaround for the erratum circulating internally, so it'll
>    probably come alongside alarm support).
> 
> CC: Guenter Roeck <linux@roeck-us.net>
> CC: Jonathan Corbet <corbet@lwn.net>
> CC: Shuah Khan <skhan@linuxfoundation.org>
> CC: Conor Dooley <conor.dooley@microchip.com>
> CC: Daire McNamara <daire.mcnamara@microchip.com>
> CC: linux-hwmon@vger.kernel.org
> CC: linux-doc@vger.kernel.org
> CC: linux-kernel@vger.kernel.org
> CC: linux-riscv@lists.infradead.org
> CC: Valentina.FernandezAlanis@microchip.com
> ---
>   Documentation/hwmon/index.rst    |   1 +
>   Documentation/hwmon/tvs-mpfs.rst |  53 +++++
>   MAINTAINERS                      |   1 +
>   drivers/hwmon/Kconfig            |  13 +
>   drivers/hwmon/Makefile           |   1 +
>   drivers/hwmon/tvs-mpfs.c         | 394 +++++++++++++++++++++++++++++++
>   6 files changed, 463 insertions(+)
>   create mode 100644 Documentation/hwmon/tvs-mpfs.rst
>   create mode 100644 drivers/hwmon/tvs-mpfs.c
> 
> diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
> index 8b655e5d6b68..84a5339e1d6f 100644
> --- a/Documentation/hwmon/index.rst
> +++ b/Documentation/hwmon/index.rst
> @@ -262,6 +262,7 @@ Hardware Monitoring Kernel Drivers
>      tps53679
>      tps546d24
>      tsc1641
> +   tvs-mpfs
>      twl4030-madc-hwmon
>      ucd9000
>      ucd9200
> diff --git a/Documentation/hwmon/tvs-mpfs.rst b/Documentation/hwmon/tvs-mpfs.rst
> new file mode 100644
> index 000000000000..ff445844d07c
> --- /dev/null
> +++ b/Documentation/hwmon/tvs-mpfs.rst
> @@ -0,0 +1,53 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +Kernel driver tvs-mpfs
> +======================
> +
> +Supported chips:
> +
> +  * PolarFire SoC
> +
> +Authors:
> +
> +   - Conor Dooley <conor.dooley@microchip.com>
> +   - Lars Randers <lranders@mail.dk>
> +
> +Description
> +-----------
> +
> +This driver implements support for the temperature and voltage sensors on
> +PolarFire SoC. The temperature reports how hot the die is, and the voltages are
> +the SoC's 1.05, 1.8 and 2.5 volt rails respectively.
> +
> +
> +Usage Notes
> +-----------
> +
> +update_interval has a permitted range of 0 to 8.
> +
> +

It might make sense to document what "0" means.

Temperatures are read in millidegrees Celsius, but the hardware measures in
> +degrees Kelvin, storing the result as 11.4 fixed point data, for a maximum
> +value of 2047.9375 degrees Kelvin.
> +
> +Voltages are read in millivolts. The hardware measures in millivolts, storing
> +the value as 12.3 fixed point data, for a maximum of 4095.875 millivolts.
> +The minimum value reportable by the driver is 0 volts, although the hardware
> +is capable of measuring negative values.
> +
> +Sysfs entries
> +-------------
> +
> +The following attributes are supported. update_interval is read-write, as are
> +the enables. All other attributes are read only.
> +
> +======================= ====================================================
> +temp1_label		Fixed name for channel.
> +temp1_input		Measured temperature for channel.
> +temp1_enable		Enable/disable for channel.
> +
> +in[0-2]_label		Fixed name for channel.
> +in[0-2]_input		Measured voltage for channel.
> +in[0-2]_enable		Enable/disable for channel.
> +
> +update_interval		The interval at which the chip will update readings.
> +======================= ====================================================
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2fb1c75afd16..a492cf5ad0fc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -22938,6 +22938,7 @@ F:	drivers/char/hw_random/mpfs-rng.c
>   F:	drivers/clk/microchip/clk-mpfs*.c
>   F:	drivers/firmware/microchip/mpfs-auto-update.c
>   F:	drivers/gpio/gpio-mpfs.c
> +F:	drivers/hwmon/tvs-mpfs.c
>   F:	drivers/i2c/busses/i2c-microchip-corei2c.c
>   F:	drivers/mailbox/mailbox-mpfs.c
>   F:	drivers/pci/controller/plda/pcie-microchip-host.c
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 14e4cea48acc..2b9622b1db95 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -930,6 +930,19 @@ config SENSORS_JC42
>   	  This driver can also be built as a module. If so, the module
>   	  will be called jc42.
>   
> +config SENSORS_POLARFIRE_SOC_TVS
> +	tristate "PolarFire SoC (MPFS) temperature and voltage sensor"
> +	depends on POLARFIRE_SOC_SYSCONS || COMPILE_TEST
> +	depends on MFD_SYSCON
> +	help
> +	  This driver adds support for the PolarFire SoC (MPFS) Temperature and
> +	  Voltage Sensor.
> +
> +	  To compile this driver as a module, choose M here. the
> +	  module will be called tvs-mpfs.
> +
> +	  If unsure, say N.
> +
>   config SENSORS_POWERZ
>   	tristate "ChargerLAB POWER-Z USB-C tester"
>   	depends on USB
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 4788996aa137..b58d249e4cf4 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -194,6 +194,7 @@ obj-$(CONFIG_SENSORS_NZXT_SMART2) += nzxt-smart2.o
>   obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
>   obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
>   obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
> +obj-$(CONFIG_SENSORS_POLARFIRE_SOC_TVS)  += tvs-mpfs.o
>   obj-$(CONFIG_SENSORS_POWERZ)	+= powerz.o
>   obj-$(CONFIG_SENSORS_POWR1220)  += powr1220.o
>   obj-$(CONFIG_SENSORS_PT5161L)	+= pt5161l.o
> diff --git a/drivers/hwmon/tvs-mpfs.c b/drivers/hwmon/tvs-mpfs.c
> new file mode 100644
> index 000000000000..f086f178b4ba
> --- /dev/null
> +++ b/drivers/hwmon/tvs-mpfs.c
> @@ -0,0 +1,394 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Lars Randers <lranders@mail.dk>
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/err.h>
> +#include <linux/freezer.h>
> +#include <linux/hwmon.h>
> +#include <linux/io.h>
> +#include <linux/kthread.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define MPFS_TVS_CTRL 0x08
> +#define MPFS_TVS_OUTPUT0 0x24
> +#define MPFS_TVS_OUTPUT1 0x28
> +
> +#define MPFS_TVS_CTRL_TEMP_VALID	BIT(19)
> +#define MPFS_TVS_CTRL_V2P5_VALID	BIT(18)
> +#define MPFS_TVS_CTRL_V1P8_VALID	BIT(17)
> +#define MPFS_TVS_CTRL_V1P05_VALID	BIT(16)
> +
> +#define MPFS_TVS_CTRL_TEMP_ENABLE	BIT(3)
> +#define MPFS_TVS_CTRL_V2P5_ENABLE	BIT(2)
> +#define MPFS_TVS_CTRL_V1P8_ENABLE	BIT(1)
> +#define MPFS_TVS_CTRL_V1P05_ENABLE	BIT(0)
> +#define MPFS_TVS_CTRL_ENABLE_ALL	GENMASK(3, 0)
> +
> +/*
> + * For all of these the value in millivolts is stored in 16 bits, with an upper
> + * sign bit and a lower 3 bits of decimal. These masks discard the sign bit and
> + * decimal places, because if Linux is running these voltages cannot be negative
> + * and so avoid having to convert to two's complement.
> + */
> +#define MPFS_OUTPUT0_V1P8_MASK	GENMASK(30, 19)
> +#define MPFS_OUTPUT0_V1P05_MASK	GENMASK(14, 3)
> +#define MPFS_OUTPUT1_V2P5_MASK	GENMASK(14, 3)
> +
> +/*
> + * The register map claims that the temperature is stored in bits 31:16, but
> + * application note "AN4682: PolarFire FPGA Temperature and Voltage Sensor"
> + * says that 31 is reserved. Temperature is in kelvin, so what's probably a
> + * sign bit has no value anyway.
> + */
> +#define MPFS_OUTPUT1_TEMP_MASK GENMASK(30, 16)
> +
> +#define MPFS_TVS_INTERVAL_MASK GENMASK(15, 8)
> +#define MPFS_TVS_INTERVAL_OFFSET 8
> +/* The interval register is in increments of 32 us */
> +#define MPFS_TVS_INTERVAL_SCALE 32
> +
> +/* 273.1875 in 11.4 fixed-point notation */
> +#define MPFS_TVS_K_TO_C 0x1113
> +
> +enum mpfs_tvs_sensors {
> +	SENSOR_V1P05 = 0,
> +	SENSOR_V1P8,
> +	SENSOR_V2P5,
> +};
> +
> +static const char * const mpfs_tvs_voltage_labels[] = { "1P05", "1P8", "2P5" };
> +
> +struct mpfs_tvs {
> +	struct regmap *regmap;
> +};
> +
> +static int mpfs_tvs_voltage_read(struct mpfs_tvs *data, u32 attr,
> +				 int channel, long *val)
> +{
> +	u32 tmp, control;
> +
> +	if (attr != hwmon_in_input && attr != hwmon_in_enable)
> +		return -EOPNOTSUPP;
> +
> +	regmap_read(data->regmap, MPFS_TVS_CTRL, &control);
> +
> +	switch (channel) {
> +	case SENSOR_V2P5:
> +		if (attr == hwmon_in_enable) {
> +			*val = FIELD_GET(MPFS_TVS_CTRL_V2P5_ENABLE, control);
> +			break;
> +		}
> +
> +		if (!(control & MPFS_TVS_CTRL_V2P5_VALID))
> +			return -EINVAL;
> +
> +		regmap_read(data->regmap, MPFS_TVS_OUTPUT1, &tmp);
> +		*val = FIELD_GET(MPFS_OUTPUT1_V2P5_MASK, tmp);
> +		break;
> +	case SENSOR_V1P8:
> +		if (attr == hwmon_in_enable) {
> +			*val = FIELD_GET(MPFS_TVS_CTRL_V1P8_ENABLE, control);
> +			break;
> +		}
> +
> +		if (!(control & MPFS_TVS_CTRL_V1P8_VALID))
> +			return -EINVAL;
> +
> +		regmap_read(data->regmap, MPFS_TVS_OUTPUT0, &tmp);
> +		*val = FIELD_GET(MPFS_OUTPUT0_V1P8_MASK, tmp);
> +		break;
> +	case SENSOR_V1P05:
> +		if (attr == hwmon_in_enable) {
> +			*val = FIELD_GET(MPFS_TVS_CTRL_V1P05_ENABLE, control);
> +			break;
> +		}
> +
> +		if (!(control & MPFS_TVS_CTRL_V1P05_VALID))
> +			return -EINVAL;
> +
> +		regmap_read(data->regmap, MPFS_TVS_OUTPUT0, &tmp);
> +		*val = FIELD_GET(MPFS_OUTPUT0_V1P05_MASK, tmp);
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mpfs_tvs_voltage_write(struct mpfs_tvs *data, u32 attr,
> +				  int channel, long val)
> +{
> +	u32 tmp;
> +
> +	if (attr != hwmon_in_enable)
> +		return -EOPNOTSUPP;
> +
> +	switch (channel) {
> +	case SENSOR_V2P5:
> +		if (val > 1 || val < 0)
> +			return -EINVAL;
> +

Range check should happen only once. The -EOPNOTSUPP
is theoretic (channel is always valid), so duplicating
the range check to handle that theoretic case does not add value.

> +		tmp = FIELD_PREP(MPFS_TVS_CTRL_V2P5_ENABLE, val);
> +		regmap_update_bits(data->regmap, MPFS_TVS_CTRL,
> +				   MPFS_TVS_CTRL_V2P5_ENABLE, tmp);
> +		break;
> +	case SENSOR_V1P8:
> +		if (val > 1 || val < 0)
> +			return -EINVAL;
> +
> +		tmp = FIELD_PREP(MPFS_TVS_CTRL_V1P8_ENABLE, val);
> +		regmap_update_bits(data->regmap, MPFS_TVS_CTRL,
> +				   MPFS_TVS_CTRL_V1P8_ENABLE, tmp);
> +		break;
> +	case SENSOR_V1P05:
> +		if (val > 1 || val < 0)
> +			return -EINVAL;
> +
> +		tmp = FIELD_PREP(MPFS_TVS_CTRL_V1P05_ENABLE, val);
> +		regmap_update_bits(data->regmap, MPFS_TVS_CTRL,
> +				   MPFS_TVS_CTRL_V1P05_ENABLE, tmp);
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mpfs_tvs_temp_read(struct mpfs_tvs *data, u32 attr, long *val)
> +{
> +	u32 tmp, control;
> +
> +	if (attr != hwmon_temp_input && attr != hwmon_temp_enable)
> +		return -EOPNOTSUPP;
> +
> +	regmap_read(data->regmap, MPFS_TVS_CTRL, &control);
> +
> +	if (attr == hwmon_temp_enable) {
> +		*val = FIELD_GET(MPFS_TVS_CTRL_TEMP_ENABLE, control);
> +		return 0;
> +	}
> +
> +	if (!(control & MPFS_TVS_CTRL_TEMP_VALID))
> +		return -EINVAL;
> +
"Invalid argument" can not be correct for data read from the chip.
I don't know what this means. It should be either -ENODATA (no data available)
if this is transient or -EIO (I/O error) if it is a permanent problem.
The same applies to other validation checks.

> +	regmap_read(data->regmap, MPFS_TVS_OUTPUT1, &tmp);
> +	*val = FIELD_GET(MPFS_OUTPUT1_TEMP_MASK, tmp);
> +	*val -= MPFS_TVS_K_TO_C;
> +	*val = (1000 * *val) >> 4; /* fixed point (11.4) to millidegrees */
> +
> +	return 0;
> +}
> +
> +static int mpfs_tvs_temp_write(struct mpfs_tvs *data, u32 attr, long val)
> +{
> +	u32 tmp;
> +
> +	if (attr != hwmon_temp_enable)
> +		return -EOPNOTSUPP;
> +
> +	if (val > 1 || val < 0)
> +		return -EINVAL;
> +
> +	tmp = FIELD_PREP(MPFS_TVS_CTRL_TEMP_ENABLE, val);
> +	regmap_update_bits(data->regmap, MPFS_TVS_CTRL,
> +			   MPFS_TVS_CTRL_TEMP_ENABLE, tmp);
> +
> +	return 0;
> +}
> +
> +static int mpfs_tvs_interval_read(struct mpfs_tvs *data, u32 attr, long *val)
> +{
> +	u32 tmp;
> +
> +	if (attr != hwmon_chip_update_interval)
> +		return -EOPNOTSUPP;
> +
> +	regmap_read(data->regmap, MPFS_TVS_CTRL, &tmp);
> +	*val = FIELD_GET(MPFS_TVS_INTERVAL_MASK, tmp);
> +	*val *= MPFS_TVS_INTERVAL_SCALE;
> +	*val /= 1000;
> +
> +	return 0;
> +}
> +
> +static int mpfs_tvs_interval_write(struct mpfs_tvs *data, u32 attr, long val)
> +{
> +	unsigned long temp = val;
> +
> +	if (attr != hwmon_chip_update_interval)
> +		return -EOPNOTSUPP;
> +
> +	temp *= 1000;

This is likely to result in overflow issues (for example if val == LONG_MAX).

> +	temp /= MPFS_TVS_INTERVAL_SCALE;
> +
> +	/*
> +	 * The value is 8 bits wide, but 255 is described as
> +	 * "255= Do single set of transfers when scoverride set"
> +	 * but there's no scoverride bit in the tvs register region.
> +	 * Ban using 255 since its behaviour is suspect.
> +	 */
> +	if (temp > 254)
> +		return -EINVAL;

Hardware monitoring drivers should use clamp() and not return -EINVAL
for ranges such as this. Since the valid range (in ms) is 0..8, I would
suggest to clamp val to (0, 8) before any calculations to also avoid
the overflow issue mentioned above. That makes me wonder: What does "0"
stand for ? 32 us or 0 us ? It does not make a difference here, but it
may be relevant when microsecond intervals are implemented.

> +
> +	temp <<= MPFS_TVS_INTERVAL_OFFSET;
> +	regmap_update_bits(data->regmap, MPFS_TVS_CTRL,
> +			   MPFS_TVS_INTERVAL_MASK, temp);

If regmap never returns errors this needs to be documented in the driver.

> +
> +	return 0;
> +}
> +
> +static umode_t mpfs_tvs_is_visible(const void *data,
> +				   enum hwmon_sensor_types type,
> +				   u32 attr, int channel)
> +{
> +	if (type == hwmon_chip && attr == hwmon_chip_update_interval)
> +		return 0644;
> +
> +	if (type == hwmon_temp) {
> +		switch (attr) {
> +		case hwmon_temp_enable:
> +			return 0644;
> +		case hwmon_temp_input:
> +		case hwmon_temp_label:
> +			return 0444;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	if (type == hwmon_in) {
> +		switch (attr) {
> +		case hwmon_in_enable:
> +			return 0644;
> +		case hwmon_in_input:
> +		case hwmon_in_label:
> +			return 0444;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int mpfs_tvs_read(struct device *dev, enum hwmon_sensor_types type,
> +			 u32 attr, int channel, long *val)
> +{
> +	struct mpfs_tvs *data = dev_get_drvdata(dev);
> +
> +	switch (type) {
> +	case hwmon_temp:
> +		return mpfs_tvs_temp_read(data, attr, val);
> +	case hwmon_in:
> +		return mpfs_tvs_voltage_read(data, attr, channel, val);
> +	case hwmon_chip:
> +		return mpfs_tvs_interval_read(data, attr, val);
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
> +static int mpfs_tvs_write(struct device *dev, enum hwmon_sensor_types type,
> +			  u32 attr, int channel, long val)
> +{
> +	struct mpfs_tvs *data = dev_get_drvdata(dev);
> +
> +	switch (type) {
> +	case hwmon_temp:
> +		return mpfs_tvs_temp_write(data, attr, val);
> +	case hwmon_in:
> +		return mpfs_tvs_voltage_write(data, attr, channel, val);
> +	case hwmon_chip:
> +		return mpfs_tvs_interval_write(data, attr, val);
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
> +static int mpfs_tvs_read_labels(struct device *dev,
> +				enum hwmon_sensor_types type,
> +				u32 attr, int channel,
> +				const char **str)
> +{
> +	switch (type) {
> +	case hwmon_temp:
> +		*str = "Die Temp";
> +		return 0;
> +	case hwmon_in:
> +		*str = mpfs_tvs_voltage_labels[channel];
> +		return 0;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
> +static const struct hwmon_ops mpfs_tvs_ops = {
> +	.is_visible = mpfs_tvs_is_visible,
> +	.read_string = mpfs_tvs_read_labels,
> +	.read = mpfs_tvs_read,
> +	.write = mpfs_tvs_write,
> +};
> +
> +static const struct hwmon_channel_info *mpfs_tvs_info[] = {
> +	HWMON_CHANNEL_INFO(chip,
> +			   HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL),
> +	HWMON_CHANNEL_INFO(temp,
> +			   HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_ENABLE),
> +	HWMON_CHANNEL_INFO(in,
> +			   HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_ENABLE,
> +			   HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_ENABLE,
> +			   HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_ENABLE),
> +	NULL
> +};
> +
> +static const struct hwmon_chip_info mpfs_tvs_chip_info = {
> +	.ops = &mpfs_tvs_ops,
> +	.info = mpfs_tvs_info,
> +};
> +
> +static int mpfs_tvs_probe(struct platform_device *pdev)
> +{
> +	struct device *hwmon_dev;
> +	struct mpfs_tvs *data;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->regmap = device_node_to_regmap(pdev->dev.parent->of_node);
> +	if (IS_ERR(data->regmap))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(data->regmap),
> +				     "Failed to find syscon regmap\n");
> +
> +	regmap_write(data->regmap, MPFS_TVS_CTRL, MPFS_TVS_CTRL_ENABLE_ALL);
> +
> +	hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "mpfs_tvs",
> +							 data,
> +							 &mpfs_tvs_chip_info,
> +							 NULL);
> +	if (IS_ERR(hwmon_dev))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(hwmon_dev),
> +				     "hwmon device registration failed.\n");
> +
> +	return 0;
> +}
> +
> +static struct platform_driver mpfs_tvs_driver = {
> +	.probe = mpfs_tvs_probe,
> +	.driver = {
> +		.name = "mpfs-tvs",
> +	},
> +};
> +module_platform_driver(mpfs_tvs_driver);
> +
> +MODULE_AUTHOR("Lars Randers <lranders@mail.dk>");
> +MODULE_DESCRIPTION("PolarFire SoC temperature & voltage sensor driver");
> +MODULE_LICENSE("GPL");


^ permalink raw reply

* Re: [PATCH RFC v4 0/6] iio: add Open Sensor Fusion IIO driver
From: Conor Dooley @ 2026-06-08 17:28 UTC (permalink / raw)
  To: Jinseob Kim
  Cc: Jonathan Cameron, linux-iio, David Lechner, Nuno Sá,
	Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Corbet, Shuah Khan, devicetree, linux-kernel, linux-doc
In-Reply-To: <20260607234343.22109-1-kimjinseob88@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 6072 bytes --]

Hey,

On Mon, Jun 08, 2026 at 08:43:37AM +0900, Jinseob Kim wrote:
> This RFC series adds an Industrial I/O driver for Open Sensor Fusion
> sensor aggregation devices.
> 
> Open Sensor Fusion is an open hardware project for sensor
> aggregation devices. The Linux IIO driver is an initial host-side
> implementation for OSF devices. The driver receives OSF frames over
> UART, uses device capability reports to discover supported sensor
> streams, and exposes supported raw sensor data through IIO devices.
> 
> This series is still marked RFC because the DT binding identity, the
> supported OSF protocol subset, and protocol extension and backward
> compatibility rules are still under review. The v4 series
> intentionally models the Linux device as a generic Open Sensor Fusion
> device rather than an OSF GREEN board-specific device. OSF GREEN is
> the prototype board used for current runtime testing, not the Linux DT
> compatible or driver identity.

Other than the fact that new revisions must not be sent as a diff on top
of a prior revision, please stop sending new versions without actually
replying to my v1 comments. In particular:

| What does "v0" mean here? Is the data format not complete yet?
| Are versions of the protocol likely to be backwards compatible?
| Will the device identify what version of the protocol it implements?

This version drops mention of v0 in the binding, but I don't know if that
means the version is fully discoverable or if you've moved to a stable
revision etc. You need to spell this stuff out to us, I'm not going to
read a github repository to figure this out - I have hundreds of patches
to get through every day. It's your responsibility to explain it all.

> The current wire format uses the OSF0 magic for protocol major
> version 0. That is kept as an internal wire-format detail for

For example, what does "OSF0 magic" mean? Is that a detectable version
number in a consistent place across revisions? Or will OSF1 magic be
incompatible. From a devicetree point of view, that's important because
if the magic is in different places in different revisions, the
compatible needs to convey what revision the device implements.

> compatibility with existing firmware, tools, and runtime smoke
> evidence. The public driver identity remains Open Sensor Fusion / OSF,
> with protocol versioning handled by the protocol major/minor fields.

This sounds like versioning is discoverable, but you need to spell this
out in the commit message for the binding.

Thanks,
Conor.

> 
> Project links:
> https://www.opensensorfusion.org/
> https://github.com/opensensorfusion
> https://github.com/opensensorfusion/opensensorfusion-hardware
> https://github.com/opensensorfusion/opensensorfusion-linux
> 
> Runtime testing so far has used an OSF GREEN prototype connected to a
> Raspberry Pi over UART. On Raspberry Pi 6.12.75+rpt-rpi-v8, the
> driver registered osf-accel, osf-gyro, osf-magn, and osf-temp from a
> capability report. Raw reads and software kfifo buffer reads were
> tested for all four IIO devices.
> 
> Changes since v3:
> 
> * Explain why the series is still RFC.
> * Move the DT binding out of iio/imu because the device is a sensor
>   aggregation device rather than an IMU.
> * Replace the OSF GREEN board-specific compatible with the generic
>   opensensorfusion,osf compatible.
> * Treat OSF GREEN as tested prototype hardware / board model
>   information, not as the Linux compatible string.
> * Rename the kernel documentation to open-sensor-fusion.rst and
>   reduce it to a driver-facing overview.
> * Add the IIO documentation toctree entry.
> * Keep full protocol details and compatibility rules in project
>   documentation rather than duplicating the full wire specification in
>   the kernel tree.
> * Avoid using OSF0 as the public driver identity; keep it only as the
>   current wire magic for protocol major version 0.
> * Add FourCC-style wire magic handling in the decoder.
> * Use GENMASK() for the capability flags mask.
> * Clarify signed 32-bit little-endian sample decoding.
> * Stop counting normal partial UART receive waits as partial frame
>   errors.
> * Avoid decoding complete frames twice in the stream/core path.
> * Remove the local scan[] bounce before
>   iio_push_to_buffers_with_ts_unaligned() and pass the values buffer
>   directly.
> * Remove the meaningless temperature available_scan_masks entry.
> * Update MAINTAINERS paths for the new binding and documentation
>   names.
> 
> Jinseob Kim (6):
>   dt-bindings: iio: add Open Sensor Fusion device
>   Documentation: iio: add Open Sensor Fusion driver overview
>   iio: osf: add protocol decoding
>   iio: osf: add stream parser
>   iio: osf: add UART transport
>   iio: osf: register IIO devices from capabilities
> 
>  .../iio/imu/opensensorfusion,osf-green.yaml   |  43 ---
>  .../bindings/iio/opensensorfusion,osf.yaml    |  43 +++
>  Documentation/iio/index.rst                   |   1 +
>  .../iio/open-sensor-fusion-protocol-v0.rst    | 308 ------------------
>  Documentation/iio/open-sensor-fusion.rst      |  62 ++++
>  MAINTAINERS                                   |  26 +-
>  drivers/iio/opensensorfusion/Kconfig          |   4 +-
>  drivers/iio/opensensorfusion/osf_core.c       |   9 +-
>  drivers/iio/opensensorfusion/osf_iio.c        |  15 +-
>  drivers/iio/opensensorfusion/osf_protocol.c   |   4 +-
>  drivers/iio/opensensorfusion/osf_protocol.h   |   4 +-
>  drivers/iio/opensensorfusion/osf_serdev.c     |   2 +-
>  drivers/iio/opensensorfusion/osf_stream.c     |  38 +--
>  13 files changed, 145 insertions(+), 414 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/iio/imu/opensensorfusion,osf-green.yaml
>  create mode 100644 Documentation/devicetree/bindings/iio/opensensorfusion,osf.yaml
>  delete mode 100644 Documentation/iio/open-sensor-fusion-protocol-v0.rst
>  create mode 100644 Documentation/iio/open-sensor-fusion.rst
> 
> -- 
> 2.43.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Nhat Pham @ 2026-06-08 18:01 UTC (permalink / raw)
  To: Yosry Ahmed
  Cc: Hao Jia, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
	chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAO9r8zN6VVZz7dpjNrh8n7wbLkqcrsROPm70MQQxO49HJSmMFw@mail.gmail.com>

On Mon, Jun 8, 2026 at 9:48 AM Yosry Ahmed <yosry@kernel.org> wrote:
>
> > But OTOH, this does seem like a recipe for inefficient reclaim. We
> > might exhaust hotter memory of a cgroup while sparing colder memory of
> > another cgroup... But maybe if they're all cold anyway, then who
> > cares, and eventually you'll get to the cold stuff of other child?
>
> Forgot to respond to this part, the unfairness is limited to the batch
> size per-invocation, so it should be fine as long as you don't divide
> the amount over 100 iterations for some reason. Also yes, all memory
> in zswap is cold, the relative coldness is not that important (e.g.
> compared to relative coldness during reclaim).

Ok then yeah, I think we should shelve per-memcg cursor for the next
version. Down the line, if we have more data that unfairness is an
issue, we can always fix it. One step at a time :)

^ permalink raw reply

* Re: [RFC v1 0/9] kho: granular compatibility and header decoupling
From: Mike Rapoport @ 2026-06-08 18:11 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: linux-kselftest, shuah, akpm, linux-mm, skhan, linux-doc,
	jasonmiu, linux-kernel, corbet, ran.xiaokai, kexec, pratyush,
	graf, rppt
In-Reply-To: <aibYJvzQQnpoN6YW@plex>

On Mon, Jun 08, 2026 at 04:12:56PM +0000, Pasha Tatashin wrote:
> On 06-08 13:26, Mike Rapoport wrote:
> > On 2026-06-07 13:43:09+00:00, Pasha Tatashin wrote:
>
> Keeping all of that in a single KHO file is the wrong approach and goes 
> against how other logically separated subsystems in Linux are organized 
> (e.g., mm/vmap.c, mm/vmalloc.c, etc.). Yes, there are some messier 
> places in the kernel as well, but keeping this in its own dedicated 
> kho_vmalloc.c file makes complete sense to me.

Either I hallucinated or b4 ate a paragraph from my reply ;)

Regarding the code movement
- splitting radix tree makes perfect sense to me, just the documentation
  part needs more care than mechanical move
- I'm fine with abi/vmalloc.h, presuming KHOSER_PTR() is not part of it
- I can live with kho_vmalloc.c although I still consider it unnecessary
  churn
- I'm against moving vmalloc APIs from kexec_handover.h because they are
  very close in nature to folio and pages. I don't see core KHO as
  responsible for preserving physically contiguous ranges but rather as
  preserving allocations. Not sure we'll ever support kmalloc(), but still.

> However, overall enforcing the use of KHOSER is unrelated to this work. 
> I have my own thoughts on this, and perhaps with proper versioning, 
> using KHOSER_PTR everywhere would be appropriate, but let's keep that as 
> a separate work.

This is a separate work, indeed. But regardless of the versioning it's
already better than plain u64 because it provides type safety.

> > Actually FDT "compatible" handles versioning nicer than composite strings
> > You can have
> > 
> > 	compatible="kho-v4", "vmalloc-v1", "radix-v1", "block-v2";
> > 
> > and check fdt_node_check_compatible("vmalloc-v1") for vmalloc and
> > fdt_node_check_compatible("block-v2") for block.
> 
> That is actually very similar to what I am proposing—individual version 
> tokens (which in my current series are concatenated into a composite 
> compatibility string separated by ';').

Yes, you reinvented the wheel :-P

The difference between FDT-compatible and the composite strings is that the
strings are all or nothing while FDT is "any of".
But that's only a side note, we're not going to use fdt-compatible.

> But let's not get too fixated on the composite string formatting. I 
> actually really like what you are proposing: using integers for versions 
> and having each registered component carry its own "NAME" and version 
> number in the KHO FDT.

Yeah, something like that.

> Pasha

-- 
Sincerely yours,
Mike.

^ permalink raw reply

* Re: [PATCH v6 08/12] PCI: liveupdate: Inherit ACS flags in incoming preserved devices
From: Jason Gunthorpe @ 2026-06-08 18:16 UTC (permalink / raw)
  To: Pranjal Shrivastava
  Cc: David Matlack, kexec, linux-doc, linux-kernel, linux-mm,
	linux-pci, Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jonathan Corbet, Josh Hilke, Leon Romanovsky, Lukas Wunner,
	Mike Rapoport, Parav Pandit, Pasha Tatashin, Pratyush Yadav,
	Saeed Mahameed, Samiullah Khawaja, Shuah Khan, Vipin Sharma,
	William Tu, Yi Liu
In-Reply-To: <aiaeOVomxQZhoM3K@google.com>

On Mon, Jun 08, 2026 at 10:49:29AM +0000, Pranjal Shrivastava wrote:

> My point was that a FW exploit can meddle with the bitfields of the
> ACS_CTRL to spoof and mis-report the ACS flags.

Devices can also ignore the ACS flags. I don't think this is an area
where we should be worrying about devices being actively hostile.

Jason

^ permalink raw reply

* Re: [PATCH v6 09/12] PCI: liveupdate: Inherit ARI Forwarding Enable on preserved bridges
From: Jason Gunthorpe @ 2026-06-08 18:19 UTC (permalink / raw)
  To: Pranjal Shrivastava
  Cc: David Matlack, kexec, linux-doc, linux-kernel, linux-mm,
	linux-pci, Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jonathan Corbet, Josh Hilke, Leon Romanovsky, Lukas Wunner,
	Mike Rapoport, Parav Pandit, Pasha Tatashin, Pratyush Yadav,
	Saeed Mahameed, Samiullah Khawaja, Shuah Khan, Vipin Sharma,
	William Tu, Yi Liu
In-Reply-To: <aiaoc6Y6qeF_5Wn9@google.com>

On Mon, Jun 08, 2026 at 11:33:07AM +0000, Pranjal Shrivastava wrote:
> On Fri, May 22, 2026 at 08:24:07PM +0000, David Matlack wrote:
> > Inherit the ARI Forwarding Enable on preserved bridges and update
> > pci_dev->ari_enabled accordingly during a Live Update. This ensures that
> > the preserved devices on the bridge's secondary bus can be identified
> > with the same expanded 8-bit function number after a Live Update.
> > 
> > Signed-off-by: David Matlack <dmatlack@google.com>
> > ---
> >  drivers/pci/liveupdate.c | 18 ++++++++++++++++++
> >  drivers/pci/liveupdate.h |  6 ++++++
> >  drivers/pci/pci.c        |  8 +++++++-
> >  3 files changed, 31 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c
> > index a93b7ef065f2..701276ef6cfb 100644
> > --- a/drivers/pci/liveupdate.c
> > +++ b/drivers/pci/liveupdate.c
> > @@ -128,6 +128,10 @@
> >   *    way after Live Update and ensures that IOMMU groups do not change. Note
> >   *    that a device will use its inherited ACS flags for the lifetime of its
> >   *    struct pci_dev (i.e. even after pci_liveupdate_finish()).
> > + *
> > + *  * The PCI core inherits ARI Forwarding Enable on all bridges with downstream
> > + *    preserved devices to ensure that all preserved devices on the bridge's
> > + *    secondary bus are addressable after the Live Update.
> >   */
> >  
> >  #define pr_fmt(fmt) "PCI: liveupdate: " fmt
> > @@ -756,6 +760,20 @@ int pci_liveupdate_enable_acs(struct pci_dev *dev)
> >  	return 0;
> >  }
> >  
> > +int pci_liveupdate_configure_ari(struct pci_dev *dev)
> > +{
> > +	u16 val;
> > +
> > +	guard(rwsem_read)(&pci_liveupdate.rwsem);
> > +
> > +	if (!dev->liveupdate.incoming)
> > +		return -EINVAL;
> > +
> > +	pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &val);
> 
> Again, I might be thinking out loud here, but since these are
> hot-pluggable devices, with some FW / SW running on them, I'm a little
> worried while assuming the HW registers can be trusted across a kexec.
> 
> Say, if the bridge experiences a reset (e.g. link drop etc) during the
> kexec blackout, the PCI_EXP_DEVCTL2 register could revert to its default
> state, meaning the ARI bit will be 0.

This does seem like something to be concerned about, but realistically
I think if you get a PCIe error I'm not sure the incoming kernel is
equipped to handle it at all :\

Just resuming the driver is going to fail too, I don't know how VFIO
can learn and forward the event, and so on..

But maybe it is worth being a little more defensive here

Jason

^ permalink raw reply

* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Shakeel Butt @ 2026-06-08 18:30 UTC (permalink / raw)
  To: Yosry Ahmed
  Cc: Hao Jia, Johannes Weiner, mhocko, tj, mkoutny, roman.gushchin,
	Nhat Pham, akpm, chengming.zhou, muchun.song, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAO9r8zM4SDdTgz9L2s1VfXL8K2VBjMD9ej2BTDxaGge1t2+quA@mail.gmail.com>

On Wed, Jun 03, 2026 at 10:36:07PM -0700, Yosry Ahmed wrote:
> > >> But doesn't it make more sense to specify the compressed size, which is
> > >> ultimately the amount of memory you actually want to reclaim.
> > >>
> > >
> > > I personally prefer compressed size to pre-compressed size. That's
> > > kinda what user cares about, no?
> > >
> > > One thing we can do is let users prescribe a compressed size, but
> > > internally, we can multiply that by the average compression ratio.
> > > That gives us a guesstimate of how many pages we need to reclaim, and
> > > you can follow the rest of your implementation as is (perhaps with
> > > short-circuit when we reach the goal with fewer pages reclaimed).
> >
> > Got it. I will change it to use the compressed size in the next version.
> >
> > Yosry, Nhat, should we continue using the zswap_writeback_only key to
> > trigger proactive writeback?
> 
> I *really* want the memcg maintainers to chime in here, it's
> ultimately their call.
> 
> Michal? Johannes? Shakeel? Roman? Anyone? :D

Between the options of having an explicit interface (i.e.
memory.zswap.writeback*) or a key (i.e. zswap_writeback_only) to memory.reclaim
interface, I prefer the key option. I have not looked into how much proactively
reclaiming zswap memory or proactively triggering zswap writeback makes sense
but from the perspective of memcg interface, I think the key option would give a
more clean solution if we decide in the future that this whole thing was a bad
idea.

Next regarding future proofing zswap writeback trigger, do we expect any
potential additions/changes/new-features for this interface? For example do we
expect in future we may want to trigger the zswap writeback only from a specific
node or lowest memory tier?

^ permalink raw reply

* Re: [PATCH v2 0/5] watchdog: improve comments & Documentation
From: Guenter Roeck @ 2026-06-08 18:53 UTC (permalink / raw)
  To: Randy Dunlap, linux-kernel
  Cc: Wim Van Sebroeck, linux-watchdog, Jonathan Corbet, Shuah Khan,
	linux-doc
In-Reply-To: <20260529212024.2119204-1-rdunlap@infradead.org>

On 5/29/26 14:20, Randy Dunlap wrote:
> Add the missing devm_watchdog_register_device() to watchdog-kernel-api.rst.
> Convert some struct and function comments to kernel-doc format.
> Add some UAPI comments for quick reference.
> Correct some grammar and bulleted list format.
> 
> v2: modify comments in patch 3/5 per sashiko review
> 
> [PATCH v2 1/5] watchdog: add devm_watchdog_register_device() to watchdog-kernel-api
> [PATCH v2 2/5] watchdog: linux/watchdog.h: repair kernel-doc comments
> [PATCH v2 3/5] watchdog: uapi: add comments for what bit masks apply to
> [PATCH v2 4/5] watchdog: core: clean up some comments
> [PATCH v2 5/5] watchdog: dev: convert to kernel-doc comments
> 
>   Documentation/watchdog/watchdog-kernel-api.rst |    8 ++++
>   drivers/watchdog/watchdog_core.c               |   12 +++---
>   drivers/watchdog/watchdog_dev.c                |   30 +++++++--------
>   include/linux/watchdog.h                       |    8 +++-
>   include/uapi/linux/watchdog.h                  |    2 +
>   5 files changed, 37 insertions(+), 23 deletions(-)
> 
> Cc: Wim Van Sebroeck <wim@linux-watchdog.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-watchdog@vger.kernel.org
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Shuah Khan <skhan@linuxfoundation.org>
> Cc: linux-doc@vger.kernel.org

Series applied.

Thanks,
Guenter


^ permalink raw reply

* Re: [PATCH v16 00/10] arm64/riscv: Add support for crashkernel CMA reservation
From: Mike Rapoport @ 2026-06-08 19:00 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Jinjie Ruan, corbet, skhan, catalin.marinas, will, chenhuacai,
	kernel, maddy, mpe, npiggin, chleroy, pjw, palmer, aou, alex,
	tglx, mingo, bp, dave.hansen, hpa, robh, saravanak, bhe,
	pasha.tatashin, pratyush, ruirui.yang, rdunlap, peterz, feng.tang,
	dapeng1.mi, kees, elver, kuba, lirongqing, ebiggers, paulmck,
	leitao, coxu, Liam.Howlett, ryan.roberts, osandov, jbohac,
	cfsworks, tangyouling, sourabhjain, ritesh.list, adityag,
	liaoyuanhong, seanjc, fuqiang.wang, ardb, chenjiahao16, guoren,
	x86, linux-doc, linux-kernel, linux-arm-kernel, loongarch,
	linuxppc-dev, linux-riscv, devicetree, kexec
In-Reply-To: <20260608091000.d88d7f5cc1bc4fa17f5774fe@linux-foundation.org>

On Mon, Jun 08, 2026 at 09:10:00AM -0700, Andrew Morton wrote:
> On Mon, 8 Jun 2026 15:34:49 +0800 Jinjie Ruan <ruanjinjie@huawei.com> wrote:
> 
> > The crash memory allocation, and the exclude of crashk_res, crashk_low_res
> > and crashk_cma memory are almost identical across different architectures,
> > This patch set handle them in crash core in a general way, which eliminate
> > a lot of duplication code.
> > 
> > And add support for crashkernel CMA reservation for arm64 and riscv.
> 
> fyi, AI review might have found a bunch of issues in arch-specific
> code, all of them pre-existing.

v15 grew to 23 patches because of them and Baoquan suggested to split the
fixes into a separate series.
 
> 	https://sashiko.dev/#/patchset/20260608073459.3119290-1-ruanjinjie@huawei.com

-- 
Sincerely yours,
Mike.

^ permalink raw reply

* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Shakeel Butt @ 2026-06-08 19:50 UTC (permalink / raw)
  To: Yosry Ahmed
  Cc: Hao Jia, Johannes Weiner, mhocko, tj, mkoutny, roman.gushchin,
	Nhat Pham, akpm, chengming.zhou, muchun.song, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia, youngjun.park
In-Reply-To: <aicJBVT4pBvmyooT@linux.dev>

+Youngjun

On Mon, Jun 08, 2026 at 11:30:30AM -0700, Shakeel Butt wrote:
> On Wed, Jun 03, 2026 at 10:36:07PM -0700, Yosry Ahmed wrote:
> > > >> But doesn't it make more sense to specify the compressed size, which is
> > > >> ultimately the amount of memory you actually want to reclaim.
> > > >>
> > > >
> > > > I personally prefer compressed size to pre-compressed size. That's
> > > > kinda what user cares about, no?
> > > >
> > > > One thing we can do is let users prescribe a compressed size, but
> > > > internally, we can multiply that by the average compression ratio.
> > > > That gives us a guesstimate of how many pages we need to reclaim, and
> > > > you can follow the rest of your implementation as is (perhaps with
> > > > short-circuit when we reach the goal with fewer pages reclaimed).
> > >
> > > Got it. I will change it to use the compressed size in the next version.
> > >
> > > Yosry, Nhat, should we continue using the zswap_writeback_only key to
> > > trigger proactive writeback?
> > 
> > I *really* want the memcg maintainers to chime in here, it's
> > ultimately their call.
> > 
> > Michal? Johannes? Shakeel? Roman? Anyone? :D
> 
> Between the options of having an explicit interface (i.e.
> memory.zswap.writeback*) or a key (i.e. zswap_writeback_only) to memory.reclaim
> interface, I prefer the key option. I have not looked into how much proactively
> reclaiming zswap memory or proactively triggering zswap writeback makes sense
> but from the perspective of memcg interface, I think the key option would give a
> more clean solution if we decide in the future that this whole thing was a bad
> idea.
> 
> Next regarding future proofing zswap writeback trigger, do we expect any
> potential additions/changes/new-features for this interface? For example do we
> expect in future we may want to trigger the zswap writeback only from a specific
> node or lowest memory tier?

Youngjun is working on swap tiers. At the moment he is more interested in
allowing a specific swap device to a memcg or not. I can imagine in future there
will be use-cases where there will be a need to demote data on higher tier swap
to lower tier swap. What would be the appropriate interface?

BTW does zswap folks think of zswap as a top swap tier or something different?

^ permalink raw reply

* Re: [PATCH v5 09/21] nfsd: add data structures for handling CB_NOTIFY
From: Chuck Lever @ 2026-06-08 20:18 UTC (permalink / raw)
  To: Jeff Layton, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker, Jonathan Corbet,
	Shuah Khan
  Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
	Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
	linux-doc, linux-nfs
In-Reply-To: <20260522-dir-deleg-v5-9-542cddfad576@kernel.org>



On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> Add the data structures, allocation helpers, and callback operations
> needed for directory delegation CB_NOTIFY support:

> diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
> index 9c6e2e7abc82..505fabf8f1bf 100644
> --- a/fs/nfsd/state.h
> +++ b/fs/nfsd/state.h
> @@ -197,6 +197,44 @@ struct nfs4_cb_fattr {
>  #define NOTIFY4_EVENT_QUEUE_SIZE	3
>  #define NOTIFY4_PAGE_ARRAY_SIZE		1
> 
> +struct nfsd_notify_event {
> +	refcount_t	ne_ref;		// refcount
> +	u32		ne_mask;	// FS_* mask from fsnotify callback
> +	struct dentry	*ne_dentry;	// dentry reference to target
> +	u32		ne_namelen;	// length of ne_name
> +	char		ne_name[];	// name of dentry being changed

Nit: checkpatch doesn't like the C++ comment style.


> +};
> +
> +static inline struct nfsd_notify_event *nfsd_notify_event_get(struct 
> nfsd_notify_event *ne)
> +{
> +	refcount_inc(&ne->ne_ref);
> +	return ne;
> +}
> +
> +static inline void nfsd_notify_event_put(struct nfsd_notify_event *ne)
> +{
> +	if (refcount_dec_and_test(&ne->ne_ref)) {
> +		dput(ne->ne_dentry);
> +		kfree(ne);
> +	}
> +}
> +
> +/*
> + * Represents a directory delegation. The callback is for handling 
> CB_NOTIFYs.
> + * As notifications from fsnotify come in, allocate a new event, take 
> the ncn_lock,
> + * and add it to the ncn_evt queue. The CB_NOTIFY prepare handler will 
> take the
> + * lock, clean out the list and process it.
> + */
> +struct nfsd4_cb_notify {
> +	spinlock_t			ncn_lock;	// protects the evt queue and count
> +	int				ncn_evt_cnt;	// count of events in ncn_evt
> +	int				ncn_nf_cnt;	// count of valid entries in ncn_nf
> +	struct nfsd_notify_event	*ncn_evt[NOTIFY4_EVENT_QUEUE_SIZE]; // list 
> of events
> +	struct page			*ncn_pages[NOTIFY4_PAGE_ARRAY_SIZE]; // for encoding
> +	struct notify4			*ncn_nf;	// array of notify4's to be sent
> +	struct nfsd4_callback		ncn_cb;		// notify4 callback
> +};

Ditto.


-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Yosry Ahmed @ 2026-06-08 20:19 UTC (permalink / raw)
  To: Shakeel Butt
  Cc: Hao Jia, Johannes Weiner, mhocko, tj, mkoutny, roman.gushchin,
	Nhat Pham, akpm, chengming.zhou, muchun.song, cgroups, linux-mm,
	linux-kernel, linux-doc, Hao Jia, youngjun.park
In-Reply-To: <aicZ-5GX9De3MAU7@linux.dev>

On Mon, Jun 8, 2026 at 12:50 PM Shakeel Butt <shakeel.butt@linux.dev> wrote:
>
> +Youngjun
>
> On Mon, Jun 08, 2026 at 11:30:30AM -0700, Shakeel Butt wrote:
> > On Wed, Jun 03, 2026 at 10:36:07PM -0700, Yosry Ahmed wrote:
> > > > >> But doesn't it make more sense to specify the compressed size, which is
> > > > >> ultimately the amount of memory you actually want to reclaim.
> > > > >>
> > > > >
> > > > > I personally prefer compressed size to pre-compressed size. That's
> > > > > kinda what user cares about, no?
> > > > >
> > > > > One thing we can do is let users prescribe a compressed size, but
> > > > > internally, we can multiply that by the average compression ratio.
> > > > > That gives us a guesstimate of how many pages we need to reclaim, and
> > > > > you can follow the rest of your implementation as is (perhaps with
> > > > > short-circuit when we reach the goal with fewer pages reclaimed).
> > > >
> > > > Got it. I will change it to use the compressed size in the next version.
> > > >
> > > > Yosry, Nhat, should we continue using the zswap_writeback_only key to
> > > > trigger proactive writeback?
> > >
> > > I *really* want the memcg maintainers to chime in here, it's
> > > ultimately their call.
> > >
> > > Michal? Johannes? Shakeel? Roman? Anyone? :D
> >
> > Between the options of having an explicit interface (i.e.
> > memory.zswap.writeback*) or a key (i.e. zswap_writeback_only) to memory.reclaim
> > interface, I prefer the key option. I have not looked into how much proactively
> > reclaiming zswap memory or proactively triggering zswap writeback makes sense
> > but from the perspective of memcg interface, I think the key option would give a
> > more clean solution if we decide in the future that this whole thing was a bad
> > idea.
> >
> > Next regarding future proofing zswap writeback trigger, do we expect any
> > potential additions/changes/new-features for this interface? For example do we
> > expect in future we may want to trigger the zswap writeback only from a specific
> > node or lowest memory tier?

The way I see it, zswap writeback is just a "special" type of
proactive reclaim, but the goal is still proactively freeing cold
memory. In that regard, I think it makes sense to have things like
node-specific reclaim. Not sure about other extensions, but Hao
initially suggested making this age-based, so I think the answer is
yes.

For both of these examples (node-specific reclaim, age-based reclaim),
I think the same semantics could apply to memory.reclaim in general,
which is why I suggested making it a part of memory.reclaim. I also
like the idea of having a single proactive reclaim interface in
general, but maybe we don't want to overload it too much.

> Youngjun is working on swap tiers. At the moment he is more interested in
> allowing a specific swap device to a memcg or not. I can imagine in future there
> will be use-cases where there will be a need to demote data on higher tier swap
> to lower tier swap. What would be the appropriate interface?
>
> BTW does zswap folks think of zswap as a top swap tier or something different?

I haven't been following the swap tiers work closely, but personally I
do think of zswap as a top swap tier. Things will probably get more
blurry with memory tiers and compressed memory nodes though.

^ permalink raw reply

* Re: [PATCH net-next V5 00/12] devlink: add per-port resource support
From: Jakub Kicinski @ 2026-06-08 20:30 UTC (permalink / raw)
  To: Tariq Toukan
  Cc: Eric Dumazet, Paolo Abeni, Andrew Lunn, David S. Miller,
	Simon Horman, Donald Hunter, Jiri Pirko, Jonathan Corbet,
	Shuah Khan, Saeed Mahameed, Leon Romanovsky, Mark Bloch,
	Shuah Khan, Matthieu Baerts (NGI0), Chuck Lever, Carolina Jubran,
	Or Har-Toov, Moshe Shemesh, Dragos Tatulea, Daniel Zahka,
	Shahar Shitrit, Cosmin Ratiu, Jacob Keller, Parav Pandit,
	Adithya Jayachandran, Shay Drori, Kees Cook, Daniel Jurgens,
	netdev, linux-kernel, linux-doc, linux-rdma, linux-kselftest,
	Gal Pressman
In-Reply-To: <20260407194107.148063-1-tariqt@nvidia.com>

On Tue, 7 Apr 2026 22:40:55 +0300 Tariq Toukan wrote:
> Userspace patches for iproute2:
> https://github.com/ohartoov/iproute2/tree/port_resources

Hi! As far as I can tell these iproute2 patches have not even been
posted? Please try to get them upstream ASAP, we have to manually 
carry them in the CI right now.

^ permalink raw reply

* Re: [PATCH v16 08/14] iio: core: add decimal value formatting into 64-bit value
From: Nuno Sá @ 2026-06-08 20:32 UTC (permalink / raw)
  To: rodrigo.alencar, linux-kernel, linux-iio, devicetree, linux-doc,
	linux
  Cc: Jonathan Cameron, David Lechner, Andy Shevchenko,
	Lars-Peter Clausen, Michael Hennerich, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet, Andrew Morton,
	Petr Mladek, Steven Rostedt, Andy Shevchenko, Rasmus Villemoes,
	Sergey Senozhatsky, Shuah Khan
In-Reply-To: <20260604-adf41513-iio-driver-v16-8-1a7d09143bc2@analog.com>

On Thu, 2026-06-04 at 10:59 +0100, Rodrigo Alencar via B4 Relay wrote:
> From: Rodrigo Alencar <rodrigo.alencar@analog.com>
> 
> Create new format types for iio values (IIO_VAL_DECIMAL64_*), which
> defines the representation of fixed decimal point values into a single
> 64-bit number. This new format increases the range of represented values,
> allowing for integer parts greater than 2^32, as bits are not "wasted"
> in the fractional part, which can be seen in IIO_VAL_INT_PLUS_MICRO and
> IIO_VAL_INT_PLUS_NANO. Helpers are created to compose and decompose 64-bit
> decimals into integer values used in IIO formatting interfaces, which
> creates consistency and avoid error-prone manual assignments when using
> wordpart macros. When doing the parsing, kstrtodec64() is used with the
> scale defined by the specific decimal format type.
> 
> Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
> ---

Reviewed-by: Nuno Sá <nuno.sa@analog.com>

>  drivers/iio/industrialio-core.c | 49 ++++++++++++++++++++++++++++++++---------
>  include/linux/iio/types.h       | 20 +++++++++++++++++
>  2 files changed, 59 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
> index ffe0dc49c4b9..93c2540d4cd2 100644
> --- a/drivers/iio/industrialio-core.c
> +++ b/drivers/iio/industrialio-core.c
> @@ -19,6 +19,7 @@
>  #include <linux/idr.h>
>  #include <linux/kdev_t.h>
>  #include <linux/kernel.h>
> +#include <linux/math64.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/poll.h>
> @@ -26,7 +27,6 @@
>  #include <linux/sched.h>
>  #include <linux/slab.h>
>  #include <linux/wait.h>
> -#include <linux/wordpart.h>
>  
>  #include <linux/iio/buffer.h>
>  #include <linux/iio/buffer_impl.h>
> @@ -656,6 +656,7 @@ static ssize_t __iio_format_value(char *buf, size_t offset,
> unsigned int type,
>  				  int size, const int *vals)
>  {
>  	int tmp0, tmp1;
> +	int l = 0;
>  	s64 tmp2;
>  	bool scale_db = false;
>  
> @@ -699,7 +700,6 @@ static ssize_t __iio_format_value(char *buf, size_t offset,
> unsigned int type,
>  	case IIO_VAL_INT_MULTIPLE:
>  	{
>  		int i;
> -		int l = 0;
>  
>  		for (i = 0; i < size; ++i)
>  			l += sysfs_emit_at(buf, offset + l, "%d ", vals[i]);
> @@ -708,8 +708,25 @@ static ssize_t __iio_format_value(char *buf, size_t offset,
> unsigned int type,
>  	case IIO_VAL_CHAR:
>  		return sysfs_emit_at(buf, offset, "%c", (char)vals[0]);
>  	case IIO_VAL_INT_64:
> -		tmp2 = (s64)((((u64)vals[1]) << 32) | (u32)vals[0]);
> -		return sysfs_emit_at(buf, offset, "%lld", tmp2);
> +		return sysfs_emit_at(buf, offset, "%lld",
> +				     iio_val_s64_compose(vals[0], vals[1]));
> +	case IIO_VAL_DECIMAL64_MILLI:
> +	case IIO_VAL_DECIMAL64_MICRO:
> +	case IIO_VAL_DECIMAL64_NANO:
> +	case IIO_VAL_DECIMAL64_PICO:
> +	{
> +		int scale = type - IIO_VAL_DECIMAL64_BASE;
> +		s64 frac;
> +
> +		tmp2 = div64_s64_rem(iio_val_s64_compose(vals[0], vals[1]),
> +				     int_pow(10, scale), &frac);
> +		if (tmp2 == 0 && frac < 0)
> +			l += sysfs_emit_at(buf, offset, "-");
> +
> +		l += sysfs_emit_at(buf, offset + l, "%lld.%0*lld", tmp2, scale,
> +				   abs(frac));
> +		return l;
> +	}
>  	default:
>  		return 0;
>  	}
> @@ -979,6 +996,7 @@ static ssize_t iio_write_channel_info(struct device *dev,
>  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
>  	int ret, fract_mult = 100000;
> +	int type, dec_scale = 0;
>  	int integer, fract = 0;
>  	long long integer64;
>  	bool is_char = false;
> @@ -989,9 +1007,11 @@ static ssize_t iio_write_channel_info(struct device *dev,
>  	if (!indio_dev->info->write_raw)
>  		return -EINVAL;
>  
> -	if (indio_dev->info->write_raw_get_fmt)
> -		switch (indio_dev->info->write_raw_get_fmt(indio_dev,
> -			this_attr->c, this_attr->address)) {
> +	if (indio_dev->info->write_raw_get_fmt) {
> +		type = indio_dev->info->write_raw_get_fmt(indio_dev,
> +							  this_attr->c,
> +							  this_attr->address);
> +		switch (type) {
>  		case IIO_VAL_INT:
>  			fract_mult = 0;
>  			break;
> @@ -1007,12 +1027,19 @@ static ssize_t iio_write_channel_info(struct device *dev,
>  		case IIO_VAL_CHAR:
>  			is_char = true;
>  			break;
> +		case IIO_VAL_DECIMAL64_MILLI:
> +		case IIO_VAL_DECIMAL64_MICRO:
> +		case IIO_VAL_DECIMAL64_NANO:
> +		case IIO_VAL_DECIMAL64_PICO:
> +			dec_scale = type - IIO_VAL_DECIMAL64_BASE;
> +			fallthrough;
>  		case IIO_VAL_INT_64:
>  			is_64bit = true;
>  			break;
>  		default:
>  			return -EINVAL;
>  		}
> +	}
>  
>  	if (is_char) {
>  		char ch;
> @@ -1021,12 +1048,14 @@ static ssize_t iio_write_channel_info(struct device *dev,
>  			return -EINVAL;
>  		integer = ch;
>  	} else if (is_64bit) {
> -		ret = kstrtoll(buf, 0, &integer64);
> +		if (dec_scale)
> +			ret = kstrtodec64(buf, dec_scale, &integer64);
> +		else
> +			ret = kstrtoll(buf, 0, &integer64);
>  		if (ret)
>  			return ret;
>  
> -		fract = upper_32_bits(integer64);
> -		integer = lower_32_bits(integer64);
> +		iio_val_s64_decompose(integer64, &integer, &fract);
>  	} else {
>  		ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract,
>  					    scale_db);
> diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
> index 4e3099defc1d..924ac9dc6893 100644
> --- a/include/linux/iio/types.h
> +++ b/include/linux/iio/types.h
> @@ -7,6 +7,9 @@
>  #ifndef _IIO_TYPES_H_
>  #define _IIO_TYPES_H_
>  
> +#include <linux/types.h>
> +#include <linux/wordpart.h>
> +
>  #include <uapi/linux/iio/types.h>
>  
>  enum iio_event_info {
> @@ -34,6 +37,23 @@ enum iio_event_info {
>  #define IIO_VAL_FRACTIONAL_LOG2 11
>  #define IIO_VAL_CHAR 12
>  
> +#define IIO_VAL_DECIMAL64_BASE		32
> +#define IIO_VAL_DECIMAL64_MILLI		(IIO_VAL_DECIMAL64_BASE + 3)
> +#define IIO_VAL_DECIMAL64_MICRO		(IIO_VAL_DECIMAL64_BASE + 6)
> +#define IIO_VAL_DECIMAL64_NANO		(IIO_VAL_DECIMAL64_BASE + 9)
> +#define IIO_VAL_DECIMAL64_PICO		(IIO_VAL_DECIMAL64_BASE + 12)
> +
> +static inline s64 iio_val_s64_compose(s32 val0, s32 val1)
> +{
> +	return (s64)(((u64)val1 << 32) | (u32)val0);
> +}
> +
> +static inline void iio_val_s64_decompose(s64 dec64, s32 *val0, s32 *val1)
> +{
> +	*val0 = lower_32_bits(dec64);
> +	*val1 = upper_32_bits(dec64);
> +}
> +
>  enum iio_available_type {
>  	IIO_AVAIL_LIST,
>  	IIO_AVAIL_RANGE,

^ permalink raw reply

* Re: [PATCH v5 10/21] nfsd: add notification handlers for dir events
From: Chuck Lever @ 2026-06-08 20:40 UTC (permalink / raw)
  To: Jeff Layton, Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo,
	Tom Talpey, Trond Myklebust, Anna Schumaker, Jonathan Corbet,
	Shuah Khan
  Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
	Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
	linux-doc, linux-nfs
In-Reply-To: <20260522-dir-deleg-v5-10-542cddfad576@kernel.org>



On Fri, May 22, 2026, at 3:42 PM, Jeff Layton wrote:
> Add the necessary parts to accept a fsnotify callback for directory
> change event and create a CB_NOTIFY request for it. When a dir nfsd_file
> is created set a handle_event callback to handle the notification.
>
> Use that to allocate a nfsd_notify_event object and then hand off a
> reference to each delegation's CB_NOTIFY. If anything fails along the
> way, recall any affected delegations.
>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>

There are some significant-looking sashiko review findings which I did
not follow up on.


> diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
> index ea3e7deb06fa..1964a213f80e 100644
> --- a/fs/nfsd/nfs4callback.c
> +++ b/fs/nfsd/nfs4callback.c
> @@ -870,21 +870,30 @@ static void nfs4_xdr_enc_cb_notify(struct 
> rpc_rqst *req,
>  				   const void *data)
>  {
>  	const struct nfsd4_callback *cb = data;
> +	struct nfsd4_cb_notify *ncn = container_of(cb, struct 
> nfsd4_cb_notify, ncn_cb);
> +	struct nfs4_delegation *dp = container_of(ncn, struct 
> nfs4_delegation, dl_cb_notify);
>  	struct nfs4_cb_compound_hdr hdr = {
>  		.ident = 0,
>  		.minorversion = cb->cb_clp->cl_minorversion,
>  	};
> -	struct CB_NOTIFY4args args = { };
> +	struct CB_NOTIFY4args args;
> +	__be32 *p;
> 
>  	WARN_ON_ONCE(hdr.minorversion == 0);
> 
>  	encode_cb_compound4args(xdr, &hdr);
>  	encode_cb_sequence4args(xdr, cb, &hdr);
> 
> -	/*
> -	 * FIXME: get stateid and fh from delegation. Inline the cna_changes
> -	 * buffer, and zero it.
> -	 */
> +	p = xdr_reserve_space(xdr, 4);
> +	*p = cpu_to_be32(OP_CB_NOTIFY);
> +
> +	args.cna_stateid.seqid = dp->dl_stid.sc_stateid.si_generation;
> +	memcpy(&args.cna_stateid.other, &dp->dl_stid.sc_stateid.si_opaque,
> +	       ARRAY_SIZE(args.cna_stateid.other));
> +	args.cna_fh.len = dp->dl_stid.sc_file->fi_fhandle.fh_size;
> +	args.cna_fh.data = dp->dl_stid.sc_file->fi_fhandle.fh_raw;
> +	args.cna_changes.count = ncn->ncn_nf_cnt;
> +	args.cna_changes.element = ncn->ncn_nf;
>  	WARN_ON_ONCE(!xdrgen_encode_CB_NOTIFY4args(xdr, &args));
> 
>  	hdr.nops++;

I want to avoid the need to use xdrgen to encode the CB_NOTIFY arguments.
How about this:

+       struct nfsd4_cb_notify *ncn = container_of(cb, struct nfsd4_cb_notify, ncn_cb);
+       struct nfs4_delegation *dp = container_of(ncn, struct nfs4_delegation, dl_cb_notify);

   ...

+       encode_stateid4(xdr, &dp->dl_stid.sc_stateid);
+       encode_nfs_fh4(xdr, &dp->dl_stid.sc_file->fi_fhandle);
+       xdr_stream_encode_u32(xdr, ncn->ncn_nf_cnt);
+       for (u32 i = 0; i < ncn->ncn_nf_cnt; i++)
+               (void)xdrgen_encode_notify4(xdr, &ncn->ncn_nf[i]);

And then add a "pragma public notify4;" in nfs4_1.x .


> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index b0652c755b3b..20477144475b 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c

> @@ -3461,19 +3462,131 @@ nfsd4_cb_getattr_release(struct nfsd4_callback *cb)
>  	nfs4_put_stid(&dp->dl_stid);
>  }
> 
> +static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
> +{
> +	bool queued;
> +
> +	if (test_and_set_bit(NFSD4_CALLBACK_RUNNING, &dp->dl_recall.cb_flags))
> +		return;
> +
> +	/*
> +	 * We're assuming the state code never drops its reference
> +	 * without first removing the lease.  Since we're in this lease
> +	 * callback (and since the lease code is serialized by the
> +	 * flc_lock) we know the server hasn't removed the lease yet, and
> +	 * we know it's safe to take a reference.
> +	 */
> +	refcount_inc(&dp->dl_stid.sc_count);
> +	queued = nfsd4_run_cb(&dp->dl_recall);
> +	WARN_ON_ONCE(!queued);
> +	if (!queued)
> +		refcount_dec(&dp->dl_stid.sc_count);
> +}
> +
> +static bool
> +nfsd4_cb_notify_prepare(struct nfsd4_callback *cb)
> +{
> +	struct nfsd4_cb_notify *ncn = container_of(cb, struct 
> nfsd4_cb_notify, ncn_cb);
> +	struct nfs4_delegation *dp = container_of(ncn, struct 
> nfs4_delegation, dl_cb_notify);
> +	struct nfsd_notify_event *events[NOTIFY4_EVENT_QUEUE_SIZE];
> +	struct xdr_buf xdr = { .buflen = PAGE_SIZE * NOTIFY4_PAGE_ARRAY_SIZE,
> +			       .pages  = ncn->ncn_pages };
> +	struct xdr_stream stream;
> +	struct nfsd_file *nf;
> +	int count, i;
> +	bool error = false;
> +
> +	xdr_init_encode_pages(&stream, &xdr);
> +
> +	spin_lock(&ncn->ncn_lock);
> +	count = ncn->ncn_evt_cnt;
> +
> +	/* spurious queueing? */
> +	if (count == 0) {
> +		spin_unlock(&ncn->ncn_lock);
> +		return false;
> +	}
> +
> +	/* we can't keep up! */
> +	if (count > NOTIFY4_EVENT_QUEUE_SIZE) {
> +		spin_unlock(&ncn->ncn_lock);
> +		goto out_recall;
> +	}
> +
> +	memcpy(events, ncn->ncn_evt, sizeof(*events) * count);
> +	ncn->ncn_evt_cnt = 0;
> +	spin_unlock(&ncn->ncn_lock);
> +
> +	rcu_read_lock();
> +	nf = 
> nfsd_file_get(rcu_dereference(dp->dl_stid.sc_file->fi_deleg_file));
> +	rcu_read_unlock();
> +	if (!nf) {
> +		for (i = 0; i < count; ++i)
> +			nfsd_notify_event_put(events[i]);
> +		goto out_recall;
> +	}
> +
> +	for (i = 0; i < count; ++i) {
> +		struct nfsd_notify_event *nne = events[i];
> +
> +		if (!error) {
> +			u32 *maskp = (u32 *)xdr_reserve_space(&stream, sizeof(*maskp));
> +			u8 *p;
> +
> +			if (!maskp) {
> +				error = true;
> +				goto put_event;
> +			}
> +
> +			p = nfsd4_encode_notify_event(&stream, nne, dp, nf, maskp);
> +			if (!p) {
> +				pr_notice("Could not generate CB_NOTIFY from fsnotify mask 0x%x\n",
> +					  nne->ne_mask);
> +				error = true;
> +				goto put_event;
> +			}
> +
> +			ncn->ncn_nf[i].notify_mask.count = 1;
> +			ncn->ncn_nf[i].notify_mask.element = maskp;
> +			ncn->ncn_nf[i].notify_vals.data = p;
> +			ncn->ncn_nf[i].notify_vals.len = (u8 *)stream.p - p;
> +		}
> +put_event:
> +		nfsd_notify_event_put(nne);
> +	}
> +	if (!error) {
> +		ncn->ncn_nf_cnt = count;
> +		nfsd_file_put(nf);
> +		return true;
> +	}
> +	nfsd_file_put(nf);
> +out_recall:
> +	nfsd_break_one_deleg(dp);
> +	return false;
> +}
> +
>  static int
>  nfsd4_cb_notify_done(struct nfsd4_callback *cb,
>  				struct rpc_task *task)
>  {
> +	struct nfsd4_cb_notify *ncn = container_of(cb, struct 
> nfsd4_cb_notify, ncn_cb);
> +	struct nfs4_delegation *dp = container_of(ncn, struct 
> nfs4_delegation, dl_cb_notify);
> +
>  	switch (task->tk_status) {
>  	case -NFS4ERR_DELAY:
>  		rpc_delay(task, 2 * HZ);
>  		return 0;
>  	default:
> +		/* For any other hard error, recall the deleg */
> +		nfsd_break_one_deleg(dp);
> +		fallthrough;
> +	case 0:
>  		return 1;
>  	}
>  }
> 
> +static void nfsd4_run_cb_notify(struct nfsd4_cb_notify *ncn);
> +
>  static void
>  nfsd4_cb_notify_release(struct nfsd4_callback *cb)
>  {
> @@ -3482,6 +3595,9 @@ nfsd4_cb_notify_release(struct nfsd4_callback *cb)
>  	struct nfs4_delegation *dp =
>  			container_of(ncn, struct nfs4_delegation, dl_cb_notify);
> 
> +	/* Drain events that arrived while this callback was in flight */
> +	if (ncn->ncn_evt_cnt > 0)
> +		nfsd4_run_cb_notify(ncn);

The above check needs to be serialized with modification of
ncn_evt_cnt:

+       bool pending;
 
+       /* Drain events that arrived while this callback was in flight */
+       spin_lock(&ncn->ncn_lock);
+       pending = ncn->ncn_evt_cnt > 0;
+       spin_unlock(&ncn->ncn_lock);
+       if (pending)
+               nfsd4_run_cb_notify(ncn);


>  	nfs4_put_stid(&dp->dl_stid);
>  }
> 

> @@ -9858,3 +9954,133 @@ void nfsd_update_cmtime_attr(struct file *f, 
> unsigned int flags)
>  				      MINOR(inode->i_sb->s_dev),
>  				      inode->i_ino, ret);
>  }
> +
> +static void
> +nfsd4_run_cb_notify(struct nfsd4_cb_notify *ncn)
> +{
> +	struct nfs4_delegation *dp = container_of(ncn, struct 
> nfs4_delegation, dl_cb_notify);
> +
> +	if (test_and_set_bit(NFSD4_CALLBACK_RUNNING, &ncn->ncn_cb.cb_flags))
> +		return;
> +
> +	if (!refcount_inc_not_zero(&dp->dl_stid.sc_count))
> +		clear_bit(NFSD4_CALLBACK_RUNNING, &ncn->ncn_cb.cb_flags);
> +	else
> +		nfsd4_run_cb(&ncn->ncn_cb);
> +}
> +
> +static struct nfsd_notify_event *
> +alloc_nfsd_notify_event(u32 mask, const struct qstr *q, struct dentry 
> *dentry,
> +			struct inode *target)
> +{
> +	struct nfsd_notify_event *ne;
> +
> +	ne = kmalloc(sizeof(*ne) + q->len + 1, GFP_NOFS);
> +	if (!ne)
> +		return NULL;
> +
> +	memcpy(&ne->ne_name, q->name, q->len);
> +	refcount_set(&ne->ne_ref, 1);
> +	ne->ne_mask = mask;
> +	ne->ne_name[q->len] = '\0';
> +	ne->ne_namelen = q->len;
> +	ne->ne_dentry = dget(dentry);
> +	ne->ne_target = target;
> +	if (ne->ne_target)
> +		ihold(ne->ne_target);
> +	return ne;
> +}
> +
> +static bool
> +should_notify_deleg(u32 mask, struct file_lease *fl)
> +{
> +	/* Don't notify the client generating the event */
> +	if (nfsd_breaker_owns_lease(fl))
> +		return false;
> +
> +	/* Skip if this event wasn't ignored by the lease */
> +	if ((mask & FS_DELETE) && !(fl->c.flc_flags & FL_IGN_DIR_DELETE))
> +		return false;
> +	if ((mask & FS_CREATE) && !(fl->c.flc_flags & FL_IGN_DIR_CREATE))
> +		return false;
> +	if ((mask & FS_RENAME) && !(fl->c.flc_flags & FL_IGN_DIR_RENAME))
> +		return false;
> +
> +	return true;
> +}
> +
> +static void
> +nfsd_recall_all_dir_delegs(const struct inode *dir)
> +{
> +	struct file_lock_context *ctx = locks_inode_context(dir);
> +	struct file_lock_core *flc;
> +
> +	spin_lock(&ctx->flc_lock);
> +	list_for_each_entry(flc, &ctx->flc_lease, flc_list) {
> +		struct file_lease *fl = container_of(flc, struct file_lease, c);
> +
> +		if (fl->fl_lmops == &nfsd_lease_mng_ops)
> +			nfsd_break_deleg_cb(fl);
> +	}
> +	spin_unlock(&ctx->flc_lock);
> +}
> +
> +int
> +nfsd_handle_dir_event(u32 mask, const struct inode *dir, const void 
> *data,
> +		      int data_type, const struct qstr *name)
> +{
> +	struct dentry *dentry = fsnotify_data_dentry(data, data_type);
> +	struct inode *target = fsnotify_data_rename_target(data, data_type);
> +	struct file_lock_context *ctx;
> +	struct file_lock_core *flc;
> +	struct nfsd_notify_event *evt;
> +
> +	/* Normalize cross-dir rename events to create/delete */
> +	if (mask & FS_MOVED_FROM) {
> +		mask &= ~FS_MOVED_FROM;
> +		mask |= FS_DELETE;
> +	}
> +	if (mask & FS_MOVED_TO) {
> +		mask &= ~FS_MOVED_TO;
> +		mask |= FS_CREATE;
> +	}
> +

I inserted an extra check here for rename notifications:

+       /*
+        * FS_RENAME fires on the source directory even for a cross-dir
+        * rename, where the moved entry now lives under a different
+        * parent. NOTIFY4_RENAME_ENTRY describes an in-place rename, so
+        * reporting it here would advertise a name absent from this
+        * directory.
+        */
+       if ((mask & FS_RENAME) && dentry && d_inode(dentry->d_parent) != dir)
+               mask &= ~FS_RENAME;


> +	/* Don't do anything if this is not an expected event */
> +	if (!(mask & (FS_CREATE|FS_DELETE|FS_RENAME)))
> +		return 0;
> +
> +	ctx = locks_inode_context(dir);
> +	if (!ctx || list_empty(&ctx->flc_lease))
> +		return 0;
> +
> +	evt = alloc_nfsd_notify_event(mask, name, dentry, target);
> +	if (!evt) {
> +		nfsd_recall_all_dir_delegs(dir);
> +		return 0;
> +	}
> +
> +	spin_lock(&ctx->flc_lock);
> +	list_for_each_entry(flc, &ctx->flc_lease, flc_list) {
> +		struct file_lease *fl = container_of(flc, struct file_lease, c);
> +		struct nfs4_delegation *dp = flc->flc_owner;
> +		struct nfsd4_cb_notify *ncn = &dp->dl_cb_notify;
> +

I added:

+               if (fl->fl_lmops != &nfsd_lease_mng_ops)
+                       continue;

Otherwise the loop treats every lease on the inode as an nfsd delegation
unconditionally.


> +		if (!should_notify_deleg(mask, fl))
> +			continue;
> +
> +		spin_lock(&ncn->ncn_lock);
> +		if (ncn->ncn_evt_cnt >= NOTIFY4_EVENT_QUEUE_SIZE) {
> +			/* We're generating notifications too fast. Recall. */
> +			spin_unlock(&ncn->ncn_lock);
> +			nfsd_break_deleg_cb(fl);
> +			continue;
> +		}
> +		ncn->ncn_evt[ncn->ncn_evt_cnt++] = nfsd_notify_event_get(evt);
> +		spin_unlock(&ncn->ncn_lock);
> +
> +		nfsd4_run_cb_notify(ncn);
> +	}
> +	spin_unlock(&ctx->flc_lock);
> +	nfsd_notify_event_put(evt);
> +	return 0;
> +}
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index e17488a911f7..31df04675713 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -4172,6 +4172,127 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, 
> struct xdr_stream *xdr,
>  	goto out;
>  }
> 
> +static bool
> +nfsd4_setup_notify_entry4(struct notify_entry4 *ne, struct xdr_stream 
> *xdr,
> +			  struct dentry *dentry, struct nfs4_delegation *dp,
> +			  struct nfsd_file *nf, char *name, u32 namelen)
> +{
> +	uint32_t *attrmask;
> +
> +	/* Reserve space for attrmask */
> +	attrmask = xdr_reserve_space(xdr, 3 * sizeof(uint32_t));
> +	if (!attrmask)
> +		return false;
> +
> +	ne->ne_file.data = name;
> +	ne->ne_file.len = namelen;
> +	ne->ne_attrs.attrmask.element = attrmask;
> +
> +	attrmask[0] = 0;
> +	attrmask[1] = 0;
> +	attrmask[2] = 0;
> +	ne->ne_attrs.attr_vals.data = NULL;
> +	ne->ne_attrs.attr_vals.len = 0;
> +	ne->ne_attrs.attrmask.count = 1;
> +	return true;
> +}
> +
> +/**
> + * nfsd4_encode_notify_event - encode a notify
> + * @xdr: stream to which to encode the fattr4
> + * @nne: nfsd_notify_event to encode
> + * @dp: delegation where the event occurred
> + * @nf: nfsd_file on which event occurred
> + * @notify_mask: pointer to word where notification mask should be set
> + *
> + * Encode @nne into @xdr. Returns a pointer to the start of the event, 
> or NULL if
> + * the event couldn't be encoded. The appropriate bit in the 
> notify_mask will also
> + * be set on success.
> + */

Nit: Let's use the usual kdoc style to describe the return value.

+ * Encode @nne into @xdr. The matching bit in @notify_mask is set on
+ * success.
+ *
+ * Return: pointer to the start of the encoded event, or NULL if the
+ * event could not be encoded.
+ */


> +u8 *nfsd4_encode_notify_event(struct xdr_stream *xdr, struct 
> nfsd_notify_event *nne,
> +			      struct nfs4_delegation *dp, struct nfsd_file *nf,
> +			      u32 *notify_mask)
> +{
> +	u8 *p = NULL;
> +
> +	*notify_mask = 0;
> +
> +	if (nne->ne_mask & FS_DELETE) {
> +		struct notify_remove4 nr = { };
> +
> +		if (!nfsd4_setup_notify_entry4(&nr.nrm_old_entry, xdr, 
> nne->ne_dentry, dp,
> +					       nf, nne->ne_name, nne->ne_namelen))
> +			goto out_err;
> +		p = (u8 *)xdr->p;
> +		if (!xdrgen_encode_notify_remove4(xdr, &nr))
> +			goto out_err;
> +		*notify_mask |= BIT(NOTIFY4_REMOVE_ENTRY);
> +	} else if (nne->ne_mask & FS_CREATE) {
> +		struct notify_add4 na = { };
> +		struct notify_remove4 old = { };
> +
> +		if (!nfsd4_setup_notify_entry4(&na.nad_new_entry, xdr, 
> nne->ne_dentry, dp,
> +					       nf, nne->ne_name, nne->ne_namelen))
> +			goto out_err;
> +
> +		/* If a file was overwritten, report it in nad_old_entry */
> +		if (nne->ne_target) {
> +			if (!nfsd4_setup_notify_entry4(&old.nrm_old_entry, xdr,
> +						       NULL, dp, nf,
> +						       nne->ne_name, nne->ne_namelen))
> +				goto out_err;
> +			na.nad_old_entry.count = 1;
> +			na.nad_old_entry.element = &old;
> +		}
> +
> +		p = (u8 *)xdr->p;
> +		if (!xdrgen_encode_notify_add4(xdr, &na))
> +			goto out_err;
> +
> +		*notify_mask |= BIT(NOTIFY4_ADD_ENTRY);
> +	} else if (nne->ne_mask & FS_RENAME) {
> +		struct notify_rename4 nr = { };
> +		struct notify_remove4 old = { };
> +		struct name_snapshot n;
> +		bool ret;
> +
> +		/* Don't send any attributes in the old_entry since they're the same 
> in new */
> +		if (!nfsd4_setup_notify_entry4(&nr.nrn_old_entry.nrm_old_entry, xdr,
> +					       NULL, dp, nf, nne->ne_name,
> +					       nne->ne_namelen))
> +			goto out_err;
> +
> +		take_dentry_name_snapshot(&n, nne->ne_dentry);
> +		ret = nfsd4_setup_notify_entry4(&nr.nrn_new_entry.nad_new_entry, xdr,
> +					       nne->ne_dentry, dp, nf, (char *)n.name.name,
> +					       n.name.len);
> +
> +		/* If a file was overwritten, report it in nad_old_entry */
> +		if (ret && nne->ne_target) {
> +			ret = nfsd4_setup_notify_entry4(&old.nrm_old_entry, xdr,
> +							NULL, dp, nf,
> +							(char *)n.name.name, n.name.len);
> +			if (ret) {
> +				nr.nrn_new_entry.nad_old_entry.count = 1;
> +				nr.nrn_new_entry.nad_old_entry.element = &old;
> +			}
> +		}
> +
> +		if (ret) {
> +			p = (u8 *)xdr->p;
> +			ret = xdrgen_encode_notify_rename4(xdr, &nr);
> +		}
> +		release_dentry_name_snapshot(&n);
> +		if (!ret)
> +			goto out_err;
> +		*notify_mask |= BIT(NOTIFY4_RENAME_ENTRY);
> +	}
> +	return p;
> +out_err:
> +	pr_warn("nfsd: unable to marshal notify_rename4 to xdr stream\n");

Nit: The warning needs to match the semantics of nfsd4_encode_notify_event().
How about:

+       pr_warn("nfsd: unable to marshal notify event to xdr stream\n");


> +	return NULL;
> +}
> +


-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH v6 01/12] PCI: liveupdate: Set up FLB handler for the PCI core
From: David Matlack @ 2026-06-08 20:51 UTC (permalink / raw)
  To: Pranjal Shrivastava
  Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
	Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
	Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
	Pratyush Yadav, Saeed Mahameed, Samiullah Khawaja, Shuah Khan,
	Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <aiJhoq_Yj6-1Hl5r@google.com>

On 2026-06-05 05:41 AM, Pranjal Shrivastava wrote:
> On Fri, May 22, 2026 at 08:23:59PM +0000, David Matlack wrote:
> > Set up a File-Lifecycle-Bound (FLB) handler for the PCI core to enable
> > it to participate in the preservation of PCI devices across Live Update.
> > Essentially, this commit enables the PCI core to allocate a struct
> > (struct pci_ser) and preserve it across a Live Update whenever at least
> > one device is preserved.
> > 
> > Preserving PCI devices across Live Update is built on top of the Live
> > Update Orchestrator's (LUO) support for file preservation. Drivers are
> > expected to expose a file to userspace to represent a single PCI device
> > and support preservation of that file. This is intended primarily to
> > support preservation of PCI devices bound to VFIO drivers.
> > 
> > This commit enables drivers to register their liveupdate_file_handler
> > with the PCI core so that the PCI core can do its own tracking and
> > enforcement of which devices are preserved.
> > 
> >   pci_liveupdate_register_flb(driver_file_handler);
> >   pci_liveupdate_unregister_flb(driver_file_handler);
> > 
> > When the first file (with a handler registered with the PCI core) is
> > preserved, the PCI core will be notified to allocate its tracking struct
> > (pci_ser). When the last file is unpreserved (i.e. preservation
> > cancelled) the PCI core will be notified to free struct pci_ser.
> > 
> > This struct is preserved across a Live Update using KHO and can be
> > fetched by the PCI core during early boot (e.g. during device
> > enumeration) so that it knows which devices were preserved.
> > 
> > Note: This commit only allocates struct pci_ser and preserves it across
> > Live Update. A subsequent commit will add an API for drivers to tell the
> > PCI core exactly which devices are being preserved.
> > 
> > Note: There is no reason to check for kho_is_enabled() since it can be
> > assumed to return true. If KHO was not enabled then Live Update would
> > not be enabled and these routines would never run.
> > 
> 
> [...]
> 
> > +/**
> > + * struct pci_dev_ser - Serialized state about a single PCI device.
> > + *
> > + * @domain: The device's PCI domain number (segment).
> > + * @bdf: The device's PCI bus, device, and function number.
> > + * @padding: Padding to naturally align struct pci_dev_ser.
> > + */
> > +struct pci_dev_ser {
> > +	u32 domain;
> > +	u16 bdf;
> > +	u16 padding;
> > +} __packed;
> > +
> > +/**
> > + * struct pci_ser - PCI Subsystem Live Update State
> > + *
> > + * This struct tracks state about all devices that are being preserved across
> > + * a Live Update for the next kernel.
> > + *
> > + * @max_nr_devices: The length of the devices[] flexible array.
> > + * @nr_devices: The number of devices that were preserved.
> > + * @devices: Flexible array of pci_dev_ser structs for each device.
> > + */
> > +struct pci_ser {
> > +	u32 max_nr_devices;
> > +	u32 nr_devices;
> > +	struct pci_dev_ser devices[];
> > +} __packed;
> > +
> > +/* Ensure all elements of devices[] are naturally aligned. */
> > +static_assert(offsetof(struct pci_ser, devices) % sizeof(unsigned long) == 0);
> > +static_assert(sizeof(struct pci_dev_ser) % sizeof(unsigned long) == 0);
> 
> Minor Nit: Shall we consider using specific bitwidth types here?
> I'm wondering if down the line another u32 field is added to 
> struct pci_dev_ser.. in that case on a 32-bit machine 12 % 4 == 0 but on
> a 64-bit machine 12 % 8 != 0..

I think natural alignment is what matters for efficient access of the
array elements. So failing the assert only on 64-bit architectures seems
like the correct behavior.

> 
> [...]
> 
> With the nit:
> 
> Reviewed-by: Pranjal Shrivastava <praan@google.com>
> 
> Thanks,
> Praan

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox