On Fri, Jun 02, 2023 at 11:13:54PM -0700, Dan Williams wrote:
> A CONFIG_DEBUG_KOBJECT_RELEASE test of removing a device-dax region
> provider (like modprobe -r dax_hmem) yields:
> 
>  kobject: 'mapping0' (ffff93eb460e8800): kobject_release, parent 
> 0000000000000000 (delayed 2000)
>  [..]
>  DEBUG_LOCKS_WARN_ON(1)
>  WARNING: CPU: 23 PID: 282 at kernel/locking/lockdep.c:232 
> __lock_acquire+0x9fc/0x2260
>  [..]
>  RIP: 0010:__lock_acquire+0x9fc/0x2260
>  [..]
>  Call Trace:
>   <TASK>
>  [..]
>   lock_acquire+0xd4/0x2c0
>   ? ida_free+0x62/0x130
>   _raw_spin_lock_irqsave+0x47/0x70
>   ? ida_free+0x62/0x130
>   ida_free+0x62/0x130
>   dax_mapping_release+0x1f/0x30
>   device_release+0x36/0x90
>   kobject_delayed_cleanup+0x46/0x150
> 
> Due to attempting ida_free() on an ida object that has already been
> freed. Devices typically only hold a reference on their parent while
> registered. If a child needs a parent object to complete its release it
> needs to hold a reference that it drops from its release callback.
> Arrange for a dax_mapping to pin its parent dev_dax instance until
> dax_mapping_release().
> 
> Fixes: 0b07ce872a9e ("device-dax: introduce 'mapping' devices")
> Signed-off-by: Dan Williams <[email protected]>
> ---

Reviewed-by: Fan Ni <[email protected]>

>  drivers/dax/bus.c |    5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
> index 227800053309..aee695f86b44 100644
> --- a/drivers/dax/bus.c
> +++ b/drivers/dax/bus.c
> @@ -635,10 +635,12 @@ EXPORT_SYMBOL_GPL(alloc_dax_region);
>  static void dax_mapping_release(struct device *dev)
>  {
>       struct dax_mapping *mapping = to_dax_mapping(dev);
> -     struct dev_dax *dev_dax = to_dev_dax(dev->parent);
> +     struct device *parent = dev->parent;
> +     struct dev_dax *dev_dax = to_dev_dax(parent);
>  
>       ida_free(&dev_dax->ida, mapping->id);
>       kfree(mapping);
> +     put_device(parent);
>  }
>  
>  static void unregister_dax_mapping(void *data)
> @@ -778,6 +780,7 @@ static int devm_register_dax_mapping(struct dev_dax 
> *dev_dax, int range_id)
>       dev = &mapping->dev;
>       device_initialize(dev);
>       dev->parent = &dev_dax->dev;
> +     get_device(dev->parent);
>       dev->type = &dax_mapping_type;
>       dev_set_name(dev, "mapping%d", mapping->id);
>       rc = device_add(dev);
> 
> 

Reply via email to