diff mbox series

[03/10] btrfs: drop __must_check annotations

Message ID 565b63e6e34c122ca9bbe1e0272f43d6327a6316.1694126893.git.dsterba@suse.com (mailing list archive)
State New, archived
Headers show
Series Cleanups and struct packing | expand

Commit Message

David Sterba Sept. 7, 2023, 11:09 p.m. UTC
Drop all __must_check annotations because they're used in random
functions and not consistently. All errors should be handled.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/extent-tree.h | 2 +-
 fs/btrfs/relocation.c  | 2 +-
 fs/btrfs/root-tree.h   | 6 ++----
 3 files changed, 4 insertions(+), 6 deletions(-)

Comments

Qu Wenruo Sept. 7, 2023, 11:56 p.m. UTC | #1
On 2023/9/8 07:09, David Sterba wrote:
> Drop all __must_check annotations because they're used in random
> functions and not consistently. All errors should be handled.

Is there any compiler warning option to warn about unchecked return value?

In fact recently when working on qgroup GFP_ATOMIC, I found a call site
that we didn't handle error at all (qgroup_update_counters()).

I'm pretty sure that is not the last one.

>
> Signed-off-by: David Sterba <dsterba@suse.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu
> ---
>   fs/btrfs/extent-tree.h | 2 +-
>   fs/btrfs/relocation.c  | 2 +-
>   fs/btrfs/root-tree.h   | 6 ++----
>   3 files changed, 4 insertions(+), 6 deletions(-)
>
> diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h
> index ab2016db17e8..2109c72aea2a 100644
> --- a/fs/btrfs/extent-tree.h
> +++ b/fs/btrfs/extent-tree.h
> @@ -142,7 +142,7 @@ int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info,
>   int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, u64 start, u64 len);
>   int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans);
>   int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, struct btrfs_ref *generic_ref);
> -int __must_check btrfs_drop_snapshot(struct btrfs_root *root, int update_ref,
> +int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref,
>   				     int for_reloc);
>   int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
>   			struct btrfs_root *root,
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index 9951a0caf5bb..ad67a88f2bbf 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -631,7 +631,7 @@ static int clone_backref_node(struct btrfs_trans_handle *trans,
>   /*
>    * helper to add 'address of tree root -> reloc tree' mapping
>    */
> -static int __must_check __add_reloc_root(struct btrfs_root *root)
> +static int __add_reloc_root(struct btrfs_root *root)
>   {
>   	struct btrfs_fs_info *fs_info = root->fs_info;
>   	struct rb_node *rb_node;
> diff --git a/fs/btrfs/root-tree.h b/fs/btrfs/root-tree.h
> index eb15768b9170..8b2c3859e464 100644
> --- a/fs/btrfs/root-tree.h
> +++ b/fs/btrfs/root-tree.h
> @@ -20,10 +20,8 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, const struct btrfs_key *key
>   int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
>   		      const struct btrfs_key *key,
>   		      struct btrfs_root_item *item);
> -int __must_check btrfs_update_root(struct btrfs_trans_handle *trans,
> -				   struct btrfs_root *root,
> -				   struct btrfs_key *key,
> -				   struct btrfs_root_item *item);
> +int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> +		      struct btrfs_key *key, struct btrfs_root_item *item);
>   int btrfs_find_root(struct btrfs_root *root, const struct btrfs_key *search_key,
>   		    struct btrfs_path *path, struct btrfs_root_item *root_item,
>   		    struct btrfs_key *root_key);
David Sterba Sept. 8, 2023, 12:34 a.m. UTC | #2
On Fri, Sep 08, 2023 at 07:56:24AM +0800, Qu Wenruo wrote:
> 
> 
> On 2023/9/8 07:09, David Sterba wrote:
> > Drop all __must_check annotations because they're used in random
> > functions and not consistently. All errors should be handled.
> 
> Is there any compiler warning option to warn about unchecked return value?

By default this is checked for functions annotated by warn_unused_result
attribute, which is exactly what __must_check does. The check can be
disabled but that's not what we want.

> In fact recently when working on qgroup GFP_ATOMIC, I found a call site
> that we didn't handle error at all (qgroup_update_counters()).

A quick way how to check if a given function is properly handled is to
add the __must_check attribute and run build. For qgroup_update_counters
this is found right away:

  CC [M]  fs/btrfs/qgroup.o
fs/btrfs/qgroup.c: In function ‘btrfs_qgroup_account_extent’:
fs/btrfs/qgroup.c:2736:9: warning: ignoring return value of ‘qgroup_update_counters’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 2736 |         qgroup_update_counters(fs_info, qgroups, nr_old_roots, nr_new_roots,
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2737 |                                num_bytes, seq);
      |                                ~~~~~~~~~~~~~~~

> I'm pretty sure that is not the last one.

Yeah but we'd have to add the attribute to most if not all functions. It
could be possibly automated using coccinnelle scripts, list functions,
apply a semantic patch to add the attribute, compile it and get the
results. A quick test shows it's doable.

