diff options
author | Dave Chinner <dchinner@redhat.com> | 2012-03-06 23:50:22 -0500 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-03-15 15:54:23 -0400 |
commit | f074211f6041305b645669464343d504f4e6a290 (patch) | |
tree | 2fd1678c72b47683e25f69e247dfecaec79e477b /fs/xfs/xfs_bmap.c | |
parent | ad650f5b27bc9858360b42aaa0d9204d16115316 (diff) |
xfs: fallback to vmalloc for large buffers in xfs_getbmap
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>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 188ef2fbd628..3548c6f75593 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -5536,8 +5536,12 @@ xfs_getbmap( | |||
5536 | if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx)) | 5536 | if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx)) |
5537 | return XFS_ERROR(ENOMEM); | 5537 | return XFS_ERROR(ENOMEM); |
5538 | out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL); | 5538 | out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL); |
5539 | if (!out) | 5539 | if (!out) { |
5540 | return XFS_ERROR(ENOMEM); | 5540 | out = kmem_zalloc_large(bmv->bmv_count * |
5541 | sizeof(struct getbmapx)); | ||
5542 | if (!out) | ||
5543 | return XFS_ERROR(ENOMEM); | ||
5544 | } | ||
5541 | 5545 | ||
5542 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 5546 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
5543 | if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { | 5547 | if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { |
@@ -5661,7 +5665,10 @@ xfs_getbmap( | |||
5661 | break; | 5665 | break; |
5662 | } | 5666 | } |
5663 | 5667 | ||
5664 | kmem_free(out); | 5668 | if (is_vmalloc_addr(out)) |
5669 | kmem_free_large(out); | ||
5670 | else | ||
5671 | kmem_free(out); | ||
5665 | return error; | 5672 | return error; |
5666 | } | 5673 | } |
5667 | 5674 | ||