linux/kernel/ksysfs.c
<<
>>
Prefs
   1/*
   2 * kernel/ksysfs.c - sysfs attributes in /sys/kernel, which
   3 *                   are not related to any other subsystem
   4 *
   5 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
   6 * 
   7 * This file is release under the GPLv2
   8 *
   9 */
  10
  11#include <linux/kobject.h>
  12#include <linux/string.h>
  13#include <linux/sysfs.h>
  14#include <linux/export.h>
  15#include <linux/init.h>
  16#include <linux/kexec.h>
  17#include <linux/profile.h>
  18#include <linux/stat.h>
  19#include <linux/sched.h>
  20#include <linux/capability.h>
  21#include <linux/compiler.h>
  22
  23#include <linux/rcupdate.h>     /* rcu_expedited and rcu_normal */
  24
  25#define KERNEL_ATTR_RO(_name) \
  26static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
  27
  28#define KERNEL_ATTR_RW(_name) \
  29static struct kobj_attribute _name##_attr = \
  30        __ATTR(_name, 0644, _name##_show, _name##_store)
  31
  32/* current uevent sequence number */
  33static ssize_t uevent_seqnum_show(struct kobject *kobj,
  34                                  struct kobj_attribute *attr, char *buf)
  35{
  36        return sprintf(buf, "%llu\n", (unsigned long long)uevent_seqnum);
  37}
  38KERNEL_ATTR_RO(uevent_seqnum);
  39
  40#ifdef CONFIG_UEVENT_HELPER
  41/* uevent helper program, used during early boot */
  42static ssize_t uevent_helper_show(struct kobject *kobj,
  43                                  struct kobj_attribute *attr, char *buf)
  44{
  45        return sprintf(buf, "%s\n", uevent_helper);
  46}
  47static ssize_t uevent_helper_store(struct kobject *kobj,
  48                                   struct kobj_attribute *attr,
  49                                   const char *buf, size_t count)
  50{
  51        if (count+1 > UEVENT_HELPER_PATH_LEN)
  52                return -ENOENT;
  53        memcpy(uevent_helper, buf, count);
  54        uevent_helper[count] = '\0';
  55        if (count && uevent_helper[count-1] == '\n')
  56                uevent_helper[count-1] = '\0';
  57        return count;
  58}
  59KERNEL_ATTR_RW(uevent_helper);
  60#endif
  61
  62#ifdef CONFIG_PROFILING
  63static ssize_t profiling_show(struct kobject *kobj,
  64                                  struct kobj_attribute *attr, char *buf)
  65{
  66        return sprintf(buf, "%d\n", prof_on);
  67}
  68static ssize_t profiling_store(struct kobject *kobj,
  69                                   struct kobj_attribute *attr,
  70                                   const char *buf, size_t count)
  71{
  72        int ret;
  73
  74        if (prof_on)
  75                return -EEXIST;
  76        /*
  77         * This eventually calls into get_option() which
  78         * has a ton of callers and is not const.  It is
  79         * easiest to cast it away here.
  80         */
  81        profile_setup((char *)buf);
  82        ret = profile_init();
  83        if (ret)
  84                return ret;
  85        ret = create_proc_profile();
  86        if (ret)
  87                return ret;
  88        return count;
  89}
  90KERNEL_ATTR_RW(profiling);
  91#endif
  92
  93#ifdef CONFIG_KEXEC_CORE
  94static ssize_t kexec_loaded_show(struct kobject *kobj,
  95                                 struct kobj_attribute *attr, char *buf)
  96{
  97        return sprintf(buf, "%d\n", !!kexec_image);
  98}
  99KERNEL_ATTR_RO(kexec_loaded);
 100
 101static ssize_t kexec_crash_loaded_show(struct kobject *kobj,
 102                                       struct kobj_attribute *attr, char *buf)
 103{
 104        return sprintf(buf, "%d\n", kexec_crash_loaded());
 105}
 106KERNEL_ATTR_RO(kexec_crash_loaded);
 107
 108static ssize_t kexec_crash_size_show(struct kobject *kobj,
 109                                       struct kobj_attribute *attr, char *buf)
 110{
 111        return sprintf(buf, "%zu\n", crash_get_memory_size());
 112}
 113static ssize_t kexec_crash_size_store(struct kobject *kobj,
 114                                   struct kobj_attribute *attr,
 115                                   const char *buf, size_t count)
 116{
 117        unsigned long cnt;
 118        int ret;
 119
 120        if (kstrtoul(buf, 0, &cnt))
 121                return -EINVAL;
 122
 123        ret = crash_shrink_memory(cnt);
 124        return ret < 0 ? ret : count;
 125}
 126KERNEL_ATTR_RW(kexec_crash_size);
 127
 128static ssize_t vmcoreinfo_show(struct kobject *kobj,
 129                               struct kobj_attribute *attr, char *buf)
 130{
 131        phys_addr_t vmcore_base = paddr_vmcoreinfo_note();
 132        return sprintf(buf, "%pa %x\n", &vmcore_base,
 133                       (unsigned int)sizeof(vmcoreinfo_note));
 134}
 135KERNEL_ATTR_RO(vmcoreinfo);
 136
 137#endif /* CONFIG_KEXEC_CORE */
 138
 139/* whether file capabilities are enabled */
 140static ssize_t fscaps_show(struct kobject *kobj,
 141                                  struct kobj_attribute *attr, char *buf)
 142{
 143        return sprintf(buf, "%d\n", file_caps_enabled);
 144}
 145KERNEL_ATTR_RO(fscaps);
 146
 147#ifndef CONFIG_TINY_RCU
 148int rcu_expedited;
 149static ssize_t rcu_expedited_show(struct kobject *kobj,
 150                                  struct kobj_attribute *attr, char *buf)
 151{
 152        return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
 153}
 154static ssize_t rcu_expedited_store(struct kobject *kobj,
 155                                   struct kobj_attribute *attr,
 156                                   const char *buf, size_t count)
 157{
 158        if (kstrtoint(buf, 0, &rcu_expedited))
 159                return -EINVAL;
 160
 161        return count;
 162}
 163KERNEL_ATTR_RW(rcu_expedited);
 164
 165int rcu_normal;
 166static ssize_t rcu_normal_show(struct kobject *kobj,
 167                               struct kobj_attribute *attr, char *buf)
 168{
 169        return sprintf(buf, "%d\n", READ_ONCE(rcu_normal));
 170}
 171static ssize_t rcu_normal_store(struct kobject *kobj,
 172                                struct kobj_attribute *attr,
 173                                const char *buf, size_t count)
 174{
 175        if (kstrtoint(buf, 0, &rcu_normal))
 176                return -EINVAL;
 177
 178        return count;
 179}
 180KERNEL_ATTR_RW(rcu_normal);
 181#endif /* #ifndef CONFIG_TINY_RCU */
 182
 183/*
 184 * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
 185 */
 186extern const void __start_notes __weak;
 187extern const void __stop_notes __weak;
 188#define notes_size (&__stop_notes - &__start_notes)
 189
 190static ssize_t notes_read(struct file *filp, struct kobject *kobj,
 191                          struct bin_attribute *bin_attr,
 192                          char *buf, loff_t off, size_t count)
 193{
 194        memcpy(buf, &__start_notes + off, count);
 195        return count;
 196}
 197
 198static struct bin_attribute notes_attr = {
 199        .attr = {
 200                .name = "notes",
 201                .mode = S_IRUGO,
 202        },
 203        .read = &notes_read,
 204};
 205
 206struct kobject *kernel_kobj;
 207EXPORT_SYMBOL_GPL(kernel_kobj);
 208
 209static struct attribute * kernel_attrs[] = {
 210        &fscaps_attr.attr,
 211        &uevent_seqnum_attr.attr,
 212#ifdef CONFIG_UEVENT_HELPER
 213        &uevent_helper_attr.attr,
 214#endif
 215#ifdef CONFIG_PROFILING
 216        &profiling_attr.attr,
 217#endif
 218#ifdef CONFIG_KEXEC_CORE
 219        &kexec_loaded_attr.attr,
 220        &kexec_crash_loaded_attr.attr,
 221        &kexec_crash_size_attr.attr,
 222        &vmcoreinfo_attr.attr,
 223#endif
 224#ifndef CONFIG_TINY_RCU
 225        &rcu_expedited_attr.attr,
 226        &rcu_normal_attr.attr,
 227#endif
 228        NULL
 229};
 230
 231static struct attribute_group kernel_attr_group = {
 232        .attrs = kernel_attrs,
 233};
 234
 235static int __init ksysfs_init(void)
 236{
 237        int error;
 238
 239        kernel_kobj = kobject_create_and_add("kernel", NULL);
 240        if (!kernel_kobj) {
 241                error = -ENOMEM;
 242                goto exit;
 243        }
 244        error = sysfs_create_group(kernel_kobj, &kernel_attr_group);
 245        if (error)
 246                goto kset_exit;
 247
 248        if (notes_size > 0) {
 249                notes_attr.size = notes_size;
 250                error = sysfs_create_bin_file(kernel_kobj, &notes_attr);
 251                if (error)
 252                        goto group_exit;
 253        }
 254
 255        return 0;
 256
 257group_exit:
 258        sysfs_remove_group(kernel_kobj, &kernel_attr_group);
 259kset_exit:
 260        kobject_put(kernel_kobj);
 261exit:
 262        return error;
 263}
 264
 265core_initcall(ksysfs_init);
 266