Re: [PATCH] bcache:cleanup resources when bcache device init failed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2020/4/8 6:02 下午, Wu Bo wrote:
> From: Wu Bo <wubo40@xxxxxxxxxx>
> 
> Cleanup resources when device init failed on bcache_device_init function
> 
> Signed-off-by: Wu Bo <wubo40@xxxxxxxxxx>

Hi Wu Bo,

Do you test this patch ? I am not sure whether it may work properly,
because all the resources will be released in bcache_device_stop() from
register_bdev(). Your patch makes them being released twice.

If bcache_device_init() fails, cached_dev_init() will fail, then the
caller register_bdev() will fail and jump to err label to call
bcache_device_stop().

If this is a cached device, in bcache_device_stop(),
closure_queue(&d->cl) will call the callback routine cached_dev_flush().
Then in cached_dev_flush() the continue_at() callback cached_dev_free()
will be called. In cached_dev_free() you will see these resources are
freed properly.


Coly Li

> ---
>  drivers/md/bcache/super.c | 27 +++++++++++++++++++--------
>  1 file changed, 19 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
> index d98354f..b4e3d0e 100644
> --- a/drivers/md/bcache/super.c
> +++ b/drivers/md/bcache/super.c
> @@ -823,6 +823,7 @@ static int bcache_device_init(struct bcache_device
> *d, unsigned int block_size,
>                                          SIZE_MAX / sizeof(atomic_t));
>         size_t n;
>         int idx;
> +       int rtn = -ENOMEM;
> 
>         if (!d->stripe_size)
>                 d->stripe_size = 1 << 31;
> @@ -843,20 +844,22 @@ static int bcache_device_init(struct bcache_device
> *d, unsigned int block_size,
>         n = BITS_TO_LONGS(d->nr_stripes) * sizeof(unsigned long);
>         d->full_dirty_stripes = kvzalloc(n, GFP_KERNEL);
>         if (!d->full_dirty_stripes)
> -               return -ENOMEM;
> +               goto out_free_sectors_dirty;
> 
>         idx = ida_simple_get(&bcache_device_idx, 0,
>                                 BCACHE_DEVICE_IDX_MAX, GFP_KERNEL);
> -       if (idx < 0)
> -               return idx;
> +       if (idx < 0) {
> +               rtn = idx;
> +               goto out_free_dirty_stripes;
> +       }
> 
>         if (bioset_init(&d->bio_split, 4, offsetof(struct bbio, bio),
>                         BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER))
> -               goto err;
> +               goto out_free_idx;
> 
>         d->disk = alloc_disk(BCACHE_MINORS);
>         if (!d->disk)
> -               goto err;
> +               goto out_bioset_exit;
> 
>         set_capacity(d->disk, sectors);
>         snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", idx);
> @@ -868,7 +871,7 @@ static int bcache_device_init(struct bcache_device
> *d, unsigned int block_size,
> 
>         q = blk_alloc_queue(make_request_fn, NUMA_NO_NODE);
>         if (!q)
> -               return -ENOMEM;
> +               goto out_free_disk;
> 
>         d->disk->queue                  = q;
>         q->queuedata                    = d;
> @@ -890,9 +893,17 @@ static int bcache_device_init(struct bcache_device
> *d, unsigned int block_size,
> 
>         return 0;
> 
> -err:
> +out_free_disk:
> +       put_disk(d->disk);
> +out_bioset_exit:
> +       bioset_exit(&d->bio_split);
> +out_free_idx:
>         ida_simple_remove(&bcache_device_idx, idx);
> -       return -ENOMEM;
> +out_free_dirty_stripes:
> +       kvfree(d->full_dirty_stripes);
> +out_free_sectors_dirty:
> +       kvfree(d->stripe_sectors_dirty);
> +       return rtn;
> 
>  }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux ARM Kernel]     [Linux Filesystem Development]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux