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
 128#endif /* CONFIG_KEXEC_CORE */
 129
 130#ifdef CONFIG_CRASH_CORE
 131
 132static ssize_t vmcoreinfo_show(struct kobject *kobj,
 133                               struct kobj_attribute *attr, char *buf)
 134{
 135        phys_addr_t vmcore_base = paddr_vmcoreinfo_note();
 136        return sprintf(buf, "%pa %x\n", &vmcore_base,
 137                        (unsigned int)VMCOREINFO_NOTE_SIZE);
 138}
 139KERNEL_ATTR_RO(vmcoreinfo);
 140
 141#endif /* CONFIG_CRASH_CORE */
 142
 143/* whether file capabilities are enabled */
 144static ssize_t fscaps_show(struct kobject *kobj,
 145                                  struct kobj_attribute *attr, char *buf)
 146{
 147        return sprintf(buf, "%d\n", file_caps_enabled);
 148}
 149KERNEL_ATTR_RO(fscaps);
 150
 151#ifndef CONFIG_TINY_RCU
 152int rcu_expedited;
 153static ssize_t rcu_expedited_show(struct kobject *kobj,
 154                                  struct kobj_attribute *attr, char *buf)
 155{
 156        return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
 157}
 158static ssize_t rcu_expedited_store(struct kobject *kobj,
 159                                   struct kobj_attribute *attr,
 160                                   const char *buf, size_t count)
 161{
 162        if (kstrtoint(buf, 0, &rcu_expedited))
 163                return -EINVAL;
 164
 165        return count;
 166}
 167KERNEL_ATTR_RW(rcu_expedited);
 168
 169int rcu_normal;
 170static ssize_t rcu_normal_show(struct kobject *kobj,
 171                               struct kobj_attribute *attr, char *buf)
 172{
 173        return sprintf(buf, "%d\n", READ_ONCE(rcu_normal));
 174}
 175static ssize_t rcu_normal_store(struct kobject *kobj,
 176                                struct kobj_attribute *attr,
 177                                const char *buf, size_t count)
 178{
 179        if (kstrtoint(buf, 0, &rcu_normal))
 180                return -EINVAL;
 181
 182        return count;
 183}
 184KERNEL_ATTR_RW(rcu_normal);
 185#endif /* #ifndef CONFIG_TINY_RCU */
 186
 187/*
 188 * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
 189 */
 190extern const void __start_notes __weak;
 191extern const void __stop_notes __weak;
 192#define notes_size (&__stop_notes - &__start_notes)
 193
 194static ssize_t notes_read(struct file *filp, struct kobject *kobj,
 195                          struct bin_attribute *bin_attr,
 196                          char *buf, loff_t off, size_t count)
 197{
 198        memcpy(buf, &__start_notes + off, count);
 199        return count;
 200}
 201
 202static struct bin_attribute notes_attr __ro_after_init  = {
 203        .attr = {
 204                .name = "notes",
 205                .mode = S_IRUGO,
 206        },
 207        .read = &notes_read,
 208};
 209
 210struct kobject *kernel_kobj;
 211EXPORT_SYMBOL_GPL(kernel_kobj);
 212
 213static struct attribute * kernel_attrs[] = {
 214        &fscaps_attr.attr,
 215        &uevent_seqnum_attr.attr,
 216#ifdef CONFIG_UEVENT_HELPER
 217        &uevent_helper_attr.attr,
 218#endif
 219#ifdef CONFIG_PROFILING
 220        &profiling_attr.attr,
 221#endif
 222#ifdef CONFIG_KEXEC_CORE
 223        &kexec_loaded_attr.attr,
 224        &kexec_crash_loaded_attr.attr,
 225        &kexec_crash_size_attr.attr,
 226#endif
 227#ifdef CONFIG_CRASH_CORE
 228        &vmcoreinfo_attr.attr,
 229#endif
 230#ifndef CONFIG_TINY_RCU
 231        &rcu_expedited_attr.attr,
 232        &rcu_normal_attr.attr,
 233#endif
 234        NULL
 235};
 236
 237static const struct attribute_group kernel_attr_group = {
 238        .attrs = kernel_attrs,
 239};
 240
 241static int __init ksysfs_init(void)
 242{
 243        int error;
 244
 245        kernel_kobj = kobject_create_and_add("kernel", NULL);
 246        if (!kernel_kobj) {
 247                error = -ENOMEM;
 248                goto exit;
 249        }
 250        error = sysfs_create_group(kernel_kobj, &kernel_attr_group);
 251        if (error)
 252                goto kset_exit;
 253
 254        if (notes_size > 0) {
 255                notes_attr.size = notes_size;
 256                error = sysfs_create_bin_file(kernel_kobj, &notes_attr);
 257                if (error)
 258                        goto group_exit;
 259        }
 260
 261        return 0;
 262
 263group_exit:
 264        sysfs_remove_group(kernel_kobj, &kernel_attr_group);
 265kset_exit:
 266        kobject_put(kernel_kobj);
 267exit:
 268        return error;
 269}
 270
 271core_initcall(ksysfs_init);
 272