This patch is the first step toward instrumenting xen through sysfs, and
toward migrating the /proc/xen files to /sys/xen.
The major component is a set of kernel functions that hopefully make
adding files to /sys/xen as easy as adding files to /proc/xen. A
smaller file adds xen version information by creating a file under
/sys/xen/version.
I am looking for feedback on the approach and usefulness of the sysfs
support functions. The next step is to add support for sysfs binary
files and to experiment with implementing /proc/xen/privcmd as
/sysfs/xen/privcmd
Mike
--
Mike D. Day
STSM and Architect, Open Virtualization
IBM Linux Technology Center
ncmike@xxxxxxxxxx
# HG changeset patch
# User mdday@xxxxxxxxxxxxxxxxxxxxx
# Node ID cec2fc0a07c611023e096cf3496d948aa39c1342
# Parent c08884b412da24dd4c05d36fdff408f4433bd865
# Parent da7873110bbb8b55d9adb9111d100e209fc49ee6
signed-off-by Mike Day <ncmike@xxxxxxxxxx>
Stage support for xen to export information using sysfs. Make it just as easy
to add a /sys/xen/ file as it is to add a /proc/xen file currently. Starting by
exporting xen version information in /sys/xen/version.
diff -r c08884b412da -r cec2fc0a07c6
linux-2.6-xen-sparse/arch/xen/kernel/xen_sysfs.c
--- /dev/null Mon Jan 9 21:55:13 2006
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/xen_sysfs.c Mon Jan 9 23:07:04 2006
@@ -0,0 +1,698 @@
+/*
+ copyright (c) 2006 IBM Corporation
+ Mike Day <ncmike@xxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+#include <asm-generic/bug.h>
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "xen_sysfs: ", fmt, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#ifndef BOOL
+#define BOOL int
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+#define __sysfs_ref__
+
+struct xen_sysfs_object;
+
+struct xen_sysfs_attr
+{
+ struct bin_attribute attr;
+ ssize_t (*show)(void *, char *) ;
+ ssize_t (*store)(void *, const char *, size_t) ;
+ ssize_t (*read)(void *, char *, loff_t, size_t );
+ ssize_t (*write)(void *, char *, loff_t, size_t) ;
+};
+
+
+
+/* flags bits */
+#define XEN_SYSFS_UNINITIALIZED 0x00
+#define XEN_SYSFS_CHAR_TYPE 0x01
+#define XEN_SYSFS_BIN_TYPE 0x02
+#define XEN_SYSFS_DIR_TYPE 0x04
+#define XEN_SYSFS_LINKED 0x08
+#define XEN_SYSFS_UNLINKED 0x10
+#define XEN_SYSFS_LINK_TYPE 0x11
+
+
+struct xen_sysfs_object
+{
+ struct list_head list;
+ int flags;
+ struct kobject kobj;
+ struct xen_sysfs_attr attr;
+ char * path;
+ struct list_head children;
+ struct xen_sysfs_object * parent;
+ atomic_t refcount;
+ void * user_data;
+ void (*user_data_release)(void *);
+ void (*destroy)(struct xen_sysfs_object *);
+};
+
+
+static __sysfs_ref__ struct xen_sysfs_object *
+find_object(struct xen_sysfs_object * obj, const char * path);
+
+
+static __sysfs_ref__ struct xen_sysfs_object *
+new_sysfs_object(const char * path,
+ int type,
+ int mode,
+ ssize_t (*show)(void *, char *),
+ ssize_t (*store)(void *, const char *, size_t),
+ ssize_t (*read)(void *, char *, loff_t, size_t),
+ ssize_t (*write)(void *, char *, loff_t, size_t),
+ void * user_data,
+ void (* user_data_release)(void *)) ;
+
+static void destroy_sysfs_object(struct xen_sysfs_object * obj);
+static __sysfs_ref__ struct xen_sysfs_object * __find_parent(const char *
path) ;
+static __sysfs_ref__ int __add_child(struct xen_sysfs_object *parent,
+ struct xen_sysfs_object *child);
+static void remove_child(struct xen_sysfs_object *child);
+static void get_object(struct xen_sysfs_object *);
+static int put_object(struct xen_sysfs_object *,
+ void (*)(struct xen_sysfs_object *));
+
+
+/* Is A == B ? */
+#define streq(a,b) (strcmp((a),(b)) == 0)
+
+/* Does A start with B ? */
+#define strstarts(a,b) (strncmp((a),(b),strlen(b)) == 0)
+
+
+#define __sysfs_ref__
+
+#define XEN_SYSFS_ATTR(_name, _mode, _show, _store) \
+ struct xen_sysfs_attr xen_sysfs_attr_##_name = __ATTR(_name, _mode,
_show, _store)
+
+#define __XEN_KOBJ(_parent, _dentry, _ktype) \
+ { \
+ .k_name = NULL, \
+ .parent = _parent, \
+ .dentry = _dentry, \
+ .ktype = _ktype, \
+ }
+
+static struct semaphore xen_sysfs_mut = __MUTEX_INITIALIZER(xen_sysfs_mut);
+static inline int
+sysfs_down(struct semaphore * mut)
+{
+ int err;
+ do {
+ err = down_interruptible(mut);
+ } while ( err && err == -EINTR );
+ return err;
+}
+
+#define sysfs_up(mut) up(mut)
+#define to_xen_attr(_attr) container_of(_attr, struct xen_sysfs_attr,
attr.attr)
+#define to_xen_obj(_xen_attr) container_of(_xen_attr, struct xen_sysfs_object,
attr)
+
+static ssize_t
+xen_sysfs_show(struct kobject * kobj, struct attribute * attr, char * buf)
+{
+ struct xen_sysfs_attr * xen_attr = to_xen_attr(attr);
+ struct xen_sysfs_object * xen_obj = to_xen_obj(xen_attr);
+ if(xen_attr->show)
+ return xen_attr->show(xen_obj->user_data, buf);
+ return 0;
+}
+
+static ssize_t
+xen_sysfs_store(struct kobject * kobj, struct attribute * attr,
+ const char *buf, size_t count)
+{
+ struct xen_sysfs_attr * xen_attr = to_xen_attr(attr);
+ struct xen_sysfs_object * xen_obj = to_xen_obj(xen_attr);
+ if(xen_attr->store)
+ return xen_attr->store(xen_obj->user_data, buf, count) ;
+ return 0;
+}
+
+#define to_xen_obj_bin(_kobj) container_of(_kobj, struct xen_sysfs_object,
kobj)
+
+static ssize_t
+xen_sysfs_read(struct kobject *kobj, char * buf, loff_t offset, size_t size)
+{
+ struct xen_sysfs_object * xen_obj = to_xen_obj_bin(kobj);
+ if(xen_obj->attr.read)
+ return xen_obj->attr.read(xen_obj->user_data, buf, offset,
size);
+ return 0;
+}
+
+
+static ssize_t
+xen_sysfs_write(struct kobject *kobj, char * buf, loff_t offset, size_t size)
+{
+ struct xen_sysfs_object * xen_obj = to_xen_obj_bin(kobj);
+ if (xen_obj->attr.write)
+ return xen_obj->attr.write(xen_obj->user_data, buf, offset,
size);
+ if(size == 0 )
+ return PAGE_SIZE;
+
+ return size;
+}
+
+static struct sysfs_ops xen_sysfs_ops = {
+ .show = xen_sysfs_show,
+ .store = xen_sysfs_store,
+};
+
+static struct kobj_type xen_kobj_type = {
+ .release = NULL,
+ .sysfs_ops = &xen_sysfs_ops,
+ .default_attrs = NULL,
+};
+
+
+/* xen sysfs root entry */
+static struct xen_sysfs_object xen_root = {
+ .flags = 0,
+ .kobj = {
+ .k_name = NULL,
+ .parent = NULL,
+ .dentry = NULL,
+ .ktype = &xen_kobj_type,
+ },
+ .attr = {
+ .attr = {
+ .attr = {
+ .name = NULL,
+ .mode = 0775,
+ },
+
+ },
+ .show = NULL,
+ .store = NULL,
+ .read = NULL,
+ .write = NULL,
+ },
+ .path = __stringify(/sys/xen),
+ .list = LIST_HEAD_INIT(xen_root.list),
+ .children = LIST_HEAD_INIT(xen_root.children),
+ .parent = NULL,
+};
+
+/* xen sysfs path functions */
+
+static BOOL
+valid_chars(const char *path)
+{
+ if( ! strstarts(path, "/sys/xen") )
+ return FALSE;
+ if(strstr(path, "//"))
+ return FALSE;
+ return (strspn(path,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789-/_@~$") == strlen(path));
+}
+
+
+/* return value must be kfree'd */
+static char *
+dup_path(const char *path)
+{
+ char * ret;
+ int len;
+ BUG_ON( ! path );
+
+ if( FALSE == valid_chars(path) ) {
+ return NULL;
+ }
+
+ len = strlen(path) + 1;
+ ret = kcalloc(len - 1, sizeof(char), GFP_KERNEL);
+ memcpy(ret, path, len);
+ return ret;
+}
+
+
+
+static char *
+basename(const char *name)
+{
+ return strrchr(name, '/') + 1;
+}
+
+static char *
+strip_trailing_slash(char * path)
+{
+ int len = strlen(path);
+
+ char * term = path + len - 1;
+ if( *term == '/')
+ *term = 0;
+ return path;
+}
+
+/* return value must be kfree'd */
+static char * dirname(const char * name)
+{
+ char *ret;
+ int len;
+
+ len = strlen(name) - strlen(basename(name)) + 1;
+ ret = kcalloc(len, sizeof(char), GFP_KERNEL);
+ memcpy(ret, name, len - 1);
+ ret = strip_trailing_slash(ret);
+
+ return ret;
+}
+
+
+/* type must be char, bin, or dir */
+static __sysfs_ref__ struct xen_sysfs_object *
+new_sysfs_object(const char * path,
+ int type,
+ int mode,
+ ssize_t (*show)(void *, char *),
+ ssize_t (*store)(void *, const char *, size_t),
+ ssize_t (*read)(void *, char *, loff_t, size_t),
+ ssize_t (*write)(void *, char *, loff_t, size_t),
+ void * user_data,
+ void (* user_data_release)(void *))
+{
+ struct xen_sysfs_object * ret =
+ (struct xen_sysfs_object *)kcalloc(sizeof(struct
xen_sysfs_object),
+ sizeof(char),
+ GFP_KERNEL);
+ BUG_ON(ret == NULL);
+
+ ret->flags = type;
+ BUG_ON( (type & XEN_SYSFS_DIR_TYPE) && (show || store) );
+
+ if( NULL == (ret->path = dup_path(path)) ) {
+ kfree(ret);
+ return NULL;
+ }
+ kobject_set_name(&ret->kobj, basename(path));
+ kobject_init(&ret->kobj);
+ ret->attr.attr.attr.name = kobject_name(&ret->kobj);
+ ret->attr.attr.attr.owner = THIS_MODULE;
+ ret->attr.attr.attr.mode = mode;
+ ret->kobj.ktype = &xen_kobj_type;
+ if( type & XEN_SYSFS_CHAR_TYPE ) {
+ ret->attr.show = show;
+ ret->attr.store = store;
+ }
+ else if ( type & XEN_SYSFS_BIN_TYPE ) {
+ ret->attr.attr.size = PAGE_SIZE;
+ ret->attr.attr.read = xen_sysfs_read;
+ ret->attr.attr.write = xen_sysfs_write;
+ ret->attr.read = read;
+ ret->attr.write = write;
+ }
+ INIT_LIST_HEAD(&ret->list);
+ INIT_LIST_HEAD(&ret->children);
+ atomic_set(&ret->refcount, 1);
+ ret->destroy = destroy_sysfs_object;
+ return ret;
+}
+
+static void
+get_object(struct xen_sysfs_object *obj)
+{
+ BUG_ON( ! atomic_read(&obj->refcount) );
+ kobject_get(&obj->kobj);
+ atomic_inc(&obj->refcount);
+ return;
+}
+
+static int
+put_object(struct xen_sysfs_object *obj,
+ void (*release)(struct xen_sysfs_object *))
+{
+ BUG_ON( ! release );
+ BUG_ON( release == (void (*)(struct xen_sysfs_object *))kfree);
+ kobject_put(&obj->kobj);
+ if(atomic_dec_and_test(&obj->refcount)) {
+ release(obj);
+ return 1;
+ }
+ return 0;
+}
+
+
+// TODO delete object
+static void
+sysfs_release(struct xen_sysfs_object * obj)
+{
+ BUG_ON( ! (obj->flags & XEN_SYSFS_UNLINKED) );
+ BUG_ON( ! list_empty(&obj->children) );
+ BUG_ON( obj->parent ) ;
+
+ kobject_cleanup(&obj->kobj);
+ if(obj->attr.attr.attr.name)
+ kfree(obj->attr.attr.attr.name);
+ if(obj->user_data && obj->user_data_release )
+ obj->user_data_release(obj->user_data);
+ if( obj->path ) {
+ kfree(obj->path);
+ obj->path = NULL;
+ }
+ if (obj->destroy)
+ obj->destroy(obj);
+ return;
+}
+
+static void
+destroy_sysfs_object(struct xen_sysfs_object * obj)
+{
+ if(obj->path)
+ kfree(obj->path);
+ BUG_ON( ! list_empty(&obj->children) ) ;
+ BUG_ON ( obj->parent );
+ kfree(obj);
+ return;
+}
+
+
+/* refcounts object when returned */
+static __sysfs_ref__ struct xen_sysfs_object *
+find_object(struct xen_sysfs_object * obj, const char * path)
+{
+ struct list_head * tmp = NULL;
+ struct xen_sysfs_object *this_obj = NULL, * tmp_obj = NULL;
+
+ if(obj->flags & XEN_SYSFS_UNLINKED) {
+ return NULL;
+ }
+ if(! strcmp(obj->path, path) ) {
+ get_object(obj);
+ return obj;
+ }
+ // if path is longer than obj-path, search children
+ if ( strstarts(path, obj->path) &&
+ strlen(path) > strlen(obj->path) &&
+ ! list_empty(&obj->children) ) {
+ list_for_each(tmp, (&obj->children)) {
+ tmp_obj = list_entry(tmp, struct xen_sysfs_object,
list);
+ if( NULL != (this_obj = find_object(tmp_obj, path)) ) {
+ return this_obj;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* parent is ref counted when returned */
+static __sysfs_ref__ struct xen_sysfs_object *
+__find_parent(const char * path)
+{
+ char * dir;
+ struct xen_sysfs_object * parent;
+
+ BUG_ON( ! path );
+ if ( ! valid_chars(path))
+ return NULL;
+ dir = dirname(path);
+ BUG_ON ( sysfs_down(&xen_sysfs_mut) );
+ parent = find_object(&xen_root, dir);
+
+ sysfs_up(&xen_sysfs_mut);
+ kfree(dir);
+
+ return parent;
+}
+
+static __sysfs_ref__ int
+__add_child(struct xen_sysfs_object *parent,
+ struct xen_sysfs_object *child)
+{
+ int err = EINVAL;
+
+ BUG_ON ( sysfs_down(&xen_sysfs_mut) );
+ list_add_tail(&child->list, &parent->children);
+ child->kobj.parent = &parent->kobj;
+ child->kobj.dentry = parent->kobj.dentry;
+ if(child->flags & XEN_SYSFS_DIR_TYPE)
+ err = sysfs_create_dir(&child->kobj);
+ else if (child->flags & XEN_SYSFS_CHAR_TYPE)
+ err = sysfs_create_file(&child->kobj, &child->attr.attr.attr);
+ else if (child->flags & XEN_SYSFS_BIN_TYPE)
+ err = sysfs_create_bin_file(&child->kobj, &child->attr.attr);
+ child->flags |= XEN_SYSFS_LINKED;
+ child->flags &= ~XEN_SYSFS_UNLINKED;
+ child->parent = parent;
+ sysfs_up(&xen_sysfs_mut);
+ get_object(parent);
+ return err;
+}
+
+static void remove_child(struct xen_sysfs_object *child)
+{
+ struct list_head *children;
+ struct xen_sysfs_object *tmp_obj;
+
+ children = (&child->children)->next;
+ while( children != &child->children ) {
+ tmp_obj = list_entry(children, struct xen_sysfs_object, list );
+ remove_child(tmp_obj);
+ children = (&child->children)->next;
+ }
+ child->flags |= XEN_SYSFS_UNLINKED;
+ child->flags &= ~XEN_SYSFS_LINKED;
+ if(child->flags & XEN_SYSFS_DIR_TYPE)
+ sysfs_remove_dir(&child->kobj);
+ else if (child->flags & XEN_SYSFS_CHAR_TYPE)
+ sysfs_remove_file(&child->kobj, &child->attr.attr.attr);
+ else if (child->flags & XEN_SYSFS_BIN_TYPE)
+ sysfs_remove_bin_file(&child->kobj, &child->attr.attr);
+ list_del(&child->list);
+ put_object(child->parent, sysfs_release);
+ child->parent = NULL;
+ put_object(child, sysfs_release);
+ return;
+}
+
+
+
+
+int
+xen_sysfs_create_dir(const char * path, int mode)
+{
+ struct xen_sysfs_object * child, * parent;
+ int err;
+
+ if(path == NULL)
+ return -EINVAL;
+ if ( NULL == (parent = __find_parent(path)) )
+ return -EBADF;
+ if( NULL == (child = new_sysfs_object(path, XEN_SYSFS_DIR_TYPE,
+ mode, NULL,NULL, NULL,
+ NULL, NULL,NULL))) {
+ put_object(parent, sysfs_release);
+ return -ENOMEM;
+ }
+ err = __add_child(parent, child);
+ put_object(parent, sysfs_release);
+
+ return -err;
+}
+
+int
+xen_sysfs_remove_dir(const char* path, BOOL recursive)
+{
+ __label__ mut;
+ __label__ ref;
+ int err = 0;
+ struct xen_sysfs_object * dir;
+
+ if(path == NULL)
+ return -EINVAL;
+ BUG_ON(sysfs_down(&xen_sysfs_mut));
+ if(NULL == (dir = find_object(&xen_root, path))) {
+ err = -EBADF;
+ goto mut;
+ }
+ if(FALSE == recursive && ! list_empty(&dir->children) ) {
+ err = -EBUSY;
+ goto ref;
+ }
+ remove_child(dir);
+ref:
+ put_object(dir, sysfs_release);
+mut:
+ sysfs_up(&xen_sysfs_mut);
+ return err;
+}
+
+
+
+int
+xen_sysfs_create_file(const char * path,
+ int mode,
+ ssize_t (*show)(void *, char *),
+ ssize_t (*store)(void *, const char *, size_t),
+ void * private_data,
+ void (*private_data_release)(void *))
+{
+
+ struct xen_sysfs_object *parent, * file;
+ int err;
+
+ if(path == NULL || FALSE == valid_chars(path))
+ return -EINVAL;
+ if(NULL == ( parent = __find_parent(path)) )
+ return -EBADF;
+
+ if( NULL == ( file = new_sysfs_object(path,
+ XEN_SYSFS_CHAR_TYPE,
+ mode,
+ show,
+ store,
+ NULL,
+ NULL,
+ private_data,
+ private_data_release)))
+ return -ENOMEM;
+
+ err = __add_child(parent, file);
+ put_object(parent, sysfs_release);
+ return err;
+}
+
+
+int
+xen_sysfs_update_file(const char * path)
+{
+ __label__ mut;
+ int err;
+ struct xen_sysfs_object * obj;
+
+ if(path == NULL || FALSE == valid_chars(path))
+ return -EINVAL;
+ sysfs_down(&xen_sysfs_mut);
+
+ if(NULL == (obj = find_object(&xen_root, path))) {
+ err = -EBADF;
+ goto mut;
+ }
+
+ err = sysfs_update_file(&obj->kobj, &obj->attr.attr.attr);
+ put_object(obj, sysfs_release);
+mut:
+ sysfs_up(&xen_sysfs_mut);
+ return err;
+}
+
+
+int
+xen_sysfs_remove_file(const char* path)
+{
+ __label__ mut;
+ int err = 0;
+ struct xen_sysfs_object * file;
+
+ if(path == NULL)
+ return -EINVAL;
+ BUG_ON(sysfs_down(&xen_sysfs_mut));
+ if(NULL == (file = find_object(&xen_root, path))) {
+ err = -EBADF;
+ goto mut;
+ }
+ remove_child(file);
+ put_object(file, sysfs_release);
+mut:
+ sysfs_up(&xen_sysfs_mut);
+ return err;
+}
+
+int
+xen_sysfs_create_bin_file(const char * path,
+ int mode,
+ ssize_t (*read) (void *, char *, loff_t, size_t),
+ ssize_t (*write) (void *, char *, loff_t, size_t),
+ void * private_data,
+ void (*private_data_release)(void *))
+{
+
+ struct xen_sysfs_object *parent, * file;
+ int err;
+
+ if(path == NULL || FALSE == valid_chars(path))
+ return -EINVAL;
+ if(NULL == ( parent = __find_parent(path)) )
+ return -EBADF;
+
+ if( NULL == ( file = new_sysfs_object(path,
+ XEN_SYSFS_BIN_TYPE,
+ mode,
+ NULL,
+ NULL,
+ read,
+ write,
+ private_data,
+ private_data_release)))
+ return -ENOMEM;
+
+ err = __add_child(parent, file);
+ put_object(parent, sysfs_release);
+ return err;
+}
+
+int __init
+xen_sysfs_init(void)
+{
+ kobject_init(&xen_root.kobj);
+ kobject_set_name(&xen_root.kobj, "xen");
+ atomic_set(&xen_root.refcount, 1);
+ return sysfs_create_dir(&xen_root.kobj);
+}
+
+arch_initcall(xen_sysfs_init);
+
+EXPORT_SYMBOL(xen_sysfs_create_dir);
+EXPORT_SYMBOL(xen_sysfs_remove_dir);
+EXPORT_SYMBOL(xen_sysfs_create_file);
+EXPORT_SYMBOL(xen_sysfs_update_file);
+EXPORT_SYMBOL(xen_sysfs_remove_file);
+
+
diff -r c08884b412da -r cec2fc0a07c6
linux-2.6-xen-sparse/arch/xen/kernel/xen_sysfs_version.c
--- /dev/null Mon Jan 9 21:55:13 2006
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/xen_sysfs_version.c Mon Jan 9
23:07:04 2006
@@ -0,0 +1,60 @@
+/*
+ copyright (c) 2006 IBM Corporation
+ Mike Day <ncmike@xxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <asm/page.h>
+#include <asm-xen/xen-public/version.h>
+#include <asm-xen/xen-public/dom0_ops.h>
+#include <asm-xen/asm/hypercall.h>
+#include <asm-xen/xen_sysfs.h>
+
+extern int HYPERVISOR_xen_version(int, void*);
+
+
+static ssize_t xen_version_show(void *data, char *page)
+{
+ long version;
+ long major, minor;
+ static xen_extraversion_t extra_version;
+
+ version = HYPERVISOR_xen_version(XENVER_version, NULL);
+ major = version >> 16;
+ minor = version & 0xff;
+
+ HYPERVISOR_xen_version(XENVER_extraversion, extra_version);
+ return snprintf(page, PAGE_SIZE, "xen-%ld.%ld%s\n", major, minor,
extra_version);
+}
+
+
+
+int __init
+sysfs_xen_version_init(void)
+{
+ return xen_sysfs_create_file("/sys/xen/version",
+ 0444,
+ xen_version_show,
+ NULL,
+ NULL,
+ NULL);
+}
+
+device_initcall(sysfs_xen_version_init);
diff -r c08884b412da -r cec2fc0a07c6
linux-2.6-xen-sparse/include/asm-xen/xen_sysfs.h
--- /dev/null Mon Jan 9 21:55:13 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/xen_sysfs.h Mon Jan 9 23:07:04 2006
@@ -0,0 +1,88 @@
+/*
+ copyright (c) 2006 IBM Corporation
+ Mike Day <ncmike@xxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#include <asm/page.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+
+
+#ifndef _XEN_SYSFS_H_
+#define _XEN_SYSFS_H_
+
+#ifdef __KERNEL__
+
+#ifndef BOOL
+#define BOOL int
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+extern int
+xen_sysfs_create_dir(const char * path, int mode);
+
+extern int
+xen_sysfs_remove_dir(const char * path, BOOL recursive);
+
+extern int
+xen_sysfs_create_file(const char * path,
+ int mode,
+ ssize_t (*show)(void * user_data, char * buf),
+ ssize_t (*store)(void * user_data,
+ const char * buf,
+ size_t length),
+ void * private_data,
+ void (*private_data_release)(void *));
+
+extern int
+xen_sysfs_update_file(const char * path);
+
+extern int
+xen_sysfs_remove_file(const char * path);
+
+
+int xen_sysfs_create_bin_file(const char * path,
+ int mode,
+ ssize_t (*read)(void * user_data,
+ char * buf,
+ loff_t offset,
+ size_t length),
+ ssize_t (*write)(void * user_data,
+ char *buf,
+ loff_t offset,
+ size_t length),
+ void * private_data,
+ void (*private_data_release)(void *));
+int xen_sysfs_remove_bin_file(const char * path);
+
+#endif /* __KERNEL__ */
+#endif /* _XEN_SYSFS_H_ */
# HG changeset patch
# User mdday@xxxxxxxxxxxxxxxxxxxxx
# Node ID bd2c30fbc96d3b5e264740720cbcced959ef8c46
# Parent cec2fc0a07c611023e096cf3496d948aa39c1342
build xen sysfs support
diff -r cec2fc0a07c6 -r bd2c30fbc96d
linux-2.6-xen-sparse/arch/xen/kernel/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/kernel/Makefile Mon Jan 9 23:07:04 2006
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/Makefile Mon Jan 9 23:21:19 2006
XENARCH := $(subst ",,$(CONFIG_XENARCH))
@@ -16,3 +16,4 @@
obj-$(CONFIG_PROC_FS) += xen_proc.o
obj-$(CONFIG_NET) += skbuff.o
obj-$(CONFIG_SMP) += smpboot.o
+obj-$(CONFIG_SYSFS) += xen_sysfs.o xen_sysfs_version.o
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|