Changes in 4.9.232
	pinctrl: amd: fix npins for uart0 in kerncz_groups
	mac80211: allow rx of mesh eapol frames with default rx key
	scsi: scsi_transport_spi: Fix function pointer check
	xtensa: fix __sync_fetch_and_{and,or}_4 declarations
	xtensa: update *pos in cpuinfo_op.next
	drivers/net/wan/lapbether: Fixed the value of hard_header_len
	net: sky2: initialize return of gm_phy_read
	drm/nouveau/i2c/g94-: increase NV_PMGR_DP_AUXCTL_TRANSACTREQ timeout
	SUNRPC reverting d03727b248d0 ("NFSv4 fix CLOSE not waiting for direct IO compeletion")
	uprobes: Change handle_swbp() to send SIGTRAP with si_code=SI_KERNEL, to fix GDB regression
	ALSA: info: Drop WARN_ON() from buffer NULL sanity check
	ASoC: rt5670: Correct RT5670_LDO_SEL_MASK
	btrfs: fix double free on ulist after backref resolution failure
	btrfs: fix mount failure caused by race with umount
	bnxt_en: Fix race when modifying pause settings.
	hippi: Fix a size used in a 'pci_free_consistent()' in an error handling path
	ax88172a: fix ax88172a_unbind() failures
	net: dp83640: fix SIOCSHWTSTAMP to update the struct with actual configuration
	net: smc91x: Fix possible memory leak in smc_drv_probe()
	scripts/decode_stacktrace: strip basepath from all paths
	HID: i2c-hid: add Mediacom FlexBook edge13 to descriptor override
	HID: apple: Disable Fn-key key-re-mapping on clone keyboards
	dmaengine: tegra210-adma: Fix runtime PM imbalance on error
	regmap: dev_get_regmap_match(): fix string comparison
	dmaengine: ioat setting ioat timeout as module parameter
	usb: gadget: udc: gr_udc: fix memleak on error handling path in gr_ep_init()
	arm64: Use test_tsk_thread_flag() for checking TIF_SINGLESTEP
	x86: math-emu: Fix up 'cmp' insn for clang ias
	usb: xhci-mtk: fix the failure of bandwidth allocation
	usb: xhci: Fix ASM2142/ASM3142 DMA addressing
	Revert "cifs: Fix the target file was deleted when rename failed."
	staging: wlan-ng: properly check endpoint types
	staging: comedi: addi_apci_1032: check INSN_CONFIG_DIGITAL_TRIG shift
	staging: comedi: ni_6527: fix INSN_CONFIG_DIGITAL_TRIG support
	staging: comedi: addi_apci_1500: check INSN_CONFIG_DIGITAL_TRIG shift
	staging: comedi: addi_apci_1564: check INSN_CONFIG_DIGITAL_TRIG shift
	serial: 8250: fix null-ptr-deref in serial8250_start_tx()
	serial: 8250_mtk: Fix high-speed baud rates clamping
	vt: Reject zero-sized screen buffer size.
	Makefile: Fix GCC_TOOLCHAIN_DIR prefix for Clang cross compilation
	mm/memcg: fix refcount error while moving and swapping
	io-mapping: indicate mapping failure
	parisc: Add atomic64_set_release() define to avoid CPU soft lockups
	ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb
	ath9k: Fix regression with Atheros 9271
	AX.25: Fix out-of-bounds read in ax25_connect()
	AX.25: Prevent out-of-bounds read in ax25_sendmsg()
	dev: Defer free of skbs in flush_backlog
	net-sysfs: add a newline when printing 'tx_timeout' by sysfs
	net: udp: Fix wrong clean up for IS_UDPLITE macro
	rxrpc: Fix sendmsg() returning EPIPE due to recvmsg() returning ENODATA
	AX.25: Prevent integer overflows in connect and sendmsg
	tcp: allow at most one TLP probe per flight
	ip6_gre: fix null-ptr-deref in ip6gre_init_net()
	drivers/net/wan/x25_asy: Fix to make it work
	regmap: debugfs: check count when read regmap file
	xfs: set format back to extents if xfs_bmap_extents_to_btree
	perf probe: Fix to check blacklist address correctly
	perf annotate: Use asprintf when formatting objdump command line
	perf tools: Fix snprint warnings for gcc 8
	perf: Make perf able to build with latest libbfd
	Linux 4.9.232
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Iae57e72dbaebe67399c6756146f30762e5f25b2e
		
	
		
			
				
	
	
		
			174 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "util.h"
 | |
| #include "../perf.h"
 | |
| #include <subcmd/parse-options.h>
 | |
| #include "evsel.h"
 | |
| #include "cgroup.h"
 | |
| #include "evlist.h"
 | |
| 
 | |
| int nr_cgroups;
 | |
| 
 | |
| static int
 | |
| cgroupfs_find_mountpoint(char *buf, size_t maxlen)
 | |
| {
 | |
| 	FILE *fp;
 | |
| 	char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1];
 | |
| 	char *token, *saved_ptr = NULL;
 | |
| 	int found = 0;
 | |
| 
 | |
| 	fp = fopen("/proc/mounts", "r");
 | |
| 	if (!fp)
 | |
| 		return -1;
 | |
| 
 | |
