Back to home page

LXR

 
 

    


0001 /*
0002  * kernel/ksysfs.c - sysfs attributes in /sys/kernel, which
0003  *           are not related to any other subsystem
0004  *
0005  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
0006  * 
0007  * This file is release under the GPLv2
0008  *
0009  */
0010 
0011 #include <linux/kobject.h>
0012 #include <linux/string.h>
0013 #include <linux/sysfs.h>
0014 #include <linux/export.h>
0015 #include <linux/init.h>
0016 #include <linux/kexec.h>
0017 #include <linux/profile.h>
0018 #include <linux/stat.h>
0019 #include <linux/sched.h>
0020 #include <linux/capability.h>
0021 #include <linux/compiler.h>
0022 
0023 #include <linux/rcupdate.h> /* rcu_expedited and rcu_normal */
0024 
0025 #define KERNEL_ATTR_RO(_name) \
0026 static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
0027 
0028 #define KERNEL_ATTR_RW(_name) \
0029 static struct kobj_attribute _name##_attr = \
0030     __ATTR(_name, 0644, _name##_show, _name##_store)
0031 
0032 /* current uevent sequence number */
0033 static ssize_t uevent_seqnum_show(struct kobject *kobj,
0034                   struct kobj_attribute *attr, char *buf)
0035 {
0036     return sprintf(buf, "%llu\n", (unsigned long long)uevent_seqnum);
0037 }
0038 KERNEL_ATTR_RO(uevent_seqnum);
0039 
0040 #ifdef CONFIG_UEVENT_HELPER
0041 /* uevent helper program, used during early boot */
0042 static ssize_t uevent_helper_show(struct kobject *kobj,
0043                   struct kobj_attribute *attr, char *buf)
0044 {
0045     return sprintf(buf, "%s\n", uevent_helper);
0046 }
0047 static ssize_t uevent_helper_store(struct kobject *kobj,
0048                    struct kobj_attribute *attr,
0049                    const char *buf, size_t count)
0050 {
0051     if (count+1 > UEVENT_HELPER_PATH_LEN)
0052         return -ENOENT;
0053     memcpy(uevent_helper, buf, count);
0054     uevent_helper[count] = '\0';
0055     if (count && uevent_helper[count-1] == '\n')
0056         uevent_helper[count-1] = '\0';
0057     return count;
0058 }
0059 KERNEL_ATTR_RW(uevent_helper);
0060 #endif
0061 
0062 #ifdef CONFIG_PROFILING
0063 static ssize_t profiling_show(struct kobject *kobj,
0064                   struct kobj_attribute *attr, char *buf)
0065 {
0066     return sprintf(buf, "%d\n", prof_on);
0067 }
0068 static ssize_t profiling_store(struct kobject *kobj,
0069                    struct kobj_attribute *attr,
0070                    const char *buf, size_t count)
0071 {
0072     int ret;
0073 
0074     if (prof_on)
0075         return -EEXIST;
0076     /*
0077      * This eventually calls into get_option() which
0078      * has a ton of callers and is not const.  It is
0079      * easiest to cast it away here.
0080      */
0081     profile_setup((char *)buf);
0082     ret = profile_init();
0083     if (ret)
0084         return ret;
0085     ret = create_proc_profile();
0086     if (ret)
0087         return ret;
0088     return count;
0089 }
0090 KERNEL_ATTR_RW(profiling);
0091 #endif
0092 
0093 #ifdef CONFIG_KEXEC_CORE
0094 static ssize_t kexec_loaded_show(struct kobject *kobj,
0095                  struct kobj_attribute *attr, char *buf)
0096 {
0097     return sprintf(buf, "%d\n", !!kexec_image);
0098 }
0099 KERNEL_ATTR_RO(kexec_loaded);
0100 
0101 static ssize_t kexec_crash_loaded_show(struct kobject *kobj,
0102                        struct kobj_attribute *attr, char *buf)
0103 {
0104     return sprintf(buf, "%d\n", kexec_crash_loaded());
0105 }
0106 KERNEL_ATTR_RO(kexec_crash_loaded);
0107 
0108 static ssize_t kexec_crash_size_show(struct kobject *kobj,
0109                        struct kobj_attribute *attr, char *buf)
0110 {
0111     return sprintf(buf, "%zu\n", crash_get_memory_size());
0112 }
0113 static ssize_t kexec_crash_size_store(struct kobject *kobj,
0114                    struct kobj_attribute *attr,
0115                    const char *buf, size_t count)
0116 {
0117     unsigned long cnt;
0118     int ret;
0119 
0120     if (kstrtoul(buf, 0, &cnt))
0121         return -EINVAL;
0122 
0123     ret = crash_shrink_memory(cnt);
0124     return ret < 0 ? ret : count;
0125 }
0126 KERNEL_ATTR_RW(kexec_crash_size);
0127 
0128 static ssize_t vmcoreinfo_show(struct kobject *kobj,
0129                    struct kobj_attribute *attr, char *buf)
0130 {
0131     phys_addr_t vmcore_base = paddr_vmcoreinfo_note();
0132     return sprintf(buf, "%pa %x\n", &vmcore_base,
0133                (unsigned int)sizeof(vmcoreinfo_note));
0134 }
0135 KERNEL_ATTR_RO(vmcoreinfo);
0136 
0137 #endif /* CONFIG_KEXEC_CORE */
0138 
0139 /* whether file capabilities are enabled */
0140 static ssize_t fscaps_show(struct kobject *kobj,
0141                   struct kobj_attribute *attr, char *buf)
0142 {
0143     return sprintf(buf, "%d\n", file_caps_enabled);
0144 }
0145 KERNEL_ATTR_RO(fscaps);
0146 
0147 #ifndef CONFIG_TINY_RCU
0148 int rcu_expedited;
0149 static ssize_t rcu_expedited_show(struct kobject *kobj,
0150                   struct kobj_attribute *attr, char *buf)
0151 {
0152     return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
0153 }
0154 static ssize_t rcu_expedited_store(struct kobject *kobj,
0155                    struct kobj_attribute *attr,
0156                    const char *buf, size_t count)
0157 {
0158     if (kstrtoint(buf, 0, &rcu_expedited))
0159         return -EINVAL;
0160 
0161     return count;
0162 }
0163 KERNEL_ATTR_RW(rcu_expedited);
0164 
0165 int rcu_normal;
0166 static ssize_t rcu_normal_show(struct kobject *kobj,
0167                    struct kobj_attribute *attr, char *buf)
0168 {
0169     return sprintf(buf, "%d\n", READ_ONCE(rcu_normal));
0170 }
0171 static ssize_t rcu_normal_store(struct kobject *kobj,
0172                 struct kobj_attribute *attr,
0173                 const char *buf, size_t count)
0174 {
0175     if (kstrtoint(buf, 0, &rcu_normal))
0176         return -EINVAL;
0177 
0178     return count;
0179 }
0180 KERNEL_ATTR_RW(rcu_normal);
0181 #endif /* #ifndef CONFIG_TINY_RCU */
0182 
0183 /*
0184  * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
0185  */
0186 extern const void __start_notes __weak;
0187 extern const void __stop_notes __weak;
0188 #define notes_size (&__stop_notes - &__start_notes)
0189 
0190 static ssize_t notes_read(struct file *filp, struct kobject *kobj,
0191               struct bin_attribute *bin_attr,
0192               char *buf, loff_t off, size_t count)
0193 {
0194     memcpy(buf, &__start_notes + off, count);
0195     return count;
0196 }
0197 
0198 static struct bin_attribute notes_attr = {
0199     .attr = {
0200         .name = "notes",
0201         .mode = S_IRUGO,
0202     },
0203     .read = &notes_read,
0204 };
0205 
0206 struct kobject *kernel_kobj;
0207 EXPORT_SYMBOL_GPL(kernel_kobj);
0208 
0209 static struct attribute * kernel_attrs[] = {
0210     &fscaps_attr.attr,
0211     &uevent_seqnum_attr.attr,
0212 #ifdef CONFIG_UEVENT_HELPER
0213     &uevent_helper_attr.attr,
0214 #endif
0215 #ifdef CONFIG_PROFILING
0216     &profiling_attr.attr,
0217 #endif
0218 #ifdef CONFIG_KEXEC_CORE
0219     &kexec_loaded_attr.attr,
0220     &kexec_crash_loaded_attr.attr,
0221     &kexec_crash_size_attr.attr,
0222     &vmcoreinfo_attr.attr,
0223 #endif
0224 #ifndef CONFIG_TINY_RCU
0225     &rcu_expedited_attr.attr,
0226     &rcu_normal_attr.attr,
0227 #endif
0228     NULL
0229 };
0230 
0231 static struct attribute_group kernel_attr_group = {
0232     .attrs = kernel_attrs,
0233 };
0234 
0235 static int __init ksysfs_init(void)
0236 {
0237     int error;
0238 
0239     kernel_kobj = kobject_create_and_add("kernel", NULL);
0240     if (!kernel_kobj) {
0241         error = -ENOMEM;
0242         goto exit;
0243     }
0244     error = sysfs_create_group(kernel_kobj, &kernel_attr_group);
0245     if (error)
0246         goto kset_exit;
0247 
0248     if (notes_size > 0) {
0249         notes_attr.size = notes_size;
0250         error = sysfs_create_bin_file(kernel_kobj, &notes_attr);
0251         if (error)
0252             goto group_exit;
0253     }
0254 
0255     return 0;
0256 
0257 group_exit:
0258     sysfs_remove_group(kernel_kobj, &kernel_attr_group);
0259 kset_exit:
0260     kobject_put(kernel_kobj);
0261 exit:
0262     return error;
0263 }
0264 
0265 core_initcall(ksysfs_init);