From d3132792285859253c466354fd8d54d1fe0ba786 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 9 Jun 2020 21:38:24 -0700 Subject: [PATCH 001/289] HID: usbhid: do not sleep when opening device usbhid tries to give the device 50 milliseconds to drain its queues when opening the device, but does it naively by simply sleeping in open handler, which slows down device probing (and thus may affect overall boot time). However we do not need to sleep as we can instead mark a point of time in the future when we should start processing the events. Reported-by: Nicolas Boichat Signed-off-by: Dmitry Torokhov Reviewed-by: Guenter Roeck Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 53 +++++++++++++++++++---------------- drivers/hid/usbhid/usbhid.h | 2 ++ 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 17a638f15082..1235288b65bf 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -95,6 +96,18 @@ static int hid_start_in(struct hid_device *hid) set_bit(HID_NO_BANDWIDTH, &usbhid->iofl); } else { clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl); + + if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { + /* + * In case events are generated while nobody was + * listening, some are released when the device + * is re-opened. Wait 50 msec for the queue to + * empty before allowing events to go through + * hid. + */ + usbhid->input_start_time = + ktime_add_ms(ktime_get_coarse(), 50); + } } } spin_unlock_irqrestore(&usbhid->lock, flags); @@ -280,20 +293,23 @@ static void hid_irq_in(struct urb *urb) if (!test_bit(HID_OPENED, &usbhid->iofl)) break; usbhid_mark_busy(usbhid); - if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { - hid_input_report(urb->context, HID_INPUT_REPORT, - urb->transfer_buffer, - urb->actual_length, 1); - /* - * autosuspend refused while keys are pressed - * because most keyboards don't wake up when - * a key is released - */ - if (hid_check_keys_pressed(hid)) - set_bit(HID_KEYS_PRESSED, &usbhid->iofl); - else - clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); + if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { + if (ktime_before(ktime_get_coarse(), + usbhid->input_start_time)) + break; + clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); } + hid_input_report(urb->context, HID_INPUT_REPORT, + urb->transfer_buffer, urb->actual_length, 1); + /* + * autosuspend refused while keys are pressed + * because most keyboards don't wake up when + * a key is released + */ + if (hid_check_keys_pressed(hid)) + set_bit(HID_KEYS_PRESSED, &usbhid->iofl); + else + clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); break; case -EPIPE: /* stall */ usbhid_mark_busy(usbhid); @@ -720,17 +736,6 @@ static int usbhid_open(struct hid_device *hid) usb_autopm_put_interface(usbhid->intf); - /* - * In case events are generated while nobody was listening, - * some are released when the device is re-opened. - * Wait 50 msec for the queue to empty before allowing events - * to go through hid. - */ - if (res == 0) - msleep(50); - - clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); - Done: mutex_unlock(&usbhid->mutex); return res; diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 75fe85d3d27a..c6ad684d099a 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -83,6 +84,7 @@ struct usbhid_device { struct mutex mutex; /* start/stop/open/close */ spinlock_t lock; /* fifo spinlock */ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ + ktime_t input_start_time; /* When to start handling input */ struct timer_list io_retry; /* Retry timer */ unsigned long stop_retry; /* Time to give up, in jiffies */ unsigned int retry_delay; /* Delay length in ms */ From 8e9ddbde9ddbba74c86b0c5f8eefb26192b3242e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 10 Jun 2020 13:31:01 +0100 Subject: [PATCH 002/289] HID: usbhid: remove redundant assignment to variable retval The variable retval is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 1235288b65bf..492dd641a25d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1672,7 +1672,7 @@ struct usb_interface *usbhid_find_interface(int minor) static int __init hid_init(void) { - int retval = -ENOMEM; + int retval; retval = hid_quirks_init(quirks_param, BUS_USB, MAX_USBHID_BOOT_QUIRKS); if (retval) From 1ad273d6ff2d3af6ce3a4c8bd81a2ba10151ae0e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 9 Jun 2020 16:03:19 +1000 Subject: [PATCH 003/289] HID: input: do not run GET_REPORT unless there's a Resolution Multiplier hid-multitouch currently runs GET_REPORT for Contact Max and again to retrieve the Win8 blob. If both are within the same report, the Resolution Multiplier code calls GET_FEATURE again and this time, possibly due to timing, it causes the ILITEK-TP device interpret the GET_FEATURE as an instruction to change the mode and effectively stop the device from functioning as expected. Notably: the device doesn't even have a Resolution Multiplier so it shouldn't be affected by any of this at all. Fix this by making sure we only execute GET_REPORT if there is a Resolution Multiplier in the respective report. Where the HID_QUIRK_NO_INIT_REPORTS field is set we just bail out immediately. This shouldn't be triggered by any real device anyway. Signed-off-by: Peter Hutterer Tested-by: Wen He Signed-off-by: Jiri Kosina --- drivers/hid/hid-input.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index dea9cc65bf80..c8633beae260 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1560,21 +1560,12 @@ static bool __hidinput_change_resolution_multipliers(struct hid_device *hid, { struct hid_usage *usage; bool update_needed = false; + bool get_report_completed = false; int i, j; if (report->maxfield == 0) return false; - /* - * If we have more than one feature within this report we - * need to fill in the bits from the others before we can - * overwrite the ones for the Resolution Multiplier. - */ - if (report->maxfield > 1) { - hid_hw_request(hid, report, HID_REQ_GET_REPORT); - hid_hw_wait(hid); - } - for (i = 0; i < report->maxfield; i++) { __s32 value = use_logical_max ? report->field[i]->logical_maximum : @@ -1593,6 +1584,25 @@ static bool __hidinput_change_resolution_multipliers(struct hid_device *hid, if (usage->hid != HID_GD_RESOLUTION_MULTIPLIER) continue; + /* + * If we have more than one feature within this + * report we need to fill in the bits from the + * others before we can overwrite the ones for the + * Resolution Multiplier. + * + * But if we're not allowed to read from the device, + * we just bail. Such a device should not exist + * anyway. + */ + if (!get_report_completed && report->maxfield > 1) { + if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS) + return update_needed; + + hid_hw_request(hid, report, HID_REQ_GET_REPORT); + hid_hw_wait(hid); + get_report_completed = true; + } + report->field[i]->value[j] = value; update_needed = true; } From 99bbe307013059951368d12f5454d34568de4850 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 16 Jun 2020 09:56:51 -0700 Subject: [PATCH 004/289] f2fs: avoid checkpatch error ERROR:INITIALISED_STATIC: do not initialise statics to NULL Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 1e02a8c106b0..4dca9e456734 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -506,7 +506,7 @@ bool f2fs_is_compress_backend_ready(struct inode *inode) return f2fs_cops[F2FS_I(inode)->i_compress_algorithm]; } -static mempool_t *compress_page_pool = NULL; +static mempool_t *compress_page_pool; static int num_compress_pages = 512; module_param(num_compress_pages, uint, 0444); MODULE_PARM_DESC(num_compress_pages, From 742532d11d8328231d099f557e6287e75b2d247b Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Wed, 10 Jun 2020 01:14:46 +0300 Subject: [PATCH 005/289] f2fs: use kfree() instead of kvfree() to free superblock data Use kfree() instead of kvfree() to free super in read_raw_super_block() because the memory is allocated with kzalloc() in the function. Use kfree() instead of kvfree() to free sbi, raw_super in f2fs_fill_super() and f2fs_put_super() because the memory is allocated with kzalloc(). Signed-off-by: Denis Efremov Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 20e56b0fa46a..426cebdd84e5 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1243,7 +1243,7 @@ static void f2fs_put_super(struct super_block *sb) sb->s_fs_info = NULL; if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); - kvfree(sbi->raw_super); + kfree(sbi->raw_super); destroy_device_list(sbi); f2fs_destroy_xattr_caches(sbi); @@ -1259,7 +1259,7 @@ static void f2fs_put_super(struct super_block *sb) #ifdef CONFIG_UNICODE utf8_unload(sbi->s_encoding); #endif - kvfree(sbi); + kfree(sbi); } int f2fs_sync_fs(struct super_block *sb, int sync) @@ -3137,7 +3137,7 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi, /* No valid superblock */ if (!*raw_super) - kvfree(super); + kfree(super); else err = 0; @@ -3816,11 +3816,11 @@ free_options: fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); kvfree(options); free_sb_buf: - kvfree(raw_super); + kfree(raw_super); free_sbi: if (sbi->s_chksum_driver) crypto_free_shash(sbi->s_chksum_driver); - kvfree(sbi); + kfree(sbi); /* give only one another chance */ if (retry_cnt > 0 && skip_recovery) { From 6f6489288ed196a962ef8d33b1b9cf6369ff0807 Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Mon, 15 Jun 2020 16:11:38 +0800 Subject: [PATCH 006/289] f2fs: remove useless truncate in f2fs_collapse_range() Since offset < new_size, no need to do truncate_pagecache() again with new_size. Signed-off-by: Wei Fang Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 3268f8dd59bb..98721f9bef25 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1373,8 +1373,6 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) truncate_pagecache(inode, offset); new_size = i_size_read(inode) - len; - truncate_pagecache(inode, new_size); - ret = f2fs_truncate_blocks(inode, new_size, true); up_write(&F2FS_I(inode)->i_mmap_sem); if (!ret) From db5ae363292705d52c5b653d5079a07a6417ef4c Mon Sep 17 00:00:00 2001 From: Wuyun Zhao Date: Thu, 18 Jun 2020 10:58:37 +0800 Subject: [PATCH 007/289] f2fs: fix a race condition between f2fs_write_end_io and f2fs_del_fsync_node_entry Under some condition, the __write_node_page will submit a page which is not f2fs_in_warm_node_list and will not call f2fs_add_fsync_node_entry. f2fs_gc continue to run to invoke f2fs_iget -> do_read_inode to read the same node page and set code node, which make f2fs_in_warm_node_list become true, that will cause f2fs_bug_on in f2fs_del_fsync_node_entry when f2fs_write_end_io called. - f2fs_write_end_io - f2fs_iget - do_read_inode - set_cold_node recover cold node flag - f2fs_in_warm_node_list - is_cold_node if node is cold, assume we have added node to fsync_node_list during writepages() - f2fs_del_fsync_node_entry - f2fs_bug_on() due to node page is not in fsync_node_list [ 34.966133] Call trace: [ 34.969902] f2fs_del_fsync_node_entry+0x100/0x108 [ 34.976071] f2fs_write_end_io+0x1e0/0x288 [ 34.981539] bio_endio+0x248/0x270 [ 34.986289] blk_update_request+0x2b0/0x4d8 [ 34.991841] scsi_end_request+0x40/0x440 [ 34.997126] scsi_io_completion+0xa4/0x748 [ 35.002593] scsi_finish_command+0xdc/0x110 [ 35.008143] scsi_softirq_done+0x118/0x150 [ 35.013610] blk_done_softirq+0x8c/0xe8 [ 35.018811] __do_softirq+0x2e8/0x578 [ 35.023828] irq_exit+0xfc/0x120 [ 35.028398] handle_IPI+0x1d8/0x330 [ 35.033233] gic_handle_irq+0x110/0x1d4 [ 35.038433] el1_irq+0xb4/0x130 [ 35.042917] kmem_cache_alloc+0x3f0/0x418 [ 35.048288] radix_tree_node_alloc+0x50/0xf8 [ 35.053933] __radix_tree_create+0xf8/0x188 [ 35.059484] __radix_tree_insert+0x3c/0x128 [ 35.065035] add_gc_inode+0x90/0x118 [ 35.069967] f2fs_gc+0x1b80/0x2d70 [ 35.074718] f2fs_disable_checkpoint+0x94/0x1d0 [ 35.080621] f2fs_fill_super+0x10c4/0x1b88 [ 35.086088] mount_bdev+0x194/0x1e0 [ 35.090923] f2fs_mount+0x40/0x50 [ 35.095589] mount_fs+0xb4/0x190 [ 35.100159] vfs_kern_mount+0x80/0x1d8 [ 35.105260] do_mount+0x478/0xf18 [ 35.109926] ksys_mount+0x90/0xd0 [ 35.114592] __arm64_sys_mount+0x24/0x38 Signed-off-by: Wuyun Zhao Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 44582a4db513..33affa788588 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -402,6 +402,7 @@ static int do_read_inode(struct inode *inode) /* try to recover cold bit for non-dir inode */ if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) { + f2fs_wait_on_page_writeback(node_page, NODE, true, true); set_cold_node(node_page, false); set_page_dirty(node_page); } From da52f8ade40b032eb8111a0fd514c8ac5f8f0f1b Mon Sep 17 00:00:00 2001 From: Jack Qiu Date: Thu, 18 Jun 2020 12:37:10 +0800 Subject: [PATCH 008/289] f2fs: get the right gc victim section when section has several segments Assume each section has 4 segment: .___________________________. |_Segment0_|_..._|_Segment3_| . . . . .__________. |_section0_| Segment 0~2 has 0 valid block, segment 3 has 512 valid blocks. It will fail if we want to gc section0 in this scenes, because all 4 segments in section0 is not dirty. So we should use dirty section bitmap instead of dirty segment bitmap to get right victim section. Signed-off-by: Jack Qiu Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/gc.c | 39 +++++++++++++++++------------- fs/f2fs/segment.c | 61 +++++++++++++++++++++++++++++++++++++++++++++-- fs/f2fs/segment.h | 8 +++++-- 3 files changed, 88 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5b95d5a146eb..9b6fc61ce649 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -21,6 +21,9 @@ #include "gc.h" #include +static unsigned int count_bits(const unsigned long *addr, + unsigned int offset, unsigned int len); + static int gc_thread_func(void *data) { struct f2fs_sb_info *sbi = data; @@ -187,14 +190,20 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type, if (p->alloc_mode == SSR) { p->gc_mode = GC_GREEDY; - p->dirty_segmap = dirty_i->dirty_segmap[type]; + p->dirty_bitmap = dirty_i->dirty_segmap[type]; p->max_search = dirty_i->nr_dirty[type]; p->ofs_unit = 1; } else { p->gc_mode = select_gc_type(sbi, gc_type); - p->dirty_segmap = dirty_i->dirty_segmap[DIRTY]; - p->max_search = dirty_i->nr_dirty[DIRTY]; p->ofs_unit = sbi->segs_per_sec; + if (__is_large_section(sbi)) { + p->dirty_bitmap = dirty_i->dirty_secmap; + p->max_search = count_bits(p->dirty_bitmap, + 0, MAIN_SECS(sbi)); + } else { + p->dirty_bitmap = dirty_i->dirty_segmap[DIRTY]; + p->max_search = dirty_i->nr_dirty[DIRTY]; + } } /* @@ -365,10 +374,14 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, } while (1) { - unsigned long cost; - unsigned int segno; + unsigned long cost, *dirty_bitmap; + unsigned int unit_no, segno; - segno = find_next_bit(p.dirty_segmap, last_segment, p.offset); + dirty_bitmap = p.dirty_bitmap; + unit_no = find_next_bit(dirty_bitmap, + last_segment / p.ofs_unit, + p.offset / p.ofs_unit); + segno = unit_no * p.ofs_unit; if (segno >= last_segment) { if (sm->last_victim[p.gc_mode]) { last_segment = @@ -381,14 +394,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, } p.offset = segno + p.ofs_unit; - if (p.ofs_unit > 1) { - p.offset -= segno % p.ofs_unit; - nsearched += count_bits(p.dirty_segmap, - p.offset - p.ofs_unit, - p.ofs_unit); - } else { - nsearched++; - } + nsearched++; #ifdef CONFIG_F2FS_CHECK_FS /* @@ -421,9 +427,10 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, next: if (nsearched >= p.max_search) { if (!sm->last_victim[p.gc_mode] && segno <= last_victim) - sm->last_victim[p.gc_mode] = last_victim + 1; + sm->last_victim[p.gc_mode] = + last_victim + p.ofs_unit; else - sm->last_victim[p.gc_mode] = segno + 1; + sm->last_victim[p.gc_mode] = segno + p.ofs_unit; sm->last_victim[p.gc_mode] %= (MAIN_SECS(sbi) * sbi->segs_per_sec); break; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 196f31503511..66eeaba30e91 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -796,6 +796,18 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, } if (!test_and_set_bit(segno, dirty_i->dirty_segmap[t])) dirty_i->nr_dirty[t]++; + + if (__is_large_section(sbi)) { + unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); + unsigned short valid_blocks = + get_valid_blocks(sbi, segno, true); + + f2fs_bug_on(sbi, unlikely(!valid_blocks || + valid_blocks == BLKS_PER_SEC(sbi))); + + if (!IS_CURSEC(sbi, secno)) + set_bit(secno, dirty_i->dirty_secmap); + } } } @@ -803,6 +815,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, enum dirty_type dirty_type) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned short valid_blocks; if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type])) dirty_i->nr_dirty[dirty_type]--; @@ -814,13 +827,26 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) dirty_i->nr_dirty[t]--; - if (get_valid_blocks(sbi, segno, true) == 0) { + valid_blocks = get_valid_blocks(sbi, segno, true); + if (valid_blocks == 0) { clear_bit(GET_SEC_FROM_SEG(sbi, segno), dirty_i->victim_secmap); #ifdef CONFIG_F2FS_CHECK_FS clear_bit(segno, SIT_I(sbi)->invalid_segmap); #endif } + if (__is_large_section(sbi)) { + unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); + + if (!valid_blocks || + valid_blocks == BLKS_PER_SEC(sbi)) { + clear_bit(secno, dirty_i->dirty_secmap); + return; + } + + if (!IS_CURSEC(sbi, secno)) + set_bit(secno, dirty_i->dirty_secmap); + } } } @@ -4293,8 +4319,9 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct free_segmap_info *free_i = FREE_I(sbi); - unsigned int segno = 0, offset = 0; + unsigned int segno = 0, offset = 0, secno; unsigned short valid_blocks; + unsigned short blks_per_sec = BLKS_PER_SEC(sbi); while (1) { /* find dirty segment based on free segmap */ @@ -4313,6 +4340,22 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) __locate_dirty_segment(sbi, segno, DIRTY); mutex_unlock(&dirty_i->seglist_lock); } + + if (!__is_large_section(sbi)) + return; + + mutex_lock(&dirty_i->seglist_lock); + for (segno = 0; segno < MAIN_SECS(sbi); segno += blks_per_sec) { + valid_blocks = get_valid_blocks(sbi, segno, true); + secno = GET_SEC_FROM_SEG(sbi, segno); + + if (!valid_blocks || valid_blocks == blks_per_sec) + continue; + if (IS_CURSEC(sbi, secno)) + continue; + set_bit(secno, dirty_i->dirty_secmap); + } + mutex_unlock(&dirty_i->seglist_lock); } static int init_victim_secmap(struct f2fs_sb_info *sbi) @@ -4349,6 +4392,14 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi) return -ENOMEM; } + if (__is_large_section(sbi)) { + bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi)); + dirty_i->dirty_secmap = f2fs_kvzalloc(sbi, + bitmap_size, GFP_KERNEL); + if (!dirty_i->dirty_secmap) + return -ENOMEM; + } + init_dirty_segmap(sbi); return init_victim_secmap(sbi); } @@ -4775,6 +4826,12 @@ static void destroy_dirty_segmap(struct f2fs_sb_info *sbi) for (i = 0; i < NR_DIRTY_TYPE; i++) discard_dirty_segmap(sbi, i); + if (__is_large_section(sbi)) { + mutex_lock(&dirty_i->seglist_lock); + kvfree(dirty_i->dirty_secmap); + mutex_unlock(&dirty_i->seglist_lock); + } + destroy_victim_secmap(sbi); SM_I(sbi)->dirty_info = NULL; kvfree(dirty_i); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index cba16cca5189..f261e3e6a69b 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -166,8 +166,11 @@ enum { struct victim_sel_policy { int alloc_mode; /* LFS or SSR */ int gc_mode; /* GC_CB or GC_GREEDY */ - unsigned long *dirty_segmap; /* dirty segment bitmap */ - unsigned int max_search; /* maximum # of segments to search */ + unsigned long *dirty_bitmap; /* dirty segment/section bitmap */ + unsigned int max_search; /* + * maximum # of segments/sections + * to search + */ unsigned int offset; /* last scanned bitmap offset */ unsigned int ofs_unit; /* bitmap search unit */ unsigned int min_cost; /* minimum cost */ @@ -266,6 +269,7 @@ enum dirty_type { struct dirty_seglist_info { const struct victim_selection *v_ops; /* victim selction operation */ unsigned long *dirty_segmap[NR_DIRTY_TYPE]; + unsigned long *dirty_secmap; struct mutex seglist_lock; /* lock for segment bitmaps */ int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */ unsigned long *victim_secmap; /* background GC victims */ From ba87a45c23d645b25e1265b477e83cc1b73086e4 Mon Sep 17 00:00:00 2001 From: Wang Xiaojun Date: Wed, 17 Jun 2020 20:30:12 +0800 Subject: [PATCH 009/289] f2fs: use kfree() to free variables allocated by match_strdup() Use kfree() instead of kvfree() to free variables allocated by match_strdup(). Because the memory is allocated with kmalloc inside match_strdup(). Signed-off-by: Wang Xiaojun Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 426cebdd84e5..732652205737 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -348,7 +348,7 @@ static int f2fs_set_qf_name(struct super_block *sb, int qtype, set_opt(sbi, QUOTA); return 0; errout: - kvfree(qname); + kfree(qname); return ret; } @@ -360,7 +360,7 @@ static int f2fs_clear_qf_name(struct super_block *sb, int qtype) f2fs_err(sbi, "Cannot change journaled quota options when quota turned on"); return -EINVAL; } - kvfree(F2FS_OPTION(sbi).s_qf_names[qtype]); + kfree(F2FS_OPTION(sbi).s_qf_names[qtype]); F2FS_OPTION(sbi).s_qf_names[qtype] = NULL; return 0; } @@ -494,10 +494,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "sync")) { F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_disable_roll_forward: set_opt(sbi, DISABLE_ROLL_FORWARD); @@ -654,17 +654,17 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) if (!strcmp(name, "adaptive")) { if (f2fs_sb_has_blkzoned(sbi)) { f2fs_warn(sbi, "adaptive mode is not allowed with zoned block device feature"); - kvfree(name); + kfree(name); return -EINVAL; } F2FS_OPTION(sbi).fs_mode = FS_MODE_ADAPTIVE; } else if (!strcmp(name, "lfs")) { F2FS_OPTION(sbi).fs_mode = FS_MODE_LFS; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_io_size_bits: if (args->from && match_int(args, &arg)) @@ -790,10 +790,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "fs-based")) { F2FS_OPTION(sbi).whint_mode = WHINT_MODE_FS; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_alloc: name = match_strdup(&args[0]); @@ -805,10 +805,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } else if (!strcmp(name, "reuse")) { F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_REUSE; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_fsync: name = match_strdup(&args[0]); @@ -822,10 +822,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_NOBARRIER; } else { - kvfree(name); + kfree(name); return -EINVAL; } - kvfree(name); + kfree(name); break; case Opt_test_dummy_encryption: ret = f2fs_set_test_dummy_encryption(sb, p, &args[0], @@ -1250,7 +1250,7 @@ static void f2fs_put_super(struct super_block *sb) mempool_destroy(sbi->write_io_dummy); #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); destroy_percpu_info(sbi); @@ -1754,7 +1754,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) GFP_KERNEL); if (!org_mount_opt.s_qf_names[i]) { for (j = 0; j < i; j++) - kvfree(org_mount_opt.s_qf_names[j]); + kfree(org_mount_opt.s_qf_names[j]); return -ENOMEM; } } else { @@ -1879,7 +1879,7 @@ skip: #ifdef CONFIG_QUOTA /* Release old quota file names */ for (i = 0; i < MAXQUOTAS; i++) - kvfree(org_mount_opt.s_qf_names[i]); + kfree(org_mount_opt.s_qf_names[i]); #endif /* Update the POSIXACL Flag */ sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | @@ -1900,7 +1900,7 @@ restore_opts: #ifdef CONFIG_QUOTA F2FS_OPTION(sbi).s_jquota_fmt = org_mount_opt.s_jquota_fmt; for (i = 0; i < MAXQUOTAS; i++) { - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); F2FS_OPTION(sbi).s_qf_names[i] = org_mount_opt.s_qf_names[i]; } #endif @@ -3811,7 +3811,7 @@ free_bio_info: free_options: #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) - kvfree(F2FS_OPTION(sbi).s_qf_names[i]); + kfree(F2FS_OPTION(sbi).s_qf_names[i]); #endif fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); kvfree(options); From a8cbf80e9fb175feb40cb56af93b3504f3c68551 Mon Sep 17 00:00:00 2001 From: "Daniel G. Morse" Date: Tue, 26 May 2020 02:55:50 +0100 Subject: [PATCH 010/289] HID: Wiimote: Treat the d-pad as an analogue stick The controllers from the Super Nintendo Classic Edition (AKA the SNES Mini) appear as a Classic Controller Pro when connected to a Wii Remote. All the buttons work as the same, with the d-pad being mapped the same as the d-pad on the Classic Controller Pro. This differs from the behaviour of most controllers with d-pads and no analogue sticks, where the d-pad maps to ABS_HAT1X for left and right, and ABS_HAT1Y for up and down. This patch adds an option to the hid-wiimote module to make the Super Nintendo Classic Controller behave this way. The patch has been tested with a Super Nintendo Classic Controller plugged into a Wii Remote in both with the option both enabled and disabled. When enabled the d-pad acts as the analogue control, and when disabled it acts as it did before the patch was applied. This patch has not been tested with e Wii Classic Controller (either the original or the pro version) as I do not have one of these controllers. Although I have not tested it with these controllers, I think it is likely this patch will also work with the NES Classic Edition Controllers. Signed-off-by: Daniel G. Morse Reviewed-by: David Rheinsberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote-core.c | 5 +++ drivers/hid/hid-wiimote-modules.c | 67 ++++++++++++++++++++----------- drivers/hid/hid-wiimote.h | 2 + 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 92874dbe4d4a..679e142fc850 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1870,6 +1870,11 @@ static const struct hid_device_id wiimote_hid_devices[] = { USB_DEVICE_ID_NINTENDO_WIIMOTE2) }, { } }; + +bool wiimote_dpad_as_analog = false; +module_param_named(dpad_as_analog, wiimote_dpad_as_analog, bool, 0644); +MODULE_PARM_DESC(dpad_as_analog, "Use D-Pad as main analog input"); + MODULE_DEVICE_TABLE(hid, wiimote_hid_devices); static struct hid_driver wiimote_hid_driver = { diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index 2c3925357857..213c58bf2495 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c @@ -1088,12 +1088,28 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext) * is the same as before. */ + static const s8 digital_to_analog[3] = {0x20, 0, -0x20}; + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { - lx = ext[0] & 0x3e; - ly = ext[1] & 0x3e; + if (wiimote_dpad_as_analog) { + lx = digital_to_analog[1 - !(ext[4] & 0x80) + + !(ext[1] & 0x01)]; + ly = digital_to_analog[1 - !(ext[4] & 0x40) + + !(ext[0] & 0x01)]; + } else { + lx = (ext[0] & 0x3e) - 0x20; + ly = (ext[1] & 0x3e) - 0x20; + } } else { - lx = ext[0] & 0x3f; - ly = ext[1] & 0x3f; + if (wiimote_dpad_as_analog) { + lx = digital_to_analog[1 - !(ext[4] & 0x80) + + !(ext[5] & 0x02)]; + ly = digital_to_analog[1 - !(ext[4] & 0x40) + + !(ext[5] & 0x01)]; + } else { + lx = (ext[0] & 0x3f) - 0x20; + ly = (ext[1] & 0x3f) - 0x20; + } } rx = (ext[0] >> 3) & 0x18; @@ -1110,19 +1126,13 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext) rt <<= 1; lt <<= 1; - input_report_abs(wdata->extension.input, ABS_HAT1X, lx - 0x20); - input_report_abs(wdata->extension.input, ABS_HAT1Y, ly - 0x20); + input_report_abs(wdata->extension.input, ABS_HAT1X, lx); + input_report_abs(wdata->extension.input, ABS_HAT1Y, ly); input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20); input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20); input_report_abs(wdata->extension.input, ABS_HAT3X, rt); input_report_abs(wdata->extension.input, ABS_HAT3Y, lt); - input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT], - !(ext[4] & 0x80)); - input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN], - !(ext[4] & 0x40)); input_report_key(wdata->extension.input, wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT], !(ext[4] & 0x20)); @@ -1157,20 +1167,29 @@ static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext) wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR], !(ext[5] & 0x04)); - if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { + if (!wiimote_dpad_as_analog) { input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], - !(ext[1] & 0x01)); + wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT], + !(ext[4] & 0x80)); input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], - !(ext[0] & 0x01)); - } else { - input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], - !(ext[5] & 0x02)); - input_report_key(wdata->extension.input, - wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], - !(ext[5] & 0x01)); + wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN], + !(ext[4] & 0x40)); + + if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { + input_report_key(wdata->extension.input, + wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], + !(ext[1] & 0x01)); + input_report_key(wdata->extension.input, + wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], + !(ext[0] & 0x01)); + } else { + input_report_key(wdata->extension.input, + wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT], + !(ext[5] & 0x02)); + input_report_key(wdata->extension.input, + wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP], + !(ext[5] & 0x01)); + } } input_sync(wdata->extension.input); diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index b2a26a0a8f12..ad4ff837f43e 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h @@ -162,6 +162,8 @@ struct wiimote_data { struct work_struct init_worker; }; +extern bool wiimote_dpad_as_analog; + /* wiimote modules */ enum wiimod_module { From a1f8bc95c33e953e080f72be4b95176dacb423b0 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Mon, 20 Apr 2020 20:35:28 +0800 Subject: [PATCH 011/289] perf annotate: Remove unneeded conversion to bool The '>' expression itself is bool, no need to convert it to bool again. This fixes the following coccicheck warning: tools/perf/ui/browsers/annotate.c:212:30-35: WARNING: conversion to bool not needed here Signed-off-by: Jason Yan Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lore.kernel.org/lkml/20200420123528.11655-1-yanaijie@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 9023267e5643..bd77825fd5a1 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -209,7 +209,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) ui_browser__mark_fused(browser, pcnt_width + 3 + notes->widths.addr + width, from - 1, - to > from ? true : false); + to > from); } } From 387ad33fe710758a8e1b860819a7452bceb4329a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:29 +0200 Subject: [PATCH 012/289] perf tools: Add fake pmu support Add a way to create a pmu event without the actual PMU being in place. This way we can test metrics defined for any processor. The interface is to define fake_pmu in struct parse_events_state data. It will be used only in tests via special interface function added in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 6 ++--- tools/perf/util/parse-events.h | 3 ++- tools/perf/util/parse-events.l | 8 +++++-- tools/perf/util/parse-events.y | 41 ++++++++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3decbb203846..4eb7bd53d048 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1450,7 +1450,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, fprintf(stderr, "' that may result in non-fatal errors\n"); } - pmu = perf_pmu__find(name); + pmu = parse_state->fake_pmu ?: perf_pmu__find(name); if (!pmu) { char *err_str; @@ -1483,7 +1483,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, } } - if (perf_pmu__check_alias(pmu, head_config, &info)) + if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info)) return -EINVAL; if (verbose > 1) { @@ -1516,7 +1516,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms)) return -ENOMEM; - if (perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { + if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { struct evsel_config_term *pos, *tmp; list_for_each_entry_safe(pos, tmp, &config_terms, list) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 1fe23a2f9b36..bf79e1eac7d9 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -127,9 +127,10 @@ struct parse_events_state { int idx; int nr_groups; struct parse_events_error *error; - struct evlist *evlist; + struct evlist *evlist; struct list_head *terms; int stoken; + struct perf_pmu *fake_pmu; }; void parse_events__handle_error(struct parse_events_error *err, int idx, diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 002802e17059..56912c9641f5 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -129,12 +129,16 @@ do { \ yyless(0); \ } while (0) -static int pmu_str_check(yyscan_t scanner) +static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_state) { YYSTYPE *yylval = parse_events_get_lval(scanner); char *text = parse_events_get_text(scanner); yylval->str = strdup(text); + + if (parse_state->fake_pmu) + return PE_PMU_EVENT_FAKE; + switch (perf_pmu__parse_check(text)) { case PMU_EVENT_SYMBOL_PREFIX: return PE_PMU_EVENT_PRE; @@ -376,7 +380,7 @@ r{num_raw_hex} { return raw(yyscanner); } {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } {bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); } {bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); } -{name} { return pmu_str_check(yyscanner); } +{name} { return pmu_str_check(yyscanner, _parse_state); } {name_tag} { return str(yyscanner, PE_NAME); } "/" { BEGIN(config); return '/'; } - { return '-'; } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index acef87d9af58..b9fb91fdc5de 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -69,7 +69,7 @@ static void inc_group_count(struct list_head *list, %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP %token PE_ERROR -%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT +%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %token PE_ARRAY_ALL PE_ARRAY_RANGE %token PE_DRV_CFG_TERM %type PE_VALUE @@ -87,7 +87,7 @@ static void inc_group_count(struct list_head *list, %type PE_MODIFIER_EVENT %type PE_MODIFIER_BP %type PE_EVENT_NAME -%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT +%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %type PE_DRV_CFG_TERM %destructor { free ($$); } %type event_term @@ -356,6 +356,43 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc YYABORT; $$ = list; } +| +PE_PMU_EVENT_FAKE sep_dc +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYABORT; + + err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false); + free($1); + if (err < 0) { + free(list); + YYABORT; + } + $$ = list; +} +| +PE_PMU_EVENT_FAKE opt_pmu_config +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYABORT; + + err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false); + free($1); + parse_events_terms__delete($2); + if (err < 0) { + free(list); + YYABORT; + } + $$ = list; +} value_sym: PE_VALUE_SYM_HW From 34bacc9578de2893ab6301cea89ea001d8e4cf5b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:31 +0200 Subject: [PATCH 013/289] perf tests: Factor check_parse_id function Separating the generic part of check_parse_id function, so it can be used in following changes for the new test. Committer notes: Fix this error: tests/pmu-events.c:413:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] struct parse_events_error error = { 0 }; Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index ab64b4a4e284..82fa69a60ec8 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -390,9 +390,8 @@ static bool is_number(const char *str) return errno == 0 && end_ptr != str; } -static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) +static int check_parse_id(const char *id, struct parse_events_error *error) { - struct parse_events_error error; struct evlist *evlist; int ret; @@ -401,8 +400,18 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) return 0; evlist = evlist__new(); - memset(&error, 0, sizeof(error)); - ret = parse_events(evlist, id, &error); + if (!evlist) + return -ENOMEM; + ret = parse_events(evlist, id, error); + evlist__delete(evlist); + return ret; +} + +static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) +{ + struct parse_events_error error = { .idx = 0, }; + + int ret = check_parse_id(id, &error); if (ret && same_cpu) { pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", pe->metric_name, id, pe->metric_expr); @@ -413,7 +422,6 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) id, pe->metric_name, pe->metric_expr); ret = 0; } - evlist__delete(evlist); free(error.str); free(error.help); free(error.first_str); @@ -474,7 +482,7 @@ static int test_parsing(void) expr__add_id(&ctx, strdup(cur->key), k++); hashmap__for_each_entry((&ctx.ids), cur, bkt) { - if (check_parse_id(cur->key, map == cpus_map, + if (check_parse_cpu(cur->key, map == cpus_map, pe)) ret++; } From 3bf91aa5aa493b2ac24ffcfc93ffe861bf03685f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 3 Jun 2020 12:32:55 -0300 Subject: [PATCH 014/289] perf parse: Provide a way to pass a fake_pmu to parse_events() This is an alternative patch to what Jiri sent that instead of changing all callers to parse_events() for allowing to pass a fake_pmu, provide another function specifically for that. From Jiri's patch: This way it's possible to parse events from PMUs which are not present in the system. It's available only for testing purposes coming in following changes, so all the current users set fake_pmu argument as false. Based-on-a-patch-by: Jiri Olsa Link: http://lore.kernel.org/lkml/20200602214741.1218986-3-jolsa@kernel.org Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 15 ++++++++------- tools/perf/util/parse-events.h | 11 +++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4eb7bd53d048..c4906a6a9f1a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2088,15 +2088,16 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct evlist *evlist, const char *str, - struct parse_events_error *err) +int __parse_events(struct evlist *evlist, const char *str, + struct parse_events_error *err, struct perf_pmu *fake_pmu) { struct parse_events_state parse_state = { - .list = LIST_HEAD_INIT(parse_state.list), - .idx = evlist->core.nr_entries, - .error = err, - .evlist = evlist, - .stoken = PE_START_EVENTS, + .list = LIST_HEAD_INIT(parse_state.list), + .idx = evlist->core.nr_entries, + .error = err, + .evlist = evlist, + .stoken = PE_START_EVENTS, + .fake_pmu = fake_pmu, }; int ret; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index bf79e1eac7d9..f0010095fc8c 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -33,8 +33,15 @@ const char *event_type(int type); int parse_events_option(const struct option *opt, const char *str, int unset); int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset); -int parse_events(struct evlist *evlist, const char *str, - struct parse_events_error *error); +int __parse_events(struct evlist *evlist, const char *str, struct parse_events_error *error, + struct perf_pmu *fake_pmu); + +static inline int parse_events(struct evlist *evlist, const char *str, + struct parse_events_error *err) +{ + return __parse_events(evlist, str, err, NULL); +} + int parse_events_terms(struct list_head *terms, const char *str); int parse_filter(const struct option *opt, const char *str, int unset); int exclude_perf(const struct option *opt, const char *arg, int unset); From e46fc8d9dd352c88fec49b140008958d2dc1efe1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 9 Jun 2020 13:23:24 -0300 Subject: [PATCH 015/289] perf pmu: Add a perf_pmu__fake object to use with __parse_events() When wanting to use the support in __parse_events() for fake pmus, just pass it. Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Jiri Olsa Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 ++ tools/perf/util/pmu.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 93fe72a9dc0b..6d51042044fd 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -26,6 +26,8 @@ #include "strbuf.h" #include "fncache.h" +struct perf_pmu perf_pmu__fake; + struct perf_pmu_format { char *name; int value; diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index f971d9aa4570..44ccbdbb1c37 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -43,6 +43,8 @@ struct perf_pmu { struct list_head list; /* ELEM */ }; +extern struct perf_pmu perf_pmu__fake; + struct perf_pmu_info { const char *unit; const char *metric_expr; From e1c92a7fbbc5668510736624df3028accd6af0ea Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 3 Jun 2020 12:51:15 -0300 Subject: [PATCH 016/289] perf tests: Add another metric parsing test The test goes through all metrics compiled for arch within pmu events and try to parse them. This test is different from 'test_parsing' in that we go through all the events in the current arch, not just one defined for current CPU model. Using 'fake_pmu' to parse events which do not have PMUs defined in the system. Say there's bad change in ivybridge metrics file, like: - a/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json + b/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json @@ -8,7 +8,7 @@ - "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * (( + "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / / (4 * the test fails with (on my kabylake laptop): $ perf test 'Parsing of PMU event table metrics with fake PMUs' -v parsing 'idq_uops_not_delivered.core / / (4 * (( ( cpu_clk_unh... syntax error, line 1 expr__parse failed test child finished with -1 ... The test also defines its own list of metrics and tries to parse them. It's handy for developing. Committer notes: Testing it: $ perf test fake 10: PMU events : 10.4: Parsing of PMU event table metrics with fake PMUs : FAILED! $ perf test -v fake |& tail parsing '(unc_p_freq_trans_cycles / unc_p_clockticks) * 100.' parsing '(unc_m_power_channel_ppd / unc_m_clockticks) * 100.' parsing '(unc_m_power_critical_throttle_cycles / unc_m_clockticks) * 100.' parsing '(unc_m_power_self_refresh / unc_m_clockticks) * 100.' parsing 'idq_uops_not_delivered.core / * (4 * cycles)' syntax error expr__parse failed test child finished with -1 ---- end ---- PMU events subtest 4: FAILED! $ And fix this error: tests/pmu-events.c:437:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] struct parse_events_error error = { 0 }; Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-5-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 117 +++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index 82fa69a60ec8..b66b021476ec 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -390,7 +390,8 @@ static bool is_number(const char *str) return errno == 0 && end_ptr != str; } -static int check_parse_id(const char *id, struct parse_events_error *error) +static int check_parse_id(const char *id, struct parse_events_error *error, + struct perf_pmu *fake_pmu) { struct evlist *evlist; int ret; @@ -402,7 +403,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error) evlist = evlist__new(); if (!evlist) return -ENOMEM; - ret = parse_events(evlist, id, error); + ret = __parse_events(evlist, id, error, fake_pmu); evlist__delete(evlist); return ret; } @@ -411,7 +412,7 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) { struct parse_events_error error = { .idx = 0, }; - int ret = check_parse_id(id, &error); + int ret = check_parse_id(id, &error, NULL); if (ret && same_cpu) { pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", pe->metric_name, id, pe->metric_expr); @@ -429,6 +430,18 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) return ret; } +static int check_parse_fake(const char *id) +{ + struct parse_events_error error = { .idx = 0, }; + int ret = check_parse_id(id, &error, &perf_pmu__fake); + + free(error.str); + free(error.help); + free(error.first_str); + free(error.first_help); + return ret; +} + static void expr_failure(const char *msg, const struct pmu_events_map *map, const struct pmu_event *pe) @@ -498,6 +511,100 @@ static int test_parsing(void) return ret == 0 ? TEST_OK : TEST_SKIP; } +struct test_metric { + const char *str; +}; + +static struct test_metric metrics[] = { + { "(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100." }, + { "imx8_ddr0@read\\-cycles@ * 4 * 4", }, + { "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@ * 4", }, + { "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100", }, + { "(imx8_ddr0@read\\-cycles@ + imx8_ddr0@write\\-cycles@)", }, +}; + +static int metric_parse_fake(const char *str) +{ + struct expr_parse_ctx ctx; + struct hashmap_entry *cur; + double result; + int ret = -1; + size_t bkt; + int i; + + pr_debug("parsing '%s'\n", str); + + expr__ctx_init(&ctx); + if (expr__find_other(str, NULL, &ctx, 0) < 0) { + pr_err("expr__find_other failed\n"); + return -1; + } + + /* + * Add all ids with a made up value. The value may + * trigger divide by zero when subtracted and so try to + * make them unique. + */ + i = 1; + hashmap__for_each_entry((&ctx.ids), cur, bkt) + expr__add_id(&ctx, strdup(cur->key), i++); + + hashmap__for_each_entry((&ctx.ids), cur, bkt) { + if (check_parse_fake(cur->key)) { + pr_err("check_parse_fake failed\n"); + goto out; + } + } + + if (expr__parse(&result, &ctx, str, 1)) + pr_err("expr__parse failed\n"); + else + ret = 0; + +out: + expr__ctx_clear(&ctx); + return ret; +} + +/* + * Parse all the metrics for current architecture, + * or all defined cpus via the 'fake_pmu' + * in parse_events. + */ +static int test_parsing_fake(void) +{ + struct pmu_events_map *map; + struct pmu_event *pe; + unsigned int i, j; + int err = 0; + + for (i = 0; i < ARRAY_SIZE(metrics); i++) { + err = metric_parse_fake(metrics[i].str); + if (err) + return err; + } + + i = 0; + for (;;) { + map = &pmu_events_map[i++]; + if (!map->table) + break; + j = 0; + for (;;) { + pe = &map->table[j++]; + if (!pe->name && !pe->metric_group && !pe->metric_name) + break; + if (!pe->metric_expr) + continue; + err = metric_parse_fake(pe->metric_expr); + if (err) + return err; + } + } + + return 0; +} + static const struct { int (*func)(void); const char *desc; @@ -514,6 +621,10 @@ static const struct { .func = test_parsing, .desc = "Parsing of PMU event table metrics", }, + { + .func = test_parsing_fake, + .desc = "Parsing of PMU event table metrics with fake PMUs", + }, }; const char *test__pmu_events_subtest_get_desc(int subtest) From 8b4468a2107af32b796fa818e5fb76481c39ee5a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:33 +0200 Subject: [PATCH 017/289] perf parse: Factor out parse_groups() function Factor out the parse_groups function, it will be used for new test interface coming in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 9e21aa767e41..d72a565ec483 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -709,14 +709,12 @@ static void metricgroup__free_egroups(struct list_head *group_list) } } -int metricgroup__parse_groups(const struct option *opt, - const char *str, - bool metric_no_group, - bool metric_no_merge, - struct rblist *metric_events) +static int parse_groups(struct evlist *perf_evlist, const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) { struct parse_events_error parse_error; - struct evlist *perf_evlist = *(struct evlist **)opt->value; struct strbuf extra_events; LIST_HEAD(group_list); int ret; @@ -742,6 +740,18 @@ out: return ret; } +int metricgroup__parse_groups(const struct option *opt, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) +{ + struct evlist *perf_evlist = *(struct evlist **)opt->value; + + return parse_groups(perf_evlist, str, metric_no_group, + metric_no_merge, metric_events); +} + bool metricgroup__has_metric(const char *metric) { struct pmu_events_map *map = perf_pmu__find_map(NULL); From 68173bda6ac9d498e450276323f1c10a1d0307ad Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jun 2020 12:50:42 -0300 Subject: [PATCH 018/289] perf tools: Add fake_pmu to parse_group() function Allow to pass fake_pmu in parse_groups function so it can be used in parse_events call. It's will be passed by the upcoming metricgroup__parse_groups_test function. Committer notes: Made it a 'struct perf_pmu' pointer, in line with the changes at the start of this patchkit to avoid statics deep down in library code. Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index d72a565ec483..49e6f7c6fb70 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -712,6 +712,7 @@ static void metricgroup__free_egroups(struct list_head *group_list) static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, + struct perf_pmu *fake_pmu, struct rblist *metric_events) { struct parse_events_error parse_error; @@ -727,7 +728,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, return ret; pr_debug("adding %s\n", extra_events.buf); bzero(&parse_error, sizeof(parse_error)); - ret = parse_events(perf_evlist, extra_events.buf, &parse_error); + ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu); if (ret) { parse_events_print_error(&parse_error, extra_events.buf); goto out; @@ -749,7 +750,7 @@ int metricgroup__parse_groups(const struct option *opt, struct evlist *perf_evlist = *(struct evlist **)opt->value; return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, metric_events); + metric_no_merge, NULL, metric_events); } bool metricgroup__has_metric(const char *metric) From 1381396b0b778c918bf191b1960f92fbd563476d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jun 2020 12:57:47 -0300 Subject: [PATCH 019/289] perf tools: Add map to parse_groups() function For testing purposes we need to pass our own map of events from parse_groups() through metricgroup__add_metric. Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-8-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 49e6f7c6fb70..f89f656c7757 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -597,17 +597,14 @@ static int __metricgroup__add_metric(struct list_head *group_list, static int metricgroup__add_metric(const char *metric, bool metric_no_group, struct strbuf *events, - struct list_head *group_list) + struct list_head *group_list, + struct pmu_events_map *map) { - struct pmu_events_map *map = perf_pmu__find_map(NULL); struct pmu_event *pe; struct egroup *eg; int i, ret; bool has_match = false; - if (!map) - return 0; - for (i = 0; ; i++) { pe = &map->table[i]; @@ -668,7 +665,8 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, static int metricgroup__add_metric_list(const char *list, bool metric_no_group, struct strbuf *events, - struct list_head *group_list) + struct list_head *group_list, + struct pmu_events_map *map) { char *llist, *nlist, *p; int ret = -EINVAL; @@ -683,7 +681,7 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, while ((p = strsep(&llist, ",")) != NULL) { ret = metricgroup__add_metric(p, metric_no_group, events, - group_list); + group_list, map); if (ret == -EINVAL) { fprintf(stderr, "Cannot find metric or group `%s'\n", p); @@ -713,7 +711,8 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, struct perf_pmu *fake_pmu, - struct rblist *metric_events) + struct rblist *metric_events, + struct pmu_events_map *map) { struct parse_events_error parse_error; struct strbuf extra_events; @@ -723,7 +722,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, if (metric_events->nr_entries == 0) metricgroup__rblist_init(metric_events); ret = metricgroup__add_metric_list(str, metric_no_group, - &extra_events, &group_list); + &extra_events, &group_list, map); if (ret) return ret; pr_debug("adding %s\n", extra_events.buf); @@ -748,9 +747,13 @@ int metricgroup__parse_groups(const struct option *opt, struct rblist *metric_events) { struct evlist *perf_evlist = *(struct evlist **)opt->value; + struct pmu_events_map *map = perf_pmu__find_map(NULL); + + if (!map) + return 0; return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, NULL, metric_events); + metric_no_merge, NULL, metric_events, map); } bool metricgroup__has_metric(const char *metric) From f78ac00a8c999f4418e69e606485784fc5ff1d09 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:36 +0200 Subject: [PATCH 020/289] perf tools: Add metricgroup__parse_groups_test function Add the metricgroup__parse_groups_test function. It will be used as test's interface to metric parsing in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-9-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 11 +++++++++++ tools/perf/util/metricgroup.h | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index f89f656c7757..edb13b8b7a57 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -756,6 +756,17 @@ int metricgroup__parse_groups(const struct option *opt, metric_no_merge, NULL, metric_events, map); } +int metricgroup__parse_groups_test(struct evlist *evlist, + struct pmu_events_map *map, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) +{ + return parse_groups(evlist, str, metric_no_group, + metric_no_merge, &perf_pmu__fake, metric_events, map); +} + bool metricgroup__has_metric(const char *metric) { struct pmu_events_map *map = perf_pmu__find_map(NULL); diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 287850bcdeca..426c824e20bf 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -7,8 +7,10 @@ #include struct evsel; +struct evlist; struct option; struct rblist; +struct pmu_events_map; struct metric_event { struct rb_node nd; @@ -34,6 +36,13 @@ int metricgroup__parse_groups(const struct option *opt, bool metric_no_merge, struct rblist *metric_events); +int metricgroup__parse_groups_test(struct evlist *evlist, + struct pmu_events_map *map, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events); + void metricgroup__print(bool metrics, bool groups, char *filter, bool raw, bool details); bool metricgroup__has_metric(const char *metric); From 2cfaa853d8ead2fe4cd82986163b5cea21e300bd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:37 +0200 Subject: [PATCH 021/289] perf tools: Factor out prepare_metric function Factoring out prepare_metric function so it can be used in test interface coming in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-10-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 53 ++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index a7c13a88ecb9..27be7ce2fff4 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -730,25 +730,16 @@ static void print_smi_cost(struct perf_stat_config *config, out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num); } -static void generic_metric(struct perf_stat_config *config, - const char *metric_expr, - struct evsel **metric_events, - char *name, - const char *metric_name, - const char *metric_unit, - int runtime, - int cpu, - struct perf_stat_output_ctx *out, - struct runtime_stat *st) +static int prepare_metric(struct evsel **metric_events, + struct expr_parse_ctx *pctx, + int cpu, + struct runtime_stat *st) { - print_metric_t print_metric = out->print_metric; - struct expr_parse_ctx pctx; - double ratio, scale; - int i; - void *ctxp = out->ctx; + double scale; char *n, *pn; + int i; - expr__ctx_init(&pctx); + expr__ctx_init(pctx); for (i = 0; metric_events[i]; i++) { struct saved_value *v; struct stats *stats; @@ -771,7 +762,7 @@ static void generic_metric(struct perf_stat_config *config, n = strdup(metric_events[i]->name); if (!n) - return; + return -ENOMEM; /* * This display code with --no-merge adds [cpu] postfixes. * These are not supported by the parser. Remove everything @@ -782,11 +773,35 @@ static void generic_metric(struct perf_stat_config *config, *pn = 0; if (metric_total) - expr__add_id(&pctx, n, metric_total); + expr__add_id(pctx, n, metric_total); else - expr__add_id(&pctx, n, avg_stats(stats)*scale); + expr__add_id(pctx, n, avg_stats(stats)*scale); } + return i; +} + +static void generic_metric(struct perf_stat_config *config, + const char *metric_expr, + struct evsel **metric_events, + char *name, + const char *metric_name, + const char *metric_unit, + int runtime, + int cpu, + struct perf_stat_output_ctx *out, + struct runtime_stat *st) +{ + print_metric_t print_metric = out->print_metric; + struct expr_parse_ctx pctx; + double ratio, scale; + int i; + void *ctxp = out->ctx; + + i = prepare_metric(metric_events, &pctx, cpu, st); + if (i < 0) + return; + if (!metric_events[i]) { if (expr__parse(&ratio, &pctx, metric_expr, runtime) == 0) { char *unit; From 9afe5658a6fa89f59f01d2857d78203cc8665f1c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:38 +0200 Subject: [PATCH 022/289] perf tools: Release metric_events rblist We don't release metric_events rblist, add the missing delete hook and call the release before leaving cmd_stat. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-11-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 1 + tools/perf/util/metricgroup.c | 19 +++++++++++++++++++ tools/perf/util/metricgroup.h | 1 + 3 files changed, 21 insertions(+) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 9be020e0098a..911b9c3538a2 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2307,6 +2307,7 @@ out: evlist__delete(evsel_list); + metricgroup__rblist_exit(&stat_config.metric_events); runtime_stat_delete(&stat_config); return status; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index edb13b8b7a57..82fecb5a302d 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -76,11 +76,30 @@ static struct rb_node *metric_event_new(struct rblist *rblist __maybe_unused, return &me->nd; } +static void metric_event_delete(struct rblist *rblist __maybe_unused, + struct rb_node *rb_node) +{ + struct metric_event *me = container_of(rb_node, struct metric_event, nd); + struct metric_expr *expr, *tmp; + + list_for_each_entry_safe(expr, tmp, &me->head, nd) { + free(expr); + } + + free(me); +} + static void metricgroup__rblist_init(struct rblist *metric_events) { rblist__init(metric_events); metric_events->node_cmp = metric_event_cmp; metric_events->node_new = metric_event_new; + metric_events->node_delete = metric_event_delete; +} + +void metricgroup__rblist_exit(struct rblist *metric_events) +{ + rblist__exit(metric_events); } struct egroup { diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 426c824e20bf..8315bd1a7da4 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -47,4 +47,5 @@ void metricgroup__print(bool metrics, bool groups, char *filter, bool raw, bool details); bool metricgroup__has_metric(const char *metric); int arch_get_runtimeparam(void); +void metricgroup__rblist_exit(struct rblist *metric_events); #endif From 6d432c4c8aa5660d8f9f43326db8350b48dcb6f5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:39 +0200 Subject: [PATCH 023/289] perf tools: Add test_generic_metric function Adding test_generic_metric that prepares and runs given metric over the data from struct runtime_stat object. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-12-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 14 ++++++++++++++ tools/perf/util/stat.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 27be7ce2fff4..8fdef47005e6 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -842,6 +842,20 @@ static void generic_metric(struct perf_stat_config *config, expr__ctx_clear(&pctx); } +double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st) +{ + struct expr_parse_ctx pctx; + double ratio; + + if (prepare_metric(mexp->metric_events, &pctx, cpu, st) < 0) + return 0.; + + if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) + return 0.; + + return ratio; +} + void perf_stat__print_shadow_stats(struct perf_stat_config *config, struct evsel *evsel, double avg, int cpu, diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index f75ae679eb28..6911c7249199 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -230,4 +230,7 @@ perf_evlist__print_counters(struct evlist *evlist, struct target *_target, struct timespec *ts, int argc, const char **argv); + +struct metric_expr; +double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st); #endif From 0a507af9c681ac2adedc5fe1b2d534e27be85446 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:40 +0200 Subject: [PATCH 024/289] perf tests: Add parse metric test for ipc metric Adding new test that process metrics code and checks the expected results. Starting with easy ipc metric. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # # perf test -v "Parse and process metrics" 67: Parse and process metrics : --- start --- test child forked, pid 103402 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:135:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-13-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 + tools/perf/tests/parse-metric.c | 145 ++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 151 insertions(+) create mode 100644 tools/perf/tests/parse-metric.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index cd00498a5dce..84352fc49a20 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -59,6 +59,7 @@ perf-y += genelf.o perf-y += api-io.o perf-y += demangle-java-test.o perf-y += pfm.o +perf-y += parse-metric.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index da5b6cc23f25..d328caaba45d 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -337,6 +337,10 @@ static struct test generic_tests[] = { .desc = "Demangle Java", .func = test__demangle_java, }, + { + .desc = "Parse and process metrics", + .func = test__parse_metric, + }, { .func = NULL, }, diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c new file mode 100644 index 000000000000..79d956dc6a74 --- /dev/null +++ b/tools/perf/tests/parse-metric.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include "metricgroup.h" +#include "tests.h" +#include "pmu-events/pmu-events.h" +#include "evlist.h" +#include "rblist.h" +#include "debug.h" +#include "expr.h" +#include "stat.h" + +static struct pmu_event pme_test[] = { +{ + .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", + .metric_name = "IPC", +}, +}; + +static struct pmu_events_map map = { + .cpuid = "test", + .version = "1", + .type = "core", + .table = pme_test, +}; + +struct value { + const char *event; + u64 val; +}; + +static u64 find_value(const char *name, struct value *values) +{ + struct value *v = values; + + while (v->event) { + if (!strcmp(name, v->event)) + return v->val; + v++; + }; + return 0; +} + +static void load_runtime_stat(struct runtime_stat *st, struct evlist *evlist, + struct value *vals) +{ + struct evsel *evsel; + u64 count; + + evlist__for_each_entry(evlist, evsel) { + count = find_value(evsel->name, vals); + perf_stat__update_shadow_stats(evsel, count, 0, st); + } +} + +static double compute_single(struct rblist *metric_events, struct evlist *evlist, + struct runtime_stat *st) +{ + struct evsel *evsel = evlist__first(evlist); + struct metric_event *me; + + me = metricgroup__lookup(metric_events, evsel, false); + if (me != NULL) { + struct metric_expr *mexp; + + mexp = list_first_entry(&me->head, struct metric_expr, nd); + return test_generic_metric(mexp, 0, st); + } + return 0.; +} + +static int compute_metric(const char *name, struct value *vals, double *ratio) +{ + struct rblist metric_events = { + .nr_entries = 0, + }; + struct perf_cpu_map *cpus; + struct runtime_stat st; + struct evlist *evlist; + int err; + + /* + * We need to prepare evlist for stat mode running on CPU 0 + * because that's where all the stats are going to be created. + */ + evlist = evlist__new(); + if (!evlist) + return -ENOMEM; + + cpus = perf_cpu_map__new("0"); + if (!cpus) + return -ENOMEM; + + perf_evlist__set_maps(&evlist->core, cpus, NULL); + + /* Parse the metric into metric_events list. */ + err = metricgroup__parse_groups_test(evlist, &map, name, + false, false, + &metric_events); + + TEST_ASSERT_VAL("failed to parse metric", err == 0); + + if (perf_evlist__alloc_stats(evlist, false)) + return -1; + + /* Load the runtime stats with given numbers for events. */ + runtime_stat__init(&st); + load_runtime_stat(&st, evlist, vals); + + /* And execute the metric */ + *ratio = compute_single(&metric_events, evlist, &st); + + /* ... clenup. */ + metricgroup__rblist_exit(&metric_events); + runtime_stat__exit(&st); + perf_evlist__free_stats(evlist); + perf_cpu_map__put(cpus); + evlist__delete(evlist); + return 0; +} + +static int test_ipc(void) +{ + double ratio; + struct value vals[] = { + { .event = "inst_retired.any", .val = 300 }, + { .event = "cpu_clk_unhalted.thread", .val = 200 }, + { .event = NULL, }, + }; + + TEST_ASSERT_VAL("failed to compute metric", + compute_metric("IPC", vals, &ratio) == 0); + + TEST_ASSERT_VAL("IPC failed, wrong ratio", + ratio == 1.5); + return 0; +} + +int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) +{ + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + return 0; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 76a4e352eaaf..4447a516c689 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -121,6 +121,7 @@ int test__demangle_java(struct test *test, int subtest); int test__pfm(struct test *test, int subtest); const char *test__pfm_subtest_get_desc(int subtest); int test__pfm_subtest_get_nr(void); +int test__parse_metric(struct test *test, int subtest); bool test__bp_signal_is_supported(void); bool test__bp_account_is_supported(void); From 218ca91df47712a7b2b5a554e39c4a2c819a9e86 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:41 +0200 Subject: [PATCH 025/289] perf tests: Add parse metric test for frontend metric Adding new metric test for frontend metric. It's stolen from x86 pmu events. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # perf test -v "Parse and process metrics" # 67: Parse and process metrics : --- start --- test child forked, pid 104881 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W metric expr idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * ( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) ))) for Frontend_Bound_SMT found event cpu_clk_unhalted.one_thread_active found event cpu_clk_unhalted.ref_xclk found event idq_uops_not_delivered.core found event cpu_clk_unhalted.thread adding {cpu_clk_unhalted.one_thread_active,cpu_clk_unhalted.ref_xclk,idq_uops_not_delivered.core,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:154:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/parse-metric.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 79d956dc6a74..8c48251425e1 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -17,6 +17,11 @@ static struct pmu_event pme_test[] = { .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", .metric_name = "IPC", }, +{ + .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * " + "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))", + .metric_name = "Frontend_Bound_SMT", +}, }; static struct pmu_events_map map = { @@ -138,8 +143,28 @@ static int test_ipc(void) return 0; } +static int test_frontend(void) +{ + double ratio; + struct value vals[] = { + { .event = "idq_uops_not_delivered.core", .val = 300 }, + { .event = "cpu_clk_unhalted.thread", .val = 200 }, + { .event = "cpu_clk_unhalted.one_thread_active", .val = 400 }, + { .event = "cpu_clk_unhalted.ref_xclk", .val = 600 }, + { .event = NULL, }, + }; + + TEST_ASSERT_VAL("failed to compute metric", + compute_metric("Frontend_Bound_SMT", vals, &ratio) == 0); + + TEST_ASSERT_VAL("Frontend_Bound_SMT failed, wrong ratio", + ratio == 0.45); + return 0; +} + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) { TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + TEST_ASSERT_VAL("frontend failed", test_frontend() == 0); return 0; } From afdd63f5933b3c970438e8ab6bb0cd9f392f3bf6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2020 11:39:16 -0300 Subject: [PATCH 026/289] perf script: Fixup some evsel/evlist method names Fixups related to the introduction of libperf, where the perf_{evsel,evlist}__ prefix is reserved for functions operating on struct perf_{evsel,evlist}. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 181d65e5a450..1ff6a8a8dde5 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -388,7 +388,7 @@ static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char * return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false); } -static int perf_evsel__check_attr(struct evsel *evsel, struct perf_session *session) +static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) { struct perf_event_attr *attr = &evsel->core.attr; bool allow_user_set; @@ -522,7 +522,7 @@ static int perf_session__check_output_opt(struct perf_session *session) } if (evsel && output[j].fields && - perf_evsel__check_attr(evsel, session)) + evsel__check_attr(evsel, session)) return -1; if (evsel == NULL) @@ -1692,7 +1692,7 @@ struct perf_script { int range_num; }; -static int perf_evlist__max_name_len(struct evlist *evlist) +static int evlist__max_name_len(struct evlist *evlist) { struct evsel *evsel; int max = 0; @@ -1875,7 +1875,7 @@ static void process_event(struct perf_script *script, const char *evname = evsel__name(evsel); if (!script->name_width) - script->name_width = perf_evlist__max_name_len(script->session->evlist); + script->name_width = evlist__max_name_len(script->session->evlist); fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]"); } @@ -2120,7 +2120,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, } if (evsel->core.attr.sample_type) { - err = perf_evsel__check_attr(evsel, scr->session); + err = evsel__check_attr(evsel, scr->session); if (err) return err; } From 3e21a28a01e227726456a51933ed004c2df31850 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 10 Jun 2020 16:58:22 -0700 Subject: [PATCH 027/289] perf expr: Add d_ratio operation d_ratio avoids division by 0 yielding infinity, such as when a counter doesn't get scheduled. An example usage is: { "BriefDescription": "DCache L1 misses", "MetricExpr": "d_ratio(MEM_LOAD_RETIRED.L1_MISS, MEM_LOAD_RETIRED.L1_HIT + MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT)", "MetricGroup": "DCache;DCache_L1", "MetricName": "DCache_L1_Miss", "ScaleUnit": "100%", } Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Kajol Jain Cc: Mark Rutland Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200610235823.52557-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/expr.c | 2 ++ tools/perf/util/expr.l | 1 + tools/perf/util/expr.y | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 1cb02ca2b15f..c4877b36ab58 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -39,6 +39,8 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, "1+1 if 3*4 else 0", 2); ret |= test(&ctx, "1.1 + 2.1", 3.2); ret |= test(&ctx, ".1 + 2.", 2.1); + ret |= test(&ctx, "d_ratio(1, 2)", 0.5); + ret |= test(&ctx, "d_ratio(2.5, 0)", 0); if (ret) return ret; diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index f397bf8b1a48..298d86660a96 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -100,6 +100,7 @@ symbol ({spec}|{sym})+ } } +d_ratio { return D_RATIO; } max { return MAX; } min { return MIN; } if { return IF; } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index bf3e898e3055..fe145344bb39 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -10,6 +10,14 @@ #include "smt.h" #include +static double d_ratio(double val0, double val1) +{ + if (val1 == 0) { + return 0; + } + return val0 / val1; +} + %} %define api.pure full @@ -28,7 +36,7 @@ %token NUMBER %token ID %destructor { free ($$); } -%token MIN MAX IF ELSE SMT_ON +%token MIN MAX IF ELSE SMT_ON D_RATIO %left MIN MAX IF %left '|' %left '^' @@ -64,7 +72,8 @@ other: ID } | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' - +| +D_RATIO all_expr: if_expr { *final_val = $1; } ; @@ -105,6 +114,7 @@ expr: NUMBER | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; } | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; } | SMT_ON { $$ = smt_on() > 0; } + | D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); } ; %% From ff1a12f962dff5b490c5ce1c2c4bcd0bf3bf517d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 10 Jun 2020 16:58:23 -0700 Subject: [PATCH 028/289] perf expr: Add < and > operators These are broadly useful but required to handle TMA metrics. For example encoding Ports_Utilization from: https://download.01.org/perfmon/TMA_Metrics.csv requires '<'. { "BriefDescription": "This metric estimates fraction of cycles the CPU performance was potentially limited due to Core computation issues (non divider-related). Two distinct categories can be attributed into this metric: (1) heavy data-dependency among contiguous instructions would manifest in this metric - such cases are often referred to as low Instruction Level Parallelism (ILP). (2) Contention on some hardware execution unit other than Divider. For example; when there are too many multiply operations.", "MetricExpr": "( ( cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ + cpu@EXE_ACTIVITY.1_PORTS_UTIL@ + ( cpu@EXE_ACTIVITY.2_PORTS_UTIL@ * ( ( ( cpu@UOPS_RETIRED.RETIRE_SLOTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) ) / ( ( 4.000000 ) + 1.000000 ) ) ) ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) if ( cpu@ARITH.DIVIDER_ACTIVE\\,cmask\\=1@ < cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ ) else ( ( cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ + cpu@EXE_ACTIVITY.1_PORTS_UTIL@ + ( cpu@EXE_ACTIVITY.2_PORTS_UTIL@ * ( ( ( cpu@UOPS_RETIRED.RETIRE_SLOTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) ) / ( ( 4.000000 ) + 1.000000 ) ) ) ) - cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) )", "MetricGroup": "Topdown_Group_Ports_Utilization", "MetricName": "Topdown_Metric_Ports_Utilization" }, Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Kajol Jain Cc: Mark Rutland Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200610235823.52557-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/expr.c | 6 ++++++ tools/perf/util/expr.l | 2 ++ tools/perf/util/expr.y | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index c4877b36ab58..b7e5ef3007fc 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -41,6 +41,12 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, ".1 + 2.", 2.1); ret |= test(&ctx, "d_ratio(1, 2)", 0.5); ret |= test(&ctx, "d_ratio(2.5, 0)", 0); + ret |= test(&ctx, "1.1 < 2.2", 1); + ret |= test(&ctx, "2.2 > 1.1", 1); + ret |= test(&ctx, "1.1 < 1.1", 0); + ret |= test(&ctx, "2.2 > 2.2", 0); + ret |= test(&ctx, "2.2 < 1.1", 0); + ret |= test(&ctx, "1.1 > 2.2", 0); if (ret) return ret; diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index 298d86660a96..13e5e3c75f56 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -111,6 +111,8 @@ else { return ELSE; } "|" { return '|'; } "^" { return '^'; } "&" { return '&'; } +"<" { return '<'; } +">" { return '>'; } "-" { return '-'; } "+" { return '+'; } "*" { return '*'; } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index fe145344bb39..5fcb98800f9c 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -41,6 +41,7 @@ static double d_ratio(double val0, double val1) %left '|' %left '^' %left '&' +%left '<' '>' %left '-' '+' %left '*' '/' '%' %left NEG NOT @@ -73,7 +74,7 @@ other: ID | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' | -D_RATIO +'<' | '>' | D_RATIO all_expr: if_expr { *final_val = $1; } ; @@ -94,6 +95,8 @@ expr: NUMBER | expr '|' expr { $$ = (long)$1 | (long)$3; } | expr '&' expr { $$ = (long)$1 & (long)$3; } | expr '^' expr { $$ = (long)$1 ^ (long)$3; } + | expr '<' expr { $$ = $1 < $3; } + | expr '>' expr { $$ = $1 > $3; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } From 47446212832871e66f3b5fbf021c148eced2e24c Mon Sep 17 00:00:00 2001 From: Mike Leach Date: Tue, 16 Jun 2020 17:40:41 +0100 Subject: [PATCH 029/289] perf cs-etm: Allow no CoreSight sink to be specified on command line Adjust the handling of the session sink selection to allow no sink to be selected on the command line. This then forwards the sink selection to the CoreSight infrastructure which will attempt to select a sink based on the default sink select priorities. Signed-off-by: Mike Leach Tested-by: Leo Yan Cc: Mathieu Poirier Cc: Peter Zijlstra Cc: Suzuki Poulouse Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index cea5e33d61d2..cad7bf783413 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -243,10 +243,10 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu, } /* - * No sink was provided on the command line - for _now_ treat - * this as an error. + * No sink was provided on the command line - allow the CoreSight + * system to look for a default */ - return ret; + return 0; } static int cs_etm_recording_options(struct auxtrace_record *itr, From c1b4745b48b3c5a29df6ef2b68384e7cccdc3691 Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Jun 2020 17:01:53 +0800 Subject: [PATCH 030/289] perf pmu: List kernel supplied event aliases for arm64 In commit dc098b35b56f ("perf list: List kernel supplied event aliases"), the aliases for events are supplied in addition to CPU event in perf list. This relies on the name of the core PMU being "cpu", which is not the case for arm64, so arm64 has always missed this. Use generic is_pmu_core() helper which takes account of arm64 to make this feature work for arm64 (and possibly other archs). Sample, before: armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] after: br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] Signed-off-by: John Garry Acked-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Mark Rutland Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1592384514-119954-2-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 6d51042044fd..d039879bd914 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1477,7 +1477,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, list_for_each_entry(alias, &pmu->aliases, list) { char *name = alias->desc ? alias->name : format_alias(buf, sizeof(buf), pmu, alias); - bool is_cpu = !strcmp(pmu->name, "cpu"); + bool is_cpu = is_pmu_core(pmu->name); if (alias->deprecated && !deprecated) continue; From ce0dc7d22271fa7eac3875fc9b57772742b8245e Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Jun 2020 17:01:54 +0800 Subject: [PATCH 031/289] perf pmu: Improve CPU core PMU HW event list ordering For perf list, the CPU core PMU HW event ordering is such that not all events may will be listed adjacent - consider this example: $ tools/perf/perf list List of pre-defined events (to be used in -e): duration_time [Tool event] branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] cstate_core/c3-residency/ [Kernel PMU event] cstate_core/c6-residency/ [Kernel PMU event] cstate_core/c7-residency/ [Kernel PMU event] cstate_pkg/c2-residency/ [Kernel PMU event] cstate_pkg/c3-residency/ [Kernel PMU event] cstate_pkg/c6-residency/ [Kernel PMU event] cstate_pkg/c7-residency/ [Kernel PMU event] cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] cycles-t OR cpu/cycles-t/ [Kernel PMU event] el-abort OR cpu/el-abort/ [Kernel PMU event] el-capacity OR cpu/el-capacity/ [Kernel PMU event] Notice in the above example how the cstate_core PMU events are mixed in the middle of the CPU core events. For my arm64 platform, all the uncore events get mixed in, making the list very disorganised: page-faults OR faults [Software event] task-clock [Software event] duration_time [Tool event] L1-dcache-load-misses [Hardware cache event] L1-dcache-loads [Hardware cache event] L1-icache-load-misses [Hardware cache event] L1-icache-loads [Hardware cache event] branch-load-misses [Hardware cache event] branch-loads [Hardware cache event] dTLB-load-misses [Hardware cache event] dTLB-loads [Hardware cache event] iTLB-load-misses [Hardware cache event] iTLB-loads [Hardware cache event] br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] br_mis_pred_retired OR armv8_pmuv3_0/br_mis_pred_retired/ [Kernel PMU event] br_pred OR armv8_pmuv3_0/br_pred/ [Kernel PMU event] br_retired OR armv8_pmuv3_0/br_retired/ [Kernel PMU event] br_return_retired OR armv8_pmuv3_0/br_return_retired/ [Kernel PMU event] bus_access OR armv8_pmuv3_0/bus_access/ [Kernel PMU event] bus_cycles OR armv8_pmuv3_0/bus_cycles/ [Kernel PMU event] cid_write_retired OR armv8_pmuv3_0/cid_write_retired/ [Kernel PMU event] cpu_cycles OR armv8_pmuv3_0/cpu_cycles/ [Kernel PMU event] dtlb_walk OR armv8_pmuv3_0/dtlb_walk/ [Kernel PMU event] exc_return OR armv8_pmuv3_0/exc_return/ [Kernel PMU event] exc_taken OR armv8_pmuv3_0/exc_taken/ [Kernel PMU event] hisi_sccl1_ddrc0/act_cmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_rcmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_rd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_wcmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_wr/ [Kernel PMU event] hisi_sccl1_ddrc0/pre_cmd/ [Kernel PMU event] hisi_sccl1_ddrc0/rnk_chg/ [Kernel PMU event] ... hisi_sccl7_l3c21/wr_hit_cpipe/ [Kernel PMU event] hisi_sccl7_l3c21/wr_hit_spipe/ [Kernel PMU event] hisi_sccl7_l3c21/wr_spipe/ [Kernel PMU event] inst_retired OR armv8_pmuv3_0/inst_retired/ [Kernel PMU event] inst_spec OR armv8_pmuv3_0/inst_spec/ [Kernel PMU event] itlb_walk OR armv8_pmuv3_0/itlb_walk/ [Kernel PMU event] l1d_cache OR armv8_pmuv3_0/l1d_cache/ [Kernel PMU event] l1d_cache_refill OR armv8_pmuv3_0/l1d_cache_refill/ [Kernel PMU event] l1d_cache_wb OR armv8_pmuv3_0/l1d_cache_wb/ [Kernel PMU event] l1d_tlb OR armv8_pmuv3_0/l1d_tlb/ [Kernel PMU event] l1d_tlb_refill OR armv8_pmuv3_0/l1d_tlb_refill/ [Kernel PMU event] So the events are list alphabetically. However, CPU core event listing is special from commit dc098b35b56f ("perf list: List kernel supplied event aliases"), in that the alias and full event is shown (in that order). As such, the core events may become sparse. Improve this by grouping the CPU core events and ensure that they are listed first for kernel PMU events. For the first example, above, this now looks like: duration_time [Tool event] branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] cycles-t OR cpu/cycles-t/ [Kernel PMU event] el-abort OR cpu/el-abort/ [Kernel PMU event] el-capacity OR cpu/el-capacity/ [Kernel PMU event] el-commit OR cpu/el-commit/ [Kernel PMU event] el-conflict OR cpu/el-conflict/ [Kernel PMU event] el-start OR cpu/el-start/ [Kernel PMU event] instructions OR cpu/instructions/ [Kernel PMU event] mem-loads OR cpu/mem-loads/ [Kernel PMU event] mem-stores OR cpu/mem-stores/ [Kernel PMU event] ref-cycles OR cpu/ref-cycles/ [Kernel PMU event] topdown-fetch-bubbles OR cpu/topdown-fetch-bubbles/ [Kernel PMU event] topdown-recovery-bubbles OR cpu/topdown-recovery-bubbles/ [Kernel PMU event] topdown-slots-issued OR cpu/topdown-slots-issued/ [Kernel PMU event] topdown-slots-retired OR cpu/topdown-slots-retired/ [Kernel PMU event] topdown-total-slots OR cpu/topdown-total-slots/ [Kernel PMU event] tx-abort OR cpu/tx-abort/ [Kernel PMU event] tx-capacity OR cpu/tx-capacity/ [Kernel PMU event] tx-commit OR cpu/tx-commit/ [Kernel PMU event] tx-conflict OR cpu/tx-conflict/ [Kernel PMU event] tx-start OR cpu/tx-start/ [Kernel PMU event] cstate_core/c3-residency/ [Kernel PMU event] cstate_core/c6-residency/ [Kernel PMU event] cstate_core/c7-residency/ [Kernel PMU event] cstate_pkg/c2-residency/ [Kernel PMU event] cstate_pkg/c3-residency/ [Kernel PMU event] cstate_pkg/c6-residency/ [Kernel PMU event] cstate_pkg/c7-residency/ [Kernel PMU event] Signed-off-by: John Garry Acked-by: Jiri Olsa Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Mark Rutland Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1592384514-119954-3-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d039879bd914..f1688e1f6ed7 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1402,6 +1402,7 @@ struct sevent { char *pmu; char *metric_expr; char *metric_name; + int is_cpu; }; static int cmp_sevent(const void *a, const void *b) @@ -1418,6 +1419,11 @@ static int cmp_sevent(const void *a, const void *b) if (n) return n; } + + /* Order CPU core events to be first */ + if (as->is_cpu != bs->is_cpu) + return bs->is_cpu - as->is_cpu; + return strcmp(as->name, bs->name); } @@ -1509,6 +1515,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, aliases[j].pmu = pmu->name; aliases[j].metric_expr = alias->metric_expr; aliases[j].metric_name = alias->metric_name; + aliases[j].is_cpu = is_cpu; j++; } if (pmu->selectable && From e251abee87cf9c49a2ec1b143bd71f92b71557c1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:16:20 -0300 Subject: [PATCH 032/289] perf evlist: Fix the class prefix for 'struct evlist' 'add' evsel methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 4 ++-- tools/perf/builtin-stat.c | 16 +++++++--------- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 3 +-- tools/perf/util/evlist.c | 17 +++++++---------- tools/perf/util/evlist.h | 17 ++++++++--------- 7 files changed, 27 insertions(+), 34 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 95a77058023e..460945ded6dd 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1319,7 +1319,7 @@ static struct evlist *kvm_live_event_list(void) *name = '\0'; name++; - if (perf_evlist__add_newtp(evlist, sys, name, NULL)) { + if (evlist__add_newtp(evlist, sys, name, NULL)) { pr_err("Failed to add %s tracepoint to the list\n", *events_tp); free(tp); goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e108d90ae2ed..1eeb58eac5df 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -852,7 +852,7 @@ static int record__open(struct record *rec) * event synthesis. */ if (opts->initial_delay || target__has_cpu(&opts->target)) { - if (perf_evlist__add_dummy(evlist)) + if (evlist__add_dummy(evlist)) return -ENOMEM; /* Disable tracking of mmaps on lead event. */ @@ -2722,7 +2722,7 @@ int cmd_record(int argc, const char **argv) record.opts.tail_synthesize = true; if (rec->evlist->core.nr_entries == 0 && - __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { + __evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { pr_err("Not enough memory for event selector list\n"); goto out; } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 911b9c3538a2..922d9961ba98 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1679,19 +1679,17 @@ static int add_default_attributes(void) if (target__has_cpu(&target)) default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; - if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) + if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0) return -1; if (pmu_have_event("cpu", "stalled-cycles-frontend")) { - if (perf_evlist__add_default_attrs(evsel_list, - frontend_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0) return -1; } if (pmu_have_event("cpu", "stalled-cycles-backend")) { - if (perf_evlist__add_default_attrs(evsel_list, - backend_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0) return -1; } - if (perf_evlist__add_default_attrs(evsel_list, default_attrs1) < 0) + if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0) return -1; } @@ -1701,21 +1699,21 @@ static int add_default_attributes(void) return 0; /* Append detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) return -1; if (detailed_run < 2) return 0; /* Append very detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) return -1; if (detailed_run < 3) return 0; /* Append very, very detailed run extra attributes: */ - return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); + return evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); } static const char * const stat_record_usage[] = { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 13889d73f8dd..994c230027bb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1627,7 +1627,7 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; if (!top.evlist->core.nr_entries && - perf_evlist__add_default(top.evlist) < 0) { + evlist__add_default(top.evlist) < 0) { pr_err("Not enough memory for event selector list\n"); goto out_delete_evlist; } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 4cbb64edc998..b9c8b40c7135 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3917,8 +3917,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) } if (trace->sched && - perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", - trace__sched_stat_runtime)) + evlist__add_newtp(evlist, "sched", "sched_stat_runtime", trace__sched_stat_runtime)) goto out_error_sched_stat_runtime; /* * If a global cgroup was set, apply it to all the events without an diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 173b4f0e0e6e..d574e774073c 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -79,7 +79,7 @@ struct evlist *perf_evlist__new_default(void) { struct evlist *evlist = evlist__new(); - if (evlist && perf_evlist__add_default(evlist)) { + if (evlist && evlist__add_default(evlist)) { evlist__delete(evlist); evlist = NULL; } @@ -91,7 +91,7 @@ struct evlist *perf_evlist__new_dummy(void) { struct evlist *evlist = evlist__new(); - if (evlist && perf_evlist__add_dummy(evlist)) { + if (evlist && evlist__add_dummy(evlist)) { evlist__delete(evlist); evlist = NULL; } @@ -231,7 +231,7 @@ void perf_evlist__set_leader(struct evlist *evlist) } } -int __perf_evlist__add_default(struct evlist *evlist, bool precise) +int __evlist__add_default(struct evlist *evlist, bool precise) { struct evsel *evsel = evsel__new_cycles(precise); @@ -242,7 +242,7 @@ int __perf_evlist__add_default(struct evlist *evlist, bool precise) return 0; } -int perf_evlist__add_dummy(struct evlist *evlist) +int evlist__add_dummy(struct evlist *evlist) { struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, @@ -258,8 +258,7 @@ int perf_evlist__add_dummy(struct evlist *evlist) return 0; } -static int evlist__add_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) +static int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { struct evsel *evsel, *n; LIST_HEAD(head); @@ -282,8 +281,7 @@ out_delete_partial_list: return -1; } -int __perf_evlist__add_default_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { size_t i; @@ -322,8 +320,7 @@ perf_evlist__find_tracepoint_by_name(struct evlist *evlist, return NULL; } -int perf_evlist__add_newtp(struct evlist *evlist, - const char *sys, const char *name, void *handler) +int evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler) { struct evsel *evsel = evsel__newtp(sys, name); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index b6f325dfb4d2..94f210d2f313 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -92,20 +92,20 @@ void evlist__delete(struct evlist *evlist); void evlist__add(struct evlist *evlist, struct evsel *entry); void evlist__remove(struct evlist *evlist, struct evsel *evsel); -int __perf_evlist__add_default(struct evlist *evlist, bool precise); +int __evlist__add_default(struct evlist *evlist, bool precise); -static inline int perf_evlist__add_default(struct evlist *evlist) +static inline int evlist__add_default(struct evlist *evlist) { - return __perf_evlist__add_default(evlist, true); + return __evlist__add_default(evlist, true); } -int __perf_evlist__add_default_attrs(struct evlist *evlist, +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); -#define perf_evlist__add_default_attrs(evlist, array) \ - __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) +#define evlist__add_default_attrs(evlist, array) \ + __evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) -int perf_evlist__add_dummy(struct evlist *evlist); +int evlist__add_dummy(struct evlist *evlist); int perf_evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr, @@ -116,8 +116,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, struct target *target); void perf_evlist__stop_sb_thread(struct evlist *evlist); -int perf_evlist__add_newtp(struct evlist *evlist, - const char *sys, const char *name, void *handler); +int evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler); int __evlist__set_tracepoints_handlers(struct evlist *evlist, const struct evsel_str_handler *assocs, From d1f249ecbd8413cb15f3bbad403253a183aa1d81 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:19:46 -0300 Subject: [PATCH 033/289] perf evlist: Fix the class prefix for 'struct evlist' strerror methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/code-reading.c | 2 +- tools/perf/util/evlist.c | 5 ++--- tools/perf/util/evlist.h | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b9c8b40c7135..a333a9a64f27 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -4149,11 +4149,11 @@ out_error_raw_syscalls: goto out_error; out_error_mmap: - perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); goto out_error; out_error_open: - perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); out_error: fprintf(trace->output, "%s\n", errbuf); diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 6fe221d31f07..035c9123549a 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -678,7 +678,7 @@ static int do_test_code_reading(bool try_kcore) if (verbose > 0) { char errbuf[512]; - perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); pr_debug("perf_evlist__open() failed!\n%s\n", errbuf); } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d574e774073c..4b7f9f9b1588 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1461,8 +1461,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, return evsel__parse_sample_timestamp(evsel, event, timestamp); } -int perf_evlist__strerror_open(struct evlist *evlist, - int err, char *buf, size_t size) +int evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size) { int printed, value; char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); @@ -1515,7 +1514,7 @@ out_default: return 0; } -int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) +int evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) { char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); int pages_attempted = evlist->core.mmap_len / 1024, pages_max_per_user, printed = 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 94f210d2f313..a832639a8221 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -257,8 +257,8 @@ static inline struct evsel *evlist__last(struct evlist *evlist) return container_of(evsel, struct evsel, core); } -int perf_evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); -int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); +int evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); +int evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); bool perf_evlist__can_select_event(struct evlist *evlist, const char *str); void perf_evlist__to_front(struct evlist *evlist, From b3c2cc2bd21d1d97b34fcd1a08ca7f8cc29202a0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:24:21 -0300 Subject: [PATCH 034/289] perf evlist: Fix the class prefix for 'struct evlist' sample_type methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-report.c | 6 +++--- tools/perf/builtin-script.c | 4 ++-- tools/perf/util/evlist.c | 8 ++++---- tools/perf/util/evlist.h | 6 +++--- tools/perf/util/session.c | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index d617d5682c68..5938b100eaf4 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2582,7 +2582,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) static int setup_callchain(struct evlist *evlist) { - u64 sample_type = perf_evlist__combined_sample_type(evlist); + u64 sample_type = evlist__combined_sample_type(evlist); enum perf_call_graph_mode mode = CALLCHAIN_NONE; if ((sample_type & PERF_SAMPLE_REGS_USER) && diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5f1d2a878fad..67e0692489fa 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -338,7 +338,7 @@ static int process_read_event(struct perf_tool *tool, static int report__setup_sample_type(struct report *rep) { struct perf_session *session = rep->session; - u64 sample_type = perf_evlist__combined_sample_type(session->evlist); + u64 sample_type = evlist__combined_sample_type(session->evlist); bool is_pipe = perf_data__is_pipe(session->data); if (session->itrace_synth_opts->callchain || @@ -1093,7 +1093,7 @@ static int process_attr(struct perf_tool *tool __maybe_unused, * Check if we need to enable callchains based * on events sample_type. */ - sample_type = perf_evlist__combined_sample_type(*pevlist); + sample_type = evlist__combined_sample_type(*pevlist); callchain_param_setup(sample_type); return 0; } @@ -1389,7 +1389,7 @@ repeat: has_br_stack = perf_header__has_feat(&session->header, HEADER_BRANCH_STACK); - if (perf_evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER) + if (evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER) has_br_stack = false; setup_forced_leader(&report, session->evlist); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 1ff6a8a8dde5..a47d3386f4b4 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2129,7 +2129,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, * Check if we need to enable callchains based * on events sample_type. */ - sample_type = perf_evlist__combined_sample_type(evlist); + sample_type = evlist__combined_sample_type(evlist); callchain_param_setup(sample_type); /* Enable fields for callchain entries */ @@ -3171,7 +3171,7 @@ static int have_cmd(int argc, const char **argv) static void script__setup_sample_type(struct perf_script *script) { struct perf_session *session = script->session; - u64 sample_type = perf_evlist__combined_sample_type(session->evlist); + u64 sample_type = evlist__combined_sample_type(session->evlist); if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) { if ((sample_type & PERF_SAMPLE_REGS_USER) && diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4b7f9f9b1588..6415f97e2299 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1085,7 +1085,7 @@ int perf_evlist__append_tp_filter_pid(struct evlist *evlist, pid_t pid) return perf_evlist__append_tp_filter_pids(evlist, 1, &pid); } -bool perf_evlist__valid_sample_type(struct evlist *evlist) +bool evlist__valid_sample_type(struct evlist *evlist) { struct evsel *pos; @@ -1104,7 +1104,7 @@ bool perf_evlist__valid_sample_type(struct evlist *evlist) return true; } -u64 __perf_evlist__combined_sample_type(struct evlist *evlist) +u64 __evlist__combined_sample_type(struct evlist *evlist) { struct evsel *evsel; @@ -1117,10 +1117,10 @@ u64 __perf_evlist__combined_sample_type(struct evlist *evlist) return evlist->combined_sample_type; } -u64 perf_evlist__combined_sample_type(struct evlist *evlist) +u64 evlist__combined_sample_type(struct evlist *evlist) { evlist->combined_sample_type = 0; - return __perf_evlist__combined_sample_type(evlist); + return __evlist__combined_sample_type(evlist); } u64 perf_evlist__combined_branch_type(struct evlist *evlist) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a832639a8221..2edc1512c443 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -218,8 +218,8 @@ int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel); void __perf_evlist__set_leader(struct list_head *list); void perf_evlist__set_leader(struct evlist *evlist); -u64 __perf_evlist__combined_sample_type(struct evlist *evlist); -u64 perf_evlist__combined_sample_type(struct evlist *evlist); +u64 __evlist__combined_sample_type(struct evlist *evlist); +u64 evlist__combined_sample_type(struct evlist *evlist); u64 perf_evlist__combined_branch_type(struct evlist *evlist); bool perf_evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); @@ -231,7 +231,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, union perf_event *event, u64 *timestamp); -bool perf_evlist__valid_sample_type(struct evlist *evlist); +bool evlist__valid_sample_type(struct evlist *evlist); bool perf_evlist__valid_sample_id_all(struct evlist *evlist); bool perf_evlist__valid_read_format(struct evlist *evlist); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1a157e84a04a..cbc8c476c8d3 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -115,7 +115,7 @@ static int perf_session__open(struct perf_session *session) if (perf_header__has_feat(&session->header, HEADER_STAT)) return 0; - if (!perf_evlist__valid_sample_type(session->evlist)) { + if (!evlist__valid_sample_type(session->evlist)) { pr_err("non matching sample_type\n"); return -1; } @@ -1160,7 +1160,7 @@ static void perf_evlist__print_tstamp(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) { - u64 sample_type = __perf_evlist__combined_sample_type(evlist); + u64 sample_type = __evlist__combined_sample_type(evlist); if (event->header.type != PERF_RECORD_SAMPLE && !perf_evlist__sample_id_all(evlist)) { From 8cedf3a5c1f232fd8adf60affd040d32c5d9800f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:29:48 -0300 Subject: [PATCH 035/289] perf evlist: Fix the class prefix for 'struct evlist' sample_id_all methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 4 ++-- tools/perf/util/session.c | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 1eeb58eac5df..19b1d5effb7a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1646,7 +1646,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * Normally perf_session__new would do this, but it doesn't have the * evlist. */ - if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { + if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) { pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); rec->tool.ordered_events = false; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 6415f97e2299..daae5c672344 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -537,7 +537,7 @@ struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id) if (sid) return container_of(sid->evsel, struct evsel, core); - if (!perf_evlist__sample_id_all(evlist)) + if (!evlist__sample_id_all(evlist)) return evlist__first(evlist); return NULL; @@ -1188,7 +1188,7 @@ out: return size; } -bool perf_evlist__valid_sample_id_all(struct evlist *evlist) +bool evlist__valid_sample_id_all(struct evlist *evlist) { struct evsel *first = evlist__first(evlist), *pos = first; @@ -1200,7 +1200,7 @@ bool perf_evlist__valid_sample_id_all(struct evlist *evlist) return true; } -bool perf_evlist__sample_id_all(struct evlist *evlist) +bool evlist__sample_id_all(struct evlist *evlist) { struct evsel *first = evlist__first(evlist); return first->core.attr.sample_id_all; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 2edc1512c443..6c7b865e435b 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -221,7 +221,7 @@ void perf_evlist__set_leader(struct evlist *evlist); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); u64 perf_evlist__combined_branch_type(struct evlist *evlist); -bool perf_evlist__sample_id_all(struct evlist *evlist); +bool evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); int perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event, @@ -232,7 +232,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, u64 *timestamp); bool evlist__valid_sample_type(struct evlist *evlist); -bool perf_evlist__valid_sample_id_all(struct evlist *evlist); +bool evlist__valid_sample_id_all(struct evlist *evlist); bool perf_evlist__valid_read_format(struct evlist *evlist); void perf_evlist__splice_list_tail(struct evlist *evlist, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index cbc8c476c8d3..396424fcaadf 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -120,7 +120,7 @@ static int perf_session__open(struct perf_session *session) return -1; } - if (!perf_evlist__valid_sample_id_all(session->evlist)) { + if (!evlist__valid_sample_id_all(session->evlist)) { pr_err("non matching sample_id_all\n"); return -1; } @@ -252,10 +252,10 @@ struct perf_session *perf_session__new(struct perf_data *data, /* * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is - * processed, so perf_evlist__sample_id_all is not meaningful here. + * processed, so evlist__sample_id_all is not meaningful here. */ if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps && - tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { + tool->ordered_events && !evlist__sample_id_all(session->evlist)) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_events = false; } @@ -1163,7 +1163,7 @@ static void perf_evlist__print_tstamp(struct evlist *evlist, u64 sample_type = __evlist__combined_sample_type(evlist); if (event->header.type != PERF_RECORD_SAMPLE && - !perf_evlist__sample_id_all(evlist)) { + !evlist__sample_id_all(evlist)) { fputs("-1 -1 ", stdout); return; } @@ -1655,7 +1655,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, return -1; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(session->evlist)); + event_swap(event, evlist__sample_id_all(session->evlist)); out_parse_sample: @@ -1704,7 +1704,7 @@ static s64 perf_session__process_event(struct perf_session *session, int ret; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(evlist)); + event_swap(event, evlist__sample_id_all(evlist)); if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; From 92c7d7cdf490b1f906da04b6340ca8f56836f723 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:31:25 -0300 Subject: [PATCH 036/289] perf evlist: Fix the class prefix for 'struct evlist' branch_type methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 3 +-- tools/perf/builtin-script.c | 3 +-- tools/perf/util/evlist.c | 2 +- tools/perf/util/evlist.h | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 67e0692489fa..ece1cddfcd7c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -410,8 +410,7 @@ static int report__setup_sample_type(struct report *rep) } /* ??? handle more cases than just ANY? */ - if (!(perf_evlist__combined_branch_type(session->evlist) & - PERF_SAMPLE_BRANCH_ANY)) + if (!(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) rep->nonany_branch_mode = true; #if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_DWARF_SUPPORT) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a47d3386f4b4..6613e2bfef24 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -443,8 +443,7 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) return -EINVAL; } if (PRINT_FIELD(BRSTACKINSN) && !allow_user_set && - !(perf_evlist__combined_branch_type(session->evlist) & - PERF_SAMPLE_BRANCH_ANY)) { + !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) { pr_err("Display of branch stack assembler requested, but non all-branch filter set\n" "Hint: run 'perf record -b ...'\n"); return -EINVAL; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index daae5c672344..1b884695b4d3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1123,7 +1123,7 @@ u64 evlist__combined_sample_type(struct evlist *evlist) return __evlist__combined_sample_type(evlist); } -u64 perf_evlist__combined_branch_type(struct evlist *evlist) +u64 evlist__combined_branch_type(struct evlist *evlist) { struct evsel *evsel; u64 branch_type = 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 6c7b865e435b..38901c0d1599 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -220,7 +220,7 @@ void perf_evlist__set_leader(struct evlist *evlist); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); -u64 perf_evlist__combined_branch_type(struct evlist *evlist); +u64 evlist__combined_branch_type(struct evlist *evlist); bool evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); From 8d54c308c87f1b50ca088b12b89d7c0d96cf7dbf Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:47 -0700 Subject: [PATCH 037/289] perf parse-events: Use automatic variable for flex input This reduces the command line size slightly. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 8d18380ecd10..66cf009f78d8 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -193,7 +193,7 @@ CFLAGS_genelf_debug.o += -Wno-packed $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) @@ -201,7 +201,7 @@ $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) util/expr.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) @@ -209,7 +209,7 @@ $(OUTPUT)util/expr-bison.c: util/expr.y $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) From da77a14db3a03562f70dbe4951042ff84f647d7b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:48 -0700 Subject: [PATCH 038/289] perf parse-events: Use automatic variable for yacc input This reduces the command line size slightly. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 66cf009f78d8..4e1aa52d75a8 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -197,7 +197,7 @@ $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-event $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) @@ -205,7 +205,7 @@ $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) @@ -213,7 +213,7 @@ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d -o $@ -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w From 5011a52fc53570b816f80b0543cb7260cffca1bd Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:49 -0700 Subject: [PATCH 039/289] perf pmu: Add bison debug build flag Allow pmu parser to be debugged as the parse-events and expr currently are. Enabling this requires the C code to set perf_pmu_debug. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-4-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4e1aa52d75a8..3ae4adc8e966 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -213,7 +213,7 @@ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w From 970a4a3418e626d0d4220edd4e981ecbf9d87758 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:50 -0700 Subject: [PATCH 040/289] perf pmu: Add flex debug build flag Allow pmu parser's flex to be debugged as the parse-events and expr currently are. Enabling this requires the C code to call perf_pmu__flex_debug. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 3ae4adc8e966..e63bfc46d50f 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -209,7 +209,7 @@ $(OUTPUT)util/expr-bison.c: util/expr.y $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) From 4b971df992fdf8e0d55ab3cbea9fca4ce62bcefc Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:51 -0700 Subject: [PATCH 041/289] perf parse-events: Declare flex header file output Declare flex header file output so that bison C files can depend upon them. As there are multiple output targets $@ is replaced by the target name. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Jiri Olsa Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-6-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index e63bfc46d50f..55c78ac53f04 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -191,25 +191,28 @@ CFLAGS_llvm-utils.o += -DPERF_INCLUDE_DIR="BUILD_STR($(perf_include_dir_SQ))" # avoid compiler warnings in 32-bit mode CFLAGS_genelf_debug.o += -Wno-packed -$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \ + --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ -$(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c +$(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \ + --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ -$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c +$(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.h: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/pmu-flex.c \ + --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) From 3744ca1e670e6155ead37d9123ff005b07108259 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 23 Jun 2020 10:09:03 -0300 Subject: [PATCH 042/289] perf expr: Add missing headers noticed when building with NO_LIBBPF=1 These will break the build as soon as we stop disabling all warnings when building flex and bison generated files, so add them before we do that to keep the tree bisectable. Noticed when building on centos:7 with NO_LIBBPF=1: util/expr.c: In function 'key_equal': util/expr.c:29:2: error: implicit declaration of function 'strcmp' [-Werror=implicit-function-declaration] return !strcmp((const char *)key1, (const char *)key2); ^ util/expr.c: In function 'expr__add_id': util/expr.c:40:3: error: implicit declaration of function 'malloc' [-Werror=implicit-function-declaration] val_ptr = malloc(sizeof(double)); ^ util/expr.c:40:13: error: incompatible implicit declaration of built-in function 'malloc' [-Werror] val_ptr = malloc(sizeof(double)); ^ util/expr.c:42:12: error: 'ENOMEM' undeclared (first use in this function) return -ENOMEM; ^ Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/expr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index f64ab91c432b..e8f777830a23 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include +#include +#include #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" From ef9894d9667786489f710199628e0bfffccf452a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:52 -0700 Subject: [PATCH 043/289] perf parse-events: Declare bison header file output Declare bison header file output so that C files can depend upon them. As there are multiple output targets $@ is replaced by the target name. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-7-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 55c78ac53f04..504a6bb991ba 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -196,27 +196,30 @@ $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse- $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/parse-events-bison.c: util/parse-events.y +$(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/parse-events-bison.h: util/parse-events.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/parse-events-bison.c -p parse_events_ $(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/expr-bison.c: util/expr.y +$(OUTPUT)util/expr-bison.c $(OUTPUT)util/expr-bison.h: util/expr.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/expr-bison.c -p expr_ $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.h: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/pmu-flex.c \ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/pmu-bison.c: util/pmu.y +$(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.h: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w From 9dce29e65b38591eac0ce6786bdb725aea1eadeb Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 09:28:39 -0400 Subject: [PATCH 044/289] ktest.pl: Have config-bisect save each config used in the bisect When performing a automatic config bisect via ktest.pl, it is very useful to have a copy of each of the bisects used. This way, if a bisect were to go wrong, it is possible to retrace the steps and continue at the location before the error was made. The ktest.pl will make a copy of the good and bad configs, labeled as such, as well as a number attached to it that represents the iteration of the bisect. These files are saved in the ktest temp directory where it currently stores the good and bad config files. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 7570e36d636d..5f6f88911f5c 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -3188,6 +3188,8 @@ sub config_bisect_end { doprint "***************************************\n\n"; } +my $pass = 1; + sub run_config_bisect { my ($good, $bad, $last_result) = @_; my $reset = ""; @@ -3210,11 +3212,15 @@ sub run_config_bisect { $ret = run_config_bisect_test $config_bisect_type; if ($ret) { - doprint "NEW GOOD CONFIG\n"; + doprint "NEW GOOD CONFIG ($pass)\n"; + system("cp $output_config $tmpdir/good_config.tmp.$pass"); + $pass++; # Return 3 for good config return 3; } else { - doprint "NEW BAD CONFIG\n"; + doprint "NEW BAD CONFIG ($pass)\n"; + system("cp $output_config $tmpdir/bad_config.tmp.$pass"); + $pass++; # Return 4 for bad config return 4; } From 2f059db0b8313f8964ac917394e7425d966a6884 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 10:28:23 -0400 Subject: [PATCH 045/289] ktest.pl: Always show log file location if defined even on success If a log file is defined and the test were to error, a print statement is made that shows the user where the log file is to examine it further. But this is not done if the test were to succeed. I find it annoying that it does not show where the log file is on success, as I run several different tests that place their log files in various locations, and even though the test pass, there's things I want to look at in the log file (like warnings). It is much easier to find where the log file is, if it is displayed at the end of a test. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5f6f88911f5c..5d5cf3e1e81a 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -4441,6 +4441,10 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { } +if (defined($opt{"LOG_FILE"})) { + print "\n See $opt{LOG_FILE} for the record of results.\n"; +} + doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; if ($email_when_finished) { From d53cdda3fda6e737151e091c7d9388c31a73c828 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 10:32:28 -0400 Subject: [PATCH 046/289] ktest.pl: Define PRE_TEST_DIE to kill the test if the PRE_TEST fails Currently, if a PRE_TEST is defined and ran, but fails, there's nothing currently available to make the test fail too. Add a PRE_TEST_DIE option that when set, if a PRE_TEST is defined and fails, the test will die too. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 8 +++++++- tools/testing/ktest/sample.conf | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5d5cf3e1e81a..f99cf633ed84 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -98,6 +98,7 @@ my $final_post_ktest; my $pre_ktest; my $post_ktest; my $pre_test; +my $pre_test_die; my $post_test; my $pre_build; my $post_build; @@ -273,6 +274,7 @@ my %option_map = ( "PRE_KTEST" => \$pre_ktest, "POST_KTEST" => \$post_ktest, "PRE_TEST" => \$pre_test, + "PRE_TEST_DIE" => \$pre_test_die, "POST_TEST" => \$post_test, "BUILD_TYPE" => \$build_type, "BUILD_OPTIONS" => \$build_options, @@ -4347,7 +4349,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; if (defined($pre_test)) { - run_command $pre_test; + my $ret = run_command $pre_test; + if (!$ret && defined($pre_test_die) && + $pre_test_die) { + dodie "failed to pre_test\n"; + } } unlink $dmesg; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 27666b8007ed..cb8227fbd01e 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -557,6 +557,11 @@ # default (undefined) #PRE_TEST = ${SSH} reboot_to_special_kernel +# To kill the entire test if PRE_TEST is defined but fails set this +# to 1. +# (default 0) +#PRE_TEST_DIE = 1 + # If there is a command you want to run after the individual test case # completes, then you can set this option. # From 167234268cf6cb932ffb180586f3874ae3293a55 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 11:09:23 -0400 Subject: [PATCH 047/289] ktest.pl: Add a NOT operator There is a NOT DEFINED operator, but there is not an operator that can negate any other expression. For example: NOT (${FOO} == boot || ${BAR} == run) Add the keyword NOT to allow the ktest.pl config files to negate operators. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f99cf633ed84..0d04b8a2b5a2 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -911,6 +911,12 @@ sub process_expression { } } + if ($val =~ s/^\s*NOT\s+(.*)//) { + my $express = $1; + my $ret = process_expression($name, $express); + return !$ret; + } + if ($val =~ /^\s*0\s*$/) { return 0; } elsif ($val =~ /^\s*\d+\s*$/) { From d6bc29d987336927ff97219d5f661389f33f8f11 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 15:21:15 -0400 Subject: [PATCH 048/289] ktest.pl: Just open up the log file once Currently, every write to the log file is done by opening the file, writing to it, then closing the file. This rather expensive. Just open it at the beginning and close it at the end. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 0d04b8a2b5a2..f20a81bb3abe 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -509,9 +509,7 @@ EOF sub _logit { if (defined($opt{"LOG_FILE"})) { - open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; - print OUT @_; - close(OUT); + print LOG @_; } } @@ -1780,8 +1778,6 @@ sub run_command { (fail "unable to exec $command" and return 0); if (defined($opt{"LOG_FILE"})) { - open(LOG, ">>$opt{LOG_FILE}") or - dodie "failed to write to log"; $dolog = 1; } @@ -1829,7 +1825,6 @@ sub run_command { } close(CMD); - close(LOG) if ($dolog); close(RD) if ($dord); $end_time = time; @@ -4091,8 +4086,11 @@ if ($#new_configs >= 0) { } } -if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { - unlink $opt{"LOG_FILE"}; +if (defined($opt{"LOG_FILE"})) { + if ($opt{"CLEAR_LOG"}) { + unlink $opt{"LOG_FILE"}; + } + open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; } doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; @@ -4453,14 +4451,16 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { } -if (defined($opt{"LOG_FILE"})) { - print "\n See $opt{LOG_FILE} for the record of results.\n"; -} - doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; if ($email_when_finished) { send_email("KTEST: Your test has finished!", "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!"); } + +if (defined($opt{"LOG_FILE"})) { + print "\n See $opt{LOG_FILE} for the record of results.\n\n"; + close LOG; +} + exit 0; From eefb9d2b8c6a781dd1026b18e37b4bcb50cff440 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 15:29:06 -0400 Subject: [PATCH 049/289] ktest.pl: Turn off buffering to the log file The log file should be up to date to whatever is happening in ktest. Disable buffering to the LOG output file handle. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f20a81bb3abe..e90e2e7cb72c 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -11,6 +11,7 @@ use File::Path qw(mkpath); use File::Copy qw(cp); use FileHandle; use FindBin; +use IO::Handle; my $VERSION = "0.2"; @@ -4091,6 +4092,7 @@ if (defined($opt{"LOG_FILE"})) { unlink $opt{"LOG_FILE"}; } open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; + LOG->autoflush(1); } doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; From 304d7a90c43f7471fb481e6b1e2b47fef2a02b8c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:53 -0700 Subject: [PATCH 050/289] perf parse-events: Disable a subset of flex warnings Rather than disable all warnings with -w, disable specific warnings. Predicate enabling the warnings on more recent flex versions. Tested with GCC 9.3.0 and clang 9.0.1. Committer notes: The full set of compilers, gcc and clang that this will be tested on will be on the signed tag when this change goes upstream. Added -Wno-misleading-indentation to the flex_flags to overcome this on opensuse tumbleweed when building with clang: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o /tmp/build/perf/util/parse-events-flex.c:5038:13: error: misleading indentation; statement is not part of the previous 'if' [-Werror,-Wmisleading-indentation] if ( ! yyg->yy_state_buf ) ^ /tmp/build/perf/util/parse-events-flex.c:5036:9: note: previous statement is here if ( ! yyg->yy_state_buf ) ^ And we need to use this to redirect stderr to stdin and then grep in a way that is acceptable for BusyBox shell: 2>&1 | Previously I was using: |& Which seems to be bash specific. Added -Wno-sign-compare to overcome this on systems such as centos:7: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o CC /tmp/build/perf/util/pmu-flex.o util/parse-events.l: In function 'parse_events_lex': /tmp/build/perf/util/parse-events-flex.c:193:36: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] for ( yyl = n; yyl < yyleng; ++yyl )\ ^ /tmp/build/perf/util/parse-events-flex.c:204:9: note: in expansion of macro 'YY_LESS_LINENO' Added -Wno-unused-parameter to overcome this in systems such as centos:7: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o /tmp/build/perf/util/parse-events-flex.c: In function 'yy_fatal_error': /tmp/build/perf/util/parse-events-flex.c:6265:58: error: unused parameter 'yyscanner' [-Werror=unused-parameter] static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) ^ Added -Wno-missing-declarations to build in systems such as centos:6: /tmp/build/perf/util/parse-events-flex.c:6313: error: no previous prototype for 'parse_events_get_column' /tmp/build/perf/util/parse-events-flex.c:6389: error: no previous prototype for 'parse_events_set_column' And -Wno-missing-prototypes to cover older compilers: -Wmissing-prototypes (C only) Warn if a global function is defined without a previous prototype declaration. This warning is issued even if the definition itself provides a prototype. The aim is to detect global functions that fail to be declared in header files. -Wmissing-declarations (C only) Warn if a global function is defined without a previous declaration. Do so even if the definition itself provides a prototype. Use this option to detect global functions that are not declared in header files. Older C compilers lack -Wno-misleading-indentation, check if it is available before using it. Also needed to check just the first two levels of the flex version, as the patch was assuming that all versions were of the form x.y.z, and there are several cases where it is just x.y, breaking the build. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-8-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 504a6bb991ba..cd86a3068eab 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -221,9 +221,19 @@ $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.h: util/pmu.y $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ -CFLAGS_parse-events-flex.o += -w -CFLAGS_pmu-flex.o += -w -CFLAGS_expr-flex.o += -w +FLEX_GE_26 := $(shell expr $(shell $(FLEX) --version | sed -e 's/flex \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 26) +ifeq ($(FLEX_GE_26),1) + flex_flags := -Wno-switch-enum -Wno-switch-default -Wno-unused-function -Wno-redundant-decls -Wno-sign-compare -Wno-unused-parameter -Wno-missing-prototypes -Wno-missing-declarations + CC_HASNT_MISLEADING_INDENTATION := $(shell echo "int main(void) { return 0 }" | $(CC) -Werror -Wno-misleading-indentation -o /dev/null -xc - 2>&1 | grep -q -- -Wno-misleading-indentation ; echo $$?) + ifeq ($(CC_HASNT_MISLEADING_INDENTATION), 1) + flex_flags += -Wno-misleading-indentation + endif +else + flex_flags := -w +endif +CFLAGS_parse-events-flex.o += $(flex_flags) +CFLAGS_pmu-flex.o += $(flex_flags) +CFLAGS_expr-flex.o += $(flex_flags) CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w From 1f16fcad688552d442ddf1c5d3d8d4152d9bf4af Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:56 -0700 Subject: [PATCH 051/289] perf parse-events: Disable a subset of bison warnings Rather than disable all warnings with -w, disable specific warnings. Predicate enabling the warnings on a recent version of bison. Tested with GCC 9.3.0 and clang 9.0.1. Committer testing: The full set of compilers, gcc and clang that this will be tested on will be on the signed tag when this change goes upstream. Had to add -Wno-switch-enum to build on opensuse tumbleweed: /tmp/build/perf/util/parse-events-bison.c: In function 'yydestruct': /tmp/build/perf/util/parse-events-bison.c:1200:3: error: enumeration value 'YYSYMBOL_YYEMPTY' not handled in switch [-Werror=switch-enum] 1200 | switch (yykind) | ^~~~~~ /tmp/build/perf/util/parse-events-bison.c:1200:3: error: enumeration value 'YYSYMBOL_YYEOF' not handled in switch [-Werror=switch-enum] Also replace -Wno-error=implicit-function-declaration with -Wno-implicit-function-declaration. Also needed to check just the first two levels of the bison version, as the patch was assuming that all versions were of the form x.y.z, and there are several cases where it is just x.y, breaking the build. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-11-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/Build b/tools/perf/util/Build index cd86a3068eab..380e6a9f564d 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -234,9 +234,17 @@ endif CFLAGS_parse-events-flex.o += $(flex_flags) CFLAGS_pmu-flex.o += $(flex_flags) CFLAGS_expr-flex.o += $(flex_flags) -CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w -CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w -CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w + +bison_flags := -DYYENABLE_NLS=0 +BISON_GE_35 := $(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 35) +ifeq ($(BISON_GE_35),1) + bison_flags += -Wno-unused-parameter -Wno-nested-externs -Wno-implicit-function-declaration -Wno-switch-enum +else + bison_flags += -w +endif +CFLAGS_parse-events-bison.o += $(bison_flags) +CFLAGS_pmu-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags) +CFLAGS_expr-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags) $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c From 34148b13eec9c738327f8c8f84f468f4694b17a3 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 18:15:07 -0400 Subject: [PATCH 052/289] ktest.pl: Add the log of last test in email on failure If a failure happens and an email is sent, show the contents of the log of the last test that failed in the email. Link: http://lore.kernel.org/r/20200701231756.619246244@goodmis.org Reviewed-by: Greg Kroah-Hartman Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 42 ++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e90e2e7cb72c..8a4a33492952 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -82,6 +82,8 @@ my %default = ( "IGNORE_UNUSED" => 0, ); +my $test_log_start = 0; + my $ktest_config = "ktest.conf"; my $version; my $have_version = 0; @@ -1492,8 +1494,21 @@ sub dodie { if ($email_on_error) { my $name = get_test_name; + my $log_file; + + if (defined($opt{"LOG_FILE"})) { + $log_file = "$tmpdir/log"; + open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; + open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; + seek(L, $test_log_start, 0); + while () { + print O; + } + close O; + close L; + } send_email("KTEST: critical failure for test $i [$name]", - "Your test started at $script_start_time has failed with:\n@_\n"); + "Your test started at $script_start_time has failed with:\n@_\n", $log_file); } if ($monitor_cnt) { @@ -4185,7 +4200,7 @@ sub find_mailer { } sub do_send_mail { - my ($subject, $message) = @_; + my ($subject, $message, $file) = @_; if (!defined($mail_path)) { # find the mailer @@ -4195,16 +4210,30 @@ sub do_send_mail { } } + my $header_file = "$tmpdir/header"; + open (HEAD, ">$header_file") or die "Can not create $header_file\n"; + print HEAD "To: $mailto\n"; + print HEAD "Subject: $subject\n\n"; + print HEAD "$message\n"; + close HEAD; + if (!defined($mail_command)) { if ($mailer eq "mail" || $mailer eq "mailx") { - $mail_command = "\$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO <<< \'\$MESSAGE\'"; + $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO"; } elsif ($mailer eq "sendmail" ) { - $mail_command = "echo \'Subject: \$SUBJECT\n\n\$MESSAGE\' | \$MAIL_PATH/\$MAILER -t \$MAILTO"; + $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO"; } else { die "\nYour mailer: $mailer is not supported.\n"; } } + if (defined($file)) { + $mail_command =~ s/\$BODY_FILE/$file/g; + } else { + $mail_command =~ s/\$BODY_FILE//g; + } + + $mail_command =~ s/\$HEADER_FILE/$header_file/g; $mail_command =~ s/\$MAILER/$mailer/g; $mail_command =~ s/\$MAIL_PATH/$mail_path/g; $mail_command =~ s/\$MAILTO/$mailto/g; @@ -4352,6 +4381,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { } doprint "\n\n"; + + if (defined($opt{"LOG_FILE"})) { + $test_log_start = tell(LOG); + } + doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; if (defined($pre_test)) { From f986900209093f5de887d6c342139df6ebec04ac Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 18:34:10 -0400 Subject: [PATCH 053/289] ktest.pl: Add MAIL_MAX_SIZE to limit the amount of log emailed Add the ktest config option MAIL_MAX_SIZE that will limit the size of the log file that is placed into the email on failure. Link: https://lore.kernel.org/r/20200701231756.790637968@goodmis.org Reviewed-by: Greg Kroah-Hartman Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 12 +++++++++++- tools/testing/ktest/sample.conf | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 8a4a33492952..36db5b0b3647 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -227,6 +227,7 @@ my $dirname = $FindBin::Bin; my $mailto; my $mailer; my $mail_path; +my $mail_max_size; my $mail_command; my $email_on_error; my $email_when_finished; @@ -263,6 +264,7 @@ my %option_map = ( "MAILTO" => \$mailto, "MAILER" => \$mailer, "MAIL_PATH" => \$mail_path, + "MAIL_MAX_SIZE" => \$mail_max_size, "MAIL_COMMAND" => \$mail_command, "EMAIL_ON_ERROR" => \$email_on_error, "EMAIL_WHEN_FINISHED" => \$email_when_finished, @@ -1497,10 +1499,18 @@ sub dodie { my $log_file; if (defined($opt{"LOG_FILE"})) { + my $size = 0; + if (defined($mail_max_size)) { + my $log_size = tell LOG; + $log_size -= $test_log_start; + if ($log_size > $mail_max_size) { + $size = $log_size - $mail_max_size; + } + } $log_file = "$tmpdir/log"; open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; - seek(L, $test_log_start, 0); + seek(L, $test_log_start + $size, 0); while () { print O; } diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index cb8227fbd01e..5e7d1d729752 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -442,6 +442,19 @@ # Users can cancel the test by Ctrl^C # (default 0) #EMAIL_WHEN_CANCELED = 1 +# +# If a test ends with an error and EMAIL_ON_ERROR is set as well +# as a LOG_FILE is defined, then the log of the failing test will +# be included in the email that is sent. +# It is possible that the log may be very large, in which case, +# only the last amount of the log should be sent. To limit how +# much of the log is sent, set MAIL_MAX_SIZE. This will be the +# size in bytes of the last portion of the log of the failed +# test file. That is, if this is set to 100000, then only the +# last 100 thousand bytes of the log file will be included in +# the email. +# (default undef) +#MAIL_MAX_SIZE = 1000000 # Start a test setup. If you leave this off, all options # will be default and the test will run once. From 662081acfa25edf0d8fabd8021ac26f0d1e2d3a1 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 2 Jul 2020 14:53:47 -0400 Subject: [PATCH 054/289] tools lib traceevent: Add tep_load_plugins_hook() API Add the API function tep_load_plugins_hook() to the traceevent API to allow tools a common method to load in the plugins that are part of the lib traceevent library. Link: http://lore.kernel.org/linux-trace-devel/20190802110101.14759-4-tz.stoyanov@gmail.com Link: http://lore.kernel.org/linux-trace-devel/20200625100516.365338-4-tz.stoyanov@gmail.com Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200702185703.946652691@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 6 ++++++ tools/lib/traceevent/event-plugin.c | 19 +++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index b77837f75a0d..776c7c24ee79 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -396,6 +396,12 @@ struct tep_plugin_list; struct tep_plugin_list *tep_load_plugins(struct tep_handle *tep); void tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *tep); +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data); char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); int tep_plugin_add_options(const char *name, diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index e1f7ddd5a6cf..b53d9a53bcf9 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -365,20 +365,19 @@ load_plugins_dir(struct tep_handle *tep, const char *suffix, closedir(dir); } -static void -load_plugins(struct tep_handle *tep, const char *suffix, - void (*load_plugin)(struct tep_handle *tep, - const char *path, - const char *name, - void *data), - void *data) +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data) { char *home; char *path; char *envdir; int ret; - if (tep->flags & TEP_DISABLE_PLUGINS) + if (tep && tep->flags & TEP_DISABLE_PLUGINS) return; /* @@ -386,7 +385,7 @@ load_plugins(struct tep_handle *tep, const char *suffix, * check that first. */ #ifdef PLUGIN_DIR - if (!(tep->flags & TEP_DISABLE_SYS_PLUGINS)) + if (!tep || !(tep->flags & TEP_DISABLE_SYS_PLUGINS)) load_plugins_dir(tep, suffix, PLUGIN_DIR, load_plugin, data); #endif @@ -423,7 +422,7 @@ tep_load_plugins(struct tep_handle *tep) { struct tep_plugin_list *list = NULL; - load_plugins(tep, ".so", load_plugin, &list); + tep_load_plugins_hook(tep, ".so", load_plugin, &list); return list; } From 74006289cfedbb2f922fcd6fef7efee232450550 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 2 Jul 2020 14:53:48 -0400 Subject: [PATCH 055/289] tools lib traceevent: Add interface for options to plugins Add tep_plugin_add_option() and tep_plugin_print_options() to lib traceevent library that allows plugins to have their own options. For example, the function plugin by default does not print the parent, as it uses the parent to do the indenting. The "parent" option is created by the function plugin that will print the parent of the function like it does in the trace file. The tep_plugin_print_options() will print out the list of options that a Cc: Tzvetomir Stoyanov (VMware) plugin has defined. Link: http://lore.kernel.org/linux-trace-devel/20190802110101.14759-3-tz.stoyanov@gmail.com Link: http://lore.kernel.org/linux-trace-devel/20200625100516.365338-5-tz.stoyanov@gmail.com Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200702185704.092654084@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 2 + tools/lib/traceevent/event-plugin.c | 172 ++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 776c7c24ee79..02c0438527de 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -406,7 +406,9 @@ char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); int tep_plugin_add_options(const char *name, struct tep_plugin_option *options); +int tep_plugin_add_option(const char *name, const char *val); void tep_plugin_remove_options(struct tep_plugin_option *options); +void tep_plugin_print_options(struct trace_seq *s); void tep_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct tep_plugin_list *list); diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index b53d9a53bcf9..e8f4329ba8e0 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "event-parse.h" #include "event-parse-local.h" #include "event-utils.h" @@ -247,6 +248,166 @@ void tep_plugin_remove_options(struct tep_plugin_option *options) } } +static void parse_option_name(char **option, char **plugin) +{ + char *p; + + *plugin = NULL; + + if ((p = strstr(*option, ":"))) { + *plugin = *option; + *p = '\0'; + *option = strdup(p + 1); + if (!*option) + return; + } +} + +static struct tep_plugin_option * +find_registered_option(const char *plugin, const char *option) +{ + struct registered_plugin_options *reg; + struct tep_plugin_option *op; + const char *op_plugin; + + for (reg = registered_options; reg; reg = reg->next) { + for (op = reg->options; op->name; op++) { + if (op->plugin_alias) + op_plugin = op->plugin_alias; + else + op_plugin = op->file; + + if (plugin && strcmp(plugin, op_plugin) != 0) + continue; + if (strcmp(option, op->name) != 0) + continue; + + return op; + } + } + + return NULL; +} + +static int process_option(const char *plugin, const char *option, const char *val) +{ + struct tep_plugin_option *op; + + op = find_registered_option(plugin, option); + if (!op) + return 0; + + return update_option_value(op, val); +} + +/** + * tep_plugin_add_option - add an option/val pair to set plugin options + * @name: The name of the option (format: :