2009-08-17 18:18:05 +04:00
/*
* Copyright ( C ) 2008 , 2009 , Steven Rostedt < srostedt @ redhat . com >
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; version 2 of the License ( not later ! )
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*/
2011-11-16 18:55:59 +04:00
# include "util.h"
2009-08-17 18:18:05 +04:00
# 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 <pthread.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>
2009-08-17 18:18:05 +04:00
2009-08-28 05:09:58 +04:00
# include "../perf.h"
2009-08-17 18:18:05 +04:00
# include "trace-event.h"
2013-12-09 20:14:23 +04:00
# include <api/fs/debugfs.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
# define VERSION "0.5"
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
{
char * path ;
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
path = get_tracing_file ( " events/header_page " ) ;
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 ;
}
2009-08-17 18:18:05 +04:00
put_tracing_file ( path ) ;
path = get_tracing_file ( " events/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 :
2009-08-17 18:18:05 +04:00
put_tracing_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 ;
}
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
while ( ( dent = readdir ( dir ) ) ) {
2009-12-20 00:40:28 +03:00
if ( dent - > d_type ! = DT_DIR | |
strcmp ( dent - > d_name , " . " ) = = 0 | |
2009-08-28 05:09:58 +04:00
strcmp ( dent - > d_name , " .. " ) = = 0 | |
! name_in_tp_list ( dent - > d_name , tps ) )
2009-08-17 18:18:05 +04:00
continue ;
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 ) ;
while ( ( dent = readdir ( dir ) ) ) {
2009-12-20 00:40:28 +03:00
if ( dent - > d_type ! = DT_DIR | |
strcmp ( dent - > d_name , " . " ) = = 0 | |
2009-08-28 05:09:58 +04:00
strcmp ( dent - > d_name , " .. " ) = = 0 | |
! name_in_tp_list ( dent - > d_name , tps ) )
2009-08-17 18:18:05 +04:00
continue ;
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
path = get_tracing_file ( " events/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
while ( ( dent = readdir ( dir ) ) ) {
2009-12-20 00:40:28 +03:00
if ( dent - > d_type ! = DT_DIR | |
strcmp ( dent - > d_name , " . " ) = = 0 | |
2009-08-17 18:18:05 +04:00
strcmp ( dent - > d_name , " .. " ) = = 0 | |
2009-08-28 05:09:58 +04:00
strcmp ( dent - > d_name , " ftrace " ) = = 0 | |
! system_in_tp_list ( dent - > d_name , tps ) )
2009-08-17 18:18:05 +04:00
continue ;
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 ) ;
while ( ( dent = readdir ( dir ) ) ) {
2009-12-20 00:40:28 +03:00
if ( dent - > d_type ! = DT_DIR | |
strcmp ( dent - > d_name , " . " ) = = 0 | |
2009-08-17 18:18:05 +04:00
strcmp ( dent - > d_name , " .. " ) = = 0 | |
2009-08-28 05:09:58 +04:00
strcmp ( dent - > d_name , " ftrace " ) = = 0 | |
! system_in_tp_list ( dent - > d_name , tps ) )
2009-08-17 18:18:05 +04:00
continue ;
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
{
2011-07-14 07:34:43 +04:00
unsigned int size ;
2009-08-17 18:18:05 +04:00
const char * path = " /proc/kallsyms " ;
struct stat st ;
2013-03-21 11:18:46 +04:00
int ret , err = 0 ;
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 ;
return err ;
2009-08-17 18:18:05 +04:00
}
2013-03-21 11:18:46 +04:00
return record_file ( path , 4 ) ;
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-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 ;
2011-01-03 21:39:04 +03:00
struct perf_evsel * pos ;
int nr_tracepoints = 0 ;
2009-08-28 05:09:58 +04:00
2011-01-03 21:39:04 +03:00
list_for_each_entry ( pos , pattrs , node ) {
if ( pos - > 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 :
2011-01-03 21:39:04 +03:00
ppath - > next = tracepoint_id_to_path ( pos - > 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 " ) ;
put_tracepoints_path ( & path ) ;
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
{
2011-01-03 21:39:04 +03:00
struct perf_evsel * pos ;
2010-05-05 07:20:16 +04:00
2011-01-03 21:39:04 +03:00
list_for_each_entry ( pos , pattrs , node )
if ( pos - > 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 " ) ;
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 ) ;
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 ( ) ;
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
}