Commit 79eb2c07 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.12-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:

 - in incremental send, fix invalid clone operation for file that got
   its size decreased

 - fix __counted_by() annotation of send path cache entries, we do not
   store the terminating NUL

 - fix a longstanding bug in relocation (and quite hard to hit by
   chance), drop back reference cache that can get out of sync after
   transaction commit

 - wait for fixup worker kthread before finishing umount

 - add missing raid-stripe-tree extent for NOCOW files, zoned mode
   cannot have NOCOW files but RST is meant to be a standalone feature

 - handle transaction start error during relocation, avoid potential
   NULL pointer dereference of relocation control structure (reported by
   syzbot)

 - disable module-wide rate limiting of debug level messages

 - minor fix to tracepoint definition (reported by checkpatch.pl)

* tag 'for-6.12-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: disable rate limiting when debug enabled
  btrfs: wait for fixup workers before stopping cleaner kthread during umount
  btrfs: fix a NULL pointer dereference when failed to start a new trasacntion
  btrfs: send: fix invalid clone operation for file that got its size decreased
  btrfs: tracepoints: end assignment with semicolon at btrfs_qgroup_extent event class
  btrfs: drop the backref cache during relocation if we commit
  btrfs: also add stripe entries for NOCOW writes
  btrfs: send: fix buffer overflow detection when copying path to cache entry
