Skip to content

Commit 4b38431

Browse files
Mark FashehChris Mason
authored andcommitted
btrfs: Introduce extent_read_full_page_nolock()
We want this for btrfs_extent_same. Basically readpage and friends do their own extent locking but for the purposes of dedupe, we want to have both files locked down across a set of readpage operations (so that we can compare data). Introduce this variant and a flag which can be set for extent_read_full_page() to indicate that we are already locked. Partial credit for this patch goes to Gabriel de Perthuis <g2p.code@gmail.com> as I have included a fix from him to the original patch which avoids a deadlock on compressed extents. Signed-off-by: Mark Fasheh <mfasheh@suse.de> Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
1 parent 32b7c68 commit 4b38431

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

fs/btrfs/compression.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,11 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
639639
faili = nr_pages - 1;
640640
cb->nr_pages = nr_pages;
641641

642-
add_ra_bio_pages(inode, em_start + em_len, cb);
642+
/* In the parent-locked case, we only locked the range we are
643+
* interested in. In all other cases, we can opportunistically
644+
* cache decompressed data that goes beyond the requested range. */
645+
if (!(bio_flags & EXTENT_BIO_PARENT_LOCKED))
646+
add_ra_bio_pages(inode, em_start + em_len, cb);
643647

644648
/* include any pages we added in add_ra-bio_pages */
645649
uncompressed_len = bio->bi_vcnt * PAGE_CACHE_SIZE;

fs/btrfs/extent_io.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2764,11 +2764,12 @@ static int __do_readpage(struct extent_io_tree *tree,
27642764
struct block_device *bdev;
27652765
int ret;
27662766
int nr = 0;
2767+
int parent_locked = *bio_flags & EXTENT_BIO_PARENT_LOCKED;
27672768
size_t pg_offset = 0;
27682769
size_t iosize;
27692770
size_t disk_io_size;
27702771
size_t blocksize = inode->i_sb->s_blocksize;
2771-
unsigned long this_bio_flag = 0;
2772+
unsigned long this_bio_flag = *bio_flags & EXTENT_BIO_PARENT_LOCKED;
27722773

27732774
set_page_extent_mapped(page);
27742775

@@ -2807,23 +2808,26 @@ static int __do_readpage(struct extent_io_tree *tree,
28072808
kunmap_atomic(userpage);
28082809
set_extent_uptodate(tree, cur, cur + iosize - 1,
28092810
&cached, GFP_NOFS);
2810-
unlock_extent_cached(tree, cur, cur + iosize - 1,
2811-
&cached, GFP_NOFS);
2811+
if (!parent_locked)
2812+
unlock_extent_cached(tree, cur,
2813+
cur + iosize - 1,
2814+
&cached, GFP_NOFS);
28122815
break;
28132816
}
28142817
em = __get_extent_map(inode, page, pg_offset, cur,
28152818
end - cur + 1, get_extent, em_cached);
28162819
if (IS_ERR_OR_NULL(em)) {
28172820
SetPageError(page);
2818-
unlock_extent(tree, cur, end);
2821+
if (!parent_locked)
2822+
unlock_extent(tree, cur, end);
28192823
break;
28202824
}
28212825
extent_offset = cur - em->start;
28222826
BUG_ON(extent_map_end(em) <= cur);
28232827
BUG_ON(end < cur);
28242828

28252829
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) {
2826-
this_bio_flag = EXTENT_BIO_COMPRESSED;
2830+
this_bio_flag |= EXTENT_BIO_COMPRESSED;
28272831
extent_set_compress_type(&this_bio_flag,
28282832
em->compress_type);
28292833
}
@@ -2867,7 +2871,8 @@ static int __do_readpage(struct extent_io_tree *tree,
28672871
if (test_range_bit(tree, cur, cur_end,
28682872
EXTENT_UPTODATE, 1, NULL)) {
28692873
check_page_uptodate(tree, page);
2870-
unlock_extent(tree, cur, cur + iosize - 1);
2874+
if (!parent_locked)
2875+
unlock_extent(tree, cur, cur + iosize - 1);
28712876
cur = cur + iosize;
28722877
pg_offset += iosize;
28732878
continue;
@@ -2877,7 +2882,8 @@ static int __do_readpage(struct extent_io_tree *tree,
28772882
*/
28782883
if (block_start == EXTENT_MAP_INLINE) {
28792884
SetPageError(page);
2880-
unlock_extent(tree, cur, cur + iosize - 1);
2885+
if (!parent_locked)
2886+
unlock_extent(tree, cur, cur + iosize - 1);
28812887
cur = cur + iosize;
28822888
pg_offset += iosize;
28832889
continue;
@@ -2895,7 +2901,8 @@ static int __do_readpage(struct extent_io_tree *tree,
28952901
*bio_flags = this_bio_flag;
28962902
} else {
28972903
SetPageError(page);
2898-
unlock_extent(tree, cur, cur + iosize - 1);
2904+
if (!parent_locked)
2905+
unlock_extent(tree, cur, cur + iosize - 1);
28992906
}
29002907
cur = cur + iosize;
29012908
pg_offset += iosize;
@@ -3021,6 +3028,20 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
30213028
return ret;
30223029
}
30233030

3031+
int extent_read_full_page_nolock(struct extent_io_tree *tree, struct page *page,
3032+
get_extent_t *get_extent, int mirror_num)
3033+
{
3034+
struct bio *bio = NULL;
3035+
unsigned long bio_flags = EXTENT_BIO_PARENT_LOCKED;
3036+
int ret;
3037+
3038+
ret = __do_readpage(tree, page, get_extent, NULL, &bio, mirror_num,
3039+
&bio_flags, READ);
3040+
if (bio)
3041+
ret = submit_one_bio(READ, bio, mirror_num, bio_flags);
3042+
return ret;
3043+
}
3044+
30243045
static noinline void update_nr_written(struct page *page,
30253046
struct writeback_control *wbc,
30263047
unsigned long nr_written)

fs/btrfs/extent_io.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*/
3030
#define EXTENT_BIO_COMPRESSED 1
3131
#define EXTENT_BIO_TREE_LOG 2
32+
#define EXTENT_BIO_PARENT_LOCKED 4
3233
#define EXTENT_BIO_FLAG_SHIFT 16
3334

3435
/* these are bit numbers for test/set bit */
@@ -199,6 +200,8 @@ int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end,
199200
int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end);
200201
int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
201202
get_extent_t *get_extent, int mirror_num);
203+
int extent_read_full_page_nolock(struct extent_io_tree *tree, struct page *page,
204+
get_extent_t *get_extent, int mirror_num);
202205
int __init extent_io_init(void);
203206
void extent_io_exit(void);
204207

0 commit comments

Comments
 (0)