diff options
Diffstat (limited to 'fs/btrfs/inode.c')
| -rw-r--r-- | fs/btrfs/inode.c | 27 | 
1 files changed, 22 insertions, 5 deletions
| diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 128f3e58634f..d94e3f68b9b1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -135,6 +135,18 @@ static inline void btrfs_cleanup_ordered_extents(struct inode *inode,  						 const u64 offset,  						 const u64 bytes)  { +	unsigned long index = offset >> PAGE_SHIFT; +	unsigned long end_index = (offset + bytes - 1) >> PAGE_SHIFT; +	struct page *page; + +	while (index <= end_index) { +		page = find_get_page(inode->i_mapping, index); +		index++; +		if (!page) +			continue; +		ClearPagePrivate2(page); +		put_page(page); +	}  	return __endio_write_update_ordered(inode, offset + PAGE_SIZE,  					    bytes - PAGE_SIZE, false);  } @@ -8357,11 +8369,8 @@ static void btrfs_endio_direct_read(struct bio *bio)  	struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);  	blk_status_t err = bio->bi_status; -	if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED) { +	if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)  		err = btrfs_subio_endio_read(inode, io_bio, err); -		if (!err) -			bio->bi_status = 0; -	}  	unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,  		      dip->logical_offset + dip->bytes - 1); @@ -8369,7 +8378,7 @@ static void btrfs_endio_direct_read(struct bio *bio)  	kfree(dip); -	dio_bio->bi_status = bio->bi_status; +	dio_bio->bi_status = err;  	dio_end_io(dio_bio);  	if (io_bio->end_io) @@ -8387,6 +8396,7 @@ static void __endio_write_update_ordered(struct inode *inode,  	btrfs_work_func_t func;  	u64 ordered_offset = offset;  	u64 ordered_bytes = bytes; +	u64 last_offset;  	int ret;  	if (btrfs_is_free_space_inode(BTRFS_I(inode))) { @@ -8398,6 +8408,7 @@ static void __endio_write_update_ordered(struct inode *inode,  	}  again: +	last_offset = ordered_offset;  	ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,  						   &ordered_offset,  						   ordered_bytes, @@ -8409,6 +8420,12 @@ again:  	btrfs_queue_work(wq, &ordered->work);  out_test:  	/* +	 * If btrfs_dec_test_ordered_pending does not find any ordered extent +	 * in the range, we can exit. +	 */ +	if (ordered_offset == last_offset) +		return; +	/*  	 * our bio might span multiple ordered extents.  If we haven't  	 * completed the accounting for the whole dio, go back and try again  	 */ |