diff options
| author | Patrick Mochel <mochel@osdl.org> | 2002-11-24 08:30:41 -0600 |
|---|---|---|
| committer | Patrick Mochel <mochel@osdl.org> | 2002-11-24 08:30:41 -0600 |
| commit | a43b9aa9bc1e7243a60ca56ba2f1c973317dfffa (patch) | |
| tree | 9b48c6f58bd779550f8779f1b483e818d7736090 | |
| parent | cebce9d8beb7493d5c82035db854a475f6a1ae66 (diff) | |
| parent | 8083cc3514c1f79c9694d7e8f4e8c446d88819b5 (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.c | 60 | ||||
| -rw-r--r-- | include/linux/kobject.h | 9 | ||||
| -rw-r--r-- | lib/kobject.c | 34 |
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); |
