Skip to content

Commit

Permalink
Btrfs: use the inode's mapping mask for allocating pages
Browse files Browse the repository at this point in the history
Johannes pointed out we were allocating only kernel pages for doing writes,
which is kind of a big deal if you are on 32bit and have more than a gig of ram.
So fix our allocations to use the mapping's gfp but still clear __GFP_FS so we
don't re-enter.  Thanks,

Reported-by: Johannes Weiner <jweiner@redhat.com>
Signed-off-by: Josef Bacik <josef@redhat.com>
  • Loading branch information
Josef Bacik committed Oct 19, 2011
1 parent 455757c commit 3b16a4e
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 6 deletions.
6 changes: 6 additions & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <linux/kobject.h>
#include <trace/events/btrfs.h>
#include <asm/kmap_types.h>
#include <linux/pagemap.h>
#include "extent_io.h"
#include "extent_map.h"
#include "async-thread.h"
Expand Down Expand Up @@ -2117,6 +2118,11 @@ static inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info)
(space_info->flags & BTRFS_BLOCK_GROUP_DATA));
}

static inline gfp_t btrfs_alloc_write_mask(struct address_space *mapping)
{
return mapping_gfp_mask(mapping) & ~__GFP_FS;
}

/* extent-tree.c */
static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_root *root,
unsigned num_items)
Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
int i;
unsigned long index = pos >> PAGE_CACHE_SHIFT;
struct inode *inode = fdentry(file)->d_inode;
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
int err = 0;
int faili = 0;
u64 start_pos;
Expand All @@ -1080,7 +1081,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
again:
for (i = 0; i < num_pages; i++) {
pages[i] = find_or_create_page(inode->i_mapping, index + i,
GFP_NOFS);
mask);
if (!pages[i]) {
faili = i - 1;
err = -ENOMEM;
Expand Down
6 changes: 4 additions & 2 deletions fs/btrfs/free-space-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
u64 num_bitmaps;
u64 generation;
pgoff_t index = 0;
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
int ret = 0;

INIT_LIST_HEAD(&bitmaps);
Expand Down Expand Up @@ -310,7 +311,7 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
if (!num_entries && !num_bitmaps)
break;

page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
page = find_or_create_page(inode->i_mapping, index, mask);
if (!page)
goto free_cache;

Expand Down Expand Up @@ -563,6 +564,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
u64 start, end, len;
u64 bytes = 0;
u32 crc = ~(u32)0;
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
int index = 0, num_pages = 0;
int entries = 0;
int bitmaps = 0;
Expand Down Expand Up @@ -612,7 +614,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
* know and don't freak out.
*/
while (index < num_pages) {
page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
page = find_or_create_page(inode->i_mapping, index, mask);
if (!page) {
int i;

Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3282,6 +3282,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
pgoff_t index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE-1);
struct page *page;
gfp_t mask = btrfs_alloc_write_mask(mapping);
int ret = 0;
u64 page_start;
u64 page_end;
Expand All @@ -3294,7 +3295,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)

ret = -ENOMEM;
again:
page = find_or_create_page(mapping, index, GFP_NOFS);
page = find_or_create_page(mapping, index, mask);
if (!page) {
btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
goto out;
Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
int i_done;
struct btrfs_ordered_extent *ordered;
struct extent_state *cached_state = NULL;
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);

if (isize == 0)
return 0;
Expand All @@ -860,7 +861,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
for (i = 0; i < num_pages; i++) {
struct page *page;
page = find_or_create_page(inode->i_mapping,
start_index + i, GFP_NOFS);
start_index + i, mask);
if (!page)
break;

Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/relocation.c
Original file line number Diff line number Diff line change
Expand Up @@ -2921,6 +2921,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
unsigned long last_index;
struct page *page;
struct file_ra_state *ra;
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
int nr = 0;
int ret = 0;

Expand Down Expand Up @@ -2955,7 +2956,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
ra, NULL, index,
last_index + 1 - index);
page = find_or_create_page(inode->i_mapping, index,
GFP_NOFS);
mask);
if (!page) {
btrfs_delalloc_release_metadata(inode,
PAGE_CACHE_SIZE);
Expand Down

0 comments on commit 3b16a4e

Please sign in to comment.