struct cl_host *ch;
u32 cl_id;
time_t cl_connect_time;
+ int setup_done; /* ioctl BLKTRACESETUP done */
struct io_info *ios;
};
}
}
-static void setup_buts(void)
+static int setup_buts(void)
{
struct list_head *p;
+ int ret = 0;
__list_for_each(p, &devpaths) {
struct blk_user_trace_setup buts;
if (ioctl(dpp->fd, BLKTRACESETUP, &buts) >= 0) {
dpp->ncpus = max_cpus;
dpp->buts_name = strdup(buts.name);
+ dpp->setup_done = 1;
if (dpp->stats)
free(dpp->stats);
dpp->stats = calloc(dpp->ncpus, sizeof(*dpp->stats));
memset(dpp->stats, 0, dpp->ncpus * sizeof(*dpp->stats));
- } else
+ } else {
fprintf(stderr, "BLKTRACESETUP(2) %s failed: %d/%s\n",
dpp->path, errno, strerror(errno));
+ ret++;
+ }
}
+
+ return ret;
}
static void start_buts(void)
struct devpath *dpp = list_entry(p, struct devpath, head);
list_del(&dpp->head);
- __stop_trace(dpp->fd);
+ if (dpp->setup_done)
+ __stop_trace(dpp->fd);
close(dpp->fd);
if (dpp->heads)
return 0;
}
+static int create_output_files(int cpu)
+{
+ char fname[MAXPATHLEN + 64];
+ struct list_head *p;
+ FILE *f;
+
+ __list_for_each(p, &devpaths) {
+ struct devpath *dpp = list_entry(p, struct devpath, head);
+
+ if (fill_ofname(fname, sizeof(fname), NULL, dpp->buts_name,
+ cpu))
+ return 1;
+ f = my_fopen(fname, "w+");
+ if (!f)
+ return 1;
+ fclose(f);
+ }
+ return 0;
+}
+
static void start_tracers(void)
{
int cpu, started = 0;
size_t alloc_size = CPU_ALLOC_SIZE(max_cpus);
for (cpu = 0; cpu < max_cpus; cpu++) {
- if (!CPU_ISSET_S(cpu, alloc_size, online_cpus))
+ if (!CPU_ISSET_S(cpu, alloc_size, online_cpus)) {
+ /*
+ * Create fake empty output files so that other tools
+ * like blkparse don't have to bother with sparse CPU
+ * number space.
+ */
+ if (create_output_files(cpu))
+ break;
continue;
+ }
if (start_tracer(cpu))
break;
started++;
if (net_mode == Net_client)
printf("blktrace: connecting to %s\n", hostname);
- setup_buts();
+ if (setup_buts())
+ return 1;
if (use_tracer_devpaths()) {
if (setup_tracer_devpaths())