[PATCH] [RFC] sysfs support for xen linux

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] [RFC] sysfs support for xen linux

Mike D. Day

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
[hidden email]

# HG changeset patch
# User [hidden email]
# Node ID cec2fc0a07c611023e096cf3496d948aa39c1342
# Parent  c08884b412da24dd4c05d36fdff408f4433bd865
# Parent  da7873110bbb8b55d9adb9111d100e209fc49ee6
signed-off-by Mike Day <[hidden email]>

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 <[hidden email]>
+
+    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 <[hidden email]>
+
+    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 <[hidden email]>
+
+    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 [hidden email]
# 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
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Christopher G. Stach II
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 [hidden email]
> # Node ID cec2fc0a07c611023e096cf3496d948aa39c1342
> # Parent  c08884b412da24dd4c05d36fdff408f4433bd865
> # Parent  da7873110bbb8b55d9adb9111d100e209fc49ee6
> signed-off-by Mike Day <[hidden email]>
>
> 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 <[hidden email]>
> +
> +    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 <[hidden email]>
> +
> +    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 <[hidden email]>
> +
> +    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 [hidden email]
> # 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
> [hidden email]
> 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
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Keir Fraser
In reply to this post by Mike D. Day

On 9 Jan 2006, at 23:35, 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

xen_sysfs.c looks to contain a lot of code that I would expect to be
part of a generic sysfs library. Does every subsystem that uses sysfs
really have to implement all that stuff for itself?

(I am not a sysfs expert, by the way :-).

  -- Keir


_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Mike D. Day
In reply to this post by Mike D. Day
On 5:13 AM Keir Fraser wrote:
> xen_sysfs.c looks to contain a lot of code that I would expect to be
> part of a generic sysfs library. Does every subsystem that uses sysfs
> really have to implement all that stuff for itself?

No, they don't. Drivers get sysfs attributes by using the driver core
(registering a subsystem, defining attributes, etc.).

However, if all you want to do is create and remove files under /sys
(without using all the driver core), there is no simple way to do so (at
least not that I could find). I am assuming that folks will want
something that works like /proc does now.

I wrote xen_sysfs.c to provide simple sysfs interfaces for non-drivers.
It seems as though it would be a crime against nature to write a device
driver just to create a file under /sys.

> (I am not a sysfs expert, by the way :-) .
Neither am I, but perhaps some such person will give feedback. :-)

Mike

--

Mike D. Day
STSM and Architect, Open Virtualization
IBM Linux Technology Center
[hidden email]

_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Gawain Lynch
In reply to this post by Mike D. Day
> 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

<SNIP>

> +#ifndef BOOL
> +#define BOOL    int
> +#endif
> +
> +#ifndef FALSE
> +#define FALSE   0
> +#endif
> +
> +#ifndef TRUE
> +#define TRUE    1
> +#endif
> +
> +#ifndef NULL
> +#define NULL    0
> +#endif

These are already defined in kernel and a favourite nit pick on LKML.


