diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
| -rw-r--r-- | fs/btrfs/ordered-data.c | 91 |
1 files changed, 52 insertions, 39 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 5df02c707aee..b32d4eabe0ab 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -156,6 +156,20 @@ static struct btrfs_ordered_extent *alloc_ordered_extent( const bool is_nocow = (flags & ((1U << BTRFS_ORDERED_NOCOW) | (1U << BTRFS_ORDERED_PREALLOC))); + /* Only one type flag can be set. */ + ASSERT(has_single_bit_set(flags & BTRFS_ORDERED_EXCLUSIVE_FLAGS), + "flags=0x%lx", flags); + + /* DIRECT cannot be set with COMPRESSED nor ENCODED. */ + if (test_bit(BTRFS_ORDERED_DIRECT, &flags)) { + ASSERT(!test_bit(BTRFS_ORDERED_COMPRESSED, &flags)); + ASSERT(!test_bit(BTRFS_ORDERED_ENCODED, &flags)); + } + + /* ENCODED must be set with COMPRESSED. */ + if (test_bit(BTRFS_ORDERED_ENCODED, &flags)) + ASSERT(test_bit(BTRFS_ORDERED_COMPRESSED, &flags)); + /* * For a NOCOW write we can free the qgroup reserve right now. For a COW * one we transfer the reserved space from the inode's iotree into the @@ -197,7 +211,7 @@ static struct btrfs_ordered_extent *alloc_ordered_extent( entry->flags = flags; refcount_set(&entry->refs, 1); init_waitqueue_head(&entry->wait); - INIT_LIST_HEAD(&entry->list); + INIT_LIST_HEAD(&entry->csum_list); INIT_LIST_HEAD(&entry->log_list); INIT_LIST_HEAD(&entry->root_extent_list); INIT_LIST_HEAD(&entry->work_list); @@ -240,10 +254,15 @@ static void insert_ordered_extent(struct btrfs_ordered_extent *entry) spin_lock(&inode->ordered_tree_lock); node = tree_insert(&inode->ordered_tree, entry->file_offset, &entry->rb_node); - if (unlikely(node)) + if (unlikely(node)) { + struct btrfs_ordered_extent *exist = + rb_entry(node, struct btrfs_ordered_extent, rb_node); + btrfs_panic(fs_info, -EEXIST, - "inconsistency in ordered tree at offset %llu", - entry->file_offset); +"overlapping ordered extents, existing oe file_offset %llu num_bytes %llu flags 0x%lx, new oe file_offset %llu num_bytes %llu flags 0x%lx", + exist->file_offset, exist->num_bytes, exist->flags, + entry->file_offset, entry->num_bytes, entry->flags); + } spin_unlock(&inode->ordered_tree_lock); spin_lock(&root->ordered_extent_lock); @@ -284,7 +303,7 @@ struct btrfs_ordered_extent *btrfs_alloc_ordered_extent( { struct btrfs_ordered_extent *entry; - ASSERT((flags & ~BTRFS_ORDERED_TYPE_FLAGS) == 0); + ASSERT((flags & ~BTRFS_ORDERED_TYPE_FLAGS) == 0, "flags=0x%lx", flags); /* * For regular writes, we just use the members in @file_extent. @@ -329,7 +348,7 @@ void btrfs_add_ordered_sum(struct btrfs_ordered_extent *entry, struct btrfs_inode *inode = entry->inode; spin_lock(&inode->ordered_tree_lock); - list_add_tail(&sum->list, &entry->list); + list_add_tail(&sum->list, &entry->csum_list); spin_unlock(&inode->ordered_tree_lock); } @@ -339,6 +358,18 @@ void btrfs_mark_ordered_extent_error(struct btrfs_ordered_extent *ordered) mapping_set_error(ordered->inode->vfs_inode.i_mapping, -EIO); } +void btrfs_mark_ordered_extent_truncated(struct btrfs_ordered_extent *ordered, + u64 truncate_len) +{ + struct btrfs_inode *inode = ordered->inode; + + ASSERT(truncate_len <= ordered->num_bytes); + spin_lock(&inode->ordered_tree_lock); + set_bit(BTRFS_ORDERED_TRUNCATED, &ordered->flags); + ordered->truncated_len = min(ordered->truncated_len, truncate_len); + spin_unlock(&inode->ordered_tree_lock); +} + static void finish_ordered_fn(struct btrfs_work *work) { struct btrfs_ordered_extent *ordered_extent; @@ -348,30 +379,13 @@ static void finish_ordered_fn(struct btrfs_work *work) } static bool can_finish_ordered_extent(struct btrfs_ordered_extent *ordered, - struct folio *folio, u64 file_offset, - u64 len, bool uptodate) + u64 file_offset, u64 len, bool uptodate) { struct btrfs_inode *inode = ordered->inode; struct btrfs_fs_info *fs_info = inode->root->fs_info; lockdep_assert_held(&inode->ordered_tree_lock); - if (folio) { - ASSERT(folio->mapping); - ASSERT(folio_pos(folio) <= file_offset); - ASSERT(file_offset + len <= folio_next_pos(folio)); - - /* - * Ordered flag indicates whether we still have - * pending io unfinished for the ordered extent. - * - * If it's not set, we need to skip to next range. - */ - if (!btrfs_folio_test_ordered(fs_info, folio, file_offset, len)) - return false; - btrfs_folio_clear_ordered(fs_info, folio, file_offset, len); - } - /* Now we're fine to update the accounting. */ if (WARN_ON_ONCE(len > ordered->bytes_left)) { btrfs_crit(fs_info, @@ -385,7 +399,7 @@ static bool can_finish_ordered_extent(struct btrfs_ordered_extent *ordered, } if (!uptodate) - set_bit(BTRFS_ORDERED_IOERR, &ordered->flags); + btrfs_mark_ordered_extent_error(ordered); if (ordered->bytes_left) return false; @@ -413,8 +427,7 @@ static void btrfs_queue_ordered_fn(struct btrfs_ordered_extent *ordered) } void btrfs_finish_ordered_extent(struct btrfs_ordered_extent *ordered, - struct folio *folio, u64 file_offset, u64 len, - bool uptodate) + u64 file_offset, u64 len, bool uptodate) { struct btrfs_inode *inode = ordered->inode; bool ret; @@ -422,7 +435,7 @@ void btrfs_finish_ordered_extent(struct btrfs_ordered_extent *ordered, trace_btrfs_finish_ordered_extent(inode, file_offset, len, uptodate); spin_lock(&inode->ordered_tree_lock); - ret = can_finish_ordered_extent(ordered, folio, file_offset, len, + ret = can_finish_ordered_extent(ordered, file_offset, len, uptodate); spin_unlock(&inode->ordered_tree_lock); @@ -475,8 +488,7 @@ void btrfs_finish_ordered_extent(struct btrfs_ordered_extent *ordered, * extent(s) covering it. */ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode, - struct folio *folio, u64 file_offset, - u64 num_bytes, bool uptodate) + u64 file_offset, u64 num_bytes, bool uptodate) { struct rb_node *node; struct btrfs_ordered_extent *entry = NULL; @@ -536,7 +548,7 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode, len = this_end - cur; ASSERT(len < U32_MAX); - if (can_finish_ordered_extent(entry, folio, cur, len, uptodate)) { + if (can_finish_ordered_extent(entry, cur, len, uptodate)) { spin_unlock(&inode->ordered_tree_lock); btrfs_queue_ordered_fn(entry); spin_lock(&inode->ordered_tree_lock); @@ -628,7 +640,7 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) ASSERT(list_empty(&entry->log_list)); ASSERT(RB_EMPTY_NODE(&entry->rb_node)); btrfs_add_delayed_iput(entry->inode); - list_for_each_entry_safe(sum, tmp, &entry->list, list) + list_for_each_entry_safe(sum, tmp, &entry->csum_list, list) kvfree(sum); kmem_cache_free(btrfs_ordered_extent_cache, entry); } @@ -638,9 +650,9 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) * remove an ordered extent from the tree. No references are dropped * and waiters are woken up. */ -void btrfs_remove_ordered_extent(struct btrfs_inode *btrfs_inode, - struct btrfs_ordered_extent *entry) +void btrfs_remove_ordered_extent(struct btrfs_ordered_extent *entry) { + struct btrfs_inode *btrfs_inode = entry->inode; struct btrfs_root *root = btrfs_inode->root; struct btrfs_fs_info *fs_info = root->fs_info; struct rb_node *node; @@ -1239,7 +1251,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( trace_btrfs_ordered_extent_split(inode, ordered); - ASSERT(!(flags & (1U << BTRFS_ORDERED_COMPRESSED))); + ASSERT(!(flags & (1U << BTRFS_ORDERED_COMPRESSED)), "flags=0x%lx", flags); /* * The entire bio must be covered by the ordered extent, but we can't @@ -1261,7 +1273,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( } /* We cannot split partially completed ordered extents. */ if (ordered->bytes_left) { - ASSERT(!(flags & ~BTRFS_ORDERED_TYPE_FLAGS)); + ASSERT(!(flags & ~BTRFS_ORDERED_TYPE_FLAGS), "flags=0x%lx", flags); if (WARN_ON_ONCE(ordered->bytes_left != ordered->disk_num_bytes)) return ERR_PTR(-EINVAL); } @@ -1308,7 +1320,8 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( ordered->ram_bytes -= len; if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) { - ASSERT(ordered->bytes_left == 0); + ASSERT(ordered->bytes_left == 0, "ordered->bytes_left=%llu", + ordered->bytes_left); new->bytes_left = 0; } else { ordered->bytes_left -= len; @@ -1323,10 +1336,10 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( } } - list_for_each_entry_safe(sum, tmpsum, &ordered->list, list) { + list_for_each_entry_safe(sum, tmpsum, &ordered->csum_list, list) { if (offset == len) break; - list_move_tail(&sum->list, &new->list); + list_move_tail(&sum->list, &new->csum_list); offset += sum->len; } |
