From f8f8e189512cc47da448bbf8ec8c39a2ab6e7515 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 3 Apr 2018 20:57:21 +0200 Subject: btrfs: tracepoints, use correct type for inode number The size of ino_t depends on 32/64bit architecture type. Btrfs stores the full 64bit inode anyway so we should use it. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- include/trace/events/btrfs.h | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 965c650a5273..dafd58ad86ec 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -133,7 +133,7 @@ DECLARE_EVENT_CLASS(btrfs__inode, TP_ARGS(inode), TP_STRUCT__entry_btrfs( - __field( ino_t, ino ) + __field( u64, ino ) __field( blkcnt_t, blocks ) __field( u64, disk_i_size ) __field( u64, generation ) @@ -143,7 +143,7 @@ DECLARE_EVENT_CLASS(btrfs__inode, ), TP_fast_assign_btrfs(btrfs_sb(inode->i_sb), - __entry->ino = inode->i_ino; + __entry->ino = btrfs_ino(BTRFS_I(inode)); __entry->blocks = inode->i_blocks; __entry->disk_i_size = BTRFS_I(inode)->disk_i_size; __entry->generation = BTRFS_I(inode)->generation; @@ -153,11 +153,11 @@ DECLARE_EVENT_CLASS(btrfs__inode, BTRFS_I(inode)->root->root_key.objectid; ), - TP_printk_btrfs("root=%llu(%s) gen=%llu ino=%lu blocks=%llu " + TP_printk_btrfs("root=%llu(%s) gen=%llu ino=%llu blocks=%llu " "disk_i_size=%llu last_trans=%llu logged_trans=%llu", show_root_type(__entry->root_objectid), (unsigned long long)__entry->generation, - (unsigned long)__entry->ino, + (unsigned long long)__entry->ino, (unsigned long long)__entry->blocks, (unsigned long long)__entry->disk_i_size, (unsigned long long)__entry->last_trans, @@ -443,7 +443,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent, TP_ARGS(inode, ordered), TP_STRUCT__entry_btrfs( - __field( ino_t, ino ) + __field( u64, ino ) __field( u64, file_offset ) __field( u64, start ) __field( u64, len ) @@ -457,7 +457,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent, ), TP_fast_assign_btrfs(btrfs_sb(inode->i_sb), - __entry->ino = inode->i_ino; + __entry->ino = btrfs_ino(BTRFS_I(inode)); __entry->file_offset = ordered->file_offset; __entry->start = ordered->start; __entry->len = ordered->len; @@ -528,7 +528,7 @@ DECLARE_EVENT_CLASS(btrfs__writepage, TP_ARGS(page, inode, wbc), TP_STRUCT__entry_btrfs( - __field( ino_t, ino ) + __field( u64, ino ) __field( pgoff_t, index ) __field( long, nr_to_write ) __field( long, pages_skipped ) @@ -542,7 +542,7 @@ DECLARE_EVENT_CLASS(btrfs__writepage, ), TP_fast_assign_btrfs(btrfs_sb(inode->i_sb), - __entry->ino = inode->i_ino; + __entry->ino = btrfs_ino(BTRFS_I(inode)); __entry->index = page->index; __entry->nr_to_write = wbc->nr_to_write; __entry->pages_skipped = wbc->pages_skipped; @@ -556,12 +556,12 @@ DECLARE_EVENT_CLASS(btrfs__writepage, BTRFS_I(inode)->root->root_key.objectid; ), - TP_printk_btrfs("root=%llu(%s) ino=%lu page_index=%lu " + TP_printk_btrfs("root=%llu(%s) ino=%llu page_index=%lu " "nr_to_write=%ld pages_skipped=%ld range_start=%llu " "range_end=%llu for_kupdate=%d " "for_reclaim=%d range_cyclic=%d writeback_index=%lu", show_root_type(__entry->root_objectid), - (unsigned long)__entry->ino, __entry->index, + (unsigned long long)__entry->ino, __entry->index, __entry->nr_to_write, __entry->pages_skipped, __entry->range_start, __entry->range_end, __entry->for_kupdate, @@ -584,7 +584,7 @@ TRACE_EVENT(btrfs_writepage_end_io_hook, TP_ARGS(page, start, end, uptodate), TP_STRUCT__entry_btrfs( - __field( ino_t, ino ) + __field( u64, ino ) __field( pgoff_t, index ) __field( u64, start ) __field( u64, end ) @@ -593,7 +593,7 @@ TRACE_EVENT(btrfs_writepage_end_io_hook, ), TP_fast_assign_btrfs(btrfs_sb(page->mapping->host->i_sb), - __entry->ino = page->mapping->host->i_ino; + __entry->ino = btrfs_ino(BTRFS_I(page->mapping->host)); __entry->index = page->index; __entry->start = start; __entry->end = end; @@ -602,10 +602,10 @@ TRACE_EVENT(btrfs_writepage_end_io_hook, BTRFS_I(page->mapping->host)->root->root_key.objectid; ), - TP_printk_btrfs("root=%llu(%s) ino=%lu page_index=%lu start=%llu " + TP_printk_btrfs("root=%llu(%s) ino=%llu page_index=%lu start=%llu " "end=%llu uptodate=%d", show_root_type(__entry->root_objectid), - (unsigned long)__entry->ino, (unsigned long)__entry->index, + (unsigned long long)__entry->ino, (unsigned long)__entry->index, (unsigned long long)__entry->start, (unsigned long long)__entry->end, __entry->uptodate) ); @@ -617,8 +617,8 @@ TRACE_EVENT(btrfs_sync_file, TP_ARGS(file, datasync), TP_STRUCT__entry_btrfs( - __field( ino_t, ino ) - __field( ino_t, parent ) + __field( u64, ino ) + __field( u64, parent ) __field( int, datasync ) __field( u64, root_objectid ) ), @@ -628,16 +628,17 @@ TRACE_EVENT(btrfs_sync_file, const struct inode *inode = d_inode(dentry); TP_fast_assign_fsid(btrfs_sb(file->f_path.dentry->d_sb)); - __entry->ino = inode->i_ino; - __entry->parent = d_inode(dentry->d_parent)->i_ino; + __entry->ino = btrfs_ino(BTRFS_I(inode)); + __entry->parent = btrfs_ino(BTRFS_I(d_inode(dentry->d_parent))); __entry->datasync = datasync; __entry->root_objectid = BTRFS_I(inode)->root->root_key.objectid; ), - TP_printk_btrfs("root=%llu(%s) ino=%ld parent=%ld datasync=%d", + TP_printk_btrfs("root=%llu(%s) ino=%llu parent=%llu datasync=%d", show_root_type(__entry->root_objectid), - (unsigned long)__entry->ino, (unsigned long)__entry->parent, + (unsigned long long)__entry->ino, + (unsigned long long)__entry->parent, __entry->datasync) ); @@ -1476,7 +1477,7 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data, TP_STRUCT__entry_btrfs( __field( u64, rootid ) - __field( unsigned long, ino ) + __field( u64, ino ) __field( u64, start ) __field( u64, len ) __field( u64, reserved ) @@ -1485,14 +1486,14 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data, TP_fast_assign_btrfs(btrfs_sb(inode->i_sb), __entry->rootid = BTRFS_I(inode)->root->objectid; - __entry->ino = inode->i_ino; + __entry->ino = btrfs_ino(BTRFS_I(inode)); __entry->start = start; __entry->len = len; __entry->reserved = reserved; __entry->op = op; ), - TP_printk_btrfs("root=%llu ino=%lu start=%llu len=%llu reserved=%llu op=%s", + TP_printk_btrfs("root=%llu ino=%llu start=%llu len=%llu reserved=%llu op=%s", __entry->rootid, __entry->ino, __entry->start, __entry->len, __entry->reserved, __print_flags((unsigned long)__entry->op, "", -- cgit v1.2.3 From 5439c7f54c008ad727aa45a24bd8518da248f8b7 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 3 Apr 2018 21:05:37 +0200 Subject: btrfs: tracepoints, use %llu instead of %Lu For consistency, use the %llu form. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- include/trace/events/btrfs.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index dafd58ad86ec..200c45911919 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -1002,7 +1002,7 @@ TRACE_EVENT(btrfs_space_reservation, __entry->reserve = reserve; ), - TP_printk_btrfs("%s: %Lu %s %Lu", __get_str(type), __entry->val, + TP_printk_btrfs("%s: %llu %s %llu", __get_str(type), __entry->val, __entry->reserve ? "reserve" : "release", __entry->bytes) ); @@ -1141,7 +1141,7 @@ TRACE_EVENT(find_free_extent, __entry->data = data; ), - TP_printk_btrfs("root=%Lu(%s) len=%Lu empty_size=%Lu flags=%Lu(%s)", + TP_printk_btrfs("root=%llu(%s) len=%llu empty_size=%llu flags=%llu(%s)", show_root_type(BTRFS_EXTENT_TREE_OBJECTID), __entry->num_bytes, __entry->empty_size, __entry->data, __print_flags((unsigned long)__entry->data, "|", @@ -1170,8 +1170,8 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent, __entry->len = len; ), - TP_printk_btrfs("root=%Lu(%s) block_group=%Lu flags=%Lu(%s) " - "start=%Lu len=%Lu", + TP_printk_btrfs("root=%llu(%s) block_group=%llu flags=%llu(%s) " + "start=%llu len=%llu", show_root_type(BTRFS_EXTENT_TREE_OBJECTID), __entry->bg_objectid, __entry->flags, __print_flags((unsigned long)__entry->flags, @@ -1222,8 +1222,8 @@ TRACE_EVENT(btrfs_find_cluster, __entry->min_bytes = min_bytes; ), - TP_printk_btrfs("block_group=%Lu flags=%Lu(%s) start=%Lu len=%Lu " - "empty_size=%Lu min_bytes=%Lu", __entry->bg_objectid, + TP_printk_btrfs("block_group=%llu flags=%llu(%s) start=%llu len=%llu " + "empty_size=%llu min_bytes=%llu", __entry->bg_objectid, __entry->flags, __print_flags((unsigned long)__entry->flags, "|", BTRFS_GROUP_FLAGS), __entry->start, @@ -1244,7 +1244,7 @@ TRACE_EVENT(btrfs_failed_cluster_setup, __entry->bg_objectid = block_group->key.objectid; ), - TP_printk_btrfs("block_group=%Lu", __entry->bg_objectid) + TP_printk_btrfs("block_group=%llu", __entry->bg_objectid) ); TRACE_EVENT(btrfs_setup_cluster, @@ -1273,8 +1273,8 @@ TRACE_EVENT(btrfs_setup_cluster, __entry->bitmap = bitmap; ), - TP_printk_btrfs("block_group=%Lu flags=%Lu(%s) window_start=%Lu " - "size=%Lu max_size=%Lu bitmap=%d", + TP_printk_btrfs("block_group=%llu flags=%llu(%s) window_start=%llu " + "size=%llu max_size=%llu bitmap=%d", __entry->bg_objectid, __entry->flags, __print_flags((unsigned long)__entry->flags, "|", -- cgit v1.2.3 From 8eec8463085271585c41ab9ec6b30e8ff4bc0b83 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 3 Apr 2018 21:15:11 +0200 Subject: btrfs: tracepoints, drop unnecessary ULL casts The (unsigned long long) casts are not necessary since long ago. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- include/trace/events/btrfs.h | 124 +++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 62 deletions(-) (limited to 'include') diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 200c45911919..06e8b8bdfb42 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -123,7 +123,7 @@ TRACE_EVENT(btrfs_transaction_commit, TP_printk_btrfs("root = %llu(%s), gen = %llu", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->generation) + __entry->generation) ); DECLARE_EVENT_CLASS(btrfs__inode, @@ -156,12 +156,12 @@ DECLARE_EVENT_CLASS(btrfs__inode, TP_printk_btrfs("root=%llu(%s) gen=%llu ino=%llu blocks=%llu " "disk_i_size=%llu last_trans=%llu logged_trans=%llu", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->generation, - (unsigned long long)__entry->ino, + __entry->generation, + __entry->ino, (unsigned long long)__entry->blocks, - (unsigned long long)__entry->disk_i_size, - (unsigned long long)__entry->last_trans, - (unsigned long long)__entry->logged_trans) + __entry->disk_i_size, + __entry->last_trans, + __entry->logged_trans) ); DEFINE_EVENT(btrfs__inode, btrfs_inode_new, @@ -244,12 +244,12 @@ TRACE_EVENT_CONDITION(btrfs_get_extent, "block_len=%llu flags=%s refs=%u " "compress_type=%u", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->ino, - (unsigned long long)__entry->start, - (unsigned long long)__entry->len, - (unsigned long long)__entry->orig_start, + __entry->ino, + __entry->start, + __entry->len, + __entry->orig_start, show_map_type(__entry->block_start), - (unsigned long long)__entry->block_len, + __entry->block_len, show_map_flags(__entry->flags), __entry->refs, __entry->compress_type) ); @@ -281,12 +281,12 @@ TRACE_EVENT(btrfs_handle_em_exist, TP_printk("start=%llu len=%llu " "existing(start=%llu len=%llu) " "em(start=%llu len=%llu)", - (unsigned long long)__entry->start, - (unsigned long long)__entry->len, - (unsigned long long)__entry->e_start, - (unsigned long long)__entry->e_len, - (unsigned long long)__entry->map_start, - (unsigned long long)__entry->map_len) + __entry->start, + __entry->len, + __entry->e_start, + __entry->e_len, + __entry->map_start, + __entry->map_len) ); /* file extent item */ @@ -477,13 +477,13 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent, "bytes_left=%llu flags=%s compress_type=%d " "refs=%d", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->ino, - (unsigned long long)__entry->file_offset, - (unsigned long long)__entry->start, - (unsigned long long)__entry->len, - (unsigned long long)__entry->disk_len, - (unsigned long long)__entry->truncated_len, - (unsigned long long)__entry->bytes_left, + __entry->ino, + __entry->file_offset, + __entry->start, + __entry->len, + __entry->disk_len, + __entry->truncated_len, + __entry->bytes_left, show_ordered_flags(__entry->flags), __entry->compress_type, __entry->refs) ); @@ -561,7 +561,7 @@ DECLARE_EVENT_CLASS(btrfs__writepage, "range_end=%llu for_kupdate=%d " "for_reclaim=%d range_cyclic=%d writeback_index=%lu", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->ino, __entry->index, + __entry->ino, __entry->index, __entry->nr_to_write, __entry->pages_skipped, __entry->range_start, __entry->range_end, __entry->for_kupdate, @@ -605,9 +605,9 @@ TRACE_EVENT(btrfs_writepage_end_io_hook, TP_printk_btrfs("root=%llu(%s) ino=%llu page_index=%lu start=%llu " "end=%llu uptodate=%d", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->ino, (unsigned long)__entry->index, - (unsigned long long)__entry->start, - (unsigned long long)__entry->end, __entry->uptodate) + __entry->ino, (unsigned long)__entry->index, + __entry->start, + __entry->end, __entry->uptodate) ); TRACE_EVENT(btrfs_sync_file, @@ -637,8 +637,8 @@ TRACE_EVENT(btrfs_sync_file, TP_printk_btrfs("root=%llu(%s) ino=%llu parent=%llu datasync=%d", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->ino, - (unsigned long long)__entry->parent, + __entry->ino, + __entry->parent, __entry->datasync) ); @@ -690,13 +690,13 @@ TRACE_EVENT(btrfs_add_block_group, TP_printk("%pU: block_group offset=%llu size=%llu " "flags=%llu(%s) bytes_used=%llu bytes_super=%llu " "create=%d", __entry->fsid, - (unsigned long long)__entry->offset, - (unsigned long long)__entry->size, - (unsigned long long)__entry->flags, + __entry->offset, + __entry->size, + __entry->flags, __print_flags((unsigned long)__entry->flags, "|", BTRFS_GROUP_FLAGS), - (unsigned long long)__entry->bytes_used, - (unsigned long long)__entry->bytes_super, __entry->create) + __entry->bytes_used, + __entry->bytes_super, __entry->create) ); #define show_ref_action(action) \ @@ -741,13 +741,13 @@ DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref, TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s " "parent=%llu(%s) ref_root=%llu(%s) level=%d " "type=%s seq=%llu", - (unsigned long long)__entry->bytenr, - (unsigned long long)__entry->num_bytes, + __entry->bytenr, + __entry->num_bytes, show_ref_action(__entry->action), show_root_type(__entry->parent), show_root_type(__entry->ref_root), __entry->level, show_ref_type(__entry->type), - (unsigned long long)__entry->seq) + __entry->seq) ); DEFINE_EVENT(btrfs_delayed_tree_ref, add_delayed_tree_ref, @@ -806,15 +806,15 @@ DECLARE_EVENT_CLASS(btrfs_delayed_data_ref, TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s " "parent=%llu(%s) ref_root=%llu(%s) owner=%llu " "offset=%llu type=%s seq=%llu", - (unsigned long long)__entry->bytenr, - (unsigned long long)__entry->num_bytes, + __entry->bytenr, + __entry->num_bytes, show_ref_action(__entry->action), show_root_type(__entry->parent), show_root_type(__entry->ref_root), - (unsigned long long)__entry->owner, - (unsigned long long)__entry->offset, + __entry->owner, + __entry->offset, show_ref_type(__entry->type), - (unsigned long long)__entry->seq) + __entry->seq) ); DEFINE_EVENT(btrfs_delayed_data_ref, add_delayed_data_ref, @@ -860,8 +860,8 @@ DECLARE_EVENT_CLASS(btrfs_delayed_ref_head, ), TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s is_data=%d", - (unsigned long long)__entry->bytenr, - (unsigned long long)__entry->num_bytes, + __entry->bytenr, + __entry->num_bytes, show_ref_action(__entry->action), __entry->is_data) ); @@ -924,8 +924,8 @@ DECLARE_EVENT_CLASS(btrfs__chunk, TP_printk_btrfs("root=%llu(%s) offset=%llu size=%llu " "num_stripes=%d sub_stripes=%d type=%s", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->offset, - (unsigned long long)__entry->size, + __entry->offset, + __entry->size, __entry->num_stripes, __entry->sub_stripes, show_chunk_type(__entry->type)) ); @@ -975,9 +975,9 @@ TRACE_EVENT(btrfs_cow_block, "(orig_level=%d) cow_buf=%llu (cow_level=%d)", show_root_type(__entry->root_objectid), __entry->refs, - (unsigned long long)__entry->buf_start, + __entry->buf_start, __entry->buf_level, - (unsigned long long)__entry->cow_start, + __entry->cow_start, __entry->cow_level) ); @@ -1039,10 +1039,10 @@ TRACE_EVENT(btrfs_trigger_flush, TP_printk("%pU: %s: flush=%d(%s) flags=%llu(%s) bytes=%llu", __entry->fsid, __get_str(reason), __entry->flush, show_flush_action(__entry->flush), - (unsigned long long)__entry->flags, + __entry->flags, __print_flags((unsigned long)__entry->flags, "|", BTRFS_GROUP_FLAGS), - (unsigned long long)__entry->bytes) + __entry->bytes) ); #define show_flush_state(state) \ @@ -1080,10 +1080,10 @@ TRACE_EVENT(btrfs_flush_space, TP_printk("%pU: state=%d(%s) flags=%llu(%s) num_bytes=%llu ret=%d", __entry->fsid, __entry->state, show_flush_state(__entry->state), - (unsigned long long)__entry->flags, + __entry->flags, __print_flags((unsigned long)__entry->flags, "|", BTRFS_GROUP_FLAGS), - (unsigned long long)__entry->num_bytes, __entry->ret) + __entry->num_bytes, __entry->ret) ); DECLARE_EVENT_CLASS(btrfs__reserved_extent, @@ -1104,8 +1104,8 @@ DECLARE_EVENT_CLASS(btrfs__reserved_extent, TP_printk_btrfs("root=%llu(%s) start=%llu len=%llu", show_root_type(BTRFS_EXTENT_TREE_OBJECTID), - (unsigned long long)__entry->start, - (unsigned long long)__entry->len) + __entry->start, + __entry->len) ); DEFINE_EVENT(btrfs__reserved_extent, btrfs_reserved_extent_alloc, @@ -1766,14 +1766,14 @@ DECLARE_EVENT_CLASS(btrfs__prelim_ref, ), TP_printk_btrfs("root_id=%llu key=[%llu,%u,%llu] level=%d count=[%d+%d=%d] parent=%llu wanted_disk_byte=%llu nodes=%llu", - (unsigned long long)__entry->root_id, - (unsigned long long)__entry->objectid, __entry->type, - (unsigned long long)__entry->offset, __entry->level, + __entry->root_id, + __entry->objectid, __entry->type, + __entry->offset, __entry->level, __entry->old_count, __entry->mod_count, __entry->old_count + __entry->mod_count, - (unsigned long long)__entry->parent, - (unsigned long long)__entry->bytenr, - (unsigned long long)__entry->tree_size) + __entry->parent, + __entry->bytenr, + __entry->tree_size) ); DEFINE_EVENT(btrfs__prelim_ref, btrfs_prelim_ref_merge, @@ -1809,7 +1809,7 @@ TRACE_EVENT(btrfs_inode_mod_outstanding_extents, TP_printk_btrfs("root=%llu(%s) ino=%llu mod=%d", show_root_type(__entry->root_objectid), - (unsigned long long)__entry->ino, __entry->mod) + __entry->ino, __entry->mod) ); #endif /* _TRACE_BTRFS_H */ -- cgit v1.2.3 From 79bcb71a5b3adf84ec9d671ce9f0662ae5b1d0e3 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 3 Apr 2018 21:21:17 +0200 Subject: btrfs: tracepoints, fix whitespace in strings The preferred style is to avoid spaces between key and value and no commas between key=values. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- include/trace/events/btrfs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 06e8b8bdfb42..1773355e9365 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -121,7 +121,7 @@ TRACE_EVENT(btrfs_transaction_commit, __entry->root_objectid = root->root_key.objectid; ), - TP_printk_btrfs("root = %llu(%s), gen = %llu", + TP_printk_btrfs("root=%llu(%s) gen=%llu", show_root_type(__entry->root_objectid), __entry->generation) ); @@ -656,7 +656,7 @@ TRACE_EVENT(btrfs_sync_fs, __entry->wait = wait; ), - TP_printk_btrfs("wait = %d", __entry->wait) + TP_printk_btrfs("wait=%d", __entry->wait) ); TRACE_EVENT(btrfs_add_block_group, -- cgit v1.2.3 From 2e63e62d981dcaa822d3a845935b009b2543b3f2 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 3 Apr 2018 21:34:06 +0200 Subject: btrfs: tracepoints, use extended format with UUID where possible Most of the strings are prefixed by the UUID of the filesystem that generates the message, however there are a few events that still opencode the macro magic and can be converted to the common macros. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- include/trace/events/btrfs.h | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 1773355e9365..9be469706d30 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -666,8 +666,7 @@ TRACE_EVENT(btrfs_add_block_group, TP_ARGS(fs_info, block_group, create), - TP_STRUCT__entry( - __array( u8, fsid, BTRFS_FSID_SIZE ) + TP_STRUCT__entry_btrfs( __field( u64, offset ) __field( u64, size ) __field( u64, flags ) @@ -676,8 +675,7 @@ TRACE_EVENT(btrfs_add_block_group, __field( int, create ) ), - TP_fast_assign( - memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE); + TP_fast_assign_btrfs(fs_info, __entry->offset = block_group->key.objectid; __entry->size = block_group->key.offset; __entry->flags = block_group->flags; @@ -687,9 +685,9 @@ TRACE_EVENT(btrfs_add_block_group, __entry->create = create; ), - TP_printk("%pU: block_group offset=%llu size=%llu " + TP_printk_btrfs("block_group offset=%llu size=%llu " "flags=%llu(%s) bytes_used=%llu bytes_super=%llu " - "create=%d", __entry->fsid, + "create=%d", __entry->offset, __entry->size, __entry->flags, @@ -1020,24 +1018,22 @@ TRACE_EVENT(btrfs_trigger_flush, TP_ARGS(fs_info, flags, bytes, flush, reason), - TP_STRUCT__entry( - __array( u8, fsid, BTRFS_FSID_SIZE ) + TP_STRUCT__entry_btrfs( __field( u64, flags ) __field( u64, bytes ) __field( int, flush ) __string( reason, reason ) ), - TP_fast_assign( - memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE); + TP_fast_assign_btrfs(fs_info, __entry->flags = flags; __entry->bytes = bytes; __entry->flush = flush; __assign_str(reason, reason) ), - TP_printk("%pU: %s: flush=%d(%s) flags=%llu(%s) bytes=%llu", - __entry->fsid, __get_str(reason), __entry->flush, + TP_printk_btrfs("%s: flush=%d(%s) flags=%llu(%s) bytes=%llu", + __get_str(reason), __entry->flush, show_flush_action(__entry->flush), __entry->flags, __print_flags((unsigned long)__entry->flags, "|", @@ -1061,24 +1057,22 @@ TRACE_EVENT(btrfs_flush_space, TP_ARGS(fs_info, flags, num_bytes, state, ret), - TP_STRUCT__entry( - __array( u8, fsid, BTRFS_FSID_SIZE ) + TP_STRUCT__entry_btrfs( __field( u64, flags ) __field( u64, num_bytes ) __field( int, state ) __field( int, ret ) ), - TP_fast_assign( - memcpy(__entry->fsid, fs_info->fsid, BTRFS_FSID_SIZE); + TP_fast_assign_btrfs(fs_info, __entry->flags = flags; __entry->num_bytes = num_bytes; __entry->state = state; __entry->ret = ret; ), - TP_printk("%pU: state=%d(%s) flags=%llu(%s) num_bytes=%llu ret=%d", - __entry->fsid, __entry->state, + TP_printk_btrfs("state=%d(%s) flags=%llu(%s) num_bytes=%llu ret=%d", + __entry->state, show_flush_state(__entry->state), __entry->flags, __print_flags((unsigned long)__entry->flags, "|", -- cgit v1.2.3 From f46b24c9457143a367c6707eac82d546e2bcf280 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 3 Apr 2018 21:45:57 +0200 Subject: btrfs: use fs_info for btrfs_handle_em_exist tracepoint We really want to know to which filesystem the extent map events belong, but as it cannot be reached from the extent_map pointers, we need to pass it down the callchain. Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/extent_map.c | 6 ++++-- fs/btrfs/extent_map.h | 3 ++- fs/btrfs/inode.c | 2 +- fs/btrfs/tests/extent-map-tests.c | 8 ++++---- include/trace/events/btrfs.h | 12 +++++++----- 5 files changed, 18 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 1b8a078f92eb..6648d55e5339 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -518,6 +518,7 @@ static noinline int merge_extent_mapping(struct extent_map_tree *em_tree, /** * btrfs_add_extent_mapping - add extent mapping into em_tree + * @fs_info - used for tracepoint * @em_tree - the extent tree into which we want to insert the extent mapping * @em_in - extent we are inserting * @start - start of the logical range btrfs_get_extent() is requesting @@ -535,7 +536,8 @@ static noinline int merge_extent_mapping(struct extent_map_tree *em_tree, * Return 0 on success, otherwise -EEXIST. * */ -int btrfs_add_extent_mapping(struct extent_map_tree *em_tree, +int btrfs_add_extent_mapping(struct btrfs_fs_info *fs_info, + struct extent_map_tree *em_tree, struct extent_map **em_in, u64 start, u64 len) { int ret; @@ -553,7 +555,7 @@ int btrfs_add_extent_mapping(struct extent_map_tree *em_tree, existing = search_extent_mapping(em_tree, start, len); - trace_btrfs_handle_em_exist(existing, em, start, len); + trace_btrfs_handle_em_exist(fs_info, existing, em, start, len); /* * existing will always be non-NULL, since there must be diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index 5fcb80a6ce37..25d985e7532a 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h @@ -92,7 +92,8 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em); struct extent_map *search_extent_mapping(struct extent_map_tree *tree, u64 start, u64 len); -int btrfs_add_extent_mapping(struct extent_map_tree *em_tree, +int btrfs_add_extent_mapping(struct btrfs_fs_info *fs_info, + struct extent_map_tree *em_tree, struct extent_map **em_in, u64 start, u64 len); #endif diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index be17cfdcbcf5..f4447986263a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7083,7 +7083,7 @@ insert: err = 0; write_lock(&em_tree->lock); - err = btrfs_add_extent_mapping(em_tree, &em, start, len); + err = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); write_unlock(&em_tree->lock); out: diff --git a/fs/btrfs/tests/extent-map-tests.c b/fs/btrfs/tests/extent-map-tests.c index 8a39de4453e4..9c051c4a3315 100644 --- a/fs/btrfs/tests/extent-map-tests.c +++ b/fs/btrfs/tests/extent-map-tests.c @@ -91,7 +91,7 @@ static void test_case_1(struct btrfs_fs_info *fs_info, em->len = len; em->block_start = start; em->block_len = len; - ret = btrfs_add_extent_mapping(em_tree, &em, em->start, em->len); + ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len); if (ret) test_msg("case1 [%llu %llu]: ret %d\n", start, start + len, ret); if (em && @@ -155,7 +155,7 @@ static void test_case_2(struct btrfs_fs_info *fs_info, em->len = SZ_1K; em->block_start = EXTENT_MAP_INLINE; em->block_len = (u64)-1; - ret = btrfs_add_extent_mapping(em_tree, &em, em->start, em->len); + ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, em->start, em->len); if (ret) test_msg("case2 [0 1K]: ret %d\n", ret); if (em && @@ -201,7 +201,7 @@ static void __test_case_3(struct btrfs_fs_info *fs_info, em->len = SZ_16K; em->block_start = 0; em->block_len = SZ_16K; - ret = btrfs_add_extent_mapping(em_tree, &em, start, len); + ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); if (ret) test_msg("case3 [0x%llx 0x%llx): ret %d\n", start, start + len, ret); @@ -288,7 +288,7 @@ static void __test_case_4(struct btrfs_fs_info *fs_info, em->len = SZ_32K; em->block_start = 0; em->block_len = SZ_32K; - ret = btrfs_add_extent_mapping(em_tree, &em, start, len); + ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); if (ret) test_msg("case4 [0x%llx 0x%llx): ret %d\n", start, len, ret); diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 9be469706d30..d78d8ab4bc86 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -256,11 +256,13 @@ TRACE_EVENT_CONDITION(btrfs_get_extent, TRACE_EVENT(btrfs_handle_em_exist, - TP_PROTO(const struct extent_map *existing, const struct extent_map *map, u64 start, u64 len), + TP_PROTO(struct btrfs_fs_info *fs_info, + const struct extent_map *existing, const struct extent_map *map, + u64 start, u64 len), - TP_ARGS(existing, map, start, len), + TP_ARGS(fs_info, existing, map, start, len), - TP_STRUCT__entry( + TP_STRUCT__entry_btrfs( __field( u64, e_start ) __field( u64, e_len ) __field( u64, map_start ) @@ -269,7 +271,7 @@ TRACE_EVENT(btrfs_handle_em_exist, __field( u64, len ) ), - TP_fast_assign( + TP_fast_assign_btrfs(fs_info, __entry->e_start = existing->start; __entry->e_len = existing->len; __entry->map_start = map->start; @@ -278,7 +280,7 @@ TRACE_EVENT(btrfs_handle_em_exist, __entry->len = len; ), - TP_printk("start=%llu len=%llu " + TP_printk_btrfs("start=%llu len=%llu " "existing(start=%llu len=%llu) " "em(start=%llu len=%llu)", __entry->start, -- cgit v1.2.3 From 3dca5c942dac60164e6a6e89172f25b86af07ce7 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Thu, 26 Apr 2018 14:24:25 +0800 Subject: btrfs: trace: Remove unnecessary fs_info parameter for btrfs__reserve_extent event class fs_info can be extracted from btrfs_block_group_cache, and all btrfs_block_group_cache is created by btrfs_create_block_group_cache() with fs_info initialized, no need to worry about NULL pointer dereference. Signed-off-by: Qu Wenruo Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 7 +++---- include/trace/events/btrfs.h | 18 ++++++++---------- 2 files changed, 11 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fdd6ac9ee2c6..295f8298fd9e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7651,7 +7651,7 @@ have_block_group: if (offset) { /* we have a block, we're done */ spin_unlock(&last_ptr->refill_lock); - trace_btrfs_reserve_extent_cluster(fs_info, + trace_btrfs_reserve_extent_cluster( used_block_group, search_start, num_bytes); if (used_block_group != block_group) { @@ -7724,7 +7724,7 @@ refill_cluster: if (offset) { /* we found one, proceed */ spin_unlock(&last_ptr->refill_lock); - trace_btrfs_reserve_extent_cluster(fs_info, + trace_btrfs_reserve_extent_cluster( block_group, search_start, num_bytes); goto checks; @@ -7824,8 +7824,7 @@ checks: ins->objectid = search_start; ins->offset = num_bytes; - trace_btrfs_reserve_extent(fs_info, block_group, - search_start, num_bytes); + trace_btrfs_reserve_extent(block_group, search_start, num_bytes); btrfs_release_block_group(block_group, delalloc); break; loop: diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index d78d8ab4bc86..5af2479e9b16 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -1146,11 +1146,10 @@ TRACE_EVENT(find_free_extent, DECLARE_EVENT_CLASS(btrfs__reserve_extent, - TP_PROTO(const struct btrfs_fs_info *fs_info, - const struct btrfs_block_group_cache *block_group, u64 start, + TP_PROTO(const struct btrfs_block_group_cache *block_group, u64 start, u64 len), - TP_ARGS(fs_info, block_group, start, len), + TP_ARGS(block_group, start, len), TP_STRUCT__entry_btrfs( __field( u64, bg_objectid ) @@ -1159,7 +1158,7 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent, __field( u64, len ) ), - TP_fast_assign_btrfs(fs_info, + TP_fast_assign_btrfs(block_group->fs_info, __entry->bg_objectid = block_group->key.objectid; __entry->flags = block_group->flags; __entry->start = start; @@ -1177,20 +1176,18 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent, DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent, - TP_PROTO(const struct btrfs_fs_info *fs_info, - const struct btrfs_block_group_cache *block_group, u64 start, + TP_PROTO(const struct btrfs_block_group_cache *block_group, u64 start, u64 len), - TP_ARGS(fs_info, block_group, start, len) + TP_ARGS(block_group, start, len) ); DEFINE_EVENT(btrfs__reserve_extent, btrfs_reserve_extent_cluster, - TP_PROTO(const struct btrfs_fs_info *fs_info, - const struct btrfs_block_group_cache *block_group, u64 start, + TP_PROTO(const struct btrfs_block_group_cache *block_group, u64 start, u64 len), - TP_ARGS(fs_info, block_group, start, len) + TP_ARGS(block_group, start, len) ); TRACE_EVENT(btrfs_find_cluster, @@ -1807,6 +1804,7 @@ TRACE_EVENT(btrfs_inode_mod_outstanding_extents, show_root_type(__entry->root_objectid), __entry->ino, __entry->mod) ); + #endif /* _TRACE_BTRFS_H */ /* This part must be outside protection */ -- cgit v1.2.3 From 4ed0a7a3b7c3f8387caf2ad57424d9341f523856 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Thu, 26 Apr 2018 17:17:20 +0800 Subject: btrfs: trace: Add trace points for unused block groups This patch will add the following trace events: 1) btrfs_remove_block_group For btrfs_remove_block_group() function. Triggered when a block group is really removed. 2) btrfs_add_unused_block_group Triggered which block group is added to unused_bgs list. 3) btrfs_skip_unused_block_group Triggered which unused block group is not deleted. These trace events is pretty handy to debug case related to block group auto remove. Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 4 ++++ fs/btrfs/scrub.c | 1 + include/trace/events/btrfs.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) (limited to 'include') diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 295f8298fd9e..888a47894c30 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -6358,6 +6358,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, spin_lock(&info->unused_bgs_lock); if (list_empty(&cache->bg_list)) { btrfs_get_block_group(cache); + trace_btrfs_add_unused_block_group(cache); list_add_tail(&cache->bg_list, &info->unused_bgs); } @@ -10192,6 +10193,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info) /* Should always be true but just in case. */ if (list_empty(&cache->bg_list)) { btrfs_get_block_group(cache); + trace_btrfs_add_unused_block_group(cache); list_add_tail(&cache->bg_list, &info->unused_bgs); } @@ -10379,6 +10381,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, BUG_ON(!block_group); BUG_ON(!block_group->ro); + trace_btrfs_remove_block_group(block_group); /* * Free the reserved super bytes from this block group before * remove it. @@ -10743,6 +10746,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) * the ro check in case balance is currently acting on * this block group. */ + trace_btrfs_skip_unused_block_group(block_group); spin_unlock(&block_group->lock); up_write(&space_info->groups_sem); goto next; diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 52b39a0924e9..a59005862010 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -3984,6 +3984,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx, spin_lock(&fs_info->unused_bgs_lock); if (list_empty(&cache->bg_list)) { btrfs_get_block_group(cache); + trace_btrfs_add_unused_block_group(cache); list_add_tail(&cache->bg_list, &fs_info->unused_bgs); } diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 5af2479e9b16..914ddb7a6d25 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -1805,6 +1805,48 @@ TRACE_EVENT(btrfs_inode_mod_outstanding_extents, __entry->ino, __entry->mod) ); +DECLARE_EVENT_CLASS(btrfs__block_group, + TP_PROTO(const struct btrfs_block_group_cache *bg_cache), + + TP_ARGS(bg_cache), + + TP_STRUCT__entry_btrfs( + __field( u64, bytenr ) + __field( u64, len ) + __field( u64, used ) + __field( u64, flags ) + ), + + TP_fast_assign_btrfs(bg_cache->fs_info, + __entry->bytenr = bg_cache->key.objectid, + __entry->len = bg_cache->key.offset, + __entry->used = btrfs_block_group_used(&bg_cache->item); + __entry->flags = bg_cache->flags; + ), + + TP_printk_btrfs("bg bytenr=%llu len=%llu used=%llu flags=%llu(%s)", + __entry->bytenr, __entry->len, __entry->used, __entry->flags, + __print_flags(__entry->flags, "|", BTRFS_GROUP_FLAGS)) +); + +DEFINE_EVENT(btrfs__block_group, btrfs_remove_block_group, + TP_PROTO(const struct btrfs_block_group_cache *bg_cache), + + TP_ARGS(bg_cache) +); + +DEFINE_EVENT(btrfs__block_group, btrfs_add_unused_block_group, + TP_PROTO(const struct btrfs_block_group_cache *bg_cache), + + TP_ARGS(bg_cache) +); + +DEFINE_EVENT(btrfs__block_group, btrfs_skip_unused_block_group, + TP_PROTO(const struct btrfs_block_group_cache *bg_cache), + + TP_ARGS(bg_cache) +); + #endif /* _TRACE_BTRFS_H */ /* This part must be outside protection */ -- cgit v1.2.3 From 8b317901da4ab5576d109bf1aed7eb15cbe31d5f Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Mon, 30 Apr 2018 15:04:44 +0800 Subject: btrfs: trace: Allow trace_qgroup_update_counters() to record old rfer/excl value Origin trace_qgroup_update_counters() only records qgroup id and its reference count change. It's good enough to debug qgroup accounting change, but when rescan race is involved, it's pretty hard to distinguish which modification belongs to which rescan. So add old_rfer and old_excl trace output to help distinguishing different rescan instance. (Different rescan instance should reset its qgroup->rfer to 0) For trace event parameter, it just changes from u64 qgroup_id to struct btrfs_qgroup *qgroup, so number of parameters is not changed at all. Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/qgroup.c | 4 ++-- include/trace/events/btrfs.h | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 9fb758d5077a..ec2339a49ec3 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1882,8 +1882,8 @@ static int qgroup_update_counters(struct btrfs_fs_info *fs_info, cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq); cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq); - trace_qgroup_update_counters(fs_info, qg->qgroupid, - cur_old_count, cur_new_count); + trace_qgroup_update_counters(fs_info, qg, cur_old_count, + cur_new_count); /* Rfer update part */ if (cur_old_count == 0 && cur_new_count > 0) { diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 914ddb7a6d25..29f9b14412ad 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -1607,27 +1607,31 @@ TRACE_EVENT(btrfs_qgroup_account_extent, TRACE_EVENT(qgroup_update_counters, - TP_PROTO(const struct btrfs_fs_info *fs_info, u64 qgid, + TP_PROTO(const struct btrfs_fs_info *fs_info, + struct btrfs_qgroup *qgroup, u64 cur_old_count, u64 cur_new_count), - TP_ARGS(fs_info, qgid, cur_old_count, cur_new_count), + TP_ARGS(fs_info, qgroup, cur_old_count, cur_new_count), TP_STRUCT__entry_btrfs( __field( u64, qgid ) + __field( u64, old_rfer ) + __field( u64, old_excl ) __field( u64, cur_old_count ) __field( u64, cur_new_count ) ), TP_fast_assign_btrfs(fs_info, - __entry->qgid = qgid; + __entry->qgid = qgroup->qgroupid; + __entry->old_rfer = qgroup->rfer; + __entry->old_excl = qgroup->excl; __entry->cur_old_count = cur_old_count; __entry->cur_new_count = cur_new_count; ), - TP_printk_btrfs("qgid=%llu cur_old_count=%llu cur_new_count=%llu", - __entry->qgid, - __entry->cur_old_count, - __entry->cur_new_count) + TP_printk_btrfs("qgid=%llu old_rfer=%llu old_excl=%llu cur_old_count=%llu cur_new_count=%llu", + __entry->qgid, __entry->old_rfer, __entry->old_excl, + __entry->cur_old_count, __entry->cur_new_count) ); TRACE_EVENT(qgroup_update_reserve, -- cgit v1.2.3 From c9f6f3cd1c6fc4df959ce2bce15e5e6ce660bfd4 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Thu, 3 May 2018 09:59:02 +0800 Subject: btrfs: qgroup: Allow trace_btrfs_qgroup_account_extent() to record its transid When debugging quota rescan race, some times btrfs rescan could account some old (committed) leaf and then re-account newly committed leaf in next generation. This race needs extra transid to locate, so add @transid for trace_btrfs_qgroup_account_extent() for such debug. Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/qgroup.c | 4 ++-- include/trace/events/btrfs.h | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index ec2339a49ec3..9fdac5b46aa9 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -2014,8 +2014,8 @@ btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, BUG_ON(!fs_info->quota_root); - trace_btrfs_qgroup_account_extent(fs_info, bytenr, num_bytes, - nr_old_roots, nr_new_roots); + trace_btrfs_qgroup_account_extent(fs_info, trans->transid, bytenr, + num_bytes, nr_old_roots, nr_new_roots); qgroups = ulist_alloc(GFP_NOFS); if (!qgroups) { diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 29f9b14412ad..39b94ec965be 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -1578,12 +1578,14 @@ DEFINE_EVENT(btrfs_qgroup_extent, btrfs_qgroup_trace_extent, TRACE_EVENT(btrfs_qgroup_account_extent, - TP_PROTO(const struct btrfs_fs_info *fs_info, u64 bytenr, + TP_PROTO(const struct btrfs_fs_info *fs_info, u64 transid, u64 bytenr, u64 num_bytes, u64 nr_old_roots, u64 nr_new_roots), - TP_ARGS(fs_info, bytenr, num_bytes, nr_old_roots, nr_new_roots), + TP_ARGS(fs_info, transid, bytenr, num_bytes, nr_old_roots, + nr_new_roots), TP_STRUCT__entry_btrfs( + __field( u64, transid ) __field( u64, bytenr ) __field( u64, num_bytes ) __field( u64, nr_old_roots ) @@ -1591,18 +1593,20 @@ TRACE_EVENT(btrfs_qgroup_account_extent, ), TP_fast_assign_btrfs(fs_info, + __entry->transid = transid; __entry->bytenr = bytenr; __entry->num_bytes = num_bytes; __entry->nr_old_roots = nr_old_roots; __entry->nr_new_roots = nr_new_roots; ), - TP_printk_btrfs("bytenr=%llu num_bytes=%llu nr_old_roots=%llu " - "nr_new_roots=%llu", - __entry->bytenr, - __entry->num_bytes, - __entry->nr_old_roots, - __entry->nr_new_roots) + TP_printk_btrfs( +"transid=%llu bytenr=%llu num_bytes=%llu nr_old_roots=%llu nr_new_roots=%llu", + __entry->transid, + __entry->bytenr, + __entry->num_bytes, + __entry->nr_old_roots, + __entry->nr_new_roots) ); TRACE_EVENT(qgroup_update_counters, -- cgit v1.2.3 From b64ec075bded2b30bcd90af5aa5256d2237c885d Mon Sep 17 00:00:00 2001 From: Tomohiro Misono Date: Mon, 21 May 2018 10:09:42 +0900 Subject: btrfs: Add unprivileged ioctl which returns subvolume information Add new unprivileged ioctl BTRFS_IOC_GET_SUBVOL_INFO which returns the information of subvolume containing this inode. (i.e. returns the information in ROOT_ITEM and ROOT_BACKREF.) Reviewed-by: Gu Jinxiang Tested-by: Gu Jinxiang Signed-off-by: Tomohiro Misono [ minor style fixes, update struct comments ] Signed-off-by: David Sterba --- fs/btrfs/ioctl.c | 121 +++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/btrfs.h | 62 +++++++++++++++++++++++ 2 files changed, 183 insertions(+) (limited to 'include') diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4db2446c7015..42ed752288e6 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2383,6 +2383,125 @@ out: return ret; } +/* Get the subvolume information in BTRFS_ROOT_ITEM and BTRFS_ROOT_BACKREF */ +static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) +{ + struct btrfs_ioctl_get_subvol_info_args *subvol_info; + struct btrfs_fs_info *fs_info; + struct btrfs_root *root; + struct btrfs_path *path; + struct btrfs_key key; + struct btrfs_root_item *root_item; + struct btrfs_root_ref *rref; + struct extent_buffer *leaf; + unsigned long item_off; + unsigned long item_len; + struct inode *inode; + int slot; + int ret = 0; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + subvol_info = kzalloc(sizeof(*subvol_info), GFP_KERNEL); + if (!subvol_info) { + btrfs_free_path(path); + return -ENOMEM; + } + + inode = file_inode(file); + fs_info = BTRFS_I(inode)->root->fs_info; + + /* Get root_item of inode's subvolume */ + key.objectid = BTRFS_I(inode)->root->root_key.objectid; + key.type = BTRFS_ROOT_ITEM_KEY; + key.offset = (u64)-1; + root = btrfs_read_fs_root_no_name(fs_info, &key); + if (IS_ERR(root)) { + ret = PTR_ERR(root); + goto out; + } + root_item = &root->root_item; + + subvol_info->treeid = key.objectid; + + subvol_info->generation = btrfs_root_generation(root_item); + subvol_info->flags = btrfs_root_flags(root_item); + + memcpy(subvol_info->uuid, root_item->uuid, BTRFS_UUID_SIZE); + memcpy(subvol_info->parent_uuid, root_item->parent_uuid, + BTRFS_UUID_SIZE); + memcpy(subvol_info->received_uuid, root_item->received_uuid, + BTRFS_UUID_SIZE); + + subvol_info->ctransid = btrfs_root_ctransid(root_item); + subvol_info->ctime.sec = btrfs_stack_timespec_sec(&root_item->ctime); + subvol_info->ctime.nsec = btrfs_stack_timespec_nsec(&root_item->ctime); + + subvol_info->otransid = btrfs_root_otransid(root_item); + subvol_info->otime.sec = btrfs_stack_timespec_sec(&root_item->otime); + subvol_info->otime.nsec = btrfs_stack_timespec_nsec(&root_item->otime); + + subvol_info->stransid = btrfs_root_stransid(root_item); + subvol_info->stime.sec = btrfs_stack_timespec_sec(&root_item->stime); + subvol_info->stime.nsec = btrfs_stack_timespec_nsec(&root_item->stime); + + subvol_info->rtransid = btrfs_root_rtransid(root_item); + subvol_info->rtime.sec = btrfs_stack_timespec_sec(&root_item->rtime); + subvol_info->rtime.nsec = btrfs_stack_timespec_nsec(&root_item->rtime); + + if (key.objectid != BTRFS_FS_TREE_OBJECTID) { + /* Search root tree for ROOT_BACKREF of this subvolume */ + root = fs_info->tree_root; + + key.type = BTRFS_ROOT_BACKREF_KEY; + key.offset = 0; + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) { + goto out; + } else if (path->slots[0] >= + btrfs_header_nritems(path->nodes[0])) { + ret = btrfs_next_leaf(root, path); + if (ret < 0) { + goto out; + } else if (ret > 0) { + ret = -EUCLEAN; + goto out; + } + } + + leaf = path->nodes[0]; + slot = path->slots[0]; + btrfs_item_key_to_cpu(leaf, &key, slot); + if (key.objectid == subvol_info->treeid && + key.type == BTRFS_ROOT_BACKREF_KEY) { + subvol_info->parent_id = key.offset; + + rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref); + subvol_info->dirid = btrfs_root_ref_dirid(leaf, rref); + + item_off = btrfs_item_ptr_offset(leaf, slot) + + sizeof(struct btrfs_root_ref); + item_len = btrfs_item_size_nr(leaf, slot) + - sizeof(struct btrfs_root_ref); + read_extent_buffer(leaf, subvol_info->name, + item_off, item_len); + } else { + ret = -ENOENT; + goto out; + } + } + + if (copy_to_user(argp, subvol_info, sizeof(*subvol_info))) + ret = -EFAULT; + +out: + btrfs_free_path(path); + kzfree(subvol_info); + return ret; +} + static noinline int btrfs_ioctl_snap_destroy(struct file *file, void __user *arg) { @@ -5545,6 +5664,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_fsgetxattr(file, argp); case FS_IOC_FSSETXATTR: return btrfs_ioctl_fssetxattr(file, argp); + case BTRFS_IOC_GET_SUBVOL_INFO: + return btrfs_ioctl_get_subvol_info(file, argp); } return -ENOTTY; diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index c8d99b9ca550..f8f20d72b852 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -725,6 +725,66 @@ struct btrfs_ioctl_send_args { __u64 reserved[4]; /* in */ }; +/* + * Information about a fs tree root. + * + * All items are filled by the ioctl + */ +struct btrfs_ioctl_get_subvol_info_args { + /* Id of this subvolume */ + __u64 treeid; + + /* Name of this subvolume, used to get the real name at mount point */ + char name[BTRFS_VOL_NAME_MAX + 1]; + + /* + * Id of the subvolume which contains this subvolume. + * Zero for top-level subvolume or a deleted subvolume. + */ + __u64 parent_id; + + /* + * Inode number of the directory which contains this subvolume. + * Zero for top-level subvolume or a deleted subvolume + */ + __u64 dirid; + + /* Latest transaction id of this subvolume */ + __u64 generation; + + /* Flags of this subvolume */ + __u64 flags; + + /* UUID of this subvolume */ + __u8 uuid[BTRFS_UUID_SIZE]; + + /* + * UUID of the subvolume of which this subvolume is a snapshot. + * All zero for a non-snapshot subvolume. + */ + __u8 parent_uuid[BTRFS_UUID_SIZE]; + + /* + * UUID of the subvolume from which this subvolume was received. + * All zero for non-received subvolume. + */ + __u8 received_uuid[BTRFS_UUID_SIZE]; + + /* Transaction id indicating when change/create/send/receive happened */ + __u64 ctransid; + __u64 otransid; + __u64 stransid; + __u64 rtransid; + /* Time corresponding to c/o/s/rtransid */ + struct btrfs_ioctl_timespec ctime; + struct btrfs_ioctl_timespec otime; + struct btrfs_ioctl_timespec stime; + struct btrfs_ioctl_timespec rtime; + + /* Must be zero */ + __u64 reserved[8]; +}; + /* Error codes as returned by the kernel */ enum btrfs_err_code { BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1, @@ -843,5 +903,7 @@ enum btrfs_err_code { struct btrfs_ioctl_vol_args_v2) #define BTRFS_IOC_LOGICAL_INO_V2 _IOWR(BTRFS_IOCTL_MAGIC, 59, \ struct btrfs_ioctl_logical_ino_args) +#define BTRFS_IOC_GET_SUBVOL_INFO _IOR(BTRFS_IOCTL_MAGIC, 60, \ + struct btrfs_ioctl_get_subvol_info_args) #endif /* _UAPI_LINUX_BTRFS_H */ -- cgit v1.2.3 From 42e4b520c812daaf5e6177c2e4beec012ce1e2ce Mon Sep 17 00:00:00 2001 From: Tomohiro Misono Date: Mon, 21 May 2018 10:09:43 +0900 Subject: btrfs: Add unprivileged ioctl which returns subvolume's ROOT_REF Add unprivileged ioctl BTRFS_IOC_GET_SUBVOL_ROOTREF which returns ROOT_REF information of the subvolume containing this inode except the subvolume name (this is because to prevent potential name leak). The subvolume name will be gained by user version of ino_lookup ioctl (BTRFS_IOC_INO_LOOKUP_USER) which also performs permission check. The min id of root ref's subvolume to be searched is specified by @min_id in struct btrfs_ioctl_get_subvol_rootref_args. After the search ends, @min_id is set to the last searched root ref's subvolid + 1. Also, if there are more root refs than BTRFS_MAX_ROOTREF_BUFFER_NUM, -EOVERFLOW is returned. Therefore the caller can just call this ioctl again without changing the argument to continue search. Reviewed-by: Qu Wenruo Reviewed-by: Gu Jinxiang Tested-by: Gu Jinxiang Signed-off-by: Tomohiro Misono [ style fixes and struct item renames ] Signed-off-by: David Sterba --- fs/btrfs/ioctl.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/btrfs.h | 18 +++++++++ 2 files changed, 117 insertions(+) (limited to 'include') diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 42ed752288e6..be9b3f39183c 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2502,6 +2502,103 @@ out: return ret; } +/* + * Return ROOT_REF information of the subvolume containing this inode + * except the subvolume name. + */ +static int btrfs_ioctl_get_subvol_rootref(struct file *file, void __user *argp) +{ + struct btrfs_ioctl_get_subvol_rootref_args *rootrefs; + struct btrfs_root_ref *rref; + struct btrfs_root *root; + struct btrfs_path *path; + struct btrfs_key key; + struct extent_buffer *leaf; + struct inode *inode; + u64 objectid; + int slot; + int ret; + u8 found; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + rootrefs = memdup_user(argp, sizeof(*rootrefs)); + if (IS_ERR(rootrefs)) { + btrfs_free_path(path); + return PTR_ERR(rootrefs); + } + + inode = file_inode(file); + root = BTRFS_I(inode)->root->fs_info->tree_root; + objectid = BTRFS_I(inode)->root->root_key.objectid; + + key.objectid = objectid; + key.type = BTRFS_ROOT_REF_KEY; + key.offset = rootrefs->min_treeid; + found = 0; + + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) { + goto out; + } else if (path->slots[0] >= + btrfs_header_nritems(path->nodes[0])) { + ret = btrfs_next_leaf(root, path); + if (ret < 0) { + goto out; + } else if (ret > 0) { + ret = -EUCLEAN; + goto out; + } + } + while (1) { + leaf = path->nodes[0]; + slot = path->slots[0]; + + btrfs_item_key_to_cpu(leaf, &key, slot); + if (key.objectid != objectid || key.type != BTRFS_ROOT_REF_KEY) { + ret = 0; + goto out; + } + + if (found == BTRFS_MAX_ROOTREF_BUFFER_NUM) { + ret = -EOVERFLOW; + goto out; + } + + rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref); + rootrefs->rootref[found].treeid = key.offset; + rootrefs->rootref[found].dirid = + btrfs_root_ref_dirid(leaf, rref); + found++; + + ret = btrfs_next_item(root, path); + if (ret < 0) { + goto out; + } else if (ret > 0) { + ret = -EUCLEAN; + goto out; + } + } + +out: + if (!ret || ret == -EOVERFLOW) { + rootrefs->num_items = found; + /* update min_treeid for next search */ + if (found) + rootrefs->min_treeid = + rootrefs->rootref[found - 1].treeid + 1; + if (copy_to_user(argp, rootrefs, sizeof(*rootrefs))) + ret = -EFAULT; + } + + kfree(rootrefs); + btrfs_free_path(path); + + return ret; +} + static noinline int btrfs_ioctl_snap_destroy(struct file *file, void __user *arg) { @@ -5666,6 +5763,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_fssetxattr(file, argp); case BTRFS_IOC_GET_SUBVOL_INFO: return btrfs_ioctl_get_subvol_info(file, argp); + case BTRFS_IOC_GET_SUBVOL_ROOTREF: + return btrfs_ioctl_get_subvol_rootref(file, argp); } return -ENOTTY; diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index f8f20d72b852..f90d10478235 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -785,6 +785,22 @@ struct btrfs_ioctl_get_subvol_info_args { __u64 reserved[8]; }; +#define BTRFS_MAX_ROOTREF_BUFFER_NUM 255 +struct btrfs_ioctl_get_subvol_rootref_args { + /* in/out, minimum id of rootref's treeid to be searched */ + __u64 min_treeid; + + /* out */ + struct { + __u64 treeid; + __u64 dirid; + } rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM]; + + /* out, number of found items */ + __u8 num_items; + __u8 align[7]; +}; + /* Error codes as returned by the kernel */ enum btrfs_err_code { BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1, @@ -905,5 +921,7 @@ enum btrfs_err_code { struct btrfs_ioctl_logical_ino_args) #define BTRFS_IOC_GET_SUBVOL_INFO _IOR(BTRFS_IOCTL_MAGIC, 60, \ struct btrfs_ioctl_get_subvol_info_args) +#define BTRFS_IOC_GET_SUBVOL_ROOTREF _IOWR(BTRFS_IOCTL_MAGIC, 61, \ + struct btrfs_ioctl_get_subvol_rootref_args) #endif /* _UAPI_LINUX_BTRFS_H */ -- cgit v1.2.3 From 23d0b79dfaed2305b500b0215b0421701ada6b1a Mon Sep 17 00:00:00 2001 From: Tomohiro Misono Date: Mon, 21 May 2018 10:09:44 +0900 Subject: btrfs: Add unprivileged version of ino_lookup ioctl Add unprivileged version of ino_lookup ioctl BTRFS_IOC_INO_LOOKUP_USER to allow normal users to call "btrfs subvolume list/show" etc. in combination with BTRFS_IOC_GET_SUBVOL_INFO/BTRFS_IOC_GET_SUBVOL_ROOTREF. This can be used like BTRFS_IOC_INO_LOOKUP but the argument is different. This is because it always searches the fs/file tree correspoinding to the fd with which this ioctl is called and also returns the name of bottom subvolume. The main differences from original ino_lookup ioctl are: 1. Read + Exec permission will be checked using inode_permission() during path construction. -EACCES will be returned in case of failure. 2. Path construction will be stopped at the inode number which corresponds to the fd with which this ioctl is called. If constructed path does not exist under fd's inode, -EACCES will be returned. 3. The name of bottom subvolume is also searched and filled. Note that the maximum length of path is shorter 256 (BTRFS_VOL_NAME_MAX+1) bytes than ino_lookup ioctl because of space of subvolume's name. Reviewed-by: Gu Jinxiang Reviewed-by: Qu Wenruo Tested-by: Gu Jinxiang Signed-off-by: Tomohiro Misono [ style fixes ] Signed-off-by: David Sterba --- fs/btrfs/ioctl.c | 204 +++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/btrfs.h | 17 ++++ 2 files changed, 221 insertions(+) (limited to 'include') diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index be9b3f39183c..d29992f7dc63 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2341,6 +2341,165 @@ out: return ret; } +static int btrfs_search_path_in_tree_user(struct inode *inode, + struct btrfs_ioctl_ino_lookup_user_args *args) +{ + struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; + struct super_block *sb = inode->i_sb; + struct btrfs_key upper_limit = BTRFS_I(inode)->location; + u64 treeid = BTRFS_I(inode)->root->root_key.objectid; + u64 dirid = args->dirid; + unsigned long item_off; + unsigned long item_len; + struct btrfs_inode_ref *iref; + struct btrfs_root_ref *rref; + struct btrfs_root *root; + struct btrfs_path *path; + struct btrfs_key key, key2; + struct extent_buffer *leaf; + struct inode *temp_inode; + char *ptr; + int slot; + int len; + int total_len = 0; + int ret; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + /* + * If the bottom subvolume does not exist directly under upper_limit, + * construct the path in from the bottom up. + */ + if (dirid != upper_limit.objectid) { + ptr = &args->path[BTRFS_INO_LOOKUP_USER_PATH_MAX - 1]; + + key.objectid = treeid; + key.type = BTRFS_ROOT_ITEM_KEY; + key.offset = (u64)-1; + root = btrfs_read_fs_root_no_name(fs_info, &key); + if (IS_ERR(root)) { + ret = PTR_ERR(root); + goto out; + } + + key.objectid = dirid; + key.type = BTRFS_INODE_REF_KEY; + key.offset = (u64)-1; + while (1) { + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) { + goto out; + } else if (ret > 0) { + ret = btrfs_previous_item(root, path, dirid, + BTRFS_INODE_REF_KEY); + if (ret < 0) { + goto out; + } else if (ret > 0) { + ret = -ENOENT; + goto out; + } + } + + leaf = path->nodes[0]; + slot = path->slots[0]; + btrfs_item_key_to_cpu(leaf, &key, slot); + + iref = btrfs_item_ptr(leaf, slot, struct btrfs_inode_ref); + len = btrfs_inode_ref_name_len(leaf, iref); + ptr -= len + 1; + total_len += len + 1; + if (ptr < args->path) { + ret = -ENAMETOOLONG; + goto out; + } + + *(ptr + len) = '/'; + read_extent_buffer(leaf, ptr, + (unsigned long)(iref + 1), len); + + /* Check the read+exec permission of this directory */ + ret = btrfs_previous_item(root, path, dirid, + BTRFS_INODE_ITEM_KEY); + if (ret < 0) { + goto out; + } else if (ret > 0) { + ret = -ENOENT; + goto out; + } + + leaf = path->nodes[0]; + slot = path->slots[0]; + btrfs_item_key_to_cpu(leaf, &key2, slot); + if (key2.objectid != dirid) { + ret = -ENOENT; + goto out; + } + + temp_inode = btrfs_iget(sb, &key2, root, NULL); + ret = inode_permission(temp_inode, MAY_READ | MAY_EXEC); + iput(temp_inode); + if (ret) { + ret = -EACCES; + goto out; + } + + if (key.offset == upper_limit.objectid) + break; + if (key.objectid == BTRFS_FIRST_FREE_OBJECTID) { + ret = -EACCES; + goto out; + } + + btrfs_release_path(path); + key.objectid = key.offset; + key.offset = (u64)-1; + dirid = key.objectid; + } + + memmove(args->path, ptr, total_len); + args->path[total_len] = '\0'; + btrfs_release_path(path); + } + + /* Get the bottom subvolume's name from ROOT_REF */ + root = fs_info->tree_root; + key.objectid = treeid; + key.type = BTRFS_ROOT_REF_KEY; + key.offset = args->treeid; + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) { + goto out; + } else if (ret > 0) { + ret = -ENOENT; + goto out; + } + + leaf = path->nodes[0]; + slot = path->slots[0]; + btrfs_item_key_to_cpu(leaf, &key, slot); + + item_off = btrfs_item_ptr_offset(leaf, slot); + item_len = btrfs_item_size_nr(leaf, slot); + /* Check if dirid in ROOT_REF corresponds to passed dirid */ + rref = btrfs_item_ptr(leaf, slot, struct btrfs_root_ref); + if (args->dirid != btrfs_root_ref_dirid(leaf, rref)) { + ret = -EINVAL; + goto out; + } + + /* Copy subvolume's name */ + item_off += sizeof(struct btrfs_root_ref); + item_len -= sizeof(struct btrfs_root_ref); + read_extent_buffer(leaf, args->name, item_off, item_len); + args->name[item_len] = 0; + +out: + btrfs_free_path(path); + return ret; +} + static noinline int btrfs_ioctl_ino_lookup(struct file *file, void __user *argp) { @@ -2383,6 +2542,49 @@ out: return ret; } +/* + * Version of ino_lookup ioctl (unprivileged) + * + * The main differences from ino_lookup ioctl are: + * + * 1. Read + Exec permission will be checked using inode_permission() during + * path construction. -EACCES will be returned in case of failure. + * 2. Path construction will be stopped at the inode number which corresponds + * to the fd with which this ioctl is called. If constructed path does not + * exist under fd's inode, -EACCES will be returned. + * 3. The name of bottom subvolume is also searched and filled. + */ +static int btrfs_ioctl_ino_lookup_user(struct file *file, void __user *argp) +{ + struct btrfs_ioctl_ino_lookup_user_args *args; + struct inode *inode; + int ret; + + args = memdup_user(argp, sizeof(*args)); + if (IS_ERR(args)) + return PTR_ERR(args); + + inode = file_inode(file); + + if (args->dirid == BTRFS_FIRST_FREE_OBJECTID && + BTRFS_I(inode)->location.objectid != BTRFS_FIRST_FREE_OBJECTID) { + /* + * The subvolume does not exist under fd with which this is + * called + */ + kfree(args); + return -EACCES; + } + + ret = btrfs_search_path_in_tree_user(inode, args); + + if (ret == 0 && copy_to_user(argp, args, sizeof(*args))) + ret = -EFAULT; + + kfree(args); + return ret; +} + /* Get the subvolume information in BTRFS_ROOT_ITEM and BTRFS_ROOT_BACKREF */ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp) { @@ -5765,6 +5967,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_get_subvol_info(file, argp); case BTRFS_IOC_GET_SUBVOL_ROOTREF: return btrfs_ioctl_get_subvol_rootref(file, argp); + case BTRFS_IOC_INO_LOOKUP_USER: + return btrfs_ioctl_ino_lookup_user(file, argp); } return -ENOTTY; diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index f90d10478235..5ca1d21fc4a7 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -422,6 +422,21 @@ struct btrfs_ioctl_ino_lookup_args { char name[BTRFS_INO_LOOKUP_PATH_MAX]; }; +#define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1) +struct btrfs_ioctl_ino_lookup_user_args { + /* in, inode number containing the subvolume of 'subvolid' */ + __u64 dirid; + /* in */ + __u64 treeid; + /* out, name of the subvolume of 'treeid' */ + char name[BTRFS_VOL_NAME_MAX + 1]; + /* + * out, constructed path from the directory with which the ioctl is + * called to dirid + */ + char path[BTRFS_INO_LOOKUP_USER_PATH_MAX]; +}; + /* Search criteria for the btrfs SEARCH ioctl family. */ struct btrfs_ioctl_search_key { /* @@ -923,5 +938,7 @@ enum btrfs_err_code { struct btrfs_ioctl_get_subvol_info_args) #define BTRFS_IOC_GET_SUBVOL_ROOTREF _IOWR(BTRFS_IOCTL_MAGIC, 61, \ struct btrfs_ioctl_get_subvol_rootref_args) +#define BTRFS_IOC_INO_LOOKUP_USER _IOWR(BTRFS_IOCTL_MAGIC, 62, \ + struct btrfs_ioctl_ino_lookup_user_args) #endif /* _UAPI_LINUX_BTRFS_H */ -- cgit v1.2.3