| 	/*
 | |
| 	 * in order to handle split hierarchy, we need to scan /proc/mounts
 | |
| 	 * and inspect every cgroupfs mount point to find one that has
 | |
| 	 * perf_event subsystem
 | |
| 	 */
 | |
| 	while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %"
 | |
| 				STR(PATH_MAX)"s %*d %*d\n",
 | |
| 				mountpoint, type, tokens) == 3) {
 | |
| 
 | |
| 		if (!strcmp(type, "cgroup")) {
 | |
| 
 | |
| 			token = strtok_r(tokens, ",", &saved_ptr);
 | |
| 
 | |
| 			while (token != NULL) {
 | |
| 				if (!strcmp(token, "perf_event")) {
 | |
| 					found = 1;
 | |
| 					break;
 | |
| 				}
 | |
| 				token = strtok_r(NULL, ",", &saved_ptr);
 | |
| 			}
 | |
| 		}
 | |
| 		if (found)
 | |
| 			break;
 | |
| 	}
 | |
| 	fclose(fp);
 | |
| 	if (!found)
 | |
| 		return -1;
 | |
| 
 | |
| 	if (strlen(mountpoint) < maxlen) {
 | |
| 		strcpy(buf, mountpoint);
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| static int open_cgroup(char *name)
 | |
| {
 | |
| 	char path[PATH_MAX + 1];
 | |
| 	char mnt[PATH_MAX + 1];
 | |
| 	int fd;
 | |
| 
 | |
| 
 | |
| 	if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
 | |
| 		return -1;
 | |
| 
 | |
| 	scnprintf(path, PATH_MAX, "%s/%s", mnt, name);
 | |
| 
 | |
| 	fd = open(path, O_RDONLY);
 | |
| 	if (fd == -1)
 | |
| 		fprintf(stderr, "no access to cgroup %s\n", path);
 | |
| 
 | |
| 	return fd;
 | |
| }
 | |
| 
 | |
| static int add_cgroup(struct perf_evlist *evlist, char *str)
 | |
| {
 | |
| 	struct perf_evsel *counter;
 | |
| 	struct cgroup_sel *cgrp = NULL;
 | |
| 	int n;
 | |
| 	/*
 | |
| 	 * check if cgrp is already defined, if so we reuse it
 | |
| 	 */
 | |
| 	evlist__for_each_entry(evlist, counter) {
 | |
| 		cgrp = counter->cgrp;
 | |
| 		if (!cgrp)
 | |
| 			continue;
 | |
| 		if (!strcmp(cgrp->name, str))
 | |
| 			break;
 | |
| 
 | |
| 		cgrp = NULL;
 | |
| 	}
 | |
| 
 | |
| 	if (!cgrp) {
 | |
| 		cgrp = zalloc(sizeof(*cgrp));
 | |
| 		if (!cgrp)
 | |
| 			return -1;
 | |
| 
 | |
| 		cgrp->name = str;
 | |
| 
 | |
| 		cgrp->fd = open_cgroup(str);
 | |
| 		if (cgrp->fd == -1) {
 | |
| 			free(cgrp);
 | |
| 			return -1;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * find corresponding event
 | |
| 	 * if add cgroup N, then need to find event N
 | |
| 	 */
 | |
| 	n = 0;
 | |
| 	evlist__for_each_entry(evlist, counter) {
 | |
| 		if (n == nr_cgroups)
 | |
| 			goto found;
 | |
| 		n++;
 | |
| 	}
 | |
| 	if (atomic_read(&cgrp->refcnt) == 0)
 | |
| 		free(cgrp);
 | |
| 
 | |
| 	return -1;
 | |
| found:
 | |
| 	atomic_inc(&cgrp->refcnt);
 | |
| 	counter->cgrp = cgrp;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void close_cgroup(struct cgroup_sel *cgrp)
 | |
| {
 | |
| 	if (cgrp && atomic_dec_and_test(&cgrp->refcnt)) {
 | |
| 		close(cgrp->fd);
 | |
| 		zfree(&cgrp->name);
 | |
| 		free(cgrp);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int parse_cgroups(const struct option *opt __maybe_unused, const char *str,
 | |
| 		  int unset __maybe_unused)
 | |
| {
 | |
| 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
 | |
| 	const char *p, *e, *eos = str + strlen(str);
 | |
| 	char *s;
 | |
| 	int ret;
 | |
| 
 | |
| 	if (list_empty(&evlist->entries)) {
 | |
| 		fprintf(stderr, "must define events before cgroups\n");
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	for (;;) {
 | |
| 		p = strchr(str, ',');
 | |
| 		e = p ? p : eos;
 | |
| 
 | |
| 		/* allow empty cgroups, i.e., skip */
 | |
| 		if (e - str) {
 | |
| 			/* termination added */
 | |
| 			s = strndup(str, e - str);
 | |
| 			if (!s)
 | |
| 				return -1;
 | |
| 			ret = add_cgroup(evlist, s);
 | |
| 			if (ret) {
 | |
| 				free(s);
 | |
| 				return -1;
 | |
| 			}
 | |
| 		}
 | |
| 		/* nr_cgroups is increased een for empty cgroups */
 | |
| 		nr_cgroups++;
 | |
| 		if (!p)
 | |
| 			break;
 | |
| 		str = p+1;
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 |