2005-04-17 02:20:36 +04:00
/*
* kernel / ksysfs . c - sysfs attributes in / sys / kernel , which
* are not related to any other subsystem
*
* Copyright ( C ) 2004 Kay Sievers < kay . sievers @ vrfy . org >
*
* This file is release under the GPLv2
*
*/
# include <linux/kobject.h>
# include <linux/string.h>
# include <linux/sysfs.h>
# include <linux/module.h>
# include <linux/init.h>
2006-06-23 13:05:07 +04:00
# include <linux/kexec.h>
2008-10-16 09:01:46 +04:00
# include <linux/profile.h>
2007-10-15 19:00:14 +04:00
# include <linux/sched.h>
2005-04-17 02:20:36 +04:00
# define KERNEL_ATTR_RO(_name) \
2007-11-02 15:47:53 +03:00
static struct kobj_attribute _name # # _attr = __ATTR_RO ( _name )
2005-04-17 02:20:36 +04:00
# define KERNEL_ATTR_RW(_name) \
2007-11-02 15:47:53 +03:00
static struct kobj_attribute _name # # _attr = \
2005-04-17 02:20:36 +04:00
__ATTR ( _name , 0644 , _name # # _show , _name # # _store )
2008-11-16 13:22:09 +03:00
# if defined(CONFIG_HOTPLUG)
2005-11-11 06:58:04 +03:00
/* current uevent sequence number */
2007-11-02 15:47:53 +03:00
static ssize_t uevent_seqnum_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2007-11-02 15:47:53 +03:00
return sprintf ( buf , " %llu \n " , ( unsigned long long ) uevent_seqnum ) ;
2005-04-17 02:20:36 +04:00
}
2005-11-11 06:58:04 +03:00
KERNEL_ATTR_RO ( uevent_seqnum ) ;
/* uevent helper program, used during early boo */
2007-11-02 15:47:53 +03:00
static ssize_t uevent_helper_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
2005-11-11 06:58:04 +03:00
{
2007-11-02 15:47:53 +03:00
return sprintf ( buf , " %s \n " , uevent_helper ) ;
2005-11-11 06:58:04 +03:00
}
2007-11-02 15:47:53 +03:00
static ssize_t uevent_helper_store ( struct kobject * kobj ,
struct kobj_attribute * attr ,
const char * buf , size_t count )
2005-11-11 06:58:04 +03:00
{
2005-11-16 11:00:00 +03:00
if ( count + 1 > UEVENT_HELPER_PATH_LEN )
2005-11-11 06:58:04 +03:00
return - ENOENT ;
2007-11-02 15:47:53 +03:00
memcpy ( uevent_helper , buf , count ) ;
2005-11-16 11:00:00 +03:00
uevent_helper [ count ] = ' \0 ' ;
if ( count & & uevent_helper [ count - 1 ] = = ' \n ' )
uevent_helper [ count - 1 ] = ' \0 ' ;
2005-11-11 06:58:04 +03:00
return count ;
}
KERNEL_ATTR_RW ( uevent_helper ) ;
2005-04-17 02:20:36 +04:00
# endif
2008-10-16 09:01:46 +04:00
# ifdef CONFIG_PROFILING
static ssize_t profiling_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
{
return sprintf ( buf , " %d \n " , prof_on ) ;
}
static ssize_t profiling_store ( struct kobject * kobj ,
struct kobj_attribute * attr ,
const char * buf , size_t count )
{
int ret ;
if ( prof_on )
return - EEXIST ;
/*
* This eventually calls into get_option ( ) which
* has a ton of callers and is not const . It is
* easiest to cast it away here .
*/
profile_setup ( ( char * ) buf ) ;
ret = profile_init ( ) ;
if ( ret )
return ret ;
ret = create_proc_profile ( ) ;
if ( ret )
return ret ;
return count ;
}
KERNEL_ATTR_RW ( profiling ) ;
# endif
2006-06-23 13:05:07 +04:00
# ifdef CONFIG_KEXEC
2007-11-02 15:47:53 +03:00
static ssize_t kexec_loaded_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
2006-06-23 13:05:07 +04:00
{
2007-11-02 15:47:53 +03:00
return sprintf ( buf , " %d \n " , ! ! kexec_image ) ;
2006-06-23 13:05:07 +04:00
}
KERNEL_ATTR_RO ( kexec_loaded ) ;
2007-11-02 15:47:53 +03:00
static ssize_t kexec_crash_loaded_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
2006-06-23 13:05:07 +04:00
{
2007-11-02 15:47:53 +03:00
return sprintf ( buf , " %d \n " , ! ! kexec_crash_image ) ;
2006-06-23 13:05:07 +04:00
}
KERNEL_ATTR_RO ( kexec_crash_loaded ) ;
2007-10-17 10:27:27 +04:00
2009-12-16 03:47:46 +03:00
static ssize_t kexec_crash_size_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
{
return sprintf ( buf , " %zu \n " , crash_get_memory_size ( ) ) ;
}
static ssize_t kexec_crash_size_store ( struct kobject * kobj ,
struct kobj_attribute * attr ,
const char * buf , size_t count )
{
unsigned long cnt ;
int ret ;
if ( strict_strtoul ( buf , 0 , & cnt ) )
return - EINVAL ;
ret = crash_shrink_memory ( cnt ) ;
return ret < 0 ? ret : count ;
}
KERNEL_ATTR_RW ( kexec_crash_size ) ;
2007-11-02 15:47:53 +03:00
static ssize_t vmcoreinfo_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
2007-10-17 10:27:27 +04:00
{
2007-11-02 15:47:53 +03:00
return sprintf ( buf , " %lx %x \n " ,
2007-10-17 10:27:27 +04:00
paddr_vmcoreinfo_note ( ) ,
2007-10-17 10:27:28 +04:00
( unsigned int ) vmcoreinfo_max_size ) ;
2007-10-17 10:27:27 +04:00
}
KERNEL_ATTR_RO ( vmcoreinfo ) ;
2006-06-23 13:05:07 +04:00
# endif /* CONFIG_KEXEC */
2007-07-19 12:48:39 +04:00
/*
* Make / sys / kernel / notes give the raw contents of our kernel . notes section .
*/
2007-07-20 20:02:04 +04:00
extern const void __start_notes __attribute__ ( ( weak ) ) ;
extern const void __stop_notes __attribute__ ( ( weak ) ) ;
2007-07-19 12:48:39 +04:00
# define notes_size (&__stop_notes - &__start_notes)
static ssize_t notes_read ( struct kobject * kobj , struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
{
memcpy ( buf , & __start_notes + off , count ) ;
return count ;
}
static struct bin_attribute notes_attr = {
. attr = {
. name = " notes " ,
. mode = S_IRUGO ,
} ,
. read = & notes_read ,
} ;
2007-11-06 21:36:58 +03:00
struct kobject * kernel_kobj ;
EXPORT_SYMBOL_GPL ( kernel_kobj ) ;
2005-04-17 02:20:36 +04:00
static struct attribute * kernel_attrs [ ] = {
2008-11-16 13:22:09 +03:00
# if defined(CONFIG_HOTPLUG)
2005-11-11 06:58:04 +03:00
& uevent_seqnum_attr . attr ,
& uevent_helper_attr . attr ,
2006-06-23 13:05:07 +04:00
# endif
2008-10-16 09:01:46 +04:00
# ifdef CONFIG_PROFILING
& profiling_attr . attr ,
# endif
2006-06-23 13:05:07 +04:00
# ifdef CONFIG_KEXEC
& kexec_loaded_attr . attr ,
& kexec_crash_loaded_attr . attr ,
2009-12-16 03:47:46 +03:00
& kexec_crash_size_attr . attr ,
2007-10-17 10:27:27 +04:00
& vmcoreinfo_attr . attr ,
2005-04-17 02:20:36 +04:00
# endif
NULL
} ;
static struct attribute_group kernel_attr_group = {
. attrs = kernel_attrs ,
} ;
static int __init ksysfs_init ( void )
{
2007-10-29 22:13:17 +03:00
int error ;
2005-04-17 02:20:36 +04:00
2007-11-06 21:36:58 +03:00
kernel_kobj = kobject_create_and_add ( " kernel " , NULL ) ;
if ( ! kernel_kobj ) {
2007-10-29 22:13:17 +03:00
error = - ENOMEM ;
goto exit ;
}
2007-11-06 21:36:58 +03:00
error = sysfs_create_group ( kernel_kobj , & kernel_attr_group ) ;
2007-10-29 22:13:17 +03:00
if ( error )
goto kset_exit ;
if ( notes_size > 0 ) {
2007-07-19 12:48:39 +04:00
notes_attr . size = notes_size ;
2007-11-06 21:36:58 +03:00
error = sysfs_create_bin_file ( kernel_kobj , & notes_attr ) ;
2007-10-29 22:13:17 +03:00
if ( error )
goto group_exit ;
2007-07-19 12:48:39 +04:00
}
2007-11-02 15:47:53 +03:00
/* create the /sys/kernel/uids/ directory */
error = uids_sysfs_init ( ) ;
2007-10-29 22:13:17 +03:00
if ( error )
goto notes_exit ;
return 0 ;
notes_exit :
if ( notes_size > 0 )
2007-11-06 21:36:58 +03:00
sysfs_remove_bin_file ( kernel_kobj , & notes_attr ) ;
2007-10-29 22:13:17 +03:00
group_exit :
2007-11-06 21:36:58 +03:00
sysfs_remove_group ( kernel_kobj , & kernel_attr_group ) ;
2007-10-29 22:13:17 +03:00
kset_exit :
2007-12-20 19:13:05 +03:00
kobject_put ( kernel_kobj ) ;
2007-10-29 22:13:17 +03:00
exit :
2005-04-17 02:20:36 +04:00
return error ;
}
core_initcall ( ksysfs_init ) ;