lkml.org 
[lkml]   [2005]   [Mar]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectRe: [PATCH 0/5] I8K driver facelift
Date
On Wednesday 16 March 2005 16:38, Frank Sorenson wrote:
> Okay, I replaced the sysfs_ops with ops of my own, and now all the show
> and store functions also accept the name of the attribute as a parameter.
> This lets the functions know what attribute is being accessed, and allows
> us to create attributes that share show and store functions, so things
> don't need to be defined at compile time (I feel slightly evil!).

Hrm, can we be a little more explicit and not poke in the sysfs guts right
in the driver? What do you think about the patch below athat implements
"attribute arrays"? And I am attaching cumulative i8k patch using these
arrays so they can be tested.

I am CC-ing Greg to see what he thinks about it.

--
Dmitry

===================================================================

sysfs: add support for attribure arrays so it is possible to create
a (variable) number of similar attributes all sharing the
same show and store handlers:

../<attr_name>/0
../<attr_name>/1
...
../<attr_name>/<n>

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

fs/sysfs/Makefile | 2
fs/sysfs/array.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/sysfs.h | 20 +++++
3 files changed, 187 insertions(+), 2 deletions(-)

Index: dtor/fs/sysfs/array.c
===================================================================
--- /dev/null
+++ dtor/fs/sysfs/array.c
@@ -0,0 +1,167 @@
+/*
+ * fs/sysfs/array.c - Operations for adding/removing arrays of attributes.
+ *
+ * Copyright (c) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ * This file is released under the GPL v2.
+ *
+ */
+
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/dcache.h>
+#include <linux/err.h>
+#include "sysfs.h"
+
+struct attr_element {
+ struct attribute attr;
+ unsigned int idx;
+ char name[4];
+};
+#define to_attr_element(e) container_of(e, struct attr_element, attr)
+
+struct array_object {
+ const struct attribute_array *array;
+ unsigned int n_elements;
+ struct kobject kobj;
+ struct attr_element elements[0];
+};
+#define to_array_object(obj) container_of(obj, struct array_object, kobj)
+
+static ssize_t
+attr_array_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+ struct attr_element *element = to_attr_element(attr);
+ struct array_object *obj = to_array_object(kobj);
+ ssize_t ret = 0;
+
+ if (obj->array->show) {
+ struct kobject *parent = kobject_get(kobj->parent);
+ ret = obj->array->show(parent, element->idx, buf);
+ kobject_put(parent);
+ }
+
+ return ret;
+}
+
+static ssize_t
+attr_array_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ struct attr_element *element = to_attr_element(attr);
+ struct array_object *obj = to_array_object(kobj);
+ ssize_t ret = 0;
+
+ if (obj->array->store) {
+ struct kobject *parent = kobject_get(kobj->parent);
+ ret = obj->array->store(parent, element->idx, buf, count);
+ kobject_put(parent);
+ }
+
+ return ret;
+}
+
+static struct sysfs_ops attr_array_sysfs_ops = {
+ .show = attr_array_show,
+ .store = attr_array_store,
+};
+
+
+static void attr_array_release(struct kobject *kobj)
+{
+ kfree(to_array_object(kobj));
+}
+
+static struct kobj_type ktype_attr_array = {
+ .release = attr_array_release,
+ .sysfs_ops = &attr_array_sysfs_ops,
+};
+
+
+static int create_array_element(struct array_object *obj,
+ unsigned int idx)
+{
+ struct attr_element *element = &obj->elements[idx];
+
+ snprintf(element->name, sizeof(element->name), "%d", idx);
+ element->idx = idx;
+ element->attr = obj->array->attr;
+ element->attr.name = element->name;
+
+ return sysfs_create_file(&obj->kobj, &element->attr);
+}
+
+static inline void remove_array_element(struct array_object *obj,
+ unsigned int idx)
+{
+ sysfs_remove_file(&obj->kobj, &obj->elements[idx].attr);
+}
+
+int sysfs_create_array(struct kobject *kobj,
+ const struct attribute_array *array,
+ unsigned int n_elements)
+{
+ struct array_object *obj;
+ size_t size;
+ unsigned int i;
+ int error;
+
+ BUG_ON(!kobj || !kobj->dentry);
+ BUG_ON(!array->attr.name);
+
+ size = sizeof(struct array_object) +
+ sizeof(struct attr_element) * n_elements;
+
+ obj = kmalloc(size, GFP_KERNEL);
+ if (!obj)
+ return -ENOMEM;
+
+ memset(obj, 0, size);
+ obj->array = array;
+ obj->n_elements = n_elements;
+
+ obj->kobj.ktype = &ktype_attr_array;
+ obj->kobj.parent = kobj;
+ kobject_set_name(&obj->kobj, array->attr.name);
+
+ error = kobject_register(&obj->kobj);
+ if (error)
+ goto fail;
+
+ for (i = 0; i < n_elements; i++) {
+ error = create_array_element(obj, i);
+ if (error) {
+ while (--i)
+ remove_array_element(obj, i);
+ goto fail;
+ }
+ }
+
+ return 0;
+
+ fail:
+ kfree(obj);
+ return error;
+}
+
+void sysfs_remove_array(struct kobject *kobj,
+ const struct attribute_array *array)
+{
+ struct array_object *obj;
+ struct dentry *dir;
+ unsigned int i;
+
+ dir = sysfs_get_dentry(kobj->dentry, array->attr.name);
+
+ if (dir) {
+ obj = to_array_object(to_kobj(dir));
+ for (i = 0; i < obj->n_elements; i++)
+ remove_array_element(obj, i);
+ kobject_unregister(&obj->kobj);
+ }
+
+ dput(dir);
+}
+
+EXPORT_SYMBOL_GPL(sysfs_create_array);
+EXPORT_SYMBOL_GPL(sysfs_remove_array);
Index: dtor/include/linux/sysfs.h
===================================================================
--- dtor.orig/include/linux/sysfs.h
+++ dtor/include/linux/sysfs.h
@@ -26,7 +26,12 @@ struct attribute_group {
struct attribute ** attrs;
};

