Re: [PATCH] xfs: handle register_shrinker error

Tetsuo Handa
2017-11-23T16:17:48Z

Michal Hocko wrote:
> Hmm, you are right. I have (blindly) followed the current code flow
> which is wrong as well. The following should do the trick. Should I
> split that into two patches?

Well, xfs_alloc_buftarg() needs to be more careful.

xfs_alloc_buftarg(
struct xfs_mount *mp,
struct block_device *bdev,
struct dax_device *dax_dev)
{
xfs_buftarg_t *btp;

btp = kmem_zalloc(sizeof(*btp), KM_SLEEP | KM_NOFS); // This is GFP_NOFS context. But...

btp->bt_mount = mp;
btp->bt_dev = bdev->bd_dev;
btp->bt_bdev = bdev;
btp->bt_daxdev = dax_dev;

if (xfs_setsize_buftarg_early(btp, bdev))
goto error;

if (list_lru_init(&btp->bt_lru)) // This is GFP_KERNEL context.
goto error;

if (percpu_counter_init(&btp->bt_io_count, 0, GFP_KERNEL)) // This is GFP_KERNEL context.
goto error; // Need to undo list_lru_init() before kmem_free().

btp->bt_shrinker.count_objects = xfs_buftarg_shrink_count;
btp->bt_shrinker.scan_objects = xfs_buftarg_shrink_scan;
btp->bt_shrinker.seeks = DEFAULT_SEEKS;
btp->bt_shrinker.flags = SHRINKER_NUMA_AWARE;
register_shrinker(&btp->bt_shrinker); // This is GFP_KERNEL context.
return btp;

error:
kmem_free(btp);
return NULL;
}