diff options
Diffstat (limited to 'runtime/staprun/relay_old.c')
-rw-r--r-- | runtime/staprun/relay_old.c | 138 |
1 files changed, 128 insertions, 10 deletions
diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c index bd746f19..33d2daf3 100644 --- a/runtime/staprun/relay_old.c +++ b/runtime/staprun/relay_old.c @@ -23,6 +23,14 @@ static int bulkmode = 0; unsigned subbuf_size = 0; unsigned n_subbufs = 0; +struct switchfile_ctrl_block { + off_t wsize; + int fnum; + int rmfile; +}; + +static struct switchfile_ctrl_block global_scb = {0, 0, 0}; + /* per-cpu buffer info */ static struct buf_status { @@ -70,6 +78,41 @@ void close_oldrelayfs(int detach) close_relayfs_files(i); } +static int open_oldoutfile(int fnum, int cpu, int remove_file) +{ + char buf[PATH_MAX]; + time_t t; + if (outfile_name) { + time(&t); + if (fnum_max) { + if (remove_file) { + /* remove oldest file */ + if (make_outfile_name(buf, PATH_MAX, fnum - fnum_max, + cpu, read_backlog(cpu, fnum - fnum_max)) < 0) + return -1; + remove(buf); /* don't care */ + } + write_backlog(cpu, fnum, t); + } + if (make_outfile_name(buf, PATH_MAX, fnum, cpu, t) < 0) + return -1; + } else if (bulkmode) { + if (sprintf_chk(buf, "stpd_cpu%d.%d", cpu, fnum)) + return -1; + } else { /* stream mode */ + out_fd[cpu] = STDOUT_FILENO; + return 0; + } + + out_fd[cpu] = open (buf, O_CREAT|O_TRUNC|O_WRONLY, 0666); + if (out_fd[cpu] < 0) { + perr("Couldn't open output file %s", buf); + return -1; + } + if (set_clexec(out_fd[cpu]) < 0) + return -1; + return 0; +} /** * open_relayfs_files - open and mmap buffer and open output file. * Returns -1 on unexpected failure, 0 if file not found, 1 on success. @@ -104,18 +147,31 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p return -1; } + if (fsize_max) { + if (init_backlog(cpu) < 0) + goto err2; + if (open_oldoutfile(0, cpu, 0) < 0) + goto err2; + goto opened; + } if (outfile_name) { /* special case: for testing we sometimes want to * write to /dev/null */ if (strcmp(outfile_name, "/dev/null") == 0) { strcpy(tmp, "/dev/null"); } else { - if (sprintf_chk(tmp, "%s_%d", outfile_name, cpu)) - goto err1; + int len; + len = stap_strfloctime(tmp, PATH_MAX, outfile_name, time(NULL)); + if (len < 0) { + err("Invalid FILE name format\n"); + goto err2; + } + if (snprintf_chk(&tmp[len], PATH_MAX - len, "_%d", cpu)) + goto err2; } } else { if (sprintf_chk(tmp, "stpd_cpu%d", cpu)) - goto err1; + goto err2; } if((percpu_tmpfile[cpu] = fopen(tmp, "w+")) == NULL) { @@ -126,6 +182,7 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p perr("Couldn't open output file %s", tmp); goto err2; } +opened: total_bufsize = subbuf_size * n_subbufs; relay_buffer[cpu] = mmap(NULL, total_bufsize, PROT_READ, @@ -155,7 +212,8 @@ err1: /** * process_subbufs - write ready subbufs to disk */ -static int process_subbufs(struct _stp_buf_info *info) +static int process_subbufs(struct _stp_buf_info *info, + struct switchfile_ctrl_block *scb) { unsigned subbufs_ready, start_subbuf, end_subbuf, subbuf_idx, i; int len, cpu = info->cpu; @@ -173,10 +231,23 @@ static int process_subbufs(struct _stp_buf_info *info) padding = *((unsigned *)subbuf_ptr); subbuf_ptr += sizeof(padding); len = (subbuf_size - sizeof(padding)) - padding; + scb->wsize += len; + if (fsize_max && scb->wsize > fsize_max) { + fclose(percpu_tmpfile[cpu]); + scb->fnum ++; + if (fnum_max && scb->fnum == fnum_max) + scb->rmfile = 1; + if (open_oldoutfile(scb->fnum, cpu, scb->rmfile) < 0) { + perr("Couldn't open file for cpu %d, exiting.", cpu); + return -1; + } + scb->wsize = len; + } if (len) { if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { - _perr("Couldn't write to output file for cpu %d, exiting:", cpu); - exit(1); + if (errno != EPIPE) + _perr("Couldn't write to output file for cpu %d, exiting:", cpu); + return -1; } } subbufs_consumed++; @@ -196,6 +267,7 @@ static void *reader_thread(void *data) struct _stp_consumed_info consumed_info; unsigned subbufs_consumed; cpu_set_t cpu_mask; + struct switchfile_ctrl_block scb = {0, 0, 0}; CPU_ZERO(&cpu_mask); CPU_SET(cpu, &cpu_mask); @@ -210,14 +282,17 @@ static void *reader_thread(void *data) if (rc < 0) { if (errno != EINTR) { _perr("poll error"); - exit(1); + break; } err("WARNING: poll warning: %s\n", strerror(errno)); rc = 0; } rc = read(proc_fd[cpu], &status[cpu].info, sizeof(struct _stp_buf_info)); - subbufs_consumed = process_subbufs(&status[cpu].info); + rc = process_subbufs(&status[cpu].info, &scb); + if (rc < 0) + break; + subbufs_consumed = rc; if (subbufs_consumed) { if (subbufs_consumed > status[cpu].max_backlog) status[cpu].max_backlog = subbufs_consumed; @@ -230,6 +305,37 @@ static void *reader_thread(void *data) if (status[cpu].info.flushing) pthread_exit(NULL); } while (1); + + /* Signal the main thread that we need to quit */ + kill(getpid(), SIGTERM); + pthread_exit(NULL); +} + +/** + * write_realtime_data - write realtime data packet to disk + */ +int write_realtime_data(void *data, ssize_t nb) +{ + ssize_t bw; + global_scb.wsize += nb; + if (fsize_max && global_scb.wsize > fsize_max) { + close(out_fd[0]); + global_scb.fnum++; + if (fnum_max && global_scb.fnum == fnum_max) + global_scb.rmfile = 1; + if (open_oldoutfile(global_scb.fnum, 0, + global_scb.rmfile) < 0) { + perr("Couldn't open file, exiting."); + return -1; + } + global_scb.wsize = nb; + } + bw = write(out_fd[0], data, nb); + if (bw >= 0 && bw != nb) { + nb = nb - bw; + bw = write(out_fd[0], data, nb); + } + return bw != nb; } /** @@ -249,10 +355,22 @@ int init_oldrelayfs(void) bulkmode = 1; if (!bulkmode) { + int len; + char tmp[PATH_MAX]; + if (fsize_max) { + if (init_backlog(0)) + return -1; + return open_oldoutfile(0, 0, 0); + } if (outfile_name) { - out_fd[0] = open (outfile_name, O_CREAT|O_TRUNC|O_WRONLY, 0666); + len = stap_strfloctime(tmp, PATH_MAX, outfile_name, time(NULL)); + if (len < 0) { + err("Invalid FILE name format\n"); + return -1; + } + out_fd[0] = open (tmp, O_CREAT|O_TRUNC|O_WRONLY, 0666); if (out_fd[0] < 0 || set_clexec(out_fd[0]) < 0) { - perr("Couldn't open output file '%s'", outfile_name); + perr("Couldn't open output file '%s'", tmp); return -1; } } else |