xref: /openbmc/linux/tools/perf/builtin-record.c (revision 4804e0111662d7d89edf4e767a64c6f7e4778bb1)
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"
23e0fcfb08SArnaldo Carvalho de Melo #include "util/mmap.h"
24aeb00b1aSArnaldo Carvalho de Melo #include "util/target.h"
2594c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2645694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
278d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
28aeb00b1aSArnaldo Carvalho de Melo #include "util/record.h"
29a12b51c4SPaul Mackerras #include "util/cpumap.h"
30fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
31f5fc1412SJiri Olsa #include "util/data.h"
32bcc84ec6SStephane Eranian #include "util/perf_regs.h"
33ef149c25SAdrian Hunter #include "util/auxtrace.h"
3446bc29b9SAdrian Hunter #include "util/tsc.h"
35f00898f4SAndi Kleen #include "util/parse-branch-options.h"
36bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3771dc2326SWang Nan #include "util/llvm-utils.h"
388690a2a7SWang Nan #include "util/bpf-loader.h"
395f9cf599SWang Nan #include "util/trigger.h"
40a074865eSWang Nan #include "util/perf-hooks.h"
41f13de660SAlexey Budankov #include "util/cpu-set-sched.h"
42ea49e01cSArnaldo Carvalho de Melo #include "util/synthetic-events.h"
43c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h"
4458db1d6eSArnaldo Carvalho de Melo #include "util/units.h"
457b612e29SSong Liu #include "util/bpf-event.h"
46d8871ea7SWang Nan #include "asm/bug.h"
47c1a604dfSArnaldo Carvalho de Melo #include "perf.h"
487c6a1c65SPeter Zijlstra 
49a43783aeSArnaldo Carvalho de Melo #include <errno.h>
50fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
5167230479SArnaldo Carvalho de Melo #include <locale.h>
524208735dSArnaldo Carvalho de Melo #include <poll.h>
5386470930SIngo Molnar #include <unistd.h>
5486470930SIngo Molnar #include <sched.h>
559607ad3aSArnaldo Carvalho de Melo #include <signal.h>
56a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
574208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
58eeb399b5SAdrian Hunter #include <sys/types.h>
59eeb399b5SAdrian Hunter #include <sys/stat.h>
60eeb399b5SAdrian Hunter #include <fcntl.h>
616ef81c55SMamatha Inamdar #include <linux/err.h>
628520a98dSArnaldo Carvalho de Melo #include <linux/string.h>
630693e680SArnaldo Carvalho de Melo #include <linux/time64.h>
64d8f9da24SArnaldo Carvalho de Melo #include <linux/zalloc.h>
6578da39faSBernhard Rosenkraenzer 
661b43b704SJiri Olsa struct switch_output {
67dc0c6127SJiri Olsa 	bool		 enabled;
681b43b704SJiri Olsa 	bool		 signal;
69dc0c6127SJiri Olsa 	unsigned long	 size;
70bfacbe3bSJiri Olsa 	unsigned long	 time;
71cb4e1ebbSJiri Olsa 	const char	*str;
72cb4e1ebbSJiri Olsa 	bool		 set;
7303724b2eSAndi Kleen 	char		 **filenames;
7403724b2eSAndi Kleen 	int		 num_files;
7503724b2eSAndi Kleen 	int		 cur_file;
761b43b704SJiri Olsa };
771b43b704SJiri Olsa 
788c6f45a7SArnaldo Carvalho de Melo struct record {
7945694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
80b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
81d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
828ceb41d7SJiri Olsa 	struct perf_data	data;
83ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
8463503dbaSJiri Olsa 	struct evlist	*evlist;
85d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
86d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
87d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
88d2db9a98SWang Nan 	bool			no_buildid_set;
89d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
90d2db9a98SWang Nan 	bool			no_buildid_cache_set;
916156681bSNamhyung Kim 	bool			buildid_all;
92ecfd7a9cSWang Nan 	bool			timestamp_filename;
9368588bafSJin Yao 	bool			timestamp_boundary;
941b43b704SJiri Olsa 	struct switch_output	switch_output;
959f065194SYang Shi 	unsigned long long	samples;
969d2ed645SAlexey Budankov 	cpu_set_t		affinity_mask;
976d575816SJiwei Sun 	unsigned long		output_max_size;	/* = 0: unlimited */
980f82ebc4SArnaldo Carvalho de Melo };
9986470930SIngo Molnar 
1006d575816SJiwei Sun static volatile int done;
1016d575816SJiwei Sun 
102dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
103dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
104dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
105dc0c6127SJiri Olsa 
1069d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = {
1079d2ed645SAlexey Budankov 	"SYS", "NODE", "CPU"
1089d2ed645SAlexey Budankov };
1099d2ed645SAlexey Budankov 
110dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
111dc0c6127SJiri Olsa {
112dc0c6127SJiri Olsa 	return rec->switch_output.signal &&
113dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
114dc0c6127SJiri Olsa }
115dc0c6127SJiri Olsa 
116dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
117dc0c6127SJiri Olsa {
118dc0c6127SJiri Olsa 	return rec->switch_output.size &&
119dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger) &&
120dc0c6127SJiri Olsa 	       (rec->bytes_written >= rec->switch_output.size);
121dc0c6127SJiri Olsa }
122dc0c6127SJiri Olsa 
123bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
124bfacbe3bSJiri Olsa {
125bfacbe3bSJiri Olsa 	return rec->switch_output.time &&
126bfacbe3bSJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
127bfacbe3bSJiri Olsa }
128bfacbe3bSJiri Olsa 
1296d575816SJiwei Sun static bool record__output_max_size_exceeded(struct record *rec)
1306d575816SJiwei Sun {
1316d575816SJiwei Sun 	return rec->output_max_size &&
1326d575816SJiwei Sun 	       (rec->bytes_written >= rec->output_max_size);
1336d575816SJiwei Sun }
1346d575816SJiwei Sun 
135a5830532SJiri Olsa static int record__write(struct record *rec, struct mmap *map __maybe_unused,
136ded2b8feSJiri Olsa 			 void *bf, size_t size)
137f5970550SPeter Zijlstra {
138ded2b8feSJiri Olsa 	struct perf_data_file *file = &rec->session->data->file;
139ded2b8feSJiri Olsa 
140ded2b8feSJiri Olsa 	if (perf_data_file__write(file, bf, size) < 0) {
1414f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
1428d3eca20SDavid Ahern 		return -1;
1438d3eca20SDavid Ahern 	}
144f5970550SPeter Zijlstra 
145cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
146dc0c6127SJiri Olsa 
1476d575816SJiwei Sun 	if (record__output_max_size_exceeded(rec) && !done) {
1486d575816SJiwei Sun 		fprintf(stderr, "[ perf record: perf size limit reached (%" PRIu64 " KB),"
1496d575816SJiwei Sun 				" stopping session ]\n",
1506d575816SJiwei Sun 				rec->bytes_written >> 10);
1516d575816SJiwei Sun 		done = 1;
1526d575816SJiwei Sun 	}
1536d575816SJiwei Sun 
154dc0c6127SJiri Olsa 	if (switch_output_size(rec))
155dc0c6127SJiri Olsa 		trigger_hit(&switch_output_trigger);
156dc0c6127SJiri Olsa 
1578d3eca20SDavid Ahern 	return 0;
158f5970550SPeter Zijlstra }
159f5970550SPeter Zijlstra 
160ef781128SAlexey Budankov static int record__aio_enabled(struct record *rec);
161ef781128SAlexey Budankov static int record__comp_enabled(struct record *rec);
1625d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size,
1635d7f4116SAlexey Budankov 			    void *src, size_t src_size);
1645d7f4116SAlexey Budankov 
165d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
166d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd,
167d3d1af6fSAlexey Budankov 		void *buf, size_t size, off_t off)
168d3d1af6fSAlexey Budankov {
169d3d1af6fSAlexey Budankov 	int rc;
170d3d1af6fSAlexey Budankov 
171d3d1af6fSAlexey Budankov 	cblock->aio_fildes = trace_fd;
172d3d1af6fSAlexey Budankov 	cblock->aio_buf    = buf;
173d3d1af6fSAlexey Budankov 	cblock->aio_nbytes = size;
174d3d1af6fSAlexey Budankov 	cblock->aio_offset = off;
175d3d1af6fSAlexey Budankov 	cblock->aio_sigevent.sigev_notify = SIGEV_NONE;
176d3d1af6fSAlexey Budankov 
177d3d1af6fSAlexey Budankov 	do {
178d3d1af6fSAlexey Budankov 		rc = aio_write(cblock);
179d3d1af6fSAlexey Budankov 		if (rc == 0) {
180d3d1af6fSAlexey Budankov 			break;
181d3d1af6fSAlexey Budankov 		} else if (errno != EAGAIN) {
182d3d1af6fSAlexey Budankov 			cblock->aio_fildes = -1;
183d3d1af6fSAlexey Budankov 			pr_err("failed to queue perf data, error: %m\n");
184d3d1af6fSAlexey Budankov 			break;
185d3d1af6fSAlexey Budankov 		}
186d3d1af6fSAlexey Budankov 	} while (1);
187d3d1af6fSAlexey Budankov 
188d3d1af6fSAlexey Budankov 	return rc;
189d3d1af6fSAlexey Budankov }
190d3d1af6fSAlexey Budankov 
191a5830532SJiri Olsa static int record__aio_complete(struct mmap *md, struct aiocb *cblock)
192d3d1af6fSAlexey Budankov {
193d3d1af6fSAlexey Budankov 	void *rem_buf;
194d3d1af6fSAlexey Budankov 	off_t rem_off;
195d3d1af6fSAlexey Budankov 	size_t rem_size;
196d3d1af6fSAlexey Budankov 	int rc, aio_errno;
197d3d1af6fSAlexey Budankov 	ssize_t aio_ret, written;
198d3d1af6fSAlexey Budankov 
199d3d1af6fSAlexey Budankov 	aio_errno = aio_error(cblock);
200d3d1af6fSAlexey Budankov 	if (aio_errno == EINPROGRESS)
201d3d1af6fSAlexey Budankov 		return 0;
202d3d1af6fSAlexey Budankov 
203d3d1af6fSAlexey Budankov 	written = aio_ret = aio_return(cblock);
204d3d1af6fSAlexey Budankov 	if (aio_ret < 0) {
205d3d1af6fSAlexey Budankov 		if (aio_errno != EINTR)
206d3d1af6fSAlexey Budankov 			pr_err("failed to write perf data, error: %m\n");
207d3d1af6fSAlexey Budankov 		written = 0;
208d3d1af6fSAlexey Budankov 	}
209d3d1af6fSAlexey Budankov 
210d3d1af6fSAlexey Budankov 	rem_size = cblock->aio_nbytes - written;
211d3d1af6fSAlexey Budankov 
212d3d1af6fSAlexey Budankov 	if (rem_size == 0) {
213d3d1af6fSAlexey Budankov 		cblock->aio_fildes = -1;
214d3d1af6fSAlexey Budankov 		/*
215ef781128SAlexey Budankov 		 * md->refcount is incremented in record__aio_pushfn() for
216ef781128SAlexey Budankov 		 * every aio write request started in record__aio_push() so
217ef781128SAlexey Budankov 		 * decrement it because the request is now complete.
218d3d1af6fSAlexey Budankov 		 */
21980e53d11SJiri Olsa 		perf_mmap__put(&md->core);
220d3d1af6fSAlexey Budankov 		rc = 1;
221d3d1af6fSAlexey Budankov 	} else {
222d3d1af6fSAlexey Budankov 		/*
223d3d1af6fSAlexey Budankov 		 * aio write request may require restart with the
224d3d1af6fSAlexey Budankov 		 * reminder if the kernel didn't write whole
225d3d1af6fSAlexey Budankov 		 * chunk at once.
226d3d1af6fSAlexey Budankov 		 */
227d3d1af6fSAlexey Budankov 		rem_off = cblock->aio_offset + written;
228d3d1af6fSAlexey Budankov 		rem_buf = (void *)(cblock->aio_buf + written);
229d3d1af6fSAlexey Budankov 		record__aio_write(cblock, cblock->aio_fildes,
230d3d1af6fSAlexey Budankov 				rem_buf, rem_size, rem_off);
231d3d1af6fSAlexey Budankov 		rc = 0;
232d3d1af6fSAlexey Budankov 	}
233d3d1af6fSAlexey Budankov 
234d3d1af6fSAlexey Budankov 	return rc;
235d3d1af6fSAlexey Budankov }
236d3d1af6fSAlexey Budankov 
237a5830532SJiri Olsa static int record__aio_sync(struct mmap *md, bool sync_all)
238d3d1af6fSAlexey Budankov {
23993f20c0fSAlexey Budankov 	struct aiocb **aiocb = md->aio.aiocb;
24093f20c0fSAlexey Budankov 	struct aiocb *cblocks = md->aio.cblocks;
241d3d1af6fSAlexey Budankov 	struct timespec timeout = { 0, 1000 * 1000  * 1 }; /* 1ms */
24293f20c0fSAlexey Budankov 	int i, do_suspend;
243d3d1af6fSAlexey Budankov 
244d3d1af6fSAlexey Budankov 	do {
24593f20c0fSAlexey Budankov 		do_suspend = 0;
24693f20c0fSAlexey Budankov 		for (i = 0; i < md->aio.nr_cblocks; ++i) {
24793f20c0fSAlexey Budankov 			if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) {
24893f20c0fSAlexey Budankov 				if (sync_all)
24993f20c0fSAlexey Budankov 					aiocb[i] = NULL;
25093f20c0fSAlexey Budankov 				else
25193f20c0fSAlexey Budankov 					return i;
25293f20c0fSAlexey Budankov 			} else {
25393f20c0fSAlexey Budankov 				/*
25493f20c0fSAlexey Budankov 				 * Started aio write is not complete yet
25593f20c0fSAlexey Budankov 				 * so it has to be waited before the
25693f20c0fSAlexey Budankov 				 * next allocation.
25793f20c0fSAlexey Budankov 				 */
25893f20c0fSAlexey Budankov 				aiocb[i] = &cblocks[i];
25993f20c0fSAlexey Budankov 				do_suspend = 1;
26093f20c0fSAlexey Budankov 			}
26193f20c0fSAlexey Budankov 		}
26293f20c0fSAlexey Budankov 		if (!do_suspend)
26393f20c0fSAlexey Budankov 			return -1;
264d3d1af6fSAlexey Budankov 
26593f20c0fSAlexey Budankov 		while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) {
266d3d1af6fSAlexey Budankov 			if (!(errno == EAGAIN || errno == EINTR))
267d3d1af6fSAlexey Budankov 				pr_err("failed to sync perf data, error: %m\n");
268d3d1af6fSAlexey Budankov 		}
269d3d1af6fSAlexey Budankov 	} while (1);
270d3d1af6fSAlexey Budankov }
271d3d1af6fSAlexey Budankov 
272ef781128SAlexey Budankov struct record_aio {
273ef781128SAlexey Budankov 	struct record	*rec;
274ef781128SAlexey Budankov 	void		*data;
275ef781128SAlexey Budankov 	size_t		size;
276ef781128SAlexey Budankov };
277ef781128SAlexey Budankov 
278a5830532SJiri Olsa static int record__aio_pushfn(struct mmap *map, void *to, void *buf, size_t size)
279d3d1af6fSAlexey Budankov {
280ef781128SAlexey Budankov 	struct record_aio *aio = to;
281ef781128SAlexey Budankov 
282ef781128SAlexey Budankov 	/*
283547740f7SJiri Olsa 	 * map->core.base data pointed by buf is copied into free map->aio.data[] buffer
284ef781128SAlexey Budankov 	 * to release space in the kernel buffer as fast as possible, calling
285ef781128SAlexey Budankov 	 * perf_mmap__consume() from perf_mmap__push() function.
286ef781128SAlexey Budankov 	 *
287ef781128SAlexey Budankov 	 * That lets the kernel to proceed with storing more profiling data into
288ef781128SAlexey Budankov 	 * the kernel buffer earlier than other per-cpu kernel buffers are handled.
289ef781128SAlexey Budankov 	 *
290ef781128SAlexey Budankov 	 * Coping can be done in two steps in case the chunk of profiling data
291ef781128SAlexey Budankov 	 * crosses the upper bound of the kernel buffer. In this case we first move
292ef781128SAlexey Budankov 	 * part of data from map->start till the upper bound and then the reminder
293ef781128SAlexey Budankov 	 * from the beginning of the kernel buffer till the end of the data chunk.
294ef781128SAlexey Budankov 	 */
295ef781128SAlexey Budankov 
296ef781128SAlexey Budankov 	if (record__comp_enabled(aio->rec)) {
297ef781128SAlexey Budankov 		size = zstd_compress(aio->rec->session, aio->data + aio->size,
298bf59b305SJiri Olsa 				     mmap__mmap_len(map) - aio->size,
299ef781128SAlexey Budankov 				     buf, size);
300ef781128SAlexey Budankov 	} else {
301ef781128SAlexey Budankov 		memcpy(aio->data + aio->size, buf, size);
302ef781128SAlexey Budankov 	}
303ef781128SAlexey Budankov 
304ef781128SAlexey Budankov 	if (!aio->size) {
305ef781128SAlexey Budankov 		/*
306ef781128SAlexey Budankov 		 * Increment map->refcount to guard map->aio.data[] buffer
307ef781128SAlexey Budankov 		 * from premature deallocation because map object can be
308ef781128SAlexey Budankov 		 * released earlier than aio write request started on
309ef781128SAlexey Budankov 		 * map->aio.data[] buffer is complete.
310ef781128SAlexey Budankov 		 *
311ef781128SAlexey Budankov 		 * perf_mmap__put() is done at record__aio_complete()
312ef781128SAlexey Budankov 		 * after started aio request completion or at record__aio_push()
313ef781128SAlexey Budankov 		 * if the request failed to start.
314ef781128SAlexey Budankov 		 */
315e75710f0SJiri Olsa 		perf_mmap__get(&map->core);
316ef781128SAlexey Budankov 	}
317ef781128SAlexey Budankov 
318ef781128SAlexey Budankov 	aio->size += size;
319ef781128SAlexey Budankov 
320ef781128SAlexey Budankov 	return size;
321ef781128SAlexey Budankov }
322ef781128SAlexey Budankov 
323a5830532SJiri Olsa static int record__aio_push(struct record *rec, struct mmap *map, off_t *off)
324ef781128SAlexey Budankov {
325ef781128SAlexey Budankov 	int ret, idx;
326ef781128SAlexey Budankov 	int trace_fd = rec->session->data->file.fd;
327ef781128SAlexey Budankov 	struct record_aio aio = { .rec = rec, .size = 0 };
328ef781128SAlexey Budankov 
329ef781128SAlexey Budankov 	/*
330ef781128SAlexey Budankov 	 * Call record__aio_sync() to wait till map->aio.data[] buffer
331ef781128SAlexey Budankov 	 * becomes available after previous aio write operation.
332ef781128SAlexey Budankov 	 */
333ef781128SAlexey Budankov 
334ef781128SAlexey Budankov 	idx = record__aio_sync(map, false);
335ef781128SAlexey Budankov 	aio.data = map->aio.data[idx];
336ef781128SAlexey Budankov 	ret = perf_mmap__push(map, &aio, record__aio_pushfn);
337ef781128SAlexey Budankov 	if (ret != 0) /* ret > 0 - no data, ret < 0 - error */
338ef781128SAlexey Budankov 		return ret;
339d3d1af6fSAlexey Budankov 
340d3d1af6fSAlexey Budankov 	rec->samples++;
341ef781128SAlexey Budankov 	ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off);
342d3d1af6fSAlexey Budankov 	if (!ret) {
343ef781128SAlexey Budankov 		*off += aio.size;
344ef781128SAlexey Budankov 		rec->bytes_written += aio.size;
345d3d1af6fSAlexey Budankov 		if (switch_output_size(rec))
346d3d1af6fSAlexey Budankov 			trigger_hit(&switch_output_trigger);
347ef781128SAlexey Budankov 	} else {
348ef781128SAlexey Budankov 		/*
349ef781128SAlexey Budankov 		 * Decrement map->refcount incremented in record__aio_pushfn()
350ef781128SAlexey Budankov 		 * back if record__aio_write() operation failed to start, otherwise
351ef781128SAlexey Budankov 		 * map->refcount is decremented in record__aio_complete() after
352ef781128SAlexey Budankov 		 * aio write operation finishes successfully.
353ef781128SAlexey Budankov 		 */
35480e53d11SJiri Olsa 		perf_mmap__put(&map->core);
355d3d1af6fSAlexey Budankov 	}
356d3d1af6fSAlexey Budankov 
357d3d1af6fSAlexey Budankov 	return ret;
358d3d1af6fSAlexey Budankov }
359d3d1af6fSAlexey Budankov 
360d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd)
361d3d1af6fSAlexey Budankov {
362d3d1af6fSAlexey Budankov 	return lseek(trace_fd, 0, SEEK_CUR);
363d3d1af6fSAlexey Budankov }
364d3d1af6fSAlexey Budankov 
365d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos)
366d3d1af6fSAlexey Budankov {
367d3d1af6fSAlexey Budankov 	lseek(trace_fd, pos, SEEK_SET);
368d3d1af6fSAlexey Budankov }
369d3d1af6fSAlexey Budankov 
370d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec)
371d3d1af6fSAlexey Budankov {
372d3d1af6fSAlexey Budankov 	int i;
37363503dbaSJiri Olsa 	struct evlist *evlist = rec->evlist;
374a5830532SJiri Olsa 	struct mmap *maps = evlist->mmap;
375d3d1af6fSAlexey Budankov 
376ef781128SAlexey Budankov 	if (!record__aio_enabled(rec))
377d3d1af6fSAlexey Budankov 		return;
378d3d1af6fSAlexey Budankov 
379c976ee11SJiri Olsa 	for (i = 0; i < evlist->core.nr_mmaps; i++) {
380a5830532SJiri Olsa 		struct mmap *map = &maps[i];
381d3d1af6fSAlexey Budankov 
382547740f7SJiri Olsa 		if (map->core.base)
38393f20c0fSAlexey Budankov 			record__aio_sync(map, true);
384d3d1af6fSAlexey Budankov 	}
385d3d1af6fSAlexey Budankov }
386d3d1af6fSAlexey Budankov 
387d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1;
38893f20c0fSAlexey Budankov static int nr_cblocks_max = 4;
389d3d1af6fSAlexey Budankov 
390d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt,
39193f20c0fSAlexey Budankov 			     const char *str,
392d3d1af6fSAlexey Budankov 			     int unset)
393d3d1af6fSAlexey Budankov {
394d3d1af6fSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
395d3d1af6fSAlexey Budankov 
39693f20c0fSAlexey Budankov 	if (unset) {
397d3d1af6fSAlexey Budankov 		opts->nr_cblocks = 0;
39893f20c0fSAlexey Budankov 	} else {
39993f20c0fSAlexey Budankov 		if (str)
40093f20c0fSAlexey Budankov 			opts->nr_cblocks = strtol(str, NULL, 0);
40193f20c0fSAlexey Budankov 		if (!opts->nr_cblocks)
402d3d1af6fSAlexey Budankov 			opts->nr_cblocks = nr_cblocks_default;
40393f20c0fSAlexey Budankov 	}
404d3d1af6fSAlexey Budankov 
405d3d1af6fSAlexey Budankov 	return 0;
406d3d1af6fSAlexey Budankov }
407d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */
40893f20c0fSAlexey Budankov static int nr_cblocks_max = 0;
40993f20c0fSAlexey Budankov 
410a5830532SJiri Olsa static int record__aio_push(struct record *rec __maybe_unused, struct mmap *map __maybe_unused,
411ef781128SAlexey Budankov 			    off_t *off __maybe_unused)
412d3d1af6fSAlexey Budankov {
413d3d1af6fSAlexey Budankov 	return -1;
414d3d1af6fSAlexey Budankov }
415d3d1af6fSAlexey Budankov 
416d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused)
417d3d1af6fSAlexey Budankov {
418d3d1af6fSAlexey Budankov 	return -1;
419d3d1af6fSAlexey Budankov }
420d3d1af6fSAlexey Budankov 
421d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused)
422d3d1af6fSAlexey Budankov {
423d3d1af6fSAlexey Budankov }
424d3d1af6fSAlexey Budankov 
425d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused)
426d3d1af6fSAlexey Budankov {
427d3d1af6fSAlexey Budankov }
428d3d1af6fSAlexey Budankov #endif
429d3d1af6fSAlexey Budankov 
430d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec)
431d3d1af6fSAlexey Budankov {
432d3d1af6fSAlexey Budankov 	return rec->opts.nr_cblocks > 0;
433d3d1af6fSAlexey Budankov }
434d3d1af6fSAlexey Budankov 
435470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1
436470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt,
437470530bbSAlexey Budankov 				    const char *str,
438470530bbSAlexey Budankov 				    int unset)
439470530bbSAlexey Budankov {
440470530bbSAlexey Budankov 	int flush_max;
441470530bbSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
442470530bbSAlexey Budankov 	static struct parse_tag tags[] = {
443470530bbSAlexey Budankov 			{ .tag  = 'B', .mult = 1       },
444470530bbSAlexey Budankov 			{ .tag  = 'K', .mult = 1 << 10 },
445470530bbSAlexey Budankov 			{ .tag  = 'M', .mult = 1 << 20 },
446470530bbSAlexey Budankov 			{ .tag  = 'G', .mult = 1 << 30 },
447470530bbSAlexey Budankov 			{ .tag  = 0 },
448470530bbSAlexey Budankov 	};
449470530bbSAlexey Budankov 
450470530bbSAlexey Budankov 	if (unset)
451470530bbSAlexey Budankov 		return 0;
452470530bbSAlexey Budankov 
453470530bbSAlexey Budankov 	if (str) {
454470530bbSAlexey Budankov 		opts->mmap_flush = parse_tag_value(str, tags);
455470530bbSAlexey Budankov 		if (opts->mmap_flush == (int)-1)
456470530bbSAlexey Budankov 			opts->mmap_flush = strtol(str, NULL, 0);
457470530bbSAlexey Budankov 	}
458470530bbSAlexey Budankov 
459470530bbSAlexey Budankov 	if (!opts->mmap_flush)
460470530bbSAlexey Budankov 		opts->mmap_flush = MMAP_FLUSH_DEFAULT;
461470530bbSAlexey Budankov 
4629521b5f2SJiri Olsa 	flush_max = evlist__mmap_size(opts->mmap_pages);
463470530bbSAlexey Budankov 	flush_max /= 4;
464470530bbSAlexey Budankov 	if (opts->mmap_flush > flush_max)
465470530bbSAlexey Budankov 		opts->mmap_flush = flush_max;
466470530bbSAlexey Budankov 
467470530bbSAlexey Budankov 	return 0;
468470530bbSAlexey Budankov }
469470530bbSAlexey Budankov 
470504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT
471504c1ad1SAlexey Budankov static unsigned int comp_level_default = 1;
472504c1ad1SAlexey Budankov 
473504c1ad1SAlexey Budankov static int record__parse_comp_level(const struct option *opt, const char *str, int unset)
474504c1ad1SAlexey Budankov {
475504c1ad1SAlexey Budankov 	struct record_opts *opts = opt->value;
476504c1ad1SAlexey Budankov 
477504c1ad1SAlexey Budankov 	if (unset) {
478504c1ad1SAlexey Budankov 		opts->comp_level = 0;
479504c1ad1SAlexey Budankov 	} else {
480504c1ad1SAlexey Budankov 		if (str)
481504c1ad1SAlexey Budankov 			opts->comp_level = strtol(str, NULL, 0);
482504c1ad1SAlexey Budankov 		if (!opts->comp_level)
483504c1ad1SAlexey Budankov 			opts->comp_level = comp_level_default;
484504c1ad1SAlexey Budankov 	}
485504c1ad1SAlexey Budankov 
486504c1ad1SAlexey Budankov 	return 0;
487504c1ad1SAlexey Budankov }
488504c1ad1SAlexey Budankov #endif
48951255a8aSAlexey Budankov static unsigned int comp_level_max = 22;
49051255a8aSAlexey Budankov 
49142e1fd80SAlexey Budankov static int record__comp_enabled(struct record *rec)
49242e1fd80SAlexey Budankov {
49342e1fd80SAlexey Budankov 	return rec->opts.comp_level > 0;
49442e1fd80SAlexey Budankov }
49542e1fd80SAlexey Budankov 
49645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
497d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
4981d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
4991d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
500234fbbf5SArnaldo Carvalho de Melo {
5018c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
502ded2b8feSJiri Olsa 	return record__write(rec, NULL, event, event->header.size);
503234fbbf5SArnaldo Carvalho de Melo }
504234fbbf5SArnaldo Carvalho de Melo 
505a5830532SJiri Olsa static int record__pushfn(struct mmap *map, void *to, void *bf, size_t size)
506d37f1586SArnaldo Carvalho de Melo {
507d37f1586SArnaldo Carvalho de Melo 	struct record *rec = to;
508d37f1586SArnaldo Carvalho de Melo 
5095d7f4116SAlexey Budankov 	if (record__comp_enabled(rec)) {
510bf59b305SJiri Olsa 		size = zstd_compress(rec->session, map->data, mmap__mmap_len(map), bf, size);
5115d7f4116SAlexey Budankov 		bf   = map->data;
5125d7f4116SAlexey Budankov 	}
5135d7f4116SAlexey Budankov 
514d37f1586SArnaldo Carvalho de Melo 	rec->samples++;
515ded2b8feSJiri Olsa 	return record__write(rec, map, bf, size);
516d37f1586SArnaldo Carvalho de Melo }
517d37f1586SArnaldo Carvalho de Melo 
5182dd6d8a1SAdrian Hunter static volatile int signr = -1;
5192dd6d8a1SAdrian Hunter static volatile int child_finished;
520c0bdc1c4SWang Nan 
5212dd6d8a1SAdrian Hunter static void sig_handler(int sig)
5222dd6d8a1SAdrian Hunter {
5232dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
5242dd6d8a1SAdrian Hunter 		child_finished = 1;
5252dd6d8a1SAdrian Hunter 	else
5262dd6d8a1SAdrian Hunter 		signr = sig;
5272dd6d8a1SAdrian Hunter 
5282dd6d8a1SAdrian Hunter 	done = 1;
5292dd6d8a1SAdrian Hunter }
5302dd6d8a1SAdrian Hunter 
531a074865eSWang Nan static void sigsegv_handler(int sig)
532a074865eSWang Nan {
533a074865eSWang Nan 	perf_hooks__recover();
534a074865eSWang Nan 	sighandler_dump_stack(sig);
535a074865eSWang Nan }
536a074865eSWang Nan 
5372dd6d8a1SAdrian Hunter static void record__sig_exit(void)
5382dd6d8a1SAdrian Hunter {
5392dd6d8a1SAdrian Hunter 	if (signr == -1)
5402dd6d8a1SAdrian Hunter 		return;
5412dd6d8a1SAdrian Hunter 
5422dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
5432dd6d8a1SAdrian Hunter 	raise(signr);
5442dd6d8a1SAdrian Hunter }
5452dd6d8a1SAdrian Hunter 
546e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
547e31f0d01SAdrian Hunter 
548ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
549a5830532SJiri Olsa 				    struct mmap *map,
550ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
551ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
552ef149c25SAdrian Hunter {
553ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
5548ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
555ef149c25SAdrian Hunter 	size_t padding;
556ef149c25SAdrian Hunter 	u8 pad[8] = {0};
557ef149c25SAdrian Hunter 
55846e201efSAdrian Hunter 	if (!perf_data__is_pipe(data) && perf_data__is_single_file(data)) {
55999fa2984SAdrian Hunter 		off_t file_offset;
5608ceb41d7SJiri Olsa 		int fd = perf_data__fd(data);
56199fa2984SAdrian Hunter 		int err;
56299fa2984SAdrian Hunter 
56399fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
56499fa2984SAdrian Hunter 		if (file_offset == -1)
56599fa2984SAdrian Hunter 			return -1;
56699fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
56799fa2984SAdrian Hunter 						     event, file_offset);
56899fa2984SAdrian Hunter 		if (err)
56999fa2984SAdrian Hunter 			return err;
57099fa2984SAdrian Hunter 	}
57199fa2984SAdrian Hunter 
572ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
573ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
574ef149c25SAdrian Hunter 	if (padding)
575ef149c25SAdrian Hunter 		padding = 8 - padding;
576ef149c25SAdrian Hunter 
577ded2b8feSJiri Olsa 	record__write(rec, map, event, event->header.size);
578ded2b8feSJiri Olsa 	record__write(rec, map, data1, len1);
579ef149c25SAdrian Hunter 	if (len2)
580ded2b8feSJiri Olsa 		record__write(rec, map, data2, len2);
581ded2b8feSJiri Olsa 	record__write(rec, map, &pad, padding);
582ef149c25SAdrian Hunter 
583ef149c25SAdrian Hunter 	return 0;
584ef149c25SAdrian Hunter }
585ef149c25SAdrian Hunter 
586ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
587a5830532SJiri Olsa 				      struct mmap *map)
588ef149c25SAdrian Hunter {
589ef149c25SAdrian Hunter 	int ret;
590ef149c25SAdrian Hunter 
591e035f4caSJiri Olsa 	ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
592ef149c25SAdrian Hunter 				  record__process_auxtrace);
593ef149c25SAdrian Hunter 	if (ret < 0)
594ef149c25SAdrian Hunter 		return ret;
595ef149c25SAdrian Hunter 
596ef149c25SAdrian Hunter 	if (ret)
597ef149c25SAdrian Hunter 		rec->samples++;
598ef149c25SAdrian Hunter 
599ef149c25SAdrian Hunter 	return 0;
600ef149c25SAdrian Hunter }
601ef149c25SAdrian Hunter 
6022dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
603a5830532SJiri Olsa 					       struct mmap *map)
6042dd6d8a1SAdrian Hunter {
6052dd6d8a1SAdrian Hunter 	int ret;
6062dd6d8a1SAdrian Hunter 
607e035f4caSJiri Olsa 	ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
6082dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
6092dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
6102dd6d8a1SAdrian Hunter 	if (ret < 0)
6112dd6d8a1SAdrian Hunter 		return ret;
6122dd6d8a1SAdrian Hunter 
6132dd6d8a1SAdrian Hunter 	if (ret)
6142dd6d8a1SAdrian Hunter 		rec->samples++;
6152dd6d8a1SAdrian Hunter 
6162dd6d8a1SAdrian Hunter 	return 0;
6172dd6d8a1SAdrian Hunter }
6182dd6d8a1SAdrian Hunter 
6192dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
6202dd6d8a1SAdrian Hunter {
6212dd6d8a1SAdrian Hunter 	int i;
6222dd6d8a1SAdrian Hunter 	int rc = 0;
6232dd6d8a1SAdrian Hunter 
624c976ee11SJiri Olsa 	for (i = 0; i < rec->evlist->core.nr_mmaps; i++) {
625a5830532SJiri Olsa 		struct mmap *map = &rec->evlist->mmap[i];
6262dd6d8a1SAdrian Hunter 
627e035f4caSJiri Olsa 		if (!map->auxtrace_mmap.base)
6282dd6d8a1SAdrian Hunter 			continue;
6292dd6d8a1SAdrian Hunter 
630e035f4caSJiri Olsa 		if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
6312dd6d8a1SAdrian Hunter 			rc = -1;
6322dd6d8a1SAdrian Hunter 			goto out;
6332dd6d8a1SAdrian Hunter 		}
6342dd6d8a1SAdrian Hunter 	}
6352dd6d8a1SAdrian Hunter out:
6362dd6d8a1SAdrian Hunter 	return rc;
6372dd6d8a1SAdrian Hunter }
6382dd6d8a1SAdrian Hunter 
639ce7b0e42SAlexander Shishkin static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit)
6402dd6d8a1SAdrian Hunter {
6412dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
6422dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
6435f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
6442dd6d8a1SAdrian Hunter 	} else {
645ce7b0e42SAlexander Shishkin 		if (auxtrace_record__snapshot_finish(rec->itr, on_exit))
6465f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
6475f9cf599SWang Nan 		else
6485f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
6492dd6d8a1SAdrian Hunter 	}
6502dd6d8a1SAdrian Hunter }
6512dd6d8a1SAdrian Hunter 
652ce7b0e42SAlexander Shishkin static int record__auxtrace_snapshot_exit(struct record *rec)
653ce7b0e42SAlexander Shishkin {
654ce7b0e42SAlexander Shishkin 	if (trigger_is_error(&auxtrace_snapshot_trigger))
655ce7b0e42SAlexander Shishkin 		return 0;
656ce7b0e42SAlexander Shishkin 
657ce7b0e42SAlexander Shishkin 	if (!auxtrace_record__snapshot_started &&
658ce7b0e42SAlexander Shishkin 	    auxtrace_record__snapshot_start(rec->itr))
659ce7b0e42SAlexander Shishkin 		return -1;
660ce7b0e42SAlexander Shishkin 
661ce7b0e42SAlexander Shishkin 	record__read_auxtrace_snapshot(rec, true);
662ce7b0e42SAlexander Shishkin 	if (trigger_is_error(&auxtrace_snapshot_trigger))
663ce7b0e42SAlexander Shishkin 		return -1;
664ce7b0e42SAlexander Shishkin 
665ce7b0e42SAlexander Shishkin 	return 0;
666ce7b0e42SAlexander Shishkin }
667ce7b0e42SAlexander Shishkin 
6684b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec)
6694b5ea3bdSAdrian Hunter {
6704b5ea3bdSAdrian Hunter 	int err;
6714b5ea3bdSAdrian Hunter 
6724b5ea3bdSAdrian Hunter 	if (!rec->itr) {
6734b5ea3bdSAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
6744b5ea3bdSAdrian Hunter 		if (err)
6754b5ea3bdSAdrian Hunter 			return err;
6764b5ea3bdSAdrian Hunter 	}
6774b5ea3bdSAdrian Hunter 
6784b5ea3bdSAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
6794b5ea3bdSAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
6804b5ea3bdSAdrian Hunter 	if (err)
6814b5ea3bdSAdrian Hunter 		return err;
6824b5ea3bdSAdrian Hunter 
683c0a6de06SAdrian Hunter 	err = auxtrace_parse_sample_options(rec->itr, rec->evlist, &rec->opts,
684c0a6de06SAdrian Hunter 					    rec->opts.auxtrace_sample_opts);
685c0a6de06SAdrian Hunter 	if (err)
686c0a6de06SAdrian Hunter 		return err;
687c0a6de06SAdrian Hunter 
6884b5ea3bdSAdrian Hunter 	return auxtrace_parse_filters(rec->evlist);
6894b5ea3bdSAdrian Hunter }
6904b5ea3bdSAdrian Hunter 
691e31f0d01SAdrian Hunter #else
692e31f0d01SAdrian Hunter 
693e31f0d01SAdrian Hunter static inline
694e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
695a5830532SJiri Olsa 			       struct mmap *map __maybe_unused)
696e31f0d01SAdrian Hunter {
697e31f0d01SAdrian Hunter 	return 0;
698e31f0d01SAdrian Hunter }
699e31f0d01SAdrian Hunter 
7002dd6d8a1SAdrian Hunter static inline
701ce7b0e42SAlexander Shishkin void record__read_auxtrace_snapshot(struct record *rec __maybe_unused,
702ce7b0e42SAlexander Shishkin 				    bool on_exit __maybe_unused)
7032dd6d8a1SAdrian Hunter {
7042dd6d8a1SAdrian Hunter }
7052dd6d8a1SAdrian Hunter 
7062dd6d8a1SAdrian Hunter static inline
7072dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
7082dd6d8a1SAdrian Hunter {
7092dd6d8a1SAdrian Hunter 	return 0;
7102dd6d8a1SAdrian Hunter }
7112dd6d8a1SAdrian Hunter 
712ce7b0e42SAlexander Shishkin static inline
713ce7b0e42SAlexander Shishkin int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused)
714ce7b0e42SAlexander Shishkin {
715ce7b0e42SAlexander Shishkin 	return 0;
716ce7b0e42SAlexander Shishkin }
717ce7b0e42SAlexander Shishkin 
7184b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused)
7194b5ea3bdSAdrian Hunter {
7204b5ea3bdSAdrian Hunter 	return 0;
7214b5ea3bdSAdrian Hunter }
7224b5ea3bdSAdrian Hunter 
723e31f0d01SAdrian Hunter #endif
724e31f0d01SAdrian Hunter 
725eeb399b5SAdrian Hunter static bool record__kcore_readable(struct machine *machine)
726eeb399b5SAdrian Hunter {
727eeb399b5SAdrian Hunter 	char kcore[PATH_MAX];
728eeb399b5SAdrian Hunter 	int fd;
729eeb399b5SAdrian Hunter 
730eeb399b5SAdrian Hunter 	scnprintf(kcore, sizeof(kcore), "%s/proc/kcore", machine->root_dir);
731eeb399b5SAdrian Hunter 
732eeb399b5SAdrian Hunter 	fd = open(kcore, O_RDONLY);
733eeb399b5SAdrian Hunter 	if (fd < 0)
734eeb399b5SAdrian Hunter 		return false;
735eeb399b5SAdrian Hunter 
736eeb399b5SAdrian Hunter 	close(fd);
737eeb399b5SAdrian Hunter 
738eeb399b5SAdrian Hunter 	return true;
739eeb399b5SAdrian Hunter }
740eeb399b5SAdrian Hunter 
741eeb399b5SAdrian Hunter static int record__kcore_copy(struct machine *machine, struct perf_data *data)
742eeb399b5SAdrian Hunter {
743eeb399b5SAdrian Hunter 	char from_dir[PATH_MAX];
744eeb399b5SAdrian Hunter 	char kcore_dir[PATH_MAX];
745eeb399b5SAdrian Hunter 	int ret;
746eeb399b5SAdrian Hunter 
747eeb399b5SAdrian Hunter 	snprintf(from_dir, sizeof(from_dir), "%s/proc", machine->root_dir);
748eeb399b5SAdrian Hunter 
749eeb399b5SAdrian Hunter 	ret = perf_data__make_kcore_dir(data, kcore_dir, sizeof(kcore_dir));
750eeb399b5SAdrian Hunter 	if (ret)
751eeb399b5SAdrian Hunter 		return ret;
752eeb399b5SAdrian Hunter 
753eeb399b5SAdrian Hunter 	return kcore_copy(from_dir, kcore_dir);
754eeb399b5SAdrian Hunter }
755eeb399b5SAdrian Hunter 
756cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
75763503dbaSJiri Olsa 			       struct evlist *evlist)
758cda57a8cSWang Nan {
759cda57a8cSWang Nan 	struct record_opts *opts = &rec->opts;
760c0a6de06SAdrian Hunter 	bool auxtrace_overwrite = opts->auxtrace_snapshot_mode ||
761c0a6de06SAdrian Hunter 				  opts->auxtrace_sample_mode;
762cda57a8cSWang Nan 	char msg[512];
763cda57a8cSWang Nan 
764f13de660SAlexey Budankov 	if (opts->affinity != PERF_AFFINITY_SYS)
765f13de660SAlexey Budankov 		cpu__setup_cpunode_map();
766f13de660SAlexey Budankov 
7679521b5f2SJiri Olsa 	if (evlist__mmap_ex(evlist, opts->mmap_pages,
768cda57a8cSWang Nan 				 opts->auxtrace_mmap_pages,
769c0a6de06SAdrian Hunter 				 auxtrace_overwrite,
770470530bbSAlexey Budankov 				 opts->nr_cblocks, opts->affinity,
77151255a8aSAlexey Budankov 				 opts->mmap_flush, opts->comp_level) < 0) {
772cda57a8cSWang Nan 		if (errno == EPERM) {
773cda57a8cSWang Nan 			pr_err("Permission error mapping pages.\n"
774cda57a8cSWang Nan 			       "Consider increasing "
775cda57a8cSWang Nan 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
776cda57a8cSWang Nan 			       "or try again with a smaller value of -m/--mmap_pages.\n"
777cda57a8cSWang Nan 			       "(current value: %u,%u)\n",
778cda57a8cSWang Nan 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
779cda57a8cSWang Nan 			return -errno;
780cda57a8cSWang Nan 		} else {
781cda57a8cSWang Nan 			pr_err("failed to mmap with %d (%s)\n", errno,
782c8b5f2c9SArnaldo Carvalho de Melo 				str_error_r(errno, msg, sizeof(msg)));
783cda57a8cSWang Nan 			if (errno)
784cda57a8cSWang Nan 				return -errno;
785cda57a8cSWang Nan 			else
786cda57a8cSWang Nan 				return -EINVAL;
787cda57a8cSWang Nan 		}
788cda57a8cSWang Nan 	}
789cda57a8cSWang Nan 	return 0;
790cda57a8cSWang Nan }
791cda57a8cSWang Nan 
792cda57a8cSWang Nan static int record__mmap(struct record *rec)
793cda57a8cSWang Nan {
794cda57a8cSWang Nan 	return record__mmap_evlist(rec, rec->evlist);
795cda57a8cSWang Nan }
796cda57a8cSWang Nan 
7978c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
798dd7927f4SArnaldo Carvalho de Melo {
799d6195a6aSArnaldo Carvalho de Melo 	char msg[BUFSIZ];
80032dcd021SJiri Olsa 	struct evsel *pos;
80163503dbaSJiri Olsa 	struct evlist *evlist = rec->evlist;
802d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
803b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
8048d3eca20SDavid Ahern 	int rc = 0;
805dd7927f4SArnaldo Carvalho de Melo 
806d3dbf43cSArnaldo Carvalho de Melo 	/*
807d3dbf43cSArnaldo Carvalho de Melo 	 * For initial_delay we need to add a dummy event so that we can track
808d3dbf43cSArnaldo Carvalho de Melo 	 * PERF_RECORD_MMAP while we wait for the initial delay to enable the
809d3dbf43cSArnaldo Carvalho de Melo 	 * real events, the ones asked by the user.
810d3dbf43cSArnaldo Carvalho de Melo 	 */
811d3dbf43cSArnaldo Carvalho de Melo 	if (opts->initial_delay) {
812d3dbf43cSArnaldo Carvalho de Melo 		if (perf_evlist__add_dummy(evlist))
813d3dbf43cSArnaldo Carvalho de Melo 			return -ENOMEM;
814d3dbf43cSArnaldo Carvalho de Melo 
815515dbe48SJiri Olsa 		pos = evlist__first(evlist);
816d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 0;
817515dbe48SJiri Olsa 		pos = evlist__last(evlist);
818d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 1;
8191fc632ceSJiri Olsa 		pos->core.attr.enable_on_exec = 1;
820d3dbf43cSArnaldo Carvalho de Melo 	}
821d3dbf43cSArnaldo Carvalho de Melo 
822e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
823cac21425SJiri Olsa 
824e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
8253da297a6SIngo Molnar try_again:
826af663bd0SJiri Olsa 		if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) {
82756e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
828bb963e16SNamhyung Kim 				if (verbose > 0)
829c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
8303da297a6SIngo Molnar 				goto try_again;
8313da297a6SIngo Molnar 			}
832cf99ad14SAndi Kleen 			if ((errno == EINVAL || errno == EBADF) &&
833cf99ad14SAndi Kleen 			    pos->leader != pos &&
834cf99ad14SAndi Kleen 			    pos->weak_group) {
835*4804e011SAndi Kleen 			        pos = perf_evlist__reset_weak_group(evlist, pos, true);
836cf99ad14SAndi Kleen 				goto try_again;
837cf99ad14SAndi Kleen 			}
83856e52e85SArnaldo Carvalho de Melo 			rc = -errno;
83956e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
84056e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
84156e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
8428d3eca20SDavid Ahern 			goto out;
8437c6a1c65SPeter Zijlstra 		}
844bfd8f72cSAndi Kleen 
845bfd8f72cSAndi Kleen 		pos->supported = true;
8467c6a1c65SPeter Zijlstra 	}
8477c6a1c65SPeter Zijlstra 
848c8b567c8SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(evlist)) {
849c8b567c8SArnaldo Carvalho de Melo 		pr_warning(
850c8b567c8SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
851c8b567c8SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
852c8b567c8SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
853c8b567c8SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
854c8b567c8SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
855c8b567c8SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
856c8b567c8SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
857c8b567c8SArnaldo Carvalho de Melo 	}
858c8b567c8SArnaldo Carvalho de Melo 
85923d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
86062d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
86123d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
862c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, msg, sizeof(msg)));
8638d3eca20SDavid Ahern 		rc = -1;
8648d3eca20SDavid Ahern 		goto out;
8650a102479SFrederic Weisbecker 	}
8660a102479SFrederic Weisbecker 
867cda57a8cSWang Nan 	rc = record__mmap(rec);
868cda57a8cSWang Nan 	if (rc)
8698d3eca20SDavid Ahern 		goto out;
8700a27d7f9SArnaldo Carvalho de Melo 
871a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
8727b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
8738d3eca20SDavid Ahern out:
8748d3eca20SDavid Ahern 	return rc;
875a91e5431SArnaldo Carvalho de Melo }
876a91e5431SArnaldo Carvalho de Melo 
877e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
878e3d59112SNamhyung Kim 				union perf_event *event,
879e3d59112SNamhyung Kim 				struct perf_sample *sample,
88032dcd021SJiri Olsa 				struct evsel *evsel,
881e3d59112SNamhyung Kim 				struct machine *machine)
882e3d59112SNamhyung Kim {
883e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
884e3d59112SNamhyung Kim 
88568588bafSJin Yao 	if (rec->evlist->first_sample_time == 0)
88668588bafSJin Yao 		rec->evlist->first_sample_time = sample->time;
887e3d59112SNamhyung Kim 
88868588bafSJin Yao 	rec->evlist->last_sample_time = sample->time;
88968588bafSJin Yao 
89068588bafSJin Yao 	if (rec->buildid_all)
89168588bafSJin Yao 		return 0;
89268588bafSJin Yao 
89368588bafSJin Yao 	rec->samples++;
894e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
895e3d59112SNamhyung Kim }
896e3d59112SNamhyung Kim 
8978c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
8986122e4e4SArnaldo Carvalho de Melo {
899f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
9006122e4e4SArnaldo Carvalho de Melo 
90145112e89SJiri Olsa 	if (perf_data__size(&rec->data) == 0)
9029f591fd7SArnaldo Carvalho de Melo 		return 0;
9039f591fd7SArnaldo Carvalho de Melo 
90400dc8657SNamhyung Kim 	/*
90500dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
90600dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
90700dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
90800dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
90900dc8657SNamhyung Kim 	 *
91000dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
91100dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
91200dc8657SNamhyung Kim 	 */
91300dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
91400dc8657SNamhyung Kim 
9156156681bSNamhyung Kim 	/*
9166156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
91768588bafSJin Yao 	 * so no need to process samples. But if timestamp_boundary is enabled,
91868588bafSJin Yao 	 * it still needs to walk on all samples to get the timestamps of
91968588bafSJin Yao 	 * first/last samples.
9206156681bSNamhyung Kim 	 */
92168588bafSJin Yao 	if (rec->buildid_all && !rec->timestamp_boundary)
9226156681bSNamhyung Kim 		rec->tool.sample = NULL;
9236156681bSNamhyung Kim 
924b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
9256122e4e4SArnaldo Carvalho de Melo }
9266122e4e4SArnaldo Carvalho de Melo 
9278115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
928a1645ce1SZhang, Yanmin {
929a1645ce1SZhang, Yanmin 	int err;
93045694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
931a1645ce1SZhang, Yanmin 	/*
932a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
933a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
934a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
935a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
936a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
937a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
938a1645ce1SZhang, Yanmin 	 */
93945694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
940743eb868SArnaldo Carvalho de Melo 					     machine);
941a1645ce1SZhang, Yanmin 	if (err < 0)
942a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
94323346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
944a1645ce1SZhang, Yanmin 
945a1645ce1SZhang, Yanmin 	/*
946a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
947a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
948a1645ce1SZhang, Yanmin 	 */
94945694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
9500ae617beSAdrian Hunter 						 machine);
951a1645ce1SZhang, Yanmin 	if (err < 0)
952a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
95323346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
954a1645ce1SZhang, Yanmin }
955a1645ce1SZhang, Yanmin 
95698402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
95798402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
95898402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
95998402807SFrederic Weisbecker };
96098402807SFrederic Weisbecker 
961a5830532SJiri Olsa static void record__adjust_affinity(struct record *rec, struct mmap *map)
962f13de660SAlexey Budankov {
963f13de660SAlexey Budankov 	if (rec->opts.affinity != PERF_AFFINITY_SYS &&
964f13de660SAlexey Budankov 	    !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) {
965f13de660SAlexey Budankov 		CPU_ZERO(&rec->affinity_mask);
966f13de660SAlexey Budankov 		CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask);
967f13de660SAlexey Budankov 		sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask);
968f13de660SAlexey Budankov 	}
969f13de660SAlexey Budankov }
970f13de660SAlexey Budankov 
9715d7f4116SAlexey Budankov static size_t process_comp_header(void *record, size_t increment)
9725d7f4116SAlexey Budankov {
97372932371SJiri Olsa 	struct perf_record_compressed *event = record;
9745d7f4116SAlexey Budankov 	size_t size = sizeof(*event);
9755d7f4116SAlexey Budankov 
9765d7f4116SAlexey Budankov 	if (increment) {
9775d7f4116SAlexey Budankov 		event->header.size += increment;
9785d7f4116SAlexey Budankov 		return increment;
9795d7f4116SAlexey Budankov 	}
9805d7f4116SAlexey Budankov 
9815d7f4116SAlexey Budankov 	event->header.type = PERF_RECORD_COMPRESSED;
9825d7f4116SAlexey Budankov 	event->header.size = size;
9835d7f4116SAlexey Budankov 
9845d7f4116SAlexey Budankov 	return size;
9855d7f4116SAlexey Budankov }
9865d7f4116SAlexey Budankov 
9875d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size,
9885d7f4116SAlexey Budankov 			    void *src, size_t src_size)
9895d7f4116SAlexey Budankov {
9905d7f4116SAlexey Budankov 	size_t compressed;
99172932371SJiri Olsa 	size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1;
9925d7f4116SAlexey Budankov 
9935d7f4116SAlexey Budankov 	compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size,
9945d7f4116SAlexey Budankov 						     max_record_size, process_comp_header);
9955d7f4116SAlexey Budankov 
9965d7f4116SAlexey Budankov 	session->bytes_transferred += src_size;
9975d7f4116SAlexey Budankov 	session->bytes_compressed  += compressed;
9985d7f4116SAlexey Budankov 
9995d7f4116SAlexey Budankov 	return compressed;
10005d7f4116SAlexey Budankov }
10015d7f4116SAlexey Budankov 
100263503dbaSJiri Olsa static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
1003470530bbSAlexey Budankov 				    bool overwrite, bool synch)
100498402807SFrederic Weisbecker {
1005dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
10060e2e63ddSPeter Zijlstra 	int i;
10078d3eca20SDavid Ahern 	int rc = 0;
1008a5830532SJiri Olsa 	struct mmap *maps;
1009d3d1af6fSAlexey Budankov 	int trace_fd = rec->data.file.fd;
1010ef781128SAlexey Budankov 	off_t off = 0;
101198402807SFrederic Weisbecker 
1012cb21686bSWang Nan 	if (!evlist)
1013cb21686bSWang Nan 		return 0;
1014ef149c25SAdrian Hunter 
10150b72d69aSWang Nan 	maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
1016a4ea0ec4SWang Nan 	if (!maps)
1017a4ea0ec4SWang Nan 		return 0;
1018cb21686bSWang Nan 
10190b72d69aSWang Nan 	if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
102054cc54deSWang Nan 		return 0;
102154cc54deSWang Nan 
1022d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
1023d3d1af6fSAlexey Budankov 		off = record__aio_get_pos(trace_fd);
1024d3d1af6fSAlexey Budankov 
1025c976ee11SJiri Olsa 	for (i = 0; i < evlist->core.nr_mmaps; i++) {
1026470530bbSAlexey Budankov 		u64 flush = 0;
1027a5830532SJiri Olsa 		struct mmap *map = &maps[i];
1028a4ea0ec4SWang Nan 
1029547740f7SJiri Olsa 		if (map->core.base) {
1030f13de660SAlexey Budankov 			record__adjust_affinity(rec, map);
1031470530bbSAlexey Budankov 			if (synch) {
103265aa2e6bSJiri Olsa 				flush = map->core.flush;
103365aa2e6bSJiri Olsa 				map->core.flush = 1;
1034470530bbSAlexey Budankov 			}
1035d3d1af6fSAlexey Budankov 			if (!record__aio_enabled(rec)) {
1036ef781128SAlexey Budankov 				if (perf_mmap__push(map, rec, record__pushfn) < 0) {
1037470530bbSAlexey Budankov 					if (synch)
103865aa2e6bSJiri Olsa 						map->core.flush = flush;
10398d3eca20SDavid Ahern 					rc = -1;
10408d3eca20SDavid Ahern 					goto out;
10418d3eca20SDavid Ahern 				}
1042d3d1af6fSAlexey Budankov 			} else {
1043ef781128SAlexey Budankov 				if (record__aio_push(rec, map, &off) < 0) {
1044d3d1af6fSAlexey Budankov 					record__aio_set_pos(trace_fd, off);
1045470530bbSAlexey Budankov 					if (synch)
104665aa2e6bSJiri Olsa 						map->core.flush = flush;
1047d3d1af6fSAlexey Budankov 					rc = -1;
1048d3d1af6fSAlexey Budankov 					goto out;
1049d3d1af6fSAlexey Budankov 				}
1050d3d1af6fSAlexey Budankov 			}
1051470530bbSAlexey Budankov 			if (synch)
105265aa2e6bSJiri Olsa 				map->core.flush = flush;
10538d3eca20SDavid Ahern 		}
1054ef149c25SAdrian Hunter 
1055e035f4caSJiri Olsa 		if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
1056c0a6de06SAdrian Hunter 		    !rec->opts.auxtrace_sample_mode &&
1057e035f4caSJiri Olsa 		    record__auxtrace_mmap_read(rec, map) != 0) {
1058ef149c25SAdrian Hunter 			rc = -1;
1059ef149c25SAdrian Hunter 			goto out;
1060ef149c25SAdrian Hunter 		}
106198402807SFrederic Weisbecker 	}
106298402807SFrederic Weisbecker 
1063d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
1064d3d1af6fSAlexey Budankov 		record__aio_set_pos(trace_fd, off);
1065d3d1af6fSAlexey Budankov 
1066dcabb507SJiri Olsa 	/*
1067dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
1068dcabb507SJiri Olsa 	 * at least one event.
1069dcabb507SJiri Olsa 	 */
1070dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
1071ded2b8feSJiri Olsa 		rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
10728d3eca20SDavid Ahern 
10730b72d69aSWang Nan 	if (overwrite)
107454cc54deSWang Nan 		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
10758d3eca20SDavid Ahern out:
10768d3eca20SDavid Ahern 	return rc;
107798402807SFrederic Weisbecker }
107898402807SFrederic Weisbecker 
1079470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch)
1080cb21686bSWang Nan {
1081cb21686bSWang Nan 	int err;
1082cb21686bSWang Nan 
1083470530bbSAlexey Budankov 	err = record__mmap_read_evlist(rec, rec->evlist, false, synch);
1084cb21686bSWang Nan 	if (err)
1085cb21686bSWang Nan 		return err;
1086cb21686bSWang Nan 
1087470530bbSAlexey Budankov 	return record__mmap_read_evlist(rec, rec->evlist, true, synch);
1088cb21686bSWang Nan }
1089cb21686bSWang Nan 
10908c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
109157706abcSDavid Ahern {
109257706abcSDavid Ahern 	struct perf_session *session = rec->session;
109357706abcSDavid Ahern 	int feat;
109457706abcSDavid Ahern 
109557706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
109657706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
109757706abcSDavid Ahern 
109857706abcSDavid Ahern 	if (rec->no_buildid)
109957706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
110057706abcSDavid Ahern 
1101ce9036a6SJiri Olsa 	if (!have_tracepoints(&rec->evlist->core.entries))
110257706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
110357706abcSDavid Ahern 
110457706abcSDavid Ahern 	if (!rec->opts.branch_stack)
110557706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
1106ef149c25SAdrian Hunter 
1107ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
1108ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
1109ffa517adSJiri Olsa 
1110cf790516SAlexey Budankov 	if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
1111cf790516SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_CLOCKID);
1112cf790516SAlexey Budankov 
1113258031c0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
111442e1fd80SAlexey Budankov 	if (!record__comp_enabled(rec))
111542e1fd80SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_COMPRESSED);
1116258031c0SJiri Olsa 
1117ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
111857706abcSDavid Ahern }
111957706abcSDavid Ahern 
1120e1ab48baSWang Nan static void
1121e1ab48baSWang Nan record__finish_output(struct record *rec)
1122e1ab48baSWang Nan {
11238ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
11248ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
1125e1ab48baSWang Nan 
11268ceb41d7SJiri Olsa 	if (data->is_pipe)
1127e1ab48baSWang Nan 		return;
1128e1ab48baSWang Nan 
1129e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
113045112e89SJiri Olsa 	data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
1131e1ab48baSWang Nan 
1132e1ab48baSWang Nan 	if (!rec->no_buildid) {
1133e1ab48baSWang Nan 		process_buildids(rec);
1134e1ab48baSWang Nan 
1135e1ab48baSWang Nan 		if (rec->buildid_all)
1136e1ab48baSWang Nan 			dsos__hit_all(rec->session);
1137e1ab48baSWang Nan 	}
1138e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
1139e1ab48baSWang Nan 
1140e1ab48baSWang Nan 	return;
1141e1ab48baSWang Nan }
1142e1ab48baSWang Nan 
11434ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
1144be7b0c9eSWang Nan {
11459d6aae72SArnaldo Carvalho de Melo 	int err;
11469749b90eSJiri Olsa 	struct perf_thread_map *thread_map;
1147be7b0c9eSWang Nan 
11484ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
11494ea648aeSWang Nan 		return 0;
11504ea648aeSWang Nan 
11519d6aae72SArnaldo Carvalho de Melo 	thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
11529d6aae72SArnaldo Carvalho de Melo 	if (thread_map == NULL)
11539d6aae72SArnaldo Carvalho de Melo 		return -1;
11549d6aae72SArnaldo Carvalho de Melo 
11559d6aae72SArnaldo Carvalho de Melo 	err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
1156be7b0c9eSWang Nan 						 process_synthesized_event,
1157be7b0c9eSWang Nan 						 &rec->session->machines.host,
11583fcb10e4SMark Drayton 						 rec->opts.sample_address);
11597836e52eSJiri Olsa 	perf_thread_map__put(thread_map);
11609d6aae72SArnaldo Carvalho de Melo 	return err;
1161be7b0c9eSWang Nan }
1162be7b0c9eSWang Nan 
11634ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
11643c1cb7e3SWang Nan 
1165ecfd7a9cSWang Nan static int
1166ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
1167ecfd7a9cSWang Nan {
11688ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1169ecfd7a9cSWang Nan 	int fd, err;
117003724b2eSAndi Kleen 	char *new_filename;
1171ecfd7a9cSWang Nan 
1172ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
1173ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
1174ecfd7a9cSWang Nan 
1175d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
1176d3d1af6fSAlexey Budankov 
11774ea648aeSWang Nan 	record__synthesize(rec, true);
11784ea648aeSWang Nan 	if (target__none(&rec->opts.target))
11794ea648aeSWang Nan 		record__synthesize_workload(rec, true);
11804ea648aeSWang Nan 
1181ecfd7a9cSWang Nan 	rec->samples = 0;
1182ecfd7a9cSWang Nan 	record__finish_output(rec);
1183ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
1184ecfd7a9cSWang Nan 	if (err) {
1185ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
1186ecfd7a9cSWang Nan 		return -EINVAL;
1187ecfd7a9cSWang Nan 	}
1188ecfd7a9cSWang Nan 
11898ceb41d7SJiri Olsa 	fd = perf_data__switch(data, timestamp,
1190ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
119103724b2eSAndi Kleen 				    at_exit, &new_filename);
1192ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
1193ecfd7a9cSWang Nan 		rec->bytes_written = 0;
1194ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
1195ecfd7a9cSWang Nan 	}
1196ecfd7a9cSWang Nan 
1197ecfd7a9cSWang Nan 	if (!quiet)
1198ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
11992d4f2799SJiri Olsa 			data->path, timestamp);
12003c1cb7e3SWang Nan 
120103724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
120203724b2eSAndi Kleen 		int n = rec->switch_output.cur_file + 1;
120303724b2eSAndi Kleen 
120403724b2eSAndi Kleen 		if (n >= rec->switch_output.num_files)
120503724b2eSAndi Kleen 			n = 0;
120603724b2eSAndi Kleen 		rec->switch_output.cur_file = n;
120703724b2eSAndi Kleen 		if (rec->switch_output.filenames[n]) {
120803724b2eSAndi Kleen 			remove(rec->switch_output.filenames[n]);
1209d8f9da24SArnaldo Carvalho de Melo 			zfree(&rec->switch_output.filenames[n]);
121003724b2eSAndi Kleen 		}
121103724b2eSAndi Kleen 		rec->switch_output.filenames[n] = new_filename;
121203724b2eSAndi Kleen 	} else {
121303724b2eSAndi Kleen 		free(new_filename);
121403724b2eSAndi Kleen 	}
121503724b2eSAndi Kleen 
12163c1cb7e3SWang Nan 	/* Output tracking events */
1217be7b0c9eSWang Nan 	if (!at_exit) {
12184ea648aeSWang Nan 		record__synthesize(rec, false);
12193c1cb7e3SWang Nan 
1220be7b0c9eSWang Nan 		/*
1221be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
1222be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
1223be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
1224be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
1225be7b0c9eSWang Nan 		 * contain map and comm information.
1226be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
1227be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
1228be7b0c9eSWang Nan 		 */
1229be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
12304ea648aeSWang Nan 			record__synthesize_workload(rec, false);
1231be7b0c9eSWang Nan 	}
1232ecfd7a9cSWang Nan 	return fd;
1233ecfd7a9cSWang Nan }
1234ecfd7a9cSWang Nan 
1235f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
1236f33cbe72SArnaldo Carvalho de Melo 
1237f33cbe72SArnaldo Carvalho de Melo /*
1238f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
1239f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
1240f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
1241f33cbe72SArnaldo Carvalho de Melo  */
124245604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
124345604710SNamhyung Kim 					siginfo_t *info,
1244f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
1245f33cbe72SArnaldo Carvalho de Melo {
1246f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
1247f33cbe72SArnaldo Carvalho de Melo 	done = 1;
1248f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
1249f33cbe72SArnaldo Carvalho de Melo }
1250f33cbe72SArnaldo Carvalho de Melo 
12512dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
1252bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
12532dd6d8a1SAdrian Hunter 
1254ee667f94SWang Nan static const struct perf_event_mmap_page *
125563503dbaSJiri Olsa perf_evlist__pick_pc(struct evlist *evlist)
1256ee667f94SWang Nan {
1257b2cb615dSWang Nan 	if (evlist) {
1258547740f7SJiri Olsa 		if (evlist->mmap && evlist->mmap[0].core.base)
1259547740f7SJiri Olsa 			return evlist->mmap[0].core.base;
1260547740f7SJiri Olsa 		if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].core.base)
1261547740f7SJiri Olsa 			return evlist->overwrite_mmap[0].core.base;
1262b2cb615dSWang Nan 	}
1263ee667f94SWang Nan 	return NULL;
1264ee667f94SWang Nan }
1265ee667f94SWang Nan 
1266c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
1267c45628b0SWang Nan {
1268ee667f94SWang Nan 	const struct perf_event_mmap_page *pc;
1269ee667f94SWang Nan 
1270ee667f94SWang Nan 	pc = perf_evlist__pick_pc(rec->evlist);
1271ee667f94SWang Nan 	if (pc)
1272ee667f94SWang Nan 		return pc;
1273c45628b0SWang Nan 	return NULL;
1274c45628b0SWang Nan }
1275c45628b0SWang Nan 
12764ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
1277c45c86ebSWang Nan {
1278c45c86ebSWang Nan 	struct perf_session *session = rec->session;
1279c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
12808ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1281c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
1282c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
12838ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
1284c45c86ebSWang Nan 	int err = 0;
1285c45c86ebSWang Nan 
12864ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
12874ea648aeSWang Nan 		return 0;
12884ea648aeSWang Nan 
12898ceb41d7SJiri Olsa 	if (data->is_pipe) {
1290a2015516SJiri Olsa 		/*
1291a2015516SJiri Olsa 		 * We need to synthesize events first, because some
1292a2015516SJiri Olsa 		 * features works on top of them (on report side).
1293a2015516SJiri Olsa 		 */
1294318ec184SJiri Olsa 		err = perf_event__synthesize_attrs(tool, rec->evlist,
1295c45c86ebSWang Nan 						   process_synthesized_event);
1296c45c86ebSWang Nan 		if (err < 0) {
1297c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
1298c45c86ebSWang Nan 			goto out;
1299c45c86ebSWang Nan 		}
1300c45c86ebSWang Nan 
1301a2015516SJiri Olsa 		err = perf_event__synthesize_features(tool, session, rec->evlist,
1302a2015516SJiri Olsa 						      process_synthesized_event);
1303a2015516SJiri Olsa 		if (err < 0) {
1304a2015516SJiri Olsa 			pr_err("Couldn't synthesize features.\n");
1305a2015516SJiri Olsa 			return err;
1306a2015516SJiri Olsa 		}
1307a2015516SJiri Olsa 
1308ce9036a6SJiri Olsa 		if (have_tracepoints(&rec->evlist->core.entries)) {
1309c45c86ebSWang Nan 			/*
1310c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
1311c45c86ebSWang Nan 			 * there were no tracepoints so its not really
1312c45c86ebSWang Nan 			 * an error, just that we don't need to
1313c45c86ebSWang Nan 			 * synthesize anything.  We really have to
1314c45c86ebSWang Nan 			 * return this more properly and also
1315c45c86ebSWang Nan 			 * propagate errors that now are calling die()
1316c45c86ebSWang Nan 			 */
1317c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
1318c45c86ebSWang Nan 								  process_synthesized_event);
1319c45c86ebSWang Nan 			if (err <= 0) {
1320c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
1321c45c86ebSWang Nan 				goto out;
1322c45c86ebSWang Nan 			}
1323c45c86ebSWang Nan 			rec->bytes_written += err;
1324c45c86ebSWang Nan 		}
1325c45c86ebSWang Nan 	}
1326c45c86ebSWang Nan 
1327c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
132846bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
132946bc29b9SAdrian Hunter 	if (err)
133046bc29b9SAdrian Hunter 		goto out;
133146bc29b9SAdrian Hunter 
1332c0a6de06SAdrian Hunter 	/* Synthesize id_index before auxtrace_info */
1333c0a6de06SAdrian Hunter 	if (rec->opts.auxtrace_sample_mode) {
1334c0a6de06SAdrian Hunter 		err = perf_event__synthesize_id_index(tool,
1335c0a6de06SAdrian Hunter 						      process_synthesized_event,
1336c0a6de06SAdrian Hunter 						      session->evlist, machine);
1337c0a6de06SAdrian Hunter 		if (err)
1338c0a6de06SAdrian Hunter 			goto out;
1339c0a6de06SAdrian Hunter 	}
1340c0a6de06SAdrian Hunter 
1341c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
1342c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
1343c45c86ebSWang Nan 					session, process_synthesized_event);
1344c45c86ebSWang Nan 		if (err)
1345c45c86ebSWang Nan 			goto out;
1346c45c86ebSWang Nan 	}
1347c45c86ebSWang Nan 
13486c443954SArnaldo Carvalho de Melo 	if (!perf_evlist__exclude_kernel(rec->evlist)) {
1349c45c86ebSWang Nan 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
1350c45c86ebSWang Nan 							 machine);
1351c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
1352c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1353c45c86ebSWang Nan 				   "Check /proc/kallsyms permission or run as root.\n");
1354c45c86ebSWang Nan 
1355c45c86ebSWang Nan 		err = perf_event__synthesize_modules(tool, process_synthesized_event,
1356c45c86ebSWang Nan 						     machine);
1357c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
1358c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1359c45c86ebSWang Nan 				   "Check /proc/modules permission or run as root.\n");
13606c443954SArnaldo Carvalho de Melo 	}
1361c45c86ebSWang Nan 
1362c45c86ebSWang Nan 	if (perf_guest) {
1363c45c86ebSWang Nan 		machines__process_guests(&session->machines,
1364c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
1365c45c86ebSWang Nan 	}
1366c45c86ebSWang Nan 
1367bfd8f72cSAndi Kleen 	err = perf_event__synthesize_extra_attr(&rec->tool,
1368bfd8f72cSAndi Kleen 						rec->evlist,
1369bfd8f72cSAndi Kleen 						process_synthesized_event,
1370bfd8f72cSAndi Kleen 						data->is_pipe);
1371bfd8f72cSAndi Kleen 	if (err)
1372bfd8f72cSAndi Kleen 		goto out;
1373bfd8f72cSAndi Kleen 
137403617c22SJiri Olsa 	err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads,
1375373565d2SAndi Kleen 						 process_synthesized_event,
1376373565d2SAndi Kleen 						NULL);
1377373565d2SAndi Kleen 	if (err < 0) {
1378373565d2SAndi Kleen 		pr_err("Couldn't synthesize thread map.\n");
1379373565d2SAndi Kleen 		return err;
1380373565d2SAndi Kleen 	}
1381373565d2SAndi Kleen 
1382f72f901dSJiri Olsa 	err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus,
1383373565d2SAndi Kleen 					     process_synthesized_event, NULL);
1384373565d2SAndi Kleen 	if (err < 0) {
1385373565d2SAndi Kleen 		pr_err("Couldn't synthesize cpu map.\n");
1386373565d2SAndi Kleen 		return err;
1387373565d2SAndi Kleen 	}
1388373565d2SAndi Kleen 
1389e5416950SSong Liu 	err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
13907b612e29SSong Liu 						machine, opts);
13917b612e29SSong Liu 	if (err < 0)
13927b612e29SSong Liu 		pr_warning("Couldn't synthesize bpf events.\n");
13937b612e29SSong Liu 
139403617c22SJiri Olsa 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->core.threads,
1395c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
13963fcb10e4SMark Drayton 					    1);
1397c45c86ebSWang Nan out:
1398c45c86ebSWang Nan 	return err;
1399c45c86ebSWang Nan }
1400c45c86ebSWang Nan 
14018c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
140286470930SIngo Molnar {
140357706abcSDavid Ahern 	int err;
140445604710SNamhyung Kim 	int status = 0;
14058b412664SPeter Zijlstra 	unsigned long waking = 0;
140646be604bSZhang, Yanmin 	const bool forks = argc > 0;
140745694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
1408b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
14098ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1410d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
14116dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
141263503dbaSJiri Olsa 	struct evlist *sb_evlist = NULL;
141342aa276fSNamhyung Kim 	int fd;
1414d3c8c08eSAlexey Budankov 	float ratio = 0;
141586470930SIngo Molnar 
141645604710SNamhyung Kim 	atexit(record__sig_exit);
1417f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
1418f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
1419804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
1420a074865eSWang Nan 	signal(SIGSEGV, sigsegv_handler);
1421c0bdc1c4SWang Nan 
1422f3b3614aSHari Bathini 	if (rec->opts.record_namespaces)
1423f3b3614aSHari Bathini 		tool->namespace_events = true;
1424f3b3614aSHari Bathini 
1425dc0c6127SJiri Olsa 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
14262dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
14273c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
14285f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
1429dc0c6127SJiri Olsa 		if (rec->switch_output.enabled)
14303c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
1431c0bdc1c4SWang Nan 	} else {
14322dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
1433c0bdc1c4SWang Nan 	}
1434f5970550SPeter Zijlstra 
14358ceb41d7SJiri Olsa 	session = perf_session__new(data, false, tool);
14366ef81c55SMamatha Inamdar 	if (IS_ERR(session)) {
1437ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
14386ef81c55SMamatha Inamdar 		return PTR_ERR(session);
1439a9a70bbcSArnaldo Carvalho de Melo 	}
1440a9a70bbcSArnaldo Carvalho de Melo 
14418ceb41d7SJiri Olsa 	fd = perf_data__fd(data);
1442d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
1443d20deb64SArnaldo Carvalho de Melo 
14445d7f4116SAlexey Budankov 	if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) {
14455d7f4116SAlexey Budankov 		pr_err("Compression initialization failed.\n");
14465d7f4116SAlexey Budankov 		return -1;
14475d7f4116SAlexey Budankov 	}
14485d7f4116SAlexey Budankov 
14495d7f4116SAlexey Budankov 	session->header.env.comp_type  = PERF_COMP_ZSTD;
14505d7f4116SAlexey Budankov 	session->header.env.comp_level = rec->opts.comp_level;
14515d7f4116SAlexey Budankov 
1452eeb399b5SAdrian Hunter 	if (rec->opts.kcore &&
1453eeb399b5SAdrian Hunter 	    !record__kcore_readable(&session->machines.host)) {
1454eeb399b5SAdrian Hunter 		pr_err("ERROR: kcore is not readable.\n");
1455eeb399b5SAdrian Hunter 		return -1;
1456eeb399b5SAdrian Hunter 	}
1457eeb399b5SAdrian Hunter 
14588c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
1459330aa675SStephane Eranian 
1460cf790516SAlexey Budankov 	if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
1461cf790516SAlexey Budankov 		session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
1462cf790516SAlexey Budankov 
1463d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
14643e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
14658ceb41d7SJiri Olsa 						    argv, data->is_pipe,
1466735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
146735b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
146835b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
146945604710SNamhyung Kim 			status = err;
147035b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
1471856e9660SPeter Zijlstra 		}
1472856e9660SPeter Zijlstra 	}
1473856e9660SPeter Zijlstra 
1474ad46e48cSJiri Olsa 	/*
1475ad46e48cSJiri Olsa 	 * If we have just single event and are sending data
1476ad46e48cSJiri Olsa 	 * through pipe, we need to force the ids allocation,
1477ad46e48cSJiri Olsa 	 * because we synthesize event name through the pipe
1478ad46e48cSJiri Olsa 	 * and need the id for that.
1479ad46e48cSJiri Olsa 	 */
14806484d2f9SJiri Olsa 	if (data->is_pipe && rec->evlist->core.nr_entries == 1)
1481ad46e48cSJiri Olsa 		rec->opts.sample_id = true;
1482ad46e48cSJiri Olsa 
14838c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
14848d3eca20SDavid Ahern 		err = -1;
148545604710SNamhyung Kim 		goto out_child;
14868d3eca20SDavid Ahern 	}
1487f6fa4375SJiri Olsa 	session->header.env.comp_mmap_len = session->evlist->core.mmap_len;
148886470930SIngo Molnar 
1489eeb399b5SAdrian Hunter 	if (rec->opts.kcore) {
1490eeb399b5SAdrian Hunter 		err = record__kcore_copy(&session->machines.host, data);
1491eeb399b5SAdrian Hunter 		if (err) {
1492eeb399b5SAdrian Hunter 			pr_err("ERROR: Failed to copy kcore\n");
1493eeb399b5SAdrian Hunter 			goto out_child;
1494eeb399b5SAdrian Hunter 		}
1495eeb399b5SAdrian Hunter 	}
1496eeb399b5SAdrian Hunter 
14978690a2a7SWang Nan 	err = bpf__apply_obj_config();
14988690a2a7SWang Nan 	if (err) {
14998690a2a7SWang Nan 		char errbuf[BUFSIZ];
15008690a2a7SWang Nan 
15018690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
15028690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
15038690a2a7SWang Nan 			 errbuf);
15048690a2a7SWang Nan 		goto out_child;
15058690a2a7SWang Nan 	}
15068690a2a7SWang Nan 
1507cca8482cSAdrian Hunter 	/*
1508cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
1509cca8482cSAdrian Hunter 	 * evlist.
1510cca8482cSAdrian Hunter 	 */
1511cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
1512cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
1513cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
1514cca8482cSAdrian Hunter 	}
1515cca8482cSAdrian Hunter 
15163e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
1517a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
1518a8bb559bSNamhyung Kim 
15198ceb41d7SJiri Olsa 	if (data->is_pipe) {
152042aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
1521529870e3STom Zanussi 		if (err < 0)
152245604710SNamhyung Kim 			goto out_child;
1523563aecb2SJiri Olsa 	} else {
152442aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
1525d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
152645604710SNamhyung Kim 			goto out_child;
1527d5eed904SArnaldo Carvalho de Melo 	}
15287c6a1c65SPeter Zijlstra 
1529d3665498SDavid Ahern 	if (!rec->no_buildid
1530e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
1531d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
1532e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
15338d3eca20SDavid Ahern 		err = -1;
153445604710SNamhyung Kim 		goto out_child;
1535e20960c0SRobert Richter 	}
1536e20960c0SRobert Richter 
1537d56354dcSSong Liu 	if (!opts->no_bpf_event)
1538d56354dcSSong Liu 		bpf_event__add_sb_event(&sb_evlist, &session->header.env);
1539d56354dcSSong Liu 
1540657ee553SSong Liu 	if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) {
1541657ee553SSong Liu 		pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
1542657ee553SSong Liu 		opts->no_bpf_event = true;
1543657ee553SSong Liu 	}
1544657ee553SSong Liu 
15454ea648aeSWang Nan 	err = record__synthesize(rec, false);
1546c45c86ebSWang Nan 	if (err < 0)
154745604710SNamhyung Kim 		goto out_child;
15488d3eca20SDavid Ahern 
1549d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
155086470930SIngo Molnar 		struct sched_param param;
155186470930SIngo Molnar 
1552d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
155386470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
15546beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
15558d3eca20SDavid Ahern 			err = -1;
155645604710SNamhyung Kim 			goto out_child;
155786470930SIngo Molnar 		}
155886470930SIngo Molnar 	}
155986470930SIngo Molnar 
1560774cb499SJiri Olsa 	/*
1561774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
1562774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
1563774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
1564774cb499SJiri Olsa 	 */
15656619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
15661c87f165SJiri Olsa 		evlist__enable(rec->evlist);
1567764e16a3SDavid Ahern 
1568856e9660SPeter Zijlstra 	/*
1569856e9660SPeter Zijlstra 	 * Let the child rip
1570856e9660SPeter Zijlstra 	 */
1571e803cf97SNamhyung Kim 	if (forks) {
157220a8a3cfSJiri Olsa 		struct machine *machine = &session->machines.host;
1573e5bed564SNamhyung Kim 		union perf_event *event;
1574e907caf3SHari Bathini 		pid_t tgid;
1575e5bed564SNamhyung Kim 
1576e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
1577e5bed564SNamhyung Kim 		if (event == NULL) {
1578e5bed564SNamhyung Kim 			err = -ENOMEM;
1579e5bed564SNamhyung Kim 			goto out_child;
1580e5bed564SNamhyung Kim 		}
1581e5bed564SNamhyung Kim 
1582e803cf97SNamhyung Kim 		/*
1583e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
1584e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
1585e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
1586e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
1587e803cf97SNamhyung Kim 		 */
1588e907caf3SHari Bathini 		tgid = perf_event__synthesize_comm(tool, event,
1589e803cf97SNamhyung Kim 						   rec->evlist->workload.pid,
1590e803cf97SNamhyung Kim 						   process_synthesized_event,
1591e803cf97SNamhyung Kim 						   machine);
1592e5bed564SNamhyung Kim 		free(event);
1593e803cf97SNamhyung Kim 
1594e907caf3SHari Bathini 		if (tgid == -1)
1595e907caf3SHari Bathini 			goto out_child;
1596e907caf3SHari Bathini 
1597e907caf3SHari Bathini 		event = malloc(sizeof(event->namespaces) +
1598e907caf3SHari Bathini 			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
1599e907caf3SHari Bathini 			       machine->id_hdr_size);
1600e907caf3SHari Bathini 		if (event == NULL) {
1601e907caf3SHari Bathini 			err = -ENOMEM;
1602e907caf3SHari Bathini 			goto out_child;
1603e907caf3SHari Bathini 		}
1604e907caf3SHari Bathini 
1605e907caf3SHari Bathini 		/*
1606e907caf3SHari Bathini 		 * Synthesize NAMESPACES event for the command specified.
1607e907caf3SHari Bathini 		 */
1608e907caf3SHari Bathini 		perf_event__synthesize_namespaces(tool, event,
1609e907caf3SHari Bathini 						  rec->evlist->workload.pid,
1610e907caf3SHari Bathini 						  tgid, process_synthesized_event,
1611e907caf3SHari Bathini 						  machine);
1612e907caf3SHari Bathini 		free(event);
1613e907caf3SHari Bathini 
16143e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
1615e803cf97SNamhyung Kim 	}
1616856e9660SPeter Zijlstra 
16176619a53eSAndi Kleen 	if (opts->initial_delay) {
16180693e680SArnaldo Carvalho de Melo 		usleep(opts->initial_delay * USEC_PER_MSEC);
16191c87f165SJiri Olsa 		evlist__enable(rec->evlist);
16206619a53eSAndi Kleen 	}
16216619a53eSAndi Kleen 
16225f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
16233c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
1624a074865eSWang Nan 	perf_hooks__invoke_record_start();
1625649c48a9SPeter Zijlstra 	for (;;) {
16269f065194SYang Shi 		unsigned long long hits = rec->samples;
162786470930SIngo Molnar 
162805737464SWang Nan 		/*
162905737464SWang Nan 		 * rec->evlist->bkw_mmap_state is possible to be
163005737464SWang Nan 		 * BKW_MMAP_EMPTY here: when done == true and
163105737464SWang Nan 		 * hits != rec->samples in previous round.
163205737464SWang Nan 		 *
163305737464SWang Nan 		 * perf_evlist__toggle_bkw_mmap ensure we never
163405737464SWang Nan 		 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
163505737464SWang Nan 		 */
163605737464SWang Nan 		if (trigger_is_hit(&switch_output_trigger) || done || draining)
163705737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
163805737464SWang Nan 
1639470530bbSAlexey Budankov 		if (record__mmap_read_all(rec, false) < 0) {
16405f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
16413c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
16428d3eca20SDavid Ahern 			err = -1;
164345604710SNamhyung Kim 			goto out_child;
16448d3eca20SDavid Ahern 		}
164586470930SIngo Molnar 
16462dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
16472dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
16485f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
1649ce7b0e42SAlexander Shishkin 				record__read_auxtrace_snapshot(rec, false);
16505f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
16512dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
16522dd6d8a1SAdrian Hunter 				err = -1;
16532dd6d8a1SAdrian Hunter 				goto out_child;
16542dd6d8a1SAdrian Hunter 			}
16552dd6d8a1SAdrian Hunter 		}
16562dd6d8a1SAdrian Hunter 
16573c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
165805737464SWang Nan 			/*
165905737464SWang Nan 			 * If switch_output_trigger is hit, the data in
166005737464SWang Nan 			 * overwritable ring buffer should have been collected,
166105737464SWang Nan 			 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
166205737464SWang Nan 			 *
166305737464SWang Nan 			 * If SIGUSR2 raise after or during record__mmap_read_all(),
166405737464SWang Nan 			 * record__mmap_read_all() didn't collect data from
166505737464SWang Nan 			 * overwritable ring buffer. Read again.
166605737464SWang Nan 			 */
166705737464SWang Nan 			if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
166805737464SWang Nan 				continue;
16693c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
16703c1cb7e3SWang Nan 
167105737464SWang Nan 			/*
167205737464SWang Nan 			 * Reenable events in overwrite ring buffer after
167305737464SWang Nan 			 * record__mmap_read_all(): we should have collected
167405737464SWang Nan 			 * data from it.
167505737464SWang Nan 			 */
167605737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
167705737464SWang Nan 
16783c1cb7e3SWang Nan 			if (!quiet)
16793c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
16803c1cb7e3SWang Nan 					waking);
16813c1cb7e3SWang Nan 			waking = 0;
16823c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
16833c1cb7e3SWang Nan 			if (fd < 0) {
16843c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
16853c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
16863c1cb7e3SWang Nan 				err = fd;
16873c1cb7e3SWang Nan 				goto out_child;
16883c1cb7e3SWang Nan 			}
1689bfacbe3bSJiri Olsa 
1690bfacbe3bSJiri Olsa 			/* re-arm the alarm */
1691bfacbe3bSJiri Olsa 			if (rec->switch_output.time)
1692bfacbe3bSJiri Olsa 				alarm(rec->switch_output.time);
16933c1cb7e3SWang Nan 		}
16943c1cb7e3SWang Nan 
1695d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
16966dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
1697649c48a9SPeter Zijlstra 				break;
169880ab2987SJiri Olsa 			err = evlist__poll(rec->evlist, -1);
1699a515114fSJiri Olsa 			/*
1700a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
1701a515114fSJiri Olsa 			 * number of returned events and interrupt error.
1702a515114fSJiri Olsa 			 */
1703a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
170445604710SNamhyung Kim 				err = 0;
17058b412664SPeter Zijlstra 			waking++;
17066dcf45efSArnaldo Carvalho de Melo 
1707f4009e7bSJiri Olsa 			if (evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
17086dcf45efSArnaldo Carvalho de Melo 				draining = true;
17098b412664SPeter Zijlstra 		}
17108b412664SPeter Zijlstra 
1711774cb499SJiri Olsa 		/*
1712774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
1713774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
1714774cb499SJiri Olsa 		 * disable events in this case.
1715774cb499SJiri Olsa 		 */
1716602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
17175f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
1718e74676deSJiri Olsa 			evlist__disable(rec->evlist);
17192711926aSJiri Olsa 			disabled = true;
17202711926aSJiri Olsa 		}
17218b412664SPeter Zijlstra 	}
1722ce7b0e42SAlexander Shishkin 
17235f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
17243c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
17258b412664SPeter Zijlstra 
1726ce7b0e42SAlexander Shishkin 	if (opts->auxtrace_snapshot_on_exit)
1727ce7b0e42SAlexander Shishkin 		record__auxtrace_snapshot_exit(rec);
1728ce7b0e42SAlexander Shishkin 
1729f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
173035550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
1731c8b5f2c9SArnaldo Carvalho de Melo 		const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
1732f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
1733f33cbe72SArnaldo Carvalho de Melo 		err = -1;
173445604710SNamhyung Kim 		goto out_child;
1735f33cbe72SArnaldo Carvalho de Melo 	}
1736f33cbe72SArnaldo Carvalho de Melo 
1737e3d59112SNamhyung Kim 	if (!quiet)
17388b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
173986470930SIngo Molnar 
17404ea648aeSWang Nan 	if (target__none(&rec->opts.target))
17414ea648aeSWang Nan 		record__synthesize_workload(rec, true);
17424ea648aeSWang Nan 
174345604710SNamhyung Kim out_child:
1744470530bbSAlexey Budankov 	record__mmap_read_all(rec, true);
1745d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
1746d3d1af6fSAlexey Budankov 
1747d3c8c08eSAlexey Budankov 	if (rec->session->bytes_transferred && rec->session->bytes_compressed) {
1748d3c8c08eSAlexey Budankov 		ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed;
1749d3c8c08eSAlexey Budankov 		session->header.env.comp_ratio = ratio + 0.5;
1750d3c8c08eSAlexey Budankov 	}
1751d3c8c08eSAlexey Budankov 
175245604710SNamhyung Kim 	if (forks) {
175345604710SNamhyung Kim 		int exit_status;
175445604710SNamhyung Kim 
175545604710SNamhyung Kim 		if (!child_finished)
175645604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
175745604710SNamhyung Kim 
175845604710SNamhyung Kim 		wait(&exit_status);
175945604710SNamhyung Kim 
176045604710SNamhyung Kim 		if (err < 0)
176145604710SNamhyung Kim 			status = err;
176245604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
176345604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
176445604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
176545604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
176645604710SNamhyung Kim 	} else
176745604710SNamhyung Kim 		status = err;
176845604710SNamhyung Kim 
17694ea648aeSWang Nan 	record__synthesize(rec, true);
1770e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
1771e3d59112SNamhyung Kim 	rec->samples = 0;
1772e3d59112SNamhyung Kim 
1773ecfd7a9cSWang Nan 	if (!err) {
1774ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
1775e1ab48baSWang Nan 			record__finish_output(rec);
1776ecfd7a9cSWang Nan 		} else {
1777ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
1778ecfd7a9cSWang Nan 			if (fd < 0) {
1779ecfd7a9cSWang Nan 				status = fd;
1780ecfd7a9cSWang Nan 				goto out_delete_session;
1781ecfd7a9cSWang Nan 			}
1782ecfd7a9cSWang Nan 		}
1783ecfd7a9cSWang Nan 	}
178439d17dacSArnaldo Carvalho de Melo 
1785a074865eSWang Nan 	perf_hooks__invoke_record_end();
1786a074865eSWang Nan 
1787e3d59112SNamhyung Kim 	if (!err && !quiet) {
1788e3d59112SNamhyung Kim 		char samples[128];
1789ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
1790ecfd7a9cSWang Nan 					".<timestamp>" : "";
1791e3d59112SNamhyung Kim 
1792ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
1793e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
1794e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
1795e3d59112SNamhyung Kim 		else
1796e3d59112SNamhyung Kim 			samples[0] = '\0';
1797e3d59112SNamhyung Kim 
1798d3c8c08eSAlexey Budankov 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s",
17998ceb41d7SJiri Olsa 			perf_data__size(data) / 1024.0 / 1024.0,
18002d4f2799SJiri Olsa 			data->path, postfix, samples);
1801d3c8c08eSAlexey Budankov 		if (ratio) {
1802d3c8c08eSAlexey Budankov 			fprintf(stderr,	", compressed (original %.3f MB, ratio is %.3f)",
1803d3c8c08eSAlexey Budankov 					rec->session->bytes_transferred / 1024.0 / 1024.0,
1804d3c8c08eSAlexey Budankov 					ratio);
1805d3c8c08eSAlexey Budankov 		}
1806d3c8c08eSAlexey Budankov 		fprintf(stderr, " ]\n");
1807e3d59112SNamhyung Kim 	}
1808e3d59112SNamhyung Kim 
180939d17dacSArnaldo Carvalho de Melo out_delete_session:
18105d7f4116SAlexey Budankov 	zstd_fini(&session->zstd_data);
181139d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
1812657ee553SSong Liu 
1813657ee553SSong Liu 	if (!opts->no_bpf_event)
1814657ee553SSong Liu 		perf_evlist__stop_sb_thread(sb_evlist);
181545604710SNamhyung Kim 	return status;
181686470930SIngo Molnar }
181786470930SIngo Molnar 
18180883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
181909b0fd45SJiri Olsa {
1820aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
1821a601fdffSJiri Olsa 
18220883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
182326d33022SJiri Olsa 
18240883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
182509b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
18260883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
18270883e820SArnaldo Carvalho de Melo }
18280883e820SArnaldo Carvalho de Melo 
18290883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
18300883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
18310883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
18320883e820SArnaldo Carvalho de Melo {
18330883e820SArnaldo Carvalho de Melo 	int ret;
18340883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
18350883e820SArnaldo Carvalho de Melo 
18360883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
18370883e820SArnaldo Carvalho de Melo 	if (unset) {
18380883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
18390883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
18400883e820SArnaldo Carvalho de Melo 		return 0;
18410883e820SArnaldo Carvalho de Melo 	}
18420883e820SArnaldo Carvalho de Melo 
18430883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
18440883e820SArnaldo Carvalho de Melo 	if (!ret) {
18450883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
18460883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
18470883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
18480883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
18490883e820SArnaldo Carvalho de Melo 	}
18500883e820SArnaldo Carvalho de Melo 
18510883e820SArnaldo Carvalho de Melo 	return ret;
185209b0fd45SJiri Olsa }
185309b0fd45SJiri Olsa 
1854c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
185509b0fd45SJiri Olsa 			       const char *arg,
185609b0fd45SJiri Olsa 			       int unset)
185709b0fd45SJiri Olsa {
18580883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
185926d33022SJiri Olsa }
186026d33022SJiri Olsa 
1861c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
186209b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
186309b0fd45SJiri Olsa 			 int unset __maybe_unused)
186409b0fd45SJiri Olsa {
18652ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1866c421e80bSKan Liang 
18672ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
186809b0fd45SJiri Olsa 
18692ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
18702ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1871eb853e80SJiri Olsa 
18722ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
187309b0fd45SJiri Olsa 	return 0;
187409b0fd45SJiri Olsa }
187509b0fd45SJiri Olsa 
1876eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1877eb853e80SJiri Olsa {
18787a29c087SNamhyung Kim 	struct record *rec = cb;
18797a29c087SNamhyung Kim 
18807a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
18817a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
18827a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
18837a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
18847a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
18857a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
18867a29c087SNamhyung Kim 			rec->no_buildid = true;
18877a29c087SNamhyung Kim 		else
18887a29c087SNamhyung Kim 			return -1;
18897a29c087SNamhyung Kim 		return 0;
18907a29c087SNamhyung Kim 	}
1891cff17205SYisheng Xie 	if (!strcmp(var, "record.call-graph")) {
1892cff17205SYisheng Xie 		var = "call-graph.record-mode";
1893eb853e80SJiri Olsa 		return perf_default_config(var, value, cb);
1894eb853e80SJiri Olsa 	}
189593f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
189693f20c0fSAlexey Budankov 	if (!strcmp(var, "record.aio")) {
189793f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = strtol(value, NULL, 0);
189893f20c0fSAlexey Budankov 		if (!rec->opts.nr_cblocks)
189993f20c0fSAlexey Budankov 			rec->opts.nr_cblocks = nr_cblocks_default;
190093f20c0fSAlexey Budankov 	}
190193f20c0fSAlexey Budankov #endif
1902eb853e80SJiri Olsa 
1903cff17205SYisheng Xie 	return 0;
1904cff17205SYisheng Xie }
1905cff17205SYisheng Xie 
1906814c8c38SPeter Zijlstra struct clockid_map {
1907814c8c38SPeter Zijlstra 	const char *name;
1908814c8c38SPeter Zijlstra 	int clockid;
1909814c8c38SPeter Zijlstra };
1910814c8c38SPeter Zijlstra 
1911814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1912814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1913814c8c38SPeter Zijlstra 
1914814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1915814c8c38SPeter Zijlstra 
1916814c8c38SPeter Zijlstra 
1917814c8c38SPeter Zijlstra /*
1918814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1919814c8c38SPeter Zijlstra  */
1920814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1921814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1922814c8c38SPeter Zijlstra #endif
1923814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1924814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1925814c8c38SPeter Zijlstra #endif
1926814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1927814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1928814c8c38SPeter Zijlstra #endif
1929814c8c38SPeter Zijlstra 
1930814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1931814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1932814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1933814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1934814c8c38SPeter Zijlstra 
1935814c8c38SPeter Zijlstra 	/* available for some events */
1936814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1937814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1938814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1939814c8c38SPeter Zijlstra 
1940814c8c38SPeter Zijlstra 	/* available for the lazy */
1941814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1942814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1943814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1944814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1945814c8c38SPeter Zijlstra 
1946814c8c38SPeter Zijlstra 	CLOCKID_END,
1947814c8c38SPeter Zijlstra };
1948814c8c38SPeter Zijlstra 
1949cf790516SAlexey Budankov static int get_clockid_res(clockid_t clk_id, u64 *res_ns)
1950cf790516SAlexey Budankov {
1951cf790516SAlexey Budankov 	struct timespec res;
1952cf790516SAlexey Budankov 
1953cf790516SAlexey Budankov 	*res_ns = 0;
1954cf790516SAlexey Budankov 	if (!clock_getres(clk_id, &res))
1955cf790516SAlexey Budankov 		*res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
1956cf790516SAlexey Budankov 	else
1957cf790516SAlexey Budankov 		pr_warning("WARNING: Failed to determine specified clock resolution.\n");
1958cf790516SAlexey Budankov 
1959cf790516SAlexey Budankov 	return 0;
1960cf790516SAlexey Budankov }
1961cf790516SAlexey Budankov 
1962814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1963814c8c38SPeter Zijlstra {
1964814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1965814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1966814c8c38SPeter Zijlstra 	const char *ostr = str;
1967814c8c38SPeter Zijlstra 
1968814c8c38SPeter Zijlstra 	if (unset) {
1969814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1970814c8c38SPeter Zijlstra 		return 0;
1971814c8c38SPeter Zijlstra 	}
1972814c8c38SPeter Zijlstra 
1973814c8c38SPeter Zijlstra 	/* no arg passed */
1974814c8c38SPeter Zijlstra 	if (!str)
1975814c8c38SPeter Zijlstra 		return 0;
1976814c8c38SPeter Zijlstra 
1977814c8c38SPeter Zijlstra 	/* no setting it twice */
1978814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1979814c8c38SPeter Zijlstra 		return -1;
1980814c8c38SPeter Zijlstra 
1981814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1982814c8c38SPeter Zijlstra 
1983814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1984814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1985cf790516SAlexey Budankov 		return get_clockid_res(opts->clockid, &opts->clockid_res_ns);
1986814c8c38SPeter Zijlstra 
1987814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1988814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1989814c8c38SPeter Zijlstra 		str += 6;
1990814c8c38SPeter Zijlstra 
1991814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1992814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1993814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1994cf790516SAlexey Budankov 			return get_clockid_res(opts->clockid,
1995cf790516SAlexey Budankov 					       &opts->clockid_res_ns);
1996814c8c38SPeter Zijlstra 		}
1997814c8c38SPeter Zijlstra 	}
1998814c8c38SPeter Zijlstra 
1999814c8c38SPeter Zijlstra 	opts->use_clockid = false;
2000814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
2001814c8c38SPeter Zijlstra 	return -1;
2002814c8c38SPeter Zijlstra }
2003814c8c38SPeter Zijlstra 
2004f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset)
2005f4fe11b7SAlexey Budankov {
2006f4fe11b7SAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
2007f4fe11b7SAlexey Budankov 
2008f4fe11b7SAlexey Budankov 	if (unset || !str)
2009f4fe11b7SAlexey Budankov 		return 0;
2010f4fe11b7SAlexey Budankov 
2011f4fe11b7SAlexey Budankov 	if (!strcasecmp(str, "node"))
2012f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_NODE;
2013f4fe11b7SAlexey Budankov 	else if (!strcasecmp(str, "cpu"))
2014f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_CPU;
2015f4fe11b7SAlexey Budankov 
2016f4fe11b7SAlexey Budankov 	return 0;
2017f4fe11b7SAlexey Budankov }
2018f4fe11b7SAlexey Budankov 
20196d575816SJiwei Sun static int parse_output_max_size(const struct option *opt,
20206d575816SJiwei Sun 				 const char *str, int unset)
20216d575816SJiwei Sun {
20226d575816SJiwei Sun 	unsigned long *s = (unsigned long *)opt->value;
20236d575816SJiwei Sun 	static struct parse_tag tags_size[] = {
20246d575816SJiwei Sun 		{ .tag  = 'B', .mult = 1       },
20256d575816SJiwei Sun 		{ .tag  = 'K', .mult = 1 << 10 },
20266d575816SJiwei Sun 		{ .tag  = 'M', .mult = 1 << 20 },
20276d575816SJiwei Sun 		{ .tag  = 'G', .mult = 1 << 30 },
20286d575816SJiwei Sun 		{ .tag  = 0 },
20296d575816SJiwei Sun 	};
20306d575816SJiwei Sun 	unsigned long val;
20316d575816SJiwei Sun 
20326d575816SJiwei Sun 	if (unset) {
20336d575816SJiwei Sun 		*s = 0;
20346d575816SJiwei Sun 		return 0;
20356d575816SJiwei Sun 	}
20366d575816SJiwei Sun 
20376d575816SJiwei Sun 	val = parse_tag_value(str, tags_size);
20386d575816SJiwei Sun 	if (val != (unsigned long) -1) {
20396d575816SJiwei Sun 		*s = val;
20406d575816SJiwei Sun 		return 0;
20416d575816SJiwei Sun 	}
20426d575816SJiwei Sun 
20436d575816SJiwei Sun 	return -1;
20446d575816SJiwei Sun }
20456d575816SJiwei Sun 
2046e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
2047e9db1310SAdrian Hunter 				    const char *str,
2048e9db1310SAdrian Hunter 				    int unset __maybe_unused)
2049e9db1310SAdrian Hunter {
2050e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
2051e9db1310SAdrian Hunter 	char *s, *p;
2052e9db1310SAdrian Hunter 	unsigned int mmap_pages;
2053e9db1310SAdrian Hunter 	int ret;
2054e9db1310SAdrian Hunter 
2055e9db1310SAdrian Hunter 	if (!str)
2056e9db1310SAdrian Hunter 		return -EINVAL;
2057e9db1310SAdrian Hunter 
2058e9db1310SAdrian Hunter 	s = strdup(str);
2059e9db1310SAdrian Hunter 	if (!s)
2060e9db1310SAdrian Hunter 		return -ENOMEM;
2061e9db1310SAdrian Hunter 
2062e9db1310SAdrian Hunter 	p = strchr(s, ',');
2063e9db1310SAdrian Hunter 	if (p)
2064e9db1310SAdrian Hunter 		*p = '\0';
2065e9db1310SAdrian Hunter 
2066e9db1310SAdrian Hunter 	if (*s) {
2067e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
2068e9db1310SAdrian Hunter 		if (ret)
2069e9db1310SAdrian Hunter 			goto out_free;
2070e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
2071e9db1310SAdrian Hunter 	}
2072e9db1310SAdrian Hunter 
2073e9db1310SAdrian Hunter 	if (!p) {
2074e9db1310SAdrian Hunter 		ret = 0;
2075e9db1310SAdrian Hunter 		goto out_free;
2076e9db1310SAdrian Hunter 	}
2077e9db1310SAdrian Hunter 
2078e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
2079e9db1310SAdrian Hunter 	if (ret)
2080e9db1310SAdrian Hunter 		goto out_free;
2081e9db1310SAdrian Hunter 
2082e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
2083e9db1310SAdrian Hunter 
2084e9db1310SAdrian Hunter out_free:
2085e9db1310SAdrian Hunter 	free(s);
2086e9db1310SAdrian Hunter 	return ret;
2087e9db1310SAdrian Hunter }
2088e9db1310SAdrian Hunter 
20890c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
20900c582449SJiri Olsa {
20919521b5f2SJiri Olsa 	u64 wakeup_size = evlist__mmap_size(rec->opts.mmap_pages);
20920c582449SJiri Olsa 	struct switch_output *s = &rec->switch_output;
20930c582449SJiri Olsa 
20940c582449SJiri Olsa 	wakeup_size /= 2;
20950c582449SJiri Olsa 
20960c582449SJiri Olsa 	if (s->size < wakeup_size) {
20970c582449SJiri Olsa 		char buf[100];
20980c582449SJiri Olsa 
20990c582449SJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
21000c582449SJiri Olsa 		pr_warning("WARNING: switch-output data size lower than "
21010c582449SJiri Olsa 			   "wakeup kernel buffer size (%s) "
21020c582449SJiri Olsa 			   "expect bigger perf.data sizes\n", buf);
21030c582449SJiri Olsa 	}
21040c582449SJiri Olsa }
21050c582449SJiri Olsa 
2106cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
2107cb4e1ebbSJiri Olsa {
2108cb4e1ebbSJiri Olsa 	struct switch_output *s = &rec->switch_output;
2109dc0c6127SJiri Olsa 	static struct parse_tag tags_size[] = {
2110dc0c6127SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
2111dc0c6127SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
2112dc0c6127SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
2113dc0c6127SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
2114dc0c6127SJiri Olsa 		{ .tag  = 0 },
2115dc0c6127SJiri Olsa 	};
2116bfacbe3bSJiri Olsa 	static struct parse_tag tags_time[] = {
2117bfacbe3bSJiri Olsa 		{ .tag  = 's', .mult = 1        },
2118bfacbe3bSJiri Olsa 		{ .tag  = 'm', .mult = 60       },
2119bfacbe3bSJiri Olsa 		{ .tag  = 'h', .mult = 60*60    },
2120bfacbe3bSJiri Olsa 		{ .tag  = 'd', .mult = 60*60*24 },
2121bfacbe3bSJiri Olsa 		{ .tag  = 0 },
2122bfacbe3bSJiri Olsa 	};
2123dc0c6127SJiri Olsa 	unsigned long val;
2124cb4e1ebbSJiri Olsa 
2125cb4e1ebbSJiri Olsa 	if (!s->set)
2126cb4e1ebbSJiri Olsa 		return 0;
2127cb4e1ebbSJiri Olsa 
2128cb4e1ebbSJiri Olsa 	if (!strcmp(s->str, "signal")) {
2129cb4e1ebbSJiri Olsa 		s->signal = true;
2130cb4e1ebbSJiri Olsa 		pr_debug("switch-output with SIGUSR2 signal\n");
2131dc0c6127SJiri Olsa 		goto enabled;
2132dc0c6127SJiri Olsa 	}
2133dc0c6127SJiri Olsa 
2134dc0c6127SJiri Olsa 	val = parse_tag_value(s->str, tags_size);
2135dc0c6127SJiri Olsa 	if (val != (unsigned long) -1) {
2136dc0c6127SJiri Olsa 		s->size = val;
2137dc0c6127SJiri Olsa 		pr_debug("switch-output with %s size threshold\n", s->str);
2138dc0c6127SJiri Olsa 		goto enabled;
2139cb4e1ebbSJiri Olsa 	}
2140cb4e1ebbSJiri Olsa 
2141bfacbe3bSJiri Olsa 	val = parse_tag_value(s->str, tags_time);
2142bfacbe3bSJiri Olsa 	if (val != (unsigned long) -1) {
2143bfacbe3bSJiri Olsa 		s->time = val;
2144bfacbe3bSJiri Olsa 		pr_debug("switch-output with %s time threshold (%lu seconds)\n",
2145bfacbe3bSJiri Olsa 			 s->str, s->time);
2146bfacbe3bSJiri Olsa 		goto enabled;
2147bfacbe3bSJiri Olsa 	}
2148bfacbe3bSJiri Olsa 
2149cb4e1ebbSJiri Olsa 	return -1;
2150dc0c6127SJiri Olsa 
2151dc0c6127SJiri Olsa enabled:
2152dc0c6127SJiri Olsa 	rec->timestamp_filename = true;
2153dc0c6127SJiri Olsa 	s->enabled              = true;
21540c582449SJiri Olsa 
21550c582449SJiri Olsa 	if (s->size && !rec->opts.no_buffering)
21560c582449SJiri Olsa 		switch_output_size_warn(rec);
21570c582449SJiri Olsa 
2158dc0c6127SJiri Olsa 	return 0;
2159cb4e1ebbSJiri Olsa }
2160cb4e1ebbSJiri Olsa 
2161e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
216286470930SIngo Molnar 	"perf record [<options>] [<command>]",
216386470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
216486470930SIngo Molnar 	NULL
216586470930SIngo Molnar };
2166e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
216786470930SIngo Molnar 
21686e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap(struct perf_tool *tool, union perf_event *event,
21696e0a9b3dSArnaldo Carvalho de Melo 				  struct perf_sample *sample, struct machine *machine)
21706e0a9b3dSArnaldo Carvalho de Melo {
21716e0a9b3dSArnaldo Carvalho de Melo 	/*
21726e0a9b3dSArnaldo Carvalho de Melo 	 * We already have the kernel maps, put in place via perf_session__create_kernel_maps()
21736e0a9b3dSArnaldo Carvalho de Melo 	 * no need to add them twice.
21746e0a9b3dSArnaldo Carvalho de Melo 	 */
21756e0a9b3dSArnaldo Carvalho de Melo 	if (!(event->header.misc & PERF_RECORD_MISC_USER))
21766e0a9b3dSArnaldo Carvalho de Melo 		return 0;
21776e0a9b3dSArnaldo Carvalho de Melo 	return perf_event__process_mmap(tool, event, sample, machine);
21786e0a9b3dSArnaldo Carvalho de Melo }
21796e0a9b3dSArnaldo Carvalho de Melo 
21806e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap2(struct perf_tool *tool, union perf_event *event,
21816e0a9b3dSArnaldo Carvalho de Melo 				   struct perf_sample *sample, struct machine *machine)
21826e0a9b3dSArnaldo Carvalho de Melo {
21836e0a9b3dSArnaldo Carvalho de Melo 	/*
21846e0a9b3dSArnaldo Carvalho de Melo 	 * We already have the kernel maps, put in place via perf_session__create_kernel_maps()
21856e0a9b3dSArnaldo Carvalho de Melo 	 * no need to add them twice.
21866e0a9b3dSArnaldo Carvalho de Melo 	 */
21876e0a9b3dSArnaldo Carvalho de Melo 	if (!(event->header.misc & PERF_RECORD_MISC_USER))
21886e0a9b3dSArnaldo Carvalho de Melo 		return 0;
21896e0a9b3dSArnaldo Carvalho de Melo 
21906e0a9b3dSArnaldo Carvalho de Melo 	return perf_event__process_mmap2(tool, event, sample, machine);
21916e0a9b3dSArnaldo Carvalho de Melo }
21926e0a9b3dSArnaldo Carvalho de Melo 
2193d20deb64SArnaldo Carvalho de Melo /*
21948c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
21958c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
2196d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
2197d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
2198d20deb64SArnaldo Carvalho de Melo  *
2199d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
2200d20deb64SArnaldo Carvalho de Melo  *
2201d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
2202d20deb64SArnaldo Carvalho de Melo  */
22038c6f45a7SArnaldo Carvalho de Melo static struct record record = {
2204d20deb64SArnaldo Carvalho de Melo 	.opts = {
22058affc2b8SAndi Kleen 		.sample_time	     = true,
2206d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
2207d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
2208d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
2209447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
2210d1cb9fceSNamhyung Kim 		.target		     = {
2211d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
22123aa5939dSAdrian Hunter 			.default_per_cpu = true,
2213d1cb9fceSNamhyung Kim 		},
2214470530bbSAlexey Budankov 		.mmap_flush          = MMAP_FLUSH_DEFAULT,
2215d20deb64SArnaldo Carvalho de Melo 	},
2216e3d59112SNamhyung Kim 	.tool = {
2217e3d59112SNamhyung Kim 		.sample		= process_sample_event,
2218e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
2219cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
2220e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
2221f3b3614aSHari Bathini 		.namespaces	= perf_event__process_namespaces,
22226e0a9b3dSArnaldo Carvalho de Melo 		.mmap		= build_id__process_mmap,
22236e0a9b3dSArnaldo Carvalho de Melo 		.mmap2		= build_id__process_mmap2,
2224cca8482cSAdrian Hunter 		.ordered_events	= true,
2225e3d59112SNamhyung Kim 	},
2226d20deb64SArnaldo Carvalho de Melo };
22277865e817SFrederic Weisbecker 
222876a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
222976a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
223061eaa3beSArnaldo Carvalho de Melo 
22310aab2136SWang Nan static bool dry_run;
22320aab2136SWang Nan 
2233d20deb64SArnaldo Carvalho de Melo /*
2234d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
2235d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
2236b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
2237d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
2238d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
2239d20deb64SArnaldo Carvalho de Melo  */
2240efd21307SJiri Olsa static struct option __record_options[] = {
2241d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
224286470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
2243f120f9d5SJiri Olsa 		     parse_events_option),
2244d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
2245c171b552SLi Zefan 		     "event filter", parse_filter),
22464ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
22474ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
22484ba1faa1SWang Nan 			   exclude_perf),
2249bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
2250d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
2251bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
2252d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
2253d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
225486470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
2255509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
2256acac03faSKirill Smelkov 		    "collect data without buffering"),
2257d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
2258daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
2259bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
226086470930SIngo Molnar 			    "system-wide collection from all CPUs"),
2261bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
2262c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
2263d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
22642d4f2799SJiri Olsa 	OPT_STRING('o', "output", &record.data.path, "file",
226586470930SIngo Molnar 		    "output file name"),
226669e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
226769e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
22682e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
22694ea648aeSWang Nan 	OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
22704ea648aeSWang Nan 		    "synthesize non-sample events at the end of output"),
2271626a6b78SWang Nan 	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
227271184c6aSSong Liu 	OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"),
2273b09c2364SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
2274b09c2364SArnaldo Carvalho de Melo 		    "Fail if the specified frequency can't be used"),
227567230479SArnaldo Carvalho de Melo 	OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
227667230479SArnaldo Carvalho de Melo 		     "profile at this frequency",
227767230479SArnaldo Carvalho de Melo 		      record__parse_freq),
2278e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
2279e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
2280e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
2281470530bbSAlexey Budankov 	OPT_CALLBACK(0, "mmap-flush", &record.opts, "number",
2282470530bbSAlexey Budankov 		     "Minimal number of bytes that is extracted from mmap data pages (default: 1)",
2283470530bbSAlexey Budankov 		     record__mmap_flush_parse),
2284d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
228543bece79SLin Ming 		    "put the counters into a counter group"),
22862ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
228709b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
228809b0fd45SJiri Olsa 			   &record_callchain_opt),
228909b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
229076a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
229109b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
2292c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
22933da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
2294b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
2295d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
2296649c48a9SPeter Zijlstra 		    "per thread counts"),
229756100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
22983b0a5daaSKan Liang 	OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
22993b0a5daaSKan Liang 		    "Record the sample physical addresses"),
2300b6f35ed7SJiri Olsa 	OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
23013abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
23023abebc55SAdrian Hunter 			&record.opts.sample_time_set,
23033abebc55SAdrian Hunter 			"Record the sample timestamps"),
2304f290aa1fSJiri Olsa 	OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set,
2305f290aa1fSJiri Olsa 			"Record the sample period"),
2306d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
2307649c48a9SPeter Zijlstra 		    "don't sample"),
2308d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
2309d2db9a98SWang Nan 			&record.no_buildid_cache_set,
2310a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
2311d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
2312d2db9a98SWang Nan 			&record.no_buildid_set,
2313baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
2314d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
2315023695d9SStephane Eranian 		     "monitor event in cgroup name only",
2316023695d9SStephane Eranian 		     parse_cgroups),
2317a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
23186619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
2319eeb399b5SAdrian Hunter 	OPT_BOOLEAN(0, "kcore", &record.opts.kcore, "copy /proc/kcore"),
2320bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
2321bea03405SNamhyung Kim 		   "user to profile"),
2322a5aabdacSStephane Eranian 
2323a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
2324a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
2325a5aabdacSStephane Eranian 		     parse_branch_stack),
2326a5aabdacSStephane Eranian 
2327a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
2328a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
2329bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
233005484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
233105484298SAndi Kleen 		    "sample by weight (on special events only)"),
2332475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
2333475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
23343aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
23353aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
2336bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
2337bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
2338aeea9062SKan Liang 		    " use '-I?' to list register names", parse_intr_regs),
233984c41742SAndi Kleen 	OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
234084c41742SAndi Kleen 		    "sample selected machine registers on interrupt,"
2341aeea9062SKan Liang 		    " use '--user-regs=?' to list register names", parse_user_regs),
234285c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
234385c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
2344814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
2345814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
2346814c8c38SPeter Zijlstra 	parse_clockid),
23472dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
23482dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
2349c0a6de06SAdrian Hunter 	OPT_STRING_OPTARG(0, "aux-sample", &record.opts.auxtrace_sample_opts,
2350c0a6de06SAdrian Hunter 			  "opts", "sample AUX area", ""),
23513fcb10e4SMark Drayton 	OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
23529d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
2353f3b3614aSHari Bathini 	OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
2354f3b3614aSHari Bathini 		    "Record namespaces events"),
2355b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
2356b757bb09SAdrian Hunter 		    "Record context switch events"),
235785723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
235885723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
235985723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
236085723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
236185723885SJiri Olsa 			 "Configure all used events to run in user space.",
236285723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
236353651b28Syuzhoujian 	OPT_BOOLEAN(0, "kernel-callchains", &record.opts.kernel_callchains,
236453651b28Syuzhoujian 		    "collect kernel callchains"),
236553651b28Syuzhoujian 	OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains,
236653651b28Syuzhoujian 		    "collect user callchains"),
236771dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
236871dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
236971dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
237071dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
23717efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
23727efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
23736156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
23746156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
2375ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
2376ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
237768588bafSJin Yao 	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
237868588bafSJin Yao 		    "Record timestamp boundary (time of first/last samples)"),
2379cb4e1ebbSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
2380c38dab7dSAndi Kleen 			  &record.switch_output.set, "signal or size[BKMG] or time[smhd]",
2381c38dab7dSAndi Kleen 			  "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold",
2382dc0c6127SJiri Olsa 			  "signal"),
238303724b2eSAndi Kleen 	OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
238403724b2eSAndi Kleen 		   "Limit number of switch output generated files"),
23850aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
23860aab2136SWang Nan 		    "Parse options then exit"),
2387d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
238893f20c0fSAlexey Budankov 	OPT_CALLBACK_OPTARG(0, "aio", &record.opts,
238993f20c0fSAlexey Budankov 		     &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)",
2390d3d1af6fSAlexey Budankov 		     record__aio_parse),
2391d3d1af6fSAlexey Budankov #endif
2392f4fe11b7SAlexey Budankov 	OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
2393f4fe11b7SAlexey Budankov 		     "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer",
2394f4fe11b7SAlexey Budankov 		     record__parse_affinity),
2395504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT
2396504c1ad1SAlexey Budankov 	OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default,
2397504c1ad1SAlexey Budankov 			    "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)",
2398504c1ad1SAlexey Budankov 			    record__parse_comp_level),
2399504c1ad1SAlexey Budankov #endif
24006d575816SJiwei Sun 	OPT_CALLBACK(0, "max-size", &record.output_max_size,
24016d575816SJiwei Sun 		     "size", "Limit the maximum size of the output file", parse_output_max_size),
240286470930SIngo Molnar 	OPT_END()
240386470930SIngo Molnar };
240486470930SIngo Molnar 
2405e5b2c207SNamhyung Kim struct option *record_options = __record_options;
2406e5b2c207SNamhyung Kim 
2407b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
240886470930SIngo Molnar {
2409ef149c25SAdrian Hunter 	int err;
24108c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
241116ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
241286470930SIngo Molnar 
241367230479SArnaldo Carvalho de Melo 	setlocale(LC_ALL, "");
241467230479SArnaldo Carvalho de Melo 
241548e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
241648e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
241748e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
241848e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
241948e1cab1SWang Nan # undef set_nobuild
242048e1cab1SWang Nan #endif
242148e1cab1SWang Nan 
24227efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
24237efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
24247efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
24257efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
24267efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
24277efe0e03SHe Kuang # else
24287efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
24297efe0e03SHe Kuang # endif
24307efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
24317efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
24327efe0e03SHe Kuang # undef set_nobuild
24337efe0e03SHe Kuang # undef REASON
24347efe0e03SHe Kuang #endif
24357efe0e03SHe Kuang 
24369d2ed645SAlexey Budankov 	CPU_ZERO(&rec->affinity_mask);
24379d2ed645SAlexey Budankov 	rec->opts.affinity = PERF_AFFINITY_SYS;
24389d2ed645SAlexey Budankov 
24390f98b11cSJiri Olsa 	rec->evlist = evlist__new();
24403e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
2441361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
2442361c99a6SArnaldo Carvalho de Melo 
2443ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(perf_record_config, rec);
2444ecc4c561SArnaldo Carvalho de Melo 	if (err)
2445ecc4c561SArnaldo Carvalho de Melo 		return err;
2446eb853e80SJiri Olsa 
2447bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
2448a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
244968ba3235SNamhyung Kim 	if (quiet)
245068ba3235SNamhyung Kim 		perf_quiet_option();
2451483635a9SJiri Olsa 
2452483635a9SJiri Olsa 	/* Make system wide (-a) the default target. */
2453602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
2454483635a9SJiri Olsa 		rec->opts.target.system_wide = true;
245586470930SIngo Molnar 
2456bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
2457c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
2458c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
2459c7118369SNamhyung Kim 
2460023695d9SStephane Eranian 	}
2461504c1ad1SAlexey Budankov 
2462eeb399b5SAdrian Hunter 	if (rec->opts.kcore)
2463eeb399b5SAdrian Hunter 		rec->data.is_dir = true;
2464eeb399b5SAdrian Hunter 
2465504c1ad1SAlexey Budankov 	if (rec->opts.comp_level != 0) {
2466504c1ad1SAlexey Budankov 		pr_debug("Compression enabled, disabling build id collection at the end of the session.\n");
2467504c1ad1SAlexey Budankov 		rec->no_buildid = true;
2468504c1ad1SAlexey Budankov 	}
2469504c1ad1SAlexey Budankov 
2470b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
2471b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
2472c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
2473c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
2474c7118369SNamhyung Kim 		return -EINVAL;
2475b757bb09SAdrian Hunter 	}
2476023695d9SStephane Eranian 
2477cb4e1ebbSJiri Olsa 	if (switch_output_setup(rec)) {
2478cb4e1ebbSJiri Olsa 		parse_options_usage(record_usage, record_options, "switch-output", 0);
2479cb4e1ebbSJiri Olsa 		return -EINVAL;
2480cb4e1ebbSJiri Olsa 	}
2481cb4e1ebbSJiri Olsa 
2482bfacbe3bSJiri Olsa 	if (rec->switch_output.time) {
2483bfacbe3bSJiri Olsa 		signal(SIGALRM, alarm_sig_handler);
2484bfacbe3bSJiri Olsa 		alarm(rec->switch_output.time);
2485bfacbe3bSJiri Olsa 	}
2486bfacbe3bSJiri Olsa 
248703724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
248803724b2eSAndi Kleen 		rec->switch_output.filenames = calloc(sizeof(char *),
248903724b2eSAndi Kleen 						      rec->switch_output.num_files);
249003724b2eSAndi Kleen 		if (!rec->switch_output.filenames)
249103724b2eSAndi Kleen 			return -EINVAL;
249203724b2eSAndi Kleen 	}
249303724b2eSAndi Kleen 
24941b36c03eSAdrian Hunter 	/*
24951b36c03eSAdrian Hunter 	 * Allow aliases to facilitate the lookup of symbols for address
24961b36c03eSAdrian Hunter 	 * filters. Refer to auxtrace_parse_filters().
24971b36c03eSAdrian Hunter 	 */
24981b36c03eSAdrian Hunter 	symbol_conf.allow_aliases = true;
24991b36c03eSAdrian Hunter 
25001b36c03eSAdrian Hunter 	symbol__init(NULL);
25011b36c03eSAdrian Hunter 
25024b5ea3bdSAdrian Hunter 	err = record__auxtrace_init(rec);
25031b36c03eSAdrian Hunter 	if (err)
25041b36c03eSAdrian Hunter 		goto out;
25051b36c03eSAdrian Hunter 
25060aab2136SWang Nan 	if (dry_run)
25075c01ad60SAdrian Hunter 		goto out;
25080aab2136SWang Nan 
2509d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
2510d7888573SWang Nan 	if (err) {
2511d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
2512d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
2513d7888573SWang Nan 			 errbuf);
25145c01ad60SAdrian Hunter 		goto out;
2515d7888573SWang Nan 	}
2516d7888573SWang Nan 
2517ef149c25SAdrian Hunter 	err = -ENOMEM;
2518ef149c25SAdrian Hunter 
25190c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
2520a1ac1d3cSStephane Eranian 		disable_buildid_cache();
2521dc0c6127SJiri Olsa 	} else if (rec->switch_output.enabled) {
25220c1d46a8SWang Nan 		/*
25230c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
25240c1d46a8SWang Nan 		 * generation by default to reduce data file switching
25250c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
25260c1d46a8SWang Nan 		 * explicitly using
25270c1d46a8SWang Nan 		 *
252860437ac0SJiri Olsa 		 *  perf record --switch-output --no-no-buildid \
25290c1d46a8SWang Nan 		 *              --no-no-buildid-cache
25300c1d46a8SWang Nan 		 *
25310c1d46a8SWang Nan 		 * Following code equals to:
25320c1d46a8SWang Nan 		 *
25330c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
25340c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
25350c1d46a8SWang Nan 		 *         disable_buildid_cache();
25360c1d46a8SWang Nan 		 */
25370c1d46a8SWang Nan 		bool disable = true;
25380c1d46a8SWang Nan 
25390c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
25400c1d46a8SWang Nan 			disable = false;
25410c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
25420c1d46a8SWang Nan 			disable = false;
25430c1d46a8SWang Nan 		if (disable) {
25440c1d46a8SWang Nan 			rec->no_buildid = true;
25450c1d46a8SWang Nan 			rec->no_buildid_cache = true;
25460c1d46a8SWang Nan 			disable_buildid_cache();
25470c1d46a8SWang Nan 		}
25480c1d46a8SWang Nan 	}
2549655000e7SArnaldo Carvalho de Melo 
25504ea648aeSWang Nan 	if (record.opts.overwrite)
25514ea648aeSWang Nan 		record.opts.tail_synthesize = true;
25524ea648aeSWang Nan 
25536484d2f9SJiri Olsa 	if (rec->evlist->core.nr_entries == 0 &&
25544b4cd503SArnaldo Carvalho de Melo 	    __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
255569aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
2556394c01edSAdrian Hunter 		goto out;
2557bbd36e5eSPeter Zijlstra 	}
255886470930SIngo Molnar 
255969e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
256069e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
256169e7e5b0SAdrian Hunter 
2562602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
256316ad2ffbSNamhyung Kim 	if (err) {
2564602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
2565c3dec27bSJiri Olsa 		ui__warning("%s\n", errbuf);
256616ad2ffbSNamhyung Kim 	}
25674bd0f2d2SNamhyung Kim 
2568602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
256916ad2ffbSNamhyung Kim 	if (err) {
257016ad2ffbSNamhyung Kim 		int saved_errno = errno;
257116ad2ffbSNamhyung Kim 
2572602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
25733780f488SNamhyung Kim 		ui__error("%s", errbuf);
257416ad2ffbSNamhyung Kim 
257516ad2ffbSNamhyung Kim 		err = -saved_errno;
2576394c01edSAdrian Hunter 		goto out;
257716ad2ffbSNamhyung Kim 	}
25780d37aa34SArnaldo Carvalho de Melo 
2579ca800068SMengting Zhang 	/* Enable ignoring missing threads when -u/-p option is defined. */
2580ca800068SMengting Zhang 	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
258123dc4f15SJiri Olsa 
258216ad2ffbSNamhyung Kim 	err = -ENOMEM;
25833e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
2584dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
258569aad6f1SArnaldo Carvalho de Melo 
2586ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
2587ef149c25SAdrian Hunter 	if (err)
2588394c01edSAdrian Hunter 		goto out;
2589ef149c25SAdrian Hunter 
25906156681bSNamhyung Kim 	/*
25916156681bSNamhyung Kim 	 * We take all buildids when the file contains
25926156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
25936156681bSNamhyung Kim 	 * trace because it would take too long.
25946156681bSNamhyung Kim 	 */
25956156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
25966156681bSNamhyung Kim 		rec->buildid_all = true;
25976156681bSNamhyung Kim 
2598b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
259939d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
2600394c01edSAdrian Hunter 		goto out;
26017e4ff9e3SMike Galbraith 	}
26027e4ff9e3SMike Galbraith 
260393f20c0fSAlexey Budankov 	if (rec->opts.nr_cblocks > nr_cblocks_max)
260493f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = nr_cblocks_max;
26055d7f4116SAlexey Budankov 	pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks);
2606d3d1af6fSAlexey Budankov 
26079d2ed645SAlexey Budankov 	pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]);
2608470530bbSAlexey Budankov 	pr_debug("mmap flush: %d\n", rec->opts.mmap_flush);
26099d2ed645SAlexey Budankov 
261051255a8aSAlexey Budankov 	if (rec->opts.comp_level > comp_level_max)
261151255a8aSAlexey Budankov 		rec->opts.comp_level = comp_level_max;
261251255a8aSAlexey Budankov 	pr_debug("comp level: %d\n", rec->opts.comp_level);
261351255a8aSAlexey Budankov 
2614d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
2615394c01edSAdrian Hunter out:
2616c12995a5SJiri Olsa 	evlist__delete(rec->evlist);
2617d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
2618ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
261939d17dacSArnaldo Carvalho de Melo 	return err;
262086470930SIngo Molnar }
26212dd6d8a1SAdrian Hunter 
26222dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
26232dd6d8a1SAdrian Hunter {
2624dc0c6127SJiri Olsa 	struct record *rec = &record;
2625dc0c6127SJiri Olsa 
26265f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
26275f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
26282dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
26295f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
26305f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
26315f9cf599SWang Nan 	}
26323c1cb7e3SWang Nan 
2633dc0c6127SJiri Olsa 	if (switch_output_signal(rec))
26343c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
26352dd6d8a1SAdrian Hunter }
2636bfacbe3bSJiri Olsa 
2637bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
2638bfacbe3bSJiri Olsa {
2639bfacbe3bSJiri Olsa 	struct record *rec = &record;
2640bfacbe3bSJiri Olsa 
2641bfacbe3bSJiri Olsa 	if (switch_output_time(rec))
2642bfacbe3bSJiri Olsa 		trigger_hit(&switch_output_trigger);
2643bfacbe3bSJiri Olsa }
2644