I think in general the error handling is good but if we want to make
sure we haven't missed anything important we can't do it manually
efficiently.
David Sterba Sept. 8, 2023, 12:33 p.m. UTC | #3
On Fri, Sep 08, 2023 at 02:34:15AM +0200, David Sterba wrote:
> On Fri, Sep 08, 2023 at 07:56:24AM +0800, Qu Wenruo wrote:
> > 
> > 
> > On 2023/9/8 07:09, David Sterba wrote:
> > > Drop all __must_check annotations because they're used in random
> > > functions and not consistently. All errors should be handled.
> > 
> > Is there any compiler warning option to warn about unchecked return value?
> 
> By default this is checked for functions annotated by warn_unused_result
> attribute, which is exactly what __must_check does. The check can be
> disabled but that's not what we want.
> 
> > In fact recently when working on qgroup GFP_ATOMIC, I found a call site
> > that we didn't handle error at all (qgroup_update_counters()).
> 
> A quick way how to check if a given function is properly handled is to
> add the __must_check attribute and run build. For qgroup_update_counters
> this is found right away:
> 
>   CC [M]  fs/btrfs/qgroup.o
> fs/btrfs/qgroup.c: In function ‘btrfs_qgroup_account_extent’:
> fs/btrfs/qgroup.c:2736:9: warning: ignoring return value of ‘qgroup_update_counters’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
>  2736 |         qgroup_update_counters(fs_info, qgroups, nr_old_roots, nr_new_roots,
>       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>  2737 |                                num_bytes, seq);
>       |                                ~~~~~~~~~~~~~~~
> 
> > I'm pretty sure that is not the last one.
> 
> Yeah but we'd have to add the attribute to most if not all functions. It
> could be possibly automated using coccinnelle scripts, list functions,
> apply a semantic patch to add the attribute, compile it and get the
> results. A quick test shows it's doable.

We have 3179 functions, lots of them return void (but they might ignore
return values from called functions so it does not mean they're safe).
There are 65 Functions that don't have all their return values checked,
which 2%.

There are several that do the extent bit handling and we knowingly don't
handle the errors because all fatal erros lead to panic. The remaining
are a mixed bag, I tried to check a few randomly and it seems that the
error handling could lead to bad situations.

Ideally we should audit the whole list, and also maybe identify some key
functions that should have the __must_check attribute, e.g.
btrfs_commit_transaction (which is not in the list).

add_async_extent
add_delayed_ref_head
add_extent_mapping
add_ra_bio_pages
addrm_unknown_feature_attrs
btree_release_folio
__btrfs_add_free_space
btrfs_block_rsv_release
btrfs_cache_block_group
btrfs_cleanup_transaction
__btrfs_commit_inode_delayed_items
btrfs_del_item
btrfs_do_readpage
btrfs_end_transaction
btrfs_finish_ordered_io
btrfs_forget_devices
btrfs_free_reserved_extent
btrfs_free_stale_devices
btrfs_grab_root
btrfs_inode_lock
btrfs_log_inode_parent
btrfs_orphan_del
btrfs_pin_extent
btrfs_ref_tree_mod
__btrfs_release_folio
btrfs_release_folio
btrfs_repair_eb_io_failure
btrfs_reset_sb_log_zones
__btrfs_run_defrag_inode
btrfs_wait_block_group_cache_done
btrfs_wq_run_delayed_node
btrfs_zone_activate
cache_save_setup
clear_extent_bit
clear_extent_bits
clear_extent_dirty
clear_extent_uptodate
clear_state_bit
del_qgroup_rb
del_qgroup_relation_item
del_relation_rb
dev_extent_hole_check
do_zone_finish
fill_writer_pointer_gap
find_next_key
get_raid56_logic_offset
inc_block_group_ro
insert_root_entry
invalidate_extent_cache
link_free_space
load_block_group_size_class
maybe_fail_all_tickets
pin_down_extent
process_page_range
push_for_double_split
qgroup_unreserve_range
qgroup_update_counters
release_extent_buffer
remove_from_discard_list
tree_insert_offset
try_merge_free_space
unlock_extent
unpin_extent_range
update_backref_cache
__update_reloc_root
diff mbox series

Patch

diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h
index ab2016db17e8..2109c72aea2a 100644
--- a/fs/btrfs/extent-tree.h
+++ b/fs/btrfs/extent-tree.h
@@ -142,7 +142,7 @@  int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info,
 int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, u64 start, u64 len);
 int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans);
 int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, struct btrfs_ref *generic_ref);
-int __must_check btrfs_drop_snapshot(struct btrfs_root *root, int update_ref,
+int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref,
 				     int for_reloc);
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
 			struct btrfs_root *root,
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 9951a0caf5bb..ad67a88f2bbf 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -631,7 +631,7 @@  static int clone_backref_node(struct btrfs_trans_handle *trans,
 /*
  * helper to add 'address of tree root -> reloc tree' mapping
  */
-static int __must_check __add_reloc_root(struct btrfs_root *root)
+static int __add_reloc_root(struct btrfs_root *root)
 {
 	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct rb_node *rb_node;
diff --git a/fs/btrfs/root-tree.h b/fs/btrfs/root-tree.h
index eb15768b9170..8b2c3859e464 100644
--- a/fs/btrfs/root-tree.h
+++ b/fs/btrfs/root-tree.h
@@ -20,10 +20,8 @@  int btrfs_del_root(struct btrfs_trans_handle *trans, const struct btrfs_key *key
 int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		      const struct btrfs_key *key,
 		      struct btrfs_root_item *item);
-int __must_check btrfs_update_root(struct btrfs_trans_handle *trans,
-				   struct btrfs_root *root,
-				   struct btrfs_key *key,
-				   struct btrfs_root_item *item);
+int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		      struct btrfs_key *key, struct btrfs_root_item *item);
 int btrfs_find_root(struct btrfs_root *root, const struct btrfs_key *search_key,
 		    struct btrfs_path *path, struct btrfs_root_item *root_item,
 		    struct btrfs_key *root_key);