On Fri, 13 Sep 2013 11:06:37 +0900
Yoshihiro YUNOMAE <yoshihiro.yunomae...@hitachi.com> wrote:

>  static int *create_all_readers(int cpus, const char *node, const char *port,
> -                            int pagesize, int fd)
> +                            const char *domain, int virtpid, int pagesize, 
> int fd)
>  {
>       char buf[BUFSIZ];
> -     int *port_array;
> +     int *port_array = NULL;
>       int *pid_array;
>       int start_port;
>       int udp_port;
>       int cpu;
>       int pid;
>  
> -     port_array = malloc_or_die(sizeof(int) * cpus);
> +     if (node) {
> +             port_array = malloc_or_die(sizeof(int) * cpus);
> +             start_port = START_PORT_SEARCH;
> +     }
>       pid_array = malloc_or_die(sizeof(int) * cpus);
>       memset(pid_array, 0, sizeof(int) * cpus);
>  
> -     start_port = START_PORT_SEARCH;
> -
> -     /* Now create a UDP port for each CPU */
> +     /* Now create a reader for each CPU */
>       for (cpu = 0; cpu < cpus; cpu++) {
> -             udp_port = open_udp(node, port, &pid, cpu,
> -                                 pagesize, start_port);
> -             if (udp_port < 0)
> -                     goto out_free;
> -             port_array[cpu] = udp_port;
> +             if (node) {
> +                     udp_port = open_udp(node, port, &pid, cpu,
> +                                         pagesize, start_port);
> +                     if (udp_port < 0)
> +                             goto out_free;
> +                     port_array[cpu] = udp_port;
> +                     /*
> +                      * due to some bugging finding ports,

s/due/Due/

> +                      * force search after last port
> +                      */
> +                     start_port = udp_port + 1;
> +             } else {
> +                     if (open_virtio_serial_pipe(&pid, cpu, pagesize,
> +                                                 domain, virtpid) < 0)
> +                             goto out_free;
> +             }
>               pid_array[cpu] = pid;
>               /*
>                * Due to some bugging finding ports,

Hmm, it seems that you added the start_port = udp_port + 1 above, but
shouldn't you remove the one here?

> @@ -482,7 +595,7 @@ static int *create_all_readers(int cpus, const char 
> *node, const char *port,
>       return pid_array;
>  
>   out_free:
> -     destroy_all_readers(cpus, pid_array, node, port);
> +     destroy_all_readers(cpus, pid_array, node, port, domain, virtpid);
>       return NULL;
>  }
>  
> @@ -524,7 +637,7 @@ static void stop_all_readers(int cpus, int *pid_array)
>  }
>  
>  static void put_together_file(int cpus, int ofd, const char *node,
> -                           const char *port)
> +                           const char *port, const char *domain, int virtpid)
>  {
>       char **temp_files;
>       int cpu;
> @@ -533,25 +646,31 @@ static void put_together_file(int cpus, int ofd, const 
> char *node,
>       temp_files = malloc_or_die(sizeof(*temp_files) * cpus);
>  
>       for (cpu = 0; cpu < cpus; cpu++)
> -             temp_files[cpu] = get_temp_file(node, port, cpu);
> +             temp_files[cpu] = get_temp_file(node, port, domain,
> +                                             virtpid, cpu);
>  
>       tracecmd_attach_cpu_data_fd(ofd, cpus, temp_files);
>       free(temp_files);
>  }
>  
> -static void process_client(const char *node, const char *port, int fd)
> +static void process_client(const char *node, const char *port,
> +                        const char *domain, int virtpid, int fd)
>  {
>       int *pid_array;
>       int pagesize;
>       int cpus;
>       int ofd;
>  
> -     if (communicate_with_client(fd, &cpus, &pagesize) < 0)
> -             return;
> -
> -     ofd = create_client_file(node, port);
> +     if (node) {
> +             if (communicate_with_client_nw(fd, &cpus, &pagesize) < 0)

I take it _nw is for "network". If so, please use "*_net" instead. "nw"
is pretty meaningless.

This applies for all functions.

-- Steve

> +                     return;
> +     } else {
> +             if (communicate_with_client_virt(fd, domain, &cpus, &pagesize) 
> < 0)
> +                     return;
> +     }
>  
> -     pid_array = create_all_readers(cpus, node, port, pagesize, fd);
> +     ofd = create_client_file(node, port, domain, virtpid);
> +     pid_array = create_all_readers(cpus, node, port, domain, virtpid, 
> pagesize, fd);
>       if (!pid_array)
>               return;
>  
> @@ -570,9 +689,22 @@ static void process_client(const char *node, const char 
> *port, int fd)
>       /* wait a little to have the readers clean up */
>       sleep(1);
>  
> -     put_together_file(cpus, ofd, node, port);
> +     put_together_file(cpus, ofd, node, port, domain, virtpid);
>  
> -     destroy_all_readers(cpus, pid_array, node, port);
> +     destroy_all_readers(cpus, pid_array, node, port, domain, virtpid);
> +}
> +
> +static void process_client_nw(const char *node, const char *port, int fd)
> +{
> +     process_client(node, port, NULL, 0, fd);
> +}
> +
> +static void process_client_virt(const char *domain, int virtpid, int fd)
> +{
> +     /* keep connection to qemu if clients on guests finish operation */
> +     do {
> +             process_client(NULL, NULL, domain, virtpid, fd);
> +     } while (!done);
>  }
>  
>  static int do_fork(int cfd)
> @@ -599,8 +731,8 @@ static int do_fork(int cfd)
>       return 0;
>  }
>  
> -static int do_connection(int cfd, struct sockaddr_storage *peer_addr,
> -                       socklen_t peer_addr_len)
> +static int do_connection(int cfd, struct sockaddr *peer_addr,
> +                      socklen_t *peer_addr_len, const char *domain, int 
> virtpid)
>  {
>       char host[NI_MAXHOST], service[NI_MAXSERV];
>       int s;
> @@ -610,21 +742,22 @@ static int do_connection(int cfd, struct 
> sockaddr_storage *peer_addr,
>       if (ret)
>               return ret;
>  
> -     s = getnameinfo((struct sockaddr *)peer_addr, peer_addr_len,
> -                     host, NI_MAXHOST,
> -                     service, NI_MAXSERV, NI_NUMERICSERV);
> -
> -     if (s == 0)
> -             plog("Connected with %s:%s\n",
> -                    host, service);
> -     else {
> -             plog("Error with getnameinfo: %s\n",
> -                    gai_strerror(s));
> -             close(cfd);
> -             return -1;
> -     }
> -
> -     process_client(host, service, cfd);
> +     if (peer_addr) {
> +             s = getnameinfo(peer_addr, *peer_addr_len, host, NI_MAXHOST,
> +                             service, NI_MAXSERV, NI_NUMERICSERV);
> +     
> +             if (s == 0)
> +                     plog("Connected with %s:%s\n",
> +                            host, service);
> +             else {
> +                     plog("Error with getnameinfo: %s\n",
> +                            gai_strerror(s));
> +                     close(cfd);
> +                     return -1;
> +             }
> +             process_client_nw(host, service, cfd);
> +     } else
> +             process_client_virt(domain, virtpid, cfd);
>  
>       close(cfd);
>  
> @@ -634,6 +767,77 @@ static int do_connection(int cfd, struct 
> sockaddr_storage *peer_addr,
>       return 0;
>  }
>  
> +static int do_connection_nw(int cfd, struct sockaddr *addr, socklen_t 
> *addrlen)
> +{
> +     return do_connection(cfd, addr, addrlen, NULL, 0);
> +}
> +
> +#define LIBVIRT_DOMAIN_PATH     "/var/run/libvirt/qemu/"
> +
> +/* We can convert pid to domain name of a guest when we use libvirt. */
> +static char *get_guest_domain_from_pid(int pid)
> +{
> +     struct dirent *dirent;
> +     char file_name[NAME_MAX];
> +     char *file_name_ret, *domain;
> +     char buf[BUFSIZ];
> +     DIR *dir;
> +     size_t doml;
> +     int fd;
> +
> +     dir = opendir(LIBVIRT_DOMAIN_PATH);
> +     if (!dir) {
> +             if (errno == ENOENT)
> +                     warning("Only support for using libvirt");
> +             return NULL;
> +     }
> +
> +     for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) {
> +             snprintf(file_name, NAME_MAX, LIBVIRT_DOMAIN_PATH"%s",
> +                      dirent->d_name);
> +             file_name_ret = strstr(file_name, ".pid");
> +             if (file_name_ret) {
> +                     fd = open(file_name, O_RDONLY);
> +                     if (fd < 0)
> +                             return NULL;
> +                     if (read(fd, buf, BUFSIZ) < 0)
> +                             return NULL;
> +
> +                     if (pid == atoi(buf)) {
> +                             /* not include /var/run/libvirt/qemu */
> +                             doml = (size_t)(file_name_ret - file_name)
> +                                     - strlen(LIBVIRT_DOMAIN_PATH);
> +                             domain = strndup(file_name +
> +                                              strlen(LIBVIRT_DOMAIN_PATH),
> +                                              doml);
> +                             plog("start %s:%d\n", domain, pid);
> +                             return domain;
> +                     }
> +             }
> +     }
> +
> +     return NULL;
> +}
> +
> +static int do_connection_virt(int cfd)
> +{
> +     struct ucred cr;
> +     socklen_t cl;
> +     int ret;
> +     char *domain;
> +
> +     cl = sizeof(cr);
> +     ret = getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl);
> +     if (ret < 0)
> +             return ret;
> +
> +     domain = get_guest_domain_from_pid(cr.pid);
> +     if (!domain)
> +             return -1;
> +
> +     return do_connection(cfd, NULL, NULL, domain, cr.pid);
> +}
> +
>  static int *client_pids;
>  static int saved_pids;
>  static int size_pids;
> @@ -678,12 +882,11 @@ static void remove_process(int pid)
>  
>  static void kill_clients(void)
>  {
> -     int status;
>       int i;
>  
>       for (i = 0; i < saved_pids; i++) {
>               kill(client_pids[i], SIGINT);
> -             waitpid(client_pids[i], &status, 0);
> +             waitpid(client_pids[i], NULL, 0);
>       }
>  
>       saved_pids = 0;
> @@ -702,31 +905,51 @@ static void clean_up(int sig)
>       } while (ret > 0);
>  }
>  
> -static void do_accept_loop(int sfd)
> +static void do_accept_loop(int sfd, bool nw, struct sockaddr *addr,
> +                        socklen_t *addrlen)
>  {
> -     struct sockaddr_storage peer_addr;
> -     socklen_t peer_addr_len;
>       int cfd, pid;
>  
> -     peer_addr_len = sizeof(peer_addr);
> -
>       do {
> -             cfd = accept(sfd, (struct sockaddr *)&peer_addr,
> -                          &peer_addr_len);
> +             cfd = accept(sfd, addr, addrlen);
>               printf("connected!\n");
>               if (cfd < 0 && errno == EINTR)
>                       continue;
>               if (cfd < 0)
>                       pdie("connecting");
>  
> -             pid = do_connection(cfd, &peer_addr, peer_addr_len);
> +             if (nw)
> +                     pid = do_connection_nw(cfd, addr, addrlen);
> +             else
> +                     pid = do_connection_virt(cfd);
>               if (pid > 0)
>                       add_process(pid);
>  
>       } while (!done);
>  }
>  
> -static void do_listen(char *port)
> +static void do_accept_loop_nw(int sfd)
> +{
> +     struct sockaddr_storage peer_addr;
> +     socklen_t peer_addr_len;
> +
> +     peer_addr_len = sizeof(peer_addr);
> +
> +     do_accept_loop(sfd, true, (struct sockaddr *)&peer_addr,
> +                    &peer_addr_len);
> +}
> +
> +static void do_accept_loop_virt(int sfd)
> +{
> +     struct sockaddr_un un_addr;
> +     socklen_t un_addrlen;
> +
> +     un_addrlen = sizeof(un_addr);
> +
> +     do_accept_loop(sfd, false, (struct sockaddr *)&un_addr, &un_addrlen);
> +}
> +
> +static void do_listen_nw(char *port)
>  {
>       struct addrinfo hints;
>       struct addrinfo *result, *rp;
> @@ -764,11 +987,67 @@ static void do_listen(char *port)
>       if (listen(sfd, backlog) < 0)
>               pdie("listen");
>  
> -     do_accept_loop(sfd);
> +     do_accept_loop_nw(sfd);
>  
>       kill_clients();
>  }
>  
> +static void make_virt_if_dir(void)
> +{
> +     struct group *group;
> +
> +     if (mkdir(TRACE_CMD_DIR, 0710) < 0) {
> +             if (errno != EEXIST)
> +                     pdie("mkdir %s", TRACE_CMD_DIR);
> +     }
> +     /* QEMU operates as qemu:qemu */
> +     chmod(TRACE_CMD_DIR, 0710);
> +     group = getgrnam("qemu");
> +     if (chown(TRACE_CMD_DIR, -1, group->gr_gid) < 0)
> +             pdie("chown %s", TRACE_CMD_DIR);
> +
> +     if (mkdir(VIRT_DIR, 0710) < 0) {
> +             if (errno != EEXIST)
> +                     pdie("mkdir %s", VIRT_DIR);
> +     }
> +     chmod(VIRT_DIR, 0710);
> +     if (chown(VIRT_DIR, -1, group->gr_gid) < 0)
> +             pdie("chown %s", VIRT_DIR);
> +}
> +
> +static void do_listen_virt(void)
> +{
> +     struct sockaddr_un un_server;
> +     struct group *group;
> +     socklen_t slen;
> +     int sfd;
> +
> +     make_virt_if_dir();
> +
> +     slen = sizeof(un_server);
> +     sfd = socket(AF_UNIX, SOCK_STREAM, 0);
> +     if (sfd < 0)
> +             pdie("socket");
> +
> +     un_server.sun_family = AF_UNIX;
> +     snprintf(un_server.sun_path, PATH_MAX, VIRT_TRACE_CTL_SOCK);
> +
> +     if (bind(sfd, (struct sockaddr *)&un_server, slen) < 0)
> +             pdie("bind");
> +     chmod(VIRT_TRACE_CTL_SOCK, 0660);
> +     group = getgrnam("qemu");
> +     if (chown(VIRT_TRACE_CTL_SOCK, -1, group->gr_gid) < 0)
> +             pdie("fchown %s", VIRT_TRACE_CTL_SOCK);
> +
> +     if (listen(sfd, backlog) < 0)
> +             pdie("listen");
> +
> +     do_accept_loop_virt(sfd);
> +
> +     unlink(VIRT_TRACE_CTL_SOCK);
> +     kill_clients();
> +}
> +
>  static void start_daemon(void)
>  {
>       if (daemon(1, 0) < 0)
> @@ -785,11 +1064,17 @@ void trace_listen(int argc, char **argv)
>       char *port = NULL;
>       int daemon = 0;
>       int c;
> +     int nw = 0;
> +     int virt = 0;
>  
>       if (argc < 2)
>               usage(argv);
>  
> -     if (strcmp(argv[1], "listen") != 0)
> +     if ((nw = (strcmp(argv[1], "listen") == 0)))
> +             ; /* do nothing */
> +     else if ((virt = (strcmp(argv[1], "virt-server") == 0)))
> +             ; /* do nothing */
> +     else
>               usage(argv);
>  
>       for (;;) {
> @@ -810,6 +1095,8 @@ void trace_listen(int argc, char **argv)
>                       usage(argv);
>                       break;
>               case 'p':
> +                     if (virt)
> +                             die("-p only available with listen");
>                       port = optarg;
>                       break;
>               case 'd':
> @@ -832,7 +1119,7 @@ void trace_listen(int argc, char **argv)
>               }
>       }
>  
> -     if (!port)
> +     if (!port && nw)
>               usage(argv);
>  
>       if ((argc - optind) >= 2)
> @@ -860,7 +1147,10 @@ void trace_listen(int argc, char **argv)
>       signal_setup(SIGINT, finish);
>       signal_setup(SIGTERM, finish);
>  
> -     do_listen(port);
> +     if (nw)
> +             do_listen_nw(port);
> +     else
> +             do_listen_virt();
>  
>       return;
>  }
> diff --git a/trace-msg.c b/trace-msg.c
> index 61bde54..0b3b356 100644
> --- a/trace-msg.c
> +++ b/trace-msg.c
> @@ -59,6 +59,11 @@ typedef __be32 be32;
>  
>  #define CPU_MAX                              256
>  
> +/* use CONNECTION_MSG as a protocol version of trace-msg */
> +#define MSG_VERSION          "V2"
> +#define CONNECTION_MSG               "tracecmd-" MSG_VERSION
> +#define CONNECTION_MSGSIZE   sizeof(CONNECTION_MSG)
> +
>  /* for both client and server */
>  bool use_tcp;
>  int cpu_count;
> @@ -78,6 +83,10 @@ struct tracecmd_msg_str {
>       char *buf;
>  } __attribute__((packed));
>  
> +struct tracecmd_msg_rconnect {
> +     struct tracecmd_msg_str str;
> +};
> +
>  struct tracecmd_msg_opt {
>       be32 size;
>       be32 opt_cmd;
> @@ -104,6 +113,7 @@ struct tracecmd_msg_error {
>       be32 size;
>       be32 cmd;
>       union {
> +             struct tracecmd_msg_rconnect rconnect;
>               struct tracecmd_msg_tinit tinit;
>               struct tracecmd_msg_rinit rinit;
>               struct tracecmd_msg_meta meta;
> @@ -111,7 +121,10 @@ struct tracecmd_msg_error {
>  } __attribute__((packed));
>  
>  enum tracecmd_msg_cmd {
> +     MSG_ERROR       = 0,
>       MSG_CLOSE       = 1,
> +     MSG_TCONNECT    = 2,
> +     MSG_RCONNECT    = 3,
>       MSG_TINIT       = 4,
>       MSG_RINIT       = 5,
>       MSG_SENDMETA    = 6,
> @@ -122,6 +135,7 @@ struct tracecmd_msg {
>       be32 size;
>       be32 cmd;
>       union {
> +             struct tracecmd_msg_rconnect rconnect;
>               struct tracecmd_msg_tinit tinit;
>               struct tracecmd_msg_rinit rinit;
>               struct tracecmd_msg_meta meta;
> @@ -155,6 +169,16 @@ static void bufcpy(void *dest, u32 offset, const void 
> *buf, u32 buflen)
>       memcpy(dest+offset, buf, buflen);
>  }
>  
> +static int make_rconnect(const char *buf, int buflen, struct tracecmd_msg 
> *msg)
> +{
> +     u32 offset = offsetof(struct tracecmd_msg, data.rconnect.str.buf);
> +
> +     msg->data.rconnect.str.size = htonl(buflen);
> +     bufcpy(msg, offset, buf, buflen);
> +
> +     return 0;
> +}
> +
>  enum msg_opt_command {
>       MSGOPT_USETCP = 1,
>  };
> @@ -232,11 +256,13 @@ static int make_rinit(struct tracecmd_msg *msg)
>  
>       msg->data.rinit.cpus = htonl(cpu_count);
>  
> -     for (i = 0; i < cpu_count; i++) {
> -             /* + rrqports->cpus or rrqports->port_array[i] */
> -             offset += sizeof(be32);
> -             port = htonl(port_array[i]);
> -             bufcpy(msg, offset, &port, sizeof(be32) * cpu_count);
> +     if (port_array) {
> +             for (i = 0; i < cpu_count; i++) {
> +                     /* + rrqports->cpus or rrqports->port_array[i] */
> +                     offset += sizeof(be32);
> +                     port = htonl(port_array[i]);
> +                     bufcpy(msg, offset, &port, sizeof(be32) * cpu_count);
> +             }
>       }
>  
>       return 0;
> @@ -248,6 +274,8 @@ static u32 tracecmd_msg_get_body_length(u32 cmd)
>       u32 len = 0;
>  
>       switch (cmd) {
> +     case MSG_RCONNECT:
> +             return sizeof(msg->data.rconnect.str.size) + CONNECTION_MSGSIZE;
>       case MSG_TINIT:
>               len = sizeof(msg->data.tinit.cpus)
>                     + sizeof(msg->data.tinit.page_size)
> @@ -285,6 +313,8 @@ static u32 tracecmd_msg_get_body_length(u32 cmd)
>  static int tracecmd_msg_make_body(u32 cmd, u32 len, struct tracecmd_msg *msg)
>  {
>       switch (cmd) {
> +     case MSG_RCONNECT:
> +             return make_rconnect(CONNECTION_MSG, CONNECTION_MSGSIZE, msg);
>       case MSG_TINIT:
>               return make_tinit(len, msg);
>       case MSG_RINIT:
> @@ -425,6 +455,8 @@ static void *tracecmd_msg_buf_access(struct tracecmd_msg 
> *msg, int offset)
>  static int tracecmd_msg_wait_for_msg(int fd, struct tracecmd_msg **msg)
>  {
>       char msg_tmp[TRACECMD_MSG_MAX_LEN];
> +     char *buf;
> +     int offset = TRACECMD_MSG_HDR_LEN;
>       u32 cmd;
>       int ret;
>  
> @@ -437,8 +469,20 @@ static int tracecmd_msg_wait_for_msg(int fd, struct 
> tracecmd_msg **msg)
>  
>       *msg = (struct tracecmd_msg *)msg_tmp;
>       cmd = ntohl((*msg)->cmd);
> -     if (cmd == MSG_CLOSE)
> +     switch (cmd) {
> +     case MSG_RCONNECT:
> +             offset += sizeof((*msg)->data.rconnect.str.size);
> +             buf = tracecmd_msg_buf_access(*msg, offset);
> +             /* Make sure the server is the tracecmd server */
> +             if (memcmp(buf, CONNECTION_MSG,
> +                 ntohl((*msg)->data.rconnect.str.size) - 1) != 0) {
> +                     warning("server not tracecmd server");
> +                     return -EPROTONOSUPPORT;
> +             }
> +             break;
> +     case MSG_CLOSE:
>               return -ECONNABORTED;
> +     }
>  
>       return 0;
>  }
> @@ -495,7 +539,54 @@ static void error_operation_for_server(struct 
> tracecmd_msg *msg)
>  
>       cmd = ntohl(msg->cmd);
>  
> -     warning("Message: cmd=%d size=%d\n", cmd, ntohl(msg->size));
> +     if (cmd == MSG_ERROR)
> +             plog("Receive error message: cmd=%d size=%d\n",
> +                  ntohl(msg->data.err.cmd), ntohl(msg->data.err.size));
> +     else
> +             warning("Message: cmd=%d size=%d\n", cmd, ntohl(msg->size));
> +}
> +
> +int tracecmd_msg_set_connection(int fd, const char *domain)
> +{
> +     struct tracecmd_msg *msg;
> +     char buf[TRACECMD_MSG_MAX_LEN] = {};
> +     u32 cmd;
> +     int ret;
> +
> +     /*
> +      * Wait for connection msg by a client first.
> +      * If a client uses virtio-serial, a connection message will
> +      * not be sent immediately after accept(). connect() is called
> +      * in QEMU, so the client can send the connection message
> +      * after guest boots. Therefore, the virt-server patiently
> +      * waits for the connection request of a client.
> +      */ 
> +     ret = tracecmd_msg_recv(fd, buf);
> +     if (ret < 0) {
> +             if (!buf[0]) {
> +                     /* No data means QEMU has already died. */
> +                     close(fd);
> +                     die("Connection refuesd: %s", domain);
> +             }
> +             return -ENOMSG;
> +     }
> +
> +     msg = (struct tracecmd_msg *)buf;
> +     cmd = ntohl(msg->cmd);
> +     if (cmd == MSG_CLOSE)
> +             return -ECONNABORTED;
> +     else if (cmd != MSG_TCONNECT)
> +             return -EINVAL;
> +
> +     ret = tracecmd_msg_send(fd, MSG_RCONNECT);
> +     if (ret < 0)
> +             goto error;
> +
> +     return 0;
> +
> +error:
> +     error_operation_for_server(msg);
> +     return ret;
>  }
>  
>  #define MAX_OPTION_SIZE 4096
> diff --git a/trace-recorder.c b/trace-recorder.c
> index 520d486..8169dc3 100644
> --- a/trace-recorder.c
> +++ b/trace-recorder.c
> @@ -149,19 +149,23 @@ tracecmd_create_buffer_recorder_fd2(int fd, int fd2, 
> int cpu, unsigned flags,
>       recorder->fd1 = fd;
>       recorder->fd2 = fd2;
>  
> -     path = malloc_or_die(strlen(buffer) + 40);
> -     if (!path)
> -             goto out_free;
> -
> -     if (flags & TRACECMD_RECORD_SNAPSHOT)
> -             sprintf(path, "%s/per_cpu/cpu%d/snapshot_raw", buffer, cpu);
> -     else
> -             sprintf(path, "%s/per_cpu/cpu%d/trace_pipe_raw", buffer, cpu);
> -     recorder->trace_fd = open(path, O_RDONLY);
> -     if (recorder->trace_fd < 0)
> -             goto out_free;
> -
> -     free(path);
> +     if (buffer) {
> +             path = malloc_or_die(strlen(buffer) + 40);
> +             if (!path)
> +                     goto out_free;
> +     
> +             if (flags & TRACECMD_RECORD_SNAPSHOT)
> +                     sprintf(path, "%s/per_cpu/cpu%d/snapshot_raw",
> +                             buffer, cpu);
> +             else
> +                     sprintf(path, "%s/per_cpu/cpu%d/trace_pipe_raw",
> +                             buffer, cpu);
> +             recorder->trace_fd = open(path, O_RDONLY);
> +             if (recorder->trace_fd < 0)
> +                     goto out_free;
> +     
> +             free(path);
> +     }
>  
>       if ((recorder->flags & TRACECMD_RECORD_NOSPLICE) == 0) {
>               ret = pipe(recorder->brass);
> @@ -184,8 +188,9 @@ tracecmd_create_buffer_recorder_fd(int fd, int cpu, 
> unsigned flags, const char *
>       return tracecmd_create_buffer_recorder_fd2(fd, -1, cpu, flags, buffer, 
> 0);
>  }
>  
> -struct tracecmd_recorder *
> -tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags, 
> const char *buffer)
> +static struct tracecmd_recorder *
> +__tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags,
> +                               const char *buffer)
>  {
>       struct tracecmd_recorder *recorder;
>       int fd;
> @@ -248,6 +253,25 @@ tracecmd_create_buffer_recorder_maxkb(const char *file, 
> int cpu, unsigned flags,
>       goto out;
>  }
>  
> +struct tracecmd_recorder *
> +tracecmd_create_buffer_recorder(const char *file, int cpu, unsigned flags,
> +                             const char *buffer)
> +{
> +     return __tracecmd_create_buffer_recorder(file, cpu, flags, buffer);
> +}
> +
> +struct tracecmd_recorder *
> +tracecmd_create_recorder_virt(const char *file, int cpu, int trace_fd)
> +{
> +     struct tracecmd_recorder *recorder;
> +
> +     recorder = __tracecmd_create_buffer_recorder(file, cpu, 0, NULL);
> +     if (recorder)
> +             recorder->trace_fd = trace_fd;
> +
> +     return recorder;
> +}
> +
>  struct tracecmd_recorder *tracecmd_create_recorder_fd(int fd, int cpu, 
> unsigned flags)
>  {
>       char *tracing;
> diff --git a/trace-usage.c b/trace-usage.c
> index b8f26e6..e6a239f 100644
> --- a/trace-usage.c
> +++ b/trace-usage.c
> @@ -153,6 +153,16 @@ static struct usage_help usage_help[] = {
>               "          -l logfile to write messages to.\n"
>       },
>       {
> +             "virt-server",
> +             "listen on a virtio-serial for trace clients",
> +             " %s virt-server [-o file][-d dir][-l logfile]\n"
> +             "          Creates a socket to listen for clients.\n"
> +             "          -D create it in daemon mode.\n"
> +             "          -o file name to use for clients.\n"
> +             "          -d diretory to store client files.\n"
> +             "          -l logfile to write messages to.\n"
> +     },
> +     {
>               "list",
>               "list the available events, plugins or options",
>               " %s list [-e][-t][-o][-f [regex]]\n"

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to