The dynamic device-dax probe path publishes its devm-allocated pgmap
before several operations that can still fail.  If one of them fails,
devres frees the pgmap while dev_dax->pgmap remains non-NULL.  A later
bind then fails the dynamic-dax invariant check and leaves the device
unusable until its region is recreated.

Defer assigning dev_dax->pgmap until the final devm action has been
installed and probe can no longer fail.  A failed probe then never
publishes the temporary pgmap.

Fixes: fc65c4eb0b2a ("device-dax: ensure dev_dax->pgmap is valid for dynamic 
devices")
Cc: [email protected]
Signed-off-by: Jiale Yao <[email protected]>
---
 drivers/dax/device.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index d0c9b4e03b47..8cd8e05872c3 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -409,7 +409,6 @@ static int dev_dax_probe(struct dev_dax *dev_dax)
                        return -ENOMEM;
 
                pgmap->nr_range = dev_dax->nr_range;
-               dev_dax->pgmap = pgmap;
 
                for (i = 0; i < dev_dax->nr_range; i++) {
                        struct range *range = &dev_dax->ranges[i].range;
@@ -450,7 +449,13 @@ static int dev_dax_probe(struct dev_dax *dev_dax)
                return rc;
 
        run_dax(dax_dev);
-       return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
+       rc = devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
+       if (rc)
+               return rc;
+
+       /* Probe can no longer fail; expose the pgmap via dev_dax. */
+       dev_dax->pgmap = pgmap;
+       return 0;
 }
 
 static struct dax_device_driver device_dax_driver = {
-- 
2.34.1


Reply via email to