aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-03-06 23:50:22 -0500
committerBen Myers <bpm@sgi.com>2012-03-15 15:54:23 -0400
commitf074211f6041305b645669464343d504f4e6a290 (patch)
tree2fd1678c72b47683e25f69e247dfecaec79e477b /fs/xfs/xfs_bmap.c
parentad650f5b27bc9858360b42aaa0d9204d16115316 (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.c13
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