diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fc6401a..6016500 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -120,30 +120,26 @@ static int btrfs_dirty_inode(struct inode *inode); static void __endio_write_update_ordered(struct inode *inode, u64 offset, u64 bytes, - bool uptodate, bool cleanup); - -static inline void btrfs_endio_direct_write_update_ordered(struct inode *inode, - u64 offset, - u64 bytes, - bool uptodate) -{ - return __endio_write_update_ordered(inode, offset, bytes, uptodate, false); -} + bool uptodate); /* - * Cleanup all submitted ordered extents in specified range to handle error - * in cow_file_range() and run_delalloc_nocow(). - * Compression handles error and ordered extent submission by itself, - * so no need to call this function. + * Cleanup all submitted ordered extents in specified range to handle errors + * from the fill_dellaloc() callback. * - * NOTE: caller must ensure extent_clear_unlock_delalloc() in error handler - * doesn't cover any range of submitted ordered extent. - * Or we will double free metadata for submitted ordered extent. + * NOTE: caller must ensure that when an error happens, it can not call + * extent_clear_unlock_delalloc() to clear both the bits EXTENT_DO_ACCOUNTING + * and EXTENT_DELALLOC simultaneously, because that causes the reserved metadata + * to be released, which we want to happen only when finishing the ordered + * extent (btrfs_finish_ordered_io()). Also note that the caller of the + * fill_dealloc() callback already does proper cleanup for the first page of + * the range, that is, it invokes the callback writepage_end_io_hook() for the + * range of the first page. */ static inline void btrfs_cleanup_ordered_extents(struct inode *inode, u64 offset, u64 bytes) { - return __endio_write_update_ordered(inode, offset, bytes, false, true); + return __endio_write_update_ordered(inode, offset + PAGE_SIZE, + bytes - PAGE_SIZE, false); } #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS @@ -958,7 +954,6 @@ static noinline int cow_file_range(struct inode *inode, u64 disk_num_bytes; u64 cur_alloc_size; u64 blocksize = fs_info->sectorsize; - u64 orig_start = start; struct btrfs_key ins; struct extent_map *em; int ret = 0; @@ -1100,7 +1095,6 @@ static noinline int cow_file_range(struct inode *inode, EXTENT_DELALLOC | EXTENT_DEFRAG, PAGE_UNLOCK | PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK); - btrfs_cleanup_ordered_extents(inode, orig_start, end - orig_start + 1); goto out; } @@ -1526,8 +1520,6 @@ static noinline int run_delalloc_nocow(struct inode *inode, PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK); - if (ret) - btrfs_cleanup_ordered_extents(inode, start, end - start + 1); btrfs_free_path(path); return ret; } @@ -1577,6 +1569,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, ret = cow_file_range_async(inode, locked_page, start, end, page_started, nr_written); } + if (ret) + btrfs_cleanup_ordered_extents(inode, start, end - start + 1); return ret; } @@ -8176,7 +8170,7 @@ static void btrfs_endio_direct_read(struct bio *bio) static void __endio_write_update_ordered(struct inode *inode, u64 offset, u64 bytes, - bool uptodate, bool cleanup) + bool uptodate) { struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_ordered_extent *ordered = NULL; @@ -8194,16 +8188,6 @@ static void __endio_write_update_ordered(struct inode *inode, func = btrfs_endio_write_helper; } - /* - * In cleanup case, the first page of the range will be handled - * by end_extent_writepage() when called from __extent_writepage() - * - * So we must skip first page, or we will underflow ordered->bytes_left - */ - if (cleanup) { - ordered_offset += PAGE_SIZE; - ordered_bytes -= PAGE_SIZE; - } again: ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, &ordered_offset, @@ -8231,10 +8215,10 @@ static void btrfs_endio_direct_write(struct bio *bio) struct btrfs_dio_private *dip = bio->bi_private; struct bio *dio_bio = dip->dio_bio; - btrfs_endio_direct_write_update_ordered(dip->inode, - dip->logical_offset, - dip->bytes, - !bio->bi_error); + __endio_write_update_ordered(dip->inode, + dip->logical_offset, + dip->bytes, + !bio->bi_error); kfree(dip); @@ -8595,10 +8579,10 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode, io_bio = NULL; } else { if (write) - btrfs_endio_direct_write_update_ordered(inode, + __endio_write_update_ordered(inode, file_offset, dio_bio->bi_iter.bi_size, - 0); + false); else unlock_extent(&BTRFS_I(inode)->io_tree, file_offset, file_offset + dio_bio->bi_iter.bi_size - 1); @@ -8733,11 +8717,11 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) */ if (dio_data.unsubmitted_oe_range_start < dio_data.unsubmitted_oe_range_end) - btrfs_endio_direct_write_update_ordered(inode, + __endio_write_update_ordered(inode, dio_data.unsubmitted_oe_range_start, dio_data.unsubmitted_oe_range_end - dio_data.unsubmitted_oe_range_start, - 0); + false); } else if (ret >= 0 && (size_t)ret < count) btrfs_delalloc_release_space(inode, offset, count - (size_t)ret);