xref: /aosp_15_r20/external/blktrace/blktrace.c (revision 1a3d31e37cc95e9919fd86900a2b6a555f55952c)
1*1a3d31e3SAndroid Build Coastguard Worker /*
2*1a3d31e3SAndroid Build Coastguard Worker  * block queue tracing application
3*1a3d31e3SAndroid Build Coastguard Worker  *
4*1a3d31e3SAndroid Build Coastguard Worker  * Copyright (C) 2005 Jens Axboe <[email protected]>
5*1a3d31e3SAndroid Build Coastguard Worker  * Copyright (C) 2006 Jens Axboe <[email protected]>
6*1a3d31e3SAndroid Build Coastguard Worker  *
7*1a3d31e3SAndroid Build Coastguard Worker  * Rewrite to have a single thread per CPU (managing all devices on that CPU)
8*1a3d31e3SAndroid Build Coastguard Worker  *	Alan D. Brunelle <[email protected]> - January 2009
9*1a3d31e3SAndroid Build Coastguard Worker  *
10*1a3d31e3SAndroid Build Coastguard Worker  *  This program is free software; you can redistribute it and/or modify
11*1a3d31e3SAndroid Build Coastguard Worker  *  it under the terms of the GNU General Public License as published by
12*1a3d31e3SAndroid Build Coastguard Worker  *  the Free Software Foundation; either version 2 of the License, or
13*1a3d31e3SAndroid Build Coastguard Worker  *  (at your option) any later version.
14*1a3d31e3SAndroid Build Coastguard Worker  *
15*1a3d31e3SAndroid Build Coastguard Worker  *  This program is distributed in the hope that it will be useful,
16*1a3d31e3SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17*1a3d31e3SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*1a3d31e3SAndroid Build Coastguard Worker  *  GNU General Public License for more details.
19*1a3d31e3SAndroid Build Coastguard Worker  *
20*1a3d31e3SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU General Public License
21*1a3d31e3SAndroid Build Coastguard Worker  *  along with this program; if not, write to the Free Software
22*1a3d31e3SAndroid Build Coastguard Worker  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23*1a3d31e3SAndroid Build Coastguard Worker  *
24*1a3d31e3SAndroid Build Coastguard Worker  */
25*1a3d31e3SAndroid Build Coastguard Worker 
26*1a3d31e3SAndroid Build Coastguard Worker #include <errno.h>
27*1a3d31e3SAndroid Build Coastguard Worker #include <stdarg.h>
28*1a3d31e3SAndroid Build Coastguard Worker #include <stdio.h>
29*1a3d31e3SAndroid Build Coastguard Worker #include <stdlib.h>
30*1a3d31e3SAndroid Build Coastguard Worker #include <string.h>
31*1a3d31e3SAndroid Build Coastguard Worker #include <fcntl.h>
32*1a3d31e3SAndroid Build Coastguard Worker #include <getopt.h>
33*1a3d31e3SAndroid Build Coastguard Worker #include <sched.h>
34*1a3d31e3SAndroid Build Coastguard Worker #include <unistd.h>
35*1a3d31e3SAndroid Build Coastguard Worker #include <poll.h>
36*1a3d31e3SAndroid Build Coastguard Worker #include <signal.h>
37*1a3d31e3SAndroid Build Coastguard Worker #include <pthread.h>
38*1a3d31e3SAndroid Build Coastguard Worker #include <locale.h>
39*1a3d31e3SAndroid Build Coastguard Worker #include <sys/ioctl.h>
40*1a3d31e3SAndroid Build Coastguard Worker #include <sys/types.h>
41*1a3d31e3SAndroid Build Coastguard Worker #include <sys/stat.h>
42*1a3d31e3SAndroid Build Coastguard Worker #include <sys/vfs.h>
43*1a3d31e3SAndroid Build Coastguard Worker #include <sys/mman.h>
44*1a3d31e3SAndroid Build Coastguard Worker #include <sys/param.h>
45*1a3d31e3SAndroid Build Coastguard Worker #include <sys/time.h>
46*1a3d31e3SAndroid Build Coastguard Worker #include <sys/resource.h>
47*1a3d31e3SAndroid Build Coastguard Worker #include <sys/socket.h>
48*1a3d31e3SAndroid Build Coastguard Worker #include <netinet/in.h>
49*1a3d31e3SAndroid Build Coastguard Worker #include <arpa/inet.h>
50*1a3d31e3SAndroid Build Coastguard Worker #include <netdb.h>
51*1a3d31e3SAndroid Build Coastguard Worker #include <sys/sendfile.h>
52*1a3d31e3SAndroid Build Coastguard Worker 
53*1a3d31e3SAndroid Build Coastguard Worker #include "btt/list.h"
54*1a3d31e3SAndroid Build Coastguard Worker #include "blktrace.h"
55*1a3d31e3SAndroid Build Coastguard Worker 
56*1a3d31e3SAndroid Build Coastguard Worker /*
57*1a3d31e3SAndroid Build Coastguard Worker  * You may want to increase this even more, if you are logging at a high
58*1a3d31e3SAndroid Build Coastguard Worker  * rate and see skipped/missed events
59*1a3d31e3SAndroid Build Coastguard Worker  */
60*1a3d31e3SAndroid Build Coastguard Worker #define BUF_SIZE		(512 * 1024)
61*1a3d31e3SAndroid Build Coastguard Worker #define BUF_NR			(4)
62*1a3d31e3SAndroid Build Coastguard Worker 
63*1a3d31e3SAndroid Build Coastguard Worker #define FILE_VBUF_SIZE		(128 * 1024)
64*1a3d31e3SAndroid Build Coastguard Worker 
65*1a3d31e3SAndroid Build Coastguard Worker #define DEBUGFS_TYPE		(0x64626720)
66*1a3d31e3SAndroid Build Coastguard Worker #define TRACE_NET_PORT		(8462)
67*1a3d31e3SAndroid Build Coastguard Worker 
68*1a3d31e3SAndroid Build Coastguard Worker enum {
69*1a3d31e3SAndroid Build Coastguard Worker 	Net_none = 0,
70*1a3d31e3SAndroid Build Coastguard Worker 	Net_server,
71*1a3d31e3SAndroid Build Coastguard Worker 	Net_client,
72*1a3d31e3SAndroid Build Coastguard Worker };
73*1a3d31e3SAndroid Build Coastguard Worker 
74*1a3d31e3SAndroid Build Coastguard Worker enum thread_status {
75*1a3d31e3SAndroid Build Coastguard Worker 	Th_running,
76*1a3d31e3SAndroid Build Coastguard Worker 	Th_leaving,
77*1a3d31e3SAndroid Build Coastguard Worker 	Th_error
78*1a3d31e3SAndroid Build Coastguard Worker };
79*1a3d31e3SAndroid Build Coastguard Worker 
80*1a3d31e3SAndroid Build Coastguard Worker /*
81*1a3d31e3SAndroid Build Coastguard Worker  * Generic stats collected: nevents can be _roughly_ estimated by data_read
82*1a3d31e3SAndroid Build Coastguard Worker  * (discounting pdu...)
83*1a3d31e3SAndroid Build Coastguard Worker  *
84*1a3d31e3SAndroid Build Coastguard Worker  * These fields are updated w/ pdc_dr_update & pdc_nev_update below.
85*1a3d31e3SAndroid Build Coastguard Worker  */
86*1a3d31e3SAndroid Build Coastguard Worker struct pdc_stats {
87*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long long data_read;
88*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long long nevents;
89*1a3d31e3SAndroid Build Coastguard Worker };
90*1a3d31e3SAndroid Build Coastguard Worker 
91*1a3d31e3SAndroid Build Coastguard Worker struct devpath {
92*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head head;
93*1a3d31e3SAndroid Build Coastguard Worker 	char *path;			/* path to device special file */
94*1a3d31e3SAndroid Build Coastguard Worker 	char *buts_name;		/* name returned from bt kernel code */
95*1a3d31e3SAndroid Build Coastguard Worker 	struct pdc_stats *stats;
96*1a3d31e3SAndroid Build Coastguard Worker 	int fd, ncpus;
97*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long long drops;
98*1a3d31e3SAndroid Build Coastguard Worker 
99*1a3d31e3SAndroid Build Coastguard Worker 	/*
100*1a3d31e3SAndroid Build Coastguard Worker 	 * For piped output only:
101*1a3d31e3SAndroid Build Coastguard Worker 	 *
102*1a3d31e3SAndroid Build Coastguard Worker 	 * Each tracer will have a tracer_devpath_head that it will add new
103*1a3d31e3SAndroid Build Coastguard Worker 	 * data onto. It's list is protected above (tracer_devpath_head.mutex)
104*1a3d31e3SAndroid Build Coastguard Worker 	 * and it will signal the processing thread using the dp_cond,
105*1a3d31e3SAndroid Build Coastguard Worker 	 * dp_mutex & dp_entries variables above.
106*1a3d31e3SAndroid Build Coastguard Worker 	 */
107*1a3d31e3SAndroid Build Coastguard Worker 	struct tracer_devpath_head *heads;
108*1a3d31e3SAndroid Build Coastguard Worker 
109*1a3d31e3SAndroid Build Coastguard Worker 	/*
110*1a3d31e3SAndroid Build Coastguard Worker 	 * For network server mode only:
111*1a3d31e3SAndroid Build Coastguard Worker 	 */
112*1a3d31e3SAndroid Build Coastguard Worker 	struct cl_host *ch;
113*1a3d31e3SAndroid Build Coastguard Worker 	u32 cl_id;
114*1a3d31e3SAndroid Build Coastguard Worker 	time_t cl_connect_time;
115*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *ios;
116*1a3d31e3SAndroid Build Coastguard Worker };
117*1a3d31e3SAndroid Build Coastguard Worker 
118*1a3d31e3SAndroid Build Coastguard Worker /*
119*1a3d31e3SAndroid Build Coastguard Worker  * For piped output to stdout we will have each tracer thread (one per dev)
120*1a3d31e3SAndroid Build Coastguard Worker  * tack buffers read from the relay queues on a per-device list.
121*1a3d31e3SAndroid Build Coastguard Worker  *
122*1a3d31e3SAndroid Build Coastguard Worker  * The main thread will then collect trace buffers from each of lists in turn.
123*1a3d31e3SAndroid Build Coastguard Worker  *
124*1a3d31e3SAndroid Build Coastguard Worker  * We will use a mutex to guard each of the trace_buf list. The tracers
125*1a3d31e3SAndroid Build Coastguard Worker  * can then signal the main thread using <dp_cond,dp_mutex> and
126*1a3d31e3SAndroid Build Coastguard Worker  * dp_entries. (When dp_entries is 0, and a tracer adds an entry it will
127*1a3d31e3SAndroid Build Coastguard Worker  * signal. When dp_entries is 0, the main thread will wait for that condition
128*1a3d31e3SAndroid Build Coastguard Worker  * to be signalled.)
129*1a3d31e3SAndroid Build Coastguard Worker  *
130*1a3d31e3SAndroid Build Coastguard Worker  * adb: It may be better just to have a large buffer per tracer per dev,
131*1a3d31e3SAndroid Build Coastguard Worker  * and then use it as a ring-buffer. This would certainly cut down a lot
132*1a3d31e3SAndroid Build Coastguard Worker  * of malloc/free thrashing, at the cost of more memory movements (potentially).
133*1a3d31e3SAndroid Build Coastguard Worker  */
134*1a3d31e3SAndroid Build Coastguard Worker struct trace_buf {
135*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head head;
136*1a3d31e3SAndroid Build Coastguard Worker 	struct devpath *dpp;
137*1a3d31e3SAndroid Build Coastguard Worker 	void *buf;
138*1a3d31e3SAndroid Build Coastguard Worker 	int cpu, len;
139*1a3d31e3SAndroid Build Coastguard Worker };
140*1a3d31e3SAndroid Build Coastguard Worker 
141*1a3d31e3SAndroid Build Coastguard Worker struct tracer_devpath_head {
142*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_t mutex;
143*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head head;
144*1a3d31e3SAndroid Build Coastguard Worker 	struct trace_buf *prev;
145*1a3d31e3SAndroid Build Coastguard Worker };
146*1a3d31e3SAndroid Build Coastguard Worker 
147*1a3d31e3SAndroid Build Coastguard Worker /*
148*1a3d31e3SAndroid Build Coastguard Worker  * Used to handle the mmap() interfaces for output file (containing traces)
149*1a3d31e3SAndroid Build Coastguard Worker  */
150*1a3d31e3SAndroid Build Coastguard Worker struct mmap_info {
151*1a3d31e3SAndroid Build Coastguard Worker 	void *fs_buf;
152*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long long fs_size, fs_max_size, fs_off, fs_buf_len;
153*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long buf_size, buf_nr;
154*1a3d31e3SAndroid Build Coastguard Worker 	int pagesize;
155*1a3d31e3SAndroid Build Coastguard Worker };
156*1a3d31e3SAndroid Build Coastguard Worker 
157*1a3d31e3SAndroid Build Coastguard Worker /*
158*1a3d31e3SAndroid Build Coastguard Worker  * Each thread doing work on a (client) side of blktrace will have one
159*1a3d31e3SAndroid Build Coastguard Worker  * of these. The ios array contains input/output information, pfds holds
160*1a3d31e3SAndroid Build Coastguard Worker  * poll() data. The volatile's provide flags to/from the main executing
161*1a3d31e3SAndroid Build Coastguard Worker  * thread.
162*1a3d31e3SAndroid Build Coastguard Worker  */
163*1a3d31e3SAndroid Build Coastguard Worker struct tracer {
164*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head head;
165*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *ios;
166*1a3d31e3SAndroid Build Coastguard Worker 	struct pollfd *pfds;
167*1a3d31e3SAndroid Build Coastguard Worker 	pthread_t thread;
168*1a3d31e3SAndroid Build Coastguard Worker 	int cpu, nios;
169*1a3d31e3SAndroid Build Coastguard Worker 	volatile int status, is_done;
170*1a3d31e3SAndroid Build Coastguard Worker };
171*1a3d31e3SAndroid Build Coastguard Worker 
172*1a3d31e3SAndroid Build Coastguard Worker /*
173*1a3d31e3SAndroid Build Coastguard Worker  * networking stuff follows. we include a magic number so we know whether
174*1a3d31e3SAndroid Build Coastguard Worker  * to endianness convert or not.
175*1a3d31e3SAndroid Build Coastguard Worker  *
176*1a3d31e3SAndroid Build Coastguard Worker  * The len field is overloaded:
177*1a3d31e3SAndroid Build Coastguard Worker  *	0 - Indicates an "open" - allowing the server to set up for a dev/cpu
178*1a3d31e3SAndroid Build Coastguard Worker  *	1 - Indicates a "close" - Shut down connection orderly
179*1a3d31e3SAndroid Build Coastguard Worker  *
180*1a3d31e3SAndroid Build Coastguard Worker  * The cpu field is overloaded on close: it will contain the number of drops.
181*1a3d31e3SAndroid Build Coastguard Worker  */
182*1a3d31e3SAndroid Build Coastguard Worker struct blktrace_net_hdr {
183*1a3d31e3SAndroid Build Coastguard Worker 	u32 magic;		/* same as trace magic */
184*1a3d31e3SAndroid Build Coastguard Worker 	char buts_name[32];	/* trace name */
185*1a3d31e3SAndroid Build Coastguard Worker 	u32 cpu;		/* for which cpu */
186*1a3d31e3SAndroid Build Coastguard Worker 	u32 max_cpus;
187*1a3d31e3SAndroid Build Coastguard Worker 	u32 len;		/* length of following trace data */
188*1a3d31e3SAndroid Build Coastguard Worker 	u32 cl_id;		/* id for set of client per-cpu connections */
189*1a3d31e3SAndroid Build Coastguard Worker 	u32 buf_size;		/* client buf_size for this trace  */
190*1a3d31e3SAndroid Build Coastguard Worker 	u32 buf_nr;		/* client buf_nr for this trace  */
191*1a3d31e3SAndroid Build Coastguard Worker 	u32 page_size;		/* client page_size for this trace  */
192*1a3d31e3SAndroid Build Coastguard Worker };
193*1a3d31e3SAndroid Build Coastguard Worker 
194*1a3d31e3SAndroid Build Coastguard Worker /*
195*1a3d31e3SAndroid Build Coastguard Worker  * Each host encountered has one of these. The head is used to link this
196*1a3d31e3SAndroid Build Coastguard Worker  * on to the network server's ch_list. Connections associated with this
197*1a3d31e3SAndroid Build Coastguard Worker  * host are linked on conn_list, and any devices traced on that host
198*1a3d31e3SAndroid Build Coastguard Worker  * are connected on the devpaths list.
199*1a3d31e3SAndroid Build Coastguard Worker  */
200*1a3d31e3SAndroid Build Coastguard Worker struct cl_host {
201*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head head;
202*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head conn_list;
203*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head devpaths;
204*1a3d31e3SAndroid Build Coastguard Worker 	struct net_server_s *ns;
205*1a3d31e3SAndroid Build Coastguard Worker 	char *hostname;
206*1a3d31e3SAndroid Build Coastguard Worker 	struct in_addr cl_in_addr;
207*1a3d31e3SAndroid Build Coastguard Worker 	int connects, ndevs, cl_opens;
208*1a3d31e3SAndroid Build Coastguard Worker };
209*1a3d31e3SAndroid Build Coastguard Worker 
210*1a3d31e3SAndroid Build Coastguard Worker /*
211*1a3d31e3SAndroid Build Coastguard Worker  * Each connection (client to server socket ('fd')) has one of these. A
212*1a3d31e3SAndroid Build Coastguard Worker  * back reference to the host ('ch'), and lists headers (for the host
213*1a3d31e3SAndroid Build Coastguard Worker  * list, and the network server conn_list) are also included.
214*1a3d31e3SAndroid Build Coastguard Worker  */
215*1a3d31e3SAndroid Build Coastguard Worker struct cl_conn {
216*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head ch_head, ns_head;
217*1a3d31e3SAndroid Build Coastguard Worker 	struct cl_host *ch;
218*1a3d31e3SAndroid Build Coastguard Worker 	int fd, ncpus;
219*1a3d31e3SAndroid Build Coastguard Worker 	time_t connect_time;
220*1a3d31e3SAndroid Build Coastguard Worker };
221*1a3d31e3SAndroid Build Coastguard Worker 
222*1a3d31e3SAndroid Build Coastguard Worker /*
223*1a3d31e3SAndroid Build Coastguard Worker  * The network server requires some poll structures to be maintained -
224*1a3d31e3SAndroid Build Coastguard Worker  * one per conection currently on conn_list. The nchs/ch_list values
225*1a3d31e3SAndroid Build Coastguard Worker  * are for each host connected to this server. The addr field is used
226*1a3d31e3SAndroid Build Coastguard Worker  * for scratch as new connections are established.
227*1a3d31e3SAndroid Build Coastguard Worker  */
228*1a3d31e3SAndroid Build Coastguard Worker struct net_server_s {
229*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head conn_list;
230*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head ch_list;
231*1a3d31e3SAndroid Build Coastguard Worker 	struct pollfd *pfds;
232*1a3d31e3SAndroid Build Coastguard Worker 	int listen_fd, connects, nchs;
233*1a3d31e3SAndroid Build Coastguard Worker 	struct sockaddr_in addr;
234*1a3d31e3SAndroid Build Coastguard Worker };
235*1a3d31e3SAndroid Build Coastguard Worker 
236*1a3d31e3SAndroid Build Coastguard Worker /*
237*1a3d31e3SAndroid Build Coastguard Worker  * This structure is (generically) used to providide information
238*1a3d31e3SAndroid Build Coastguard Worker  * for a read-to-write set of values.
239*1a3d31e3SAndroid Build Coastguard Worker  *
240*1a3d31e3SAndroid Build Coastguard Worker  * ifn & ifd represent input information
241*1a3d31e3SAndroid Build Coastguard Worker  *
242*1a3d31e3SAndroid Build Coastguard Worker  * ofn, ofd, ofp, obuf & mmap_info are used for output file (optionally).
243*1a3d31e3SAndroid Build Coastguard Worker  */
244*1a3d31e3SAndroid Build Coastguard Worker struct io_info {
245*1a3d31e3SAndroid Build Coastguard Worker 	struct devpath *dpp;
246*1a3d31e3SAndroid Build Coastguard Worker 	FILE *ofp;
247*1a3d31e3SAndroid Build Coastguard Worker 	char *obuf;
248*1a3d31e3SAndroid Build Coastguard Worker 	struct cl_conn *nc;	/* Server network connection */
249*1a3d31e3SAndroid Build Coastguard Worker 
250*1a3d31e3SAndroid Build Coastguard Worker 	/*
251*1a3d31e3SAndroid Build Coastguard Worker 	 * mmap controlled output files
252*1a3d31e3SAndroid Build Coastguard Worker 	 */
253*1a3d31e3SAndroid Build Coastguard Worker 	struct mmap_info mmap_info;
254*1a3d31e3SAndroid Build Coastguard Worker 
255*1a3d31e3SAndroid Build Coastguard Worker 	/*
256*1a3d31e3SAndroid Build Coastguard Worker 	 * Client network fields
257*1a3d31e3SAndroid Build Coastguard Worker 	 */
258*1a3d31e3SAndroid Build Coastguard Worker 	unsigned int ready;
259*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long long data_queued;
260*1a3d31e3SAndroid Build Coastguard Worker 
261*1a3d31e3SAndroid Build Coastguard Worker 	/*
262*1a3d31e3SAndroid Build Coastguard Worker 	 * Input/output file descriptors & names
263*1a3d31e3SAndroid Build Coastguard Worker 	 */
264*1a3d31e3SAndroid Build Coastguard Worker 	int ifd, ofd;
265*1a3d31e3SAndroid Build Coastguard Worker 	char ifn[MAXPATHLEN + 64];
266*1a3d31e3SAndroid Build Coastguard Worker 	char ofn[MAXPATHLEN + 64];
267*1a3d31e3SAndroid Build Coastguard Worker };
268*1a3d31e3SAndroid Build Coastguard Worker 
269*1a3d31e3SAndroid Build Coastguard Worker static char blktrace_version[] = "2.0.0";
270*1a3d31e3SAndroid Build Coastguard Worker 
271*1a3d31e3SAndroid Build Coastguard Worker /*
272*1a3d31e3SAndroid Build Coastguard Worker  * Linkage to blktrace helper routines (trace conversions)
273*1a3d31e3SAndroid Build Coastguard Worker  */
274*1a3d31e3SAndroid Build Coastguard Worker int data_is_native = -1;
275*1a3d31e3SAndroid Build Coastguard Worker 
276*1a3d31e3SAndroid Build Coastguard Worker static int ndevs;
277*1a3d31e3SAndroid Build Coastguard Worker static int max_cpus;
278*1a3d31e3SAndroid Build Coastguard Worker static int ncpus;
279*1a3d31e3SAndroid Build Coastguard Worker static cpu_set_t *online_cpus;
280*1a3d31e3SAndroid Build Coastguard Worker static int pagesize;
281*1a3d31e3SAndroid Build Coastguard Worker static int act_mask = ~0U;
282*1a3d31e3SAndroid Build Coastguard Worker static int kill_running_trace;
283*1a3d31e3SAndroid Build Coastguard Worker static int stop_watch;
284*1a3d31e3SAndroid Build Coastguard Worker static int piped_output;
285*1a3d31e3SAndroid Build Coastguard Worker 
286*1a3d31e3SAndroid Build Coastguard Worker static char *debugfs_path = "/sys/kernel/debug";
287*1a3d31e3SAndroid Build Coastguard Worker static char *output_name;
288*1a3d31e3SAndroid Build Coastguard Worker static char *output_dir;
289*1a3d31e3SAndroid Build Coastguard Worker 
290*1a3d31e3SAndroid Build Coastguard Worker static unsigned long buf_size = BUF_SIZE;
291*1a3d31e3SAndroid Build Coastguard Worker static unsigned long buf_nr = BUF_NR;
292*1a3d31e3SAndroid Build Coastguard Worker 
293*1a3d31e3SAndroid Build Coastguard Worker static FILE *pfp;
294*1a3d31e3SAndroid Build Coastguard Worker 
295*1a3d31e3SAndroid Build Coastguard Worker static LIST_HEAD(devpaths);
296*1a3d31e3SAndroid Build Coastguard Worker static LIST_HEAD(tracers);
297*1a3d31e3SAndroid Build Coastguard Worker 
298*1a3d31e3SAndroid Build Coastguard Worker static volatile int done;
299*1a3d31e3SAndroid Build Coastguard Worker 
300*1a3d31e3SAndroid Build Coastguard Worker /*
301*1a3d31e3SAndroid Build Coastguard Worker  * tracer threads add entries, the main thread takes them off and processes
302*1a3d31e3SAndroid Build Coastguard Worker  * them. These protect the dp_entries variable.
303*1a3d31e3SAndroid Build Coastguard Worker  */
304*1a3d31e3SAndroid Build Coastguard Worker static pthread_cond_t dp_cond = PTHREAD_COND_INITIALIZER;
305*1a3d31e3SAndroid Build Coastguard Worker static pthread_mutex_t dp_mutex = PTHREAD_MUTEX_INITIALIZER;
306*1a3d31e3SAndroid Build Coastguard Worker static volatile int dp_entries;
307*1a3d31e3SAndroid Build Coastguard Worker 
308*1a3d31e3SAndroid Build Coastguard Worker /*
309*1a3d31e3SAndroid Build Coastguard Worker  * These synchronize master / thread interactions.
310*1a3d31e3SAndroid Build Coastguard Worker  */
311*1a3d31e3SAndroid Build Coastguard Worker static pthread_cond_t mt_cond = PTHREAD_COND_INITIALIZER;
312*1a3d31e3SAndroid Build Coastguard Worker static pthread_mutex_t mt_mutex = PTHREAD_MUTEX_INITIALIZER;
313*1a3d31e3SAndroid Build Coastguard Worker static volatile int nthreads_running;
314*1a3d31e3SAndroid Build Coastguard Worker static volatile int nthreads_leaving;
315*1a3d31e3SAndroid Build Coastguard Worker static volatile int nthreads_error;
316*1a3d31e3SAndroid Build Coastguard Worker static volatile int tracers_run;
317*1a3d31e3SAndroid Build Coastguard Worker 
318*1a3d31e3SAndroid Build Coastguard Worker /*
319*1a3d31e3SAndroid Build Coastguard Worker  * network cmd line params
320*1a3d31e3SAndroid Build Coastguard Worker  */
321*1a3d31e3SAndroid Build Coastguard Worker static struct sockaddr_in hostname_addr;
322*1a3d31e3SAndroid Build Coastguard Worker static char hostname[MAXHOSTNAMELEN];
323*1a3d31e3SAndroid Build Coastguard Worker static int net_port = TRACE_NET_PORT;
324*1a3d31e3SAndroid Build Coastguard Worker static int net_use_sendfile = 1;
325*1a3d31e3SAndroid Build Coastguard Worker static int net_mode;
326*1a3d31e3SAndroid Build Coastguard Worker static int *cl_fds;
327*1a3d31e3SAndroid Build Coastguard Worker 
328*1a3d31e3SAndroid Build Coastguard Worker static int (*handle_pfds)(struct tracer *, int, int);
329*1a3d31e3SAndroid Build Coastguard Worker static int (*handle_list)(struct tracer_devpath_head *, struct list_head *);
330*1a3d31e3SAndroid Build Coastguard Worker 
331*1a3d31e3SAndroid Build Coastguard Worker #define S_OPTS	"d:a:A:r:o:kw:vVb:n:D:lh:p:sI:"
332*1a3d31e3SAndroid Build Coastguard Worker static struct option l_opts[] = {
333*1a3d31e3SAndroid Build Coastguard Worker 	{
334*1a3d31e3SAndroid Build Coastguard Worker 		.name = "dev",
335*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
336*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
337*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'd'
338*1a3d31e3SAndroid Build Coastguard Worker 	},
339*1a3d31e3SAndroid Build Coastguard Worker 	{
340*1a3d31e3SAndroid Build Coastguard Worker 		.name = "input-devs",
341*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
342*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
343*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'I'
344*1a3d31e3SAndroid Build Coastguard Worker 	},
345*1a3d31e3SAndroid Build Coastguard Worker 	{
346*1a3d31e3SAndroid Build Coastguard Worker 		.name = "act-mask",
347*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
348*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
349*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'a'
350*1a3d31e3SAndroid Build Coastguard Worker 	},
351*1a3d31e3SAndroid Build Coastguard Worker 	{
352*1a3d31e3SAndroid Build Coastguard Worker 		.name = "set-mask",
353*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
354*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
355*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'A'
356*1a3d31e3SAndroid Build Coastguard Worker 	},
357*1a3d31e3SAndroid Build Coastguard Worker 	{
358*1a3d31e3SAndroid Build Coastguard Worker 		.name = "relay",
359*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
360*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
361*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'r'
362*1a3d31e3SAndroid Build Coastguard Worker 	},
363*1a3d31e3SAndroid Build Coastguard Worker 	{
364*1a3d31e3SAndroid Build Coastguard Worker 		.name = "output",
365*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
366*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
367*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'o'
368*1a3d31e3SAndroid Build Coastguard Worker 	},
369*1a3d31e3SAndroid Build Coastguard Worker 	{
370*1a3d31e3SAndroid Build Coastguard Worker 		.name = "kill",
371*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = no_argument,
372*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
373*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'k'
374*1a3d31e3SAndroid Build Coastguard Worker 	},
375*1a3d31e3SAndroid Build Coastguard Worker 	{
376*1a3d31e3SAndroid Build Coastguard Worker 		.name = "stopwatch",
377*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
378*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
379*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'w'
380*1a3d31e3SAndroid Build Coastguard Worker 	},
381*1a3d31e3SAndroid Build Coastguard Worker 	{
382*1a3d31e3SAndroid Build Coastguard Worker 		.name = "version",
383*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = no_argument,
384*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
385*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'v'
386*1a3d31e3SAndroid Build Coastguard Worker 	},
387*1a3d31e3SAndroid Build Coastguard Worker 	{
388*1a3d31e3SAndroid Build Coastguard Worker 		.name = "version",
389*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = no_argument,
390*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
391*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'V'
392*1a3d31e3SAndroid Build Coastguard Worker 	},
393*1a3d31e3SAndroid Build Coastguard Worker 	{
394*1a3d31e3SAndroid Build Coastguard Worker 		.name = "buffer-size",
395*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
396*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
397*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'b'
398*1a3d31e3SAndroid Build Coastguard Worker 	},
399*1a3d31e3SAndroid Build Coastguard Worker 	{
400*1a3d31e3SAndroid Build Coastguard Worker 		.name = "num-sub-buffers",
401*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
402*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
403*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'n'
404*1a3d31e3SAndroid Build Coastguard Worker 	},
405*1a3d31e3SAndroid Build Coastguard Worker 	{
406*1a3d31e3SAndroid Build Coastguard Worker 		.name = "output-dir",
407*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
408*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
409*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'D'
410*1a3d31e3SAndroid Build Coastguard Worker 	},
411*1a3d31e3SAndroid Build Coastguard Worker 	{
412*1a3d31e3SAndroid Build Coastguard Worker 		.name = "listen",
413*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = no_argument,
414*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
415*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'l'
416*1a3d31e3SAndroid Build Coastguard Worker 	},
417*1a3d31e3SAndroid Build Coastguard Worker 	{
418*1a3d31e3SAndroid Build Coastguard Worker 		.name = "host",
419*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
420*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
421*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'h'
422*1a3d31e3SAndroid Build Coastguard Worker 	},
423*1a3d31e3SAndroid Build Coastguard Worker 	{
424*1a3d31e3SAndroid Build Coastguard Worker 		.name = "port",
425*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = required_argument,
426*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
427*1a3d31e3SAndroid Build Coastguard Worker 		.val = 'p'
428*1a3d31e3SAndroid Build Coastguard Worker 	},
429*1a3d31e3SAndroid Build Coastguard Worker 	{
430*1a3d31e3SAndroid Build Coastguard Worker 		.name = "no-sendfile",
431*1a3d31e3SAndroid Build Coastguard Worker 		.has_arg = no_argument,
432*1a3d31e3SAndroid Build Coastguard Worker 		.flag = NULL,
433*1a3d31e3SAndroid Build Coastguard Worker 		.val = 's'
434*1a3d31e3SAndroid Build Coastguard Worker 	},
435*1a3d31e3SAndroid Build Coastguard Worker 	{
436*1a3d31e3SAndroid Build Coastguard Worker 		.name = NULL,
437*1a3d31e3SAndroid Build Coastguard Worker 	}
438*1a3d31e3SAndroid Build Coastguard Worker };
439*1a3d31e3SAndroid Build Coastguard Worker 
440*1a3d31e3SAndroid Build Coastguard Worker static char usage_str[] = "\n\n" \
441*1a3d31e3SAndroid Build Coastguard Worker 	"-d <dev>             | --dev=<dev>\n" \
442*1a3d31e3SAndroid Build Coastguard Worker         "[ -r <debugfs path>  | --relay=<debugfs path> ]\n" \
443*1a3d31e3SAndroid Build Coastguard Worker         "[ -o <file>          | --output=<file>]\n" \
444*1a3d31e3SAndroid Build Coastguard Worker         "[ -D <dir>           | --output-dir=<dir>\n" \
445*1a3d31e3SAndroid Build Coastguard Worker         "[ -w <time>          | --stopwatch=<time>]\n" \
446*1a3d31e3SAndroid Build Coastguard Worker         "[ -a <action field>  | --act-mask=<action field>]\n" \
447*1a3d31e3SAndroid Build Coastguard Worker         "[ -A <action mask>   | --set-mask=<action mask>]\n" \
448*1a3d31e3SAndroid Build Coastguard Worker         "[ -b <size>          | --buffer-size]\n" \
449*1a3d31e3SAndroid Build Coastguard Worker         "[ -n <number>        | --num-sub-buffers=<number>]\n" \
450*1a3d31e3SAndroid Build Coastguard Worker         "[ -l                 | --listen]\n" \
451*1a3d31e3SAndroid Build Coastguard Worker         "[ -h <hostname>      | --host=<hostname>]\n" \
452*1a3d31e3SAndroid Build Coastguard Worker         "[ -p <port number>   | --port=<port number>]\n" \
453*1a3d31e3SAndroid Build Coastguard Worker         "[ -s                 | --no-sendfile]\n" \
454*1a3d31e3SAndroid Build Coastguard Worker         "[ -I <devs file>     | --input-devs=<devs file>]\n" \
455*1a3d31e3SAndroid Build Coastguard Worker         "[ -v <version>       | --version]\n" \
456*1a3d31e3SAndroid Build Coastguard Worker         "[ -V <version>       | --version]\n" \
457*1a3d31e3SAndroid Build Coastguard Worker 
458*1a3d31e3SAndroid Build Coastguard Worker 	"\t-d Use specified device. May also be given last after options\n" \
459*1a3d31e3SAndroid Build Coastguard Worker 	"\t-r Path to mounted debugfs, defaults to /sys/kernel/debug\n" \
460*1a3d31e3SAndroid Build Coastguard Worker 	"\t-o File(s) to send output to\n" \
461*1a3d31e3SAndroid Build Coastguard Worker 	"\t-D Directory to prepend to output file names\n" \
462*1a3d31e3SAndroid Build Coastguard Worker 	"\t-w Stop after defined time, in seconds\n" \
463*1a3d31e3SAndroid Build Coastguard Worker 	"\t-a Only trace specified actions. See documentation\n" \
464*1a3d31e3SAndroid Build Coastguard Worker 	"\t-A Give trace mask as a single value. See documentation\n" \
465*1a3d31e3SAndroid Build Coastguard Worker 	"\t-b Sub buffer size in KiB (default 512)\n" \
466*1a3d31e3SAndroid Build Coastguard Worker 	"\t-n Number of sub buffers (default 4)\n" \
467*1a3d31e3SAndroid Build Coastguard Worker 	"\t-l Run in network listen mode (blktrace server)\n" \
468*1a3d31e3SAndroid Build Coastguard Worker 	"\t-h Run in network client mode, connecting to the given host\n" \
469*1a3d31e3SAndroid Build Coastguard Worker 	"\t-p Network port to use (default 8462)\n" \
470*1a3d31e3SAndroid Build Coastguard Worker 	"\t-s Make the network client NOT use sendfile() to transfer data\n" \
471*1a3d31e3SAndroid Build Coastguard Worker 	"\t-I Add devices found in <devs file>\n" \
472*1a3d31e3SAndroid Build Coastguard Worker 	"\t-v Print program version info\n" \
473*1a3d31e3SAndroid Build Coastguard Worker 	"\t-V Print program version info\n\n";
474*1a3d31e3SAndroid Build Coastguard Worker 
clear_events(struct pollfd * pfd)475*1a3d31e3SAndroid Build Coastguard Worker static void clear_events(struct pollfd *pfd)
476*1a3d31e3SAndroid Build Coastguard Worker {
477*1a3d31e3SAndroid Build Coastguard Worker 	pfd->events = 0;
478*1a3d31e3SAndroid Build Coastguard Worker 	pfd->revents = 0;
479*1a3d31e3SAndroid Build Coastguard Worker }
480*1a3d31e3SAndroid Build Coastguard Worker 
net_client_use_sendfile(void)481*1a3d31e3SAndroid Build Coastguard Worker static inline int net_client_use_sendfile(void)
482*1a3d31e3SAndroid Build Coastguard Worker {
483*1a3d31e3SAndroid Build Coastguard Worker 	return net_mode == Net_client && net_use_sendfile;
484*1a3d31e3SAndroid Build Coastguard Worker }
485*1a3d31e3SAndroid Build Coastguard Worker 
net_client_use_send(void)486*1a3d31e3SAndroid Build Coastguard Worker static inline int net_client_use_send(void)
487*1a3d31e3SAndroid Build Coastguard Worker {
488*1a3d31e3SAndroid Build Coastguard Worker 	return net_mode == Net_client && !net_use_sendfile;
489*1a3d31e3SAndroid Build Coastguard Worker }
490*1a3d31e3SAndroid Build Coastguard Worker 
use_tracer_devpaths(void)491*1a3d31e3SAndroid Build Coastguard Worker static inline int use_tracer_devpaths(void)
492*1a3d31e3SAndroid Build Coastguard Worker {
493*1a3d31e3SAndroid Build Coastguard Worker 	return piped_output || net_client_use_send();
494*1a3d31e3SAndroid Build Coastguard Worker }
495*1a3d31e3SAndroid Build Coastguard Worker 
in_addr_eq(struct in_addr a,struct in_addr b)496*1a3d31e3SAndroid Build Coastguard Worker static inline int in_addr_eq(struct in_addr a, struct in_addr b)
497*1a3d31e3SAndroid Build Coastguard Worker {
498*1a3d31e3SAndroid Build Coastguard Worker 	return a.s_addr == b.s_addr;
499*1a3d31e3SAndroid Build Coastguard Worker }
500*1a3d31e3SAndroid Build Coastguard Worker 
pdc_dr_update(struct devpath * dpp,int cpu,int data_read)501*1a3d31e3SAndroid Build Coastguard Worker static inline void pdc_dr_update(struct devpath *dpp, int cpu, int data_read)
502*1a3d31e3SAndroid Build Coastguard Worker {
503*1a3d31e3SAndroid Build Coastguard Worker 	dpp->stats[cpu].data_read += data_read;
504*1a3d31e3SAndroid Build Coastguard Worker }
505*1a3d31e3SAndroid Build Coastguard Worker 
pdc_nev_update(struct devpath * dpp,int cpu,int nevents)506*1a3d31e3SAndroid Build Coastguard Worker static inline void pdc_nev_update(struct devpath *dpp, int cpu, int nevents)
507*1a3d31e3SAndroid Build Coastguard Worker {
508*1a3d31e3SAndroid Build Coastguard Worker 	dpp->stats[cpu].nevents += nevents;
509*1a3d31e3SAndroid Build Coastguard Worker }
510*1a3d31e3SAndroid Build Coastguard Worker 
show_usage(char * prog)511*1a3d31e3SAndroid Build Coastguard Worker static void show_usage(char *prog)
512*1a3d31e3SAndroid Build Coastguard Worker {
513*1a3d31e3SAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: %s %s", prog, usage_str);
514*1a3d31e3SAndroid Build Coastguard Worker }
515*1a3d31e3SAndroid Build Coastguard Worker 
516*1a3d31e3SAndroid Build Coastguard Worker /*
517*1a3d31e3SAndroid Build Coastguard Worker  * Create a timespec 'msec' milliseconds into the future
518*1a3d31e3SAndroid Build Coastguard Worker  */
make_timespec(struct timespec * tsp,long delta_msec)519*1a3d31e3SAndroid Build Coastguard Worker static inline void make_timespec(struct timespec *tsp, long delta_msec)
520*1a3d31e3SAndroid Build Coastguard Worker {
521*1a3d31e3SAndroid Build Coastguard Worker 	struct timeval now;
522*1a3d31e3SAndroid Build Coastguard Worker 
523*1a3d31e3SAndroid Build Coastguard Worker 	gettimeofday(&now, NULL);
524*1a3d31e3SAndroid Build Coastguard Worker 	tsp->tv_sec = now.tv_sec;
525*1a3d31e3SAndroid Build Coastguard Worker 	tsp->tv_nsec = 1000L * now.tv_usec;
526*1a3d31e3SAndroid Build Coastguard Worker 
527*1a3d31e3SAndroid Build Coastguard Worker 	tsp->tv_nsec += (delta_msec * 1000000L);
528*1a3d31e3SAndroid Build Coastguard Worker 	if (tsp->tv_nsec > 1000000000L) {
529*1a3d31e3SAndroid Build Coastguard Worker 		long secs = tsp->tv_nsec / 1000000000L;
530*1a3d31e3SAndroid Build Coastguard Worker 
531*1a3d31e3SAndroid Build Coastguard Worker 		tsp->tv_sec += secs;
532*1a3d31e3SAndroid Build Coastguard Worker 		tsp->tv_nsec -= (secs * 1000000000L);
533*1a3d31e3SAndroid Build Coastguard Worker 	}
534*1a3d31e3SAndroid Build Coastguard Worker }
535*1a3d31e3SAndroid Build Coastguard Worker 
536*1a3d31e3SAndroid Build Coastguard Worker /*
537*1a3d31e3SAndroid Build Coastguard Worker  * Add a timer to ensure wait ends
538*1a3d31e3SAndroid Build Coastguard Worker  */
t_pthread_cond_wait(pthread_cond_t * cond,pthread_mutex_t * mutex)539*1a3d31e3SAndroid Build Coastguard Worker static void t_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
540*1a3d31e3SAndroid Build Coastguard Worker {
541*1a3d31e3SAndroid Build Coastguard Worker 	struct timespec ts;
542*1a3d31e3SAndroid Build Coastguard Worker 
543*1a3d31e3SAndroid Build Coastguard Worker 	make_timespec(&ts, 50);
544*1a3d31e3SAndroid Build Coastguard Worker 	pthread_cond_timedwait(cond, mutex, &ts);
545*1a3d31e3SAndroid Build Coastguard Worker }
546*1a3d31e3SAndroid Build Coastguard Worker 
unblock_tracers(void)547*1a3d31e3SAndroid Build Coastguard Worker static void unblock_tracers(void)
548*1a3d31e3SAndroid Build Coastguard Worker {
549*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&mt_mutex);
550*1a3d31e3SAndroid Build Coastguard Worker 	tracers_run = 1;
551*1a3d31e3SAndroid Build Coastguard Worker 	pthread_cond_broadcast(&mt_cond);
552*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&mt_mutex);
553*1a3d31e3SAndroid Build Coastguard Worker }
554*1a3d31e3SAndroid Build Coastguard Worker 
tracer_wait_unblock(struct tracer * tp)555*1a3d31e3SAndroid Build Coastguard Worker static void tracer_wait_unblock(struct tracer *tp)
556*1a3d31e3SAndroid Build Coastguard Worker {
557*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&mt_mutex);
558*1a3d31e3SAndroid Build Coastguard Worker 	while (!tp->is_done && !tracers_run)
559*1a3d31e3SAndroid Build Coastguard Worker 		pthread_cond_wait(&mt_cond, &mt_mutex);
560*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&mt_mutex);
561*1a3d31e3SAndroid Build Coastguard Worker }
562*1a3d31e3SAndroid Build Coastguard Worker 
tracer_signal_ready(struct tracer * tp,enum thread_status th_status,int status)563*1a3d31e3SAndroid Build Coastguard Worker static void tracer_signal_ready(struct tracer *tp,
564*1a3d31e3SAndroid Build Coastguard Worker 				enum thread_status th_status,
565*1a3d31e3SAndroid Build Coastguard Worker 				int status)
566*1a3d31e3SAndroid Build Coastguard Worker {
567*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&mt_mutex);
568*1a3d31e3SAndroid Build Coastguard Worker 	tp->status = status;
569*1a3d31e3SAndroid Build Coastguard Worker 
570*1a3d31e3SAndroid Build Coastguard Worker 	if (th_status == Th_running)
571*1a3d31e3SAndroid Build Coastguard Worker 		nthreads_running++;
572*1a3d31e3SAndroid Build Coastguard Worker 	else if (th_status == Th_error)
573*1a3d31e3SAndroid Build Coastguard Worker 		nthreads_error++;
574*1a3d31e3SAndroid Build Coastguard Worker 	else
575*1a3d31e3SAndroid Build Coastguard Worker 		nthreads_leaving++;
576*1a3d31e3SAndroid Build Coastguard Worker 
577*1a3d31e3SAndroid Build Coastguard Worker 	pthread_cond_signal(&mt_cond);
578*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&mt_mutex);
579*1a3d31e3SAndroid Build Coastguard Worker }
580*1a3d31e3SAndroid Build Coastguard Worker 
wait_tracers_ready(int ncpus_started)581*1a3d31e3SAndroid Build Coastguard Worker static void wait_tracers_ready(int ncpus_started)
582*1a3d31e3SAndroid Build Coastguard Worker {
583*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&mt_mutex);
584*1a3d31e3SAndroid Build Coastguard Worker 	while ((nthreads_running + nthreads_error) < ncpus_started)
585*1a3d31e3SAndroid Build Coastguard Worker 		t_pthread_cond_wait(&mt_cond, &mt_mutex);
586*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&mt_mutex);
587*1a3d31e3SAndroid Build Coastguard Worker }
588*1a3d31e3SAndroid Build Coastguard Worker 
wait_tracers_leaving(void)589*1a3d31e3SAndroid Build Coastguard Worker static void wait_tracers_leaving(void)
590*1a3d31e3SAndroid Build Coastguard Worker {
591*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&mt_mutex);
592*1a3d31e3SAndroid Build Coastguard Worker 	while (nthreads_leaving < nthreads_running)
593*1a3d31e3SAndroid Build Coastguard Worker 		t_pthread_cond_wait(&mt_cond, &mt_mutex);
594*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&mt_mutex);
595*1a3d31e3SAndroid Build Coastguard Worker }
596*1a3d31e3SAndroid Build Coastguard Worker 
init_mmap_info(struct mmap_info * mip)597*1a3d31e3SAndroid Build Coastguard Worker static void init_mmap_info(struct mmap_info *mip)
598*1a3d31e3SAndroid Build Coastguard Worker {
599*1a3d31e3SAndroid Build Coastguard Worker 	mip->buf_size = buf_size;
600*1a3d31e3SAndroid Build Coastguard Worker 	mip->buf_nr = buf_nr;
601*1a3d31e3SAndroid Build Coastguard Worker 	mip->pagesize = pagesize;
602*1a3d31e3SAndroid Build Coastguard Worker }
603*1a3d31e3SAndroid Build Coastguard Worker 
net_close_connection(int * fd)604*1a3d31e3SAndroid Build Coastguard Worker static void net_close_connection(int *fd)
605*1a3d31e3SAndroid Build Coastguard Worker {
606*1a3d31e3SAndroid Build Coastguard Worker 	shutdown(*fd, SHUT_RDWR);
607*1a3d31e3SAndroid Build Coastguard Worker 	close(*fd);
608*1a3d31e3SAndroid Build Coastguard Worker 	*fd = -1;
609*1a3d31e3SAndroid Build Coastguard Worker }
610*1a3d31e3SAndroid Build Coastguard Worker 
dpp_free(struct devpath * dpp)611*1a3d31e3SAndroid Build Coastguard Worker static void dpp_free(struct devpath *dpp)
612*1a3d31e3SAndroid Build Coastguard Worker {
613*1a3d31e3SAndroid Build Coastguard Worker 	if (dpp->stats)
614*1a3d31e3SAndroid Build Coastguard Worker 		free(dpp->stats);
615*1a3d31e3SAndroid Build Coastguard Worker 	if (dpp->ios)
616*1a3d31e3SAndroid Build Coastguard Worker 		free(dpp->ios);
617*1a3d31e3SAndroid Build Coastguard Worker 	if (dpp->path)
618*1a3d31e3SAndroid Build Coastguard Worker 		free(dpp->path);
619*1a3d31e3SAndroid Build Coastguard Worker 	if (dpp->buts_name)
620*1a3d31e3SAndroid Build Coastguard Worker 		free(dpp->buts_name);
621*1a3d31e3SAndroid Build Coastguard Worker 	free(dpp);
622*1a3d31e3SAndroid Build Coastguard Worker }
623*1a3d31e3SAndroid Build Coastguard Worker 
lock_on_cpu(int cpu)624*1a3d31e3SAndroid Build Coastguard Worker static int lock_on_cpu(int cpu)
625*1a3d31e3SAndroid Build Coastguard Worker {
626*1a3d31e3SAndroid Build Coastguard Worker 	cpu_set_t * cpu_mask;
627*1a3d31e3SAndroid Build Coastguard Worker 	size_t size;
628*1a3d31e3SAndroid Build Coastguard Worker 
629*1a3d31e3SAndroid Build Coastguard Worker 	cpu_mask = CPU_ALLOC(max_cpus);
630*1a3d31e3SAndroid Build Coastguard Worker 	size = CPU_ALLOC_SIZE(max_cpus);
631*1a3d31e3SAndroid Build Coastguard Worker 
632*1a3d31e3SAndroid Build Coastguard Worker 	CPU_ZERO_S(size, cpu_mask);
633*1a3d31e3SAndroid Build Coastguard Worker 	CPU_SET_S(cpu, size, cpu_mask);
634*1a3d31e3SAndroid Build Coastguard Worker 	if (sched_setaffinity(0, size, cpu_mask) < 0) {
635*1a3d31e3SAndroid Build Coastguard Worker 		CPU_FREE(cpu_mask);
636*1a3d31e3SAndroid Build Coastguard Worker 		return errno;
637*1a3d31e3SAndroid Build Coastguard Worker 	}
638*1a3d31e3SAndroid Build Coastguard Worker 
639*1a3d31e3SAndroid Build Coastguard Worker 	CPU_FREE(cpu_mask);
640*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
641*1a3d31e3SAndroid Build Coastguard Worker }
642*1a3d31e3SAndroid Build Coastguard Worker 
increase_limit(int resource,rlim_t increase)643*1a3d31e3SAndroid Build Coastguard Worker static int increase_limit(int resource, rlim_t increase)
644*1a3d31e3SAndroid Build Coastguard Worker {
645*1a3d31e3SAndroid Build Coastguard Worker 	struct rlimit rlim;
646*1a3d31e3SAndroid Build Coastguard Worker 	int save_errno = errno;
647*1a3d31e3SAndroid Build Coastguard Worker 
648*1a3d31e3SAndroid Build Coastguard Worker 	if (!getrlimit(resource, &rlim)) {
649*1a3d31e3SAndroid Build Coastguard Worker 		rlim.rlim_cur += increase;
650*1a3d31e3SAndroid Build Coastguard Worker 		if (rlim.rlim_cur >= rlim.rlim_max)
651*1a3d31e3SAndroid Build Coastguard Worker 			rlim.rlim_max = rlim.rlim_cur + increase;
652*1a3d31e3SAndroid Build Coastguard Worker 
653*1a3d31e3SAndroid Build Coastguard Worker 		if (!setrlimit(resource, &rlim))
654*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
655*1a3d31e3SAndroid Build Coastguard Worker 	}
656*1a3d31e3SAndroid Build Coastguard Worker 
657*1a3d31e3SAndroid Build Coastguard Worker 	errno = save_errno;
658*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
659*1a3d31e3SAndroid Build Coastguard Worker }
660*1a3d31e3SAndroid Build Coastguard Worker 
handle_open_failure(void)661*1a3d31e3SAndroid Build Coastguard Worker static int handle_open_failure(void)
662*1a3d31e3SAndroid Build Coastguard Worker {
663*1a3d31e3SAndroid Build Coastguard Worker 	if (errno == ENFILE || errno == EMFILE)
664*1a3d31e3SAndroid Build Coastguard Worker 		return increase_limit(RLIMIT_NOFILE, 16);
665*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
666*1a3d31e3SAndroid Build Coastguard Worker }
667*1a3d31e3SAndroid Build Coastguard Worker 
handle_mem_failure(size_t length)668*1a3d31e3SAndroid Build Coastguard Worker static int handle_mem_failure(size_t length)
669*1a3d31e3SAndroid Build Coastguard Worker {
670*1a3d31e3SAndroid Build Coastguard Worker 	if (errno == ENFILE)
671*1a3d31e3SAndroid Build Coastguard Worker 		return handle_open_failure();
672*1a3d31e3SAndroid Build Coastguard Worker 	else if (errno == ENOMEM)
673*1a3d31e3SAndroid Build Coastguard Worker 		return increase_limit(RLIMIT_MEMLOCK, 2 * length);
674*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
675*1a3d31e3SAndroid Build Coastguard Worker }
676*1a3d31e3SAndroid Build Coastguard Worker 
my_fopen(const char * path,const char * mode)677*1a3d31e3SAndroid Build Coastguard Worker static FILE *my_fopen(const char *path, const char *mode)
678*1a3d31e3SAndroid Build Coastguard Worker {
679*1a3d31e3SAndroid Build Coastguard Worker 	FILE *fp;
680*1a3d31e3SAndroid Build Coastguard Worker 
681*1a3d31e3SAndroid Build Coastguard Worker 	do {
682*1a3d31e3SAndroid Build Coastguard Worker 		fp = fopen(path, mode);
683*1a3d31e3SAndroid Build Coastguard Worker 	} while (fp == NULL && handle_open_failure());
684*1a3d31e3SAndroid Build Coastguard Worker 
685*1a3d31e3SAndroid Build Coastguard Worker 	return fp;
686*1a3d31e3SAndroid Build Coastguard Worker }
687*1a3d31e3SAndroid Build Coastguard Worker 
my_open(const char * path,int flags)688*1a3d31e3SAndroid Build Coastguard Worker static int my_open(const char *path, int flags)
689*1a3d31e3SAndroid Build Coastguard Worker {
690*1a3d31e3SAndroid Build Coastguard Worker 	int fd;
691*1a3d31e3SAndroid Build Coastguard Worker 
692*1a3d31e3SAndroid Build Coastguard Worker 	do {
693*1a3d31e3SAndroid Build Coastguard Worker 		fd = open(path, flags);
694*1a3d31e3SAndroid Build Coastguard Worker 	} while (fd < 0 && handle_open_failure());
695*1a3d31e3SAndroid Build Coastguard Worker 
696*1a3d31e3SAndroid Build Coastguard Worker 	return fd;
697*1a3d31e3SAndroid Build Coastguard Worker }
698*1a3d31e3SAndroid Build Coastguard Worker 
my_socket(int domain,int type,int protocol)699*1a3d31e3SAndroid Build Coastguard Worker static int my_socket(int domain, int type, int protocol)
700*1a3d31e3SAndroid Build Coastguard Worker {
701*1a3d31e3SAndroid Build Coastguard Worker 	int fd;
702*1a3d31e3SAndroid Build Coastguard Worker 
703*1a3d31e3SAndroid Build Coastguard Worker 	do {
704*1a3d31e3SAndroid Build Coastguard Worker 		fd = socket(domain, type, protocol);
705*1a3d31e3SAndroid Build Coastguard Worker 	} while (fd < 0 && handle_open_failure());
706*1a3d31e3SAndroid Build Coastguard Worker 
707*1a3d31e3SAndroid Build Coastguard Worker 	return fd;
708*1a3d31e3SAndroid Build Coastguard Worker }
709*1a3d31e3SAndroid Build Coastguard Worker 
my_accept(int sockfd,struct sockaddr * addr,socklen_t * addrlen)710*1a3d31e3SAndroid Build Coastguard Worker static int my_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
711*1a3d31e3SAndroid Build Coastguard Worker {
712*1a3d31e3SAndroid Build Coastguard Worker 	int fd;
713*1a3d31e3SAndroid Build Coastguard Worker 
714*1a3d31e3SAndroid Build Coastguard Worker 	do {
715*1a3d31e3SAndroid Build Coastguard Worker 		fd = accept(sockfd, addr, addrlen);
716*1a3d31e3SAndroid Build Coastguard Worker 	} while (fd < 0 && handle_open_failure());
717*1a3d31e3SAndroid Build Coastguard Worker 
718*1a3d31e3SAndroid Build Coastguard Worker 	return fd;
719*1a3d31e3SAndroid Build Coastguard Worker }
720*1a3d31e3SAndroid Build Coastguard Worker 
my_mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offset)721*1a3d31e3SAndroid Build Coastguard Worker static void *my_mmap(void *addr, size_t length, int prot, int flags, int fd,
722*1a3d31e3SAndroid Build Coastguard Worker 		     off_t offset)
723*1a3d31e3SAndroid Build Coastguard Worker {
724*1a3d31e3SAndroid Build Coastguard Worker 	void *new;
725*1a3d31e3SAndroid Build Coastguard Worker 
726*1a3d31e3SAndroid Build Coastguard Worker 	do {
727*1a3d31e3SAndroid Build Coastguard Worker 		new = mmap(addr, length, prot, flags, fd, offset);
728*1a3d31e3SAndroid Build Coastguard Worker 	} while (new == MAP_FAILED && handle_mem_failure(length));
729*1a3d31e3SAndroid Build Coastguard Worker 
730*1a3d31e3SAndroid Build Coastguard Worker 	return new;
731*1a3d31e3SAndroid Build Coastguard Worker }
732*1a3d31e3SAndroid Build Coastguard Worker 
my_mlock(struct tracer * tp,const void * addr,size_t len)733*1a3d31e3SAndroid Build Coastguard Worker static int my_mlock(struct tracer *tp,
734*1a3d31e3SAndroid Build Coastguard Worker 		    const void *addr, size_t len)
735*1a3d31e3SAndroid Build Coastguard Worker {
736*1a3d31e3SAndroid Build Coastguard Worker 	int ret, retry = 0;
737*1a3d31e3SAndroid Build Coastguard Worker 
738*1a3d31e3SAndroid Build Coastguard Worker 	do {
739*1a3d31e3SAndroid Build Coastguard Worker 		ret = mlock(addr, len);
740*1a3d31e3SAndroid Build Coastguard Worker 		if ((retry >= 10) && tp && tp->is_done)
741*1a3d31e3SAndroid Build Coastguard Worker 			break;
742*1a3d31e3SAndroid Build Coastguard Worker 		retry++;
743*1a3d31e3SAndroid Build Coastguard Worker 	} while (ret < 0 && handle_mem_failure(len));
744*1a3d31e3SAndroid Build Coastguard Worker 
745*1a3d31e3SAndroid Build Coastguard Worker 	return ret;
746*1a3d31e3SAndroid Build Coastguard Worker }
747*1a3d31e3SAndroid Build Coastguard Worker 
setup_mmap(int fd,unsigned int maxlen,struct mmap_info * mip,struct tracer * tp)748*1a3d31e3SAndroid Build Coastguard Worker static int setup_mmap(int fd, unsigned int maxlen,
749*1a3d31e3SAndroid Build Coastguard Worker 		      struct mmap_info *mip,
750*1a3d31e3SAndroid Build Coastguard Worker 		      struct tracer *tp)
751*1a3d31e3SAndroid Build Coastguard Worker {
752*1a3d31e3SAndroid Build Coastguard Worker 	if (mip->fs_off + maxlen > mip->fs_buf_len) {
753*1a3d31e3SAndroid Build Coastguard Worker 		unsigned long nr = max(16, mip->buf_nr);
754*1a3d31e3SAndroid Build Coastguard Worker 
755*1a3d31e3SAndroid Build Coastguard Worker 		if (mip->fs_buf) {
756*1a3d31e3SAndroid Build Coastguard Worker 			munlock(mip->fs_buf, mip->fs_buf_len);
757*1a3d31e3SAndroid Build Coastguard Worker 			munmap(mip->fs_buf, mip->fs_buf_len);
758*1a3d31e3SAndroid Build Coastguard Worker 			mip->fs_buf = NULL;
759*1a3d31e3SAndroid Build Coastguard Worker 		}
760*1a3d31e3SAndroid Build Coastguard Worker 
761*1a3d31e3SAndroid Build Coastguard Worker 		mip->fs_off = mip->fs_size & (mip->pagesize - 1);
762*1a3d31e3SAndroid Build Coastguard Worker 		mip->fs_buf_len = (nr * mip->buf_size) - mip->fs_off;
763*1a3d31e3SAndroid Build Coastguard Worker 		mip->fs_max_size += mip->fs_buf_len;
764*1a3d31e3SAndroid Build Coastguard Worker 
765*1a3d31e3SAndroid Build Coastguard Worker 		if (ftruncate(fd, mip->fs_max_size) < 0) {
766*1a3d31e3SAndroid Build Coastguard Worker 			perror("setup_mmap: ftruncate");
767*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
768*1a3d31e3SAndroid Build Coastguard Worker 		}
769*1a3d31e3SAndroid Build Coastguard Worker 
770*1a3d31e3SAndroid Build Coastguard Worker 		mip->fs_buf = my_mmap(NULL, mip->fs_buf_len, PROT_WRITE,
771*1a3d31e3SAndroid Build Coastguard Worker 				      MAP_SHARED, fd,
772*1a3d31e3SAndroid Build Coastguard Worker 				      mip->fs_size - mip->fs_off);
773*1a3d31e3SAndroid Build Coastguard Worker 		if (mip->fs_buf == MAP_FAILED) {
774*1a3d31e3SAndroid Build Coastguard Worker 			perror("setup_mmap: mmap");
775*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
776*1a3d31e3SAndroid Build Coastguard Worker 		}
777*1a3d31e3SAndroid Build Coastguard Worker 		if (my_mlock(tp, mip->fs_buf, mip->fs_buf_len) < 0) {
778*1a3d31e3SAndroid Build Coastguard Worker 			perror("setup_mlock: mlock");
779*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
780*1a3d31e3SAndroid Build Coastguard Worker 		}
781*1a3d31e3SAndroid Build Coastguard Worker 	}
782*1a3d31e3SAndroid Build Coastguard Worker 
783*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
784*1a3d31e3SAndroid Build Coastguard Worker }
785*1a3d31e3SAndroid Build Coastguard Worker 
__stop_trace(int fd)786*1a3d31e3SAndroid Build Coastguard Worker static int __stop_trace(int fd)
787*1a3d31e3SAndroid Build Coastguard Worker {
788*1a3d31e3SAndroid Build Coastguard Worker 	/*
789*1a3d31e3SAndroid Build Coastguard Worker 	 * Should be stopped, don't complain if it isn't
790*1a3d31e3SAndroid Build Coastguard Worker 	 */
791*1a3d31e3SAndroid Build Coastguard Worker 	ioctl(fd, BLKTRACESTOP);
792*1a3d31e3SAndroid Build Coastguard Worker 	return ioctl(fd, BLKTRACETEARDOWN);
793*1a3d31e3SAndroid Build Coastguard Worker }
794*1a3d31e3SAndroid Build Coastguard Worker 
write_data(char * buf,int len)795*1a3d31e3SAndroid Build Coastguard Worker static int write_data(char *buf, int len)
796*1a3d31e3SAndroid Build Coastguard Worker {
797*1a3d31e3SAndroid Build Coastguard Worker 	int ret;
798*1a3d31e3SAndroid Build Coastguard Worker 
799*1a3d31e3SAndroid Build Coastguard Worker rewrite:
800*1a3d31e3SAndroid Build Coastguard Worker 	ret = fwrite(buf, len, 1, pfp);
801*1a3d31e3SAndroid Build Coastguard Worker 	if (ferror(pfp) || ret != 1) {
802*1a3d31e3SAndroid Build Coastguard Worker 		if (errno == EINTR) {
803*1a3d31e3SAndroid Build Coastguard Worker 			clearerr(pfp);
804*1a3d31e3SAndroid Build Coastguard Worker 			goto rewrite;
805*1a3d31e3SAndroid Build Coastguard Worker 		}
806*1a3d31e3SAndroid Build Coastguard Worker 
807*1a3d31e3SAndroid Build Coastguard Worker 		if (!piped_output || (errno != EPIPE && errno != EBADF)) {
808*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr, "write(%d) failed: %d/%s\n",
809*1a3d31e3SAndroid Build Coastguard Worker 				len, errno, strerror(errno));
810*1a3d31e3SAndroid Build Coastguard Worker 		}
811*1a3d31e3SAndroid Build Coastguard Worker 		goto err;
812*1a3d31e3SAndroid Build Coastguard Worker 	}
813*1a3d31e3SAndroid Build Coastguard Worker 
814*1a3d31e3SAndroid Build Coastguard Worker 	fflush(pfp);
815*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
816*1a3d31e3SAndroid Build Coastguard Worker 
817*1a3d31e3SAndroid Build Coastguard Worker err:
818*1a3d31e3SAndroid Build Coastguard Worker 	clearerr(pfp);
819*1a3d31e3SAndroid Build Coastguard Worker 	return 1;
820*1a3d31e3SAndroid Build Coastguard Worker }
821*1a3d31e3SAndroid Build Coastguard Worker 
822*1a3d31e3SAndroid Build Coastguard Worker /*
823*1a3d31e3SAndroid Build Coastguard Worker  * Returns the number of bytes read (successfully)
824*1a3d31e3SAndroid Build Coastguard Worker  */
__net_recv_data(int fd,void * buf,unsigned int len)825*1a3d31e3SAndroid Build Coastguard Worker static int __net_recv_data(int fd, void *buf, unsigned int len)
826*1a3d31e3SAndroid Build Coastguard Worker {
827*1a3d31e3SAndroid Build Coastguard Worker 	unsigned int bytes_left = len;
828*1a3d31e3SAndroid Build Coastguard Worker 
829*1a3d31e3SAndroid Build Coastguard Worker 	while (bytes_left && !done) {
830*1a3d31e3SAndroid Build Coastguard Worker 		int ret = recv(fd, buf, bytes_left, MSG_WAITALL);
831*1a3d31e3SAndroid Build Coastguard Worker 
832*1a3d31e3SAndroid Build Coastguard Worker 		if (ret == 0)
833*1a3d31e3SAndroid Build Coastguard Worker 			break;
834*1a3d31e3SAndroid Build Coastguard Worker 		else if (ret < 0) {
835*1a3d31e3SAndroid Build Coastguard Worker 			if (errno == EAGAIN) {
836*1a3d31e3SAndroid Build Coastguard Worker 				usleep(50);
837*1a3d31e3SAndroid Build Coastguard Worker 				continue;
838*1a3d31e3SAndroid Build Coastguard Worker 			}
839*1a3d31e3SAndroid Build Coastguard Worker 			perror("server: net_recv_data: recv failed");
840*1a3d31e3SAndroid Build Coastguard Worker 			break;
841*1a3d31e3SAndroid Build Coastguard Worker 		} else {
842*1a3d31e3SAndroid Build Coastguard Worker 			buf += ret;
843*1a3d31e3SAndroid Build Coastguard Worker 			bytes_left -= ret;
844*1a3d31e3SAndroid Build Coastguard Worker 		}
845*1a3d31e3SAndroid Build Coastguard Worker 	}
846*1a3d31e3SAndroid Build Coastguard Worker 
847*1a3d31e3SAndroid Build Coastguard Worker 	return len - bytes_left;
848*1a3d31e3SAndroid Build Coastguard Worker }
849*1a3d31e3SAndroid Build Coastguard Worker 
net_recv_data(int fd,void * buf,unsigned int len)850*1a3d31e3SAndroid Build Coastguard Worker static int net_recv_data(int fd, void *buf, unsigned int len)
851*1a3d31e3SAndroid Build Coastguard Worker {
852*1a3d31e3SAndroid Build Coastguard Worker 	return __net_recv_data(fd, buf, len);
853*1a3d31e3SAndroid Build Coastguard Worker }
854*1a3d31e3SAndroid Build Coastguard Worker 
855*1a3d31e3SAndroid Build Coastguard Worker /*
856*1a3d31e3SAndroid Build Coastguard Worker  * Returns number of bytes written
857*1a3d31e3SAndroid Build Coastguard Worker  */
net_send_data(int fd,void * buf,unsigned int buf_len)858*1a3d31e3SAndroid Build Coastguard Worker static int net_send_data(int fd, void *buf, unsigned int buf_len)
859*1a3d31e3SAndroid Build Coastguard Worker {
860*1a3d31e3SAndroid Build Coastguard Worker 	int ret;
861*1a3d31e3SAndroid Build Coastguard Worker 	unsigned int bytes_left = buf_len;
862*1a3d31e3SAndroid Build Coastguard Worker 
863*1a3d31e3SAndroid Build Coastguard Worker 	while (bytes_left) {
864*1a3d31e3SAndroid Build Coastguard Worker 		ret = send(fd, buf, bytes_left, 0);
865*1a3d31e3SAndroid Build Coastguard Worker 		if (ret < 0) {
866*1a3d31e3SAndroid Build Coastguard Worker 			perror("send");
867*1a3d31e3SAndroid Build Coastguard Worker 			break;
868*1a3d31e3SAndroid Build Coastguard Worker 		}
869*1a3d31e3SAndroid Build Coastguard Worker 
870*1a3d31e3SAndroid Build Coastguard Worker 		buf += ret;
871*1a3d31e3SAndroid Build Coastguard Worker 		bytes_left -= ret;
872*1a3d31e3SAndroid Build Coastguard Worker 	}
873*1a3d31e3SAndroid Build Coastguard Worker 
874*1a3d31e3SAndroid Build Coastguard Worker 	return buf_len - bytes_left;
875*1a3d31e3SAndroid Build Coastguard Worker }
876*1a3d31e3SAndroid Build Coastguard Worker 
net_send_header(int fd,int cpu,char * buts_name,int len)877*1a3d31e3SAndroid Build Coastguard Worker static int net_send_header(int fd, int cpu, char *buts_name, int len)
878*1a3d31e3SAndroid Build Coastguard Worker {
879*1a3d31e3SAndroid Build Coastguard Worker 	struct blktrace_net_hdr hdr;
880*1a3d31e3SAndroid Build Coastguard Worker 
881*1a3d31e3SAndroid Build Coastguard Worker 	memset(&hdr, 0, sizeof(hdr));
882*1a3d31e3SAndroid Build Coastguard Worker 
883*1a3d31e3SAndroid Build Coastguard Worker 	hdr.magic = BLK_IO_TRACE_MAGIC;
884*1a3d31e3SAndroid Build Coastguard Worker 	memset(hdr.buts_name, 0, sizeof(hdr.buts_name));
885*1a3d31e3SAndroid Build Coastguard Worker 	strncpy(hdr.buts_name, buts_name, sizeof(hdr.buts_name));
886*1a3d31e3SAndroid Build Coastguard Worker 	hdr.buts_name[sizeof(hdr.buts_name) - 1] = '\0';
887*1a3d31e3SAndroid Build Coastguard Worker 	hdr.cpu = cpu;
888*1a3d31e3SAndroid Build Coastguard Worker 	hdr.max_cpus = max_cpus;
889*1a3d31e3SAndroid Build Coastguard Worker 	hdr.len = len;
890*1a3d31e3SAndroid Build Coastguard Worker 	hdr.cl_id = getpid();
891*1a3d31e3SAndroid Build Coastguard Worker 	hdr.buf_size = buf_size;
892*1a3d31e3SAndroid Build Coastguard Worker 	hdr.buf_nr = buf_nr;
893*1a3d31e3SAndroid Build Coastguard Worker 	hdr.page_size = pagesize;
894*1a3d31e3SAndroid Build Coastguard Worker 
895*1a3d31e3SAndroid Build Coastguard Worker 	return net_send_data(fd, &hdr, sizeof(hdr)) != sizeof(hdr);
896*1a3d31e3SAndroid Build Coastguard Worker }
897*1a3d31e3SAndroid Build Coastguard Worker 
net_send_open_close(int fd,int cpu,char * buts_name,int len)898*1a3d31e3SAndroid Build Coastguard Worker static void net_send_open_close(int fd, int cpu, char *buts_name, int len)
899*1a3d31e3SAndroid Build Coastguard Worker {
900*1a3d31e3SAndroid Build Coastguard Worker 	struct blktrace_net_hdr ret_hdr;
901*1a3d31e3SAndroid Build Coastguard Worker 
902*1a3d31e3SAndroid Build Coastguard Worker 	net_send_header(fd, cpu, buts_name, len);
903*1a3d31e3SAndroid Build Coastguard Worker 	net_recv_data(fd, &ret_hdr, sizeof(ret_hdr));
904*1a3d31e3SAndroid Build Coastguard Worker }
905*1a3d31e3SAndroid Build Coastguard Worker 
net_send_open(int fd,int cpu,char * buts_name)906*1a3d31e3SAndroid Build Coastguard Worker static void net_send_open(int fd, int cpu, char *buts_name)
907*1a3d31e3SAndroid Build Coastguard Worker {
908*1a3d31e3SAndroid Build Coastguard Worker 	net_send_open_close(fd, cpu, buts_name, 0);
909*1a3d31e3SAndroid Build Coastguard Worker }
910*1a3d31e3SAndroid Build Coastguard Worker 
net_send_close(int fd,char * buts_name,int drops)911*1a3d31e3SAndroid Build Coastguard Worker static void net_send_close(int fd, char *buts_name, int drops)
912*1a3d31e3SAndroid Build Coastguard Worker {
913*1a3d31e3SAndroid Build Coastguard Worker 	/*
914*1a3d31e3SAndroid Build Coastguard Worker 	 * Overload CPU w/ number of drops
915*1a3d31e3SAndroid Build Coastguard Worker 	 *
916*1a3d31e3SAndroid Build Coastguard Worker 	 * XXX: Need to clear/set done around call - done=1 (which
917*1a3d31e3SAndroid Build Coastguard Worker 	 * is true here) stops reads from happening... :-(
918*1a3d31e3SAndroid Build Coastguard Worker 	 */
919*1a3d31e3SAndroid Build Coastguard Worker 	done = 0;
920*1a3d31e3SAndroid Build Coastguard Worker 	net_send_open_close(fd, drops, buts_name, 1);
921*1a3d31e3SAndroid Build Coastguard Worker 	done = 1;
922*1a3d31e3SAndroid Build Coastguard Worker }
923*1a3d31e3SAndroid Build Coastguard Worker 
ack_open_close(int fd,char * buts_name)924*1a3d31e3SAndroid Build Coastguard Worker static void ack_open_close(int fd, char *buts_name)
925*1a3d31e3SAndroid Build Coastguard Worker {
926*1a3d31e3SAndroid Build Coastguard Worker 	net_send_header(fd, 0, buts_name, 2);
927*1a3d31e3SAndroid Build Coastguard Worker }
928*1a3d31e3SAndroid Build Coastguard Worker 
net_send_drops(int fd)929*1a3d31e3SAndroid Build Coastguard Worker static void net_send_drops(int fd)
930*1a3d31e3SAndroid Build Coastguard Worker {
931*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
932*1a3d31e3SAndroid Build Coastguard Worker 
933*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
934*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
935*1a3d31e3SAndroid Build Coastguard Worker 
936*1a3d31e3SAndroid Build Coastguard Worker 		net_send_close(fd, dpp->buts_name, dpp->drops);
937*1a3d31e3SAndroid Build Coastguard Worker 	}
938*1a3d31e3SAndroid Build Coastguard Worker }
939*1a3d31e3SAndroid Build Coastguard Worker 
940*1a3d31e3SAndroid Build Coastguard Worker /*
941*1a3d31e3SAndroid Build Coastguard Worker  * Returns:
942*1a3d31e3SAndroid Build Coastguard Worker  *	 0: "EOF"
943*1a3d31e3SAndroid Build Coastguard Worker  *	 1: OK
944*1a3d31e3SAndroid Build Coastguard Worker  *	-1: Error
945*1a3d31e3SAndroid Build Coastguard Worker  */
net_get_header(struct cl_conn * nc,struct blktrace_net_hdr * bnh)946*1a3d31e3SAndroid Build Coastguard Worker static int net_get_header(struct cl_conn *nc, struct blktrace_net_hdr *bnh)
947*1a3d31e3SAndroid Build Coastguard Worker {
948*1a3d31e3SAndroid Build Coastguard Worker 	int bytes_read;
949*1a3d31e3SAndroid Build Coastguard Worker 	int fl = fcntl(nc->fd, F_GETFL);
950*1a3d31e3SAndroid Build Coastguard Worker 
951*1a3d31e3SAndroid Build Coastguard Worker 	fcntl(nc->fd, F_SETFL, fl | O_NONBLOCK);
952*1a3d31e3SAndroid Build Coastguard Worker 	bytes_read = __net_recv_data(nc->fd, bnh, sizeof(*bnh));
953*1a3d31e3SAndroid Build Coastguard Worker 	fcntl(nc->fd, F_SETFL, fl & ~O_NONBLOCK);
954*1a3d31e3SAndroid Build Coastguard Worker 
955*1a3d31e3SAndroid Build Coastguard Worker 	if (bytes_read == sizeof(*bnh))
956*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
957*1a3d31e3SAndroid Build Coastguard Worker 	else if (bytes_read == 0)
958*1a3d31e3SAndroid Build Coastguard Worker 		return 0;
959*1a3d31e3SAndroid Build Coastguard Worker 	else
960*1a3d31e3SAndroid Build Coastguard Worker 		return -1;
961*1a3d31e3SAndroid Build Coastguard Worker }
962*1a3d31e3SAndroid Build Coastguard Worker 
net_setup_addr(void)963*1a3d31e3SAndroid Build Coastguard Worker static int net_setup_addr(void)
964*1a3d31e3SAndroid Build Coastguard Worker {
965*1a3d31e3SAndroid Build Coastguard Worker 	struct sockaddr_in *addr = &hostname_addr;
966*1a3d31e3SAndroid Build Coastguard Worker 
967*1a3d31e3SAndroid Build Coastguard Worker 	memset(addr, 0, sizeof(*addr));
968*1a3d31e3SAndroid Build Coastguard Worker 	addr->sin_family = AF_INET;
969*1a3d31e3SAndroid Build Coastguard Worker 	addr->sin_port = htons(net_port);
970*1a3d31e3SAndroid Build Coastguard Worker 
971*1a3d31e3SAndroid Build Coastguard Worker 	if (inet_aton(hostname, &addr->sin_addr) != 1) {
972*1a3d31e3SAndroid Build Coastguard Worker 		struct hostent *hent;
973*1a3d31e3SAndroid Build Coastguard Worker retry:
974*1a3d31e3SAndroid Build Coastguard Worker 		hent = gethostbyname(hostname);
975*1a3d31e3SAndroid Build Coastguard Worker 		if (!hent) {
976*1a3d31e3SAndroid Build Coastguard Worker 			if (h_errno == TRY_AGAIN) {
977*1a3d31e3SAndroid Build Coastguard Worker 				usleep(100);
978*1a3d31e3SAndroid Build Coastguard Worker 				goto retry;
979*1a3d31e3SAndroid Build Coastguard Worker 			} else if (h_errno == NO_RECOVERY) {
980*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr, "gethostbyname(%s)"
981*1a3d31e3SAndroid Build Coastguard Worker 					"non-recoverable error encountered\n",
982*1a3d31e3SAndroid Build Coastguard Worker 					hostname);
983*1a3d31e3SAndroid Build Coastguard Worker 			} else {
984*1a3d31e3SAndroid Build Coastguard Worker 				/*
985*1a3d31e3SAndroid Build Coastguard Worker 				 * HOST_NOT_FOUND, NO_ADDRESS or NO_DATA
986*1a3d31e3SAndroid Build Coastguard Worker 				 */
987*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr, "Host %s not found\n",
988*1a3d31e3SAndroid Build Coastguard Worker 					hostname);
989*1a3d31e3SAndroid Build Coastguard Worker 			}
990*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
991*1a3d31e3SAndroid Build Coastguard Worker 		}
992*1a3d31e3SAndroid Build Coastguard Worker 
993*1a3d31e3SAndroid Build Coastguard Worker 		memcpy(&addr->sin_addr, hent->h_addr, 4);
994*1a3d31e3SAndroid Build Coastguard Worker 		memset(hostname, 0, sizeof(hostname));
995*1a3d31e3SAndroid Build Coastguard Worker 		strncpy(hostname, hent->h_name, sizeof(hostname));
996*1a3d31e3SAndroid Build Coastguard Worker 		hostname[sizeof(hostname) - 1] = '\0';
997*1a3d31e3SAndroid Build Coastguard Worker 	}
998*1a3d31e3SAndroid Build Coastguard Worker 
999*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1000*1a3d31e3SAndroid Build Coastguard Worker }
1001*1a3d31e3SAndroid Build Coastguard Worker 
net_setup_client(void)1002*1a3d31e3SAndroid Build Coastguard Worker static int net_setup_client(void)
1003*1a3d31e3SAndroid Build Coastguard Worker {
1004*1a3d31e3SAndroid Build Coastguard Worker 	int fd;
1005*1a3d31e3SAndroid Build Coastguard Worker 	struct sockaddr_in *addr = &hostname_addr;
1006*1a3d31e3SAndroid Build Coastguard Worker 
1007*1a3d31e3SAndroid Build Coastguard Worker 	fd = my_socket(AF_INET, SOCK_STREAM, 0);
1008*1a3d31e3SAndroid Build Coastguard Worker 	if (fd < 0) {
1009*1a3d31e3SAndroid Build Coastguard Worker 		perror("client: socket");
1010*1a3d31e3SAndroid Build Coastguard Worker 		return -1;
1011*1a3d31e3SAndroid Build Coastguard Worker 	}
1012*1a3d31e3SAndroid Build Coastguard Worker 
1013*1a3d31e3SAndroid Build Coastguard Worker 	if (connect(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
1014*1a3d31e3SAndroid Build Coastguard Worker 		if (errno == ECONNREFUSED)
1015*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr,
1016*1a3d31e3SAndroid Build Coastguard Worker 				"\nclient: Connection to %s refused, "
1017*1a3d31e3SAndroid Build Coastguard Worker 				"perhaps the server is not started?\n\n",
1018*1a3d31e3SAndroid Build Coastguard Worker 				hostname);
1019*1a3d31e3SAndroid Build Coastguard Worker 		else
1020*1a3d31e3SAndroid Build Coastguard Worker 			perror("client: connect");
1021*1a3d31e3SAndroid Build Coastguard Worker 
1022*1a3d31e3SAndroid Build Coastguard Worker 		close(fd);
1023*1a3d31e3SAndroid Build Coastguard Worker 		return -1;
1024*1a3d31e3SAndroid Build Coastguard Worker 	}
1025*1a3d31e3SAndroid Build Coastguard Worker 
1026*1a3d31e3SAndroid Build Coastguard Worker 	return fd;
1027*1a3d31e3SAndroid Build Coastguard Worker }
1028*1a3d31e3SAndroid Build Coastguard Worker 
open_client_connections(void)1029*1a3d31e3SAndroid Build Coastguard Worker static int open_client_connections(void)
1030*1a3d31e3SAndroid Build Coastguard Worker {
1031*1a3d31e3SAndroid Build Coastguard Worker 	int cpu;
1032*1a3d31e3SAndroid Build Coastguard Worker 	size_t alloc_size = CPU_ALLOC_SIZE(max_cpus);
1033*1a3d31e3SAndroid Build Coastguard Worker 
1034*1a3d31e3SAndroid Build Coastguard Worker 	cl_fds = calloc(ncpus, sizeof(*cl_fds));
1035*1a3d31e3SAndroid Build Coastguard Worker 	for (cpu = 0; cpu < max_cpus; cpu++) {
1036*1a3d31e3SAndroid Build Coastguard Worker 		if (!CPU_ISSET_S(cpu, alloc_size, online_cpus))
1037*1a3d31e3SAndroid Build Coastguard Worker 			continue;
1038*1a3d31e3SAndroid Build Coastguard Worker 		cl_fds[cpu] = net_setup_client();
1039*1a3d31e3SAndroid Build Coastguard Worker 		if (cl_fds[cpu] < 0)
1040*1a3d31e3SAndroid Build Coastguard Worker 			goto err;
1041*1a3d31e3SAndroid Build Coastguard Worker 	}
1042*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1043*1a3d31e3SAndroid Build Coastguard Worker 
1044*1a3d31e3SAndroid Build Coastguard Worker err:
1045*1a3d31e3SAndroid Build Coastguard Worker 	while (cpu > 0)
1046*1a3d31e3SAndroid Build Coastguard Worker 		close(cl_fds[cpu--]);
1047*1a3d31e3SAndroid Build Coastguard Worker 	free(cl_fds);
1048*1a3d31e3SAndroid Build Coastguard Worker 	return 1;
1049*1a3d31e3SAndroid Build Coastguard Worker }
1050*1a3d31e3SAndroid Build Coastguard Worker 
close_client_connections(void)1051*1a3d31e3SAndroid Build Coastguard Worker static void close_client_connections(void)
1052*1a3d31e3SAndroid Build Coastguard Worker {
1053*1a3d31e3SAndroid Build Coastguard Worker 	if (cl_fds) {
1054*1a3d31e3SAndroid Build Coastguard Worker 		int cpu, *fdp;
1055*1a3d31e3SAndroid Build Coastguard Worker 		size_t alloc_size = CPU_ALLOC_SIZE(max_cpus);
1056*1a3d31e3SAndroid Build Coastguard Worker 
1057*1a3d31e3SAndroid Build Coastguard Worker 		for (cpu = 0, fdp = cl_fds; cpu < max_cpus; cpu++, fdp++) {
1058*1a3d31e3SAndroid Build Coastguard Worker 			if (!CPU_ISSET_S(cpu, alloc_size, online_cpus))
1059*1a3d31e3SAndroid Build Coastguard Worker 				continue;
1060*1a3d31e3SAndroid Build Coastguard Worker 			if (*fdp >= 0) {
1061*1a3d31e3SAndroid Build Coastguard Worker 				net_send_drops(*fdp);
1062*1a3d31e3SAndroid Build Coastguard Worker 				net_close_connection(fdp);
1063*1a3d31e3SAndroid Build Coastguard Worker 			}
1064*1a3d31e3SAndroid Build Coastguard Worker 		}
1065*1a3d31e3SAndroid Build Coastguard Worker 		free(cl_fds);
1066*1a3d31e3SAndroid Build Coastguard Worker 	}
1067*1a3d31e3SAndroid Build Coastguard Worker }
1068*1a3d31e3SAndroid Build Coastguard Worker 
setup_buts(void)1069*1a3d31e3SAndroid Build Coastguard Worker static int setup_buts(void)
1070*1a3d31e3SAndroid Build Coastguard Worker {
1071*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1072*1a3d31e3SAndroid Build Coastguard Worker 	int ret = 0;
1073*1a3d31e3SAndroid Build Coastguard Worker 
1074*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1075*1a3d31e3SAndroid Build Coastguard Worker 		struct blk_user_trace_setup buts;
1076*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1077*1a3d31e3SAndroid Build Coastguard Worker 
1078*1a3d31e3SAndroid Build Coastguard Worker 		memset(&buts, 0, sizeof(buts));
1079*1a3d31e3SAndroid Build Coastguard Worker 		buts.buf_size = buf_size;
1080*1a3d31e3SAndroid Build Coastguard Worker 		buts.buf_nr = buf_nr;
1081*1a3d31e3SAndroid Build Coastguard Worker 		buts.act_mask = act_mask;
1082*1a3d31e3SAndroid Build Coastguard Worker 
1083*1a3d31e3SAndroid Build Coastguard Worker 		if (ioctl(dpp->fd, BLKTRACESETUP, &buts) >= 0) {
1084*1a3d31e3SAndroid Build Coastguard Worker 			dpp->ncpus = max_cpus;
1085*1a3d31e3SAndroid Build Coastguard Worker 			dpp->buts_name = strdup(buts.name);
1086*1a3d31e3SAndroid Build Coastguard Worker 			if (dpp->stats)
1087*1a3d31e3SAndroid Build Coastguard Worker 				free(dpp->stats);
1088*1a3d31e3SAndroid Build Coastguard Worker 			dpp->stats = calloc(dpp->ncpus, sizeof(*dpp->stats));
1089*1a3d31e3SAndroid Build Coastguard Worker 			memset(dpp->stats, 0, dpp->ncpus * sizeof(*dpp->stats));
1090*1a3d31e3SAndroid Build Coastguard Worker 		} else {
1091*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr, "BLKTRACESETUP(2) %s failed: %d/%s\n",
1092*1a3d31e3SAndroid Build Coastguard Worker 				dpp->path, errno, strerror(errno));
1093*1a3d31e3SAndroid Build Coastguard Worker 			ret++;
1094*1a3d31e3SAndroid Build Coastguard Worker 		}
1095*1a3d31e3SAndroid Build Coastguard Worker 	}
1096*1a3d31e3SAndroid Build Coastguard Worker 
1097*1a3d31e3SAndroid Build Coastguard Worker 	return ret;
1098*1a3d31e3SAndroid Build Coastguard Worker }
1099*1a3d31e3SAndroid Build Coastguard Worker 
start_buts(void)1100*1a3d31e3SAndroid Build Coastguard Worker static void start_buts(void)
1101*1a3d31e3SAndroid Build Coastguard Worker {
1102*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1103*1a3d31e3SAndroid Build Coastguard Worker 
1104*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1105*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1106*1a3d31e3SAndroid Build Coastguard Worker 
1107*1a3d31e3SAndroid Build Coastguard Worker 		if (ioctl(dpp->fd, BLKTRACESTART) < 0) {
1108*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr, "BLKTRACESTART %s failed: %d/%s\n",
1109*1a3d31e3SAndroid Build Coastguard Worker 				dpp->path, errno, strerror(errno));
1110*1a3d31e3SAndroid Build Coastguard Worker 		}
1111*1a3d31e3SAndroid Build Coastguard Worker 	}
1112*1a3d31e3SAndroid Build Coastguard Worker }
1113*1a3d31e3SAndroid Build Coastguard Worker 
get_drops(struct devpath * dpp)1114*1a3d31e3SAndroid Build Coastguard Worker static int get_drops(struct devpath *dpp)
1115*1a3d31e3SAndroid Build Coastguard Worker {
1116*1a3d31e3SAndroid Build Coastguard Worker 	int fd, drops = 0;
1117*1a3d31e3SAndroid Build Coastguard Worker 	char fn[MAXPATHLEN + 64], tmp[256];
1118*1a3d31e3SAndroid Build Coastguard Worker 
1119*1a3d31e3SAndroid Build Coastguard Worker 	snprintf(fn, sizeof(fn), "%s/block/%s/dropped", debugfs_path,
1120*1a3d31e3SAndroid Build Coastguard Worker 		 dpp->buts_name);
1121*1a3d31e3SAndroid Build Coastguard Worker 
1122*1a3d31e3SAndroid Build Coastguard Worker 	fd = my_open(fn, O_RDONLY);
1123*1a3d31e3SAndroid Build Coastguard Worker 	if (fd < 0) {
1124*1a3d31e3SAndroid Build Coastguard Worker 		/*
1125*1a3d31e3SAndroid Build Coastguard Worker 		 * This may be ok: the kernel may not support
1126*1a3d31e3SAndroid Build Coastguard Worker 		 * dropped counts.
1127*1a3d31e3SAndroid Build Coastguard Worker 		 */
1128*1a3d31e3SAndroid Build Coastguard Worker 		if (errno != ENOENT)
1129*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr, "Could not open %s: %d/%s\n",
1130*1a3d31e3SAndroid Build Coastguard Worker 				fn, errno, strerror(errno));
1131*1a3d31e3SAndroid Build Coastguard Worker 		return 0;
1132*1a3d31e3SAndroid Build Coastguard Worker 	} else if (read(fd, tmp, sizeof(tmp)) < 0) {
1133*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "Could not read %s: %d/%s\n",
1134*1a3d31e3SAndroid Build Coastguard Worker 			fn, errno, strerror(errno));
1135*1a3d31e3SAndroid Build Coastguard Worker 	} else
1136*1a3d31e3SAndroid Build Coastguard Worker 		drops = atoi(tmp);
1137*1a3d31e3SAndroid Build Coastguard Worker 	close(fd);
1138*1a3d31e3SAndroid Build Coastguard Worker 
1139*1a3d31e3SAndroid Build Coastguard Worker 	return drops;
1140*1a3d31e3SAndroid Build Coastguard Worker }
1141*1a3d31e3SAndroid Build Coastguard Worker 
get_all_drops(void)1142*1a3d31e3SAndroid Build Coastguard Worker static void get_all_drops(void)
1143*1a3d31e3SAndroid Build Coastguard Worker {
1144*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1145*1a3d31e3SAndroid Build Coastguard Worker 
1146*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1147*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1148*1a3d31e3SAndroid Build Coastguard Worker 
1149*1a3d31e3SAndroid Build Coastguard Worker 		dpp->drops = get_drops(dpp);
1150*1a3d31e3SAndroid Build Coastguard Worker 	}
1151*1a3d31e3SAndroid Build Coastguard Worker }
1152*1a3d31e3SAndroid Build Coastguard Worker 
alloc_trace_buf(int cpu,int bufsize)1153*1a3d31e3SAndroid Build Coastguard Worker static inline struct trace_buf *alloc_trace_buf(int cpu, int bufsize)
1154*1a3d31e3SAndroid Build Coastguard Worker {
1155*1a3d31e3SAndroid Build Coastguard Worker 	struct trace_buf *tbp;
1156*1a3d31e3SAndroid Build Coastguard Worker 
1157*1a3d31e3SAndroid Build Coastguard Worker 	tbp = malloc(sizeof(*tbp) + bufsize);
1158*1a3d31e3SAndroid Build Coastguard Worker 	INIT_LIST_HEAD(&tbp->head);
1159*1a3d31e3SAndroid Build Coastguard Worker 	tbp->len = 0;
1160*1a3d31e3SAndroid Build Coastguard Worker 	tbp->buf = (void *)(tbp + 1);
1161*1a3d31e3SAndroid Build Coastguard Worker 	tbp->cpu = cpu;
1162*1a3d31e3SAndroid Build Coastguard Worker 	tbp->dpp = NULL;	/* Will be set when tbp is added */
1163*1a3d31e3SAndroid Build Coastguard Worker 
1164*1a3d31e3SAndroid Build Coastguard Worker 	return tbp;
1165*1a3d31e3SAndroid Build Coastguard Worker }
1166*1a3d31e3SAndroid Build Coastguard Worker 
free_tracer_heads(struct devpath * dpp)1167*1a3d31e3SAndroid Build Coastguard Worker static void free_tracer_heads(struct devpath *dpp)
1168*1a3d31e3SAndroid Build Coastguard Worker {
1169*1a3d31e3SAndroid Build Coastguard Worker 	int cpu;
1170*1a3d31e3SAndroid Build Coastguard Worker 	struct tracer_devpath_head *hd;
1171*1a3d31e3SAndroid Build Coastguard Worker 
1172*1a3d31e3SAndroid Build Coastguard Worker 	for (cpu = 0, hd = dpp->heads; cpu < max_cpus; cpu++, hd++) {
1173*1a3d31e3SAndroid Build Coastguard Worker 		if (hd->prev)
1174*1a3d31e3SAndroid Build Coastguard Worker 			free(hd->prev);
1175*1a3d31e3SAndroid Build Coastguard Worker 
1176*1a3d31e3SAndroid Build Coastguard Worker 		pthread_mutex_destroy(&hd->mutex);
1177*1a3d31e3SAndroid Build Coastguard Worker 	}
1178*1a3d31e3SAndroid Build Coastguard Worker 	free(dpp->heads);
1179*1a3d31e3SAndroid Build Coastguard Worker }
1180*1a3d31e3SAndroid Build Coastguard Worker 
setup_tracer_devpaths(void)1181*1a3d31e3SAndroid Build Coastguard Worker static int setup_tracer_devpaths(void)
1182*1a3d31e3SAndroid Build Coastguard Worker {
1183*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1184*1a3d31e3SAndroid Build Coastguard Worker 
1185*1a3d31e3SAndroid Build Coastguard Worker 	if (net_client_use_send())
1186*1a3d31e3SAndroid Build Coastguard Worker 		if (open_client_connections())
1187*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
1188*1a3d31e3SAndroid Build Coastguard Worker 
1189*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1190*1a3d31e3SAndroid Build Coastguard Worker 		int cpu;
1191*1a3d31e3SAndroid Build Coastguard Worker 		struct tracer_devpath_head *hd;
1192*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1193*1a3d31e3SAndroid Build Coastguard Worker 
1194*1a3d31e3SAndroid Build Coastguard Worker 		dpp->heads = calloc(max_cpus, sizeof(struct tracer_devpath_head));
1195*1a3d31e3SAndroid Build Coastguard Worker 		for (cpu = 0, hd = dpp->heads; cpu < max_cpus; cpu++, hd++) {
1196*1a3d31e3SAndroid Build Coastguard Worker 			INIT_LIST_HEAD(&hd->head);
1197*1a3d31e3SAndroid Build Coastguard Worker 			pthread_mutex_init(&hd->mutex, NULL);
1198*1a3d31e3SAndroid Build Coastguard Worker 			hd->prev = NULL;
1199*1a3d31e3SAndroid Build Coastguard Worker 		}
1200*1a3d31e3SAndroid Build Coastguard Worker 	}
1201*1a3d31e3SAndroid Build Coastguard Worker 
1202*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1203*1a3d31e3SAndroid Build Coastguard Worker }
1204*1a3d31e3SAndroid Build Coastguard Worker 
add_trace_buf(struct devpath * dpp,int cpu,struct trace_buf ** tbpp)1205*1a3d31e3SAndroid Build Coastguard Worker static inline void add_trace_buf(struct devpath *dpp, int cpu,
1206*1a3d31e3SAndroid Build Coastguard Worker 						struct trace_buf **tbpp)
1207*1a3d31e3SAndroid Build Coastguard Worker {
1208*1a3d31e3SAndroid Build Coastguard Worker 	struct trace_buf *tbp = *tbpp;
1209*1a3d31e3SAndroid Build Coastguard Worker 	struct tracer_devpath_head *hd = &dpp->heads[cpu];
1210*1a3d31e3SAndroid Build Coastguard Worker 
1211*1a3d31e3SAndroid Build Coastguard Worker 	tbp->dpp = dpp;
1212*1a3d31e3SAndroid Build Coastguard Worker 
1213*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&hd->mutex);
1214*1a3d31e3SAndroid Build Coastguard Worker 	list_add_tail(&tbp->head, &hd->head);
1215*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&hd->mutex);
1216*1a3d31e3SAndroid Build Coastguard Worker 
1217*1a3d31e3SAndroid Build Coastguard Worker 	*tbpp = alloc_trace_buf(cpu, buf_size);
1218*1a3d31e3SAndroid Build Coastguard Worker }
1219*1a3d31e3SAndroid Build Coastguard Worker 
incr_entries(int entries_handled)1220*1a3d31e3SAndroid Build Coastguard Worker static inline void incr_entries(int entries_handled)
1221*1a3d31e3SAndroid Build Coastguard Worker {
1222*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&dp_mutex);
1223*1a3d31e3SAndroid Build Coastguard Worker 	if (dp_entries == 0)
1224*1a3d31e3SAndroid Build Coastguard Worker 		pthread_cond_signal(&dp_cond);
1225*1a3d31e3SAndroid Build Coastguard Worker 	dp_entries += entries_handled;
1226*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&dp_mutex);
1227*1a3d31e3SAndroid Build Coastguard Worker }
1228*1a3d31e3SAndroid Build Coastguard Worker 
decr_entries(int handled)1229*1a3d31e3SAndroid Build Coastguard Worker static void decr_entries(int handled)
1230*1a3d31e3SAndroid Build Coastguard Worker {
1231*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&dp_mutex);
1232*1a3d31e3SAndroid Build Coastguard Worker 	dp_entries -= handled;
1233*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&dp_mutex);
1234*1a3d31e3SAndroid Build Coastguard Worker }
1235*1a3d31e3SAndroid Build Coastguard Worker 
wait_empty_entries(void)1236*1a3d31e3SAndroid Build Coastguard Worker static int wait_empty_entries(void)
1237*1a3d31e3SAndroid Build Coastguard Worker {
1238*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_lock(&dp_mutex);
1239*1a3d31e3SAndroid Build Coastguard Worker 	while (!done && dp_entries == 0)
1240*1a3d31e3SAndroid Build Coastguard Worker 		t_pthread_cond_wait(&dp_cond, &dp_mutex);
1241*1a3d31e3SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&dp_mutex);
1242*1a3d31e3SAndroid Build Coastguard Worker 
1243*1a3d31e3SAndroid Build Coastguard Worker 	return !done;
1244*1a3d31e3SAndroid Build Coastguard Worker }
1245*1a3d31e3SAndroid Build Coastguard Worker 
add_devpath(char * path)1246*1a3d31e3SAndroid Build Coastguard Worker static int add_devpath(char *path)
1247*1a3d31e3SAndroid Build Coastguard Worker {
1248*1a3d31e3SAndroid Build Coastguard Worker 	int fd;
1249*1a3d31e3SAndroid Build Coastguard Worker 	struct devpath *dpp;
1250*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1251*1a3d31e3SAndroid Build Coastguard Worker 
1252*1a3d31e3SAndroid Build Coastguard Worker 	/*
1253*1a3d31e3SAndroid Build Coastguard Worker 	 * Verify device is not duplicated
1254*1a3d31e3SAndroid Build Coastguard Worker 	 */
1255*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1256*1a3d31e3SAndroid Build Coastguard Worker 	       struct devpath *tmp = list_entry(p, struct devpath, head);
1257*1a3d31e3SAndroid Build Coastguard Worker 	       if (!strcmp(tmp->path, path))
1258*1a3d31e3SAndroid Build Coastguard Worker 		        return 0;
1259*1a3d31e3SAndroid Build Coastguard Worker 	}
1260*1a3d31e3SAndroid Build Coastguard Worker 	/*
1261*1a3d31e3SAndroid Build Coastguard Worker 	 * Verify device is valid before going too far
1262*1a3d31e3SAndroid Build Coastguard Worker 	 */
1263*1a3d31e3SAndroid Build Coastguard Worker 	fd = my_open(path, O_RDONLY | O_NONBLOCK);
1264*1a3d31e3SAndroid Build Coastguard Worker 	if (fd < 0) {
1265*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid path %s specified: %d/%s\n",
1266*1a3d31e3SAndroid Build Coastguard Worker 			path, errno, strerror(errno));
1267*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1268*1a3d31e3SAndroid Build Coastguard Worker 	}
1269*1a3d31e3SAndroid Build Coastguard Worker 
1270*1a3d31e3SAndroid Build Coastguard Worker 	dpp = malloc(sizeof(*dpp));
1271*1a3d31e3SAndroid Build Coastguard Worker 	memset(dpp, 0, sizeof(*dpp));
1272*1a3d31e3SAndroid Build Coastguard Worker 	dpp->path = strdup(path);
1273*1a3d31e3SAndroid Build Coastguard Worker 	dpp->fd = fd;
1274*1a3d31e3SAndroid Build Coastguard Worker 	ndevs++;
1275*1a3d31e3SAndroid Build Coastguard Worker 	list_add_tail(&dpp->head, &devpaths);
1276*1a3d31e3SAndroid Build Coastguard Worker 
1277*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1278*1a3d31e3SAndroid Build Coastguard Worker }
1279*1a3d31e3SAndroid Build Coastguard Worker 
rel_devpaths(void)1280*1a3d31e3SAndroid Build Coastguard Worker static void rel_devpaths(void)
1281*1a3d31e3SAndroid Build Coastguard Worker {
1282*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p, *q;
1283*1a3d31e3SAndroid Build Coastguard Worker 
1284*1a3d31e3SAndroid Build Coastguard Worker 	list_for_each_safe(p, q, &devpaths) {
1285*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1286*1a3d31e3SAndroid Build Coastguard Worker 
1287*1a3d31e3SAndroid Build Coastguard Worker 		list_del(&dpp->head);
1288*1a3d31e3SAndroid Build Coastguard Worker 		__stop_trace(dpp->fd);
1289*1a3d31e3SAndroid Build Coastguard Worker 		close(dpp->fd);
1290*1a3d31e3SAndroid Build Coastguard Worker 
1291*1a3d31e3SAndroid Build Coastguard Worker 		if (dpp->heads)
1292*1a3d31e3SAndroid Build Coastguard Worker 			free_tracer_heads(dpp);
1293*1a3d31e3SAndroid Build Coastguard Worker 
1294*1a3d31e3SAndroid Build Coastguard Worker 		dpp_free(dpp);
1295*1a3d31e3SAndroid Build Coastguard Worker 		ndevs--;
1296*1a3d31e3SAndroid Build Coastguard Worker 	}
1297*1a3d31e3SAndroid Build Coastguard Worker }
1298*1a3d31e3SAndroid Build Coastguard Worker 
flush_subbuf_net(struct trace_buf * tbp)1299*1a3d31e3SAndroid Build Coastguard Worker static int flush_subbuf_net(struct trace_buf *tbp)
1300*1a3d31e3SAndroid Build Coastguard Worker {
1301*1a3d31e3SAndroid Build Coastguard Worker 	int fd = cl_fds[tbp->cpu];
1302*1a3d31e3SAndroid Build Coastguard Worker 	struct devpath *dpp = tbp->dpp;
1303*1a3d31e3SAndroid Build Coastguard Worker 
1304*1a3d31e3SAndroid Build Coastguard Worker 	if (net_send_header(fd, tbp->cpu, dpp->buts_name, tbp->len))
1305*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1306*1a3d31e3SAndroid Build Coastguard Worker 	else if (net_send_data(fd, tbp->buf, tbp->len) != tbp->len)
1307*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1308*1a3d31e3SAndroid Build Coastguard Worker 
1309*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1310*1a3d31e3SAndroid Build Coastguard Worker }
1311*1a3d31e3SAndroid Build Coastguard Worker 
1312*1a3d31e3SAndroid Build Coastguard Worker static int
handle_list_net(struct tracer_devpath_head * hd,struct list_head * list)1313*1a3d31e3SAndroid Build Coastguard Worker handle_list_net(__attribute__((__unused__))struct tracer_devpath_head *hd,
1314*1a3d31e3SAndroid Build Coastguard Worker 		struct list_head *list)
1315*1a3d31e3SAndroid Build Coastguard Worker {
1316*1a3d31e3SAndroid Build Coastguard Worker 	struct trace_buf *tbp;
1317*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p, *q;
1318*1a3d31e3SAndroid Build Coastguard Worker 	int entries_handled = 0;
1319*1a3d31e3SAndroid Build Coastguard Worker 
1320*1a3d31e3SAndroid Build Coastguard Worker 	list_for_each_safe(p, q, list) {
1321*1a3d31e3SAndroid Build Coastguard Worker 		tbp = list_entry(p, struct trace_buf, head);
1322*1a3d31e3SAndroid Build Coastguard Worker 
1323*1a3d31e3SAndroid Build Coastguard Worker 		list_del(&tbp->head);
1324*1a3d31e3SAndroid Build Coastguard Worker 		entries_handled++;
1325*1a3d31e3SAndroid Build Coastguard Worker 
1326*1a3d31e3SAndroid Build Coastguard Worker 		if (cl_fds[tbp->cpu] >= 0) {
1327*1a3d31e3SAndroid Build Coastguard Worker 			if (flush_subbuf_net(tbp)) {
1328*1a3d31e3SAndroid Build Coastguard Worker 				close(cl_fds[tbp->cpu]);
1329*1a3d31e3SAndroid Build Coastguard Worker 				cl_fds[tbp->cpu] = -1;
1330*1a3d31e3SAndroid Build Coastguard Worker 			}
1331*1a3d31e3SAndroid Build Coastguard Worker 		}
1332*1a3d31e3SAndroid Build Coastguard Worker 
1333*1a3d31e3SAndroid Build Coastguard Worker 		free(tbp);
1334*1a3d31e3SAndroid Build Coastguard Worker 	}
1335*1a3d31e3SAndroid Build Coastguard Worker 
1336*1a3d31e3SAndroid Build Coastguard Worker 	return entries_handled;
1337*1a3d31e3SAndroid Build Coastguard Worker }
1338*1a3d31e3SAndroid Build Coastguard Worker 
1339*1a3d31e3SAndroid Build Coastguard Worker /*
1340*1a3d31e3SAndroid Build Coastguard Worker  * Tack 'tbp's buf onto the tail of 'prev's buf
1341*1a3d31e3SAndroid Build Coastguard Worker  */
tb_combine(struct trace_buf * prev,struct trace_buf * tbp)1342*1a3d31e3SAndroid Build Coastguard Worker static struct trace_buf *tb_combine(struct trace_buf *prev,
1343*1a3d31e3SAndroid Build Coastguard Worker 				    struct trace_buf *tbp)
1344*1a3d31e3SAndroid Build Coastguard Worker {
1345*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long tot_len;
1346*1a3d31e3SAndroid Build Coastguard Worker 
1347*1a3d31e3SAndroid Build Coastguard Worker 	tot_len = prev->len + tbp->len;
1348*1a3d31e3SAndroid Build Coastguard Worker 	if (tot_len > buf_size) {
1349*1a3d31e3SAndroid Build Coastguard Worker 		/*
1350*1a3d31e3SAndroid Build Coastguard Worker 		 * tbp->head isn't connected (it was 'prev'
1351*1a3d31e3SAndroid Build Coastguard Worker 		 * so it had been taken off of the list
1352*1a3d31e3SAndroid Build Coastguard Worker 		 * before). Therefore, we can realloc
1353*1a3d31e3SAndroid Build Coastguard Worker 		 * the whole structures, as the other fields
1354*1a3d31e3SAndroid Build Coastguard Worker 		 * are "static".
1355*1a3d31e3SAndroid Build Coastguard Worker 		 */
1356*1a3d31e3SAndroid Build Coastguard Worker 		prev = realloc(prev, sizeof(*prev) + tot_len);
1357*1a3d31e3SAndroid Build Coastguard Worker 		prev->buf = (void *)(prev + 1);
1358*1a3d31e3SAndroid Build Coastguard Worker 	}
1359*1a3d31e3SAndroid Build Coastguard Worker 
1360*1a3d31e3SAndroid Build Coastguard Worker 	memcpy(prev->buf + prev->len, tbp->buf, tbp->len);
1361*1a3d31e3SAndroid Build Coastguard Worker 	prev->len = tot_len;
1362*1a3d31e3SAndroid Build Coastguard Worker 
1363*1a3d31e3SAndroid Build Coastguard Worker 	free(tbp);
1364*1a3d31e3SAndroid Build Coastguard Worker 	return prev;
1365*1a3d31e3SAndroid Build Coastguard Worker }
1366*1a3d31e3SAndroid Build Coastguard Worker 
handle_list_file(struct tracer_devpath_head * hd,struct list_head * list)1367*1a3d31e3SAndroid Build Coastguard Worker static int handle_list_file(struct tracer_devpath_head *hd,
1368*1a3d31e3SAndroid Build Coastguard Worker 			    struct list_head *list)
1369*1a3d31e3SAndroid Build Coastguard Worker {
1370*1a3d31e3SAndroid Build Coastguard Worker 	int off, t_len, nevents;
1371*1a3d31e3SAndroid Build Coastguard Worker 	struct blk_io_trace *t;
1372*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p, *q;
1373*1a3d31e3SAndroid Build Coastguard Worker 	int entries_handled = 0;
1374*1a3d31e3SAndroid Build Coastguard Worker 	struct trace_buf *tbp, *prev;
1375*1a3d31e3SAndroid Build Coastguard Worker 
1376*1a3d31e3SAndroid Build Coastguard Worker 	prev = hd->prev;
1377*1a3d31e3SAndroid Build Coastguard Worker 	list_for_each_safe(p, q, list) {
1378*1a3d31e3SAndroid Build Coastguard Worker 		tbp = list_entry(p, struct trace_buf, head);
1379*1a3d31e3SAndroid Build Coastguard Worker 		list_del(&tbp->head);
1380*1a3d31e3SAndroid Build Coastguard Worker 		entries_handled++;
1381*1a3d31e3SAndroid Build Coastguard Worker 
1382*1a3d31e3SAndroid Build Coastguard Worker 		/*
1383*1a3d31e3SAndroid Build Coastguard Worker 		 * If there was some leftover before, tack this new
1384*1a3d31e3SAndroid Build Coastguard Worker 		 * entry onto the tail of the previous one.
1385*1a3d31e3SAndroid Build Coastguard Worker 		 */
1386*1a3d31e3SAndroid Build Coastguard Worker 		if (prev)
1387*1a3d31e3SAndroid Build Coastguard Worker 			tbp = tb_combine(prev, tbp);
1388*1a3d31e3SAndroid Build Coastguard Worker 
1389*1a3d31e3SAndroid Build Coastguard Worker 		/*
1390*1a3d31e3SAndroid Build Coastguard Worker 		 * See how many whole traces there are - send them
1391*1a3d31e3SAndroid Build Coastguard Worker 		 * all out in one go.
1392*1a3d31e3SAndroid Build Coastguard Worker 		 */
1393*1a3d31e3SAndroid Build Coastguard Worker 		off = 0;
1394*1a3d31e3SAndroid Build Coastguard Worker 		nevents = 0;
1395*1a3d31e3SAndroid Build Coastguard Worker 		while (off + (int)sizeof(*t) <= tbp->len) {
1396*1a3d31e3SAndroid Build Coastguard Worker 			t = (struct blk_io_trace *)(tbp->buf + off);
1397*1a3d31e3SAndroid Build Coastguard Worker 			t_len = sizeof(*t) + t->pdu_len;
1398*1a3d31e3SAndroid Build Coastguard Worker 			if (off + t_len > tbp->len)
1399*1a3d31e3SAndroid Build Coastguard Worker 				break;
1400*1a3d31e3SAndroid Build Coastguard Worker 
1401*1a3d31e3SAndroid Build Coastguard Worker 			off += t_len;
1402*1a3d31e3SAndroid Build Coastguard Worker 			nevents++;
1403*1a3d31e3SAndroid Build Coastguard Worker 		}
1404*1a3d31e3SAndroid Build Coastguard Worker 		if (nevents)
1405*1a3d31e3SAndroid Build Coastguard Worker 			pdc_nev_update(tbp->dpp, tbp->cpu, nevents);
1406*1a3d31e3SAndroid Build Coastguard Worker 
1407*1a3d31e3SAndroid Build Coastguard Worker 		/*
1408*1a3d31e3SAndroid Build Coastguard Worker 		 * Write any full set of traces, any remaining data is kept
1409*1a3d31e3SAndroid Build Coastguard Worker 		 * for the next pass.
1410*1a3d31e3SAndroid Build Coastguard Worker 		 */
1411*1a3d31e3SAndroid Build Coastguard Worker 		if (off) {
1412*1a3d31e3SAndroid Build Coastguard Worker 			if (write_data(tbp->buf, off) || off == tbp->len) {
1413*1a3d31e3SAndroid Build Coastguard Worker 				free(tbp);
1414*1a3d31e3SAndroid Build Coastguard Worker 				prev = NULL;
1415*1a3d31e3SAndroid Build Coastguard Worker 			}
1416*1a3d31e3SAndroid Build Coastguard Worker 			else {
1417*1a3d31e3SAndroid Build Coastguard Worker 				/*
1418*1a3d31e3SAndroid Build Coastguard Worker 				 * Move valid data to beginning of buffer
1419*1a3d31e3SAndroid Build Coastguard Worker 				 */
1420*1a3d31e3SAndroid Build Coastguard Worker 				tbp->len -= off;
1421*1a3d31e3SAndroid Build Coastguard Worker 				memmove(tbp->buf, tbp->buf + off, tbp->len);
1422*1a3d31e3SAndroid Build Coastguard Worker 				prev = tbp;
1423*1a3d31e3SAndroid Build Coastguard Worker 			}
1424*1a3d31e3SAndroid Build Coastguard Worker 		} else
1425*1a3d31e3SAndroid Build Coastguard Worker 			prev = tbp;
1426*1a3d31e3SAndroid Build Coastguard Worker 	}
1427*1a3d31e3SAndroid Build Coastguard Worker 	hd->prev = prev;
1428*1a3d31e3SAndroid Build Coastguard Worker 
1429*1a3d31e3SAndroid Build Coastguard Worker 	return entries_handled;
1430*1a3d31e3SAndroid Build Coastguard Worker }
1431*1a3d31e3SAndroid Build Coastguard Worker 
__process_trace_bufs(void)1432*1a3d31e3SAndroid Build Coastguard Worker static void __process_trace_bufs(void)
1433*1a3d31e3SAndroid Build Coastguard Worker {
1434*1a3d31e3SAndroid Build Coastguard Worker 	int cpu;
1435*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1436*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head list;
1437*1a3d31e3SAndroid Build Coastguard Worker 	int handled = 0;
1438*1a3d31e3SAndroid Build Coastguard Worker 
1439*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1440*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1441*1a3d31e3SAndroid Build Coastguard Worker 		struct tracer_devpath_head *hd = dpp->heads;
1442*1a3d31e3SAndroid Build Coastguard Worker 
1443*1a3d31e3SAndroid Build Coastguard Worker 		for (cpu = 0; cpu < max_cpus; cpu++, hd++) {
1444*1a3d31e3SAndroid Build Coastguard Worker 			pthread_mutex_lock(&hd->mutex);
1445*1a3d31e3SAndroid Build Coastguard Worker 			if (list_empty(&hd->head)) {
1446*1a3d31e3SAndroid Build Coastguard Worker 				pthread_mutex_unlock(&hd->mutex);
1447*1a3d31e3SAndroid Build Coastguard Worker 				continue;
1448*1a3d31e3SAndroid Build Coastguard Worker 			}
1449*1a3d31e3SAndroid Build Coastguard Worker 
1450*1a3d31e3SAndroid Build Coastguard Worker 			list_replace_init(&hd->head, &list);
1451*1a3d31e3SAndroid Build Coastguard Worker 			pthread_mutex_unlock(&hd->mutex);
1452*1a3d31e3SAndroid Build Coastguard Worker 
1453*1a3d31e3SAndroid Build Coastguard Worker 			handled += handle_list(hd, &list);
1454*1a3d31e3SAndroid Build Coastguard Worker 		}
1455*1a3d31e3SAndroid Build Coastguard Worker 	}
1456*1a3d31e3SAndroid Build Coastguard Worker 
1457*1a3d31e3SAndroid Build Coastguard Worker 	if (handled)
1458*1a3d31e3SAndroid Build Coastguard Worker 		decr_entries(handled);
1459*1a3d31e3SAndroid Build Coastguard Worker }
1460*1a3d31e3SAndroid Build Coastguard Worker 
process_trace_bufs(void)1461*1a3d31e3SAndroid Build Coastguard Worker static void process_trace_bufs(void)
1462*1a3d31e3SAndroid Build Coastguard Worker {
1463*1a3d31e3SAndroid Build Coastguard Worker 	while (wait_empty_entries())
1464*1a3d31e3SAndroid Build Coastguard Worker 		__process_trace_bufs();
1465*1a3d31e3SAndroid Build Coastguard Worker }
1466*1a3d31e3SAndroid Build Coastguard Worker 
clean_trace_bufs(void)1467*1a3d31e3SAndroid Build Coastguard Worker static void clean_trace_bufs(void)
1468*1a3d31e3SAndroid Build Coastguard Worker {
1469*1a3d31e3SAndroid Build Coastguard Worker 	/*
1470*1a3d31e3SAndroid Build Coastguard Worker 	 * No mutex needed here: we're only reading from the lists,
1471*1a3d31e3SAndroid Build Coastguard Worker 	 * tracers are done
1472*1a3d31e3SAndroid Build Coastguard Worker 	 */
1473*1a3d31e3SAndroid Build Coastguard Worker 	while (dp_entries)
1474*1a3d31e3SAndroid Build Coastguard Worker 		__process_trace_bufs();
1475*1a3d31e3SAndroid Build Coastguard Worker }
1476*1a3d31e3SAndroid Build Coastguard Worker 
read_err(int cpu,char * ifn)1477*1a3d31e3SAndroid Build Coastguard Worker static inline void read_err(int cpu, char *ifn)
1478*1a3d31e3SAndroid Build Coastguard Worker {
1479*1a3d31e3SAndroid Build Coastguard Worker 	if (errno != EAGAIN)
1480*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "Thread %d failed read of %s: %d/%s\n",
1481*1a3d31e3SAndroid Build Coastguard Worker 			cpu, ifn, errno, strerror(errno));
1482*1a3d31e3SAndroid Build Coastguard Worker }
1483*1a3d31e3SAndroid Build Coastguard Worker 
net_sendfile(struct io_info * iop)1484*1a3d31e3SAndroid Build Coastguard Worker static int net_sendfile(struct io_info *iop)
1485*1a3d31e3SAndroid Build Coastguard Worker {
1486*1a3d31e3SAndroid Build Coastguard Worker 	int ret;
1487*1a3d31e3SAndroid Build Coastguard Worker 
1488*1a3d31e3SAndroid Build Coastguard Worker 	ret = sendfile(iop->ofd, iop->ifd, NULL, iop->ready);
1489*1a3d31e3SAndroid Build Coastguard Worker 	if (ret < 0) {
1490*1a3d31e3SAndroid Build Coastguard Worker 		perror("sendfile");
1491*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1492*1a3d31e3SAndroid Build Coastguard Worker 	} else if (ret < (int)iop->ready) {
1493*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "short sendfile send (%d of %d)\n",
1494*1a3d31e3SAndroid Build Coastguard Worker 			ret, iop->ready);
1495*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1496*1a3d31e3SAndroid Build Coastguard Worker 	}
1497*1a3d31e3SAndroid Build Coastguard Worker 
1498*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1499*1a3d31e3SAndroid Build Coastguard Worker }
1500*1a3d31e3SAndroid Build Coastguard Worker 
net_sendfile_data(struct tracer * tp,struct io_info * iop)1501*1a3d31e3SAndroid Build Coastguard Worker static inline int net_sendfile_data(struct tracer *tp, struct io_info *iop)
1502*1a3d31e3SAndroid Build Coastguard Worker {
1503*1a3d31e3SAndroid Build Coastguard Worker 	struct devpath *dpp = iop->dpp;
1504*1a3d31e3SAndroid Build Coastguard Worker 
1505*1a3d31e3SAndroid Build Coastguard Worker 	if (net_send_header(iop->ofd, tp->cpu, dpp->buts_name, iop->ready))
1506*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1507*1a3d31e3SAndroid Build Coastguard Worker 	return net_sendfile(iop);
1508*1a3d31e3SAndroid Build Coastguard Worker }
1509*1a3d31e3SAndroid Build Coastguard Worker 
fill_ofname(char * dst,int dstlen,char * subdir,char * buts_name,int cpu)1510*1a3d31e3SAndroid Build Coastguard Worker static int fill_ofname(char *dst, int dstlen, char *subdir, char *buts_name,
1511*1a3d31e3SAndroid Build Coastguard Worker 		       int cpu)
1512*1a3d31e3SAndroid Build Coastguard Worker {
1513*1a3d31e3SAndroid Build Coastguard Worker 	int len;
1514*1a3d31e3SAndroid Build Coastguard Worker 	struct stat sb;
1515*1a3d31e3SAndroid Build Coastguard Worker 
1516*1a3d31e3SAndroid Build Coastguard Worker 	if (output_dir)
1517*1a3d31e3SAndroid Build Coastguard Worker 		len = snprintf(dst, dstlen, "%s/", output_dir);
1518*1a3d31e3SAndroid Build Coastguard Worker 	else
1519*1a3d31e3SAndroid Build Coastguard Worker 		len = snprintf(dst, dstlen, "./");
1520*1a3d31e3SAndroid Build Coastguard Worker 
1521*1a3d31e3SAndroid Build Coastguard Worker 	if (subdir)
1522*1a3d31e3SAndroid Build Coastguard Worker 		len += snprintf(dst + len, dstlen - len, "%s", subdir);
1523*1a3d31e3SAndroid Build Coastguard Worker 
1524*1a3d31e3SAndroid Build Coastguard Worker 	if (stat(dst, &sb) < 0) {
1525*1a3d31e3SAndroid Build Coastguard Worker 		if (errno != ENOENT) {
1526*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr,
1527*1a3d31e3SAndroid Build Coastguard Worker 				"Destination dir %s stat failed: %d/%s\n",
1528*1a3d31e3SAndroid Build Coastguard Worker 				dst, errno, strerror(errno));
1529*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
1530*1a3d31e3SAndroid Build Coastguard Worker 		}
1531*1a3d31e3SAndroid Build Coastguard Worker 		/*
1532*1a3d31e3SAndroid Build Coastguard Worker 		 * There is no synchronization between multiple threads
1533*1a3d31e3SAndroid Build Coastguard Worker 		 * trying to create the directory at once.  It's harmless
1534*1a3d31e3SAndroid Build Coastguard Worker 		 * to let them try, so just detect the problem and move on.
1535*1a3d31e3SAndroid Build Coastguard Worker 		 */
1536*1a3d31e3SAndroid Build Coastguard Worker 		if (mkdir(dst, 0755) < 0 && errno != EEXIST) {
1537*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr,
1538*1a3d31e3SAndroid Build Coastguard Worker 				"Destination dir %s can't be made: %d/%s\n",
1539*1a3d31e3SAndroid Build Coastguard Worker 				dst, errno, strerror(errno));
1540*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
1541*1a3d31e3SAndroid Build Coastguard Worker 		}
1542*1a3d31e3SAndroid Build Coastguard Worker 	}
1543*1a3d31e3SAndroid Build Coastguard Worker 
1544*1a3d31e3SAndroid Build Coastguard Worker 	if (output_name)
1545*1a3d31e3SAndroid Build Coastguard Worker 		snprintf(dst + len, dstlen - len, "%s.blktrace.%d",
1546*1a3d31e3SAndroid Build Coastguard Worker 			 output_name, cpu);
1547*1a3d31e3SAndroid Build Coastguard Worker 	else
1548*1a3d31e3SAndroid Build Coastguard Worker 		snprintf(dst + len, dstlen - len, "%s.blktrace.%d",
1549*1a3d31e3SAndroid Build Coastguard Worker 			 buts_name, cpu);
1550*1a3d31e3SAndroid Build Coastguard Worker 
1551*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1552*1a3d31e3SAndroid Build Coastguard Worker }
1553*1a3d31e3SAndroid Build Coastguard Worker 
set_vbuf(struct io_info * iop,int mode,size_t size)1554*1a3d31e3SAndroid Build Coastguard Worker static int set_vbuf(struct io_info *iop, int mode, size_t size)
1555*1a3d31e3SAndroid Build Coastguard Worker {
1556*1a3d31e3SAndroid Build Coastguard Worker 	iop->obuf = malloc(size);
1557*1a3d31e3SAndroid Build Coastguard Worker 	if (setvbuf(iop->ofp, iop->obuf, mode, size) < 0) {
1558*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "setvbuf(%s, %d) failed: %d/%s\n",
1559*1a3d31e3SAndroid Build Coastguard Worker 			iop->dpp->path, (int)size, errno,
1560*1a3d31e3SAndroid Build Coastguard Worker 			strerror(errno));
1561*1a3d31e3SAndroid Build Coastguard Worker 		free(iop->obuf);
1562*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1563*1a3d31e3SAndroid Build Coastguard Worker 	}
1564*1a3d31e3SAndroid Build Coastguard Worker 
1565*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1566*1a3d31e3SAndroid Build Coastguard Worker }
1567*1a3d31e3SAndroid Build Coastguard Worker 
iop_open(struct io_info * iop,int cpu)1568*1a3d31e3SAndroid Build Coastguard Worker static int iop_open(struct io_info *iop, int cpu)
1569*1a3d31e3SAndroid Build Coastguard Worker {
1570*1a3d31e3SAndroid Build Coastguard Worker 	char hostdir[MAXPATHLEN + 64];
1571*1a3d31e3SAndroid Build Coastguard Worker 
1572*1a3d31e3SAndroid Build Coastguard Worker 	iop->ofd = -1;
1573*1a3d31e3SAndroid Build Coastguard Worker 	if (net_mode == Net_server) {
1574*1a3d31e3SAndroid Build Coastguard Worker 		struct cl_conn *nc = iop->nc;
1575*1a3d31e3SAndroid Build Coastguard Worker 		int len;
1576*1a3d31e3SAndroid Build Coastguard Worker 
1577*1a3d31e3SAndroid Build Coastguard Worker 		len = snprintf(hostdir, sizeof(hostdir), "%s-",
1578*1a3d31e3SAndroid Build Coastguard Worker 			       nc->ch->hostname);
1579*1a3d31e3SAndroid Build Coastguard Worker 		len += strftime(hostdir + len, sizeof(hostdir) - len, "%F-%T/",
1580*1a3d31e3SAndroid Build Coastguard Worker 				gmtime(&iop->dpp->cl_connect_time));
1581*1a3d31e3SAndroid Build Coastguard Worker 	} else {
1582*1a3d31e3SAndroid Build Coastguard Worker 		hostdir[0] = 0;
1583*1a3d31e3SAndroid Build Coastguard Worker 	}
1584*1a3d31e3SAndroid Build Coastguard Worker 
1585*1a3d31e3SAndroid Build Coastguard Worker 	if (fill_ofname(iop->ofn, sizeof(iop->ofn), hostdir,
1586*1a3d31e3SAndroid Build Coastguard Worker 			iop->dpp->buts_name, cpu))
1587*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1588*1a3d31e3SAndroid Build Coastguard Worker 
1589*1a3d31e3SAndroid Build Coastguard Worker 	iop->ofp = my_fopen(iop->ofn, "w+");
1590*1a3d31e3SAndroid Build Coastguard Worker 	if (iop->ofp == NULL) {
1591*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "Open output file %s failed: %d/%s\n",
1592*1a3d31e3SAndroid Build Coastguard Worker 			iop->ofn, errno, strerror(errno));
1593*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1594*1a3d31e3SAndroid Build Coastguard Worker 	}
1595*1a3d31e3SAndroid Build Coastguard Worker 
1596*1a3d31e3SAndroid Build Coastguard Worker 	if (set_vbuf(iop, _IOLBF, FILE_VBUF_SIZE)) {
1597*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "set_vbuf for file %s failed: %d/%s\n",
1598*1a3d31e3SAndroid Build Coastguard Worker 			iop->ofn, errno, strerror(errno));
1599*1a3d31e3SAndroid Build Coastguard Worker 		fclose(iop->ofp);
1600*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1601*1a3d31e3SAndroid Build Coastguard Worker 	}
1602*1a3d31e3SAndroid Build Coastguard Worker 
1603*1a3d31e3SAndroid Build Coastguard Worker 	iop->ofd = fileno(iop->ofp);
1604*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1605*1a3d31e3SAndroid Build Coastguard Worker }
1606*1a3d31e3SAndroid Build Coastguard Worker 
close_iop(struct io_info * iop)1607*1a3d31e3SAndroid Build Coastguard Worker static void close_iop(struct io_info *iop)
1608*1a3d31e3SAndroid Build Coastguard Worker {
1609*1a3d31e3SAndroid Build Coastguard Worker 	struct mmap_info *mip = &iop->mmap_info;
1610*1a3d31e3SAndroid Build Coastguard Worker 
1611*1a3d31e3SAndroid Build Coastguard Worker 	if (mip->fs_buf)
1612*1a3d31e3SAndroid Build Coastguard Worker 		munmap(mip->fs_buf, mip->fs_buf_len);
1613*1a3d31e3SAndroid Build Coastguard Worker 
1614*1a3d31e3SAndroid Build Coastguard Worker 	if (!piped_output) {
1615*1a3d31e3SAndroid Build Coastguard Worker 		if (ftruncate(fileno(iop->ofp), mip->fs_size) < 0) {
1616*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr,
1617*1a3d31e3SAndroid Build Coastguard Worker 				"Ignoring err: ftruncate(%s): %d/%s\n",
1618*1a3d31e3SAndroid Build Coastguard Worker 				iop->ofn, errno, strerror(errno));
1619*1a3d31e3SAndroid Build Coastguard Worker 		}
1620*1a3d31e3SAndroid Build Coastguard Worker 	}
1621*1a3d31e3SAndroid Build Coastguard Worker 
1622*1a3d31e3SAndroid Build Coastguard Worker 	if (iop->ofp)
1623*1a3d31e3SAndroid Build Coastguard Worker 		fclose(iop->ofp);
1624*1a3d31e3SAndroid Build Coastguard Worker 	if (iop->obuf)
1625*1a3d31e3SAndroid Build Coastguard Worker 		free(iop->obuf);
1626*1a3d31e3SAndroid Build Coastguard Worker }
1627*1a3d31e3SAndroid Build Coastguard Worker 
close_ios(struct tracer * tp)1628*1a3d31e3SAndroid Build Coastguard Worker static void close_ios(struct tracer *tp)
1629*1a3d31e3SAndroid Build Coastguard Worker {
1630*1a3d31e3SAndroid Build Coastguard Worker 	while (tp->nios > 0) {
1631*1a3d31e3SAndroid Build Coastguard Worker 		struct io_info *iop = &tp->ios[--tp->nios];
1632*1a3d31e3SAndroid Build Coastguard Worker 
1633*1a3d31e3SAndroid Build Coastguard Worker 		iop->dpp->drops = get_drops(iop->dpp);
1634*1a3d31e3SAndroid Build Coastguard Worker 		if (iop->ifd >= 0)
1635*1a3d31e3SAndroid Build Coastguard Worker 			close(iop->ifd);
1636*1a3d31e3SAndroid Build Coastguard Worker 
1637*1a3d31e3SAndroid Build Coastguard Worker 		if (iop->ofp)
1638*1a3d31e3SAndroid Build Coastguard Worker 			close_iop(iop);
1639*1a3d31e3SAndroid Build Coastguard Worker 		else if (iop->ofd >= 0) {
1640*1a3d31e3SAndroid Build Coastguard Worker 			struct devpath *dpp = iop->dpp;
1641*1a3d31e3SAndroid Build Coastguard Worker 
1642*1a3d31e3SAndroid Build Coastguard Worker 			net_send_close(iop->ofd, dpp->buts_name, dpp->drops);
1643*1a3d31e3SAndroid Build Coastguard Worker 			net_close_connection(&iop->ofd);
1644*1a3d31e3SAndroid Build Coastguard Worker 		}
1645*1a3d31e3SAndroid Build Coastguard Worker 	}
1646*1a3d31e3SAndroid Build Coastguard Worker 
1647*1a3d31e3SAndroid Build Coastguard Worker 	free(tp->ios);
1648*1a3d31e3SAndroid Build Coastguard Worker 	free(tp->pfds);
1649*1a3d31e3SAndroid Build Coastguard Worker }
1650*1a3d31e3SAndroid Build Coastguard Worker 
open_ios(struct tracer * tp)1651*1a3d31e3SAndroid Build Coastguard Worker static int open_ios(struct tracer *tp)
1652*1a3d31e3SAndroid Build Coastguard Worker {
1653*1a3d31e3SAndroid Build Coastguard Worker 	struct pollfd *pfd;
1654*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *iop;
1655*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1656*1a3d31e3SAndroid Build Coastguard Worker 
1657*1a3d31e3SAndroid Build Coastguard Worker 	tp->ios = calloc(ndevs, sizeof(struct io_info));
1658*1a3d31e3SAndroid Build Coastguard Worker 	memset(tp->ios, 0, ndevs * sizeof(struct io_info));
1659*1a3d31e3SAndroid Build Coastguard Worker 
1660*1a3d31e3SAndroid Build Coastguard Worker 	tp->pfds = calloc(ndevs, sizeof(struct pollfd));
1661*1a3d31e3SAndroid Build Coastguard Worker 	memset(tp->pfds, 0, ndevs * sizeof(struct pollfd));
1662*1a3d31e3SAndroid Build Coastguard Worker 
1663*1a3d31e3SAndroid Build Coastguard Worker 	tp->nios = 0;
1664*1a3d31e3SAndroid Build Coastguard Worker 	iop = tp->ios;
1665*1a3d31e3SAndroid Build Coastguard Worker 	pfd = tp->pfds;
1666*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1667*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1668*1a3d31e3SAndroid Build Coastguard Worker 
1669*1a3d31e3SAndroid Build Coastguard Worker 		iop->dpp = dpp;
1670*1a3d31e3SAndroid Build Coastguard Worker 		iop->ofd = -1;
1671*1a3d31e3SAndroid Build Coastguard Worker 		snprintf(iop->ifn, sizeof(iop->ifn), "%s/block/%s/trace%d",
1672*1a3d31e3SAndroid Build Coastguard Worker 			debugfs_path, dpp->buts_name, tp->cpu);
1673*1a3d31e3SAndroid Build Coastguard Worker 
1674*1a3d31e3SAndroid Build Coastguard Worker 		iop->ifd = my_open(iop->ifn, O_RDONLY | O_NONBLOCK);
1675*1a3d31e3SAndroid Build Coastguard Worker 		if (iop->ifd < 0) {
1676*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr, "Thread %d failed open %s: %d/%s\n",
1677*1a3d31e3SAndroid Build Coastguard Worker 				tp->cpu, iop->ifn, errno, strerror(errno));
1678*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
1679*1a3d31e3SAndroid Build Coastguard Worker 		}
1680*1a3d31e3SAndroid Build Coastguard Worker 
1681*1a3d31e3SAndroid Build Coastguard Worker 		init_mmap_info(&iop->mmap_info);
1682*1a3d31e3SAndroid Build Coastguard Worker 
1683*1a3d31e3SAndroid Build Coastguard Worker 		pfd->fd = iop->ifd;
1684*1a3d31e3SAndroid Build Coastguard Worker 		pfd->events = POLLIN;
1685*1a3d31e3SAndroid Build Coastguard Worker 
1686*1a3d31e3SAndroid Build Coastguard Worker 		if (piped_output)
1687*1a3d31e3SAndroid Build Coastguard Worker 			;
1688*1a3d31e3SAndroid Build Coastguard Worker 		else if (net_client_use_sendfile()) {
1689*1a3d31e3SAndroid Build Coastguard Worker 			iop->ofd = net_setup_client();
1690*1a3d31e3SAndroid Build Coastguard Worker 			if (iop->ofd < 0)
1691*1a3d31e3SAndroid Build Coastguard Worker 				goto err;
1692*1a3d31e3SAndroid Build Coastguard Worker 			net_send_open(iop->ofd, tp->cpu, dpp->buts_name);
1693*1a3d31e3SAndroid Build Coastguard Worker 		} else if (net_mode == Net_none) {
1694*1a3d31e3SAndroid Build Coastguard Worker 			if (iop_open(iop, tp->cpu))
1695*1a3d31e3SAndroid Build Coastguard Worker 				goto err;
1696*1a3d31e3SAndroid Build Coastguard Worker 		} else {
1697*1a3d31e3SAndroid Build Coastguard Worker 			/*
1698*1a3d31e3SAndroid Build Coastguard Worker 			 * This ensures that the server knows about all
1699*1a3d31e3SAndroid Build Coastguard Worker 			 * connections & devices before _any_ closes
1700*1a3d31e3SAndroid Build Coastguard Worker 			 */
1701*1a3d31e3SAndroid Build Coastguard Worker 			net_send_open(cl_fds[tp->cpu], tp->cpu, dpp->buts_name);
1702*1a3d31e3SAndroid Build Coastguard Worker 		}
1703*1a3d31e3SAndroid Build Coastguard Worker 
1704*1a3d31e3SAndroid Build Coastguard Worker 		pfd++;
1705*1a3d31e3SAndroid Build Coastguard Worker 		iop++;
1706*1a3d31e3SAndroid Build Coastguard Worker 		tp->nios++;
1707*1a3d31e3SAndroid Build Coastguard Worker 	}
1708*1a3d31e3SAndroid Build Coastguard Worker 
1709*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1710*1a3d31e3SAndroid Build Coastguard Worker 
1711*1a3d31e3SAndroid Build Coastguard Worker err:
1712*1a3d31e3SAndroid Build Coastguard Worker 	close(iop->ifd);	/* tp->nios _not_ bumped */
1713*1a3d31e3SAndroid Build Coastguard Worker 	close_ios(tp);
1714*1a3d31e3SAndroid Build Coastguard Worker 	return 1;
1715*1a3d31e3SAndroid Build Coastguard Worker }
1716*1a3d31e3SAndroid Build Coastguard Worker 
handle_pfds_file(struct tracer * tp,int nevs,int force_read)1717*1a3d31e3SAndroid Build Coastguard Worker static int handle_pfds_file(struct tracer *tp, int nevs, int force_read)
1718*1a3d31e3SAndroid Build Coastguard Worker {
1719*1a3d31e3SAndroid Build Coastguard Worker 	struct mmap_info *mip;
1720*1a3d31e3SAndroid Build Coastguard Worker 	int i, ret, nentries = 0;
1721*1a3d31e3SAndroid Build Coastguard Worker 	struct pollfd *pfd = tp->pfds;
1722*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *iop = tp->ios;
1723*1a3d31e3SAndroid Build Coastguard Worker 
1724*1a3d31e3SAndroid Build Coastguard Worker 	for (i = 0; nevs > 0 && i < ndevs; i++, pfd++, iop++) {
1725*1a3d31e3SAndroid Build Coastguard Worker 		if (pfd->revents & POLLIN || force_read) {
1726*1a3d31e3SAndroid Build Coastguard Worker 			mip = &iop->mmap_info;
1727*1a3d31e3SAndroid Build Coastguard Worker 
1728*1a3d31e3SAndroid Build Coastguard Worker 			ret = setup_mmap(iop->ofd, buf_size, mip, tp);
1729*1a3d31e3SAndroid Build Coastguard Worker 			if (ret < 0) {
1730*1a3d31e3SAndroid Build Coastguard Worker 				pfd->events = 0;
1731*1a3d31e3SAndroid Build Coastguard Worker 				break;
1732*1a3d31e3SAndroid Build Coastguard Worker 			}
1733*1a3d31e3SAndroid Build Coastguard Worker 
1734*1a3d31e3SAndroid Build Coastguard Worker 			ret = read(iop->ifd, mip->fs_buf + mip->fs_off,
1735*1a3d31e3SAndroid Build Coastguard Worker 				   buf_size);
1736*1a3d31e3SAndroid Build Coastguard Worker 			if (ret > 0) {
1737*1a3d31e3SAndroid Build Coastguard Worker 				pdc_dr_update(iop->dpp, tp->cpu, ret);
1738*1a3d31e3SAndroid Build Coastguard Worker 				mip->fs_size += ret;
1739*1a3d31e3SAndroid Build Coastguard Worker 				mip->fs_off += ret;
1740*1a3d31e3SAndroid Build Coastguard Worker 				nentries++;
1741*1a3d31e3SAndroid Build Coastguard Worker 			} else if (ret == 0) {
1742*1a3d31e3SAndroid Build Coastguard Worker 				/*
1743*1a3d31e3SAndroid Build Coastguard Worker 				 * Short reads after we're done stop us
1744*1a3d31e3SAndroid Build Coastguard Worker 				 * from trying reads.
1745*1a3d31e3SAndroid Build Coastguard Worker 				 */
1746*1a3d31e3SAndroid Build Coastguard Worker 				if (tp->is_done)
1747*1a3d31e3SAndroid Build Coastguard Worker 					clear_events(pfd);
1748*1a3d31e3SAndroid Build Coastguard Worker 			} else {
1749*1a3d31e3SAndroid Build Coastguard Worker 				read_err(tp->cpu, iop->ifn);
1750*1a3d31e3SAndroid Build Coastguard Worker 				if (errno != EAGAIN || tp->is_done)
1751*1a3d31e3SAndroid Build Coastguard Worker 					clear_events(pfd);
1752*1a3d31e3SAndroid Build Coastguard Worker 			}
1753*1a3d31e3SAndroid Build Coastguard Worker 			nevs--;
1754*1a3d31e3SAndroid Build Coastguard Worker 		}
1755*1a3d31e3SAndroid Build Coastguard Worker 	}
1756*1a3d31e3SAndroid Build Coastguard Worker 
1757*1a3d31e3SAndroid Build Coastguard Worker 	return nentries;
1758*1a3d31e3SAndroid Build Coastguard Worker }
1759*1a3d31e3SAndroid Build Coastguard Worker 
handle_pfds_netclient(struct tracer * tp,int nevs,int force_read)1760*1a3d31e3SAndroid Build Coastguard Worker static int handle_pfds_netclient(struct tracer *tp, int nevs, int force_read)
1761*1a3d31e3SAndroid Build Coastguard Worker {
1762*1a3d31e3SAndroid Build Coastguard Worker 	struct stat sb;
1763*1a3d31e3SAndroid Build Coastguard Worker 	int i, nentries = 0;
1764*1a3d31e3SAndroid Build Coastguard Worker 	struct pollfd *pfd = tp->pfds;
1765*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *iop = tp->ios;
1766*1a3d31e3SAndroid Build Coastguard Worker 
1767*1a3d31e3SAndroid Build Coastguard Worker 	for (i = 0; i < ndevs; i++, pfd++, iop++) {
1768*1a3d31e3SAndroid Build Coastguard Worker 		if (pfd->revents & POLLIN || force_read) {
1769*1a3d31e3SAndroid Build Coastguard Worker 			if (fstat(iop->ifd, &sb) < 0) {
1770*1a3d31e3SAndroid Build Coastguard Worker 				perror(iop->ifn);
1771*1a3d31e3SAndroid Build Coastguard Worker 				pfd->events = 0;
1772*1a3d31e3SAndroid Build Coastguard Worker 			} else if (sb.st_size > (off_t)iop->data_queued) {
1773*1a3d31e3SAndroid Build Coastguard Worker 				iop->ready = sb.st_size - iop->data_queued;
1774*1a3d31e3SAndroid Build Coastguard Worker 				iop->data_queued = sb.st_size;
1775*1a3d31e3SAndroid Build Coastguard Worker 
1776*1a3d31e3SAndroid Build Coastguard Worker 				if (!net_sendfile_data(tp, iop)) {
1777*1a3d31e3SAndroid Build Coastguard Worker 					pdc_dr_update(iop->dpp, tp->cpu,
1778*1a3d31e3SAndroid Build Coastguard Worker 						      iop->ready);
1779*1a3d31e3SAndroid Build Coastguard Worker 					nentries++;
1780*1a3d31e3SAndroid Build Coastguard Worker 				} else
1781*1a3d31e3SAndroid Build Coastguard Worker 					clear_events(pfd);
1782*1a3d31e3SAndroid Build Coastguard Worker 			}
1783*1a3d31e3SAndroid Build Coastguard Worker 			if (--nevs == 0)
1784*1a3d31e3SAndroid Build Coastguard Worker 				break;
1785*1a3d31e3SAndroid Build Coastguard Worker 		}
1786*1a3d31e3SAndroid Build Coastguard Worker 	}
1787*1a3d31e3SAndroid Build Coastguard Worker 
1788*1a3d31e3SAndroid Build Coastguard Worker 	if (nentries)
1789*1a3d31e3SAndroid Build Coastguard Worker 		incr_entries(nentries);
1790*1a3d31e3SAndroid Build Coastguard Worker 
1791*1a3d31e3SAndroid Build Coastguard Worker 	return nentries;
1792*1a3d31e3SAndroid Build Coastguard Worker }
1793*1a3d31e3SAndroid Build Coastguard Worker 
handle_pfds_entries(struct tracer * tp,int nevs,int force_read)1794*1a3d31e3SAndroid Build Coastguard Worker static int handle_pfds_entries(struct tracer *tp, int nevs, int force_read)
1795*1a3d31e3SAndroid Build Coastguard Worker {
1796*1a3d31e3SAndroid Build Coastguard Worker 	int i, nentries = 0;
1797*1a3d31e3SAndroid Build Coastguard Worker 	struct trace_buf *tbp;
1798*1a3d31e3SAndroid Build Coastguard Worker 	struct pollfd *pfd = tp->pfds;
1799*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *iop = tp->ios;
1800*1a3d31e3SAndroid Build Coastguard Worker 
1801*1a3d31e3SAndroid Build Coastguard Worker 	tbp = alloc_trace_buf(tp->cpu, buf_size);
1802*1a3d31e3SAndroid Build Coastguard Worker 	for (i = 0; i < ndevs; i++, pfd++, iop++) {
1803*1a3d31e3SAndroid Build Coastguard Worker 		if (pfd->revents & POLLIN || force_read) {
1804*1a3d31e3SAndroid Build Coastguard Worker 			tbp->len = read(iop->ifd, tbp->buf, buf_size);
1805*1a3d31e3SAndroid Build Coastguard Worker 			if (tbp->len > 0) {
1806*1a3d31e3SAndroid Build Coastguard Worker 				pdc_dr_update(iop->dpp, tp->cpu, tbp->len);
1807*1a3d31e3SAndroid Build Coastguard Worker 				add_trace_buf(iop->dpp, tp->cpu, &tbp);
1808*1a3d31e3SAndroid Build Coastguard Worker 				nentries++;
1809*1a3d31e3SAndroid Build Coastguard Worker 			} else if (tbp->len == 0) {
1810*1a3d31e3SAndroid Build Coastguard Worker 				/*
1811*1a3d31e3SAndroid Build Coastguard Worker 				 * Short reads after we're done stop us
1812*1a3d31e3SAndroid Build Coastguard Worker 				 * from trying reads.
1813*1a3d31e3SAndroid Build Coastguard Worker 				 */
1814*1a3d31e3SAndroid Build Coastguard Worker 				if (tp->is_done)
1815*1a3d31e3SAndroid Build Coastguard Worker 					clear_events(pfd);
1816*1a3d31e3SAndroid Build Coastguard Worker 			} else {
1817*1a3d31e3SAndroid Build Coastguard Worker 				read_err(tp->cpu, iop->ifn);
1818*1a3d31e3SAndroid Build Coastguard Worker 				if (errno != EAGAIN || tp->is_done)
1819*1a3d31e3SAndroid Build Coastguard Worker 					clear_events(pfd);
1820*1a3d31e3SAndroid Build Coastguard Worker 			}
1821*1a3d31e3SAndroid Build Coastguard Worker 			if (!piped_output && --nevs == 0)
1822*1a3d31e3SAndroid Build Coastguard Worker 				break;
1823*1a3d31e3SAndroid Build Coastguard Worker 		}
1824*1a3d31e3SAndroid Build Coastguard Worker 	}
1825*1a3d31e3SAndroid Build Coastguard Worker 	free(tbp);
1826*1a3d31e3SAndroid Build Coastguard Worker 
1827*1a3d31e3SAndroid Build Coastguard Worker 	if (nentries)
1828*1a3d31e3SAndroid Build Coastguard Worker 		incr_entries(nentries);
1829*1a3d31e3SAndroid Build Coastguard Worker 
1830*1a3d31e3SAndroid Build Coastguard Worker 	return nentries;
1831*1a3d31e3SAndroid Build Coastguard Worker }
1832*1a3d31e3SAndroid Build Coastguard Worker 
thread_main(void * arg)1833*1a3d31e3SAndroid Build Coastguard Worker static void *thread_main(void *arg)
1834*1a3d31e3SAndroid Build Coastguard Worker {
1835*1a3d31e3SAndroid Build Coastguard Worker 	int ret, ndone, to_val;
1836*1a3d31e3SAndroid Build Coastguard Worker 	struct tracer *tp = arg;
1837*1a3d31e3SAndroid Build Coastguard Worker 
1838*1a3d31e3SAndroid Build Coastguard Worker 	ret = lock_on_cpu(tp->cpu);
1839*1a3d31e3SAndroid Build Coastguard Worker 	if (ret)
1840*1a3d31e3SAndroid Build Coastguard Worker 		goto err;
1841*1a3d31e3SAndroid Build Coastguard Worker 
1842*1a3d31e3SAndroid Build Coastguard Worker 	ret = open_ios(tp);
1843*1a3d31e3SAndroid Build Coastguard Worker 	if (ret)
1844*1a3d31e3SAndroid Build Coastguard Worker 		goto err;
1845*1a3d31e3SAndroid Build Coastguard Worker 
1846*1a3d31e3SAndroid Build Coastguard Worker 	if (piped_output)
1847*1a3d31e3SAndroid Build Coastguard Worker 		to_val = 50;		/* Frequent partial handles */
1848*1a3d31e3SAndroid Build Coastguard Worker 	else
1849*1a3d31e3SAndroid Build Coastguard Worker 		to_val = 500;		/* 1/2 second intervals */
1850*1a3d31e3SAndroid Build Coastguard Worker 
1851*1a3d31e3SAndroid Build Coastguard Worker 
1852*1a3d31e3SAndroid Build Coastguard Worker 	tracer_signal_ready(tp, Th_running, 0);
1853*1a3d31e3SAndroid Build Coastguard Worker 	tracer_wait_unblock(tp);
1854*1a3d31e3SAndroid Build Coastguard Worker 
1855*1a3d31e3SAndroid Build Coastguard Worker 	while (!tp->is_done) {
1856*1a3d31e3SAndroid Build Coastguard Worker 		ndone = poll(tp->pfds, ndevs, to_val);
1857*1a3d31e3SAndroid Build Coastguard Worker 		if (ndone || piped_output)
1858*1a3d31e3SAndroid Build Coastguard Worker 			(void)handle_pfds(tp, ndone, piped_output);
1859*1a3d31e3SAndroid Build Coastguard Worker 		else if (ndone < 0 && errno != EINTR)
1860*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr, "Thread %d poll failed: %d/%s\n",
1861*1a3d31e3SAndroid Build Coastguard Worker 				tp->cpu, errno, strerror(errno));
1862*1a3d31e3SAndroid Build Coastguard Worker 	}
1863*1a3d31e3SAndroid Build Coastguard Worker 
1864*1a3d31e3SAndroid Build Coastguard Worker 	/*
1865*1a3d31e3SAndroid Build Coastguard Worker 	 * Trace is stopped, pull data until we get a short read
1866*1a3d31e3SAndroid Build Coastguard Worker 	 */
1867*1a3d31e3SAndroid Build Coastguard Worker 	while (handle_pfds(tp, ndevs, 1) > 0)
1868*1a3d31e3SAndroid Build Coastguard Worker 		;
1869*1a3d31e3SAndroid Build Coastguard Worker 
1870*1a3d31e3SAndroid Build Coastguard Worker 	close_ios(tp);
1871*1a3d31e3SAndroid Build Coastguard Worker 	tracer_signal_ready(tp, Th_leaving, 0);
1872*1a3d31e3SAndroid Build Coastguard Worker 	return NULL;
1873*1a3d31e3SAndroid Build Coastguard Worker 
1874*1a3d31e3SAndroid Build Coastguard Worker err:
1875*1a3d31e3SAndroid Build Coastguard Worker 	tracer_signal_ready(tp, Th_error, ret);
1876*1a3d31e3SAndroid Build Coastguard Worker 	return NULL;
1877*1a3d31e3SAndroid Build Coastguard Worker }
1878*1a3d31e3SAndroid Build Coastguard Worker 
start_tracer(int cpu)1879*1a3d31e3SAndroid Build Coastguard Worker static int start_tracer(int cpu)
1880*1a3d31e3SAndroid Build Coastguard Worker {
1881*1a3d31e3SAndroid Build Coastguard Worker 	struct tracer *tp;
1882*1a3d31e3SAndroid Build Coastguard Worker 
1883*1a3d31e3SAndroid Build Coastguard Worker 	tp = malloc(sizeof(*tp));
1884*1a3d31e3SAndroid Build Coastguard Worker 	memset(tp, 0, sizeof(*tp));
1885*1a3d31e3SAndroid Build Coastguard Worker 
1886*1a3d31e3SAndroid Build Coastguard Worker 	INIT_LIST_HEAD(&tp->head);
1887*1a3d31e3SAndroid Build Coastguard Worker 	tp->status = 0;
1888*1a3d31e3SAndroid Build Coastguard Worker 	tp->cpu = cpu;
1889*1a3d31e3SAndroid Build Coastguard Worker 
1890*1a3d31e3SAndroid Build Coastguard Worker 	if (pthread_create(&tp->thread, NULL, thread_main, tp)) {
1891*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "FAILED to start thread on CPU %d: %d/%s\n",
1892*1a3d31e3SAndroid Build Coastguard Worker 			cpu, errno, strerror(errno));
1893*1a3d31e3SAndroid Build Coastguard Worker 		free(tp);
1894*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
1895*1a3d31e3SAndroid Build Coastguard Worker 	}
1896*1a3d31e3SAndroid Build Coastguard Worker 
1897*1a3d31e3SAndroid Build Coastguard Worker 	list_add_tail(&tp->head, &tracers);
1898*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1899*1a3d31e3SAndroid Build Coastguard Worker }
1900*1a3d31e3SAndroid Build Coastguard Worker 
create_output_files(int cpu)1901*1a3d31e3SAndroid Build Coastguard Worker static int create_output_files(int cpu)
1902*1a3d31e3SAndroid Build Coastguard Worker {
1903*1a3d31e3SAndroid Build Coastguard Worker 	char fname[MAXPATHLEN + 64];
1904*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1905*1a3d31e3SAndroid Build Coastguard Worker 	FILE *f;
1906*1a3d31e3SAndroid Build Coastguard Worker 
1907*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1908*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1909*1a3d31e3SAndroid Build Coastguard Worker 
1910*1a3d31e3SAndroid Build Coastguard Worker 		if (fill_ofname(fname, sizeof(fname), NULL, dpp->buts_name,
1911*1a3d31e3SAndroid Build Coastguard Worker 				cpu))
1912*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
1913*1a3d31e3SAndroid Build Coastguard Worker 		f = my_fopen(fname, "w+");
1914*1a3d31e3SAndroid Build Coastguard Worker 		if (!f)
1915*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
1916*1a3d31e3SAndroid Build Coastguard Worker 		fclose(f);
1917*1a3d31e3SAndroid Build Coastguard Worker 	}
1918*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
1919*1a3d31e3SAndroid Build Coastguard Worker }
1920*1a3d31e3SAndroid Build Coastguard Worker 
start_tracers(void)1921*1a3d31e3SAndroid Build Coastguard Worker static void start_tracers(void)
1922*1a3d31e3SAndroid Build Coastguard Worker {
1923*1a3d31e3SAndroid Build Coastguard Worker 	int cpu, started = 0;
1924*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1925*1a3d31e3SAndroid Build Coastguard Worker 	size_t alloc_size = CPU_ALLOC_SIZE(max_cpus);
1926*1a3d31e3SAndroid Build Coastguard Worker 
1927*1a3d31e3SAndroid Build Coastguard Worker 	for (cpu = 0; cpu < max_cpus; cpu++) {
1928*1a3d31e3SAndroid Build Coastguard Worker 		if (!CPU_ISSET_S(cpu, alloc_size, online_cpus)) {
1929*1a3d31e3SAndroid Build Coastguard Worker 			/*
1930*1a3d31e3SAndroid Build Coastguard Worker 			 * Create fake empty output files so that other tools
1931*1a3d31e3SAndroid Build Coastguard Worker 			 * like blkparse don't have to bother with sparse CPU
1932*1a3d31e3SAndroid Build Coastguard Worker 			 * number space.
1933*1a3d31e3SAndroid Build Coastguard Worker 			 */
1934*1a3d31e3SAndroid Build Coastguard Worker 			if (create_output_files(cpu))
1935*1a3d31e3SAndroid Build Coastguard Worker 				break;
1936*1a3d31e3SAndroid Build Coastguard Worker 			continue;
1937*1a3d31e3SAndroid Build Coastguard Worker 		}
1938*1a3d31e3SAndroid Build Coastguard Worker 		if (start_tracer(cpu))
1939*1a3d31e3SAndroid Build Coastguard Worker 			break;
1940*1a3d31e3SAndroid Build Coastguard Worker 		started++;
1941*1a3d31e3SAndroid Build Coastguard Worker 	}
1942*1a3d31e3SAndroid Build Coastguard Worker 
1943*1a3d31e3SAndroid Build Coastguard Worker 	wait_tracers_ready(started);
1944*1a3d31e3SAndroid Build Coastguard Worker 
1945*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &tracers) {
1946*1a3d31e3SAndroid Build Coastguard Worker 		struct tracer *tp = list_entry(p, struct tracer, head);
1947*1a3d31e3SAndroid Build Coastguard Worker 		if (tp->status)
1948*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr,
1949*1a3d31e3SAndroid Build Coastguard Worker 				"FAILED to start thread on CPU %d: %d/%s\n",
1950*1a3d31e3SAndroid Build Coastguard Worker 				tp->cpu, tp->status, strerror(tp->status));
1951*1a3d31e3SAndroid Build Coastguard Worker 	}
1952*1a3d31e3SAndroid Build Coastguard Worker }
1953*1a3d31e3SAndroid Build Coastguard Worker 
stop_tracers(void)1954*1a3d31e3SAndroid Build Coastguard Worker static void stop_tracers(void)
1955*1a3d31e3SAndroid Build Coastguard Worker {
1956*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1957*1a3d31e3SAndroid Build Coastguard Worker 
1958*1a3d31e3SAndroid Build Coastguard Worker 	/*
1959*1a3d31e3SAndroid Build Coastguard Worker 	 * Stop the tracing - makes the tracer threads clean up quicker.
1960*1a3d31e3SAndroid Build Coastguard Worker 	 */
1961*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &devpaths) {
1962*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
1963*1a3d31e3SAndroid Build Coastguard Worker 		(void)ioctl(dpp->fd, BLKTRACESTOP);
1964*1a3d31e3SAndroid Build Coastguard Worker 	}
1965*1a3d31e3SAndroid Build Coastguard Worker 
1966*1a3d31e3SAndroid Build Coastguard Worker 	/*
1967*1a3d31e3SAndroid Build Coastguard Worker 	 * Tell each tracer to quit
1968*1a3d31e3SAndroid Build Coastguard Worker 	 */
1969*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &tracers) {
1970*1a3d31e3SAndroid Build Coastguard Worker 		struct tracer *tp = list_entry(p, struct tracer, head);
1971*1a3d31e3SAndroid Build Coastguard Worker 		tp->is_done = 1;
1972*1a3d31e3SAndroid Build Coastguard Worker 	}
1973*1a3d31e3SAndroid Build Coastguard Worker 	pthread_cond_broadcast(&mt_cond);
1974*1a3d31e3SAndroid Build Coastguard Worker }
1975*1a3d31e3SAndroid Build Coastguard Worker 
del_tracers(void)1976*1a3d31e3SAndroid Build Coastguard Worker static void del_tracers(void)
1977*1a3d31e3SAndroid Build Coastguard Worker {
1978*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p, *q;
1979*1a3d31e3SAndroid Build Coastguard Worker 
1980*1a3d31e3SAndroid Build Coastguard Worker 	list_for_each_safe(p, q, &tracers) {
1981*1a3d31e3SAndroid Build Coastguard Worker 		struct tracer *tp = list_entry(p, struct tracer, head);
1982*1a3d31e3SAndroid Build Coastguard Worker 
1983*1a3d31e3SAndroid Build Coastguard Worker 		list_del(&tp->head);
1984*1a3d31e3SAndroid Build Coastguard Worker 		free(tp);
1985*1a3d31e3SAndroid Build Coastguard Worker 	}
1986*1a3d31e3SAndroid Build Coastguard Worker }
1987*1a3d31e3SAndroid Build Coastguard Worker 
wait_tracers(void)1988*1a3d31e3SAndroid Build Coastguard Worker static void wait_tracers(void)
1989*1a3d31e3SAndroid Build Coastguard Worker {
1990*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
1991*1a3d31e3SAndroid Build Coastguard Worker 
1992*1a3d31e3SAndroid Build Coastguard Worker 	if (use_tracer_devpaths())
1993*1a3d31e3SAndroid Build Coastguard Worker 		process_trace_bufs();
1994*1a3d31e3SAndroid Build Coastguard Worker 
1995*1a3d31e3SAndroid Build Coastguard Worker 	wait_tracers_leaving();
1996*1a3d31e3SAndroid Build Coastguard Worker 
1997*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &tracers) {
1998*1a3d31e3SAndroid Build Coastguard Worker 		int ret;
1999*1a3d31e3SAndroid Build Coastguard Worker 		struct tracer *tp = list_entry(p, struct tracer, head);
2000*1a3d31e3SAndroid Build Coastguard Worker 
2001*1a3d31e3SAndroid Build Coastguard Worker 		ret = pthread_join(tp->thread, NULL);
2002*1a3d31e3SAndroid Build Coastguard Worker 		if (ret)
2003*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr, "Thread join %d failed %d\n",
2004*1a3d31e3SAndroid Build Coastguard Worker 				tp->cpu, ret);
2005*1a3d31e3SAndroid Build Coastguard Worker 	}
2006*1a3d31e3SAndroid Build Coastguard Worker 
2007*1a3d31e3SAndroid Build Coastguard Worker 	if (use_tracer_devpaths())
2008*1a3d31e3SAndroid Build Coastguard Worker 		clean_trace_bufs();
2009*1a3d31e3SAndroid Build Coastguard Worker 
2010*1a3d31e3SAndroid Build Coastguard Worker 	get_all_drops();
2011*1a3d31e3SAndroid Build Coastguard Worker }
2012*1a3d31e3SAndroid Build Coastguard Worker 
exit_tracing(void)2013*1a3d31e3SAndroid Build Coastguard Worker static void exit_tracing(void)
2014*1a3d31e3SAndroid Build Coastguard Worker {
2015*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGINT, SIG_IGN);
2016*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGHUP, SIG_IGN);
2017*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGTERM, SIG_IGN);
2018*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGALRM, SIG_IGN);
2019*1a3d31e3SAndroid Build Coastguard Worker 
2020*1a3d31e3SAndroid Build Coastguard Worker 	stop_tracers();
2021*1a3d31e3SAndroid Build Coastguard Worker 	wait_tracers();
2022*1a3d31e3SAndroid Build Coastguard Worker 	del_tracers();
2023*1a3d31e3SAndroid Build Coastguard Worker 	rel_devpaths();
2024*1a3d31e3SAndroid Build Coastguard Worker }
2025*1a3d31e3SAndroid Build Coastguard Worker 
handle_sigint(int sig)2026*1a3d31e3SAndroid Build Coastguard Worker static void handle_sigint(__attribute__((__unused__)) int sig)
2027*1a3d31e3SAndroid Build Coastguard Worker {
2028*1a3d31e3SAndroid Build Coastguard Worker 	done = 1;
2029*1a3d31e3SAndroid Build Coastguard Worker 	stop_tracers();
2030*1a3d31e3SAndroid Build Coastguard Worker }
2031*1a3d31e3SAndroid Build Coastguard Worker 
show_stats(struct list_head * devpaths)2032*1a3d31e3SAndroid Build Coastguard Worker static void show_stats(struct list_head *devpaths)
2033*1a3d31e3SAndroid Build Coastguard Worker {
2034*1a3d31e3SAndroid Build Coastguard Worker 	FILE *ofp;
2035*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
2036*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long long nevents, data_read;
2037*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long long total_drops = 0;
2038*1a3d31e3SAndroid Build Coastguard Worker 	unsigned long long total_events = 0;
2039*1a3d31e3SAndroid Build Coastguard Worker 
2040*1a3d31e3SAndroid Build Coastguard Worker 	if (piped_output)
2041*1a3d31e3SAndroid Build Coastguard Worker 		ofp = my_fopen("/dev/null", "w");
2042*1a3d31e3SAndroid Build Coastguard Worker 	else
2043*1a3d31e3SAndroid Build Coastguard Worker 		ofp = stdout;
2044*1a3d31e3SAndroid Build Coastguard Worker 
2045*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, devpaths) {
2046*1a3d31e3SAndroid Build Coastguard Worker 		int cpu;
2047*1a3d31e3SAndroid Build Coastguard Worker 		struct pdc_stats *sp;
2048*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
2049*1a3d31e3SAndroid Build Coastguard Worker 
2050*1a3d31e3SAndroid Build Coastguard Worker 		if (net_mode == Net_server)
2051*1a3d31e3SAndroid Build Coastguard Worker 			printf("server: end of run for %s:%s\n",
2052*1a3d31e3SAndroid Build Coastguard Worker 				dpp->ch->hostname, dpp->buts_name);
2053*1a3d31e3SAndroid Build Coastguard Worker 
2054*1a3d31e3SAndroid Build Coastguard Worker 		data_read = 0;
2055*1a3d31e3SAndroid Build Coastguard Worker 		nevents = 0;
2056*1a3d31e3SAndroid Build Coastguard Worker 
2057*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(ofp, "=== %s ===\n", dpp->buts_name);
2058*1a3d31e3SAndroid Build Coastguard Worker 		for (cpu = 0, sp = dpp->stats; cpu < dpp->ncpus; cpu++, sp++) {
2059*1a3d31e3SAndroid Build Coastguard Worker 			/*
2060*1a3d31e3SAndroid Build Coastguard Worker 			 * Estimate events if not known...
2061*1a3d31e3SAndroid Build Coastguard Worker 			 */
2062*1a3d31e3SAndroid Build Coastguard Worker 			if (sp->nevents == 0) {
2063*1a3d31e3SAndroid Build Coastguard Worker 				sp->nevents = sp->data_read /
2064*1a3d31e3SAndroid Build Coastguard Worker 						sizeof(struct blk_io_trace);
2065*1a3d31e3SAndroid Build Coastguard Worker 			}
2066*1a3d31e3SAndroid Build Coastguard Worker 
2067*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(ofp,
2068*1a3d31e3SAndroid Build Coastguard Worker 				"  CPU%3d: %20llu events, %8llu KiB data\n",
2069*1a3d31e3SAndroid Build Coastguard Worker 				cpu, sp->nevents, (sp->data_read + 1023) >> 10);
2070*1a3d31e3SAndroid Build Coastguard Worker 
2071*1a3d31e3SAndroid Build Coastguard Worker 			data_read += sp->data_read;
2072*1a3d31e3SAndroid Build Coastguard Worker 			nevents += sp->nevents;
2073*1a3d31e3SAndroid Build Coastguard Worker 		}
2074*1a3d31e3SAndroid Build Coastguard Worker 
2075*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(ofp, "  Total:  %20llu events (dropped %llu),"
2076*1a3d31e3SAndroid Build Coastguard Worker 			     " %8llu KiB data\n", nevents,
2077*1a3d31e3SAndroid Build Coastguard Worker 			     dpp->drops, (data_read + 1024) >> 10);
2078*1a3d31e3SAndroid Build Coastguard Worker 
2079*1a3d31e3SAndroid Build Coastguard Worker 		total_drops += dpp->drops;
2080*1a3d31e3SAndroid Build Coastguard Worker 		total_events += (nevents + dpp->drops);
2081*1a3d31e3SAndroid Build Coastguard Worker 	}
2082*1a3d31e3SAndroid Build Coastguard Worker 
2083*1a3d31e3SAndroid Build Coastguard Worker 	fflush(ofp);
2084*1a3d31e3SAndroid Build Coastguard Worker 	if (piped_output)
2085*1a3d31e3SAndroid Build Coastguard Worker 		fclose(ofp);
2086*1a3d31e3SAndroid Build Coastguard Worker 
2087*1a3d31e3SAndroid Build Coastguard Worker 	if (total_drops) {
2088*1a3d31e3SAndroid Build Coastguard Worker 		double drops_ratio = 1.0;
2089*1a3d31e3SAndroid Build Coastguard Worker 
2090*1a3d31e3SAndroid Build Coastguard Worker 		if (total_events)
2091*1a3d31e3SAndroid Build Coastguard Worker 			drops_ratio = (double)total_drops/(double)total_events;
2092*1a3d31e3SAndroid Build Coastguard Worker 
2093*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "\nYou have %llu (%5.1lf%%) dropped events\n"
2094*1a3d31e3SAndroid Build Coastguard Worker 				"Consider using a larger buffer size (-b) "
2095*1a3d31e3SAndroid Build Coastguard Worker 				"and/or more buffers (-n)\n",
2096*1a3d31e3SAndroid Build Coastguard Worker 			total_drops, 100.0 * drops_ratio);
2097*1a3d31e3SAndroid Build Coastguard Worker 	}
2098*1a3d31e3SAndroid Build Coastguard Worker }
2099*1a3d31e3SAndroid Build Coastguard Worker 
handle_args(int argc,char * argv[])2100*1a3d31e3SAndroid Build Coastguard Worker static int handle_args(int argc, char *argv[])
2101*1a3d31e3SAndroid Build Coastguard Worker {
2102*1a3d31e3SAndroid Build Coastguard Worker 	int c, i;
2103*1a3d31e3SAndroid Build Coastguard Worker 	struct statfs st;
2104*1a3d31e3SAndroid Build Coastguard Worker 	int act_mask_tmp = 0;
2105*1a3d31e3SAndroid Build Coastguard Worker 
2106*1a3d31e3SAndroid Build Coastguard Worker 	while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) >= 0) {
2107*1a3d31e3SAndroid Build Coastguard Worker 		switch (c) {
2108*1a3d31e3SAndroid Build Coastguard Worker 		case 'a':
2109*1a3d31e3SAndroid Build Coastguard Worker 			i = find_mask_map(optarg);
2110*1a3d31e3SAndroid Build Coastguard Worker 			if (i < 0) {
2111*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr, "Invalid action mask %s\n",
2112*1a3d31e3SAndroid Build Coastguard Worker 					optarg);
2113*1a3d31e3SAndroid Build Coastguard Worker 				return 1;
2114*1a3d31e3SAndroid Build Coastguard Worker 			}
2115*1a3d31e3SAndroid Build Coastguard Worker 			act_mask_tmp |= i;
2116*1a3d31e3SAndroid Build Coastguard Worker 			break;
2117*1a3d31e3SAndroid Build Coastguard Worker 
2118*1a3d31e3SAndroid Build Coastguard Worker 		case 'A':
2119*1a3d31e3SAndroid Build Coastguard Worker 			if ((sscanf(optarg, "%x", &i) != 1) ||
2120*1a3d31e3SAndroid Build Coastguard Worker 							!valid_act_opt(i)) {
2121*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr,
2122*1a3d31e3SAndroid Build Coastguard Worker 					"Invalid set action mask %s/0x%x\n",
2123*1a3d31e3SAndroid Build Coastguard Worker 					optarg, i);
2124*1a3d31e3SAndroid Build Coastguard Worker 				return 1;
2125*1a3d31e3SAndroid Build Coastguard Worker 			}
2126*1a3d31e3SAndroid Build Coastguard Worker 			act_mask_tmp = i;
2127*1a3d31e3SAndroid Build Coastguard Worker 			break;
2128*1a3d31e3SAndroid Build Coastguard Worker 
2129*1a3d31e3SAndroid Build Coastguard Worker 		case 'd':
2130*1a3d31e3SAndroid Build Coastguard Worker 			if (add_devpath(optarg) != 0)
2131*1a3d31e3SAndroid Build Coastguard Worker 				return 1;
2132*1a3d31e3SAndroid Build Coastguard Worker 			break;
2133*1a3d31e3SAndroid Build Coastguard Worker 
2134*1a3d31e3SAndroid Build Coastguard Worker 		case 'I': {
2135*1a3d31e3SAndroid Build Coastguard Worker 			char dev_line[256];
2136*1a3d31e3SAndroid Build Coastguard Worker 			FILE *ifp = my_fopen(optarg, "r");
2137*1a3d31e3SAndroid Build Coastguard Worker 
2138*1a3d31e3SAndroid Build Coastguard Worker 			if (!ifp) {
2139*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr,
2140*1a3d31e3SAndroid Build Coastguard Worker 					"Invalid file for devices %s\n",
2141*1a3d31e3SAndroid Build Coastguard Worker 					optarg);
2142*1a3d31e3SAndroid Build Coastguard Worker 				return 1;
2143*1a3d31e3SAndroid Build Coastguard Worker 			}
2144*1a3d31e3SAndroid Build Coastguard Worker 
2145*1a3d31e3SAndroid Build Coastguard Worker 			while (fscanf(ifp, "%s\n", dev_line) == 1) {
2146*1a3d31e3SAndroid Build Coastguard Worker 				if (add_devpath(dev_line) != 0) {
2147*1a3d31e3SAndroid Build Coastguard Worker 					fclose(ifp);
2148*1a3d31e3SAndroid Build Coastguard Worker 					return 1;
2149*1a3d31e3SAndroid Build Coastguard Worker 				}
2150*1a3d31e3SAndroid Build Coastguard Worker 			}
2151*1a3d31e3SAndroid Build Coastguard Worker 			fclose(ifp);
2152*1a3d31e3SAndroid Build Coastguard Worker 			break;
2153*1a3d31e3SAndroid Build Coastguard Worker 		}
2154*1a3d31e3SAndroid Build Coastguard Worker 
2155*1a3d31e3SAndroid Build Coastguard Worker 		case 'r':
2156*1a3d31e3SAndroid Build Coastguard Worker 			debugfs_path = optarg;
2157*1a3d31e3SAndroid Build Coastguard Worker 			break;
2158*1a3d31e3SAndroid Build Coastguard Worker 
2159*1a3d31e3SAndroid Build Coastguard Worker 		case 'o':
2160*1a3d31e3SAndroid Build Coastguard Worker 			output_name = optarg;
2161*1a3d31e3SAndroid Build Coastguard Worker 			break;
2162*1a3d31e3SAndroid Build Coastguard Worker 		case 'k':
2163*1a3d31e3SAndroid Build Coastguard Worker 			kill_running_trace = 1;
2164*1a3d31e3SAndroid Build Coastguard Worker 			break;
2165*1a3d31e3SAndroid Build Coastguard Worker 		case 'w':
2166*1a3d31e3SAndroid Build Coastguard Worker 			stop_watch = atoi(optarg);
2167*1a3d31e3SAndroid Build Coastguard Worker 			if (stop_watch <= 0) {
2168*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr,
2169*1a3d31e3SAndroid Build Coastguard Worker 					"Invalid stopwatch value (%d secs)\n",
2170*1a3d31e3SAndroid Build Coastguard Worker 					stop_watch);
2171*1a3d31e3SAndroid Build Coastguard Worker 				return 1;
2172*1a3d31e3SAndroid Build Coastguard Worker 			}
2173*1a3d31e3SAndroid Build Coastguard Worker 			break;
2174*1a3d31e3SAndroid Build Coastguard Worker 		case 'V':
2175*1a3d31e3SAndroid Build Coastguard Worker 		case 'v':
2176*1a3d31e3SAndroid Build Coastguard Worker 			printf("%s version %s\n", argv[0], blktrace_version);
2177*1a3d31e3SAndroid Build Coastguard Worker 			exit(0);
2178*1a3d31e3SAndroid Build Coastguard Worker 			/*NOTREACHED*/
2179*1a3d31e3SAndroid Build Coastguard Worker 		case 'b':
2180*1a3d31e3SAndroid Build Coastguard Worker 			buf_size = strtoul(optarg, NULL, 10);
2181*1a3d31e3SAndroid Build Coastguard Worker 			if (buf_size <= 0 || buf_size > 16*1024) {
2182*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr, "Invalid buffer size (%lu)\n",
2183*1a3d31e3SAndroid Build Coastguard Worker 					buf_size);
2184*1a3d31e3SAndroid Build Coastguard Worker 				return 1;
2185*1a3d31e3SAndroid Build Coastguard Worker 			}
2186*1a3d31e3SAndroid Build Coastguard Worker 			buf_size <<= 10;
2187*1a3d31e3SAndroid Build Coastguard Worker 			break;
2188*1a3d31e3SAndroid Build Coastguard Worker 		case 'n':
2189*1a3d31e3SAndroid Build Coastguard Worker 			buf_nr = strtoul(optarg, NULL, 10);
2190*1a3d31e3SAndroid Build Coastguard Worker 			if (buf_nr <= 0) {
2191*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr,
2192*1a3d31e3SAndroid Build Coastguard Worker 					"Invalid buffer nr (%lu)\n", buf_nr);
2193*1a3d31e3SAndroid Build Coastguard Worker 				return 1;
2194*1a3d31e3SAndroid Build Coastguard Worker 			}
2195*1a3d31e3SAndroid Build Coastguard Worker 			break;
2196*1a3d31e3SAndroid Build Coastguard Worker 		case 'D':
2197*1a3d31e3SAndroid Build Coastguard Worker 			output_dir = optarg;
2198*1a3d31e3SAndroid Build Coastguard Worker 			break;
2199*1a3d31e3SAndroid Build Coastguard Worker 		case 'h':
2200*1a3d31e3SAndroid Build Coastguard Worker 			net_mode = Net_client;
2201*1a3d31e3SAndroid Build Coastguard Worker 			memset(hostname, 0, sizeof(hostname));
2202*1a3d31e3SAndroid Build Coastguard Worker 			strncpy(hostname, optarg, sizeof(hostname));
2203*1a3d31e3SAndroid Build Coastguard Worker 			hostname[sizeof(hostname) - 1] = '\0';
2204*1a3d31e3SAndroid Build Coastguard Worker 			break;
2205*1a3d31e3SAndroid Build Coastguard Worker 		case 'l':
2206*1a3d31e3SAndroid Build Coastguard Worker 			net_mode = Net_server;
2207*1a3d31e3SAndroid Build Coastguard Worker 			break;
2208*1a3d31e3SAndroid Build Coastguard Worker 		case 'p':
2209*1a3d31e3SAndroid Build Coastguard Worker 			net_port = atoi(optarg);
2210*1a3d31e3SAndroid Build Coastguard Worker 			break;
2211*1a3d31e3SAndroid Build Coastguard Worker 		case 's':
2212*1a3d31e3SAndroid Build Coastguard Worker 			net_use_sendfile = 0;
2213*1a3d31e3SAndroid Build Coastguard Worker 			break;
2214*1a3d31e3SAndroid Build Coastguard Worker 		default:
2215*1a3d31e3SAndroid Build Coastguard Worker 			show_usage(argv[0]);
2216*1a3d31e3SAndroid Build Coastguard Worker 			exit(1);
2217*1a3d31e3SAndroid Build Coastguard Worker 			/*NOTREACHED*/
2218*1a3d31e3SAndroid Build Coastguard Worker 		}
2219*1a3d31e3SAndroid Build Coastguard Worker 	}
2220*1a3d31e3SAndroid Build Coastguard Worker 
2221*1a3d31e3SAndroid Build Coastguard Worker 	while (optind < argc)
2222*1a3d31e3SAndroid Build Coastguard Worker 		if (add_devpath(argv[optind++]) != 0)
2223*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
2224*1a3d31e3SAndroid Build Coastguard Worker 
2225*1a3d31e3SAndroid Build Coastguard Worker 	if (net_mode != Net_server && ndevs == 0) {
2226*1a3d31e3SAndroid Build Coastguard Worker 		show_usage(argv[0]);
2227*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
2228*1a3d31e3SAndroid Build Coastguard Worker 	}
2229*1a3d31e3SAndroid Build Coastguard Worker 
2230*1a3d31e3SAndroid Build Coastguard Worker 	if (statfs(debugfs_path, &st) < 0) {
2231*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid debug path %s: %d/%s\n",
2232*1a3d31e3SAndroid Build Coastguard Worker 			debugfs_path, errno, strerror(errno));
2233*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
2234*1a3d31e3SAndroid Build Coastguard Worker 	}
2235*1a3d31e3SAndroid Build Coastguard Worker 
2236*1a3d31e3SAndroid Build Coastguard Worker 	if (st.f_type != (long)DEBUGFS_TYPE) {
2237*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "Debugfs is not mounted at %s\n", debugfs_path);
2238*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
2239*1a3d31e3SAndroid Build Coastguard Worker 	}
2240*1a3d31e3SAndroid Build Coastguard Worker 
2241*1a3d31e3SAndroid Build Coastguard Worker 	if (act_mask_tmp != 0)
2242*1a3d31e3SAndroid Build Coastguard Worker 		act_mask = act_mask_tmp;
2243*1a3d31e3SAndroid Build Coastguard Worker 
2244*1a3d31e3SAndroid Build Coastguard Worker 	if (net_mode == Net_client && net_setup_addr())
2245*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
2246*1a3d31e3SAndroid Build Coastguard Worker 
2247*1a3d31e3SAndroid Build Coastguard Worker 	/*
2248*1a3d31e3SAndroid Build Coastguard Worker 	 * Set up for appropriate PFD handler based upon output name.
2249*1a3d31e3SAndroid Build Coastguard Worker 	 */
2250*1a3d31e3SAndroid Build Coastguard Worker 	if (net_client_use_sendfile())
2251*1a3d31e3SAndroid Build Coastguard Worker 		handle_pfds = handle_pfds_netclient;
2252*1a3d31e3SAndroid Build Coastguard Worker 	else if (net_client_use_send())
2253*1a3d31e3SAndroid Build Coastguard Worker 		handle_pfds = handle_pfds_entries;
2254*1a3d31e3SAndroid Build Coastguard Worker 	else if (output_name && (strcmp(output_name, "-") == 0)) {
2255*1a3d31e3SAndroid Build Coastguard Worker 		piped_output = 1;
2256*1a3d31e3SAndroid Build Coastguard Worker 		handle_pfds = handle_pfds_entries;
2257*1a3d31e3SAndroid Build Coastguard Worker 		pfp = stdout;
2258*1a3d31e3SAndroid Build Coastguard Worker 		if (setvbuf(pfp, NULL, _IONBF, 0)) {
2259*1a3d31e3SAndroid Build Coastguard Worker 			perror("setvbuf stdout");
2260*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
2261*1a3d31e3SAndroid Build Coastguard Worker 		}
2262*1a3d31e3SAndroid Build Coastguard Worker 	} else
2263*1a3d31e3SAndroid Build Coastguard Worker 		handle_pfds = handle_pfds_file;
2264*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
2265*1a3d31e3SAndroid Build Coastguard Worker }
2266*1a3d31e3SAndroid Build Coastguard Worker 
ch_add_connection(struct net_server_s * ns,struct cl_host * ch,int fd)2267*1a3d31e3SAndroid Build Coastguard Worker static void ch_add_connection(struct net_server_s *ns, struct cl_host *ch,
2268*1a3d31e3SAndroid Build Coastguard Worker 			      int fd)
2269*1a3d31e3SAndroid Build Coastguard Worker {
2270*1a3d31e3SAndroid Build Coastguard Worker 	struct cl_conn *nc;
2271*1a3d31e3SAndroid Build Coastguard Worker 
2272*1a3d31e3SAndroid Build Coastguard Worker 	nc = malloc(sizeof(*nc));
2273*1a3d31e3SAndroid Build Coastguard Worker 	memset(nc, 0, sizeof(*nc));
2274*1a3d31e3SAndroid Build Coastguard Worker 
2275*1a3d31e3SAndroid Build Coastguard Worker 	time(&nc->connect_time);
2276*1a3d31e3SAndroid Build Coastguard Worker 	nc->ch = ch;
2277*1a3d31e3SAndroid Build Coastguard Worker 	nc->fd = fd;
2278*1a3d31e3SAndroid Build Coastguard Worker 	nc->ncpus = -1;
2279*1a3d31e3SAndroid Build Coastguard Worker 
2280*1a3d31e3SAndroid Build Coastguard Worker 	list_add_tail(&nc->ch_head, &ch->conn_list);
2281*1a3d31e3SAndroid Build Coastguard Worker 	ch->connects++;
2282*1a3d31e3SAndroid Build Coastguard Worker 
2283*1a3d31e3SAndroid Build Coastguard Worker 	list_add_tail(&nc->ns_head, &ns->conn_list);
2284*1a3d31e3SAndroid Build Coastguard Worker 	ns->connects++;
2285*1a3d31e3SAndroid Build Coastguard Worker 	ns->pfds = realloc(ns->pfds, (ns->connects+1) * sizeof(struct pollfd));
2286*1a3d31e3SAndroid Build Coastguard Worker }
2287*1a3d31e3SAndroid Build Coastguard Worker 
ch_rem_connection(struct net_server_s * ns,struct cl_host * ch,struct cl_conn * nc)2288*1a3d31e3SAndroid Build Coastguard Worker static void ch_rem_connection(struct net_server_s *ns, struct cl_host *ch,
2289*1a3d31e3SAndroid Build Coastguard Worker 			      struct cl_conn *nc)
2290*1a3d31e3SAndroid Build Coastguard Worker {
2291*1a3d31e3SAndroid Build Coastguard Worker 	net_close_connection(&nc->fd);
2292*1a3d31e3SAndroid Build Coastguard Worker 
2293*1a3d31e3SAndroid Build Coastguard Worker 	list_del(&nc->ch_head);
2294*1a3d31e3SAndroid Build Coastguard Worker 	ch->connects--;
2295*1a3d31e3SAndroid Build Coastguard Worker 
2296*1a3d31e3SAndroid Build Coastguard Worker 	list_del(&nc->ns_head);
2297*1a3d31e3SAndroid Build Coastguard Worker 	ns->connects--;
2298*1a3d31e3SAndroid Build Coastguard Worker 	ns->pfds = realloc(ns->pfds, (ns->connects+1) * sizeof(struct pollfd));
2299*1a3d31e3SAndroid Build Coastguard Worker 
2300*1a3d31e3SAndroid Build Coastguard Worker 	free(nc);
2301*1a3d31e3SAndroid Build Coastguard Worker }
2302*1a3d31e3SAndroid Build Coastguard Worker 
net_find_client_host(struct net_server_s * ns,struct in_addr cl_in_addr)2303*1a3d31e3SAndroid Build Coastguard Worker static struct cl_host *net_find_client_host(struct net_server_s *ns,
2304*1a3d31e3SAndroid Build Coastguard Worker 					    struct in_addr cl_in_addr)
2305*1a3d31e3SAndroid Build Coastguard Worker {
2306*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
2307*1a3d31e3SAndroid Build Coastguard Worker 
2308*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &ns->ch_list) {
2309*1a3d31e3SAndroid Build Coastguard Worker 		struct cl_host *ch = list_entry(p, struct cl_host, head);
2310*1a3d31e3SAndroid Build Coastguard Worker 
2311*1a3d31e3SAndroid Build Coastguard Worker 		if (in_addr_eq(ch->cl_in_addr, cl_in_addr))
2312*1a3d31e3SAndroid Build Coastguard Worker 			return ch;
2313*1a3d31e3SAndroid Build Coastguard Worker 	}
2314*1a3d31e3SAndroid Build Coastguard Worker 
2315*1a3d31e3SAndroid Build Coastguard Worker 	return NULL;
2316*1a3d31e3SAndroid Build Coastguard Worker }
2317*1a3d31e3SAndroid Build Coastguard Worker 
net_add_client_host(struct net_server_s * ns,struct sockaddr_in * addr)2318*1a3d31e3SAndroid Build Coastguard Worker static struct cl_host *net_add_client_host(struct net_server_s *ns,
2319*1a3d31e3SAndroid Build Coastguard Worker 					   struct sockaddr_in *addr)
2320*1a3d31e3SAndroid Build Coastguard Worker {
2321*1a3d31e3SAndroid Build Coastguard Worker 	struct cl_host *ch;
2322*1a3d31e3SAndroid Build Coastguard Worker 
2323*1a3d31e3SAndroid Build Coastguard Worker 	ch = malloc(sizeof(*ch));
2324*1a3d31e3SAndroid Build Coastguard Worker 	memset(ch, 0, sizeof(*ch));
2325*1a3d31e3SAndroid Build Coastguard Worker 
2326*1a3d31e3SAndroid Build Coastguard Worker 	ch->ns = ns;
2327*1a3d31e3SAndroid Build Coastguard Worker 	ch->cl_in_addr = addr->sin_addr;
2328*1a3d31e3SAndroid Build Coastguard Worker 	list_add_tail(&ch->head, &ns->ch_list);
2329*1a3d31e3SAndroid Build Coastguard Worker 	ns->nchs++;
2330*1a3d31e3SAndroid Build Coastguard Worker 
2331*1a3d31e3SAndroid Build Coastguard Worker 	ch->hostname = strdup(inet_ntoa(addr->sin_addr));
2332*1a3d31e3SAndroid Build Coastguard Worker 	printf("server: connection from %s\n", ch->hostname);
2333*1a3d31e3SAndroid Build Coastguard Worker 
2334*1a3d31e3SAndroid Build Coastguard Worker 	INIT_LIST_HEAD(&ch->conn_list);
2335*1a3d31e3SAndroid Build Coastguard Worker 	INIT_LIST_HEAD(&ch->devpaths);
2336*1a3d31e3SAndroid Build Coastguard Worker 
2337*1a3d31e3SAndroid Build Coastguard Worker 	return ch;
2338*1a3d31e3SAndroid Build Coastguard Worker }
2339*1a3d31e3SAndroid Build Coastguard Worker 
device_done(struct devpath * dpp,int ncpus)2340*1a3d31e3SAndroid Build Coastguard Worker static void device_done(struct devpath *dpp, int ncpus)
2341*1a3d31e3SAndroid Build Coastguard Worker {
2342*1a3d31e3SAndroid Build Coastguard Worker 	int cpu;
2343*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *iop;
2344*1a3d31e3SAndroid Build Coastguard Worker 
2345*1a3d31e3SAndroid Build Coastguard Worker 	for (cpu = 0, iop = dpp->ios; cpu < ncpus; cpu++, iop++)
2346*1a3d31e3SAndroid Build Coastguard Worker 		close_iop(iop);
2347*1a3d31e3SAndroid Build Coastguard Worker 
2348*1a3d31e3SAndroid Build Coastguard Worker 	list_del(&dpp->head);
2349*1a3d31e3SAndroid Build Coastguard Worker 	dpp_free(dpp);
2350*1a3d31e3SAndroid Build Coastguard Worker }
2351*1a3d31e3SAndroid Build Coastguard Worker 
net_ch_remove(struct cl_host * ch,int ncpus)2352*1a3d31e3SAndroid Build Coastguard Worker static void net_ch_remove(struct cl_host *ch, int ncpus)
2353*1a3d31e3SAndroid Build Coastguard Worker {
2354*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p, *q;
2355*1a3d31e3SAndroid Build Coastguard Worker 	struct net_server_s *ns = ch->ns;
2356*1a3d31e3SAndroid Build Coastguard Worker 
2357*1a3d31e3SAndroid Build Coastguard Worker 	list_for_each_safe(p, q, &ch->devpaths) {
2358*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
2359*1a3d31e3SAndroid Build Coastguard Worker 		device_done(dpp, ncpus);
2360*1a3d31e3SAndroid Build Coastguard Worker 	}
2361*1a3d31e3SAndroid Build Coastguard Worker 
2362*1a3d31e3SAndroid Build Coastguard Worker 	list_for_each_safe(p, q, &ch->conn_list) {
2363*1a3d31e3SAndroid Build Coastguard Worker 		struct cl_conn *nc = list_entry(p, struct cl_conn, ch_head);
2364*1a3d31e3SAndroid Build Coastguard Worker 
2365*1a3d31e3SAndroid Build Coastguard Worker 		ch_rem_connection(ns, ch, nc);
2366*1a3d31e3SAndroid Build Coastguard Worker 	}
2367*1a3d31e3SAndroid Build Coastguard Worker 
2368*1a3d31e3SAndroid Build Coastguard Worker 	list_del(&ch->head);
2369*1a3d31e3SAndroid Build Coastguard Worker 	ns->nchs--;
2370*1a3d31e3SAndroid Build Coastguard Worker 
2371*1a3d31e3SAndroid Build Coastguard Worker 	if (ch->hostname)
2372*1a3d31e3SAndroid Build Coastguard Worker 		free(ch->hostname);
2373*1a3d31e3SAndroid Build Coastguard Worker 	free(ch);
2374*1a3d31e3SAndroid Build Coastguard Worker }
2375*1a3d31e3SAndroid Build Coastguard Worker 
net_add_connection(struct net_server_s * ns)2376*1a3d31e3SAndroid Build Coastguard Worker static void net_add_connection(struct net_server_s *ns)
2377*1a3d31e3SAndroid Build Coastguard Worker {
2378*1a3d31e3SAndroid Build Coastguard Worker 	int fd;
2379*1a3d31e3SAndroid Build Coastguard Worker 	struct cl_host *ch;
2380*1a3d31e3SAndroid Build Coastguard Worker 	socklen_t socklen = sizeof(ns->addr);
2381*1a3d31e3SAndroid Build Coastguard Worker 
2382*1a3d31e3SAndroid Build Coastguard Worker 	fd = my_accept(ns->listen_fd, (struct sockaddr *)&ns->addr, &socklen);
2383*1a3d31e3SAndroid Build Coastguard Worker 	if (fd < 0) {
2384*1a3d31e3SAndroid Build Coastguard Worker 		/*
2385*1a3d31e3SAndroid Build Coastguard Worker 		 * This is OK: we just won't accept this connection,
2386*1a3d31e3SAndroid Build Coastguard Worker 		 * nothing fatal.
2387*1a3d31e3SAndroid Build Coastguard Worker 		 */
2388*1a3d31e3SAndroid Build Coastguard Worker 		perror("accept");
2389*1a3d31e3SAndroid Build Coastguard Worker 	} else {
2390*1a3d31e3SAndroid Build Coastguard Worker 		ch = net_find_client_host(ns, ns->addr.sin_addr);
2391*1a3d31e3SAndroid Build Coastguard Worker 		if (!ch)
2392*1a3d31e3SAndroid Build Coastguard Worker 			ch = net_add_client_host(ns, &ns->addr);
2393*1a3d31e3SAndroid Build Coastguard Worker 
2394*1a3d31e3SAndroid Build Coastguard Worker 		ch_add_connection(ns, ch, fd);
2395*1a3d31e3SAndroid Build Coastguard Worker 	}
2396*1a3d31e3SAndroid Build Coastguard Worker }
2397*1a3d31e3SAndroid Build Coastguard Worker 
nc_add_dpp(struct cl_conn * nc,struct blktrace_net_hdr * bnh,time_t connect_time)2398*1a3d31e3SAndroid Build Coastguard Worker static struct devpath *nc_add_dpp(struct cl_conn *nc,
2399*1a3d31e3SAndroid Build Coastguard Worker 				  struct blktrace_net_hdr *bnh,
2400*1a3d31e3SAndroid Build Coastguard Worker 				  time_t connect_time)
2401*1a3d31e3SAndroid Build Coastguard Worker {
2402*1a3d31e3SAndroid Build Coastguard Worker 	int cpu;
2403*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *iop;
2404*1a3d31e3SAndroid Build Coastguard Worker 	struct devpath *dpp;
2405*1a3d31e3SAndroid Build Coastguard Worker 
2406*1a3d31e3SAndroid Build Coastguard Worker 	dpp = malloc(sizeof(*dpp));
2407*1a3d31e3SAndroid Build Coastguard Worker 	memset(dpp, 0, sizeof(*dpp));
2408*1a3d31e3SAndroid Build Coastguard Worker 
2409*1a3d31e3SAndroid Build Coastguard Worker 	dpp->buts_name = strdup(bnh->buts_name);
2410*1a3d31e3SAndroid Build Coastguard Worker 	dpp->path = strdup(bnh->buts_name);
2411*1a3d31e3SAndroid Build Coastguard Worker 	dpp->fd = -1;
2412*1a3d31e3SAndroid Build Coastguard Worker 	dpp->ch = nc->ch;
2413*1a3d31e3SAndroid Build Coastguard Worker 	dpp->cl_id = bnh->cl_id;
2414*1a3d31e3SAndroid Build Coastguard Worker 	dpp->cl_connect_time = connect_time;
2415*1a3d31e3SAndroid Build Coastguard Worker 	dpp->ncpus = nc->ncpus;
2416*1a3d31e3SAndroid Build Coastguard Worker 	dpp->stats = calloc(dpp->ncpus, sizeof(*dpp->stats));
2417*1a3d31e3SAndroid Build Coastguard Worker 	memset(dpp->stats, 0, dpp->ncpus * sizeof(*dpp->stats));
2418*1a3d31e3SAndroid Build Coastguard Worker 
2419*1a3d31e3SAndroid Build Coastguard Worker 	list_add_tail(&dpp->head, &nc->ch->devpaths);
2420*1a3d31e3SAndroid Build Coastguard Worker 	nc->ch->ndevs++;
2421*1a3d31e3SAndroid Build Coastguard Worker 
2422*1a3d31e3SAndroid Build Coastguard Worker 	dpp->ios = calloc(nc->ncpus, sizeof(*iop));
2423*1a3d31e3SAndroid Build Coastguard Worker 	memset(dpp->ios, 0, ndevs * sizeof(*iop));
2424*1a3d31e3SAndroid Build Coastguard Worker 
2425*1a3d31e3SAndroid Build Coastguard Worker 	for (cpu = 0, iop = dpp->ios; cpu < nc->ncpus; cpu++, iop++) {
2426*1a3d31e3SAndroid Build Coastguard Worker 		iop->dpp = dpp;
2427*1a3d31e3SAndroid Build Coastguard Worker 		iop->nc = nc;
2428*1a3d31e3SAndroid Build Coastguard Worker 		init_mmap_info(&iop->mmap_info);
2429*1a3d31e3SAndroid Build Coastguard Worker 
2430*1a3d31e3SAndroid Build Coastguard Worker 		if (iop_open(iop, cpu))
2431*1a3d31e3SAndroid Build Coastguard Worker 			goto err;
2432*1a3d31e3SAndroid Build Coastguard Worker 	}
2433*1a3d31e3SAndroid Build Coastguard Worker 
2434*1a3d31e3SAndroid Build Coastguard Worker 	return dpp;
2435*1a3d31e3SAndroid Build Coastguard Worker 
2436*1a3d31e3SAndroid Build Coastguard Worker err:
2437*1a3d31e3SAndroid Build Coastguard Worker 	/*
2438*1a3d31e3SAndroid Build Coastguard Worker 	 * Need to unravel what's been done...
2439*1a3d31e3SAndroid Build Coastguard Worker 	 */
2440*1a3d31e3SAndroid Build Coastguard Worker 	while (cpu >= 0)
2441*1a3d31e3SAndroid Build Coastguard Worker 		close_iop(&dpp->ios[cpu--]);
2442*1a3d31e3SAndroid Build Coastguard Worker 	dpp_free(dpp);
2443*1a3d31e3SAndroid Build Coastguard Worker 
2444*1a3d31e3SAndroid Build Coastguard Worker 	return NULL;
2445*1a3d31e3SAndroid Build Coastguard Worker }
2446*1a3d31e3SAndroid Build Coastguard Worker 
nc_find_dpp(struct cl_conn * nc,struct blktrace_net_hdr * bnh)2447*1a3d31e3SAndroid Build Coastguard Worker static struct devpath *nc_find_dpp(struct cl_conn *nc,
2448*1a3d31e3SAndroid Build Coastguard Worker 				   struct blktrace_net_hdr *bnh)
2449*1a3d31e3SAndroid Build Coastguard Worker {
2450*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
2451*1a3d31e3SAndroid Build Coastguard Worker 	time_t connect_time = nc->connect_time;
2452*1a3d31e3SAndroid Build Coastguard Worker 
2453*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &nc->ch->devpaths) {
2454*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp = list_entry(p, struct devpath, head);
2455*1a3d31e3SAndroid Build Coastguard Worker 
2456*1a3d31e3SAndroid Build Coastguard Worker 		if (!strcmp(dpp->buts_name, bnh->buts_name))
2457*1a3d31e3SAndroid Build Coastguard Worker 			return dpp;
2458*1a3d31e3SAndroid Build Coastguard Worker 
2459*1a3d31e3SAndroid Build Coastguard Worker 		if (dpp->cl_id == bnh->cl_id)
2460*1a3d31e3SAndroid Build Coastguard Worker 			connect_time = dpp->cl_connect_time;
2461*1a3d31e3SAndroid Build Coastguard Worker 	}
2462*1a3d31e3SAndroid Build Coastguard Worker 
2463*1a3d31e3SAndroid Build Coastguard Worker 	return nc_add_dpp(nc, bnh, connect_time);
2464*1a3d31e3SAndroid Build Coastguard Worker }
2465*1a3d31e3SAndroid Build Coastguard Worker 
net_client_read_data(struct cl_conn * nc,struct devpath * dpp,struct blktrace_net_hdr * bnh)2466*1a3d31e3SAndroid Build Coastguard Worker static void net_client_read_data(struct cl_conn *nc, struct devpath *dpp,
2467*1a3d31e3SAndroid Build Coastguard Worker 				 struct blktrace_net_hdr *bnh)
2468*1a3d31e3SAndroid Build Coastguard Worker {
2469*1a3d31e3SAndroid Build Coastguard Worker 	int ret;
2470*1a3d31e3SAndroid Build Coastguard Worker 	struct io_info *iop = &dpp->ios[bnh->cpu];
2471*1a3d31e3SAndroid Build Coastguard Worker 	struct mmap_info *mip = &iop->mmap_info;
2472*1a3d31e3SAndroid Build Coastguard Worker 
2473*1a3d31e3SAndroid Build Coastguard Worker 	if (setup_mmap(iop->ofd, bnh->len, &iop->mmap_info, NULL)) {
2474*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "ncd(%s:%d): mmap failed\n",
2475*1a3d31e3SAndroid Build Coastguard Worker 			nc->ch->hostname, nc->fd);
2476*1a3d31e3SAndroid Build Coastguard Worker 		exit(1);
2477*1a3d31e3SAndroid Build Coastguard Worker 	}
2478*1a3d31e3SAndroid Build Coastguard Worker 
2479*1a3d31e3SAndroid Build Coastguard Worker 	ret = net_recv_data(nc->fd, mip->fs_buf + mip->fs_off, bnh->len);
2480*1a3d31e3SAndroid Build Coastguard Worker 	if (ret > 0) {
2481*1a3d31e3SAndroid Build Coastguard Worker 		pdc_dr_update(dpp, bnh->cpu, ret);
2482*1a3d31e3SAndroid Build Coastguard Worker 		mip->fs_size += ret;
2483*1a3d31e3SAndroid Build Coastguard Worker 		mip->fs_off += ret;
2484*1a3d31e3SAndroid Build Coastguard Worker 	} else if (ret < 0)
2485*1a3d31e3SAndroid Build Coastguard Worker 		exit(1);
2486*1a3d31e3SAndroid Build Coastguard Worker }
2487*1a3d31e3SAndroid Build Coastguard Worker 
2488*1a3d31e3SAndroid Build Coastguard Worker /*
2489*1a3d31e3SAndroid Build Coastguard Worker  * Returns 1 if we closed a host - invalidates other polling information
2490*1a3d31e3SAndroid Build Coastguard Worker  * that may be present.
2491*1a3d31e3SAndroid Build Coastguard Worker  */
net_client_data(struct cl_conn * nc)2492*1a3d31e3SAndroid Build Coastguard Worker static int net_client_data(struct cl_conn *nc)
2493*1a3d31e3SAndroid Build Coastguard Worker {
2494*1a3d31e3SAndroid Build Coastguard Worker 	int ret;
2495*1a3d31e3SAndroid Build Coastguard Worker 	struct devpath *dpp;
2496*1a3d31e3SAndroid Build Coastguard Worker 	struct blktrace_net_hdr bnh;
2497*1a3d31e3SAndroid Build Coastguard Worker 
2498*1a3d31e3SAndroid Build Coastguard Worker 	ret = net_get_header(nc, &bnh);
2499*1a3d31e3SAndroid Build Coastguard Worker 	if (ret == 0)
2500*1a3d31e3SAndroid Build Coastguard Worker 		return 0;
2501*1a3d31e3SAndroid Build Coastguard Worker 
2502*1a3d31e3SAndroid Build Coastguard Worker 	if (ret < 0) {
2503*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "ncd(%d): header read failed\n", nc->fd);
2504*1a3d31e3SAndroid Build Coastguard Worker 		exit(1);
2505*1a3d31e3SAndroid Build Coastguard Worker 	}
2506*1a3d31e3SAndroid Build Coastguard Worker 
2507*1a3d31e3SAndroid Build Coastguard Worker 	if (data_is_native == -1 && check_data_endianness(bnh.magic)) {
2508*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "ncd(%d): received data is bad\n", nc->fd);
2509*1a3d31e3SAndroid Build Coastguard Worker 		exit(1);
2510*1a3d31e3SAndroid Build Coastguard Worker 	}
2511*1a3d31e3SAndroid Build Coastguard Worker 
2512*1a3d31e3SAndroid Build Coastguard Worker 	if (!data_is_native) {
2513*1a3d31e3SAndroid Build Coastguard Worker 		bnh.magic = be32_to_cpu(bnh.magic);
2514*1a3d31e3SAndroid Build Coastguard Worker 		bnh.cpu = be32_to_cpu(bnh.cpu);
2515*1a3d31e3SAndroid Build Coastguard Worker 		bnh.max_cpus = be32_to_cpu(bnh.max_cpus);
2516*1a3d31e3SAndroid Build Coastguard Worker 		bnh.len = be32_to_cpu(bnh.len);
2517*1a3d31e3SAndroid Build Coastguard Worker 		bnh.cl_id = be32_to_cpu(bnh.cl_id);
2518*1a3d31e3SAndroid Build Coastguard Worker 		bnh.buf_size = be32_to_cpu(bnh.buf_size);
2519*1a3d31e3SAndroid Build Coastguard Worker 		bnh.buf_nr = be32_to_cpu(bnh.buf_nr);
2520*1a3d31e3SAndroid Build Coastguard Worker 		bnh.page_size = be32_to_cpu(bnh.page_size);
2521*1a3d31e3SAndroid Build Coastguard Worker 	}
2522*1a3d31e3SAndroid Build Coastguard Worker 
2523*1a3d31e3SAndroid Build Coastguard Worker 	if ((bnh.magic & 0xffffff00) != BLK_IO_TRACE_MAGIC) {
2524*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "ncd(%s:%d): bad data magic\n",
2525*1a3d31e3SAndroid Build Coastguard Worker 			nc->ch->hostname, nc->fd);
2526*1a3d31e3SAndroid Build Coastguard Worker 		exit(1);
2527*1a3d31e3SAndroid Build Coastguard Worker 	}
2528*1a3d31e3SAndroid Build Coastguard Worker 
2529*1a3d31e3SAndroid Build Coastguard Worker 	if (nc->ncpus == -1)
2530*1a3d31e3SAndroid Build Coastguard Worker 		nc->ncpus = bnh.max_cpus;
2531*1a3d31e3SAndroid Build Coastguard Worker 
2532*1a3d31e3SAndroid Build Coastguard Worker 	/*
2533*1a3d31e3SAndroid Build Coastguard Worker 	 * len == 0 means the other end is sending us a new connection/dpp
2534*1a3d31e3SAndroid Build Coastguard Worker 	 * len == 1 means that the other end signalled end-of-run
2535*1a3d31e3SAndroid Build Coastguard Worker 	 */
2536*1a3d31e3SAndroid Build Coastguard Worker 	dpp = nc_find_dpp(nc, &bnh);
2537*1a3d31e3SAndroid Build Coastguard Worker 	if (bnh.len == 0) {
2538*1a3d31e3SAndroid Build Coastguard Worker 		/*
2539*1a3d31e3SAndroid Build Coastguard Worker 		 * Just adding in the dpp above is enough
2540*1a3d31e3SAndroid Build Coastguard Worker 		 */
2541*1a3d31e3SAndroid Build Coastguard Worker 		ack_open_close(nc->fd, dpp->buts_name);
2542*1a3d31e3SAndroid Build Coastguard Worker 		nc->ch->cl_opens++;
2543*1a3d31e3SAndroid Build Coastguard Worker 	} else if (bnh.len == 1) {
2544*1a3d31e3SAndroid Build Coastguard Worker 		/*
2545*1a3d31e3SAndroid Build Coastguard Worker 		 * overload cpu count with dropped events
2546*1a3d31e3SAndroid Build Coastguard Worker 		 */
2547*1a3d31e3SAndroid Build Coastguard Worker 		dpp->drops = bnh.cpu;
2548*1a3d31e3SAndroid Build Coastguard Worker 
2549*1a3d31e3SAndroid Build Coastguard Worker 		ack_open_close(nc->fd, dpp->buts_name);
2550*1a3d31e3SAndroid Build Coastguard Worker 		if (--nc->ch->cl_opens == 0) {
2551*1a3d31e3SAndroid Build Coastguard Worker 			show_stats(&nc->ch->devpaths);
2552*1a3d31e3SAndroid Build Coastguard Worker 			net_ch_remove(nc->ch, nc->ncpus);
2553*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
2554*1a3d31e3SAndroid Build Coastguard Worker 		}
2555*1a3d31e3SAndroid Build Coastguard Worker 	} else
2556*1a3d31e3SAndroid Build Coastguard Worker 		net_client_read_data(nc, dpp, &bnh);
2557*1a3d31e3SAndroid Build Coastguard Worker 
2558*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
2559*1a3d31e3SAndroid Build Coastguard Worker }
2560*1a3d31e3SAndroid Build Coastguard Worker 
handle_client_data(struct net_server_s * ns,int events)2561*1a3d31e3SAndroid Build Coastguard Worker static void handle_client_data(struct net_server_s *ns, int events)
2562*1a3d31e3SAndroid Build Coastguard Worker {
2563*1a3d31e3SAndroid Build Coastguard Worker 	struct cl_conn *nc;
2564*1a3d31e3SAndroid Build Coastguard Worker 	struct pollfd *pfd;
2565*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p, *q;
2566*1a3d31e3SAndroid Build Coastguard Worker 
2567*1a3d31e3SAndroid Build Coastguard Worker 	pfd = &ns->pfds[1];
2568*1a3d31e3SAndroid Build Coastguard Worker 	list_for_each_safe(p, q, &ns->conn_list) {
2569*1a3d31e3SAndroid Build Coastguard Worker 		if (pfd->revents & POLLIN) {
2570*1a3d31e3SAndroid Build Coastguard Worker 			nc = list_entry(p, struct cl_conn, ns_head);
2571*1a3d31e3SAndroid Build Coastguard Worker 
2572*1a3d31e3SAndroid Build Coastguard Worker 			if (net_client_data(nc) || --events == 0)
2573*1a3d31e3SAndroid Build Coastguard Worker 				break;
2574*1a3d31e3SAndroid Build Coastguard Worker 		}
2575*1a3d31e3SAndroid Build Coastguard Worker 		pfd++;
2576*1a3d31e3SAndroid Build Coastguard Worker 	}
2577*1a3d31e3SAndroid Build Coastguard Worker }
2578*1a3d31e3SAndroid Build Coastguard Worker 
net_setup_pfds(struct net_server_s * ns)2579*1a3d31e3SAndroid Build Coastguard Worker static void net_setup_pfds(struct net_server_s *ns)
2580*1a3d31e3SAndroid Build Coastguard Worker {
2581*1a3d31e3SAndroid Build Coastguard Worker 	struct pollfd *pfd;
2582*1a3d31e3SAndroid Build Coastguard Worker 	struct list_head *p;
2583*1a3d31e3SAndroid Build Coastguard Worker 
2584*1a3d31e3SAndroid Build Coastguard Worker 	ns->pfds[0].fd = ns->listen_fd;
2585*1a3d31e3SAndroid Build Coastguard Worker 	ns->pfds[0].events = POLLIN;
2586*1a3d31e3SAndroid Build Coastguard Worker 
2587*1a3d31e3SAndroid Build Coastguard Worker 	pfd = &ns->pfds[1];
2588*1a3d31e3SAndroid Build Coastguard Worker 	__list_for_each(p, &ns->conn_list) {
2589*1a3d31e3SAndroid Build Coastguard Worker 		struct cl_conn *nc = list_entry(p, struct cl_conn, ns_head);
2590*1a3d31e3SAndroid Build Coastguard Worker 
2591*1a3d31e3SAndroid Build Coastguard Worker 		pfd->fd = nc->fd;
2592*1a3d31e3SAndroid Build Coastguard Worker 		pfd->events = POLLIN;
2593*1a3d31e3SAndroid Build Coastguard Worker 		pfd++;
2594*1a3d31e3SAndroid Build Coastguard Worker 	}
2595*1a3d31e3SAndroid Build Coastguard Worker }
2596*1a3d31e3SAndroid Build Coastguard Worker 
net_server_handle_connections(struct net_server_s * ns)2597*1a3d31e3SAndroid Build Coastguard Worker static int net_server_handle_connections(struct net_server_s *ns)
2598*1a3d31e3SAndroid Build Coastguard Worker {
2599*1a3d31e3SAndroid Build Coastguard Worker 	int events;
2600*1a3d31e3SAndroid Build Coastguard Worker 
2601*1a3d31e3SAndroid Build Coastguard Worker 	printf("server: waiting for connections...\n");
2602*1a3d31e3SAndroid Build Coastguard Worker 
2603*1a3d31e3SAndroid Build Coastguard Worker 	while (!done) {
2604*1a3d31e3SAndroid Build Coastguard Worker 		net_setup_pfds(ns);
2605*1a3d31e3SAndroid Build Coastguard Worker 		events = poll(ns->pfds, ns->connects + 1, -1);
2606*1a3d31e3SAndroid Build Coastguard Worker 		if (events < 0) {
2607*1a3d31e3SAndroid Build Coastguard Worker 			if (errno != EINTR) {
2608*1a3d31e3SAndroid Build Coastguard Worker 				perror("FATAL: poll error");
2609*1a3d31e3SAndroid Build Coastguard Worker 				return 1;
2610*1a3d31e3SAndroid Build Coastguard Worker 			}
2611*1a3d31e3SAndroid Build Coastguard Worker 		} else if (events > 0) {
2612*1a3d31e3SAndroid Build Coastguard Worker 			if (ns->pfds[0].revents & POLLIN) {
2613*1a3d31e3SAndroid Build Coastguard Worker 				net_add_connection(ns);
2614*1a3d31e3SAndroid Build Coastguard Worker 				events--;
2615*1a3d31e3SAndroid Build Coastguard Worker 			}
2616*1a3d31e3SAndroid Build Coastguard Worker 
2617*1a3d31e3SAndroid Build Coastguard Worker 			if (events)
2618*1a3d31e3SAndroid Build Coastguard Worker 				handle_client_data(ns, events);
2619*1a3d31e3SAndroid Build Coastguard Worker 		}
2620*1a3d31e3SAndroid Build Coastguard Worker 	}
2621*1a3d31e3SAndroid Build Coastguard Worker 
2622*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
2623*1a3d31e3SAndroid Build Coastguard Worker }
2624*1a3d31e3SAndroid Build Coastguard Worker 
net_server(void)2625*1a3d31e3SAndroid Build Coastguard Worker static int net_server(void)
2626*1a3d31e3SAndroid Build Coastguard Worker {
2627*1a3d31e3SAndroid Build Coastguard Worker 	int fd, opt;
2628*1a3d31e3SAndroid Build Coastguard Worker 	int ret = 1;
2629*1a3d31e3SAndroid Build Coastguard Worker 	struct net_server_s net_server;
2630*1a3d31e3SAndroid Build Coastguard Worker 	struct net_server_s *ns = &net_server;
2631*1a3d31e3SAndroid Build Coastguard Worker 
2632*1a3d31e3SAndroid Build Coastguard Worker 	memset(ns, 0, sizeof(*ns));
2633*1a3d31e3SAndroid Build Coastguard Worker 	INIT_LIST_HEAD(&ns->ch_list);
2634*1a3d31e3SAndroid Build Coastguard Worker 	INIT_LIST_HEAD(&ns->conn_list);
2635*1a3d31e3SAndroid Build Coastguard Worker 	ns->pfds = malloc(sizeof(struct pollfd));
2636*1a3d31e3SAndroid Build Coastguard Worker 
2637*1a3d31e3SAndroid Build Coastguard Worker 	fd = my_socket(AF_INET, SOCK_STREAM, 0);
2638*1a3d31e3SAndroid Build Coastguard Worker 	if (fd < 0) {
2639*1a3d31e3SAndroid Build Coastguard Worker 		perror("server: socket");
2640*1a3d31e3SAndroid Build Coastguard Worker 		goto out;
2641*1a3d31e3SAndroid Build Coastguard Worker 	}
2642*1a3d31e3SAndroid Build Coastguard Worker 
2643*1a3d31e3SAndroid Build Coastguard Worker 	opt = 1;
2644*1a3d31e3SAndroid Build Coastguard Worker 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
2645*1a3d31e3SAndroid Build Coastguard Worker 		perror("setsockopt");
2646*1a3d31e3SAndroid Build Coastguard Worker 		goto out;
2647*1a3d31e3SAndroid Build Coastguard Worker 	}
2648*1a3d31e3SAndroid Build Coastguard Worker 
2649*1a3d31e3SAndroid Build Coastguard Worker 	memset(&ns->addr, 0, sizeof(ns->addr));
2650*1a3d31e3SAndroid Build Coastguard Worker 	ns->addr.sin_family = AF_INET;
2651*1a3d31e3SAndroid Build Coastguard Worker 	ns->addr.sin_addr.s_addr = htonl(INADDR_ANY);
2652*1a3d31e3SAndroid Build Coastguard Worker 	ns->addr.sin_port = htons(net_port);
2653*1a3d31e3SAndroid Build Coastguard Worker 
2654*1a3d31e3SAndroid Build Coastguard Worker 	if (bind(fd, (struct sockaddr *) &ns->addr, sizeof(ns->addr)) < 0) {
2655*1a3d31e3SAndroid Build Coastguard Worker 		perror("bind");
2656*1a3d31e3SAndroid Build Coastguard Worker 		goto out;
2657*1a3d31e3SAndroid Build Coastguard Worker 	}
2658*1a3d31e3SAndroid Build Coastguard Worker 
2659*1a3d31e3SAndroid Build Coastguard Worker 	if (listen(fd, 1) < 0) {
2660*1a3d31e3SAndroid Build Coastguard Worker 		perror("listen");
2661*1a3d31e3SAndroid Build Coastguard Worker 		goto out;
2662*1a3d31e3SAndroid Build Coastguard Worker 	}
2663*1a3d31e3SAndroid Build Coastguard Worker 
2664*1a3d31e3SAndroid Build Coastguard Worker 	/*
2665*1a3d31e3SAndroid Build Coastguard Worker 	 * The actual server looping is done here:
2666*1a3d31e3SAndroid Build Coastguard Worker 	 */
2667*1a3d31e3SAndroid Build Coastguard Worker 	ns->listen_fd = fd;
2668*1a3d31e3SAndroid Build Coastguard Worker 	ret = net_server_handle_connections(ns);
2669*1a3d31e3SAndroid Build Coastguard Worker 
2670*1a3d31e3SAndroid Build Coastguard Worker 	/*
2671*1a3d31e3SAndroid Build Coastguard Worker 	 * Clean up and return...
2672*1a3d31e3SAndroid Build Coastguard Worker 	 */
2673*1a3d31e3SAndroid Build Coastguard Worker out:
2674*1a3d31e3SAndroid Build Coastguard Worker 	free(ns->pfds);
2675*1a3d31e3SAndroid Build Coastguard Worker 	return ret;
2676*1a3d31e3SAndroid Build Coastguard Worker }
2677*1a3d31e3SAndroid Build Coastguard Worker 
run_tracers(void)2678*1a3d31e3SAndroid Build Coastguard Worker static int run_tracers(void)
2679*1a3d31e3SAndroid Build Coastguard Worker {
2680*1a3d31e3SAndroid Build Coastguard Worker 	atexit(exit_tracing);
2681*1a3d31e3SAndroid Build Coastguard Worker 	if (net_mode == Net_client)
2682*1a3d31e3SAndroid Build Coastguard Worker 		printf("blktrace: connecting to %s\n", hostname);
2683*1a3d31e3SAndroid Build Coastguard Worker 
2684*1a3d31e3SAndroid Build Coastguard Worker 	if (setup_buts())
2685*1a3d31e3SAndroid Build Coastguard Worker 		return 1;
2686*1a3d31e3SAndroid Build Coastguard Worker 
2687*1a3d31e3SAndroid Build Coastguard Worker 	if (use_tracer_devpaths()) {
2688*1a3d31e3SAndroid Build Coastguard Worker 		if (setup_tracer_devpaths())
2689*1a3d31e3SAndroid Build Coastguard Worker 			return 1;
2690*1a3d31e3SAndroid Build Coastguard Worker 
2691*1a3d31e3SAndroid Build Coastguard Worker 		if (piped_output)
2692*1a3d31e3SAndroid Build Coastguard Worker 			handle_list = handle_list_file;
2693*1a3d31e3SAndroid Build Coastguard Worker 		else
2694*1a3d31e3SAndroid Build Coastguard Worker 			handle_list = handle_list_net;
2695*1a3d31e3SAndroid Build Coastguard Worker 	}
2696*1a3d31e3SAndroid Build Coastguard Worker 
2697*1a3d31e3SAndroid Build Coastguard Worker 	start_tracers();
2698*1a3d31e3SAndroid Build Coastguard Worker 	if (nthreads_running == ncpus) {
2699*1a3d31e3SAndroid Build Coastguard Worker 		unblock_tracers();
2700*1a3d31e3SAndroid Build Coastguard Worker 		start_buts();
2701*1a3d31e3SAndroid Build Coastguard Worker 		if (net_mode == Net_client)
2702*1a3d31e3SAndroid Build Coastguard Worker 			printf("blktrace: connected!\n");
2703*1a3d31e3SAndroid Build Coastguard Worker 		if (stop_watch)
2704*1a3d31e3SAndroid Build Coastguard Worker 			alarm(stop_watch);
2705*1a3d31e3SAndroid Build Coastguard Worker 	} else
2706*1a3d31e3SAndroid Build Coastguard Worker 		stop_tracers();
2707*1a3d31e3SAndroid Build Coastguard Worker 
2708*1a3d31e3SAndroid Build Coastguard Worker 	wait_tracers();
2709*1a3d31e3SAndroid Build Coastguard Worker 	if (nthreads_running == ncpus)
2710*1a3d31e3SAndroid Build Coastguard Worker 		show_stats(&devpaths);
2711*1a3d31e3SAndroid Build Coastguard Worker 	if (net_client_use_send())
2712*1a3d31e3SAndroid Build Coastguard Worker 		close_client_connections();
2713*1a3d31e3SAndroid Build Coastguard Worker 	del_tracers();
2714*1a3d31e3SAndroid Build Coastguard Worker 
2715*1a3d31e3SAndroid Build Coastguard Worker 	return 0;
2716*1a3d31e3SAndroid Build Coastguard Worker }
2717*1a3d31e3SAndroid Build Coastguard Worker 
get_online_cpus(void)2718*1a3d31e3SAndroid Build Coastguard Worker static cpu_set_t *get_online_cpus(void)
2719*1a3d31e3SAndroid Build Coastguard Worker {
2720*1a3d31e3SAndroid Build Coastguard Worker 	FILE *cpus;
2721*1a3d31e3SAndroid Build Coastguard Worker 	cpu_set_t *set;
2722*1a3d31e3SAndroid Build Coastguard Worker 	size_t alloc_size;
2723*1a3d31e3SAndroid Build Coastguard Worker 	int cpuid, prevcpuid = -1;
2724*1a3d31e3SAndroid Build Coastguard Worker 	char nextch;
2725*1a3d31e3SAndroid Build Coastguard Worker 	int n, ncpu, curcpu = 0;
2726*1a3d31e3SAndroid Build Coastguard Worker 	int *cpu_nums;
2727*1a3d31e3SAndroid Build Coastguard Worker 
2728*1a3d31e3SAndroid Build Coastguard Worker 	ncpu = sysconf(_SC_NPROCESSORS_CONF);
2729*1a3d31e3SAndroid Build Coastguard Worker 	if (ncpu < 0)
2730*1a3d31e3SAndroid Build Coastguard Worker 		return NULL;
2731*1a3d31e3SAndroid Build Coastguard Worker 
2732*1a3d31e3SAndroid Build Coastguard Worker 	cpu_nums = malloc(sizeof(int)*ncpu);
2733*1a3d31e3SAndroid Build Coastguard Worker 	if (!cpu_nums) {
2734*1a3d31e3SAndroid Build Coastguard Worker 		errno = ENOMEM;
2735*1a3d31e3SAndroid Build Coastguard Worker 		return NULL;
2736*1a3d31e3SAndroid Build Coastguard Worker 	}
2737*1a3d31e3SAndroid Build Coastguard Worker 
2738*1a3d31e3SAndroid Build Coastguard Worker 	/*
2739*1a3d31e3SAndroid Build Coastguard Worker 	 * There is no way to easily get maximum CPU number. So we have to
2740*1a3d31e3SAndroid Build Coastguard Worker 	 * parse the file first to find it out and then create appropriate
2741*1a3d31e3SAndroid Build Coastguard Worker 	 * cpuset
2742*1a3d31e3SAndroid Build Coastguard Worker 	 */
2743*1a3d31e3SAndroid Build Coastguard Worker 	cpus = my_fopen("/sys/devices/system/cpu/online", "r");
2744*1a3d31e3SAndroid Build Coastguard Worker 	for (;;) {
2745*1a3d31e3SAndroid Build Coastguard Worker 		n = fscanf(cpus, "%d%c", &cpuid, &nextch);
2746*1a3d31e3SAndroid Build Coastguard Worker 		if (n <= 0)
2747*1a3d31e3SAndroid Build Coastguard Worker 			break;
2748*1a3d31e3SAndroid Build Coastguard Worker 		if (n == 2 && nextch == '-') {
2749*1a3d31e3SAndroid Build Coastguard Worker 			prevcpuid = cpuid;
2750*1a3d31e3SAndroid Build Coastguard Worker 			continue;
2751*1a3d31e3SAndroid Build Coastguard Worker 		}
2752*1a3d31e3SAndroid Build Coastguard Worker 		if (prevcpuid == -1)
2753*1a3d31e3SAndroid Build Coastguard Worker 			prevcpuid = cpuid;
2754*1a3d31e3SAndroid Build Coastguard Worker 		while (prevcpuid <= cpuid) {
2755*1a3d31e3SAndroid Build Coastguard Worker 			/* More CPUs listed than configured? */
2756*1a3d31e3SAndroid Build Coastguard Worker 			if (curcpu >= ncpu) {
2757*1a3d31e3SAndroid Build Coastguard Worker 				errno = EINVAL;
2758*1a3d31e3SAndroid Build Coastguard Worker 				return NULL;
2759*1a3d31e3SAndroid Build Coastguard Worker 			}
2760*1a3d31e3SAndroid Build Coastguard Worker 			cpu_nums[curcpu++] = prevcpuid++;
2761*1a3d31e3SAndroid Build Coastguard Worker 		}
2762*1a3d31e3SAndroid Build Coastguard Worker 		prevcpuid = -1;
2763*1a3d31e3SAndroid Build Coastguard Worker 	}
2764*1a3d31e3SAndroid Build Coastguard Worker 	fclose(cpus);
2765*1a3d31e3SAndroid Build Coastguard Worker 
2766*1a3d31e3SAndroid Build Coastguard Worker 	ncpu = curcpu;
2767*1a3d31e3SAndroid Build Coastguard Worker 	max_cpus = cpu_nums[ncpu - 1] + 1;
2768*1a3d31e3SAndroid Build Coastguard Worker 
2769*1a3d31e3SAndroid Build Coastguard Worker 	/* Now that we have maximum cpu number, create a cpuset */
2770*1a3d31e3SAndroid Build Coastguard Worker 	set = CPU_ALLOC(max_cpus);
2771*1a3d31e3SAndroid Build Coastguard Worker 	if (!set) {
2772*1a3d31e3SAndroid Build Coastguard Worker 		errno = ENOMEM;
2773*1a3d31e3SAndroid Build Coastguard Worker 		return NULL;
2774*1a3d31e3SAndroid Build Coastguard Worker 	}
2775*1a3d31e3SAndroid Build Coastguard Worker 	alloc_size = CPU_ALLOC_SIZE(max_cpus);
2776*1a3d31e3SAndroid Build Coastguard Worker 	CPU_ZERO_S(alloc_size, set);
2777*1a3d31e3SAndroid Build Coastguard Worker 
2778*1a3d31e3SAndroid Build Coastguard Worker 	for (curcpu = 0; curcpu < ncpu; curcpu++)
2779*1a3d31e3SAndroid Build Coastguard Worker 		CPU_SET_S(cpu_nums[curcpu], alloc_size, set);
2780*1a3d31e3SAndroid Build Coastguard Worker 
2781*1a3d31e3SAndroid Build Coastguard Worker 	free(cpu_nums);
2782*1a3d31e3SAndroid Build Coastguard Worker 
2783*1a3d31e3SAndroid Build Coastguard Worker 	return set;
2784*1a3d31e3SAndroid Build Coastguard Worker }
2785*1a3d31e3SAndroid Build Coastguard Worker 
main(int argc,char * argv[])2786*1a3d31e3SAndroid Build Coastguard Worker int main(int argc, char *argv[])
2787*1a3d31e3SAndroid Build Coastguard Worker {
2788*1a3d31e3SAndroid Build Coastguard Worker 	int ret = 0;
2789*1a3d31e3SAndroid Build Coastguard Worker 
2790*1a3d31e3SAndroid Build Coastguard Worker 	setlocale(LC_NUMERIC, "en_US");
2791*1a3d31e3SAndroid Build Coastguard Worker 	pagesize = getpagesize();
2792*1a3d31e3SAndroid Build Coastguard Worker 	online_cpus = get_online_cpus();
2793*1a3d31e3SAndroid Build Coastguard Worker 	if (!online_cpus) {
2794*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "cannot get online cpus %d/%s\n",
2795*1a3d31e3SAndroid Build Coastguard Worker 			errno, strerror(errno));
2796*1a3d31e3SAndroid Build Coastguard Worker 		ret = 1;
2797*1a3d31e3SAndroid Build Coastguard Worker 		goto out;
2798*1a3d31e3SAndroid Build Coastguard Worker 	} else if (handle_args(argc, argv)) {
2799*1a3d31e3SAndroid Build Coastguard Worker 		ret = 1;
2800*1a3d31e3SAndroid Build Coastguard Worker 		goto out;
2801*1a3d31e3SAndroid Build Coastguard Worker 	}
2802*1a3d31e3SAndroid Build Coastguard Worker 
2803*1a3d31e3SAndroid Build Coastguard Worker 	ncpus = CPU_COUNT_S(CPU_ALLOC_SIZE(max_cpus), online_cpus);
2804*1a3d31e3SAndroid Build Coastguard Worker 	if (ndevs > 1 && output_name && strcmp(output_name, "-") != 0) {
2805*1a3d31e3SAndroid Build Coastguard Worker 		fprintf(stderr, "-o not supported with multiple devices\n");
2806*1a3d31e3SAndroid Build Coastguard Worker 		ret = 1;
2807*1a3d31e3SAndroid Build Coastguard Worker 		goto out;
2808*1a3d31e3SAndroid Build Coastguard Worker 	}
2809*1a3d31e3SAndroid Build Coastguard Worker 
2810*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGINT, handle_sigint);
2811*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGHUP, handle_sigint);
2812*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGTERM, handle_sigint);
2813*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGALRM, handle_sigint);
2814*1a3d31e3SAndroid Build Coastguard Worker 	signal(SIGPIPE, SIG_IGN);
2815*1a3d31e3SAndroid Build Coastguard Worker 
2816*1a3d31e3SAndroid Build Coastguard Worker 	if (kill_running_trace) {
2817*1a3d31e3SAndroid Build Coastguard Worker 		struct devpath *dpp;
2818*1a3d31e3SAndroid Build Coastguard Worker 		struct list_head *p;
2819*1a3d31e3SAndroid Build Coastguard Worker 
2820*1a3d31e3SAndroid Build Coastguard Worker 		__list_for_each(p, &devpaths) {
2821*1a3d31e3SAndroid Build Coastguard Worker 			dpp = list_entry(p, struct devpath, head);
2822*1a3d31e3SAndroid Build Coastguard Worker 			if (__stop_trace(dpp->fd)) {
2823*1a3d31e3SAndroid Build Coastguard Worker 				fprintf(stderr,
2824*1a3d31e3SAndroid Build Coastguard Worker 					"BLKTRACETEARDOWN %s failed: %d/%s\n",
2825*1a3d31e3SAndroid Build Coastguard Worker 					dpp->path, errno, strerror(errno));
2826*1a3d31e3SAndroid Build Coastguard Worker 			}
2827*1a3d31e3SAndroid Build Coastguard Worker 		}
2828*1a3d31e3SAndroid Build Coastguard Worker 	} else if (net_mode == Net_server) {
2829*1a3d31e3SAndroid Build Coastguard Worker 		if (output_name) {
2830*1a3d31e3SAndroid Build Coastguard Worker 			fprintf(stderr, "-o ignored in server mode\n");
2831*1a3d31e3SAndroid Build Coastguard Worker 			output_name = NULL;
2832*1a3d31e3SAndroid Build Coastguard Worker 		}
2833*1a3d31e3SAndroid Build Coastguard Worker 		ret = net_server();
2834*1a3d31e3SAndroid Build Coastguard Worker 	} else
2835*1a3d31e3SAndroid Build Coastguard Worker 		ret = run_tracers();
2836*1a3d31e3SAndroid Build Coastguard Worker 
2837*1a3d31e3SAndroid Build Coastguard Worker out:
2838*1a3d31e3SAndroid Build Coastguard Worker 	if (pfp)
2839*1a3d31e3SAndroid Build Coastguard Worker 		fclose(pfp);
2840*1a3d31e3SAndroid Build Coastguard Worker 	rel_devpaths();
2841*1a3d31e3SAndroid Build Coastguard Worker 	return ret;
2842*1a3d31e3SAndroid Build Coastguard Worker }
2843