2005-04-16 15:20:36 -07:00
/**
* @ file oprofile_files . c
*
* @ remark Copyright 2002 OProfile authors
* @ remark Read the file COPYING
*
* @ author John Levon < levon @ movementarian . org >
*/
# include <linux/fs.h>
# include <linux/oprofile.h>
2009-07-08 13:49:38 +02:00
# include <linux/jiffies.h>
2005-04-16 15:20:36 -07:00
# include "event_buffer.h"
# include "oprofile_stats.h"
# include "oprof.h"
2008-10-16 15:01:40 +02:00
2008-12-16 16:19:54 +01:00
# define BUFFER_SIZE_DEFAULT 131072
# define CPU_BUFFER_SIZE_DEFAULT 8192
# define BUFFER_WATERSHED_DEFAULT 32768 /* FIXME: tune */
2009-07-15 15:44:18 +02:00
# define TIME_SLICE_DEFAULT 1
2008-12-09 16:56:01 +01:00
2008-12-16 16:19:54 +01:00
unsigned long oprofile_buffer_size ;
unsigned long oprofile_cpu_buffer_size ;
unsigned long oprofile_buffer_watershed ;
2009-07-15 15:19:29 +02:00
unsigned long oprofile_time_slice ;
2005-04-16 15:20:36 -07:00
2009-07-08 13:49:38 +02:00
# ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
static ssize_t timeout_read ( struct file * file , char __user * buf ,
size_t count , loff_t * offset )
{
2009-07-15 15:19:29 +02:00
return oprofilefs_ulong_to_user ( jiffies_to_msecs ( oprofile_time_slice ) ,
buf , count , offset ) ;
2009-07-08 13:49:38 +02:00
}
static ssize_t timeout_write ( struct file * file , char const __user * buf ,
size_t count , loff_t * offset )
{
unsigned long val ;
int retval ;
if ( * offset )
return - EINVAL ;
retval = oprofilefs_ulong_from_user ( & val , buf , count ) ;
if ( retval )
return retval ;
retval = oprofile_set_timeout ( val ) ;
if ( retval )
return retval ;
return count ;
}
static const struct file_operations timeout_fops = {
. read = timeout_read ,
. write = timeout_write ,
} ;
# endif
2008-09-05 17:12:36 +02:00
static ssize_t depth_read ( struct file * file , char __user * buf , size_t count , loff_t * offset )
2005-04-16 15:20:36 -07:00
{
2008-12-16 16:19:54 +01:00
return oprofilefs_ulong_to_user ( oprofile_backtrace_depth , buf , count ,
offset ) ;
2005-04-16 15:20:36 -07:00
}
2008-09-05 17:12:36 +02:00
static ssize_t depth_write ( struct file * file , char const __user * buf , size_t count , loff_t * offset )
2005-04-16 15:20:36 -07:00
{
unsigned long val ;
int retval ;
if ( * offset )
return - EINVAL ;
retval = oprofilefs_ulong_from_user ( & val , buf , count ) ;
if ( retval )
return retval ;
retval = oprofile_set_backtrace ( val ) ;
if ( retval )
return retval ;
return count ;
}
2007-02-12 00:55:34 -08:00
static const struct file_operations depth_fops = {
2005-04-16 15:20:36 -07:00
. read = depth_read ,
. write = depth_write
} ;
2008-10-16 15:01:40 +02:00
2008-09-05 17:12:36 +02:00
static ssize_t pointer_size_read ( struct file * file , char __user * buf , size_t count , loff_t * offset )
2005-04-16 15:20:36 -07:00
{
return oprofilefs_ulong_to_user ( sizeof ( void * ) , buf , count , offset ) ;
}
2007-02-12 00:55:34 -08:00
static const struct file_operations pointer_size_fops = {
2005-04-16 15:20:36 -07:00
. read = pointer_size_read ,
} ;
2008-09-05 17:12:36 +02:00
static ssize_t cpu_type_read ( struct file * file , char __user * buf , size_t count , loff_t * offset )
2005-04-16 15:20:36 -07:00
{
return oprofilefs_str_to_user ( oprofile_ops . cpu_type , buf , count , offset ) ;
}
2008-10-16 15:01:40 +02:00
2007-02-12 00:55:34 -08:00
static const struct file_operations cpu_type_fops = {
2005-04-16 15:20:36 -07:00
. read = cpu_type_read ,
} ;
2008-10-16 15:01:40 +02:00
2008-09-05 17:12:36 +02:00
static ssize_t enable_read ( struct file * file , char __user * buf , size_t count , loff_t * offset )
2005-04-16 15:20:36 -07:00
{
return oprofilefs_ulong_to_user ( oprofile_started , buf , count , offset ) ;
}
2008-09-05 17:12:36 +02:00
static ssize_t enable_write ( struct file * file , char const __user * buf , size_t count , loff_t * offset )
2005-04-16 15:20:36 -07:00
{
unsigned long val ;
int retval ;
if ( * offset )
return - EINVAL ;
2008-09-24 11:08:52 +02:00
2005-04-16 15:20:36 -07:00
retval = oprofilefs_ulong_from_user ( & val , buf , count ) ;
if ( retval )
return retval ;
2008-10-16 15:01:40 +02:00
2005-04-16 15:20:36 -07:00
if ( val )
retval = oprofile_start ( ) ;
else
oprofile_stop ( ) ;
if ( retval )
return retval ;
return count ;
}
2008-10-16 15:01:40 +02:00
2007-02-12 00:55:34 -08:00
static const struct file_operations enable_fops = {
2005-04-16 15:20:36 -07:00
. read = enable_read ,
. write = enable_write ,
} ;
2008-09-05 17:12:36 +02:00
static ssize_t dump_write ( struct file * file , char const __user * buf , size_t count , loff_t * offset )
2005-04-16 15:20:36 -07:00
{
wake_up_buffer_waiter ( ) ;
return count ;
}
2007-02-12 00:55:34 -08:00
static const struct file_operations dump_fops = {
2005-04-16 15:20:36 -07:00
. write = dump_write ,
} ;
2008-10-16 15:01:40 +02:00
2008-09-05 17:12:36 +02:00
void oprofile_create_files ( struct super_block * sb , struct dentry * root )
2005-04-16 15:20:36 -07:00
{
2008-12-09 16:56:01 +01:00
/* reinitialize default values */
2008-12-16 16:19:54 +01:00
oprofile_buffer_size = BUFFER_SIZE_DEFAULT ;
oprofile_cpu_buffer_size = CPU_BUFFER_SIZE_DEFAULT ;
oprofile_buffer_watershed = BUFFER_WATERSHED_DEFAULT ;
2009-07-15 15:44:18 +02:00
oprofile_time_slice = msecs_to_jiffies ( TIME_SLICE_DEFAULT ) ;
2008-12-09 16:56:01 +01:00
2005-04-16 15:20:36 -07:00
oprofilefs_create_file ( sb , root , " enable " , & enable_fops ) ;
oprofilefs_create_file_perm ( sb , root , " dump " , & dump_fops , 0666 ) ;
oprofilefs_create_file ( sb , root , " buffer " , & event_buffer_fops ) ;
2008-12-16 16:19:54 +01:00
oprofilefs_create_ulong ( sb , root , " buffer_size " , & oprofile_buffer_size ) ;
oprofilefs_create_ulong ( sb , root , " buffer_watershed " , & oprofile_buffer_watershed ) ;
oprofilefs_create_ulong ( sb , root , " cpu_buffer_size " , & oprofile_cpu_buffer_size ) ;
2008-10-16 15:01:40 +02:00
oprofilefs_create_file ( sb , root , " cpu_type " , & cpu_type_fops ) ;
2005-04-16 15:20:36 -07:00
oprofilefs_create_file ( sb , root , " backtrace_depth " , & depth_fops ) ;
oprofilefs_create_file ( sb , root , " pointer_size " , & pointer_size_fops ) ;
2009-07-08 13:49:38 +02:00
# ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
oprofilefs_create_file ( sb , root , " time_slice " , & timeout_fops ) ;
# endif
2005-04-16 15:20:36 -07:00
oprofile_create_stats_files ( sb , root ) ;
if ( oprofile_ops . create_files )
oprofile_ops . create_files ( sb , root ) ;
}