]> git.karo-electronics.de Git - linux-beck.git/commitdiff
vmap: flush vmap aliases when mapping fails
authorDave Chinner <dchinner@redhat.com>
Fri, 25 Mar 2011 22:13:42 +0000 (09:13 +1100)
committerDave Chinner <david@fromorbit.com>
Fri, 25 Mar 2011 22:13:42 +0000 (09:13 +1100)
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>
fs/xfs/linux-2.6/xfs_buf.c

index 3cc671c8a67f481176486b2b65f6c06ff3cf08e9..a5a260fab8241ba7fb4b1555403032bb9d94a693 100644 (file)
@@ -455,9 +455,17 @@ _xfs_buf_map_pages(
                bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset;
                bp->b_flags |= XBF_MAPPED;
        } else if (flags & XBF_MAPPED) {
-               bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
-                                       -1, PAGE_KERNEL);
-               if (unlikely(bp->b_addr == NULL))
+               int retried = 0;
+
+               do {
+                       bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
+                                               -1, PAGE_KERNEL);
+                       if (bp->b_addr)
+                               break;
+                       vm_unmap_aliases();
+               } while (retried++ <= 1);
+
+               if (!bp->b_addr)
                        return -ENOMEM;
                bp->b_addr += bp->b_offset;
                bp->b_flags |= XBF_MAPPED;