+struct attribute_array {
+ struct attribute attr;

+ ssize_t (*show)(struct kobject *, unsigned int index, char *);
+ ssize_t (*store)(struct kobject *, unsigned int index, const char *, size_t);
+};

/**
* Use these macros to make defining attributes easier. See include/linux/device.h
@@ -102,7 +107,7 @@ sysfs_update_file(struct kobject *, cons
extern void
sysfs_remove_file(struct kobject *, const struct attribute *);

-extern int
+extern int
sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name);

extern void
@@ -114,6 +119,9 @@ int sysfs_remove_bin_file(struct kobject
int sysfs_create_group(struct kobject *, const struct attribute_group *);
void sysfs_remove_group(struct kobject *, const struct attribute_group *);

+int sysfs_create_array(struct kobject *, const struct attribute_array *, unsigned int);
+void sysfs_remove_array(struct kobject *, const struct attribute_array *);
+
#else /* CONFIG_SYSFS */

static inline int sysfs_create_dir(struct kobject * k)
@@ -177,6 +185,16 @@ static inline void sysfs_remove_group(st
;
}

+static inline int sysfs_create_array(struct kobject * k, const struct attribute_array *a, unsigned int n)
+{
+ return 0;
+}
+
+static inline void sysfs_remove_array(struct kobject * k, const struct attribute_array * a)
+{
+ ;
+}
+
#endif /* CONFIG_SYSFS */

#endif /* _SYSFS_H_ */
Index: dtor/fs/sysfs/Makefile
===================================================================
--- dtor.orig/fs/sysfs/Makefile
+++ dtor/fs/sysfs/Makefile
@@ -3,4 +3,4 @@
#

obj-y := inode.o file.o dir.o symlink.o mount.o bin.o \
- group.o
+ group.o array.o
\
 
 \ /
  Last update: 2005-03-22 14:11    [W:0.145 / U:0.812 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site