1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 #include "processlist.h"
34 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
35 //#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
37 /* Preallocated Size of the index_to_pixmap array */
38 #define ALLOCATE_PROCESSES 1000
40 /*****************************************************************************
41 * Methods to synchronize process list *
42 *****************************************************************************/
45 gint
resource_sort_func ( GtkTreeModel
*model
,
53 gtk_tree_model_get(model
, it_a
, NAME_COLUMN
, &a_name
, -1);
55 gtk_tree_model_get(model
, it_b
, NAME_COLUMN
, &b_name
, -1);
57 return strcmp(a_name
, b_name
);
60 static guint
ru_numeric_hash_fct(gconstpointer key
)
62 ResourceUniqueNumeric
*ru
= (ResourceUniqueNumeric
*)key
;
63 int tmp
= (ru
->trace_num
<< 8) ^ ru
->id
;
65 return g_int_hash(&tmp
);
68 static gboolean
ru_numeric_equ_fct(gconstpointer a
, gconstpointer b
)
70 const ResourceUniqueNumeric
*pa
= (const ResourceUniqueNumeric
*)a
;
71 const ResourceUniqueNumeric
*pb
= (const ResourceUniqueNumeric
*)b
;
73 if(pa
->id
== pb
->id
&& pa
->trace_num
== pb
->trace_num
)
79 void destroy_hash_key(gpointer key
);
81 void destroy_hash_data(gpointer data
);
84 gboolean
scroll_event(GtkWidget
*widget
, GdkEventScroll
*event
, gpointer data
)
86 ControlFlowData
*control_flow_data
=
87 (ControlFlowData
*)g_object_get_data(
90 Drawing_t
*drawing
= control_flow_data
->drawing
;
91 unsigned int cell_height
=
92 get_cell_height(GTK_TREE_VIEW(control_flow_data
->process_list
->process_list_widget
));
94 switch(event
->direction
) {
96 gtk_adjustment_set_value(control_flow_data
->v_adjust
,
97 gtk_adjustment_get_value(control_flow_data
->v_adjust
) - cell_height
);
100 gtk_adjustment_set_value(control_flow_data
->v_adjust
,
101 gtk_adjustment_get_value(control_flow_data
->v_adjust
) + cell_height
);
104 g_error("should only scroll up and down.");
109 void expand_event(GtkTreeView
*treeview
, GtkTreeIter
*iter
, GtkTreePath
*arg2
, gpointer user_data
)
111 ControlFlowData
*resourceview_data
=
112 (ControlFlowData
*)g_object_get_data(
114 "resourceview_data");
115 ProcessList
*process_list
= (ProcessList
*) user_data
;
117 HashedResourceData
*hrd
;
123 /* Determine which trace has been expanded */
124 model
= gtk_tree_view_get_model(treeview
);
126 /* mark each of the trace's resources invisible */
127 result
= gtk_tree_model_iter_children(model
, &child
, iter
);
129 /* for each child of the collapsed row */
132 gtk_tree_model_get(model
, &child
, DATA_COLUMN
, &hrd
, -1);
136 result
= gtk_tree_model_iter_next(model
, &child
);
139 update_index_to_pixmap(process_list
);
141 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
144 void collapse_event(GtkTreeView
*treeview
, GtkTreeIter
*iter
, GtkTreePath
*arg2
, gpointer user_data
)
146 ControlFlowData
*resourceview_data
=
147 (ControlFlowData
*)g_object_get_data(
149 "resourceview_data");
150 ProcessList
*process_list
= (ProcessList
*) user_data
;
152 HashedResourceData
*hrd
;
158 /* Determine which trace has been expanded */
159 model
= gtk_tree_view_get_model(treeview
);
161 /* mark each of the trace's resources invisible */
162 result
= gtk_tree_model_iter_children(model
, &child
, iter
);
164 /* for each child of the collapsed row */
168 gtk_tree_model_get(model
, &child
, NAME_COLUMN
, &name
, DATA_COLUMN
, &hrd
, -1);
172 result
= gtk_tree_model_iter_next(model
, &child
);
175 update_index_to_pixmap(process_list
);
177 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
180 static gboolean
update_index_to_pixmap_each (GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
, UpdateIndexPixmapArg
*arg
)
182 guint array_index
= arg
->count
;
183 HashedResourceData
*hdata
;
186 gtk_tree_model_get(model
, iter
, NAME_COLUMN
, &name
, DATA_COLUMN
, &hdata
, -1);
188 g_assert(array_index
< arg
->process_list
->index_to_pixmap
->len
);
190 if(hdata
->hidden
== 0) {
192 (GdkPixmap
**)&g_ptr_array_index(arg
->process_list
->index_to_pixmap
, array_index
);
193 *pixmap
= hdata
->pixmap
;
201 void update_index_to_pixmap(ProcessList
*process_list
)
204 UpdateIndexPixmapArg arg
;
206 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
207 items
+= g_hash_table_size(process_list
->restypes
[i
].hash_table
);
210 /* we don't know the exact number of items there will be,
211 * so set an upper bound */
212 g_ptr_array_set_size(process_list
->index_to_pixmap
, items
);
215 arg
.process_list
= process_list
;
217 gtk_tree_model_foreach(GTK_TREE_MODEL(process_list
->list_store
),
218 (GtkTreeModelForeachFunc
)update_index_to_pixmap_each
, &arg
);
220 /* now that we know the exact number of items, set it */
221 g_ptr_array_set_size(process_list
->index_to_pixmap
, arg
.count
);
225 static void update_pixmap_size_each(void *key
,
226 HashedResourceData
*value
,
229 GdkPixmap
*old_pixmap
= value
->pixmap
;
232 gdk_pixmap_new(old_pixmap
,
237 gdk_pixmap_unref(old_pixmap
);
241 void update_pixmap_size(ProcessList
*process_list
, guint width
)
244 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
245 g_hash_table_foreach(process_list
->restypes
[i
].hash_table
,
246 (GHFunc
)update_pixmap_size_each
,
252 typedef struct _CopyPixmap
{
256 gint xsrc
, ysrc
, xdest
, ydest
, width
, height
;
259 static void copy_pixmap_region_each(void *key
,
260 HashedResourceData
*value
,
263 GdkPixmap
*src
= cp
->src
;
264 GdkPixmap
*dest
= cp
->dest
;
267 dest
= value
->pixmap
;
271 gdk_draw_drawable (dest
,
275 cp
->xdest
, cp
->ydest
,
276 cp
->width
, cp
->height
);
279 void copy_pixmap_region(ProcessList
*process_list
, GdkDrawable
*dest
,
280 GdkGC
*gc
, GdkDrawable
*src
,
281 gint xsrc
, gint ysrc
,
282 gint xdest
, gint ydest
, gint width
, gint height
)
285 CopyPixmap cp
= { dest
, gc
, src
, xsrc
, ysrc
, xdest
, ydest
, width
, height
};
287 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
288 g_hash_table_foreach(process_list
->restypes
[i
].hash_table
,
289 (GHFunc
)copy_pixmap_region_each
,
296 typedef struct _RectanglePixmap
{
298 gint x
, y
, width
, height
;
302 static void rectangle_pixmap_each(void *key
,
303 HashedResourceData
*value
,
307 rp
->height
= value
->height
;
309 gdk_draw_rectangle (value
->pixmap
,
313 rp
->width
, rp
->height
);
316 void rectangle_pixmap(ProcessList
*process_list
, GdkGC
*gc
,
317 gboolean filled
, gint x
, gint y
, gint width
, gint height
)
320 RectanglePixmap rp
= { filled
, x
, y
, width
, height
, gc
};
322 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
323 g_hash_table_foreach(process_list
->restypes
[i
].hash_table
,
324 (GHFunc
)rectangle_pixmap_each
,
329 /* Renders each pixmaps into on big drawable */
330 void copy_pixmap_to_screen(ProcessList
*process_list
,
334 gint width
, gint height
)
336 if(process_list
->index_to_pixmap
->len
== 0) return;
337 guint cell_height
= process_list
->cell_height
;
340 gint begin
= floor(y
/(double)cell_height
);
341 gint end
= MIN(ceil((y
+height
)/(double)cell_height
),
342 process_list
->index_to_pixmap
->len
);
345 for(i
=begin
; i
<end
; i
++) {
346 g_assert(i
<process_list
->index_to_pixmap
->len
);
347 /* Render the pixmap to the screen */
349 //(GdkPixmap*)g_ptr_array_index(process_list->index_to_pixmap, i);
350 GDK_PIXMAP(g_ptr_array_index(process_list
->index_to_pixmap
, i
));
352 gdk_draw_drawable (dest
,
362 ProcessList
*processlist_construct(void)
364 GtkTreeViewColumn
*column
;
365 GtkCellRenderer
*renderer
;
367 ProcessList
* process_list
= g_new(ProcessList
,1);
369 process_list
->number_of_process
= 0;
371 process_list
->current_hash_data
= NULL
;
373 /* Create the Process list */
374 process_list
->list_store
= gtk_tree_store_new ( N_COLUMNS
, G_TYPE_STRING
, G_TYPE_POINTER
);
376 process_list
->process_list_widget
=
377 gtk_tree_view_new_with_model
378 (GTK_TREE_MODEL (process_list
->list_store
));
379 g_object_set(process_list
->process_list_widget
, "enable-tree-lines", TRUE
, NULL
);
381 g_object_unref (G_OBJECT (process_list
->list_store
));
383 gtk_tree_sortable_set_default_sort_func(
384 GTK_TREE_SORTABLE(process_list
->list_store
),
390 gtk_tree_sortable_set_sort_column_id(
391 GTK_TREE_SORTABLE(process_list
->list_store
),
392 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
,
395 gtk_tree_view_set_headers_visible(
396 GTK_TREE_VIEW(process_list
->process_list_widget
), TRUE
);
398 /* Create a column, associating the "text" attribute of the
399 * cell_renderer to the first column of the model */
400 /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */
401 renderer
= gtk_cell_renderer_text_new ();
402 process_list
->renderer
= renderer
;
404 gint vertical_separator
;
405 gtk_widget_style_get (GTK_WIDGET (process_list
->process_list_widget
),
406 "vertical-separator", &vertical_separator
,
408 gtk_cell_renderer_get_size(renderer
,
409 GTK_WIDGET(process_list
->process_list_widget
),
414 &process_list
->cell_height
);
416 g_signal_connect(process_list
->process_list_widget
, "row-expanded", G_CALLBACK(expand_event
), process_list
);
417 g_signal_connect(process_list
->process_list_widget
, "row-collapsed", G_CALLBACK(collapse_event
), process_list
);
419 #if GTK_CHECK_VERSION(2,4,15)
421 g_object_get(G_OBJECT(renderer
), "ypad", &ypad
, NULL
);
423 process_list
->cell_height
+= ypad
;
425 process_list
->cell_height
+= vertical_separator
;
428 column
= gtk_tree_view_column_new_with_attributes ( "Resource",
433 gtk_tree_view_column_set_alignment (column
, 0.0);
434 gtk_tree_view_column_set_fixed_width (column
, 45);
435 gtk_tree_view_append_column (
436 GTK_TREE_VIEW (process_list
->process_list_widget
), column
);
438 process_list
->button
= column
->button
;
440 g_object_set_data_full(
441 G_OBJECT(process_list
->process_list_widget
),
444 (GDestroyNotify
)processlist_destroy
);
446 process_list
->index_to_pixmap
= g_ptr_array_sized_new(ALLOCATE_PROCESSES
);
448 process_list
->restypes
[RV_RESOURCE_MACHINE
].hash_table
= g_hash_table_new(ru_numeric_hash_fct
, ru_numeric_equ_fct
);
449 process_list
->restypes
[RV_RESOURCE_CPU
].hash_table
= g_hash_table_new(ru_numeric_hash_fct
, ru_numeric_equ_fct
);
450 process_list
->restypes
[RV_RESOURCE_IRQ
].hash_table
= g_hash_table_new(ru_numeric_hash_fct
, ru_numeric_equ_fct
);
451 process_list
->restypes
[RV_RESOURCE_SOFT_IRQ
].hash_table
= g_hash_table_new(ru_numeric_hash_fct
, ru_numeric_equ_fct
);
452 process_list
->restypes
[RV_RESOURCE_TRAP
].hash_table
= g_hash_table_new(ru_numeric_hash_fct
, ru_numeric_equ_fct
);
453 process_list
->restypes
[RV_RESOURCE_BDEV
].hash_table
= g_hash_table_new(ru_numeric_hash_fct
, ru_numeric_equ_fct
);
458 void processlist_destroy(ProcessList
*process_list
)
462 g_debug("processlist_destroy %p", process_list
);
464 for(i
=0; i
<RV_RESOURCE_COUNT
; i
++) {
465 g_hash_table_destroy(process_list
->restypes
[i
].hash_table
);
466 process_list
->restypes
[i
].hash_table
= NULL
;
468 g_ptr_array_free(process_list
->index_to_pixmap
, TRUE
);
470 g_free(process_list
);
471 g_debug("processlist_destroy end");
474 static gboolean
remove_hash_item(void *key
,
475 HashedResourceData
*hashed_process_data
,
476 ProcessList
*process_list
)
480 iter
= hashed_process_data
->y_iter
;
482 gtk_tree_store_remove (process_list
->list_store
, &iter
);
483 gdk_pixmap_unref(hashed_process_data
->pixmap
);
485 // TODO pmf: check this; might be needed
486 // if(likely(process_list->current_hash_data != NULL)) {
487 // if(likely(hashed_process_data ==
488 // process_list->current_hash_data[process_info->trace_num][process_info->cpu]))
489 // process_list->current_hash_data[process_info->trace_num][process_info->cpu] = NULL;
491 return TRUE
; /* remove the element from the hash table */
494 void processlist_clear(ProcessList
*process_list
)
498 g_info("processlist_clear %p", process_list
);
500 for(i
=RV_RESOURCE_COUNT
-1; i
>=0; i
--) {
501 g_hash_table_foreach_remove(process_list
->restypes
[i
].hash_table
,
502 (GHRFunc
)remove_hash_item
,
503 (gpointer
)process_list
);
505 process_list
->number_of_process
= 0;
506 update_index_to_pixmap(process_list
);
510 GtkWidget
*processlist_get_widget(ProcessList
*process_list
)
512 return process_list
->process_list_widget
;
516 void destroy_hash_key(gpointer key
)
521 void destroy_hash_data(gpointer data
)
526 GQuark
make_cpu_name(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
531 str
= g_strdup_printf("CPU%u", id
);
532 name
= g_quark_from_string(str
);
538 GQuark
make_irq_name(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
543 str
= g_strdup_printf("IRQ %u", id
);
544 name
= g_quark_from_string(str
);
550 GQuark
make_soft_irq_name(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
555 str
= g_strdup_printf("SOFTIRQ %u", id
);
556 name
= g_quark_from_string(str
);
562 GQuark
make_trap_name(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
567 str
= g_strdup_printf("Trap %u", id
);
568 name
= g_quark_from_string(str
);
574 GQuark
make_bdev_name(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
579 str
= g_strdup_printf("Block (%u,%u)", MAJOR(id
), MINOR(id
));
580 name
= g_quark_from_string(str
);
586 HashedResourceData
*resourcelist_obtain_machine(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
588 ResourceUniqueNumeric
*ru
= g_new(ResourceUniqueNumeric
, 1);
589 HashedResourceData
*data
= g_new(HashedResourceData
, 1);
591 /* Prepare hash key */
592 ru
->trace_num
= trace_num
;
595 /* Search within hash table */
596 GHashTable
*ht
= resourceview_data
->process_list
->restypes
[RV_RESOURCE_MACHINE
].hash_table
;
597 data
= g_hash_table_lookup(ht
, ru
);
599 /* If not found in hash table, add it */
603 data
= g_malloc(sizeof(HashedResourceData
));
604 /* Prepare hashed data */
605 data
->type
= RV_RESOURCE_MACHINE
;
607 data
->x
.over_used
= FALSE
;
608 data
->x
.over_marked
= FALSE
;
609 data
->x
.middle
= 0; // last
610 data
->x
.middle_used
= FALSE
;
611 data
->x
.middle_marked
= FALSE
;
613 data
->x
.under_used
= FALSE
;
614 data
->x
.under_marked
= FALSE
;
615 data
->next_good_time
= ltt_time_zero
;
618 data
->height
= resourceview_data
->process_list
->cell_height
;
620 gdk_pixmap_new(resourceview_data
->drawing
->drawing_area
->window
,
621 resourceview_data
->drawing
->alloc_width
,
624 g_assert(data
->pixmap
);
626 gdk_draw_rectangle (data
->pixmap
,
627 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
630 resourceview_data
->drawing
->alloc_width
,
633 /* add to hash table */
634 g_hash_table_insert(ht
, ru
, data
);
635 resourceview_data
->process_list
->number_of_process
++; // TODO: check
637 /* add to process list */
640 str
= g_strdup_printf("Trace %u", id
);
641 name
= g_quark_from_string(str
);
645 gtk_tree_store_append(resourceview_data
->process_list
->list_store
, &data
->y_iter
, NULL
);
646 gtk_tree_store_set(resourceview_data
->process_list
->list_store
, &data
->y_iter
,
647 NAME_COLUMN
, g_quark_to_string(name
), DATA_COLUMN
, data
,
650 update_index_to_pixmap(resourceview_data
->process_list
);
652 int heightall
= data
->height
* resourceview_data
->process_list
->number_of_process
;
654 gtk_widget_set_size_request(resourceview_data
->drawing
->drawing_area
,
658 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
661 /* expand the newly added machine */
663 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(resourceview_data
->process_list
->process_list_widget
));
665 path
= gtk_tree_model_get_path(model
, &data
->y_iter
);
667 gtk_tree_view_expand_row(GTK_TREE_VIEW(resourceview_data
->process_list
->process_list_widget
), path
, FALSE
);
669 gtk_tree_path_free(path
);
675 HashedResourceData
*resourcelist_obtain_generic(ControlFlowData
*resourceview_data
, gint res_type
, guint trace_num
, guint id
, GQuark (*make_name_func
)(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
))
677 ResourceUniqueNumeric
*ru
= g_new(ResourceUniqueNumeric
, 1);
678 HashedResourceData
*data
= g_new(HashedResourceData
, 1);
680 /* Prepare hash key */
681 ru
->ru
.type
= &(resourceview_data
->process_list
->restypes
[res_type
]);
682 ru
->trace_num
= trace_num
;
685 /* Search within hash table */
686 GHashTable
*ht
= resourceview_data
->process_list
->restypes
[res_type
].hash_table
;
687 data
= g_hash_table_lookup(ht
, ru
);
689 /* If not found in hash table, add it */
692 HashedResourceData
*parent
;
694 /* Find the parent machine */
695 parent
= resourcelist_obtain_machine(resourceview_data
, trace_num
, trace_num
);
697 /* Prepare hashed data */
698 data
= g_malloc(sizeof(HashedResourceData
));
700 data
->type
= res_type
;
702 data
->x
.over_used
= FALSE
;
703 data
->x
.over_marked
= FALSE
;
704 data
->x
.middle
= 0; // last
705 data
->x
.middle_used
= FALSE
;
706 data
->x
.middle_marked
= FALSE
;
708 data
->x
.under_used
= FALSE
;
709 data
->x
.under_marked
= FALSE
;
710 data
->next_good_time
= ltt_time_zero
;
712 data
->height
= resourceview_data
->process_list
->cell_height
;
714 gdk_pixmap_new(resourceview_data
->drawing
->drawing_area
->window
,
715 resourceview_data
->drawing
->alloc_width
,
719 gdk_draw_rectangle (data
->pixmap
,
720 resourceview_data
->drawing
->drawing_area
->style
->black_gc
,
723 resourceview_data
->drawing
->alloc_width
,
726 /* add to hash table */
727 g_hash_table_insert(ht
, ru
, data
);
728 resourceview_data
->process_list
->number_of_process
++; // TODO: check
730 /* add to process list */
731 name
= make_name_func(resourceview_data
, trace_num
, id
);
733 gtk_tree_store_append(resourceview_data
->process_list
->list_store
, &data
->y_iter
, &parent
->y_iter
);
734 gtk_tree_store_set(resourceview_data
->process_list
->list_store
, &data
->y_iter
,
735 NAME_COLUMN
, g_quark_to_string(name
), DATA_COLUMN
, data
,
738 /* Determine if we should add it hidden or not */
741 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(resourceview_data
->process_list
->process_list_widget
));
742 GtkTreeIter parent_iter
;
744 result
= gtk_tree_model_iter_parent(model
, &parent_iter
, &data
->y_iter
);
745 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &parent_iter
);
746 data
->hidden
= gtk_tree_view_row_expanded(GTK_TREE_VIEW(resourceview_data
->process_list
->process_list_widget
), path
)?0:1;
747 gtk_tree_path_free(path
);
751 update_index_to_pixmap(resourceview_data
->process_list
);
753 int heightall
= data
->height
* resourceview_data
->process_list
->number_of_process
;
755 gtk_widget_set_size_request(resourceview_data
->drawing
->drawing_area
,
759 gtk_widget_queue_draw(resourceview_data
->drawing
->drawing_area
);
765 HashedResourceData
*resourcelist_obtain_cpu(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
767 return resourcelist_obtain_generic(resourceview_data
, RV_RESOURCE_CPU
, trace_num
, id
, make_cpu_name
);
770 HashedResourceData
*resourcelist_obtain_irq(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
772 return resourcelist_obtain_generic(resourceview_data
, RV_RESOURCE_IRQ
, trace_num
, id
, make_irq_name
);
775 HashedResourceData
*resourcelist_obtain_soft_irq(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
777 return resourcelist_obtain_generic(resourceview_data
, RV_RESOURCE_SOFT_IRQ
, trace_num
, id
, make_soft_irq_name
);
780 HashedResourceData
*resourcelist_obtain_trap(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
782 return resourcelist_obtain_generic(resourceview_data
, RV_RESOURCE_TRAP
, trace_num
, id
, make_trap_name
);
785 HashedResourceData
*resourcelist_obtain_bdev(ControlFlowData
*resourceview_data
, guint trace_num
, guint id
)
787 return resourcelist_obtain_generic(resourceview_data
, RV_RESOURCE_BDEV
, trace_num
, id
, make_bdev_name
);