2019-05-31 11:09:51 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2009-08-17 18:18:05 +04:00
/*
* Copyright ( C ) 2008 , 2009 , Steven Rostedt < srostedt @ redhat . com >
*/
# include <dirent.h>
2009-12-20 00:40:28 +03:00
# include <mntent.h>
2009-08-17 18:18:05 +04:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <stdarg.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/wait.h>
# include <fcntl.h>
# include <unistd.h>
# include <errno.h>
2009-08-28 05:09:58 +04:00
# include <stdbool.h>
2011-01-03 21:39:04 +03:00
# include <linux/list.h>
2009-11-21 19:31:26 +03:00
# include <linux/kernel.h>
2019-07-04 17:32:27 +03:00
# include <linux/zalloc.h>
2019-08-06 16:25:25 +03:00
# include <internal/lib.h> // page_size
2009-08-17 18:18:05 +04:00
# include "trace-event.h"
2015-09-02 10:56:34 +03:00
# include <api/fs/tracing_path.h>
2011-01-03 21:39:04 +03:00
# include "evsel.h"
2014-07-15 01:46:48 +04:00
# include "debug.h"
2009-08-17 18:18:05 +04:00
2013-04-11 12:25:04 +04:00
# define VERSION "0.6"
2009-08-17 18:18:05 +04:00
static int output_fd ;
int bigendian ( void )
{
unsigned char str [ ] = { 0x1 , 0x2 , 0x3 , 0x4 , 0x0 , 0x0 , 0x0 , 0x0 } ;
unsigned int * ptr ;
2009-09-02 16:55:55 +04:00
ptr = ( unsigned int * ) ( void * ) str ;
2009-08-17 18:18:05 +04:00
return * ptr = = 0x01020304 ;
}
2011-07-14 07:34:43 +04:00
/* unfortunately, you can not stat debugfs or proc files for size */
2013-03-21 11:18:46 +04:00
static int record_file ( const char * file , ssize_t hdr_sz )
2009-08-17 18:18:05 +04:00
{
unsigned long long size = 0 ;
2011-07-14 07:34:43 +04:00
char buf [ BUFSIZ ] , * sizep ;
off_t hdr_pos = lseek ( output_fd , 0 , SEEK_CUR ) ;
int r , fd ;
2013-03-21 11:18:46 +04:00
int err = - EIO ;
2009-08-17 18:18:05 +04:00
fd = open ( file , O_RDONLY ) ;
2013-03-21 11:18:47 +04:00
if ( fd < 0 ) {
pr_debug ( " Can't read '%s' " , file ) ;
return - errno ;
}
2009-08-17 18:18:05 +04:00
2011-07-14 07:34:43 +04:00
/* put in zeros for file size, then fill true size later */
2013-03-21 11:18:46 +04:00
if ( hdr_sz ) {
if ( write ( output_fd , & size , hdr_sz ) ! = hdr_sz )
goto out ;
}
2009-08-17 18:18:05 +04:00
do {
r = read ( fd , buf , BUFSIZ ) ;
2011-07-14 07:34:43 +04:00
if ( r > 0 ) {
2009-08-17 18:18:05 +04:00
size + = r ;
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , buf , r ) ! = r )
goto out ;
2011-07-14 07:34:43 +04:00
}
2009-08-17 18:18:05 +04:00
} while ( r > 0 ) ;
2011-07-14 07:34:43 +04:00
/* ugh, handle big-endian hdr_size == 4 */
sizep = ( char * ) & size ;
if ( bigendian ( ) )
sizep + = sizeof ( u64 ) - hdr_sz ;
2013-03-21 11:18:47 +04:00
if ( hdr_sz & & pwrite ( output_fd , sizep , hdr_sz , hdr_pos ) < 0 ) {
pr_debug ( " writing file size failed \n " ) ;
goto out ;
}
2013-03-21 11:18:46 +04:00
err = 0 ;
out :
close ( fd ) ;
return err ;
2009-08-17 18:18:05 +04:00
}
2013-06-04 09:20:29 +04:00
static int record_header_files ( void )
2009-08-17 18:18:05 +04:00
{
2018-05-16 22:42:26 +03:00
char * path = get_events_file ( " header_page " ) ;
2011-07-14 07:34:43 +04:00
struct stat st ;
2013-03-21 11:18:46 +04:00
int err = - EIO ;
2009-08-17 18:18:05 +04:00
2013-03-21 11:18:47 +04:00
if ( ! path ) {
pr_debug ( " can't get tracing/events/header_page " ) ;
return - ENOMEM ;
}
2013-03-21 11:18:44 +04:00
2013-03-21 11:18:47 +04:00
if ( stat ( path , & st ) < 0 ) {
pr_debug ( " can't read '%s' " , path ) ;
goto out ;
}
2009-08-17 18:18:05 +04:00
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , " header_page " , 12 ) ! = 12 ) {
pr_debug ( " can't write header_page \n " ) ;
goto out ;
}
if ( record_file ( path , 8 ) < 0 ) {
pr_debug ( " can't record header_page file \n " ) ;
goto out ;
}
2018-05-16 22:42:26 +03:00
put_events_file ( path ) ;
2009-08-17 18:18:05 +04:00
2018-05-16 22:42:26 +03:00
path = get_events_file ( " header_event " ) ;
2013-03-21 11:18:47 +04:00
if ( ! path ) {
pr_debug ( " can't get tracing/events/header_event " ) ;
err = - ENOMEM ;
goto out ;
}
2013-03-21 11:18:44 +04:00
2013-03-21 11:18:47 +04:00
if ( stat ( path , & st ) < 0 ) {
pr_debug ( " can't read '%s' " , path ) ;
goto out ;
}
2009-08-17 18:18:05 +04:00
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , " header_event " , 13 ) ! = 13 ) {
pr_debug ( " can't write header_event \n " ) ;
goto out ;
}
if ( record_file ( path , 8 ) < 0 ) {
pr_debug ( " can't record header_event file \n " ) ;
goto out ;
}
err = 0 ;
out :
2018-05-16 22:42:26 +03:00
put_events_file ( path ) ;
2013-03-21 11:18:46 +04:00
return err ;
2009-08-17 18:18:05 +04:00
}
2009-08-28 05:09:58 +04:00
static bool name_in_tp_list ( char * sys , struct tracepoint_path * tps )
{
while ( tps ) {
if ( ! strcmp ( sys , tps - > name ) )
return true ;
tps = tps - > next ;
}
return false ;
}
2021-02-03 08:26:58 +03:00
# define for_each_event_tps(dir, dent, tps) \
2017-01-31 14:38:28 +03:00
while ( ( dent = readdir ( dir ) ) ) \
if ( dent - > d_type = = DT_DIR & & \
( strcmp ( dent - > d_name , " . " ) ) & & \
( strcmp ( dent - > d_name , " .. " ) ) ) \
2013-03-21 11:18:45 +04:00
static int copy_event_system ( const char * sys , struct tracepoint_path * tps )
2009-08-17 18:18:05 +04:00
{
struct dirent * dent ;
struct stat st ;
char * format ;
DIR * dir ;
int count = 0 ;
int ret ;
2013-03-21 11:18:45 +04:00
int err ;
2009-08-17 18:18:05 +04:00
dir = opendir ( sys ) ;
2013-03-21 11:18:47 +04:00
if ( ! dir ) {
pr_debug ( " can't read directory '%s' " , sys ) ;
return - errno ;
}
2009-08-17 18:18:05 +04:00
2021-02-03 08:26:58 +03:00
for_each_event_tps ( dir , dent , tps ) {
2017-01-31 14:38:28 +03:00
if ( ! name_in_tp_list ( dent - > d_name , tps ) )
2009-08-17 18:18:05 +04:00
continue ;
2017-01-31 14:38:28 +03:00
2014-07-04 15:43:48 +04:00
if ( asprintf ( & format , " %s/%s/format " , sys , dent - > d_name ) < 0 ) {
2013-03-21 11:18:45 +04:00
err = - ENOMEM ;
goto out ;
}
2009-08-17 18:18:05 +04:00
ret = stat ( format , & st ) ;
free ( format ) ;
if ( ret < 0 )
continue ;
count + + ;
}
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , & count , 4 ) ! = 4 ) {
err = - EIO ;
pr_debug ( " can't write count \n " ) ;
goto out ;
}
2009-08-17 18:18:05 +04:00
rewinddir ( dir ) ;
2021-02-03 08:26:58 +03:00
for_each_event_tps ( dir , dent , tps ) {
2017-01-31 14:38:28 +03:00
if ( ! name_in_tp_list ( dent - > d_name , tps ) )
2009-08-17 18:18:05 +04:00
continue ;
2017-01-31 14:38:28 +03:00
2014-07-04 15:43:48 +04:00
if ( asprintf ( & format , " %s/%s/format " , sys , dent - > d_name ) < 0 ) {
2013-03-21 11:18:45 +04:00
err = - ENOMEM ;
goto out ;
}
2009-08-17 18:18:05 +04:00
ret = stat ( format , & st ) ;
2013-03-21 11:18:46 +04:00
if ( ret > = 0 ) {
err = record_file ( format , 8 ) ;
if ( err ) {
free ( format ) ;
goto out ;
}
}
2009-08-17 18:18:05 +04:00
free ( format ) ;
}
2013-03-21 11:18:45 +04:00
err = 0 ;
out :
2009-12-28 11:49:38 +03:00
closedir ( dir ) ;
2013-03-21 11:18:45 +04:00
return err ;
2009-08-17 18:18:05 +04:00
}
2013-06-04 09:20:29 +04:00
static int record_ftrace_files ( struct tracepoint_path * tps )
2009-08-17 18:18:05 +04:00
{
char * path ;
2013-03-21 11:18:46 +04:00
int ret ;
2009-08-17 18:18:05 +04:00
2018-05-16 22:42:26 +03:00
path = get_events_file ( " ftrace " ) ;
2013-03-21 11:18:47 +04:00
if ( ! path ) {
pr_debug ( " can't get tracing/events/ftrace " ) ;
return - ENOMEM ;
}
2009-08-17 18:18:05 +04:00
2013-03-21 11:18:46 +04:00
ret = copy_event_system ( path , tps ) ;
2009-08-17 18:18:05 +04:00
put_tracing_file ( path ) ;
2013-03-21 11:18:46 +04:00
return ret ;
2009-08-17 18:18:05 +04:00
}
2009-08-28 05:09:58 +04:00
static bool system_in_tp_list ( char * sys , struct tracepoint_path * tps )
{
while ( tps ) {
if ( ! strcmp ( sys , tps - > system ) )
return true ;
tps = tps - > next ;
}
return false ;
}
2013-06-04 09:20:29 +04:00
static int record_event_files ( struct tracepoint_path * tps )
2009-08-17 18:18:05 +04:00
{
struct dirent * dent ;
struct stat st ;
char * path ;
char * sys ;
DIR * dir ;
int count = 0 ;
int ret ;
2013-03-21 11:18:45 +04:00
int err ;
2009-08-17 18:18:05 +04:00
path = get_tracing_file ( " events " ) ;
2013-03-21 11:18:47 +04:00
if ( ! path ) {
pr_debug ( " can't get tracing/events " ) ;
return - ENOMEM ;
}
2009-08-17 18:18:05 +04:00
dir = opendir ( path ) ;
2013-03-21 11:18:47 +04:00
if ( ! dir ) {
err = - errno ;
pr_debug ( " can't read directory '%s' " , path ) ;
goto out ;
}
2009-08-17 18:18:05 +04:00
2021-02-03 08:26:58 +03:00
for_each_event_tps ( dir , dent , tps ) {
2017-01-31 14:38:28 +03:00
if ( strcmp ( dent - > d_name , " ftrace " ) = = 0 | |
2009-08-28 05:09:58 +04:00
! system_in_tp_list ( dent - > d_name , tps ) )
2009-08-17 18:18:05 +04:00
continue ;
2017-01-31 14:38:28 +03:00
2009-12-20 00:40:28 +03:00
count + + ;
2009-08-17 18:18:05 +04:00
}
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , & count , 4 ) ! = 4 ) {
err = - EIO ;
pr_debug ( " can't write count \n " ) ;
goto out ;
}
2009-08-17 18:18:05 +04:00
rewinddir ( dir ) ;
2021-02-03 08:26:58 +03:00
for_each_event_tps ( dir , dent , tps ) {
2017-01-31 14:38:28 +03:00
if ( strcmp ( dent - > d_name , " ftrace " ) = = 0 | |
2009-08-28 05:09:58 +04:00
! system_in_tp_list ( dent - > d_name , tps ) )
2009-08-17 18:18:05 +04:00
continue ;
2017-01-31 14:38:28 +03:00
2014-07-04 15:43:48 +04:00
if ( asprintf ( & sys , " %s/%s " , path , dent - > d_name ) < 0 ) {
2013-03-21 11:18:45 +04:00
err = - ENOMEM ;
goto out ;
}
2009-08-17 18:18:05 +04:00
ret = stat ( sys , & st ) ;
if ( ret > = 0 ) {
2013-03-21 11:18:46 +04:00
ssize_t size = strlen ( dent - > d_name ) + 1 ;
if ( write ( output_fd , dent - > d_name , size ) ! = size | |
copy_event_system ( sys , tps ) < 0 ) {
err = - EIO ;
free ( sys ) ;
goto out ;
}
2009-08-17 18:18:05 +04:00
}
free ( sys ) ;
}
2013-03-21 11:18:45 +04:00
err = 0 ;
out :
2009-12-28 11:49:38 +03:00
closedir ( dir ) ;
2009-08-17 18:18:05 +04:00
put_tracing_file ( path ) ;
2013-03-21 11:18:45 +04:00
return err ;
2009-08-17 18:18:05 +04:00
}
2013-06-04 09:20:29 +04:00
static int record_proc_kallsyms ( void )
2009-08-17 18:18:05 +04:00
{
2015-07-22 23:02:18 +03:00
unsigned long long size = 0 ;
/*
* Just to keep older perf . data file parsers happy , record a zero
* sized kallsyms file , i . e . do the same thing that was done when
* / proc / kallsyms ( or something specified via - - kallsyms , in a
* different path ) couldn ' t be read .
*/
return write ( output_fd , & size , 4 ) ! = 4 ? - EIO : 0 ;
2009-08-17 18:18:05 +04:00
}
2013-06-04 09:20:29 +04:00
static int record_ftrace_printk ( void )
2009-08-17 18:18:05 +04:00
{
2011-07-14 07:34:43 +04:00
unsigned int size ;
2009-09-17 12:34:23 +04:00
char * path ;
2009-08-17 18:18:05 +04:00
struct stat st ;
2013-03-21 11:18:46 +04:00
int ret , err = 0 ;
2009-08-17 18:18:05 +04:00
path = get_tracing_file ( " printk_formats " ) ;
2013-03-21 11:18:47 +04:00
if ( ! path ) {
pr_debug ( " can't get tracing/printk_formats " ) ;
return - ENOMEM ;
}
2013-03-21 11:18:44 +04:00
2009-08-17 18:18:05 +04:00
ret = stat ( path , & st ) ;
if ( ret < 0 ) {
/* not found */
size = 0 ;
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , & size , 4 ) ! = 4 )
err = - EIO ;
2009-09-17 12:34:23 +04:00
goto out ;
2009-08-17 18:18:05 +04:00
}
2013-03-21 11:18:46 +04:00
err = record_file ( path , 4 ) ;
2011-07-14 07:34:43 +04:00
2009-09-17 12:34:23 +04:00
out :
put_tracing_file ( path ) ;
2013-03-21 11:18:46 +04:00
return err ;
2009-08-17 18:18:05 +04:00
}
2013-04-11 12:25:04 +04:00
static int record_saved_cmdline ( void )
{
2018-08-29 09:19:54 +03:00
unsigned long long size ;
2013-04-11 12:25:04 +04:00
char * path ;
struct stat st ;
int ret , err = 0 ;
path = get_tracing_file ( " saved_cmdlines " ) ;
if ( ! path ) {
pr_debug ( " can't get tracing/saved_cmdline " ) ;
return - ENOMEM ;
}
ret = stat ( path , & st ) ;
if ( ret < 0 ) {
/* not found */
size = 0 ;
if ( write ( output_fd , & size , 8 ) ! = 8 )
err = - EIO ;
goto out ;
}
err = record_file ( path , 8 ) ;
out :
put_tracing_file ( path ) ;
return err ;
}
2013-03-21 11:18:47 +04:00
static void
put_tracepoints_path ( struct tracepoint_path * tps )
{
while ( tps ) {
struct tracepoint_path * t = tps ;
tps = tps - > next ;
2013-12-27 23:55:14 +04:00
zfree ( & t - > name ) ;
zfree ( & t - > system ) ;
2013-03-21 11:18:47 +04:00
free ( t ) ;
}
}
2009-08-28 05:09:58 +04:00
static struct tracepoint_path *
2011-01-03 21:39:04 +03:00
get_tracepoints_path ( struct list_head * pattrs )
2009-08-28 05:09:58 +04:00
{
struct tracepoint_path path , * ppath = & path ;
2019-07-21 14:23:51 +03:00
struct evsel * pos ;
2011-01-03 21:39:04 +03:00
int nr_tracepoints = 0 ;
2009-08-28 05:09:58 +04:00
2019-07-21 14:24:22 +03:00
list_for_each_entry ( pos , pattrs , core . node ) {
2019-07-21 14:24:29 +03:00
if ( pos - > core . attr . type ! = PERF_TYPE_TRACEPOINT )
2009-08-28 05:09:58 +04:00
continue ;
2009-11-21 19:31:26 +03:00
+ + nr_tracepoints ;
2013-06-26 11:14:05 +04:00
if ( pos - > name ) {
ppath - > next = tracepoint_name_to_path ( pos - > name ) ;
if ( ppath - > next )
goto next ;
if ( strchr ( pos - > name , ' : ' ) = = NULL )
goto try_id ;
goto error ;
}
try_id :
2019-07-21 14:24:29 +03:00
ppath - > next = tracepoint_id_to_path ( pos - > core . attr . config ) ;
2013-03-21 11:18:47 +04:00
if ( ! ppath - > next ) {
2013-06-26 11:14:05 +04:00
error :
2013-03-21 11:18:47 +04:00
pr_debug ( " No memory to alloc tracepoints list \n " ) ;
2020-05-21 16:32:18 +03:00
put_tracepoints_path ( path . next ) ;
2013-03-21 11:18:47 +04:00
return NULL ;
}
2013-06-26 11:14:05 +04:00
next :
2009-08-28 05:09:58 +04:00
ppath = ppath - > next ;
}
2009-11-21 19:31:26 +03:00
return nr_tracepoints > 0 ? path . next : NULL ;
2009-08-28 05:09:58 +04:00
}
2009-11-21 19:31:26 +03:00
2011-01-03 21:39:04 +03:00
bool have_tracepoints ( struct list_head * pattrs )
2010-05-03 09:14:48 +04:00
{
2019-07-21 14:23:51 +03:00
struct evsel * pos ;
2010-05-05 07:20:16 +04:00
2019-07-21 14:24:22 +03:00
list_for_each_entry ( pos , pattrs , core . node )
2019-07-21 14:24:29 +03:00
if ( pos - > core . attr . type = = PERF_TYPE_TRACEPOINT )
2010-05-05 07:20:16 +04:00
return true ;
return false ;
2010-05-03 09:14:48 +04:00
}
2013-03-21 11:18:46 +04:00
static int tracing_data_header ( void )
2009-08-17 18:18:05 +04:00
{
2011-10-20 17:59:43 +04:00
char buf [ 20 ] ;
2013-03-21 11:18:46 +04:00
ssize_t size ;
2009-08-17 18:18:05 +04:00
2011-10-20 17:59:43 +04:00
/* just guessing this is someone's birthday.. ;) */
2009-08-17 18:18:05 +04:00
buf [ 0 ] = 23 ;
buf [ 1 ] = 8 ;
buf [ 2 ] = 68 ;
memcpy ( buf + 3 , " tracing " , 7 ) ;
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , buf , 10 ) ! = 10 )
return - 1 ;
2009-08-17 18:18:05 +04:00
2013-03-21 11:18:46 +04:00
size = strlen ( VERSION ) + 1 ;
if ( write ( output_fd , VERSION , size ) ! = size )
return - 1 ;
2009-08-17 18:18:05 +04:00
/* save endian */
if ( bigendian ( ) )
buf [ 0 ] = 1 ;
else
buf [ 0 ] = 0 ;
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , buf , 1 ) ! = 1 )
return - 1 ;
2009-08-17 18:18:05 +04:00
/* save size of long */
buf [ 0 ] = sizeof ( long ) ;
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , buf , 1 ) ! = 1 )
return - 1 ;
2009-08-17 18:18:05 +04:00
/* save page_size */
2013-03-21 11:18:46 +04:00
if ( write ( output_fd , & page_size , 4 ) ! = 4 )
return - 1 ;
return 0 ;
2011-10-20 17:59:43 +04:00
}
struct tracing_data * tracing_data_get ( struct list_head * pattrs ,
int fd , bool temp )
{
struct tracepoint_path * tps ;
struct tracing_data * tdata ;
2013-03-21 11:18:46 +04:00
int err ;
2011-10-20 17:59:43 +04:00
output_fd = fd ;
tps = get_tracepoints_path ( pattrs ) ;
if ( ! tps )
return NULL ;
2009-08-17 18:18:05 +04:00
2013-03-21 11:18:45 +04:00
tdata = malloc ( sizeof ( * tdata ) ) ;
if ( ! tdata )
return NULL ;
2011-10-20 17:59:43 +04:00
tdata - > temp = temp ;
tdata - > size = 0 ;
if ( temp ) {
int temp_fd ;
snprintf ( tdata - > temp_file , sizeof ( tdata - > temp_file ) ,
" /tmp/perf-XXXXXX " ) ;
2013-03-21 11:18:47 +04:00
if ( ! mkstemp ( tdata - > temp_file ) ) {
pr_debug ( " Can't make temp file " ) ;
2018-10-02 17:29:11 +03:00
free ( tdata ) ;
2013-03-21 11:18:47 +04:00
return NULL ;
}
2011-10-20 17:59:43 +04:00
temp_fd = open ( tdata - > temp_file , O_RDWR ) ;
2013-03-21 11:18:47 +04:00
if ( temp_fd < 0 ) {
pr_debug ( " Can't read '%s' " , tdata - > temp_file ) ;
2018-10-02 17:29:11 +03:00
free ( tdata ) ;
2013-03-21 11:18:47 +04:00
return NULL ;
}
2011-10-20 17:59:43 +04:00
/*
* Set the temp file the default output , so all the
* tracing data are stored into it .
*/
output_fd = temp_fd ;
}
2013-03-21 11:18:46 +04:00
err = tracing_data_header ( ) ;
if ( err )
goto out ;
2013-06-04 09:20:29 +04:00
err = record_header_files ( ) ;
2013-03-21 11:18:46 +04:00
if ( err )
goto out ;
2013-06-04 09:20:29 +04:00
err = record_ftrace_files ( tps ) ;
2013-03-21 11:18:46 +04:00
if ( err )
goto out ;
2013-06-04 09:20:29 +04:00
err = record_event_files ( tps ) ;
2013-03-21 11:18:46 +04:00
if ( err )
goto out ;
2013-06-04 09:20:29 +04:00
err = record_proc_kallsyms ( ) ;
2013-03-21 11:18:46 +04:00
if ( err )
goto out ;
2013-06-04 09:20:29 +04:00
err = record_ftrace_printk ( ) ;
2013-04-11 12:25:04 +04:00
if ( err )
goto out ;
err = record_saved_cmdline ( ) ;
2009-11-21 19:31:26 +03:00
2013-03-21 11:18:46 +04:00
out :
2011-10-20 17:59:43 +04:00
/*
* All tracing data are stored by now , we can restore
* the default output file in case we used temp file .
*/
if ( temp ) {
tdata - > size = lseek ( output_fd , 0 , SEEK_CUR ) ;
close ( output_fd ) ;
output_fd = fd ;
}
2013-12-27 00:41:15 +04:00
if ( err )
zfree ( & tdata ) ;
2013-03-21 11:18:46 +04:00
2011-10-20 17:59:43 +04:00
put_tracepoints_path ( tps ) ;
return tdata ;
2009-08-17 18:18:05 +04:00
}
2010-04-02 08:59:21 +04:00
2013-03-21 11:18:46 +04:00
int tracing_data_put ( struct tracing_data * tdata )
2010-04-02 08:59:21 +04:00
{
2013-03-21 11:18:46 +04:00
int err = 0 ;
2011-10-20 17:59:43 +04:00
if ( tdata - > temp ) {
2013-03-21 11:18:46 +04:00
err = record_file ( tdata - > temp_file , 0 ) ;
2011-10-20 17:59:43 +04:00
unlink ( tdata - > temp_file ) ;
}
2010-04-02 08:59:21 +04:00
2011-10-20 17:59:43 +04:00
free ( tdata ) ;
2013-03-21 11:18:46 +04:00
return err ;
2011-10-20 17:59:43 +04:00
}
2010-04-02 08:59:21 +04:00
2011-10-20 17:59:43 +04:00
int read_tracing_data ( int fd , struct list_head * pattrs )
{
2013-03-21 11:18:46 +04:00
int err ;
2011-10-20 17:59:43 +04:00
struct tracing_data * tdata ;
2010-04-02 08:59:21 +04:00
2011-10-20 17:59:43 +04:00
/*
* We work over the real file , so we can write data
* directly , no temp file is needed .
*/
tdata = tracing_data_get ( pattrs , fd , false ) ;
if ( ! tdata )
return - ENOMEM ;
2013-03-21 11:18:46 +04:00
err = tracing_data_put ( tdata ) ;
return err ;
2010-04-02 08:59:21 +04:00
}