parents b7a838ee d6e7ac65
...@@ -3179,10 +3179,14 @@ void btrfs_backref_release_cache(struct btrfs_backref_cache *cache) ...@@ -3179,10 +3179,14 @@ void btrfs_backref_release_cache(struct btrfs_backref_cache *cache)
btrfs_backref_cleanup_node(cache, node); btrfs_backref_cleanup_node(cache, node);
} }
cache->last_trans = 0; for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
while (!list_empty(&cache->pending[i])) {
for (i = 0; i < BTRFS_MAX_LEVEL; i++) node = list_first_entry(&cache->pending[i],
ASSERT(list_empty(&cache->pending[i])); struct btrfs_backref_node,
list);
btrfs_backref_cleanup_node(cache, node);
}
}
ASSERT(list_empty(&cache->pending_edge)); ASSERT(list_empty(&cache->pending_edge));
ASSERT(list_empty(&cache->useless_node)); ASSERT(list_empty(&cache->useless_node));
ASSERT(list_empty(&cache->changed)); ASSERT(list_empty(&cache->changed));
......
...@@ -4255,6 +4255,17 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) ...@@ -4255,6 +4255,17 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
/* clear out the rbtree of defraggable inodes */ /* clear out the rbtree of defraggable inodes */
btrfs_cleanup_defrag_inodes(fs_info); btrfs_cleanup_defrag_inodes(fs_info);
/*
* Wait for any fixup workers to complete.
* If we don't wait for them here and they are still running by the time
* we call kthread_stop() against the cleaner kthread further below, we
* get an use-after-free on the cleaner because the fixup worker adds an
* inode to the list of delayed iputs and then attempts to wakeup the
* cleaner kthread, which was already stopped and destroyed. We parked
* already the cleaner, but below we run all pending delayed iputs.
*/
btrfs_flush_workqueue(fs_info->fixup_workers);
/* /*
* After we parked the cleaner kthread, ordered extents may have * After we parked the cleaner kthread, ordered extents may have
* completed and created new delayed iputs. If one of the async reclaim * completed and created new delayed iputs. If one of the async reclaim
......
...@@ -3111,6 +3111,11 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent) ...@@ -3111,6 +3111,11 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
ret = btrfs_update_inode_fallback(trans, inode); ret = btrfs_update_inode_fallback(trans, inode);
if (ret) /* -ENOMEM or corruption */ if (ret) /* -ENOMEM or corruption */
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
ret = btrfs_insert_raid_extent(trans, ordered_extent);
if (ret)
btrfs_abort_transaction(trans, ret);
goto out; goto out;
} }
......
...@@ -239,7 +239,8 @@ void __cold _btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...@@ -239,7 +239,8 @@ void __cold _btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt,
vaf.fmt = fmt; vaf.fmt = fmt;
vaf.va = &args; vaf.va = &args;
if (__ratelimit(ratelimit)) { /* Do not ratelimit if CONFIG_BTRFS_DEBUG is enabled. */
if (IS_ENABLED(CONFIG_BTRFS_DEBUG) || __ratelimit(ratelimit)) {
if (fs_info) { if (fs_info) {
char statestr[STATE_STRING_BUF_LEN]; char statestr[STATE_STRING_BUF_LEN];
......
...@@ -232,70 +232,6 @@ static struct btrfs_backref_node *walk_down_backref( ...@@ -232,70 +232,6 @@ static struct btrfs_backref_node *walk_down_backref(
return NULL; return NULL;
} }
static void update_backref_node(struct btrfs_backref_cache *cache,
struct btrfs_backref_node *node, u64 bytenr)
{
struct rb_node *rb_node;
rb_erase(&node->rb_node, &cache->rb_root);
node->bytenr = bytenr;
rb_node = rb_simple_insert(&cache->rb_root, node->bytenr, &node->rb_node);
if (rb_node)
btrfs_backref_panic(cache->fs_info, bytenr, -EEXIST);
}
/*
* update backref cache after a transaction commit
*/
static int update_backref_cache(struct btrfs_trans_handle *trans,
struct btrfs_backref_cache *cache)
{
struct btrfs_backref_node *node;
int level = 0;
if (cache->last_trans == 0) {
cache->last_trans = trans->transid;
return 0;
}
if (cache->last_trans == trans->transid)
return 0;
/*
* detached nodes are used to avoid unnecessary backref
* lookup. transaction commit changes the extent tree.
* so the detached nodes are no longer useful.
*/
while (!list_empty(&cache->detached)) {
node = list_entry(cache->detached.next,
struct btrfs_backref_node, list);
btrfs_backref_cleanup_node(cache, node);
}
while (!list_empty(&cache->changed)) {
node = list_entry(cache->changed.next,
struct btrfs_backref_node, list);
list_del_init(&node->list);
BUG_ON(node->pending);
update_backref_node(cache, node, node->new_bytenr);
}
/*
* some nodes can be left in the pending list if there were
* errors during processing the pending nodes.
*/
for (level = 0; level < BTRFS_MAX_LEVEL; level++) {
list_for_each_entry(node, &cache->pending[level], list) {
BUG_ON(!node->pending);
if (node->bytenr == node->new_bytenr)
continue;
update_backref_node(cache, node, node->new_bytenr);
}
}
cache->last_trans = 0;
return 1;
}
static bool reloc_root_is_dead(const struct btrfs_root *root) static bool reloc_root_is_dead(const struct btrfs_root *root)
{ {
/* /*
...@@ -551,9 +487,6 @@ static int clone_backref_node(struct btrfs_trans_handle *trans, ...@@ -551,9 +487,6 @@ static int clone_backref_node(struct btrfs_trans_handle *trans,
struct btrfs_backref_edge *new_edge; struct btrfs_backref_edge *new_edge;
struct rb_node *rb_node; struct rb_node *rb_node;
if (cache->last_trans > 0)
update_backref_cache(trans, cache);
rb_node = rb_simple_search(&cache->rb_root, src->commit_root->start); rb_node = rb_simple_search(&cache->rb_root, src->commit_root->start);
if (rb_node) { if (rb_node) {
node = rb_entry(rb_node, struct btrfs_backref_node, rb_node); node = rb_entry(rb_node, struct btrfs_backref_node, rb_node);
...@@ -923,7 +856,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, ...@@ -923,7 +856,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
btrfs_grab_root(reloc_root); btrfs_grab_root(reloc_root);
/* root->reloc_root will stay until current relocation finished */ /* root->reloc_root will stay until current relocation finished */
if (fs_info->reloc_ctl->merge_reloc_tree && if (fs_info->reloc_ctl && fs_info->reloc_ctl->merge_reloc_tree &&
btrfs_root_refs(root_item) == 0) { btrfs_root_refs(root_item) == 0) {
set_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state); set_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state);
/* /*
...@@ -3698,11 +3631,9 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) ...@@ -3698,11 +3631,9 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
break; break;
} }
restart: restart:
if (update_backref_cache(trans, &rc->backref_cache)) { if (rc->backref_cache.last_trans != trans->transid)
btrfs_end_transaction(trans); btrfs_backref_release_cache(&rc->backref_cache);
trans = NULL; rc->backref_cache.last_trans = trans->transid;
continue;
}
ret = find_next_extent(rc, path, &key); ret = find_next_extent(rc, path, &key);
if (ret < 0) if (ret < 0)
......
...@@ -346,8 +346,10 @@ struct name_cache_entry { ...@@ -346,8 +346,10 @@ struct name_cache_entry {
u64 parent_gen; u64 parent_gen;
int ret; int ret;
int need_later_update; int need_later_update;
/* Name length without NUL terminator. */
int name_len; int name_len;
char name[] __counted_by(name_len); /* Not NUL terminated. */
char name[] __counted_by(name_len) __nonstring;
}; };
/* See the comment at lru_cache.h about struct btrfs_lru_cache_entry. */ /* See the comment at lru_cache.h about struct btrfs_lru_cache_entry. */
...@@ -2388,7 +2390,7 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx, ...@@ -2388,7 +2390,7 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx,
/* /*
* Store the result of the lookup in the name cache. * Store the result of the lookup in the name cache.
*/ */
nce = kmalloc(sizeof(*nce) + fs_path_len(dest) + 1, GFP_KERNEL); nce = kmalloc(sizeof(*nce) + fs_path_len(dest), GFP_KERNEL);
if (!nce) { if (!nce) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
...@@ -2400,7 +2402,7 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx, ...@@ -2400,7 +2402,7 @@ static int __get_cur_name_and_parent(struct send_ctx *sctx,
nce->parent_gen = *parent_gen; nce->parent_gen = *parent_gen;
nce->name_len = fs_path_len(dest); nce->name_len = fs_path_len(dest);
nce->ret = ret; nce->ret = ret;
strcpy(nce->name, dest->start); memcpy(nce->name, dest->start, nce->name_len);
if (ino < sctx->send_progress) if (ino < sctx->send_progress)
nce->need_later_update = 0; nce->need_later_update = 0;
...@@ -6187,8 +6189,29 @@ static int send_write_or_clone(struct send_ctx *sctx, ...@@ -6187,8 +6189,29 @@ static int send_write_or_clone(struct send_ctx *sctx,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (clone_root->offset + num_bytes == info.size) if (clone_root->offset + num_bytes == info.size) {
/*
* The final size of our file matches the end offset, but it may
* be that its current size is larger, so we have to truncate it
* to any value between the start offset of the range and the
* final i_size, otherwise the clone operation is invalid
* because it's unaligned and it ends before the current EOF.
* We do this truncate to the final i_size when we finish
* processing the inode, but it's too late by then. And here we
* truncate to the start offset of the range because it's always
* sector size aligned while if it were the final i_size it
* would result in dirtying part of a page, filling part of a
* page with zeroes and then having the clone operation at the
* receiver trigger IO and wait for it due to the dirty page.
*/
if (sctx->parent_root != NULL) {
ret = send_truncate(sctx, sctx->cur_ino,
sctx->cur_inode_gen, offset);
if (ret < 0)
return ret;
}
goto clone_data; goto clone_data;
}
write_data: write_data:
ret = send_extent_data(sctx, path, offset, num_bytes); ret = send_extent_data(sctx, path, offset, num_bytes);
......
...@@ -1716,7 +1716,7 @@ DECLARE_EVENT_CLASS(btrfs_qgroup_extent, ...@@ -1716,7 +1716,7 @@ DECLARE_EVENT_CLASS(btrfs_qgroup_extent,
), ),
TP_fast_assign_btrfs(fs_info, TP_fast_assign_btrfs(fs_info,
__entry->bytenr = rec->bytenr, __entry->bytenr = rec->bytenr;
__entry->num_bytes = rec->num_bytes; __entry->num_bytes = rec->num_bytes;
), ),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment