[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] [RFC] sysfs support for xen linux
Mike D. Day wrote: > > 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 > > > ------------------------------------------------------------------------ > > # 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 In addition to /sys/xen/version, it would also be very helpful to init scripts if there was another file that said whether it is running in dom0 or a domU. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |