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