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