Re: [PATCH] xfs: handle register_shrinker error

From: Tetsuo Handa
Date: Thu Nov 23 2017 - 11:17:50 EST

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.

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;

return NULL;