ia64/linux-2.6.18-xen.hg

annotate drivers/oprofile/oprofilefs.c @ 893:f994bfe9b93b

linux/blktap2: reduce TLB flush scope

c/s 885 added very coarse TLB flushing. Since these flushes always
follow single page updates, single page flushes (when available) are
sufficient.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 04 10:32:57 2009 +0100 (2009-06-04)
parents 831230e53067
children
rev   line source
ian@0 1 /**
ian@0 2 * @file oprofilefs.c
ian@0 3 *
ian@0 4 * @remark Copyright 2002 OProfile authors
ian@0 5 * @remark Read the file COPYING
ian@0 6 *
ian@0 7 * @author John Levon
ian@0 8 *
ian@0 9 * A simple filesystem for configuration and
ian@0 10 * access of oprofile.
ian@0 11 */
ian@0 12
ian@0 13 #include <linux/init.h>
ian@0 14 #include <linux/module.h>
ian@0 15 #include <linux/oprofile.h>
ian@0 16 #include <linux/fs.h>
ian@0 17 #include <linux/pagemap.h>
ian@0 18 #include <asm/uaccess.h>
ian@0 19
ian@0 20 #include "oprof.h"
ian@0 21
ian@0 22 #define OPROFILEFS_MAGIC 0x6f70726f
ian@0 23
ian@0 24 DEFINE_SPINLOCK(oprofilefs_lock);
ian@0 25
ian@0 26 static struct inode * oprofilefs_get_inode(struct super_block * sb, int mode)
ian@0 27 {
ian@0 28 struct inode * inode = new_inode(sb);
ian@0 29
ian@0 30 if (inode) {
ian@0 31 inode->i_mode = mode;
ian@0 32 inode->i_uid = 0;
ian@0 33 inode->i_gid = 0;
ian@0 34 inode->i_blksize = PAGE_CACHE_SIZE;
ian@0 35 inode->i_blocks = 0;
ian@0 36 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
ian@0 37 }
ian@0 38 return inode;
ian@0 39 }
ian@0 40
ian@0 41
ian@0 42 static struct super_operations s_ops = {
ian@0 43 .statfs = simple_statfs,
ian@0 44 .drop_inode = generic_delete_inode,
ian@0 45 };
ian@0 46
ian@0 47
ian@0 48 ssize_t oprofilefs_str_to_user(char const * str, char __user * buf, size_t count, loff_t * offset)
ian@0 49 {
ian@0 50 return simple_read_from_buffer(buf, count, offset, str, strlen(str));
ian@0 51 }
ian@0 52
ian@0 53
ian@0 54 #define TMPBUFSIZE 50
ian@0 55
ian@0 56 ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t count, loff_t * offset)
ian@0 57 {
ian@0 58 char tmpbuf[TMPBUFSIZE];
ian@0 59 size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val);
ian@0 60 if (maxlen > TMPBUFSIZE)
ian@0 61 maxlen = TMPBUFSIZE;
ian@0 62 return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen);
ian@0 63 }
ian@0 64
ian@0 65
ian@0 66 int oprofilefs_ulong_from_user(unsigned long * val, char const __user * buf, size_t count)
ian@0 67 {
ian@0 68 char tmpbuf[TMPBUFSIZE];
ian@0 69
ian@0 70 if (!count)
ian@0 71 return 0;
ian@0 72
ian@0 73 if (count > TMPBUFSIZE - 1)
ian@0 74 return -EINVAL;
ian@0 75
ian@0 76 memset(tmpbuf, 0x0, TMPBUFSIZE);
ian@0 77
ian@0 78 if (copy_from_user(tmpbuf, buf, count))
ian@0 79 return -EFAULT;
ian@0 80
ian@0 81 spin_lock(&oprofilefs_lock);
ian@0 82 *val = simple_strtoul(tmpbuf, NULL, 0);
ian@0 83 spin_unlock(&oprofilefs_lock);
ian@0 84 return 0;
ian@0 85 }
ian@0 86
ian@0 87
ian@0 88 static ssize_t ulong_read_file(struct file * file, char __user * buf, size_t count, loff_t * offset)
ian@0 89 {
ian@0 90 unsigned long * val = file->private_data;
ian@0 91 return oprofilefs_ulong_to_user(*val, buf, count, offset);
ian@0 92 }
ian@0 93
ian@0 94
ian@0 95 static ssize_t ulong_write_file(struct file * file, char const __user * buf, size_t count, loff_t * offset)
ian@0 96 {
ian@0 97 unsigned long * value = file->private_data;
ian@0 98 int retval;
ian@0 99
ian@0 100 if (*offset)
ian@0 101 return -EINVAL;
ian@0 102
ian@0 103 retval = oprofilefs_ulong_from_user(value, buf, count);
ian@0 104
ian@0 105 if (retval)
ian@0 106 return retval;
ian@0 107 return count;
ian@0 108 }
ian@0 109
ian@0 110
ian@0 111 static int default_open(struct inode * inode, struct file * filp)
ian@0 112 {
ian@0 113 if (inode->u.generic_ip)
ian@0 114 filp->private_data = inode->u.generic_ip;
ian@0 115 return 0;
ian@0 116 }
ian@0 117
ian@0 118
ian@0 119 static struct file_operations ulong_fops = {
ian@0 120 .read = ulong_read_file,
ian@0 121 .write = ulong_write_file,
ian@0 122 .open = default_open,
ian@0 123 };
ian@0 124
ian@0 125
ian@0 126 static struct file_operations ulong_ro_fops = {
ian@0 127 .read = ulong_read_file,
ian@0 128 .open = default_open,
ian@0 129 };
ian@0 130
ian@0 131
ian@0 132 static struct dentry * __oprofilefs_create_file(struct super_block * sb,
ian@0 133 struct dentry * root, char const * name, const struct file_operations * fops,
ian@0 134 int perm)
ian@0 135 {
ian@0 136 struct dentry * dentry;
ian@0 137 struct inode * inode;
ian@0 138
ian@0 139 dentry = d_alloc_name(root, name);
ian@0 140 if (!dentry)
ian@0 141 return NULL;
ian@0 142 inode = oprofilefs_get_inode(sb, S_IFREG | perm);
ian@0 143 if (!inode) {
ian@0 144 dput(dentry);
ian@0 145 return NULL;
ian@0 146 }
ian@0 147 inode->i_fop = fops;
ian@0 148 d_add(dentry, inode);
ian@0 149 return dentry;
ian@0 150 }
ian@0 151
ian@0 152
ian@0 153 int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root,
ian@0 154 char const * name, unsigned long * val)
ian@0 155 {
ian@0 156 struct dentry * d = __oprofilefs_create_file(sb, root, name,
ian@0 157 &ulong_fops, 0644);
ian@0 158 if (!d)
ian@0 159 return -EFAULT;
ian@0 160
ian@0 161 d->d_inode->u.generic_ip = val;
ian@0 162 return 0;
ian@0 163 }
ian@0 164
ian@0 165
ian@0 166 int oprofilefs_create_ro_ulong(struct super_block * sb, struct dentry * root,
ian@0 167 char const * name, unsigned long * val)
ian@0 168 {
ian@0 169 struct dentry * d = __oprofilefs_create_file(sb, root, name,
ian@0 170 &ulong_ro_fops, 0444);
ian@0 171 if (!d)
ian@0 172 return -EFAULT;
ian@0 173
ian@0 174 d->d_inode->u.generic_ip = val;
ian@0 175 return 0;
ian@0 176 }
ian@0 177
ian@0 178
ian@0 179 static ssize_t atomic_read_file(struct file * file, char __user * buf, size_t count, loff_t * offset)
ian@0 180 {
ian@0 181 atomic_t * val = file->private_data;
ian@0 182 return oprofilefs_ulong_to_user(atomic_read(val), buf, count, offset);
ian@0 183 }
ian@0 184
ian@0 185
ian@0 186 static struct file_operations atomic_ro_fops = {
ian@0 187 .read = atomic_read_file,
ian@0 188 .open = default_open,
ian@0 189 };
ian@0 190
ian@0 191
ian@0 192 int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
ian@0 193 char const * name, atomic_t * val)
ian@0 194 {
ian@0 195 struct dentry * d = __oprofilefs_create_file(sb, root, name,
ian@0 196 &atomic_ro_fops, 0444);
ian@0 197 if (!d)
ian@0 198 return -EFAULT;
ian@0 199
ian@0 200 d->d_inode->u.generic_ip = val;
ian@0 201 return 0;
ian@0 202 }
ian@0 203
ian@0 204
ian@0 205 int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
ian@0 206 char const * name, const struct file_operations * fops)
ian@0 207 {
ian@0 208 if (!__oprofilefs_create_file(sb, root, name, fops, 0644))
ian@0 209 return -EFAULT;
ian@0 210 return 0;
ian@0 211 }
ian@0 212
ian@0 213
ian@0 214 int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root,
ian@0 215 char const * name, const struct file_operations * fops, int perm)
ian@0 216 {
ian@0 217 if (!__oprofilefs_create_file(sb, root, name, fops, perm))
ian@0 218 return -EFAULT;
ian@0 219 return 0;
ian@0 220 }
ian@0 221
ian@0 222
ian@0 223 struct dentry * oprofilefs_mkdir(struct super_block * sb,
ian@0 224 struct dentry * root, char const * name)
ian@0 225 {
ian@0 226 struct dentry * dentry;
ian@0 227 struct inode * inode;
ian@0 228
ian@0 229 dentry = d_alloc_name(root, name);
ian@0 230 if (!dentry)
ian@0 231 return NULL;
ian@0 232 inode = oprofilefs_get_inode(sb, S_IFDIR | 0755);
ian@0 233 if (!inode) {
ian@0 234 dput(dentry);
ian@0 235 return NULL;
ian@0 236 }
ian@0 237 inode->i_op = &simple_dir_inode_operations;
ian@0 238 inode->i_fop = &simple_dir_operations;
ian@0 239 d_add(dentry, inode);
ian@0 240 return dentry;
ian@0 241 }
ian@0 242
ian@0 243
ian@0 244 static int oprofilefs_fill_super(struct super_block * sb, void * data, int silent)
ian@0 245 {
ian@0 246 struct inode * root_inode;
ian@0 247 struct dentry * root_dentry;
ian@0 248
ian@0 249 sb->s_blocksize = PAGE_CACHE_SIZE;
ian@0 250 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
ian@0 251 sb->s_magic = OPROFILEFS_MAGIC;
ian@0 252 sb->s_op = &s_ops;
ian@0 253 sb->s_time_gran = 1;
ian@0 254
ian@0 255 root_inode = oprofilefs_get_inode(sb, S_IFDIR | 0755);
ian@0 256 if (!root_inode)
ian@0 257 return -ENOMEM;
ian@0 258 root_inode->i_op = &simple_dir_inode_operations;
ian@0 259 root_inode->i_fop = &simple_dir_operations;
ian@0 260 root_dentry = d_alloc_root(root_inode);
ian@0 261 if (!root_dentry) {
ian@0 262 iput(root_inode);
ian@0 263 return -ENOMEM;
ian@0 264 }
ian@0 265
ian@0 266 sb->s_root = root_dentry;
ian@0 267
ian@0 268 oprofile_create_files(sb, root_dentry);
ian@0 269
ian@0 270 // FIXME: verify kill_litter_super removes our dentries
ian@0 271 return 0;
ian@0 272 }
ian@0 273
ian@0 274
ian@0 275 static int oprofilefs_get_sb(struct file_system_type *fs_type,
ian@0 276 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
ian@0 277 {
ian@0 278 return get_sb_single(fs_type, flags, data, oprofilefs_fill_super, mnt);
ian@0 279 }
ian@0 280
ian@0 281
ian@0 282 static struct file_system_type oprofilefs_type = {
ian@0 283 .owner = THIS_MODULE,
ian@0 284 .name = "oprofilefs",
ian@0 285 .get_sb = oprofilefs_get_sb,
ian@0 286 .kill_sb = kill_litter_super,
ian@0 287 };
ian@0 288
ian@0 289
ian@0 290 int __init oprofilefs_register(void)
ian@0 291 {
ian@0 292 return register_filesystem(&oprofilefs_type);
ian@0 293 }
ian@0 294
ian@0 295
ian@0 296 void __exit oprofilefs_unregister(void)
ian@0 297 {
ian@0 298 unregister_filesystem(&oprofilefs_type);
ian@0 299 }