summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2002-11-24 08:30:41 -0600
committerPatrick Mochel <mochel@osdl.org>2002-11-24 08:30:41 -0600
commita43b9aa9bc1e7243a60ca56ba2f1c973317dfffa (patch)
tree9b48c6f58bd779550f8779f1b483e818d7736090
parentcebce9d8beb7493d5c82035db854a475f6a1ae66 (diff)
parent8083cc3514c1f79c9694d7e8f4e8c446d88819b5 (diff)
Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin
into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core
-rw-r--r--fs/sysfs/inode.c60
-rw-r--r--include/linux/kobject.h9
-rw-r--r--lib/kobject.c34
3 files changed, 95 insertions, 8 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 73633052e993..684038810f77 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -96,9 +96,10 @@ static int sysfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
if (!dentry->d_inode) {
inode = sysfs_get_inode(dir->i_sb, mode, dev);
- if (inode)
+ if (inode) {
d_instantiate(dentry, inode);
- else
+ dget(dentry);
+ } else
error = -ENOSPC;
} else
error = -EEXIST;
@@ -135,14 +136,52 @@ static int sysfs_symlink(struct inode * dir, struct dentry *dentry, const char *
if (inode) {
int l = strlen(symname)+1;
error = page_symlink(inode, symname, l);
- if (!error)
+ if (!error) {
d_instantiate(dentry, inode);
- else
+ dget(dentry);
+ } else
iput(inode);
}
return error;
}
+#define to_subsys(k) container_of(k,struct subsystem,kobj)
+#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
+
+/**
+ * Subsystem file operations.
+ * These operations allow subsystems to have files that can be
+ * read/written.
+ */
+ssize_t subsys_attr_show(struct kobject * kobj, struct attribute * attr,
+ char * page, size_t count, loff_t off)
+{
+ struct subsystem * s = to_subsys(kobj);
+ struct subsys_attribute * sattr = to_sattr(attr);
+ ssize_t ret = 0;
+
+ if (sattr->show)
+ ret = sattr->show(s,page,count,off);
+ return ret;
+}
+
+ssize_t subsys_attr_store(struct kobject * kobj, struct attribute * attr,
+ const char * page, size_t count, loff_t off)
+{
+ struct subsystem * s = to_subsys(kobj);
+ struct subsys_attribute * sattr = to_sattr(attr);
+ ssize_t ret = 0;
+
+ if (sattr->store)
+ ret = sattr->store(s,page,count,off);
+ return ret;
+}
+
+static struct sysfs_ops subsys_sysfs_ops = {
+ .show = subsys_attr_show,
+ .store = subsys_attr_store,
+};
+
/**
* sysfs_read_file - read an attribute.
* @file: file pointer.
@@ -263,9 +302,14 @@ static int check_perm(struct inode * inode, struct file * file)
if (!kobj || !attr)
goto Einval;
-
+
+ /* if the kobject has no subsystem, then it is a subsystem itself,
+ * so give it the subsys_sysfs_ops.
+ */
if (kobj->subsys)
ops = kobj->subsys->sysfs_ops;
+ else
+ ops = &subsys_sysfs_ops;
/* No sysfs operations, either from having no subsystem,
* or the subsystem have no operations.
@@ -571,8 +615,8 @@ static void hash_and_remove(struct dentry * dir, const char * name)
/* make sure dentry is really there */
if (victim->d_inode &&
(victim->d_parent->d_inode == dir->d_inode)) {
- d_invalidate(victim);
simple_unlink(dir->d_inode,victim);
+ d_delete(victim);
}
}
up(&dir->d_inode->i_sem);
@@ -631,15 +675,15 @@ void sysfs_remove_dir(struct kobject * kobj)
struct dentry * d = list_entry(node,struct dentry,d_child);
/* make sure dentry is still there */
if (d->d_inode) {
- d_invalidate(d);
simple_unlink(dentry->d_inode,d);
+ d_delete(dentry);
}
}
up(&dentry->d_inode->i_sem);
d_invalidate(dentry);
simple_rmdir(parent->d_inode,dentry);
-
+ d_delete(dentry);
up(&parent->d_inode->i_sem);
dput(parent);
}
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 7b3157a78f7e..6b528c5a61cb 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -60,4 +60,13 @@ static inline void subsys_put(struct subsystem * s)
kobject_put(&s->kobj);
}
+struct subsys_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct subsystem *, char *, size_t, loff_t);
+ ssize_t (*store)(struct subsystem *, const char *, size_t, loff_t);
+};
+
+extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
+extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
+
#endif /* _KOBJECT_H_ */
diff --git a/lib/kobject.c b/lib/kobject.c
index 33e4f8c9ce58..bdf6636d2b2e 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -229,6 +229,38 @@ void subsystem_unregister(struct subsystem * s)
}
+/**
+ * subsystem_create_file - export sysfs attribute file.
+ * @s: subsystem.
+ * @a: subsystem attribute descriptor.
+ */
+
+int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
+{
+ int error = 0;
+ if (subsys_get(s)) {
+ error = sysfs_create_file(&s->kobj,&a->attr);
+ subsys_put(s);
+ }
+ return error;
+}
+
+
+/**
+ * subsystem_remove_file - remove sysfs attribute file.
+ * @s: subsystem.
+ * @a: attribute desciptor.
+ */
+
+void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
+{
+ if (subsys_get(s)) {
+ sysfs_remove_file(&s->kobj,&a->attr);
+ subsys_put(s);
+ }
+}
+
+
EXPORT_SYMBOL(kobject_init);
EXPORT_SYMBOL(kobject_register);
EXPORT_SYMBOL(kobject_unregister);
@@ -238,3 +270,5 @@ EXPORT_SYMBOL(kobject_put);
EXPORT_SYMBOL(subsystem_init);
EXPORT_SYMBOL(subsystem_register);
EXPORT_SYMBOL(subsystem_unregister);
+EXPORT_SYMBOL(subsys_create_file);
+EXPORT_SYMBOL(subsys_remove_file);