> +struct xen_sysfs_attr
> +{
struct xen_sysfs_attr {

New line for braces are reserved for functions()

> +struct xen_sysfs_object
> +{
struct xen_sysfs_object {

> --- /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

<SNIP>

> +#ifndef BOOL
> +#define BOOL    int
> +#endif
> +
> +#ifndef FALSE
> +#define FALSE   0
> +#endif
> +
> +#ifndef TRUE
> +#define TRUE    1
> +#endif
> +
> +#ifndef NULL
> +#define NULL    0
> +#endif
>

See above...




_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Keir Fraser
In reply to this post by Mike D. Day

On 10 Jan 2006, at 12:58, Mike D. Day wrote:

> No, they don't. Drivers get sysfs attributes by using the driver core
> (registering a subsystem, defining attributes, etc.).
>
> However, if all you want to do is create and remove files under /sys
> (without using all the driver core), there is no simple way to do so
> (at least not that I could find). I am assuming that folks will want
> something that works like /proc does now.
>
> I wrote xen_sysfs.c to provide simple sysfs interfaces for
> non-drivers. It seems as though it would be a crime against nature to
> write a device driver just to create a file under /sys.

Well, here's a question, and I really don't know the answer: It of
course makes sense that the kernel maintainers want drivers to install
themselves under /sys, and fit in with the whole kobject and hotplug
infrastructure. But, for a few odds-and-ends special files that don't
really relate to a device, is /proc also out of bounds these days?
Seems to me that the kernel proc interfaces were designed to have a few
random files thrown at them, in a way that the sysfs interfaces aren't.
If the argument is really that random special files are a bad idea,
that would continue to hold regardless of whether we move e.g.,
/proc/xen/privcmd to /sys.

  -- Keir


_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Mike D. Day
In reply to this post by Mike D. Day
On 5:21 AM Keir Fraser wrote:

> Well, here's a question, and I really don't know the answer: It of
> course makes sense that the kernel maintainers want drivers to
> install themselves under /sys, and fit in with the whole kobject and
> hotplug infrastructure. But, for a few odds-and-ends special files
> that don't really relate to a device, is /proc also out of bounds
> these days? Seems to me that the kernel proc interfaces were designed
> to have a few random files thrown at them, in a way that the sysfs
> interfaces aren't. If the argument is really that random special
> files are a bad idea, that would continue to hold regardless of
> whether we move e.g., /proc/xen/privcmd to /sys.

I think that /sys is clearly the right place to put information about
Xen, including version, domains and domain info, and perhaps info about
xenstore. This is according to feedback received when I submitted my
first (braindead) patch moving /proc/xen to /proc/sys/xen.

Still I agree that we need input from lkml and am going to cross-post an
  RFC so we can move forward.

regards,

Mike


--

Mike D. Day
STSM and Architect, Open Virtualization
IBM Linux Technology Center
[hidden email]

_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Mark Williamson
My impression is was that sysfs files are mostly meant to be very simple
get/set attributes and not have magic properties like the privcmd file - do
any other sysfs files even support ioctls().

Also, for things like privcmd() which are used to perform operations, isn't it
cleanest to make them a character device than a proc file?

$0.02,
Mark

On Wednesday 11 January 2006 16:12, Mike D. Day wrote:

> On 5:21 AM Keir Fraser wrote:
> > Well, here's a question, and I really don't know the answer: It of
> > course makes sense that the kernel maintainers want drivers to
> > install themselves under /sys, and fit in with the whole kobject and
> > hotplug infrastructure. But, for a few odds-and-ends special files
> > that don't really relate to a device, is /proc also out of bounds
> > these days? Seems to me that the kernel proc interfaces were designed
> > to have a few random files thrown at them, in a way that the sysfs
> > interfaces aren't. If the argument is really that random special
> > files are a bad idea, that would continue to hold regardless of
> > whether we move e.g., /proc/xen/privcmd to /sys.
>
> I think that /sys is clearly the right place to put information about
> Xen, including version, domains and domain info, and perhaps info about
> xenstore. This is according to feedback received when I submitted my
> first (braindead) patch moving /proc/xen to /proc/sys/xen.
>
> Still I agree that we need input from lkml and am going to cross-post an
>   RFC so we can move forward.
>
> regards,
>
> Mike

--
> Just a question. What use is a unicyle with no seat?  And no pedals!
Me: To answer a question with a question: What use is a skateboard?
> Skateboards have wheels.
Me: My wheel has a wheel!

_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Mike D. Day
In reply to this post by Mike D. Day
On 11:05 AM Mark Williamson wrote:
> My impression is was that sysfs files are mostly meant to be very
> simple
> get/set attributes and not have magic properties like the privcmd
> file - do
> any other sysfs files even support ioctls().


Yes, true. I think privcmd might be more appropriate for /proc, but
would like to see how it works as a binary file under /sys. ioctl's are
not supported by sysfs that I can see, so privcmd would have to be a
read/write interface.

Regardless of privcmd there are numerous simple attributes related to
Xen that are consistent with "zen" of sysfs. :-)

Mike



--

Mike D. Day
STSM and Architect, Open Virtualization
IBM Linux Technology Center
[hidden email]

_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Mark Williamson
> Yes, true. I think privcmd might be more appropriate for /proc, but
> would like to see how it works as a binary file under /sys. ioctl's are
> not supported by sysfs that I can see, so privcmd would have to be a
> read/write interface.
>
> Regardless of privcmd there are numerous simple attributes related to
> Xen that are consistent with "zen" of sysfs. :-)

Agreed.  It's an ideal place for many of the things that are in proc, and many
things we'd want to add in the future.

You could possibly abuse sysfs into supporting ioctl but I'm pretty sure the
kernel people would find that quite distressing ;-)  I had the impression
binary files under sysfs were also a no-no (all meant to be cat-able -
addressing one of the other problems of /proc), but I could be mistaken.

Cheers,
Mark

--
> Just a question. What use is a unicyle with no seat?  And no pedals!
Me: To answer a question with a question: What use is a skateboard?
> Skateboards have wheels.
Me: My wheel has a wheel!

_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Keir Fraser
In reply to this post by Mark Williamson

On 11 Jan 2006, at 16:05, Mark Williamson wrote:

> My impression is was that sysfs files are mostly meant to be very
> simple
> get/set attributes and not have magic properties like the privcmd file
> - do
> any other sysfs files even support ioctls().
>
> Also, for things like privcmd() which are used to perform operations,
> isn't it
> cleanest to make them a character device than a proc file?

Probably true, but then it's a pain either needing to create device
files in /dev, or interface with the devfs/udev du jour. I suppose we
already have that issue with /dev/xen/evtchn though, and creating the
device node can be hidden in libxc.

  -- Keir


_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Ronald G Minnich
Keir Fraser wrote:

>
> Probably true, but then it's a pain either needing to create device
> files in /dev, or interface with the devfs/udev du jour. I suppose we
> already have that issue with /dev/xen/evtchn though, and creating the
> device node can be hidden in libxc.

we've observed that as well, one performance toolkit uses a /proc file
to avoid the mess of "devfs/udev du jour" (what a great description ...).

So maybe it oughtta be a device, who knows, but the sys file will save a
lot of trouble.

ron

_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Anthony Liguori
In reply to this post by Mark Williamson
Mark Williamson wrote:

>>Yes, true. I think privcmd might be more appropriate for /proc, but
>>would like to see how it works as a binary file under /sys. ioctl's are
>>not supported by sysfs that I can see, so privcmd would have to be a
>>read/write interface.
>>
>>Regardless of privcmd there are numerous simple attributes related to
>>Xen that are consistent with "zen" of sysfs. :-)
>>    
>>
>
>Agreed.  It's an ideal place for many of the things that are in proc, and many
>things we'd want to add in the future.
>
>You could possibly abuse sysfs into supporting ioctl but I'm pretty sure the
>kernel people would find that quite distressing ;-)  I had the impression
>binary files under sysfs were also a no-no (all meant to be cat-able -
>addressing one of the other problems of /proc), but I could be mistaken.
>  
>
There was a discussion a while back about this.

