Message ID | 20240425113746.335530-9-kernel@pankajraghav.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | enable bs > ps in XFS | expand |
On Thu, Apr 25, 2024 at 01:37:43PM +0200, Pankaj Raghav (Samsung) wrote: > From: Dave Chinner <dchinner@redhat.com> > > Pankaj Raghav reported that when filesystem block size is larger > than page size, the xattr code can use kmalloc() for high order > allocations. This triggers a useless warning in the allocator as it > is a __GFP_NOFAIL allocation here: > > static inline > struct page *rmqueue(struct zone *preferred_zone, > struct zone *zone, unsigned int order, > gfp_t gfp_flags, unsigned int alloc_flags, > int migratetype) > { > struct page *page; > > /* > * We most definitely don't want callers attempting to > * allocate greater than order-1 page units with __GFP_NOFAIL. > */ > >>>> WARN_ON_ONCE((gfp_flags & __GFP_NOFAIL) && (order > 1)); > ... > > Fix this by changing all these call sites to use kvmalloc(), which > will strip the NOFAIL from the kmalloc attempt and if that fails > will do a __GFP_NOFAIL vmalloc(). > > This is not an issue that productions systems will see as > filesystems with block size > page size cannot be mounted by the > kernel; Pankaj is developing this functionality right now. > > Reported-by: Pankaj Raghav <kernel@pankajraghav.com> > Fixes: f078d4ea8276 ("xfs: convert kmem_alloc() to kmalloc()") > Signed-off-by: Dave Chinner <dchinner@redhat.com> Didn't this already go in for-next? If not, Reviewed-by: Darrick J. Wong <djwong@kernel.org> --D > --- > fs/xfs/libxfs/xfs_attr_leaf.c | 15 ++++++--------- > 1 file changed, 6 insertions(+), 9 deletions(-) > > diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c > index ac904cc1a97b..969abc6efd70 100644 > --- a/fs/xfs/libxfs/xfs_attr_leaf.c > +++ b/fs/xfs/libxfs/xfs_attr_leaf.c > @@ -1059,10 +1059,7 @@ xfs_attr3_leaf_to_shortform( > > trace_xfs_attr_leaf_to_sf(args); > > - tmpbuffer = kmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); > - if (!tmpbuffer) > - return -ENOMEM; > - > + tmpbuffer = kvmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); > memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); > > leaf = (xfs_attr_leafblock_t *)tmpbuffer; > @@ -1125,7 +1122,7 @@ xfs_attr3_leaf_to_shortform( > error = 0; > > out: > - kfree(tmpbuffer); > + kvfree(tmpbuffer); > return error; > } > > @@ -1533,7 +1530,7 @@ xfs_attr3_leaf_compact( > > trace_xfs_attr_leaf_compact(args); > > - tmpbuffer = kmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); > + tmpbuffer = kvmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); > memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); > memset(bp->b_addr, 0, args->geo->blksize); > leaf_src = (xfs_attr_leafblock_t *)tmpbuffer; > @@ -1571,7 +1568,7 @@ xfs_attr3_leaf_compact( > */ > xfs_trans_log_buf(trans, bp, 0, args->geo->blksize - 1); > > - kfree(tmpbuffer); > + kvfree(tmpbuffer); > } > > /* > @@ -2250,7 +2247,7 @@ xfs_attr3_leaf_unbalance( > struct xfs_attr_leafblock *tmp_leaf; > struct xfs_attr3_icleaf_hdr tmphdr; > > - tmp_leaf = kzalloc(state->args->geo->blksize, > + tmp_leaf = kvzalloc(state->args->geo->blksize, > GFP_KERNEL | __GFP_NOFAIL); > > /* > @@ -2291,7 +2288,7 @@ xfs_attr3_leaf_unbalance( > } > memcpy(save_leaf, tmp_leaf, state->args->geo->blksize); > savehdr = tmphdr; /* struct copy */ > - kfree(tmp_leaf); > + kvfree(tmp_leaf); > } > > xfs_attr3_leaf_hdr_to_disk(state->args->geo, save_leaf, &savehdr); > -- > 2.34.1 > >
On Fri, Apr 26, 2024 at 08:18:44AM -0700, Darrick J. Wong wrote: > On Thu, Apr 25, 2024 at 01:37:43PM +0200, Pankaj Raghav (Samsung) wrote: > > From: Dave Chinner <dchinner@redhat.com> > > > > Pankaj Raghav reported that when filesystem block size is larger > > than page size, the xattr code can use kmalloc() for high order > > allocations. This triggers a useless warning in the allocator as it > > is a __GFP_NOFAIL allocation here: > > > > static inline > > struct page *rmqueue(struct zone *preferred_zone, > > struct zone *zone, unsigned int order, > > gfp_t gfp_flags, unsigned int alloc_flags, > > int migratetype) > > { > > struct page *page; > > > > /* > > * We most definitely don't want callers attempting to > > * allocate greater than order-1 page units with __GFP_NOFAIL. > > */ > > >>>> WARN_ON_ONCE((gfp_flags & __GFP_NOFAIL) && (order > 1)); > > ... > > > > Fix this by changing all these call sites to use kvmalloc(), which > > will strip the NOFAIL from the kmalloc attempt and if that fails > > will do a __GFP_NOFAIL vmalloc(). > > > > This is not an issue that productions systems will see as > > filesystems with block size > page size cannot be mounted by the > > kernel; Pankaj is developing this functionality right now. > > > > Reported-by: Pankaj Raghav <kernel@pankajraghav.com> > > Fixes: f078d4ea8276 ("xfs: convert kmem_alloc() to kmalloc()") > > Signed-off-by: Dave Chinner <dchinner@redhat.com> > > Didn't this already go in for-next? I don't think so. I think Christoph suggested to have it in the LBS series and see if MM folks can fix the issue upstream.[1] [1] https://www.spinics.net/lists/linux-xfs/msg83130.html > > If not, > Reviewed-by: Darrick J. Wong <djwong@kernel.org> > > --D > > > --- > > fs/xfs/libxfs/xfs_attr_leaf.c | 15 ++++++--------- > > 1 file changed, 6 insertions(+), 9 deletions(-) > > > > diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c > > index ac904cc1a97b..969abc6efd70 100644 > > --- a/fs/xfs/libxfs/xfs_attr_leaf.c > > +++ b/fs/xfs/libxfs/xfs_attr_leaf.c > > @@ -1059,10 +1059,7 @@ xfs_attr3_leaf_to_shortform( > > > > trace_xfs_attr_leaf_to_sf(args); > > > > - tmpbuffer = kmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); > > - if (!tmpbuffer) > > - return -ENOMEM; > > - > > + tmpbuffer = kvmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); > > memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); > > > > leaf = (xfs_attr_leafblock_t *)tmpbuffer; > > @@ -1125,7 +1122,7 @@ xfs_attr3_leaf_to_shortform( > > error = 0; > > > > out: > > - kfree(tmpbuffer); > > + kvfree(tmpbuffer); > > return error; > > } > > > > @@ -1533,7 +1530,7 @@ xfs_attr3_leaf_compact( > > > > trace_xfs_attr_leaf_compact(args); > > > > - tmpbuffer = kmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); > > + tmpbuffer = kvmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); > > memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); > > memset(bp->b_addr, 0, args->geo->blksize); > > leaf_src = (xfs_attr_leafblock_t *)tmpbuffer; > > @@ -1571,7 +1568,7 @@ xfs_attr3_leaf_compact( > > */ > > xfs_trans_log_buf(trans, bp, 0, args->geo->blksize - 1); > > > > - kfree(tmpbuffer); > > + kvfree(tmpbuffer); > > } > > > > /* > > @@ -2250,7 +2247,7 @@ xfs_attr3_leaf_unbalance( > > struct xfs_attr_leafblock *tmp_leaf; > > struct xfs_attr3_icleaf_hdr tmphdr; > > > > - tmp_leaf = kzalloc(state->args->geo->blksize, > > + tmp_leaf = kvzalloc(state->args->geo->blksize, > > GFP_KERNEL | __GFP_NOFAIL); > > > > /* > > @@ -2291,7 +2288,7 @@ xfs_attr3_leaf_unbalance( > > } > > memcpy(save_leaf, tmp_leaf, state->args->geo->blksize); > > savehdr = tmphdr; /* struct copy */ > > - kfree(tmp_leaf); > > + kvfree(tmp_leaf); > > } > > > > xfs_attr3_leaf_hdr_to_disk(state->args->geo, save_leaf, &savehdr); > > -- > > 2.34.1 > > > >
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index ac904cc1a97b..969abc6efd70 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -1059,10 +1059,7 @@ xfs_attr3_leaf_to_shortform( trace_xfs_attr_leaf_to_sf(args); - tmpbuffer = kmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); - if (!tmpbuffer) - return -ENOMEM; - + tmpbuffer = kvmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); leaf = (xfs_attr_leafblock_t *)tmpbuffer; @@ -1125,7 +1122,7 @@ xfs_attr3_leaf_to_shortform( error = 0; out: - kfree(tmpbuffer); + kvfree(tmpbuffer); return error; } @@ -1533,7 +1530,7 @@ xfs_attr3_leaf_compact( trace_xfs_attr_leaf_compact(args); - tmpbuffer = kmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); + tmpbuffer = kvmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); memcpy(tmpbuffer, bp->b_addr, args->geo->blksize); memset(bp->b_addr, 0, args->geo->blksize); leaf_src = (xfs_attr_leafblock_t *)tmpbuffer; @@ -1571,7 +1568,7 @@ xfs_attr3_leaf_compact( */ xfs_trans_log_buf(trans, bp, 0, args->geo->blksize - 1); - kfree(tmpbuffer); + kvfree(tmpbuffer); } /* @@ -2250,7 +2247,7 @@ xfs_attr3_leaf_unbalance( struct xfs_attr_leafblock *tmp_leaf; struct xfs_attr3_icleaf_hdr tmphdr; - tmp_leaf = kzalloc(state->args->geo->blksize, + tmp_leaf = kvzalloc(state->args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL); /* @@ -2291,7 +2288,7 @@ xfs_attr3_leaf_unbalance( } memcpy(save_leaf, tmp_leaf, state->args->geo->blksize); savehdr = tmphdr; /* struct copy */ - kfree(tmp_leaf); + kvfree(tmp_leaf); } xfs_attr3_leaf_hdr_to_disk(state->args->geo, save_leaf, &savehdr);