1/** 2 * @file oprofile_files.c 3 * 4 * @remark Copyright 2002 OProfile authors 5 * @remark Read the file COPYING 6 * 7 * @author John Levon <levon@movementarian.org> 8 */ 9 10#include <linux/fs.h> 11#include <linux/oprofile.h> 12 13#include "event_buffer.h" 14#include "oprofile_stats.h" 15#include "oprof.h" 16 17unsigned long fs_buffer_size = 131072; 18unsigned long fs_cpu_buffer_size = 8192; 19unsigned long fs_buffer_watershed = 32768; 20 21static ssize_t depth_read(struct file * file, char __user * buf, size_t count, loff_t * offset) 22{ 23 return oprofilefs_ulong_to_user(backtrace_depth, buf, count, offset); 24} 25 26 27static ssize_t depth_write(struct file * file, char const __user * buf, size_t count, loff_t * offset) 28{ 29 unsigned long val; 30 int retval; 31 32 if (*offset) 33 return -EINVAL; 34 35 retval = oprofilefs_ulong_from_user(&val, buf, count); 36 if (retval) 37 return retval; 38 39 retval = oprofile_set_backtrace(val); 40 41 if (retval) 42 return retval; 43 return count; 44} 45 46 47static const struct file_operations depth_fops = { 48 .read = depth_read, 49 .write = depth_write 50}; 51 52 53static ssize_t pointer_size_read(struct file * file, char __user * buf, size_t count, loff_t * offset) 54{ 55 return oprofilefs_ulong_to_user(sizeof(void *), buf, count, offset); 56} 57 58 59static const struct file_operations pointer_size_fops = { 60 .read = pointer_size_read, 61}; 62 63 64static ssize_t cpu_type_read(struct file * file, char __user * buf, size_t count, loff_t * offset) 65{ 66 return oprofilefs_str_to_user(oprofile_ops.cpu_type, buf, count, offset); 67} 68 69 70static const struct file_operations cpu_type_fops = { 71 .read = cpu_type_read, 72}; 73 74 75static ssize_t enable_read(struct file * file, char __user * buf, size_t count, loff_t * offset) 76{ 77 return oprofilefs_ulong_to_user(oprofile_started, buf, count, offset); 78} 79 80 81static ssize_t enable_write(struct file * file, char const __user * buf, size_t count, loff_t * offset) 82{ 83 unsigned long val; 84 int retval; 85 86 if (*offset) 87 return -EINVAL; 88 89 retval = oprofilefs_ulong_from_user(&val, buf, count); 90 if (retval) 91 return retval; 92 93 if (val) 94 retval = oprofile_start(); 95 else 96 oprofile_stop(); 97 98 if (retval) 99 return retval; 100 return count; 101} 102 103 104static const struct file_operations enable_fops = { 105 .read = enable_read, 106 .write = enable_write, 107}; 108 109 110static ssize_t dump_write(struct file * file, char const __user * buf, size_t count, loff_t * offset) 111{ 112 wake_up_buffer_waiter(); 113 return count; 114} 115 116 117static const struct file_operations dump_fops = { 118 .write = dump_write, 119}; 120 121void oprofile_create_files(struct super_block * sb, struct dentry * root) 122{ 123 oprofilefs_create_file(sb, root, "enable", &enable_fops); 124 oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); 125 oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops); 126 oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size); 127 oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed); 128 oprofilefs_create_ulong(sb, root, "cpu_buffer_size", &fs_cpu_buffer_size); 129 oprofilefs_create_file(sb, root, "cpu_type", &cpu_type_fops); 130 oprofilefs_create_file(sb, root, "backtrace_depth", &depth_fops); 131 oprofilefs_create_file(sb, root, "pointer_size", &pointer_size_fops); 132 oprofile_create_stats_files(sb, root); 133 if (oprofile_ops.create_files) 134 oprofile_ops.create_files(sb, root); 135} 136