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