xref: /openbmc/linux/tools/perf/builtin-record.c (revision c8b567c8a96a35acff746b1eef6f859e2a9fc195)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
286470930SIngo Molnar /*
386470930SIngo Molnar  * builtin-record.c
486470930SIngo Molnar  *
586470930SIngo Molnar  * Builtin record command: Record the profile of a workload
686470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
786470930SIngo Molnar  * later analysis via perf report.
886470930SIngo Molnar  */
986470930SIngo Molnar #include "builtin.h"
1086470930SIngo Molnar 
116122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
124b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1386470930SIngo Molnar #include "util/parse-events.h"
1441840d21STaeung Song #include "util/config.h"
1586470930SIngo Molnar 
168f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
17f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
187c6a1c65SPeter Zijlstra #include "util/header.h"
1966e274f3SFrederic Weisbecker #include "util/event.h"
20361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2169aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
228f28827aSFrederic Weisbecker #include "util/debug.h"
23aeb00b1aSArnaldo Carvalho de Melo #include "util/target.h"
2494c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
27aeb00b1aSArnaldo Carvalho de Melo #include "util/record.h"
28a12b51c4SPaul Mackerras #include "util/cpumap.h"
29fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
30f5fc1412SJiri Olsa #include "util/data.h"
31bcc84ec6SStephane Eranian #include "util/perf_regs.h"
32ef149c25SAdrian Hunter #include "util/auxtrace.h"
3346bc29b9SAdrian Hunter #include "util/tsc.h"
34f00898f4SAndi Kleen #include "util/parse-branch-options.h"
35bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3671dc2326SWang Nan #include "util/llvm-utils.h"
378690a2a7SWang Nan #include "util/bpf-loader.h"
385f9cf599SWang Nan #include "util/trigger.h"
39a074865eSWang Nan #include "util/perf-hooks.h"
40f13de660SAlexey Budankov #include "util/cpu-set-sched.h"
41ea49e01cSArnaldo Carvalho de Melo #include "util/synthetic-events.h"
42c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h"
4358db1d6eSArnaldo Carvalho de Melo #include "util/units.h"
447b612e29SSong Liu #include "util/bpf-event.h"
45d8871ea7SWang Nan #include "asm/bug.h"
46c1a604dfSArnaldo Carvalho de Melo #include "perf.h"
477c6a1c65SPeter Zijlstra 
48a43783aeSArnaldo Carvalho de Melo #include <errno.h>
49fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
5067230479SArnaldo Carvalho de Melo #include <locale.h>
514208735dSArnaldo Carvalho de Melo #include <poll.h>
5286470930SIngo Molnar #include <unistd.h>
5386470930SIngo Molnar #include <sched.h>
549607ad3aSArnaldo Carvalho de Melo #include <signal.h>
55a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
564208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
576ef81c55SMamatha Inamdar #include <linux/err.h>
588520a98dSArnaldo Carvalho de Melo #include <linux/string.h>
590693e680SArnaldo Carvalho de Melo #include <linux/time64.h>
60d8f9da24SArnaldo Carvalho de Melo #include <linux/zalloc.h>
6178da39faSBernhard Rosenkraenzer 
621b43b704SJiri Olsa struct switch_output {
63dc0c6127SJiri Olsa 	bool		 enabled;
641b43b704SJiri Olsa 	bool		 signal;
65dc0c6127SJiri Olsa 	unsigned long	 size;
66bfacbe3bSJiri Olsa 	unsigned long	 time;
67cb4e1ebbSJiri Olsa 	const char	*str;
68cb4e1ebbSJiri Olsa 	bool		 set;
6903724b2eSAndi Kleen 	char		 **filenames;
7003724b2eSAndi Kleen 	int		 num_files;
7103724b2eSAndi Kleen 	int		 cur_file;
721b43b704SJiri Olsa };
731b43b704SJiri Olsa 
748c6f45a7SArnaldo Carvalho de Melo struct record {
7545694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
76b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
77d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
788ceb41d7SJiri Olsa 	struct perf_data	data;
79ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
8063503dbaSJiri Olsa 	struct evlist	*evlist;
81d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
82d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
83d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
84d2db9a98SWang Nan 	bool			no_buildid_set;
85d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
86d2db9a98SWang Nan 	bool			no_buildid_cache_set;
876156681bSNamhyung Kim 	bool			buildid_all;
88ecfd7a9cSWang Nan 	bool			timestamp_filename;
8968588bafSJin Yao 	bool			timestamp_boundary;
901b43b704SJiri Olsa 	struct switch_output	switch_output;
919f065194SYang Shi 	unsigned long long	samples;
929d2ed645SAlexey Budankov 	cpu_set_t		affinity_mask;
930f82ebc4SArnaldo Carvalho de Melo };
9486470930SIngo Molnar 
95dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
96dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
97dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
98dc0c6127SJiri Olsa 
999d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = {
1009d2ed645SAlexey Budankov 	"SYS", "NODE", "CPU"
1019d2ed645SAlexey Budankov };
1029d2ed645SAlexey Budankov 
103dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
104dc0c6127SJiri Olsa {
105dc0c6127SJiri Olsa 	return rec->switch_output.signal &&
106dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
107dc0c6127SJiri Olsa }
108dc0c6127SJiri Olsa 
109dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
110dc0c6127SJiri Olsa {
111dc0c6127SJiri Olsa 	return rec->switch_output.size &&
112dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger) &&
113dc0c6127SJiri Olsa 	       (rec->bytes_written >= rec->switch_output.size);
114dc0c6127SJiri Olsa }
115dc0c6127SJiri Olsa 
116bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
117bfacbe3bSJiri Olsa {
118bfacbe3bSJiri Olsa 	return rec->switch_output.time &&
119bfacbe3bSJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
120bfacbe3bSJiri Olsa }
121bfacbe3bSJiri Olsa 
122ded2b8feSJiri Olsa static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
123ded2b8feSJiri Olsa 			 void *bf, size_t size)
124f5970550SPeter Zijlstra {
125ded2b8feSJiri Olsa 	struct perf_data_file *file = &rec->session->data->file;
126ded2b8feSJiri Olsa 
127ded2b8feSJiri Olsa 	if (perf_data_file__write(file, bf, size) < 0) {
1284f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
1298d3eca20SDavid Ahern 		return -1;
1308d3eca20SDavid Ahern 	}
131f5970550SPeter Zijlstra 
132cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
133dc0c6127SJiri Olsa 
134dc0c6127SJiri Olsa 	if (switch_output_size(rec))
135dc0c6127SJiri Olsa 		trigger_hit(&switch_output_trigger);
136dc0c6127SJiri Olsa 
1378d3eca20SDavid Ahern 	return 0;
138f5970550SPeter Zijlstra }
139f5970550SPeter Zijlstra 
140ef781128SAlexey Budankov static int record__aio_enabled(struct record *rec);
141ef781128SAlexey Budankov static int record__comp_enabled(struct record *rec);
1425d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size,
1435d7f4116SAlexey Budankov 			    void *src, size_t src_size);
1445d7f4116SAlexey Budankov 
145d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
146d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd,
147d3d1af6fSAlexey Budankov 		void *buf, size_t size, off_t off)
148d3d1af6fSAlexey Budankov {
149d3d1af6fSAlexey Budankov 	int rc;
150d3d1af6fSAlexey Budankov 
151d3d1af6fSAlexey Budankov 	cblock->aio_fildes = trace_fd;
152d3d1af6fSAlexey Budankov 	cblock->aio_buf    = buf;
153d3d1af6fSAlexey Budankov 	cblock->aio_nbytes = size;
154d3d1af6fSAlexey Budankov 	cblock->aio_offset = off;
155d3d1af6fSAlexey Budankov 	cblock->aio_sigevent.sigev_notify = SIGEV_NONE;
156d3d1af6fSAlexey Budankov 
157d3d1af6fSAlexey Budankov 	do {
158d3d1af6fSAlexey Budankov 		rc = aio_write(cblock);
159d3d1af6fSAlexey Budankov 		if (rc == 0) {
160d3d1af6fSAlexey Budankov 			break;
161d3d1af6fSAlexey Budankov 		} else if (errno != EAGAIN) {
162d3d1af6fSAlexey Budankov 			cblock->aio_fildes = -1;
163d3d1af6fSAlexey Budankov 			pr_err("failed to queue perf data, error: %m\n");
164d3d1af6fSAlexey Budankov 			break;
165d3d1af6fSAlexey Budankov 		}
166d3d1af6fSAlexey Budankov 	} while (1);
167d3d1af6fSAlexey Budankov 
168d3d1af6fSAlexey Budankov 	return rc;
169d3d1af6fSAlexey Budankov }
170d3d1af6fSAlexey Budankov 
171d3d1af6fSAlexey Budankov static int record__aio_complete(struct perf_mmap *md, struct aiocb *cblock)
172d3d1af6fSAlexey Budankov {
173d3d1af6fSAlexey Budankov 	void *rem_buf;
174d3d1af6fSAlexey Budankov 	off_t rem_off;
175d3d1af6fSAlexey Budankov 	size_t rem_size;
176d3d1af6fSAlexey Budankov 	int rc, aio_errno;
177d3d1af6fSAlexey Budankov 	ssize_t aio_ret, written;
178d3d1af6fSAlexey Budankov 
179d3d1af6fSAlexey Budankov 	aio_errno = aio_error(cblock);
180d3d1af6fSAlexey Budankov 	if (aio_errno == EINPROGRESS)
181d3d1af6fSAlexey Budankov 		return 0;
182d3d1af6fSAlexey Budankov 
183d3d1af6fSAlexey Budankov 	written = aio_ret = aio_return(cblock);
184d3d1af6fSAlexey Budankov 	if (aio_ret < 0) {
185d3d1af6fSAlexey Budankov 		if (aio_errno != EINTR)
186d3d1af6fSAlexey Budankov 			pr_err("failed to write perf data, error: %m\n");
187d3d1af6fSAlexey Budankov 		written = 0;
188d3d1af6fSAlexey Budankov 	}
189d3d1af6fSAlexey Budankov 
190d3d1af6fSAlexey Budankov 	rem_size = cblock->aio_nbytes - written;
191d3d1af6fSAlexey Budankov 
192d3d1af6fSAlexey Budankov 	if (rem_size == 0) {
193d3d1af6fSAlexey Budankov 		cblock->aio_fildes = -1;
194d3d1af6fSAlexey Budankov 		/*
195ef781128SAlexey Budankov 		 * md->refcount is incremented in record__aio_pushfn() for
196ef781128SAlexey Budankov 		 * every aio write request started in record__aio_push() so
197ef781128SAlexey Budankov 		 * decrement it because the request is now complete.
198d3d1af6fSAlexey Budankov 		 */
199d3d1af6fSAlexey Budankov 		perf_mmap__put(md);
200d3d1af6fSAlexey Budankov 		rc = 1;
201d3d1af6fSAlexey Budankov 	} else {
202d3d1af6fSAlexey Budankov 		/*
203d3d1af6fSAlexey Budankov 		 * aio write request may require restart with the
204d3d1af6fSAlexey Budankov 		 * reminder if the kernel didn't write whole
205d3d1af6fSAlexey Budankov 		 * chunk at once.
206d3d1af6fSAlexey Budankov 		 */
207d3d1af6fSAlexey Budankov 		rem_off = cblock->aio_offset + written;
208d3d1af6fSAlexey Budankov 		rem_buf = (void *)(cblock->aio_buf + written);
209d3d1af6fSAlexey Budankov 		record__aio_write(cblock, cblock->aio_fildes,
210d3d1af6fSAlexey Budankov 				rem_buf, rem_size, rem_off);
211d3d1af6fSAlexey Budankov 		rc = 0;
212d3d1af6fSAlexey Budankov 	}
213d3d1af6fSAlexey Budankov 
214d3d1af6fSAlexey Budankov 	return rc;
215d3d1af6fSAlexey Budankov }
216d3d1af6fSAlexey Budankov 
21793f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md, bool sync_all)
218d3d1af6fSAlexey Budankov {
21993f20c0fSAlexey Budankov 	struct aiocb **aiocb = md->aio.aiocb;
22093f20c0fSAlexey Budankov 	struct aiocb *cblocks = md->aio.cblocks;
221d3d1af6fSAlexey Budankov 	struct timespec timeout = { 0, 1000 * 1000  * 1 }; /* 1ms */
22293f20c0fSAlexey Budankov 	int i, do_suspend;
223d3d1af6fSAlexey Budankov 
224d3d1af6fSAlexey Budankov 	do {
22593f20c0fSAlexey Budankov 		do_suspend = 0;
22693f20c0fSAlexey Budankov 		for (i = 0; i < md->aio.nr_cblocks; ++i) {
22793f20c0fSAlexey Budankov 			if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) {
22893f20c0fSAlexey Budankov 				if (sync_all)
22993f20c0fSAlexey Budankov 					aiocb[i] = NULL;
23093f20c0fSAlexey Budankov 				else
23193f20c0fSAlexey Budankov 					return i;
23293f20c0fSAlexey Budankov 			} else {
23393f20c0fSAlexey Budankov 				/*
23493f20c0fSAlexey Budankov 				 * Started aio write is not complete yet
23593f20c0fSAlexey Budankov 				 * so it has to be waited before the
23693f20c0fSAlexey Budankov 				 * next allocation.
23793f20c0fSAlexey Budankov 				 */
23893f20c0fSAlexey Budankov 				aiocb[i] = &cblocks[i];
23993f20c0fSAlexey Budankov 				do_suspend = 1;
24093f20c0fSAlexey Budankov 			}
24193f20c0fSAlexey Budankov 		}
24293f20c0fSAlexey Budankov 		if (!do_suspend)
24393f20c0fSAlexey Budankov 			return -1;
244d3d1af6fSAlexey Budankov 
24593f20c0fSAlexey Budankov 		while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) {
246d3d1af6fSAlexey Budankov 			if (!(errno == EAGAIN || errno == EINTR))
247d3d1af6fSAlexey Budankov 				pr_err("failed to sync perf data, error: %m\n");
248d3d1af6fSAlexey Budankov 		}
249d3d1af6fSAlexey Budankov 	} while (1);
250d3d1af6fSAlexey Budankov }
251d3d1af6fSAlexey Budankov 
252ef781128SAlexey Budankov struct record_aio {
253ef781128SAlexey Budankov 	struct record	*rec;
254ef781128SAlexey Budankov 	void		*data;
255ef781128SAlexey Budankov 	size_t		size;
256ef781128SAlexey Budankov };
257ef781128SAlexey Budankov 
258ef781128SAlexey Budankov static int record__aio_pushfn(struct perf_mmap *map, void *to, void *buf, size_t size)
259d3d1af6fSAlexey Budankov {
260ef781128SAlexey Budankov 	struct record_aio *aio = to;
261ef781128SAlexey Budankov 
262ef781128SAlexey Budankov 	/*
263ef781128SAlexey Budankov 	 * map->base data pointed by buf is copied into free map->aio.data[] buffer
264ef781128SAlexey Budankov 	 * to release space in the kernel buffer as fast as possible, calling
265ef781128SAlexey Budankov 	 * perf_mmap__consume() from perf_mmap__push() function.
266ef781128SAlexey Budankov 	 *
267ef781128SAlexey Budankov 	 * That lets the kernel to proceed with storing more profiling data into
268ef781128SAlexey Budankov 	 * the kernel buffer earlier than other per-cpu kernel buffers are handled.
269ef781128SAlexey Budankov 	 *
270ef781128SAlexey Budankov 	 * Coping can be done in two steps in case the chunk of profiling data
271ef781128SAlexey Budankov 	 * crosses the upper bound of the kernel buffer. In this case we first move
272ef781128SAlexey Budankov 	 * part of data from map->start till the upper bound and then the reminder
273ef781128SAlexey Budankov 	 * from the beginning of the kernel buffer till the end of the data chunk.
274ef781128SAlexey Budankov 	 */
275ef781128SAlexey Budankov 
276ef781128SAlexey Budankov 	if (record__comp_enabled(aio->rec)) {
277ef781128SAlexey Budankov 		size = zstd_compress(aio->rec->session, aio->data + aio->size,
278ef781128SAlexey Budankov 				     perf_mmap__mmap_len(map) - aio->size,
279ef781128SAlexey Budankov 				     buf, size);
280ef781128SAlexey Budankov 	} else {
281ef781128SAlexey Budankov 		memcpy(aio->data + aio->size, buf, size);
282ef781128SAlexey Budankov 	}
283ef781128SAlexey Budankov 
284ef781128SAlexey Budankov 	if (!aio->size) {
285ef781128SAlexey Budankov 		/*
286ef781128SAlexey Budankov 		 * Increment map->refcount to guard map->aio.data[] buffer
287ef781128SAlexey Budankov 		 * from premature deallocation because map object can be
288ef781128SAlexey Budankov 		 * released earlier than aio write request started on
289ef781128SAlexey Budankov 		 * map->aio.data[] buffer is complete.
290ef781128SAlexey Budankov 		 *
291ef781128SAlexey Budankov 		 * perf_mmap__put() is done at record__aio_complete()
292ef781128SAlexey Budankov 		 * after started aio request completion or at record__aio_push()
293ef781128SAlexey Budankov 		 * if the request failed to start.
294ef781128SAlexey Budankov 		 */
295ef781128SAlexey Budankov 		perf_mmap__get(map);
296ef781128SAlexey Budankov 	}
297ef781128SAlexey Budankov 
298ef781128SAlexey Budankov 	aio->size += size;
299ef781128SAlexey Budankov 
300ef781128SAlexey Budankov 	return size;
301ef781128SAlexey Budankov }
302ef781128SAlexey Budankov 
303ef781128SAlexey Budankov static int record__aio_push(struct record *rec, struct perf_mmap *map, off_t *off)
304ef781128SAlexey Budankov {
305ef781128SAlexey Budankov 	int ret, idx;
306ef781128SAlexey Budankov 	int trace_fd = rec->session->data->file.fd;
307ef781128SAlexey Budankov 	struct record_aio aio = { .rec = rec, .size = 0 };
308ef781128SAlexey Budankov 
309ef781128SAlexey Budankov 	/*
310ef781128SAlexey Budankov 	 * Call record__aio_sync() to wait till map->aio.data[] buffer
311ef781128SAlexey Budankov 	 * becomes available after previous aio write operation.
312ef781128SAlexey Budankov 	 */
313ef781128SAlexey Budankov 
314ef781128SAlexey Budankov 	idx = record__aio_sync(map, false);
315ef781128SAlexey Budankov 	aio.data = map->aio.data[idx];
316ef781128SAlexey Budankov 	ret = perf_mmap__push(map, &aio, record__aio_pushfn);
317ef781128SAlexey Budankov 	if (ret != 0) /* ret > 0 - no data, ret < 0 - error */
318ef781128SAlexey Budankov 		return ret;
319d3d1af6fSAlexey Budankov 
320d3d1af6fSAlexey Budankov 	rec->samples++;
321ef781128SAlexey Budankov 	ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off);
322d3d1af6fSAlexey Budankov 	if (!ret) {
323ef781128SAlexey Budankov 		*off += aio.size;
324ef781128SAlexey Budankov 		rec->bytes_written += aio.size;
325d3d1af6fSAlexey Budankov 		if (switch_output_size(rec))
326d3d1af6fSAlexey Budankov 			trigger_hit(&switch_output_trigger);
327ef781128SAlexey Budankov 	} else {
328ef781128SAlexey Budankov 		/*
329ef781128SAlexey Budankov 		 * Decrement map->refcount incremented in record__aio_pushfn()
330ef781128SAlexey Budankov 		 * back if record__aio_write() operation failed to start, otherwise
331ef781128SAlexey Budankov 		 * map->refcount is decremented in record__aio_complete() after
332ef781128SAlexey Budankov 		 * aio write operation finishes successfully.
333ef781128SAlexey Budankov 		 */
334ef781128SAlexey Budankov 		perf_mmap__put(map);
335d3d1af6fSAlexey Budankov 	}
336d3d1af6fSAlexey Budankov 
337d3d1af6fSAlexey Budankov 	return ret;
338d3d1af6fSAlexey Budankov }
339d3d1af6fSAlexey Budankov 
340d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd)
341d3d1af6fSAlexey Budankov {
342d3d1af6fSAlexey Budankov 	return lseek(trace_fd, 0, SEEK_CUR);
343d3d1af6fSAlexey Budankov }
344d3d1af6fSAlexey Budankov 
345d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos)
346d3d1af6fSAlexey Budankov {
347d3d1af6fSAlexey Budankov 	lseek(trace_fd, pos, SEEK_SET);
348d3d1af6fSAlexey Budankov }
349d3d1af6fSAlexey Budankov 
350d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec)
351d3d1af6fSAlexey Budankov {
352d3d1af6fSAlexey Budankov 	int i;
35363503dbaSJiri Olsa 	struct evlist *evlist = rec->evlist;
354d3d1af6fSAlexey Budankov 	struct perf_mmap *maps = evlist->mmap;
355d3d1af6fSAlexey Budankov 
356ef781128SAlexey Budankov 	if (!record__aio_enabled(rec))
357d3d1af6fSAlexey Budankov 		return;
358d3d1af6fSAlexey Budankov 
359d3d1af6fSAlexey Budankov 	for (i = 0; i < evlist->nr_mmaps; i++) {
360d3d1af6fSAlexey Budankov 		struct perf_mmap *map = &maps[i];
361d3d1af6fSAlexey Budankov 
362d3d1af6fSAlexey Budankov 		if (map->base)
36393f20c0fSAlexey Budankov 			record__aio_sync(map, true);
364d3d1af6fSAlexey Budankov 	}
365d3d1af6fSAlexey Budankov }
366d3d1af6fSAlexey Budankov 
367d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1;
36893f20c0fSAlexey Budankov static int nr_cblocks_max = 4;
369d3d1af6fSAlexey Budankov 
370d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt,
37193f20c0fSAlexey Budankov 			     const char *str,
372d3d1af6fSAlexey Budankov 			     int unset)
373d3d1af6fSAlexey Budankov {
374d3d1af6fSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
375d3d1af6fSAlexey Budankov 
37693f20c0fSAlexey Budankov 	if (unset) {
377d3d1af6fSAlexey Budankov 		opts->nr_cblocks = 0;
37893f20c0fSAlexey Budankov 	} else {
37993f20c0fSAlexey Budankov 		if (str)
38093f20c0fSAlexey Budankov 			opts->nr_cblocks = strtol(str, NULL, 0);
38193f20c0fSAlexey Budankov 		if (!opts->nr_cblocks)
382d3d1af6fSAlexey Budankov 			opts->nr_cblocks = nr_cblocks_default;
38393f20c0fSAlexey Budankov 	}
384d3d1af6fSAlexey Budankov 
385d3d1af6fSAlexey Budankov 	return 0;
386d3d1af6fSAlexey Budankov }
387d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */
38893f20c0fSAlexey Budankov static int nr_cblocks_max = 0;
38993f20c0fSAlexey Budankov 
390ef781128SAlexey Budankov static int record__aio_push(struct record *rec __maybe_unused, struct perf_mmap *map __maybe_unused,
391ef781128SAlexey Budankov 			    off_t *off __maybe_unused)
392d3d1af6fSAlexey Budankov {
393d3d1af6fSAlexey Budankov 	return -1;
394d3d1af6fSAlexey Budankov }
395d3d1af6fSAlexey Budankov 
396d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused)
397d3d1af6fSAlexey Budankov {
398d3d1af6fSAlexey Budankov 	return -1;
399d3d1af6fSAlexey Budankov }
400d3d1af6fSAlexey Budankov 
401d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused)
402d3d1af6fSAlexey Budankov {
403d3d1af6fSAlexey Budankov }
404d3d1af6fSAlexey Budankov 
405d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused)
406d3d1af6fSAlexey Budankov {
407d3d1af6fSAlexey Budankov }
408d3d1af6fSAlexey Budankov #endif
409d3d1af6fSAlexey Budankov 
410d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec)
411d3d1af6fSAlexey Budankov {
412d3d1af6fSAlexey Budankov 	return rec->opts.nr_cblocks > 0;
413d3d1af6fSAlexey Budankov }
414d3d1af6fSAlexey Budankov 
415470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1
416470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt,
417470530bbSAlexey Budankov 				    const char *str,
418470530bbSAlexey Budankov 				    int unset)
419470530bbSAlexey Budankov {
420470530bbSAlexey Budankov 	int flush_max;
421470530bbSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
422470530bbSAlexey Budankov 	static struct parse_tag tags[] = {
423470530bbSAlexey Budankov 			{ .tag  = 'B', .mult = 1       },
424470530bbSAlexey Budankov 			{ .tag  = 'K', .mult = 1 << 10 },
425470530bbSAlexey Budankov 			{ .tag  = 'M', .mult = 1 << 20 },
426470530bbSAlexey Budankov 			{ .tag  = 'G', .mult = 1 << 30 },
427470530bbSAlexey Budankov 			{ .tag  = 0 },
428470530bbSAlexey Budankov 	};
429470530bbSAlexey Budankov 
430470530bbSAlexey Budankov 	if (unset)
431470530bbSAlexey Budankov 		return 0;
432470530bbSAlexey Budankov 
433470530bbSAlexey Budankov 	if (str) {
434470530bbSAlexey Budankov 		opts->mmap_flush = parse_tag_value(str, tags);
435470530bbSAlexey Budankov 		if (opts->mmap_flush == (int)-1)
436470530bbSAlexey Budankov 			opts->mmap_flush = strtol(str, NULL, 0);
437470530bbSAlexey Budankov 	}
438470530bbSAlexey Budankov 
439470530bbSAlexey Budankov 	if (!opts->mmap_flush)
440470530bbSAlexey Budankov 		opts->mmap_flush = MMAP_FLUSH_DEFAULT;
441470530bbSAlexey Budankov 
442470530bbSAlexey Budankov 	flush_max = perf_evlist__mmap_size(opts->mmap_pages);
443470530bbSAlexey Budankov 	flush_max /= 4;
444470530bbSAlexey Budankov 	if (opts->mmap_flush > flush_max)
445470530bbSAlexey Budankov 		opts->mmap_flush = flush_max;
446470530bbSAlexey Budankov 
447470530bbSAlexey Budankov 	return 0;
448470530bbSAlexey Budankov }
449470530bbSAlexey Budankov 
450504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT
451504c1ad1SAlexey Budankov static unsigned int comp_level_default = 1;
452504c1ad1SAlexey Budankov 
453504c1ad1SAlexey Budankov static int record__parse_comp_level(const struct option *opt, const char *str, int unset)
454504c1ad1SAlexey Budankov {
455504c1ad1SAlexey Budankov 	struct record_opts *opts = opt->value;
456504c1ad1SAlexey Budankov 
457504c1ad1SAlexey Budankov 	if (unset) {
458504c1ad1SAlexey Budankov 		opts->comp_level = 0;
459504c1ad1SAlexey Budankov 	} else {
460504c1ad1SAlexey Budankov 		if (str)
461504c1ad1SAlexey Budankov 			opts->comp_level = strtol(str, NULL, 0);
462504c1ad1SAlexey Budankov 		if (!opts->comp_level)
463504c1ad1SAlexey Budankov 			opts->comp_level = comp_level_default;
464504c1ad1SAlexey Budankov 	}
465504c1ad1SAlexey Budankov 
466504c1ad1SAlexey Budankov 	return 0;
467504c1ad1SAlexey Budankov }
468504c1ad1SAlexey Budankov #endif
46951255a8aSAlexey Budankov static unsigned int comp_level_max = 22;
47051255a8aSAlexey Budankov 
47142e1fd80SAlexey Budankov static int record__comp_enabled(struct record *rec)
47242e1fd80SAlexey Budankov {
47342e1fd80SAlexey Budankov 	return rec->opts.comp_level > 0;
47442e1fd80SAlexey Budankov }
47542e1fd80SAlexey Budankov 
47645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
477d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
4781d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
4791d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
480234fbbf5SArnaldo Carvalho de Melo {
4818c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
482ded2b8feSJiri Olsa 	return record__write(rec, NULL, event, event->header.size);
483234fbbf5SArnaldo Carvalho de Melo }
484234fbbf5SArnaldo Carvalho de Melo 
485ded2b8feSJiri Olsa static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size)
486d37f1586SArnaldo Carvalho de Melo {
487d37f1586SArnaldo Carvalho de Melo 	struct record *rec = to;
488d37f1586SArnaldo Carvalho de Melo 
4895d7f4116SAlexey Budankov 	if (record__comp_enabled(rec)) {
4905d7f4116SAlexey Budankov 		size = zstd_compress(rec->session, map->data, perf_mmap__mmap_len(map), bf, size);
4915d7f4116SAlexey Budankov 		bf   = map->data;
4925d7f4116SAlexey Budankov 	}
4935d7f4116SAlexey Budankov 
494d37f1586SArnaldo Carvalho de Melo 	rec->samples++;
495ded2b8feSJiri Olsa 	return record__write(rec, map, bf, size);
496d37f1586SArnaldo Carvalho de Melo }
497d37f1586SArnaldo Carvalho de Melo 
4982dd6d8a1SAdrian Hunter static volatile int done;
4992dd6d8a1SAdrian Hunter static volatile int signr = -1;
5002dd6d8a1SAdrian Hunter static volatile int child_finished;
501c0bdc1c4SWang Nan 
5022dd6d8a1SAdrian Hunter static void sig_handler(int sig)
5032dd6d8a1SAdrian Hunter {
5042dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
5052dd6d8a1SAdrian Hunter 		child_finished = 1;
5062dd6d8a1SAdrian Hunter 	else
5072dd6d8a1SAdrian Hunter 		signr = sig;
5082dd6d8a1SAdrian Hunter 
5092dd6d8a1SAdrian Hunter 	done = 1;
5102dd6d8a1SAdrian Hunter }
5112dd6d8a1SAdrian Hunter 
512a074865eSWang Nan static void sigsegv_handler(int sig)
513a074865eSWang Nan {
514a074865eSWang Nan 	perf_hooks__recover();
515a074865eSWang Nan 	sighandler_dump_stack(sig);
516a074865eSWang Nan }
517a074865eSWang Nan 
5182dd6d8a1SAdrian Hunter static void record__sig_exit(void)
5192dd6d8a1SAdrian Hunter {
5202dd6d8a1SAdrian Hunter 	if (signr == -1)
5212dd6d8a1SAdrian Hunter 		return;
5222dd6d8a1SAdrian Hunter 
5232dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
5242dd6d8a1SAdrian Hunter 	raise(signr);
5252dd6d8a1SAdrian Hunter }
5262dd6d8a1SAdrian Hunter 
527e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
528e31f0d01SAdrian Hunter 
529ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
530ded2b8feSJiri Olsa 				    struct perf_mmap *map,
531ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
532ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
533ef149c25SAdrian Hunter {
534ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
5358ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
536ef149c25SAdrian Hunter 	size_t padding;
537ef149c25SAdrian Hunter 	u8 pad[8] = {0};
538ef149c25SAdrian Hunter 
539cd3dd8ddSJiri Olsa 	if (!perf_data__is_pipe(data) && !perf_data__is_dir(data)) {
54099fa2984SAdrian Hunter 		off_t file_offset;
5418ceb41d7SJiri Olsa 		int fd = perf_data__fd(data);
54299fa2984SAdrian Hunter 		int err;
54399fa2984SAdrian Hunter 
54499fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
54599fa2984SAdrian Hunter 		if (file_offset == -1)
54699fa2984SAdrian Hunter 			return -1;
54799fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
54899fa2984SAdrian Hunter 						     event, file_offset);
54999fa2984SAdrian Hunter 		if (err)
55099fa2984SAdrian Hunter 			return err;
55199fa2984SAdrian Hunter 	}
55299fa2984SAdrian Hunter 
553ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
554ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
555ef149c25SAdrian Hunter 	if (padding)
556ef149c25SAdrian Hunter 		padding = 8 - padding;
557ef149c25SAdrian Hunter 
558ded2b8feSJiri Olsa 	record__write(rec, map, event, event->header.size);
559ded2b8feSJiri Olsa 	record__write(rec, map, data1, len1);
560ef149c25SAdrian Hunter 	if (len2)
561ded2b8feSJiri Olsa 		record__write(rec, map, data2, len2);
562ded2b8feSJiri Olsa 	record__write(rec, map, &pad, padding);
563ef149c25SAdrian Hunter 
564ef149c25SAdrian Hunter 	return 0;
565ef149c25SAdrian Hunter }
566ef149c25SAdrian Hunter 
567ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
568e035f4caSJiri Olsa 				      struct perf_mmap *map)
569ef149c25SAdrian Hunter {
570ef149c25SAdrian Hunter 	int ret;
571ef149c25SAdrian Hunter 
572e035f4caSJiri Olsa 	ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
573ef149c25SAdrian Hunter 				  record__process_auxtrace);
574ef149c25SAdrian Hunter 	if (ret < 0)
575ef149c25SAdrian Hunter 		return ret;
576ef149c25SAdrian Hunter 
577ef149c25SAdrian Hunter 	if (ret)
578ef149c25SAdrian Hunter 		rec->samples++;
579ef149c25SAdrian Hunter 
580ef149c25SAdrian Hunter 	return 0;
581ef149c25SAdrian Hunter }
582ef149c25SAdrian Hunter 
5832dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
584e035f4caSJiri Olsa 					       struct perf_mmap *map)
5852dd6d8a1SAdrian Hunter {
5862dd6d8a1SAdrian Hunter 	int ret;
5872dd6d8a1SAdrian Hunter 
588e035f4caSJiri Olsa 	ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
5892dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
5902dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
5912dd6d8a1SAdrian Hunter 	if (ret < 0)
5922dd6d8a1SAdrian Hunter 		return ret;
5932dd6d8a1SAdrian Hunter 
5942dd6d8a1SAdrian Hunter 	if (ret)
5952dd6d8a1SAdrian Hunter 		rec->samples++;
5962dd6d8a1SAdrian Hunter 
5972dd6d8a1SAdrian Hunter 	return 0;
5982dd6d8a1SAdrian Hunter }
5992dd6d8a1SAdrian Hunter 
6002dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
6012dd6d8a1SAdrian Hunter {
6022dd6d8a1SAdrian Hunter 	int i;
6032dd6d8a1SAdrian Hunter 	int rc = 0;
6042dd6d8a1SAdrian Hunter 
6052dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
606e035f4caSJiri Olsa 		struct perf_mmap *map = &rec->evlist->mmap[i];
6072dd6d8a1SAdrian Hunter 
608e035f4caSJiri Olsa 		if (!map->auxtrace_mmap.base)
6092dd6d8a1SAdrian Hunter 			continue;
6102dd6d8a1SAdrian Hunter 
611e035f4caSJiri Olsa 		if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
6122dd6d8a1SAdrian Hunter 			rc = -1;
6132dd6d8a1SAdrian Hunter 			goto out;
6142dd6d8a1SAdrian Hunter 		}
6152dd6d8a1SAdrian Hunter 	}
6162dd6d8a1SAdrian Hunter out:
6172dd6d8a1SAdrian Hunter 	return rc;
6182dd6d8a1SAdrian Hunter }
6192dd6d8a1SAdrian Hunter 
620ce7b0e42SAlexander Shishkin static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit)
6212dd6d8a1SAdrian Hunter {
6222dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
6232dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
6245f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
6252dd6d8a1SAdrian Hunter 	} else {
626ce7b0e42SAlexander Shishkin 		if (auxtrace_record__snapshot_finish(rec->itr, on_exit))
6275f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
6285f9cf599SWang Nan 		else
6295f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
6302dd6d8a1SAdrian Hunter 	}
6312dd6d8a1SAdrian Hunter }
6322dd6d8a1SAdrian Hunter 
633ce7b0e42SAlexander Shishkin static int record__auxtrace_snapshot_exit(struct record *rec)
634ce7b0e42SAlexander Shishkin {
635ce7b0e42SAlexander Shishkin 	if (trigger_is_error(&auxtrace_snapshot_trigger))
636ce7b0e42SAlexander Shishkin 		return 0;
637ce7b0e42SAlexander Shishkin 
638ce7b0e42SAlexander Shishkin 	if (!auxtrace_record__snapshot_started &&
639ce7b0e42SAlexander Shishkin 	    auxtrace_record__snapshot_start(rec->itr))
640ce7b0e42SAlexander Shishkin 		return -1;
641ce7b0e42SAlexander Shishkin 
642ce7b0e42SAlexander Shishkin 	record__read_auxtrace_snapshot(rec, true);
643ce7b0e42SAlexander Shishkin 	if (trigger_is_error(&auxtrace_snapshot_trigger))
644ce7b0e42SAlexander Shishkin 		return -1;
645ce7b0e42SAlexander Shishkin 
646ce7b0e42SAlexander Shishkin 	return 0;
647ce7b0e42SAlexander Shishkin }
648ce7b0e42SAlexander Shishkin 
6494b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec)
6504b5ea3bdSAdrian Hunter {
6514b5ea3bdSAdrian Hunter 	int err;
6524b5ea3bdSAdrian Hunter 
6534b5ea3bdSAdrian Hunter 	if (!rec->itr) {
6544b5ea3bdSAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
6554b5ea3bdSAdrian Hunter 		if (err)
6564b5ea3bdSAdrian Hunter 			return err;
6574b5ea3bdSAdrian Hunter 	}
6584b5ea3bdSAdrian Hunter 
6594b5ea3bdSAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
6604b5ea3bdSAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
6614b5ea3bdSAdrian Hunter 	if (err)
6624b5ea3bdSAdrian Hunter 		return err;
6634b5ea3bdSAdrian Hunter 
6644b5ea3bdSAdrian Hunter 	return auxtrace_parse_filters(rec->evlist);
6654b5ea3bdSAdrian Hunter }
6664b5ea3bdSAdrian Hunter 
667e31f0d01SAdrian Hunter #else
668e31f0d01SAdrian Hunter 
669e31f0d01SAdrian Hunter static inline
670e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
671e035f4caSJiri Olsa 			       struct perf_mmap *map __maybe_unused)
672e31f0d01SAdrian Hunter {
673e31f0d01SAdrian Hunter 	return 0;
674e31f0d01SAdrian Hunter }
675e31f0d01SAdrian Hunter 
6762dd6d8a1SAdrian Hunter static inline
677ce7b0e42SAlexander Shishkin void record__read_auxtrace_snapshot(struct record *rec __maybe_unused,
678ce7b0e42SAlexander Shishkin 				    bool on_exit __maybe_unused)
6792dd6d8a1SAdrian Hunter {
6802dd6d8a1SAdrian Hunter }
6812dd6d8a1SAdrian Hunter 
6822dd6d8a1SAdrian Hunter static inline
6832dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
6842dd6d8a1SAdrian Hunter {
6852dd6d8a1SAdrian Hunter 	return 0;
6862dd6d8a1SAdrian Hunter }
6872dd6d8a1SAdrian Hunter 
688ce7b0e42SAlexander Shishkin static inline
689ce7b0e42SAlexander Shishkin int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused)
690ce7b0e42SAlexander Shishkin {
691ce7b0e42SAlexander Shishkin 	return 0;
692ce7b0e42SAlexander Shishkin }
693ce7b0e42SAlexander Shishkin 
6944b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused)
6954b5ea3bdSAdrian Hunter {
6964b5ea3bdSAdrian Hunter 	return 0;
6974b5ea3bdSAdrian Hunter }
6984b5ea3bdSAdrian Hunter 
699e31f0d01SAdrian Hunter #endif
700e31f0d01SAdrian Hunter 
701cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
70263503dbaSJiri Olsa 			       struct evlist *evlist)
703cda57a8cSWang Nan {
704cda57a8cSWang Nan 	struct record_opts *opts = &rec->opts;
705cda57a8cSWang Nan 	char msg[512];
706cda57a8cSWang Nan 
707f13de660SAlexey Budankov 	if (opts->affinity != PERF_AFFINITY_SYS)
708f13de660SAlexey Budankov 		cpu__setup_cpunode_map();
709f13de660SAlexey Budankov 
7107a276ff6SWang Nan 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages,
711cda57a8cSWang Nan 				 opts->auxtrace_mmap_pages,
7129d2ed645SAlexey Budankov 				 opts->auxtrace_snapshot_mode,
713470530bbSAlexey Budankov 				 opts->nr_cblocks, opts->affinity,
71451255a8aSAlexey Budankov 				 opts->mmap_flush, opts->comp_level) < 0) {
715cda57a8cSWang Nan 		if (errno == EPERM) {
716cda57a8cSWang Nan 			pr_err("Permission error mapping pages.\n"
717cda57a8cSWang Nan 			       "Consider increasing "
718cda57a8cSWang Nan 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
719cda57a8cSWang Nan 			       "or try again with a smaller value of -m/--mmap_pages.\n"
720cda57a8cSWang Nan 			       "(current value: %u,%u)\n",
721cda57a8cSWang Nan 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
722cda57a8cSWang Nan 			return -errno;
723cda57a8cSWang Nan 		} else {
724cda57a8cSWang Nan 			pr_err("failed to mmap with %d (%s)\n", errno,
725c8b5f2c9SArnaldo Carvalho de Melo 				str_error_r(errno, msg, sizeof(msg)));
726cda57a8cSWang Nan 			if (errno)
727cda57a8cSWang Nan 				return -errno;
728cda57a8cSWang Nan 			else
729cda57a8cSWang Nan 				return -EINVAL;
730cda57a8cSWang Nan 		}
731cda57a8cSWang Nan 	}
732cda57a8cSWang Nan 	return 0;
733cda57a8cSWang Nan }
734cda57a8cSWang Nan 
735cda57a8cSWang Nan static int record__mmap(struct record *rec)
736cda57a8cSWang Nan {
737cda57a8cSWang Nan 	return record__mmap_evlist(rec, rec->evlist);
738cda57a8cSWang Nan }
739cda57a8cSWang Nan 
7408c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
741dd7927f4SArnaldo Carvalho de Melo {
742d6195a6aSArnaldo Carvalho de Melo 	char msg[BUFSIZ];
74332dcd021SJiri Olsa 	struct evsel *pos;
74463503dbaSJiri Olsa 	struct evlist *evlist = rec->evlist;
745d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
746b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
7478d3eca20SDavid Ahern 	int rc = 0;
748dd7927f4SArnaldo Carvalho de Melo 
749d3dbf43cSArnaldo Carvalho de Melo 	/*
750d3dbf43cSArnaldo Carvalho de Melo 	 * For initial_delay we need to add a dummy event so that we can track
751d3dbf43cSArnaldo Carvalho de Melo 	 * PERF_RECORD_MMAP while we wait for the initial delay to enable the
752d3dbf43cSArnaldo Carvalho de Melo 	 * real events, the ones asked by the user.
753d3dbf43cSArnaldo Carvalho de Melo 	 */
754d3dbf43cSArnaldo Carvalho de Melo 	if (opts->initial_delay) {
755d3dbf43cSArnaldo Carvalho de Melo 		if (perf_evlist__add_dummy(evlist))
756d3dbf43cSArnaldo Carvalho de Melo 			return -ENOMEM;
757d3dbf43cSArnaldo Carvalho de Melo 
758d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__first(evlist);
759d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 0;
760d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__last(evlist);
761d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 1;
7621fc632ceSJiri Olsa 		pos->core.attr.enable_on_exec = 1;
763d3dbf43cSArnaldo Carvalho de Melo 	}
764d3dbf43cSArnaldo Carvalho de Melo 
765e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
766cac21425SJiri Olsa 
767e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
7683da297a6SIngo Molnar try_again:
769af663bd0SJiri Olsa 		if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) {
77056e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
771bb963e16SNamhyung Kim 				if (verbose > 0)
772c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
7733da297a6SIngo Molnar 				goto try_again;
7743da297a6SIngo Molnar 			}
775cf99ad14SAndi Kleen 			if ((errno == EINVAL || errno == EBADF) &&
776cf99ad14SAndi Kleen 			    pos->leader != pos &&
777cf99ad14SAndi Kleen 			    pos->weak_group) {
778cf99ad14SAndi Kleen 			        pos = perf_evlist__reset_weak_group(evlist, pos);
779cf99ad14SAndi Kleen 				goto try_again;
780cf99ad14SAndi Kleen 			}
78156e52e85SArnaldo Carvalho de Melo 			rc = -errno;
78256e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
78356e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
78456e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
7858d3eca20SDavid Ahern 			goto out;
7867c6a1c65SPeter Zijlstra 		}
787bfd8f72cSAndi Kleen 
788bfd8f72cSAndi Kleen 		pos->supported = true;
7897c6a1c65SPeter Zijlstra 	}
7907c6a1c65SPeter Zijlstra 
791*c8b567c8SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(evlist)) {
792*c8b567c8SArnaldo Carvalho de Melo 		pr_warning(
793*c8b567c8SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
794*c8b567c8SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
795*c8b567c8SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
796*c8b567c8SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
797*c8b567c8SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
798*c8b567c8SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
799*c8b567c8SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
800*c8b567c8SArnaldo Carvalho de Melo 	}
801*c8b567c8SArnaldo Carvalho de Melo 
80223d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
80362d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
80423d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
805c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, msg, sizeof(msg)));
8068d3eca20SDavid Ahern 		rc = -1;
8078d3eca20SDavid Ahern 		goto out;
8080a102479SFrederic Weisbecker 	}
8090a102479SFrederic Weisbecker 
810cda57a8cSWang Nan 	rc = record__mmap(rec);
811cda57a8cSWang Nan 	if (rc)
8128d3eca20SDavid Ahern 		goto out;
8130a27d7f9SArnaldo Carvalho de Melo 
814a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
8157b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
8168d3eca20SDavid Ahern out:
8178d3eca20SDavid Ahern 	return rc;
818a91e5431SArnaldo Carvalho de Melo }
819a91e5431SArnaldo Carvalho de Melo 
820e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
821e3d59112SNamhyung Kim 				union perf_event *event,
822e3d59112SNamhyung Kim 				struct perf_sample *sample,
82332dcd021SJiri Olsa 				struct evsel *evsel,
824e3d59112SNamhyung Kim 				struct machine *machine)
825e3d59112SNamhyung Kim {
826e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
827e3d59112SNamhyung Kim 
82868588bafSJin Yao 	if (rec->evlist->first_sample_time == 0)
82968588bafSJin Yao 		rec->evlist->first_sample_time = sample->time;
830e3d59112SNamhyung Kim 
83168588bafSJin Yao 	rec->evlist->last_sample_time = sample->time;
83268588bafSJin Yao 
83368588bafSJin Yao 	if (rec->buildid_all)
83468588bafSJin Yao 		return 0;
83568588bafSJin Yao 
83668588bafSJin Yao 	rec->samples++;
837e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
838e3d59112SNamhyung Kim }
839e3d59112SNamhyung Kim 
8408c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
8416122e4e4SArnaldo Carvalho de Melo {
842f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
8436122e4e4SArnaldo Carvalho de Melo 
84445112e89SJiri Olsa 	if (perf_data__size(&rec->data) == 0)
8459f591fd7SArnaldo Carvalho de Melo 		return 0;
8469f591fd7SArnaldo Carvalho de Melo 
84700dc8657SNamhyung Kim 	/*
84800dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
84900dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
85000dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
85100dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
85200dc8657SNamhyung Kim 	 *
85300dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
85400dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
85500dc8657SNamhyung Kim 	 */
85600dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
85700dc8657SNamhyung Kim 
8586156681bSNamhyung Kim 	/*
8596156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
86068588bafSJin Yao 	 * so no need to process samples. But if timestamp_boundary is enabled,
86168588bafSJin Yao 	 * it still needs to walk on all samples to get the timestamps of
86268588bafSJin Yao 	 * first/last samples.
8636156681bSNamhyung Kim 	 */
86468588bafSJin Yao 	if (rec->buildid_all && !rec->timestamp_boundary)
8656156681bSNamhyung Kim 		rec->tool.sample = NULL;
8666156681bSNamhyung Kim 
867b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
8686122e4e4SArnaldo Carvalho de Melo }
8696122e4e4SArnaldo Carvalho de Melo 
8708115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
871a1645ce1SZhang, Yanmin {
872a1645ce1SZhang, Yanmin 	int err;
87345694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
874a1645ce1SZhang, Yanmin 	/*
875a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
876a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
877a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
878a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
879a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
880a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
881a1645ce1SZhang, Yanmin 	 */
88245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
883743eb868SArnaldo Carvalho de Melo 					     machine);
884a1645ce1SZhang, Yanmin 	if (err < 0)
885a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
88623346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
887a1645ce1SZhang, Yanmin 
888a1645ce1SZhang, Yanmin 	/*
889a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
890a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
891a1645ce1SZhang, Yanmin 	 */
89245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
8930ae617beSAdrian Hunter 						 machine);
894a1645ce1SZhang, Yanmin 	if (err < 0)
895a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
89623346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
897a1645ce1SZhang, Yanmin }
898a1645ce1SZhang, Yanmin 
89998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
90098402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
90198402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
90298402807SFrederic Weisbecker };
90398402807SFrederic Weisbecker 
904f13de660SAlexey Budankov static void record__adjust_affinity(struct record *rec, struct perf_mmap *map)
905f13de660SAlexey Budankov {
906f13de660SAlexey Budankov 	if (rec->opts.affinity != PERF_AFFINITY_SYS &&
907f13de660SAlexey Budankov 	    !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) {
908f13de660SAlexey Budankov 		CPU_ZERO(&rec->affinity_mask);
909f13de660SAlexey Budankov 		CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask);
910f13de660SAlexey Budankov 		sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask);
911f13de660SAlexey Budankov 	}
912f13de660SAlexey Budankov }
913f13de660SAlexey Budankov 
9145d7f4116SAlexey Budankov static size_t process_comp_header(void *record, size_t increment)
9155d7f4116SAlexey Budankov {
91672932371SJiri Olsa 	struct perf_record_compressed *event = record;
9175d7f4116SAlexey Budankov 	size_t size = sizeof(*event);
9185d7f4116SAlexey Budankov 
9195d7f4116SAlexey Budankov 	if (increment) {
9205d7f4116SAlexey Budankov 		event->header.size += increment;
9215d7f4116SAlexey Budankov 		return increment;
9225d7f4116SAlexey Budankov 	}
9235d7f4116SAlexey Budankov 
9245d7f4116SAlexey Budankov 	event->header.type = PERF_RECORD_COMPRESSED;
9255d7f4116SAlexey Budankov 	event->header.size = size;
9265d7f4116SAlexey Budankov 
9275d7f4116SAlexey Budankov 	return size;
9285d7f4116SAlexey Budankov }
9295d7f4116SAlexey Budankov 
9305d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size,
9315d7f4116SAlexey Budankov 			    void *src, size_t src_size)
9325d7f4116SAlexey Budankov {
9335d7f4116SAlexey Budankov 	size_t compressed;
93472932371SJiri Olsa 	size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1;
9355d7f4116SAlexey Budankov 
9365d7f4116SAlexey Budankov 	compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size,
9375d7f4116SAlexey Budankov 						     max_record_size, process_comp_header);
9385d7f4116SAlexey Budankov 
9395d7f4116SAlexey Budankov 	session->bytes_transferred += src_size;
9405d7f4116SAlexey Budankov 	session->bytes_compressed  += compressed;
9415d7f4116SAlexey Budankov 
9425d7f4116SAlexey Budankov 	return compressed;
9435d7f4116SAlexey Budankov }
9445d7f4116SAlexey Budankov 
94563503dbaSJiri Olsa static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
946470530bbSAlexey Budankov 				    bool overwrite, bool synch)
94798402807SFrederic Weisbecker {
948dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
9490e2e63ddSPeter Zijlstra 	int i;
9508d3eca20SDavid Ahern 	int rc = 0;
951a4ea0ec4SWang Nan 	struct perf_mmap *maps;
952d3d1af6fSAlexey Budankov 	int trace_fd = rec->data.file.fd;
953ef781128SAlexey Budankov 	off_t off = 0;
95498402807SFrederic Weisbecker 
955cb21686bSWang Nan 	if (!evlist)
956cb21686bSWang Nan 		return 0;
957ef149c25SAdrian Hunter 
9580b72d69aSWang Nan 	maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
959a4ea0ec4SWang Nan 	if (!maps)
960a4ea0ec4SWang Nan 		return 0;
961cb21686bSWang Nan 
9620b72d69aSWang Nan 	if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
96354cc54deSWang Nan 		return 0;
96454cc54deSWang Nan 
965d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
966d3d1af6fSAlexey Budankov 		off = record__aio_get_pos(trace_fd);
967d3d1af6fSAlexey Budankov 
968a4ea0ec4SWang Nan 	for (i = 0; i < evlist->nr_mmaps; i++) {
969470530bbSAlexey Budankov 		u64 flush = 0;
970e035f4caSJiri Olsa 		struct perf_mmap *map = &maps[i];
971a4ea0ec4SWang Nan 
972e035f4caSJiri Olsa 		if (map->base) {
973f13de660SAlexey Budankov 			record__adjust_affinity(rec, map);
974470530bbSAlexey Budankov 			if (synch) {
975470530bbSAlexey Budankov 				flush = map->flush;
976470530bbSAlexey Budankov 				map->flush = 1;
977470530bbSAlexey Budankov 			}
978d3d1af6fSAlexey Budankov 			if (!record__aio_enabled(rec)) {
979ef781128SAlexey Budankov 				if (perf_mmap__push(map, rec, record__pushfn) < 0) {
980470530bbSAlexey Budankov 					if (synch)
981470530bbSAlexey Budankov 						map->flush = flush;
9828d3eca20SDavid Ahern 					rc = -1;
9838d3eca20SDavid Ahern 					goto out;
9848d3eca20SDavid Ahern 				}
985d3d1af6fSAlexey Budankov 			} else {
986ef781128SAlexey Budankov 				if (record__aio_push(rec, map, &off) < 0) {
987d3d1af6fSAlexey Budankov 					record__aio_set_pos(trace_fd, off);
988470530bbSAlexey Budankov 					if (synch)
989470530bbSAlexey Budankov 						map->flush = flush;
990d3d1af6fSAlexey Budankov 					rc = -1;
991d3d1af6fSAlexey Budankov 					goto out;
992d3d1af6fSAlexey Budankov 				}
993d3d1af6fSAlexey Budankov 			}
994470530bbSAlexey Budankov 			if (synch)
995470530bbSAlexey Budankov 				map->flush = flush;
9968d3eca20SDavid Ahern 		}
997ef149c25SAdrian Hunter 
998e035f4caSJiri Olsa 		if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
999e035f4caSJiri Olsa 		    record__auxtrace_mmap_read(rec, map) != 0) {
1000ef149c25SAdrian Hunter 			rc = -1;
1001ef149c25SAdrian Hunter 			goto out;
1002ef149c25SAdrian Hunter 		}
100398402807SFrederic Weisbecker 	}
100498402807SFrederic Weisbecker 
1005d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
1006d3d1af6fSAlexey Budankov 		record__aio_set_pos(trace_fd, off);
1007d3d1af6fSAlexey Budankov 
1008dcabb507SJiri Olsa 	/*
1009dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
1010dcabb507SJiri Olsa 	 * at least one event.
1011dcabb507SJiri Olsa 	 */
1012dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
1013ded2b8feSJiri Olsa 		rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
10148d3eca20SDavid Ahern 
10150b72d69aSWang Nan 	if (overwrite)
101654cc54deSWang Nan 		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
10178d3eca20SDavid Ahern out:
10188d3eca20SDavid Ahern 	return rc;
101998402807SFrederic Weisbecker }
102098402807SFrederic Weisbecker 
1021470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch)
1022cb21686bSWang Nan {
1023cb21686bSWang Nan 	int err;
1024cb21686bSWang Nan 
1025470530bbSAlexey Budankov 	err = record__mmap_read_evlist(rec, rec->evlist, false, synch);
1026cb21686bSWang Nan 	if (err)
1027cb21686bSWang Nan 		return err;
1028cb21686bSWang Nan 
1029470530bbSAlexey Budankov 	return record__mmap_read_evlist(rec, rec->evlist, true, synch);
1030cb21686bSWang Nan }
1031cb21686bSWang Nan 
10328c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
103357706abcSDavid Ahern {
103457706abcSDavid Ahern 	struct perf_session *session = rec->session;
103557706abcSDavid Ahern 	int feat;
103657706abcSDavid Ahern 
103757706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
103857706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
103957706abcSDavid Ahern 
104057706abcSDavid Ahern 	if (rec->no_buildid)
104157706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
104257706abcSDavid Ahern 
1043ce9036a6SJiri Olsa 	if (!have_tracepoints(&rec->evlist->core.entries))
104457706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
104557706abcSDavid Ahern 
104657706abcSDavid Ahern 	if (!rec->opts.branch_stack)
104757706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
1048ef149c25SAdrian Hunter 
1049ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
1050ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
1051ffa517adSJiri Olsa 
1052cf790516SAlexey Budankov 	if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
1053cf790516SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_CLOCKID);
1054cf790516SAlexey Budankov 
1055258031c0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
105642e1fd80SAlexey Budankov 	if (!record__comp_enabled(rec))
105742e1fd80SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_COMPRESSED);
1058258031c0SJiri Olsa 
1059ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
106057706abcSDavid Ahern }
106157706abcSDavid Ahern 
1062e1ab48baSWang Nan static void
1063e1ab48baSWang Nan record__finish_output(struct record *rec)
1064e1ab48baSWang Nan {
10658ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
10668ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
1067e1ab48baSWang Nan 
10688ceb41d7SJiri Olsa 	if (data->is_pipe)
1069e1ab48baSWang Nan 		return;
1070e1ab48baSWang Nan 
1071e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
107245112e89SJiri Olsa 	data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
1073e1ab48baSWang Nan 
1074e1ab48baSWang Nan 	if (!rec->no_buildid) {
1075e1ab48baSWang Nan 		process_buildids(rec);
1076e1ab48baSWang Nan 
1077e1ab48baSWang Nan 		if (rec->buildid_all)
1078e1ab48baSWang Nan 			dsos__hit_all(rec->session);
1079e1ab48baSWang Nan 	}
1080e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
1081e1ab48baSWang Nan 
1082e1ab48baSWang Nan 	return;
1083e1ab48baSWang Nan }
1084e1ab48baSWang Nan 
10854ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
1086be7b0c9eSWang Nan {
10879d6aae72SArnaldo Carvalho de Melo 	int err;
10889749b90eSJiri Olsa 	struct perf_thread_map *thread_map;
1089be7b0c9eSWang Nan 
10904ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
10914ea648aeSWang Nan 		return 0;
10924ea648aeSWang Nan 
10939d6aae72SArnaldo Carvalho de Melo 	thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
10949d6aae72SArnaldo Carvalho de Melo 	if (thread_map == NULL)
10959d6aae72SArnaldo Carvalho de Melo 		return -1;
10969d6aae72SArnaldo Carvalho de Melo 
10979d6aae72SArnaldo Carvalho de Melo 	err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
1098be7b0c9eSWang Nan 						 process_synthesized_event,
1099be7b0c9eSWang Nan 						 &rec->session->machines.host,
11003fcb10e4SMark Drayton 						 rec->opts.sample_address);
11017836e52eSJiri Olsa 	perf_thread_map__put(thread_map);
11029d6aae72SArnaldo Carvalho de Melo 	return err;
1103be7b0c9eSWang Nan }
1104be7b0c9eSWang Nan 
11054ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
11063c1cb7e3SWang Nan 
1107ecfd7a9cSWang Nan static int
1108ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
1109ecfd7a9cSWang Nan {
11108ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1111ecfd7a9cSWang Nan 	int fd, err;
111203724b2eSAndi Kleen 	char *new_filename;
1113ecfd7a9cSWang Nan 
1114ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
1115ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
1116ecfd7a9cSWang Nan 
1117d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
1118d3d1af6fSAlexey Budankov 
11194ea648aeSWang Nan 	record__synthesize(rec, true);
11204ea648aeSWang Nan 	if (target__none(&rec->opts.target))
11214ea648aeSWang Nan 		record__synthesize_workload(rec, true);
11224ea648aeSWang Nan 
1123ecfd7a9cSWang Nan 	rec->samples = 0;
1124ecfd7a9cSWang Nan 	record__finish_output(rec);
1125ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
1126ecfd7a9cSWang Nan 	if (err) {
1127ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
1128ecfd7a9cSWang Nan 		return -EINVAL;
1129ecfd7a9cSWang Nan 	}
1130ecfd7a9cSWang Nan 
11318ceb41d7SJiri Olsa 	fd = perf_data__switch(data, timestamp,
1132ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
113303724b2eSAndi Kleen 				    at_exit, &new_filename);
1134ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
1135ecfd7a9cSWang Nan 		rec->bytes_written = 0;
1136ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
1137ecfd7a9cSWang Nan 	}
1138ecfd7a9cSWang Nan 
1139ecfd7a9cSWang Nan 	if (!quiet)
1140ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
11412d4f2799SJiri Olsa 			data->path, timestamp);
11423c1cb7e3SWang Nan 
114303724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
114403724b2eSAndi Kleen 		int n = rec->switch_output.cur_file + 1;
114503724b2eSAndi Kleen 
114603724b2eSAndi Kleen 		if (n >= rec->switch_output.num_files)
114703724b2eSAndi Kleen 			n = 0;
114803724b2eSAndi Kleen 		rec->switch_output.cur_file = n;
114903724b2eSAndi Kleen 		if (rec->switch_output.filenames[n]) {
115003724b2eSAndi Kleen 			remove(rec->switch_output.filenames[n]);
1151d8f9da24SArnaldo Carvalho de Melo 			zfree(&rec->switch_output.filenames[n]);
115203724b2eSAndi Kleen 		}
115303724b2eSAndi Kleen 		rec->switch_output.filenames[n] = new_filename;
115403724b2eSAndi Kleen 	} else {
115503724b2eSAndi Kleen 		free(new_filename);
115603724b2eSAndi Kleen 	}
115703724b2eSAndi Kleen 
11583c1cb7e3SWang Nan 	/* Output tracking events */
1159be7b0c9eSWang Nan 	if (!at_exit) {
11604ea648aeSWang Nan 		record__synthesize(rec, false);
11613c1cb7e3SWang Nan 
1162be7b0c9eSWang Nan 		/*
1163be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
1164be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
1165be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
1166be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
1167be7b0c9eSWang Nan 		 * contain map and comm information.
1168be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
1169be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
1170be7b0c9eSWang Nan 		 */
1171be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
11724ea648aeSWang Nan 			record__synthesize_workload(rec, false);
1173be7b0c9eSWang Nan 	}
1174ecfd7a9cSWang Nan 	return fd;
1175ecfd7a9cSWang Nan }
1176ecfd7a9cSWang Nan 
1177f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
1178f33cbe72SArnaldo Carvalho de Melo 
1179f33cbe72SArnaldo Carvalho de Melo /*
1180f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
1181f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
1182f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
1183f33cbe72SArnaldo Carvalho de Melo  */
118445604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
118545604710SNamhyung Kim 					siginfo_t *info,
1186f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
1187f33cbe72SArnaldo Carvalho de Melo {
1188f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
1189f33cbe72SArnaldo Carvalho de Melo 	done = 1;
1190f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
1191f33cbe72SArnaldo Carvalho de Melo }
1192f33cbe72SArnaldo Carvalho de Melo 
11932dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
1194bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
11952dd6d8a1SAdrian Hunter 
1196ee667f94SWang Nan static const struct perf_event_mmap_page *
119763503dbaSJiri Olsa perf_evlist__pick_pc(struct evlist *evlist)
1198ee667f94SWang Nan {
1199b2cb615dSWang Nan 	if (evlist) {
1200b2cb615dSWang Nan 		if (evlist->mmap && evlist->mmap[0].base)
1201ee667f94SWang Nan 			return evlist->mmap[0].base;
12020b72d69aSWang Nan 		if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base)
12030b72d69aSWang Nan 			return evlist->overwrite_mmap[0].base;
1204b2cb615dSWang Nan 	}
1205ee667f94SWang Nan 	return NULL;
1206ee667f94SWang Nan }
1207ee667f94SWang Nan 
1208c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
1209c45628b0SWang Nan {
1210ee667f94SWang Nan 	const struct perf_event_mmap_page *pc;
1211ee667f94SWang Nan 
1212ee667f94SWang Nan 	pc = perf_evlist__pick_pc(rec->evlist);
1213ee667f94SWang Nan 	if (pc)
1214ee667f94SWang Nan 		return pc;
1215c45628b0SWang Nan 	return NULL;
1216c45628b0SWang Nan }
1217c45628b0SWang Nan 
12184ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
1219c45c86ebSWang Nan {
1220c45c86ebSWang Nan 	struct perf_session *session = rec->session;
1221c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
12228ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1223c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
1224c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
12258ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
1226c45c86ebSWang Nan 	int err = 0;
1227c45c86ebSWang Nan 
12284ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
12294ea648aeSWang Nan 		return 0;
12304ea648aeSWang Nan 
12318ceb41d7SJiri Olsa 	if (data->is_pipe) {
1232a2015516SJiri Olsa 		/*
1233a2015516SJiri Olsa 		 * We need to synthesize events first, because some
1234a2015516SJiri Olsa 		 * features works on top of them (on report side).
1235a2015516SJiri Olsa 		 */
1236318ec184SJiri Olsa 		err = perf_event__synthesize_attrs(tool, rec->evlist,
1237c45c86ebSWang Nan 						   process_synthesized_event);
1238c45c86ebSWang Nan 		if (err < 0) {
1239c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
1240c45c86ebSWang Nan 			goto out;
1241c45c86ebSWang Nan 		}
1242c45c86ebSWang Nan 
1243a2015516SJiri Olsa 		err = perf_event__synthesize_features(tool, session, rec->evlist,
1244a2015516SJiri Olsa 						      process_synthesized_event);
1245a2015516SJiri Olsa 		if (err < 0) {
1246a2015516SJiri Olsa 			pr_err("Couldn't synthesize features.\n");
1247a2015516SJiri Olsa 			return err;
1248a2015516SJiri Olsa 		}
1249a2015516SJiri Olsa 
1250ce9036a6SJiri Olsa 		if (have_tracepoints(&rec->evlist->core.entries)) {
1251c45c86ebSWang Nan 			/*
1252c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
1253c45c86ebSWang Nan 			 * there were no tracepoints so its not really
1254c45c86ebSWang Nan 			 * an error, just that we don't need to
1255c45c86ebSWang Nan 			 * synthesize anything.  We really have to
1256c45c86ebSWang Nan 			 * return this more properly and also
1257c45c86ebSWang Nan 			 * propagate errors that now are calling die()
1258c45c86ebSWang Nan 			 */
1259c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
1260c45c86ebSWang Nan 								  process_synthesized_event);
1261c45c86ebSWang Nan 			if (err <= 0) {
1262c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
1263c45c86ebSWang Nan 				goto out;
1264c45c86ebSWang Nan 			}
1265c45c86ebSWang Nan 			rec->bytes_written += err;
1266c45c86ebSWang Nan 		}
1267c45c86ebSWang Nan 	}
1268c45c86ebSWang Nan 
1269c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
127046bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
127146bc29b9SAdrian Hunter 	if (err)
127246bc29b9SAdrian Hunter 		goto out;
127346bc29b9SAdrian Hunter 
1274c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
1275c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
1276c45c86ebSWang Nan 					session, process_synthesized_event);
1277c45c86ebSWang Nan 		if (err)
1278c45c86ebSWang Nan 			goto out;
1279c45c86ebSWang Nan 	}
1280c45c86ebSWang Nan 
12816c443954SArnaldo Carvalho de Melo 	if (!perf_evlist__exclude_kernel(rec->evlist)) {
1282c45c86ebSWang Nan 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
1283c45c86ebSWang Nan 							 machine);
1284c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
1285c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1286c45c86ebSWang Nan 				   "Check /proc/kallsyms permission or run as root.\n");
1287c45c86ebSWang Nan 
1288c45c86ebSWang Nan 		err = perf_event__synthesize_modules(tool, process_synthesized_event,
1289c45c86ebSWang Nan 						     machine);
1290c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
1291c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1292c45c86ebSWang Nan 				   "Check /proc/modules permission or run as root.\n");
12936c443954SArnaldo Carvalho de Melo 	}
1294c45c86ebSWang Nan 
1295c45c86ebSWang Nan 	if (perf_guest) {
1296c45c86ebSWang Nan 		machines__process_guests(&session->machines,
1297c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
1298c45c86ebSWang Nan 	}
1299c45c86ebSWang Nan 
1300bfd8f72cSAndi Kleen 	err = perf_event__synthesize_extra_attr(&rec->tool,
1301bfd8f72cSAndi Kleen 						rec->evlist,
1302bfd8f72cSAndi Kleen 						process_synthesized_event,
1303bfd8f72cSAndi Kleen 						data->is_pipe);
1304bfd8f72cSAndi Kleen 	if (err)
1305bfd8f72cSAndi Kleen 		goto out;
1306bfd8f72cSAndi Kleen 
130703617c22SJiri Olsa 	err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads,
1308373565d2SAndi Kleen 						 process_synthesized_event,
1309373565d2SAndi Kleen 						NULL);
1310373565d2SAndi Kleen 	if (err < 0) {
1311373565d2SAndi Kleen 		pr_err("Couldn't synthesize thread map.\n");
1312373565d2SAndi Kleen 		return err;
1313373565d2SAndi Kleen 	}
1314373565d2SAndi Kleen 
1315f72f901dSJiri Olsa 	err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus,
1316373565d2SAndi Kleen 					     process_synthesized_event, NULL);
1317373565d2SAndi Kleen 	if (err < 0) {
1318373565d2SAndi Kleen 		pr_err("Couldn't synthesize cpu map.\n");
1319373565d2SAndi Kleen 		return err;
1320373565d2SAndi Kleen 	}
1321373565d2SAndi Kleen 
1322e5416950SSong Liu 	err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
13237b612e29SSong Liu 						machine, opts);
13247b612e29SSong Liu 	if (err < 0)
13257b612e29SSong Liu 		pr_warning("Couldn't synthesize bpf events.\n");
13267b612e29SSong Liu 
132703617c22SJiri Olsa 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->core.threads,
1328c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
13293fcb10e4SMark Drayton 					    1);
1330c45c86ebSWang Nan out:
1331c45c86ebSWang Nan 	return err;
1332c45c86ebSWang Nan }
1333c45c86ebSWang Nan 
13348c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
133586470930SIngo Molnar {
133657706abcSDavid Ahern 	int err;
133745604710SNamhyung Kim 	int status = 0;
13388b412664SPeter Zijlstra 	unsigned long waking = 0;
133946be604bSZhang, Yanmin 	const bool forks = argc > 0;
134045694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
1341b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
13428ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1343d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
13446dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
134563503dbaSJiri Olsa 	struct evlist *sb_evlist = NULL;
134642aa276fSNamhyung Kim 	int fd;
1347d3c8c08eSAlexey Budankov 	float ratio = 0;
134886470930SIngo Molnar 
134945604710SNamhyung Kim 	atexit(record__sig_exit);
1350f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
1351f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
1352804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
1353a074865eSWang Nan 	signal(SIGSEGV, sigsegv_handler);
1354c0bdc1c4SWang Nan 
1355f3b3614aSHari Bathini 	if (rec->opts.record_namespaces)
1356f3b3614aSHari Bathini 		tool->namespace_events = true;
1357f3b3614aSHari Bathini 
1358dc0c6127SJiri Olsa 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
13592dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
13603c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
13615f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
1362dc0c6127SJiri Olsa 		if (rec->switch_output.enabled)
13633c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
1364c0bdc1c4SWang Nan 	} else {
13652dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
1366c0bdc1c4SWang Nan 	}
1367f5970550SPeter Zijlstra 
13688ceb41d7SJiri Olsa 	session = perf_session__new(data, false, tool);
13696ef81c55SMamatha Inamdar 	if (IS_ERR(session)) {
1370ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
13716ef81c55SMamatha Inamdar 		return PTR_ERR(session);
1372a9a70bbcSArnaldo Carvalho de Melo 	}
1373a9a70bbcSArnaldo Carvalho de Melo 
13748ceb41d7SJiri Olsa 	fd = perf_data__fd(data);
1375d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
1376d20deb64SArnaldo Carvalho de Melo 
13775d7f4116SAlexey Budankov 	if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) {
13785d7f4116SAlexey Budankov 		pr_err("Compression initialization failed.\n");
13795d7f4116SAlexey Budankov 		return -1;
13805d7f4116SAlexey Budankov 	}
13815d7f4116SAlexey Budankov 
13825d7f4116SAlexey Budankov 	session->header.env.comp_type  = PERF_COMP_ZSTD;
13835d7f4116SAlexey Budankov 	session->header.env.comp_level = rec->opts.comp_level;
13845d7f4116SAlexey Budankov 
13858c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
1386330aa675SStephane Eranian 
1387cf790516SAlexey Budankov 	if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
1388cf790516SAlexey Budankov 		session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
1389cf790516SAlexey Budankov 
1390d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
13913e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
13928ceb41d7SJiri Olsa 						    argv, data->is_pipe,
1393735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
139435b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
139535b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
139645604710SNamhyung Kim 			status = err;
139735b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
1398856e9660SPeter Zijlstra 		}
1399856e9660SPeter Zijlstra 	}
1400856e9660SPeter Zijlstra 
1401ad46e48cSJiri Olsa 	/*
1402ad46e48cSJiri Olsa 	 * If we have just single event and are sending data
1403ad46e48cSJiri Olsa 	 * through pipe, we need to force the ids allocation,
1404ad46e48cSJiri Olsa 	 * because we synthesize event name through the pipe
1405ad46e48cSJiri Olsa 	 * and need the id for that.
1406ad46e48cSJiri Olsa 	 */
14076484d2f9SJiri Olsa 	if (data->is_pipe && rec->evlist->core.nr_entries == 1)
1408ad46e48cSJiri Olsa 		rec->opts.sample_id = true;
1409ad46e48cSJiri Olsa 
14108c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
14118d3eca20SDavid Ahern 		err = -1;
141245604710SNamhyung Kim 		goto out_child;
14138d3eca20SDavid Ahern 	}
141442e1fd80SAlexey Budankov 	session->header.env.comp_mmap_len = session->evlist->mmap_len;
141586470930SIngo Molnar 
14168690a2a7SWang Nan 	err = bpf__apply_obj_config();
14178690a2a7SWang Nan 	if (err) {
14188690a2a7SWang Nan 		char errbuf[BUFSIZ];
14198690a2a7SWang Nan 
14208690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
14218690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
14228690a2a7SWang Nan 			 errbuf);
14238690a2a7SWang Nan 		goto out_child;
14248690a2a7SWang Nan 	}
14258690a2a7SWang Nan 
1426cca8482cSAdrian Hunter 	/*
1427cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
1428cca8482cSAdrian Hunter 	 * evlist.
1429cca8482cSAdrian Hunter 	 */
1430cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
1431cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
1432cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
1433cca8482cSAdrian Hunter 	}
1434cca8482cSAdrian Hunter 
14353e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
1436a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
1437a8bb559bSNamhyung Kim 
14388ceb41d7SJiri Olsa 	if (data->is_pipe) {
143942aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
1440529870e3STom Zanussi 		if (err < 0)
144145604710SNamhyung Kim 			goto out_child;
1442563aecb2SJiri Olsa 	} else {
144342aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
1444d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
144545604710SNamhyung Kim 			goto out_child;
1446d5eed904SArnaldo Carvalho de Melo 	}
14477c6a1c65SPeter Zijlstra 
1448d3665498SDavid Ahern 	if (!rec->no_buildid
1449e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
1450d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
1451e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
14528d3eca20SDavid Ahern 		err = -1;
145345604710SNamhyung Kim 		goto out_child;
1454e20960c0SRobert Richter 	}
1455e20960c0SRobert Richter 
1456d56354dcSSong Liu 	if (!opts->no_bpf_event)
1457d56354dcSSong Liu 		bpf_event__add_sb_event(&sb_evlist, &session->header.env);
1458d56354dcSSong Liu 
1459657ee553SSong Liu 	if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) {
1460657ee553SSong Liu 		pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
1461657ee553SSong Liu 		opts->no_bpf_event = true;
1462657ee553SSong Liu 	}
1463657ee553SSong Liu 
14644ea648aeSWang Nan 	err = record__synthesize(rec, false);
1465c45c86ebSWang Nan 	if (err < 0)
146645604710SNamhyung Kim 		goto out_child;
14678d3eca20SDavid Ahern 
1468d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
146986470930SIngo Molnar 		struct sched_param param;
147086470930SIngo Molnar 
1471d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
147286470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
14736beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
14748d3eca20SDavid Ahern 			err = -1;
147545604710SNamhyung Kim 			goto out_child;
147686470930SIngo Molnar 		}
147786470930SIngo Molnar 	}
147886470930SIngo Molnar 
1479774cb499SJiri Olsa 	/*
1480774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
1481774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
1482774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
1483774cb499SJiri Olsa 	 */
14846619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
14851c87f165SJiri Olsa 		evlist__enable(rec->evlist);
1486764e16a3SDavid Ahern 
1487856e9660SPeter Zijlstra 	/*
1488856e9660SPeter Zijlstra 	 * Let the child rip
1489856e9660SPeter Zijlstra 	 */
1490e803cf97SNamhyung Kim 	if (forks) {
149120a8a3cfSJiri Olsa 		struct machine *machine = &session->machines.host;
1492e5bed564SNamhyung Kim 		union perf_event *event;
1493e907caf3SHari Bathini 		pid_t tgid;
1494e5bed564SNamhyung Kim 
1495e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
1496e5bed564SNamhyung Kim 		if (event == NULL) {
1497e5bed564SNamhyung Kim 			err = -ENOMEM;
1498e5bed564SNamhyung Kim 			goto out_child;
1499e5bed564SNamhyung Kim 		}
1500e5bed564SNamhyung Kim 
1501e803cf97SNamhyung Kim 		/*
1502e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
1503e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
1504e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
1505e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
1506e803cf97SNamhyung Kim 		 */
1507e907caf3SHari Bathini 		tgid = perf_event__synthesize_comm(tool, event,
1508e803cf97SNamhyung Kim 						   rec->evlist->workload.pid,
1509e803cf97SNamhyung Kim 						   process_synthesized_event,
1510e803cf97SNamhyung Kim 						   machine);
1511e5bed564SNamhyung Kim 		free(event);
1512e803cf97SNamhyung Kim 
1513e907caf3SHari Bathini 		if (tgid == -1)
1514e907caf3SHari Bathini 			goto out_child;
1515e907caf3SHari Bathini 
1516e907caf3SHari Bathini 		event = malloc(sizeof(event->namespaces) +
1517e907caf3SHari Bathini 			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
1518e907caf3SHari Bathini 			       machine->id_hdr_size);
1519e907caf3SHari Bathini 		if (event == NULL) {
1520e907caf3SHari Bathini 			err = -ENOMEM;
1521e907caf3SHari Bathini 			goto out_child;
1522e907caf3SHari Bathini 		}
1523e907caf3SHari Bathini 
1524e907caf3SHari Bathini 		/*
1525e907caf3SHari Bathini 		 * Synthesize NAMESPACES event for the command specified.
1526e907caf3SHari Bathini 		 */
1527e907caf3SHari Bathini 		perf_event__synthesize_namespaces(tool, event,
1528e907caf3SHari Bathini 						  rec->evlist->workload.pid,
1529e907caf3SHari Bathini 						  tgid, process_synthesized_event,
1530e907caf3SHari Bathini 						  machine);
1531e907caf3SHari Bathini 		free(event);
1532e907caf3SHari Bathini 
15333e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
1534e803cf97SNamhyung Kim 	}
1535856e9660SPeter Zijlstra 
15366619a53eSAndi Kleen 	if (opts->initial_delay) {
15370693e680SArnaldo Carvalho de Melo 		usleep(opts->initial_delay * USEC_PER_MSEC);
15381c87f165SJiri Olsa 		evlist__enable(rec->evlist);
15396619a53eSAndi Kleen 	}
15406619a53eSAndi Kleen 
15415f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
15423c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
1543a074865eSWang Nan 	perf_hooks__invoke_record_start();
1544649c48a9SPeter Zijlstra 	for (;;) {
15459f065194SYang Shi 		unsigned long long hits = rec->samples;
154686470930SIngo Molnar 
154705737464SWang Nan 		/*
154805737464SWang Nan 		 * rec->evlist->bkw_mmap_state is possible to be
154905737464SWang Nan 		 * BKW_MMAP_EMPTY here: when done == true and
155005737464SWang Nan 		 * hits != rec->samples in previous round.
155105737464SWang Nan 		 *
155205737464SWang Nan 		 * perf_evlist__toggle_bkw_mmap ensure we never
155305737464SWang Nan 		 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
155405737464SWang Nan 		 */
155505737464SWang Nan 		if (trigger_is_hit(&switch_output_trigger) || done || draining)
155605737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
155705737464SWang Nan 
1558470530bbSAlexey Budankov 		if (record__mmap_read_all(rec, false) < 0) {
15595f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
15603c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
15618d3eca20SDavid Ahern 			err = -1;
156245604710SNamhyung Kim 			goto out_child;
15638d3eca20SDavid Ahern 		}
156486470930SIngo Molnar 
15652dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
15662dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
15675f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
1568ce7b0e42SAlexander Shishkin 				record__read_auxtrace_snapshot(rec, false);
15695f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
15702dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
15712dd6d8a1SAdrian Hunter 				err = -1;
15722dd6d8a1SAdrian Hunter 				goto out_child;
15732dd6d8a1SAdrian Hunter 			}
15742dd6d8a1SAdrian Hunter 		}
15752dd6d8a1SAdrian Hunter 
15763c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
157705737464SWang Nan 			/*
157805737464SWang Nan 			 * If switch_output_trigger is hit, the data in
157905737464SWang Nan 			 * overwritable ring buffer should have been collected,
158005737464SWang Nan 			 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
158105737464SWang Nan 			 *
158205737464SWang Nan 			 * If SIGUSR2 raise after or during record__mmap_read_all(),
158305737464SWang Nan 			 * record__mmap_read_all() didn't collect data from
158405737464SWang Nan 			 * overwritable ring buffer. Read again.
158505737464SWang Nan 			 */
158605737464SWang Nan 			if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
158705737464SWang Nan 				continue;
15883c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
15893c1cb7e3SWang Nan 
159005737464SWang Nan 			/*
159105737464SWang Nan 			 * Reenable events in overwrite ring buffer after
159205737464SWang Nan 			 * record__mmap_read_all(): we should have collected
159305737464SWang Nan 			 * data from it.
159405737464SWang Nan 			 */
159505737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
159605737464SWang Nan 
15973c1cb7e3SWang Nan 			if (!quiet)
15983c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
15993c1cb7e3SWang Nan 					waking);
16003c1cb7e3SWang Nan 			waking = 0;
16013c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
16023c1cb7e3SWang Nan 			if (fd < 0) {
16033c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
16043c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
16053c1cb7e3SWang Nan 				err = fd;
16063c1cb7e3SWang Nan 				goto out_child;
16073c1cb7e3SWang Nan 			}
1608bfacbe3bSJiri Olsa 
1609bfacbe3bSJiri Olsa 			/* re-arm the alarm */
1610bfacbe3bSJiri Olsa 			if (rec->switch_output.time)
1611bfacbe3bSJiri Olsa 				alarm(rec->switch_output.time);
16123c1cb7e3SWang Nan 		}
16133c1cb7e3SWang Nan 
1614d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
16156dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
1616649c48a9SPeter Zijlstra 				break;
1617f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
1618a515114fSJiri Olsa 			/*
1619a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
1620a515114fSJiri Olsa 			 * number of returned events and interrupt error.
1621a515114fSJiri Olsa 			 */
1622a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
162345604710SNamhyung Kim 				err = 0;
16248b412664SPeter Zijlstra 			waking++;
16256dcf45efSArnaldo Carvalho de Melo 
16266dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
16276dcf45efSArnaldo Carvalho de Melo 				draining = true;
16288b412664SPeter Zijlstra 		}
16298b412664SPeter Zijlstra 
1630774cb499SJiri Olsa 		/*
1631774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
1632774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
1633774cb499SJiri Olsa 		 * disable events in this case.
1634774cb499SJiri Olsa 		 */
1635602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
16365f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
1637e74676deSJiri Olsa 			evlist__disable(rec->evlist);
16382711926aSJiri Olsa 			disabled = true;
16392711926aSJiri Olsa 		}
16408b412664SPeter Zijlstra 	}
1641ce7b0e42SAlexander Shishkin 
16425f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
16433c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
16448b412664SPeter Zijlstra 
1645ce7b0e42SAlexander Shishkin 	if (opts->auxtrace_snapshot_on_exit)
1646ce7b0e42SAlexander Shishkin 		record__auxtrace_snapshot_exit(rec);
1647ce7b0e42SAlexander Shishkin 
1648f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
164935550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
1650c8b5f2c9SArnaldo Carvalho de Melo 		const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
1651f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
1652f33cbe72SArnaldo Carvalho de Melo 		err = -1;
165345604710SNamhyung Kim 		goto out_child;
1654f33cbe72SArnaldo Carvalho de Melo 	}
1655f33cbe72SArnaldo Carvalho de Melo 
1656e3d59112SNamhyung Kim 	if (!quiet)
16578b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
165886470930SIngo Molnar 
16594ea648aeSWang Nan 	if (target__none(&rec->opts.target))
16604ea648aeSWang Nan 		record__synthesize_workload(rec, true);
16614ea648aeSWang Nan 
166245604710SNamhyung Kim out_child:
1663470530bbSAlexey Budankov 	record__mmap_read_all(rec, true);
1664d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
1665d3d1af6fSAlexey Budankov 
1666d3c8c08eSAlexey Budankov 	if (rec->session->bytes_transferred && rec->session->bytes_compressed) {
1667d3c8c08eSAlexey Budankov 		ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed;
1668d3c8c08eSAlexey Budankov 		session->header.env.comp_ratio = ratio + 0.5;
1669d3c8c08eSAlexey Budankov 	}
1670d3c8c08eSAlexey Budankov 
167145604710SNamhyung Kim 	if (forks) {
167245604710SNamhyung Kim 		int exit_status;
167345604710SNamhyung Kim 
167445604710SNamhyung Kim 		if (!child_finished)
167545604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
167645604710SNamhyung Kim 
167745604710SNamhyung Kim 		wait(&exit_status);
167845604710SNamhyung Kim 
167945604710SNamhyung Kim 		if (err < 0)
168045604710SNamhyung Kim 			status = err;
168145604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
168245604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
168345604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
168445604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
168545604710SNamhyung Kim 	} else
168645604710SNamhyung Kim 		status = err;
168745604710SNamhyung Kim 
16884ea648aeSWang Nan 	record__synthesize(rec, true);
1689e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
1690e3d59112SNamhyung Kim 	rec->samples = 0;
1691e3d59112SNamhyung Kim 
1692ecfd7a9cSWang Nan 	if (!err) {
1693ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
1694e1ab48baSWang Nan 			record__finish_output(rec);
1695ecfd7a9cSWang Nan 		} else {
1696ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
1697ecfd7a9cSWang Nan 			if (fd < 0) {
1698ecfd7a9cSWang Nan 				status = fd;
1699ecfd7a9cSWang Nan 				goto out_delete_session;
1700ecfd7a9cSWang Nan 			}
1701ecfd7a9cSWang Nan 		}
1702ecfd7a9cSWang Nan 	}
170339d17dacSArnaldo Carvalho de Melo 
1704a074865eSWang Nan 	perf_hooks__invoke_record_end();
1705a074865eSWang Nan 
1706e3d59112SNamhyung Kim 	if (!err && !quiet) {
1707e3d59112SNamhyung Kim 		char samples[128];
1708ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
1709ecfd7a9cSWang Nan 					".<timestamp>" : "";
1710e3d59112SNamhyung Kim 
1711ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
1712e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
1713e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
1714e3d59112SNamhyung Kim 		else
1715e3d59112SNamhyung Kim 			samples[0] = '\0';
1716e3d59112SNamhyung Kim 
1717d3c8c08eSAlexey Budankov 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s",
17188ceb41d7SJiri Olsa 			perf_data__size(data) / 1024.0 / 1024.0,
17192d4f2799SJiri Olsa 			data->path, postfix, samples);
1720d3c8c08eSAlexey Budankov 		if (ratio) {
1721d3c8c08eSAlexey Budankov 			fprintf(stderr,	", compressed (original %.3f MB, ratio is %.3f)",
1722d3c8c08eSAlexey Budankov 					rec->session->bytes_transferred / 1024.0 / 1024.0,
1723d3c8c08eSAlexey Budankov 					ratio);
1724d3c8c08eSAlexey Budankov 		}
1725d3c8c08eSAlexey Budankov 		fprintf(stderr, " ]\n");
1726e3d59112SNamhyung Kim 	}
1727e3d59112SNamhyung Kim 
172839d17dacSArnaldo Carvalho de Melo out_delete_session:
17295d7f4116SAlexey Budankov 	zstd_fini(&session->zstd_data);
173039d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
1731657ee553SSong Liu 
1732657ee553SSong Liu 	if (!opts->no_bpf_event)
1733657ee553SSong Liu 		perf_evlist__stop_sb_thread(sb_evlist);
173445604710SNamhyung Kim 	return status;
173586470930SIngo Molnar }
173686470930SIngo Molnar 
17370883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
173809b0fd45SJiri Olsa {
1739aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
1740a601fdffSJiri Olsa 
17410883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
174226d33022SJiri Olsa 
17430883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
174409b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
17450883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
17460883e820SArnaldo Carvalho de Melo }
17470883e820SArnaldo Carvalho de Melo 
17480883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
17490883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
17500883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
17510883e820SArnaldo Carvalho de Melo {
17520883e820SArnaldo Carvalho de Melo 	int ret;
17530883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
17540883e820SArnaldo Carvalho de Melo 
17550883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
17560883e820SArnaldo Carvalho de Melo 	if (unset) {
17570883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
17580883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
17590883e820SArnaldo Carvalho de Melo 		return 0;
17600883e820SArnaldo Carvalho de Melo 	}
17610883e820SArnaldo Carvalho de Melo 
17620883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
17630883e820SArnaldo Carvalho de Melo 	if (!ret) {
17640883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
17650883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
17660883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
17670883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
17680883e820SArnaldo Carvalho de Melo 	}
17690883e820SArnaldo Carvalho de Melo 
17700883e820SArnaldo Carvalho de Melo 	return ret;
177109b0fd45SJiri Olsa }
177209b0fd45SJiri Olsa 
1773c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
177409b0fd45SJiri Olsa 			       const char *arg,
177509b0fd45SJiri Olsa 			       int unset)
177609b0fd45SJiri Olsa {
17770883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
177826d33022SJiri Olsa }
177926d33022SJiri Olsa 
1780c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
178109b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
178209b0fd45SJiri Olsa 			 int unset __maybe_unused)
178309b0fd45SJiri Olsa {
17842ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1785c421e80bSKan Liang 
17862ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
178709b0fd45SJiri Olsa 
17882ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
17892ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1790eb853e80SJiri Olsa 
17912ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
179209b0fd45SJiri Olsa 	return 0;
179309b0fd45SJiri Olsa }
179409b0fd45SJiri Olsa 
1795eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1796eb853e80SJiri Olsa {
17977a29c087SNamhyung Kim 	struct record *rec = cb;
17987a29c087SNamhyung Kim 
17997a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
18007a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
18017a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
18027a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
18037a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
18047a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
18057a29c087SNamhyung Kim 			rec->no_buildid = true;
18067a29c087SNamhyung Kim 		else
18077a29c087SNamhyung Kim 			return -1;
18087a29c087SNamhyung Kim 		return 0;
18097a29c087SNamhyung Kim 	}
1810cff17205SYisheng Xie 	if (!strcmp(var, "record.call-graph")) {
1811cff17205SYisheng Xie 		var = "call-graph.record-mode";
1812eb853e80SJiri Olsa 		return perf_default_config(var, value, cb);
1813eb853e80SJiri Olsa 	}
181493f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
181593f20c0fSAlexey Budankov 	if (!strcmp(var, "record.aio")) {
181693f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = strtol(value, NULL, 0);
181793f20c0fSAlexey Budankov 		if (!rec->opts.nr_cblocks)
181893f20c0fSAlexey Budankov 			rec->opts.nr_cblocks = nr_cblocks_default;
181993f20c0fSAlexey Budankov 	}
182093f20c0fSAlexey Budankov #endif
1821eb853e80SJiri Olsa 
1822cff17205SYisheng Xie 	return 0;
1823cff17205SYisheng Xie }
1824cff17205SYisheng Xie 
1825814c8c38SPeter Zijlstra struct clockid_map {
1826814c8c38SPeter Zijlstra 	const char *name;
1827814c8c38SPeter Zijlstra 	int clockid;
1828814c8c38SPeter Zijlstra };
1829814c8c38SPeter Zijlstra 
1830814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1831814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1832814c8c38SPeter Zijlstra 
1833814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1834814c8c38SPeter Zijlstra 
1835814c8c38SPeter Zijlstra 
1836814c8c38SPeter Zijlstra /*
1837814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1838814c8c38SPeter Zijlstra  */
1839814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1840814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1841814c8c38SPeter Zijlstra #endif
1842814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1843814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1844814c8c38SPeter Zijlstra #endif
1845814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1846814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1847814c8c38SPeter Zijlstra #endif
1848814c8c38SPeter Zijlstra 
1849814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1850814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1851814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1852814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1853814c8c38SPeter Zijlstra 
1854814c8c38SPeter Zijlstra 	/* available for some events */
1855814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1856814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1857814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1858814c8c38SPeter Zijlstra 
1859814c8c38SPeter Zijlstra 	/* available for the lazy */
1860814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1861814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1862814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1863814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1864814c8c38SPeter Zijlstra 
1865814c8c38SPeter Zijlstra 	CLOCKID_END,
1866814c8c38SPeter Zijlstra };
1867814c8c38SPeter Zijlstra 
1868cf790516SAlexey Budankov static int get_clockid_res(clockid_t clk_id, u64 *res_ns)
1869cf790516SAlexey Budankov {
1870cf790516SAlexey Budankov 	struct timespec res;
1871cf790516SAlexey Budankov 
1872cf790516SAlexey Budankov 	*res_ns = 0;
1873cf790516SAlexey Budankov 	if (!clock_getres(clk_id, &res))
1874cf790516SAlexey Budankov 		*res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
1875cf790516SAlexey Budankov 	else
1876cf790516SAlexey Budankov 		pr_warning("WARNING: Failed to determine specified clock resolution.\n");
1877cf790516SAlexey Budankov 
1878cf790516SAlexey Budankov 	return 0;
1879cf790516SAlexey Budankov }
1880cf790516SAlexey Budankov 
1881814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1882814c8c38SPeter Zijlstra {
1883814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1884814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1885814c8c38SPeter Zijlstra 	const char *ostr = str;
1886814c8c38SPeter Zijlstra 
1887814c8c38SPeter Zijlstra 	if (unset) {
1888814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1889814c8c38SPeter Zijlstra 		return 0;
1890814c8c38SPeter Zijlstra 	}
1891814c8c38SPeter Zijlstra 
1892814c8c38SPeter Zijlstra 	/* no arg passed */
1893814c8c38SPeter Zijlstra 	if (!str)
1894814c8c38SPeter Zijlstra 		return 0;
1895814c8c38SPeter Zijlstra 
1896814c8c38SPeter Zijlstra 	/* no setting it twice */
1897814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1898814c8c38SPeter Zijlstra 		return -1;
1899814c8c38SPeter Zijlstra 
1900814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1901814c8c38SPeter Zijlstra 
1902814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1903814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1904cf790516SAlexey Budankov 		return get_clockid_res(opts->clockid, &opts->clockid_res_ns);
1905814c8c38SPeter Zijlstra 
1906814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1907814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1908814c8c38SPeter Zijlstra 		str += 6;
1909814c8c38SPeter Zijlstra 
1910814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1911814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1912814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1913cf790516SAlexey Budankov 			return get_clockid_res(opts->clockid,
1914cf790516SAlexey Budankov 					       &opts->clockid_res_ns);
1915814c8c38SPeter Zijlstra 		}
1916814c8c38SPeter Zijlstra 	}
1917814c8c38SPeter Zijlstra 
1918814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1919814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1920814c8c38SPeter Zijlstra 	return -1;
1921814c8c38SPeter Zijlstra }
1922814c8c38SPeter Zijlstra 
1923f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset)
1924f4fe11b7SAlexey Budankov {
1925f4fe11b7SAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
1926f4fe11b7SAlexey Budankov 
1927f4fe11b7SAlexey Budankov 	if (unset || !str)
1928f4fe11b7SAlexey Budankov 		return 0;
1929f4fe11b7SAlexey Budankov 
1930f4fe11b7SAlexey Budankov 	if (!strcasecmp(str, "node"))
1931f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_NODE;
1932f4fe11b7SAlexey Budankov 	else if (!strcasecmp(str, "cpu"))
1933f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_CPU;
1934f4fe11b7SAlexey Budankov 
1935f4fe11b7SAlexey Budankov 	return 0;
1936f4fe11b7SAlexey Budankov }
1937f4fe11b7SAlexey Budankov 
1938e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1939e9db1310SAdrian Hunter 				    const char *str,
1940e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1941e9db1310SAdrian Hunter {
1942e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1943e9db1310SAdrian Hunter 	char *s, *p;
1944e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1945e9db1310SAdrian Hunter 	int ret;
1946e9db1310SAdrian Hunter 
1947e9db1310SAdrian Hunter 	if (!str)
1948e9db1310SAdrian Hunter 		return -EINVAL;
1949e9db1310SAdrian Hunter 
1950e9db1310SAdrian Hunter 	s = strdup(str);
1951e9db1310SAdrian Hunter 	if (!s)
1952e9db1310SAdrian Hunter 		return -ENOMEM;
1953e9db1310SAdrian Hunter 
1954e9db1310SAdrian Hunter 	p = strchr(s, ',');
1955e9db1310SAdrian Hunter 	if (p)
1956e9db1310SAdrian Hunter 		*p = '\0';
1957e9db1310SAdrian Hunter 
1958e9db1310SAdrian Hunter 	if (*s) {
1959e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1960e9db1310SAdrian Hunter 		if (ret)
1961e9db1310SAdrian Hunter 			goto out_free;
1962e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1963e9db1310SAdrian Hunter 	}
1964e9db1310SAdrian Hunter 
1965e9db1310SAdrian Hunter 	if (!p) {
1966e9db1310SAdrian Hunter 		ret = 0;
1967e9db1310SAdrian Hunter 		goto out_free;
1968e9db1310SAdrian Hunter 	}
1969e9db1310SAdrian Hunter 
1970e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1971e9db1310SAdrian Hunter 	if (ret)
1972e9db1310SAdrian Hunter 		goto out_free;
1973e9db1310SAdrian Hunter 
1974e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1975e9db1310SAdrian Hunter 
1976e9db1310SAdrian Hunter out_free:
1977e9db1310SAdrian Hunter 	free(s);
1978e9db1310SAdrian Hunter 	return ret;
1979e9db1310SAdrian Hunter }
1980e9db1310SAdrian Hunter 
19810c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
19820c582449SJiri Olsa {
19830c582449SJiri Olsa 	u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages);
19840c582449SJiri Olsa 	struct switch_output *s = &rec->switch_output;
19850c582449SJiri Olsa 
19860c582449SJiri Olsa 	wakeup_size /= 2;
19870c582449SJiri Olsa 
19880c582449SJiri Olsa 	if (s->size < wakeup_size) {
19890c582449SJiri Olsa 		char buf[100];
19900c582449SJiri Olsa 
19910c582449SJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
19920c582449SJiri Olsa 		pr_warning("WARNING: switch-output data size lower than "
19930c582449SJiri Olsa 			   "wakeup kernel buffer size (%s) "
19940c582449SJiri Olsa 			   "expect bigger perf.data sizes\n", buf);
19950c582449SJiri Olsa 	}
19960c582449SJiri Olsa }
19970c582449SJiri Olsa 
1998cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
1999cb4e1ebbSJiri Olsa {
2000cb4e1ebbSJiri Olsa 	struct switch_output *s = &rec->switch_output;
2001dc0c6127SJiri Olsa 	static struct parse_tag tags_size[] = {
2002dc0c6127SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
2003dc0c6127SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
2004dc0c6127SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
2005dc0c6127SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
2006dc0c6127SJiri Olsa 		{ .tag  = 0 },
2007dc0c6127SJiri Olsa 	};
2008bfacbe3bSJiri Olsa 	static struct parse_tag tags_time[] = {
2009bfacbe3bSJiri Olsa 		{ .tag  = 's', .mult = 1        },
2010bfacbe3bSJiri Olsa 		{ .tag  = 'm', .mult = 60       },
2011bfacbe3bSJiri Olsa 		{ .tag  = 'h', .mult = 60*60    },
2012bfacbe3bSJiri Olsa 		{ .tag  = 'd', .mult = 60*60*24 },
2013bfacbe3bSJiri Olsa 		{ .tag  = 0 },
2014bfacbe3bSJiri Olsa 	};
2015dc0c6127SJiri Olsa 	unsigned long val;
2016cb4e1ebbSJiri Olsa 
2017cb4e1ebbSJiri Olsa 	if (!s->set)
2018cb4e1ebbSJiri Olsa 		return 0;
2019cb4e1ebbSJiri Olsa 
2020cb4e1ebbSJiri Olsa 	if (!strcmp(s->str, "signal")) {
2021cb4e1ebbSJiri Olsa 		s->signal = true;
2022cb4e1ebbSJiri Olsa 		pr_debug("switch-output with SIGUSR2 signal\n");
2023dc0c6127SJiri Olsa 		goto enabled;
2024dc0c6127SJiri Olsa 	}
2025dc0c6127SJiri Olsa 
2026dc0c6127SJiri Olsa 	val = parse_tag_value(s->str, tags_size);
2027dc0c6127SJiri Olsa 	if (val != (unsigned long) -1) {
2028dc0c6127SJiri Olsa 		s->size = val;
2029dc0c6127SJiri Olsa 		pr_debug("switch-output with %s size threshold\n", s->str);
2030dc0c6127SJiri Olsa 		goto enabled;
2031cb4e1ebbSJiri Olsa 	}
2032cb4e1ebbSJiri Olsa 
2033bfacbe3bSJiri Olsa 	val = parse_tag_value(s->str, tags_time);
2034bfacbe3bSJiri Olsa 	if (val != (unsigned long) -1) {
2035bfacbe3bSJiri Olsa 		s->time = val;
2036bfacbe3bSJiri Olsa 		pr_debug("switch-output with %s time threshold (%lu seconds)\n",
2037bfacbe3bSJiri Olsa 			 s->str, s->time);
2038bfacbe3bSJiri Olsa 		goto enabled;
2039bfacbe3bSJiri Olsa 	}
2040bfacbe3bSJiri Olsa 
2041cb4e1ebbSJiri Olsa 	return -1;
2042dc0c6127SJiri Olsa 
2043dc0c6127SJiri Olsa enabled:
2044dc0c6127SJiri Olsa 	rec->timestamp_filename = true;
2045dc0c6127SJiri Olsa 	s->enabled              = true;
20460c582449SJiri Olsa 
20470c582449SJiri Olsa 	if (s->size && !rec->opts.no_buffering)
20480c582449SJiri Olsa 		switch_output_size_warn(rec);
20490c582449SJiri Olsa 
2050dc0c6127SJiri Olsa 	return 0;
2051cb4e1ebbSJiri Olsa }
2052cb4e1ebbSJiri Olsa 
2053e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
205486470930SIngo Molnar 	"perf record [<options>] [<command>]",
205586470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
205686470930SIngo Molnar 	NULL
205786470930SIngo Molnar };
2058e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
205986470930SIngo Molnar 
2060d20deb64SArnaldo Carvalho de Melo /*
20618c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
20628c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
2063d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
2064d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
2065d20deb64SArnaldo Carvalho de Melo  *
2066d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
2067d20deb64SArnaldo Carvalho de Melo  *
2068d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
2069d20deb64SArnaldo Carvalho de Melo  */
20708c6f45a7SArnaldo Carvalho de Melo static struct record record = {
2071d20deb64SArnaldo Carvalho de Melo 	.opts = {
20728affc2b8SAndi Kleen 		.sample_time	     = true,
2073d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
2074d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
2075d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
2076447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
2077d1cb9fceSNamhyung Kim 		.target		     = {
2078d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
20793aa5939dSAdrian Hunter 			.default_per_cpu = true,
2080d1cb9fceSNamhyung Kim 		},
2081470530bbSAlexey Budankov 		.mmap_flush          = MMAP_FLUSH_DEFAULT,
2082d20deb64SArnaldo Carvalho de Melo 	},
2083e3d59112SNamhyung Kim 	.tool = {
2084e3d59112SNamhyung Kim 		.sample		= process_sample_event,
2085e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
2086cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
2087e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
2088f3b3614aSHari Bathini 		.namespaces	= perf_event__process_namespaces,
2089e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
2090e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
2091cca8482cSAdrian Hunter 		.ordered_events	= true,
2092e3d59112SNamhyung Kim 	},
2093d20deb64SArnaldo Carvalho de Melo };
20947865e817SFrederic Weisbecker 
209576a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
209676a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
209761eaa3beSArnaldo Carvalho de Melo 
20980aab2136SWang Nan static bool dry_run;
20990aab2136SWang Nan 
2100d20deb64SArnaldo Carvalho de Melo /*
2101d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
2102d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
2103b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
2104d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
2105d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
2106d20deb64SArnaldo Carvalho de Melo  */
2107efd21307SJiri Olsa static struct option __record_options[] = {
2108d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
210986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
2110f120f9d5SJiri Olsa 		     parse_events_option),
2111d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
2112c171b552SLi Zefan 		     "event filter", parse_filter),
21134ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
21144ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
21154ba1faa1SWang Nan 			   exclude_perf),
2116bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
2117d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
2118bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
2119d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
2120d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
212186470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
2122509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
2123acac03faSKirill Smelkov 		    "collect data without buffering"),
2124d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
2125daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
2126bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
212786470930SIngo Molnar 			    "system-wide collection from all CPUs"),
2128bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
2129c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
2130d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
21312d4f2799SJiri Olsa 	OPT_STRING('o', "output", &record.data.path, "file",
213286470930SIngo Molnar 		    "output file name"),
213369e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
213469e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
21352e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
21364ea648aeSWang Nan 	OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
21374ea648aeSWang Nan 		    "synthesize non-sample events at the end of output"),
2138626a6b78SWang Nan 	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
213971184c6aSSong Liu 	OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"),
2140b09c2364SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
2141b09c2364SArnaldo Carvalho de Melo 		    "Fail if the specified frequency can't be used"),
214267230479SArnaldo Carvalho de Melo 	OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
214367230479SArnaldo Carvalho de Melo 		     "profile at this frequency",
214467230479SArnaldo Carvalho de Melo 		      record__parse_freq),
2145e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
2146e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
2147e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
2148470530bbSAlexey Budankov 	OPT_CALLBACK(0, "mmap-flush", &record.opts, "number",
2149470530bbSAlexey Budankov 		     "Minimal number of bytes that is extracted from mmap data pages (default: 1)",
2150470530bbSAlexey Budankov 		     record__mmap_flush_parse),
2151d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
215243bece79SLin Ming 		    "put the counters into a counter group"),
21532ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
215409b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
215509b0fd45SJiri Olsa 			   &record_callchain_opt),
215609b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
215776a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
215809b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
2159c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
21603da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
2161b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
2162d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
2163649c48a9SPeter Zijlstra 		    "per thread counts"),
216456100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
21653b0a5daaSKan Liang 	OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
21663b0a5daaSKan Liang 		    "Record the sample physical addresses"),
2167b6f35ed7SJiri Olsa 	OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
21683abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
21693abebc55SAdrian Hunter 			&record.opts.sample_time_set,
21703abebc55SAdrian Hunter 			"Record the sample timestamps"),
2171f290aa1fSJiri Olsa 	OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set,
2172f290aa1fSJiri Olsa 			"Record the sample period"),
2173d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
2174649c48a9SPeter Zijlstra 		    "don't sample"),
2175d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
2176d2db9a98SWang Nan 			&record.no_buildid_cache_set,
2177a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
2178d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
2179d2db9a98SWang Nan 			&record.no_buildid_set,
2180baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
2181d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
2182023695d9SStephane Eranian 		     "monitor event in cgroup name only",
2183023695d9SStephane Eranian 		     parse_cgroups),
2184a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
21856619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
2186bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
2187bea03405SNamhyung Kim 		   "user to profile"),
2188a5aabdacSStephane Eranian 
2189a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
2190a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
2191a5aabdacSStephane Eranian 		     parse_branch_stack),
2192a5aabdacSStephane Eranian 
2193a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
2194a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
2195bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
219605484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
219705484298SAndi Kleen 		    "sample by weight (on special events only)"),
2198475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
2199475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
22003aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
22013aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
2202bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
2203bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
2204aeea9062SKan Liang 		    " use '-I?' to list register names", parse_intr_regs),
220584c41742SAndi Kleen 	OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
220684c41742SAndi Kleen 		    "sample selected machine registers on interrupt,"
2207aeea9062SKan Liang 		    " use '--user-regs=?' to list register names", parse_user_regs),
220885c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
220985c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
2210814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
2211814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
2212814c8c38SPeter Zijlstra 	parse_clockid),
22132dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
22142dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
22153fcb10e4SMark Drayton 	OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
22169d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
2217f3b3614aSHari Bathini 	OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
2218f3b3614aSHari Bathini 		    "Record namespaces events"),
2219b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
2220b757bb09SAdrian Hunter 		    "Record context switch events"),
222185723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
222285723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
222385723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
222485723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
222585723885SJiri Olsa 			 "Configure all used events to run in user space.",
222685723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
222753651b28Syuzhoujian 	OPT_BOOLEAN(0, "kernel-callchains", &record.opts.kernel_callchains,
222853651b28Syuzhoujian 		    "collect kernel callchains"),
222953651b28Syuzhoujian 	OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains,
223053651b28Syuzhoujian 		    "collect user callchains"),
223171dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
223271dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
223371dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
223471dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
22357efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
22367efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
22376156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
22386156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
2239ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
2240ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
224168588bafSJin Yao 	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
224268588bafSJin Yao 		    "Record timestamp boundary (time of first/last samples)"),
2243cb4e1ebbSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
2244c38dab7dSAndi Kleen 			  &record.switch_output.set, "signal or size[BKMG] or time[smhd]",
2245c38dab7dSAndi Kleen 			  "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold",
2246dc0c6127SJiri Olsa 			  "signal"),
224703724b2eSAndi Kleen 	OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
224803724b2eSAndi Kleen 		   "Limit number of switch output generated files"),
22490aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
22500aab2136SWang Nan 		    "Parse options then exit"),
2251d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
225293f20c0fSAlexey Budankov 	OPT_CALLBACK_OPTARG(0, "aio", &record.opts,
225393f20c0fSAlexey Budankov 		     &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)",
2254d3d1af6fSAlexey Budankov 		     record__aio_parse),
2255d3d1af6fSAlexey Budankov #endif
2256f4fe11b7SAlexey Budankov 	OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
2257f4fe11b7SAlexey Budankov 		     "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer",
2258f4fe11b7SAlexey Budankov 		     record__parse_affinity),
2259504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT
2260504c1ad1SAlexey Budankov 	OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default,
2261504c1ad1SAlexey Budankov 			    "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)",
2262504c1ad1SAlexey Budankov 			    record__parse_comp_level),
2263504c1ad1SAlexey Budankov #endif
226486470930SIngo Molnar 	OPT_END()
226586470930SIngo Molnar };
226686470930SIngo Molnar 
2267e5b2c207SNamhyung Kim struct option *record_options = __record_options;
2268e5b2c207SNamhyung Kim 
2269b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
227086470930SIngo Molnar {
2271ef149c25SAdrian Hunter 	int err;
22728c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
227316ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
227486470930SIngo Molnar 
227567230479SArnaldo Carvalho de Melo 	setlocale(LC_ALL, "");
227667230479SArnaldo Carvalho de Melo 
227748e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
227848e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
227948e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
228048e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
228148e1cab1SWang Nan # undef set_nobuild
228248e1cab1SWang Nan #endif
228348e1cab1SWang Nan 
22847efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
22857efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
22867efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
22877efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
22887efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
22897efe0e03SHe Kuang # else
22907efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
22917efe0e03SHe Kuang # endif
22927efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
22937efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
22947efe0e03SHe Kuang # undef set_nobuild
22957efe0e03SHe Kuang # undef REASON
22967efe0e03SHe Kuang #endif
22977efe0e03SHe Kuang 
22989d2ed645SAlexey Budankov 	CPU_ZERO(&rec->affinity_mask);
22999d2ed645SAlexey Budankov 	rec->opts.affinity = PERF_AFFINITY_SYS;
23009d2ed645SAlexey Budankov 
23010f98b11cSJiri Olsa 	rec->evlist = evlist__new();
23023e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
2303361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
2304361c99a6SArnaldo Carvalho de Melo 
2305ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(perf_record_config, rec);
2306ecc4c561SArnaldo Carvalho de Melo 	if (err)
2307ecc4c561SArnaldo Carvalho de Melo 		return err;
2308eb853e80SJiri Olsa 
2309bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
2310a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
231168ba3235SNamhyung Kim 	if (quiet)
231268ba3235SNamhyung Kim 		perf_quiet_option();
2313483635a9SJiri Olsa 
2314483635a9SJiri Olsa 	/* Make system wide (-a) the default target. */
2315602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
2316483635a9SJiri Olsa 		rec->opts.target.system_wide = true;
231786470930SIngo Molnar 
2318bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
2319c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
2320c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
2321c7118369SNamhyung Kim 
2322023695d9SStephane Eranian 	}
2323504c1ad1SAlexey Budankov 
2324504c1ad1SAlexey Budankov 	if (rec->opts.comp_level != 0) {
2325504c1ad1SAlexey Budankov 		pr_debug("Compression enabled, disabling build id collection at the end of the session.\n");
2326504c1ad1SAlexey Budankov 		rec->no_buildid = true;
2327504c1ad1SAlexey Budankov 	}
2328504c1ad1SAlexey Budankov 
2329b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
2330b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
2331c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
2332c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
2333c7118369SNamhyung Kim 		return -EINVAL;
2334b757bb09SAdrian Hunter 	}
2335023695d9SStephane Eranian 
2336cb4e1ebbSJiri Olsa 	if (switch_output_setup(rec)) {
2337cb4e1ebbSJiri Olsa 		parse_options_usage(record_usage, record_options, "switch-output", 0);
2338cb4e1ebbSJiri Olsa 		return -EINVAL;
2339cb4e1ebbSJiri Olsa 	}
2340cb4e1ebbSJiri Olsa 
2341bfacbe3bSJiri Olsa 	if (rec->switch_output.time) {
2342bfacbe3bSJiri Olsa 		signal(SIGALRM, alarm_sig_handler);
2343bfacbe3bSJiri Olsa 		alarm(rec->switch_output.time);
2344bfacbe3bSJiri Olsa 	}
2345bfacbe3bSJiri Olsa 
234603724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
234703724b2eSAndi Kleen 		rec->switch_output.filenames = calloc(sizeof(char *),
234803724b2eSAndi Kleen 						      rec->switch_output.num_files);
234903724b2eSAndi Kleen 		if (!rec->switch_output.filenames)
235003724b2eSAndi Kleen 			return -EINVAL;
235103724b2eSAndi Kleen 	}
235203724b2eSAndi Kleen 
23531b36c03eSAdrian Hunter 	/*
23541b36c03eSAdrian Hunter 	 * Allow aliases to facilitate the lookup of symbols for address
23551b36c03eSAdrian Hunter 	 * filters. Refer to auxtrace_parse_filters().
23561b36c03eSAdrian Hunter 	 */
23571b36c03eSAdrian Hunter 	symbol_conf.allow_aliases = true;
23581b36c03eSAdrian Hunter 
23591b36c03eSAdrian Hunter 	symbol__init(NULL);
23601b36c03eSAdrian Hunter 
23614b5ea3bdSAdrian Hunter 	err = record__auxtrace_init(rec);
23621b36c03eSAdrian Hunter 	if (err)
23631b36c03eSAdrian Hunter 		goto out;
23641b36c03eSAdrian Hunter 
23650aab2136SWang Nan 	if (dry_run)
23665c01ad60SAdrian Hunter 		goto out;
23670aab2136SWang Nan 
2368d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
2369d7888573SWang Nan 	if (err) {
2370d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
2371d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
2372d7888573SWang Nan 			 errbuf);
23735c01ad60SAdrian Hunter 		goto out;
2374d7888573SWang Nan 	}
2375d7888573SWang Nan 
2376ef149c25SAdrian Hunter 	err = -ENOMEM;
2377ef149c25SAdrian Hunter 
23780c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
2379a1ac1d3cSStephane Eranian 		disable_buildid_cache();
2380dc0c6127SJiri Olsa 	} else if (rec->switch_output.enabled) {
23810c1d46a8SWang Nan 		/*
23820c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
23830c1d46a8SWang Nan 		 * generation by default to reduce data file switching
23840c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
23850c1d46a8SWang Nan 		 * explicitly using
23860c1d46a8SWang Nan 		 *
238760437ac0SJiri Olsa 		 *  perf record --switch-output --no-no-buildid \
23880c1d46a8SWang Nan 		 *              --no-no-buildid-cache
23890c1d46a8SWang Nan 		 *
23900c1d46a8SWang Nan 		 * Following code equals to:
23910c1d46a8SWang Nan 		 *
23920c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
23930c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
23940c1d46a8SWang Nan 		 *         disable_buildid_cache();
23950c1d46a8SWang Nan 		 */
23960c1d46a8SWang Nan 		bool disable = true;
23970c1d46a8SWang Nan 
23980c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
23990c1d46a8SWang Nan 			disable = false;
24000c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
24010c1d46a8SWang Nan 			disable = false;
24020c1d46a8SWang Nan 		if (disable) {
24030c1d46a8SWang Nan 			rec->no_buildid = true;
24040c1d46a8SWang Nan 			rec->no_buildid_cache = true;
24050c1d46a8SWang Nan 			disable_buildid_cache();
24060c1d46a8SWang Nan 		}
24070c1d46a8SWang Nan 	}
2408655000e7SArnaldo Carvalho de Melo 
24094ea648aeSWang Nan 	if (record.opts.overwrite)
24104ea648aeSWang Nan 		record.opts.tail_synthesize = true;
24114ea648aeSWang Nan 
24126484d2f9SJiri Olsa 	if (rec->evlist->core.nr_entries == 0 &&
24134b4cd503SArnaldo Carvalho de Melo 	    __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
241469aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
2415394c01edSAdrian Hunter 		goto out;
2416bbd36e5eSPeter Zijlstra 	}
241786470930SIngo Molnar 
241869e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
241969e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
242069e7e5b0SAdrian Hunter 
2421602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
242216ad2ffbSNamhyung Kim 	if (err) {
2423602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
2424c3dec27bSJiri Olsa 		ui__warning("%s\n", errbuf);
242516ad2ffbSNamhyung Kim 	}
24264bd0f2d2SNamhyung Kim 
2427602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
242816ad2ffbSNamhyung Kim 	if (err) {
242916ad2ffbSNamhyung Kim 		int saved_errno = errno;
243016ad2ffbSNamhyung Kim 
2431602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
24323780f488SNamhyung Kim 		ui__error("%s", errbuf);
243316ad2ffbSNamhyung Kim 
243416ad2ffbSNamhyung Kim 		err = -saved_errno;
2435394c01edSAdrian Hunter 		goto out;
243616ad2ffbSNamhyung Kim 	}
24370d37aa34SArnaldo Carvalho de Melo 
2438ca800068SMengting Zhang 	/* Enable ignoring missing threads when -u/-p option is defined. */
2439ca800068SMengting Zhang 	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
244023dc4f15SJiri Olsa 
244116ad2ffbSNamhyung Kim 	err = -ENOMEM;
24423e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
2443dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
244469aad6f1SArnaldo Carvalho de Melo 
2445ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
2446ef149c25SAdrian Hunter 	if (err)
2447394c01edSAdrian Hunter 		goto out;
2448ef149c25SAdrian Hunter 
24496156681bSNamhyung Kim 	/*
24506156681bSNamhyung Kim 	 * We take all buildids when the file contains
24516156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
24526156681bSNamhyung Kim 	 * trace because it would take too long.
24536156681bSNamhyung Kim 	 */
24546156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
24556156681bSNamhyung Kim 		rec->buildid_all = true;
24566156681bSNamhyung Kim 
2457b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
245839d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
2459394c01edSAdrian Hunter 		goto out;
24607e4ff9e3SMike Galbraith 	}
24617e4ff9e3SMike Galbraith 
246293f20c0fSAlexey Budankov 	if (rec->opts.nr_cblocks > nr_cblocks_max)
246393f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = nr_cblocks_max;
24645d7f4116SAlexey Budankov 	pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks);
2465d3d1af6fSAlexey Budankov 
24669d2ed645SAlexey Budankov 	pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]);
2467470530bbSAlexey Budankov 	pr_debug("mmap flush: %d\n", rec->opts.mmap_flush);
24689d2ed645SAlexey Budankov 
246951255a8aSAlexey Budankov 	if (rec->opts.comp_level > comp_level_max)
247051255a8aSAlexey Budankov 		rec->opts.comp_level = comp_level_max;
247151255a8aSAlexey Budankov 	pr_debug("comp level: %d\n", rec->opts.comp_level);
247251255a8aSAlexey Budankov 
2473d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
2474394c01edSAdrian Hunter out:
2475c12995a5SJiri Olsa 	evlist__delete(rec->evlist);
2476d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
2477ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
247839d17dacSArnaldo Carvalho de Melo 	return err;
247986470930SIngo Molnar }
24802dd6d8a1SAdrian Hunter 
24812dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
24822dd6d8a1SAdrian Hunter {
2483dc0c6127SJiri Olsa 	struct record *rec = &record;
2484dc0c6127SJiri Olsa 
24855f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
24865f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
24872dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
24885f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
24895f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
24905f9cf599SWang Nan 	}
24913c1cb7e3SWang Nan 
2492dc0c6127SJiri Olsa 	if (switch_output_signal(rec))
24933c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
24942dd6d8a1SAdrian Hunter }
2495bfacbe3bSJiri Olsa 
2496bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
2497bfacbe3bSJiri Olsa {
2498bfacbe3bSJiri Olsa 	struct record *rec = &record;
2499bfacbe3bSJiri Olsa 
2500bfacbe3bSJiri Olsa 	if (switch_output_time(rec))
2501bfacbe3bSJiri Olsa 		trigger_hit(&switch_output_trigger);
2502bfacbe3bSJiri Olsa }
2503