On Mon, Jun 15, 2026 at 04:07:01PM +0800, John Groves wrote: > From: John Groves <[email protected]> > > fsdev_dax_probe() sets pgmap->ops = &fsdev_pagemap_ops and > pgmap->owner = dev_dax, but nothing ever clears them. For a dynamic > device the pgmap is devm-allocated and freed on unbind, so this is > harmless. For a static device the pgmap is the shared, long-lived one > owned by the dax bus (kill_dev_dax() only NULLs dev_dax->pgmap for the > non-static case), and device.c's probe sets only pgmap->type, never > clearing ops/owner. > > So after fsdev unbinds a static device the stale fsdev_pagemap_ops > survives on the shared pgmap. If the device is then rebound to > device_dax (MEMORY_DEVICE_GENERIC, which installs no ->memory_failure), > or the fsdev_dax module is unloaded, a subsequent memory_failure on that > pgmap dispatches through the stale -- and possibly freed -- handler. > > Register a devm action that clears pgmap->ops and pgmap->owner on unbind, > symmetric with setting them at probe, so the pgmap carries no fsdev state > once fsdev is detached. > > Suggested-by: Richard Cheng <[email protected]> > Fixes: d5406bd458b0a ("dax: add fsdev.c driver for fs-dax on character dax") > Signed-off-by: John Groves <[email protected]> > --- > drivers/dax/fsdev.c | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > > diff --git a/drivers/dax/fsdev.c b/drivers/dax/fsdev.c > index 0fd5e1293d725..68a4369562f70 100644 > --- a/drivers/dax/fsdev.c > +++ b/drivers/dax/fsdev.c > @@ -127,6 +127,23 @@ static void fsdev_clear_ops(void *data) > dax_set_ops(dev_dax->dax_dev, NULL); > } > > +static void fsdev_clear_pgmap_ops(void *data) > +{ > + struct dev_pagemap *pgmap = data; > + > + /* > + * fsdev installs pgmap->ops and ->owner at probe. For a static device > + * the pgmap is shared and long-lived (owned by the dax bus), so > + * leaving fsdev's ops behind on unbind would let a later > + * memory_failure -- after rebind to another driver, or after this > + * module is unloaded -- dispatch through a stale or freed > + * ->memory_failure handler. Clear them so the pgmap carries no fsdev > + * state once we are unbound. > + */ > + pgmap->ops = NULL; > + pgmap->owner = NULL; > +} > + > /* > * Page map operations for FS-DAX mode > * Similar to fsdax_pagemap_ops in drivers/nvdimm/pmem.c > @@ -306,6 +323,11 @@ static int fsdev_dax_probe(struct dev_dax *dev_dax) > if (IS_ERR(addr)) > return PTR_ERR(addr); > > + /* Drop fsdev's pgmap->ops/owner on unbind so no stale ops survive. */ > + rc = devm_add_action_or_reset(dev, fsdev_clear_pgmap_ops, pgmap); > + if (rc) > + return rc; > + > /* > * Clear any stale compound folio state left over from a previous > * driver (e.g., device_dax with vmemmap_shift). Also register this > -- > 2.53.0 >
Thanks for this, LGTM. Reviewed-by: Richard Cheng <[email protected]> Best regards, Richard Cheng.