http://permalink.gmane.org/gmane.comp.emulators.xen.devel/14273

I think the consensus was to move any ioctl interface to a char device
and everything else to sysfs.

You'll probably want a proper kobject hierarchy too which means working
with GKH et al to figure out where out stuff should be
(/sys/hypervisor/xen??)

Regards,

Anthony Liguori

>Cheers,
>Mark
>
>  
>


_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Daniel Stekloff
On Wed, 2006-01-11 at 10:50 -0600, Anthony Liguori wrote:

> Mark Williamson wrote:
>
> >>Yes, true. I think privcmd might be more appropriate for /proc, but
> >>would like to see how it works as a binary file under /sys. ioctl's are
> >>not supported by sysfs that I can see, so privcmd would have to be a
> >>read/write interface.
> >>
> >>Regardless of privcmd there are numerous simple attributes related to
> >>Xen that are consistent with "zen" of sysfs. :-)
> >>    
> >>
> >
> >Agreed.  It's an ideal place for many of the things that are in proc, and many
> >things we'd want to add in the future.
> >
> >You could possibly abuse sysfs into supporting ioctl but I'm pretty sure the
> >kernel people would find that quite distressing ;-)  I had the impression
> >binary files under sysfs were also a no-no (all meant to be cat-able -
> >addressing one of the other problems of /proc), but I could be mistaken.
> >  
> >
> There was a discussion a while back about this.
>
> http://permalink.gmane.org/gmane.comp.emulators.xen.devel/14273
>
> I think the consensus was to move any ioctl interface to a char device
> and everything else to sysfs.
>
> You'll probably want a proper kobject hierarchy too which means working
> with GKH et al to figure out where out stuff should be
> (/sys/hypervisor/xen??)



I think it would be a good idea if you included lkml in on your
discussions. Why not get their opinions early rather than late?

Thanks,
Dan


_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] [RFC] sysfs support for xen linux

Chris Wright-3
In reply to this post by Mike D. Day
* Mike D. Day ([hidden email]) 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

You're re-inventing the wheel here.  The infrastructure is there so
that you don't have to create your own.  I think you need to back up and
consider the requirements again.  E.g. exporting version should be _tiny_.

> # HG changeset patch
> # User [hidden email]
> # Node ID cec2fc0a07c611023e096cf3496d948aa39c1342
> # Parent  c08884b412da24dd4c05d36fdff408f4433bd865
> # Parent  da7873110bbb8b55d9adb9111d100e209fc49ee6
> signed-off-by Mike Day <[hidden email]>
>
> 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 <[hidden email]>
> +
> +    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

pr_debug

> +#ifndef BOOL
> +#define BOOL    int
> +#endif
> +
> +#ifndef FALSE
> +#define FALSE   0
> +#endif
> +
> +#ifndef TRUE
> +#define TRUE    1
> +#endif

> +#ifndef NULL
> +#define NULL    0
> +#endif

unecessary, drop all this

> +#define __sysfs_ref__

what's this for?

> +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;

This looks like you're creating your own tree structure.  kobjects
already handle this.

> + 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)

these are typically done open coded...

> +#define __sysfs_ref__

debugging?

> +#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;
> +}

What's the point of using down_interruptible if you can't really interrupt the
call flow?

> +#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") )

OK, that's a serious problem.  You should not have pathnames here at
all.

> + return FALSE;
> + if(strstr(path, "//"))
> + return FALSE;
> + return (strspn(path,
> +       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
> +       "abcdefghijklmnopqrstuvwxyz"
> +       "0123456789-/_@~$") == strlen(path));

eek

> +}
> +
> +
> +/* 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);

(despite the fact that this shouldn't be necessary...s/kcalloc/kzalloc/)

_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel