* [PATCH] [RFC] sysfs support for xen linux
@ 2006-01-09 23:35 Mike D. Day
2006-01-10 1:09 ` Christopher G. Stach II
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Mike D. Day @ 2006-01-09 23:35 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 683 bytes --]
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@us.ibm.com
[-- Attachment #2: xen_sysfs.diff --]
[-- Type: text/plain, Size: 23096 bytes --]
# HG changeset patch
# User mdday@mdday.raleigh.ibm.com
# Node ID cec2fc0a07c611023e096cf3496d948aa39c1342
# Parent c08884b412da24dd4c05d36fdff408f4433bd865
# Parent da7873110bbb8b55d9adb9111d100e209fc49ee6
signed-off-by Mike Day <ncmike@us.ibm.com>
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@us.ibm.com>
+
+ 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@us.ibm.com>
+
+ 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@us.ibm.com>
+
+ 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@mdday.raleigh.ibm.com
# 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
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-09 23:35 [PATCH] [RFC] sysfs support for xen linux Mike D. Day
@ 2006-01-10 1:09 ` Christopher G. Stach II
2006-01-10 10:13 ` Keir Fraser
` (2 subsequent siblings)
3 siblings, 0 replies; 15+ messages in thread
From: Christopher G. Stach II @ 2006-01-10 1:09 UTC (permalink / raw)
To: Mike D. Day; +Cc: xen-devel
Mike D. Day wrote:
>
> This patch is the first step toward instrumenting xen through sysfs, and
> toward migrating the /proc/xen files to /sys/xen.
>
> The major component is a set of kernel functions that hopefully make
> adding files to /sys/xen as easy as adding files to /proc/xen. A
> smaller file adds xen version information by creating a file under
> /sys/xen/version.
>
> I am looking for feedback on the approach and usefulness of the sysfs
> support functions. The next step is to add support for sysfs binary
> files and to experiment with implementing /proc/xen/privcmd as
> /sysfs/xen/privcmd
>
> Mike
>
>
> ------------------------------------------------------------------------
>
> # HG changeset patch
> # User mdday@mdday.raleigh.ibm.com
> # Node ID cec2fc0a07c611023e096cf3496d948aa39c1342
> # Parent c08884b412da24dd4c05d36fdff408f4433bd865
> # Parent da7873110bbb8b55d9adb9111d100e209fc49ee6
> signed-off-by Mike Day <ncmike@us.ibm.com>
>
> 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@us.ibm.com>
> +
> + 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@us.ibm.com>
> +
> + 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@us.ibm.com>
> +
> + 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@mdday.raleigh.ibm.com
> # 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@lists.xensource.com
> 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.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-09 23:35 [PATCH] [RFC] sysfs support for xen linux Mike D. Day
2006-01-10 1:09 ` Christopher G. Stach II
@ 2006-01-10 10:13 ` Keir Fraser
2006-01-10 13:23 ` Gawain Lynch
2006-01-12 1:44 ` Chris Wright
3 siblings, 0 replies; 15+ messages in thread
From: Keir Fraser @ 2006-01-10 10:13 UTC (permalink / raw)
To: Mike D. Day; +Cc: xen-devel
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-09 23:35 [PATCH] [RFC] sysfs support for xen linux Mike D. Day
2006-01-10 1:09 ` Christopher G. Stach II
2006-01-10 10:13 ` Keir Fraser
@ 2006-01-10 13:23 ` Gawain Lynch
2006-01-12 1:44 ` Chris Wright
3 siblings, 0 replies; 15+ messages in thread
From: Gawain Lynch @ 2006-01-10 13:23 UTC (permalink / raw)
To: xen-devel, 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...
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-09 23:35 [PATCH] [RFC] sysfs support for xen linux Mike D. Day
` (2 preceding siblings ...)
2006-01-10 13:23 ` Gawain Lynch
@ 2006-01-12 1:44 ` Chris Wright
3 siblings, 0 replies; 15+ messages in thread
From: Chris Wright @ 2006-01-12 1:44 UTC (permalink / raw)
To: Mike D. Day; +Cc: xen-devel
* Mike D. Day (ncmike@us.ibm.com) 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 mdday@mdday.raleigh.ibm.com
> # Node ID cec2fc0a07c611023e096cf3496d948aa39c1342
> # Parent c08884b412da24dd4c05d36fdff408f4433bd865
> # Parent da7873110bbb8b55d9adb9111d100e209fc49ee6
> signed-off-by Mike Day <ncmike@us.ibm.com>
>
> 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@us.ibm.com>
> +
> + 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/)
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
@ 2006-01-10 12:58 Mike D. Day
2006-01-11 10:21 ` Keir Fraser
0 siblings, 1 reply; 15+ messages in thread
From: Mike D. Day @ 2006-01-10 12:58 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
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
ncmike@us.ibm.com
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-10 12:58 Mike D. Day
@ 2006-01-11 10:21 ` Keir Fraser
0 siblings, 0 replies; 15+ messages in thread
From: Keir Fraser @ 2006-01-11 10:21 UTC (permalink / raw)
To: Mike D. Day; +Cc: xen-devel
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
@ 2006-01-11 16:12 Mike D. Day
2006-01-11 16:05 ` Mark Williamson
0 siblings, 1 reply; 15+ messages in thread
From: Mike D. Day @ 2006-01-11 16:12 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
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
ncmike@us.ibm.com
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-11 16:12 Mike D. Day
@ 2006-01-11 16:05 ` Mark Williamson
2006-01-11 16:35 ` Keir Fraser
0 siblings, 1 reply; 15+ messages in thread
From: Mark Williamson @ 2006-01-11 16:05 UTC (permalink / raw)
To: xen-devel; +Cc: Mike D. Day
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!
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-11 16:05 ` Mark Williamson
@ 2006-01-11 16:35 ` Keir Fraser
2006-01-11 16:40 ` Ronald G Minnich
0 siblings, 1 reply; 15+ messages in thread
From: Keir Fraser @ 2006-01-11 16:35 UTC (permalink / raw)
To: Mark Williamson; +Cc: Mike D. Day, xen-devel
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-11 16:35 ` Keir Fraser
@ 2006-01-11 16:40 ` Ronald G Minnich
0 siblings, 0 replies; 15+ messages in thread
From: Ronald G Minnich @ 2006-01-11 16:40 UTC (permalink / raw)
To: Keir Fraser; +Cc: Mike D. Day, xen-devel, Mark Williamson
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
@ 2006-01-11 16:28 Mike D. Day
2006-01-11 16:28 ` Mark Williamson
0 siblings, 1 reply; 15+ messages in thread
From: Mike D. Day @ 2006-01-11 16:28 UTC (permalink / raw)
To: Mark Williamson; +Cc: xen-devel
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
ncmike@us.ibm.com
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-11 16:28 Mike D. Day
@ 2006-01-11 16:28 ` Mark Williamson
2006-01-11 16:50 ` Anthony Liguori
0 siblings, 1 reply; 15+ messages in thread
From: Mark Williamson @ 2006-01-11 16:28 UTC (permalink / raw)
To: Mike D. Day; +Cc: xen-devel
> 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!
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-11 16:28 ` Mark Williamson
@ 2006-01-11 16:50 ` Anthony Liguori
2006-01-11 17:03 ` Daniel Stekloff
0 siblings, 1 reply; 15+ messages in thread
From: Anthony Liguori @ 2006-01-11 16:50 UTC (permalink / raw)
To: Mark Williamson; +Cc: Mike D. Day, xen-devel
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
>
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [RFC] sysfs support for xen linux
2006-01-11 16:50 ` Anthony Liguori
@ 2006-01-11 17:03 ` Daniel Stekloff
0 siblings, 0 replies; 15+ messages in thread
From: Daniel Stekloff @ 2006-01-11 17:03 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Mike D. Day, xen-devel, Mark Williamson
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
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2006-01-12 1:44 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-01-09 23:35 [PATCH] [RFC] sysfs support for xen linux Mike D. Day
2006-01-10 1:09 ` Christopher G. Stach II
2006-01-10 10:13 ` Keir Fraser
2006-01-10 13:23 ` Gawain Lynch
2006-01-12 1:44 ` Chris Wright
-- strict thread matches above, loose matches on Subject: below --
2006-01-10 12:58 Mike D. Day
2006-01-11 10:21 ` Keir Fraser
2006-01-11 16:12 Mike D. Day
2006-01-11 16:05 ` Mark Williamson
2006-01-11 16:35 ` Keir Fraser
2006-01-11 16:40 ` Ronald G Minnich
2006-01-11 16:28 Mike D. Day
2006-01-11 16:28 ` Mark Williamson
2006-01-11 16:50 ` Anthony Liguori
2006-01-11 17:03 ` Daniel Stekloff
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.