mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
btrfs: factor out a can_finish_ordered_extent helper
Factor out a helper from btrfs_mark_ordered_io_finished that does the actual per-ordered_extent work to check if we want to schedule an I/O completion. This new helper will later be used complete an ordered_extent without first doing a lookup. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
c59360f61a
commit
53df25869a
@ -303,6 +303,60 @@ static void finish_ordered_fn(struct btrfs_work *work)
|
||||
btrfs_finish_ordered_io(ordered_extent);
|
||||
}
|
||||
|
||||
static bool can_finish_ordered_extent(struct btrfs_ordered_extent *ordered,
|
||||
struct page *page, u64 file_offset,
|
||||
u64 len, bool uptodate)
|
||||
{
|
||||
struct btrfs_inode *inode = BTRFS_I(ordered->inode);
|
||||
struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
||||
|
||||
lockdep_assert_held(&inode->ordered_tree.lock);
|
||||
|
||||
if (page) {
|
||||
ASSERT(page->mapping);
|
||||
ASSERT(page_offset(page) <= file_offset);
|
||||
ASSERT(file_offset + len <= page_offset(page) + PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Ordered (Private2) bit indicates whether we still have
|
||||
* pending io unfinished for the ordered extent.
|
||||
*
|
||||
* If there's no such bit, we need to skip to next range.
|
||||
*/
|
||||
if (!btrfs_page_test_ordered(fs_info, page, file_offset, len))
|
||||
return false;
|
||||
btrfs_page_clear_ordered(fs_info, page, file_offset, len);
|
||||
}
|
||||
|
||||
/* Now we're fine to update the accounting. */
|
||||
if (WARN_ON_ONCE(len > ordered->bytes_left)) {
|
||||
btrfs_crit(fs_info,
|
||||
"bad ordered extent accounting, root=%llu ino=%llu OE offset=%llu OE len=%llu to_dec=%llu left=%llu",
|
||||
inode->root->root_key.objectid, btrfs_ino(inode),
|
||||
ordered->file_offset, ordered->num_bytes,
|
||||
len, ordered->bytes_left);
|
||||
ordered->bytes_left = 0;
|
||||
} else {
|
||||
ordered->bytes_left -= len;
|
||||
}
|
||||
|
||||
if (!uptodate)
|
||||
set_bit(BTRFS_ORDERED_IOERR, &ordered->flags);
|
||||
|
||||
if (ordered->bytes_left)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* All the IO of the ordered extent is finished, we need to queue
|
||||
* the finish_func to be executed.
|
||||
*/
|
||||
set_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags);
|
||||
cond_wake_up(&ordered->wait);
|
||||
refcount_inc(&ordered->refs);
|
||||
trace_btrfs_ordered_extent_mark_finished(inode, ordered);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark all ordered extents io inside the specified range finished.
|
||||
*
|
||||
@ -333,10 +387,6 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode,
|
||||
else
|
||||
wq = fs_info->endio_write_workers;
|
||||
|
||||
if (page)
|
||||
ASSERT(page->mapping && page_offset(page) <= file_offset &&
|
||||
file_offset + num_bytes <= page_offset(page) + PAGE_SIZE);
|
||||
|
||||
spin_lock_irqsave(&tree->lock, flags);
|
||||
while (cur < file_offset + num_bytes) {
|
||||
u64 entry_end;
|
||||
@ -389,47 +439,7 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode,
|
||||
ASSERT(end + 1 - cur < U32_MAX);
|
||||
len = end + 1 - cur;
|
||||
|
||||
if (page) {
|
||||
/*
|
||||
* Ordered (Private2) bit indicates whether we still
|
||||
* have pending io unfinished for the ordered extent.
|
||||
*
|
||||
* If there's no such bit, we need to skip to next range.
|
||||
*/
|
||||
if (!btrfs_page_test_ordered(fs_info, page, cur, len)) {
|
||||
cur += len;
|
||||
continue;
|
||||
}
|
||||
btrfs_page_clear_ordered(fs_info, page, cur, len);
|
||||
}
|
||||
|
||||
/* Now we're fine to update the accounting */
|
||||
if (unlikely(len > entry->bytes_left)) {
|
||||
WARN_ON(1);
|
||||
btrfs_crit(fs_info,
|
||||
"bad ordered extent accounting, root=%llu ino=%llu OE offset=%llu OE len=%llu to_dec=%u left=%llu",
|
||||
inode->root->root_key.objectid,
|
||||
btrfs_ino(inode),
|
||||
entry->file_offset,
|
||||
entry->num_bytes,
|
||||
len, entry->bytes_left);
|
||||
entry->bytes_left = 0;
|
||||
} else {
|
||||
entry->bytes_left -= len;
|
||||
}
|
||||
|
||||
if (!uptodate)
|
||||
set_bit(BTRFS_ORDERED_IOERR, &entry->flags);
|
||||
|
||||
/*
|
||||
* All the IO of the ordered extent is finished, we need to queue
|
||||
* the finish_func to be executed.
|
||||
*/
|
||||
if (entry->bytes_left == 0) {
|
||||
set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags);
|
||||
cond_wake_up(&entry->wait);
|
||||
refcount_inc(&entry->refs);
|
||||
trace_btrfs_ordered_extent_mark_finished(inode, entry);
|
||||
if (can_finish_ordered_extent(entry, page, cur, len, uptodate)) {
|
||||
spin_unlock_irqrestore(&tree->lock, flags);
|
||||
btrfs_init_work(&entry->work, finish_ordered_fn, NULL, NULL);
|
||||
btrfs_queue_work(wq, &entry->work);
|
||||
|
Loading…
Reference in New Issue
Block a user