aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-03-25 18:13:42 -0400
committerDave Chinner <david@fromorbit.com>2011-03-25 18:13:42 -0400
commita19fb380961f209a3a406443686647bcd01bb9a6 (patch)
tree304baceb45f2b40991900a546c39663bb37814ea /fs
parent8287889742940cf3c416e755322090d09f2829be (diff)
vmap: flush vmap aliases when mapping fails
On 32 bit systems, vmalloc space is limited and XFS can chew through it quickly as the vmalloc space is lazily freed. This can result in failure to map buffers, even when there is apparently large amounts of vmalloc space available. Hence, if we fail to map a buffer, purge the aliases that have not yet been freed to hopefuly free up enough vmalloc space to allow a retry to succeed. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 3cc671c8a67f..a5a260fab824 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -455,9 +455,17 @@ _xfs_buf_map_pages(
455 bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset; 455 bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset;
456 bp->b_flags |= XBF_MAPPED; 456 bp->b_flags |= XBF_MAPPED;
457 } else if (flags & XBF_MAPPED) { 457 } else if (flags & XBF_MAPPED) {
458 bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count, 458 int retried = 0;
459 -1, PAGE_KERNEL); 459
460 if (unlikely(bp->b_addr == NULL)) 460 do {
461 bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
462 -1, PAGE_KERNEL);
463 if (bp->b_addr)
464 break;
465 vm_unmap_aliases();
466 } while (retried++ <= 1);
467
468 if (!bp->b_addr)
461 return -ENOMEM; 469 return -ENOMEM;
462 bp->b_addr += bp->b_offset; 470 bp->b_addr += bp->b_offset;
463 bp->b_flags |= XBF_MAPPED; 471 bp->b_flags |= XBF_MAPPED;