|
@@ -135,6 +135,18 @@ static inline void btrfs_cleanup_ordered_extents(struct inode *inode,
|
|
const u64 offset,
|
|
const u64 offset,
|
|
const u64 bytes)
|
|
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,
|
|
return __endio_write_update_ordered(inode, offset + PAGE_SIZE,
|
|
bytes - PAGE_SIZE, false);
|
|
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);
|
|
struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
|
|
blk_status_t err = bio->bi_status;
|
|
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);
|
|
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,
|
|
unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
|
|
dip->logical_offset + dip->bytes - 1);
|
|
dip->logical_offset + dip->bytes - 1);
|
|
@@ -8369,7 +8378,7 @@ static void btrfs_endio_direct_read(struct bio *bio)
|
|
|
|
|
|
kfree(dip);
|
|
kfree(dip);
|
|
|
|
|
|
- dio_bio->bi_status = bio->bi_status;
|
|
|
|
|
|
+ dio_bio->bi_status = err;
|
|
dio_end_io(dio_bio);
|
|
dio_end_io(dio_bio);
|
|
|
|
|
|
if (io_bio->end_io)
|
|
if (io_bio->end_io)
|
|
@@ -8387,6 +8396,7 @@ static void __endio_write_update_ordered(struct inode *inode,
|
|
btrfs_work_func_t func;
|
|
btrfs_work_func_t func;
|
|
u64 ordered_offset = offset;
|
|
u64 ordered_offset = offset;
|
|
u64 ordered_bytes = bytes;
|
|
u64 ordered_bytes = bytes;
|
|
|
|
+ u64 last_offset;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
|
|
if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
|
|
@@ -8398,6 +8408,7 @@ static void __endio_write_update_ordered(struct inode *inode,
|
|
}
|
|
}
|
|
|
|
|
|
again:
|
|
again:
|
|
|
|
+ last_offset = ordered_offset;
|
|
ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
|
|
ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
|
|
&ordered_offset,
|
|
&ordered_offset,
|
|
ordered_bytes,
|
|
ordered_bytes,
|
|
@@ -8408,6 +8419,12 @@ again:
|
|
btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL);
|
|
btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL);
|
|
btrfs_queue_work(wq, &ordered->work);
|
|
btrfs_queue_work(wq, &ordered->work);
|
|
out_test:
|
|
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
|
|
* our bio might span multiple ordered extents. If we haven't
|
|
* completed the accounting for the whole dio, go back and try again
|
|
* completed the accounting for the whole dio, go back and try again
|