Skip to content

Commit

Permalink
xfs: fallback to vmalloc for large buffers in xfs_getbmap
Browse files Browse the repository at this point in the history
xfs_getbmap uses for a large buffer for extents, which is kmalloc'd.
This can fail after the system has been running for some time as it
is a high order allocation. Add a fallback to vmalloc so that it
doesn't require contiguous memory and so won't randomly fail on
files with large extent lists.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
  • Loading branch information
Dave Chinner authored and Ben Myers committed Mar 15, 2012
1 parent ad650f5 commit f074211
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions fs/xfs/xfs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -5536,8 +5536,12 @@ xfs_getbmap(
if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx))
return XFS_ERROR(ENOMEM);
out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL);
if (!out)
return XFS_ERROR(ENOMEM);
if (!out) {
out = kmem_zalloc_large(bmv->bmv_count *
sizeof(struct getbmapx));
if (!out)
return XFS_ERROR(ENOMEM);
}

xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
Expand Down Expand Up @@ -5661,7 +5665,10 @@ xfs_getbmap(
break;
}

kmem_free(out);
if (is_vmalloc_addr(out))
kmem_free_large(out);
else
kmem_free(out);
return error;
}

Expand Down

0 comments on commit f074211

Please sign in to comment.