aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2011-03-27 04:07:36 -0400
committerroot <Chris Mason chris.mason@oracle.com>2011-03-28 05:37:58 -0400
commit1561deda687eef0e95065f1268d680ddc5976ee7 (patch)
tree3ad8a8305fc3ca960cf7ef472f64d9cfef246ffd /fs/btrfs
parentc055e99eea6e4f614267632fac546e7896c0227b (diff)
btrfs: fix possible deadlock by clearing __GFP_FS flag
Using the GFP_HIGHUSER_MOVABLE flag to allocate the metadata's page may cause deadlock. Task1 open() ... btrfs_search_slot() ... btrfs_cow_block() ... alloc_page() wait for reclaiming shrink_slab() ... shrink_icache_memory() ... btrfs_evict_inode() ... btrfs_search_slot() If the path is locked by task1, the deadlock happens. So the btree's page cache is different with the file's page cache, it can not allocate pages by GFP_HIGHUSER_MOVABLE flag, we must clear __GFP_FS flag in GFP_HIGHUSER_MOVABLE flag. Reported-by: Itaru Kitayama <kitayama@cl.bb4u.ne.jp> Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/inode.c3
2 files changed, 4 insertions, 1 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b3fc8475870f..5cf3aa7b125c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1724,6 +1724,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1724 goto fail_bdi; 1724 goto fail_bdi;
1725 } 1725 }
1726 1726
1727 fs_info->btree_inode->i_mapping->flags &= ~__GFP_FS;
1728
1727 INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC); 1729 INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
1728 INIT_LIST_HEAD(&fs_info->trans_list); 1730 INIT_LIST_HEAD(&fs_info->trans_list);
1729 INIT_LIST_HEAD(&fs_info->dead_roots); 1731 INIT_LIST_HEAD(&fs_info->dead_roots);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 04babaf31a33..06274186b290 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2536,6 +2536,8 @@ static void btrfs_read_locked_inode(struct inode *inode)
2536 BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); 2536 BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
2537 2537
2538 alloc_group_block = btrfs_inode_block_group(leaf, inode_item); 2538 alloc_group_block = btrfs_inode_block_group(leaf, inode_item);
2539 if (location.objectid == BTRFS_FREE_SPACE_OBJECTID)
2540 inode->i_mapping->flags &= ~__GFP_FS;
2539 2541
2540 /* 2542 /*
2541 * try to precache a NULL acl entry for files that don't have 2543 * try to precache a NULL acl entry for files that don't have
@@ -4084,7 +4086,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
4084 BTRFS_I(inode)->root = root; 4086 BTRFS_I(inode)->root = root;
4085 memcpy(&BTRFS_I(inode)->location, location, sizeof(*location)); 4087 memcpy(&BTRFS_I(inode)->location, location, sizeof(*location));
4086 btrfs_read_locked_inode(inode); 4088 btrfs_read_locked_inode(inode);
4087
4088 inode_tree_add(inode); 4089 inode_tree_add(inode);
4089 unlock_new_inode(inode); 4090 unlock_new_inode(inode);
4090 if (new) 4091 if (new)