WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] [RFC] sysfs support for xen linux

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] [RFC] sysfs support for xen linux
From: "Mike D. Day" <ncmike@xxxxxxxxxx>
Date: Mon, 09 Jan 2006 18:35:00 -0500
Delivery-date: Mon, 09 Jan 2006 23:40:57 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla Thunderbird 1.0.7 (Macintosh/20050923)

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