diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 19c258d2c7e2..1281c393c7e6 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -936,14 +936,25 @@ void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) | |||
936 | struct inode *inode; | 936 | struct inode *inode; |
937 | struct extent_map_tree *em_tree; | 937 | struct extent_map_tree *em_tree; |
938 | struct extent_map *em; | 938 | struct extent_map *em; |
939 | struct address_space *mapping; | ||
939 | u64 offset; | 940 | u64 offset; |
940 | 941 | ||
942 | /* the generic O_DIRECT read code does this */ | ||
941 | if (!page) { | 943 | if (!page) { |
942 | __unplug_io_fn(bdi, page); | 944 | __unplug_io_fn(bdi, page); |
943 | return; | 945 | return; |
944 | } | 946 | } |
945 | 947 | ||
946 | inode = page->mapping->host; | 948 | /* |
949 | * page->mapping may change at any time. Get a consistent copy | ||
950 | * and use that for everything below | ||
951 | */ | ||
952 | smp_mb(); | ||
953 | mapping = page->mapping; | ||
954 | if (!mapping) | ||
955 | return; | ||
956 | |||
957 | inode = mapping->host; | ||
947 | offset = page_offset(page); | 958 | offset = page_offset(page); |
948 | 959 | ||
949 | em_tree = &BTRFS_I(inode)->extent_tree; | 960 | em_tree = &BTRFS_I(inode)->extent_tree; |