Re: [PATCH V6 05/10] dax/fsdev: clear pgmap ops and owner on unbind

From: Richard Cheng

Date: Mon Jun 22 2026 - 06:32:28 EST


On Mon, Jun 15, 2026 at 04:07:01PM +0800, John Groves wrote:
> From: John Groves <John@xxxxxxxxxx>
>
> 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 <icheng@xxxxxxxxxx>
> Fixes: d5406bd458b0a ("dax: add fsdev.c driver for fs-dax on character dax")
> Signed-off-by: John Groves <john@xxxxxxxxxx>
> ---
> 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 <icheng@xxxxxxxxxx>

Best regards,
Richard Cheng.