From 35551cf5753fe89869f24fc06f6b787b02a10acc Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Thu, 21 Nov 2002 01:50:58 -0600 Subject: sysfs: fix file deletion again. After looking into again, I realize that I was again getting file and directory deletion a little wrong. This patch should go back to mimmicking the VFS again. - The extra dget() in sysfs_mknod() and sysfs_symlink() has been readded. This is identical to the way ramfs does creation. - We do d_delete() after simple_unlink() and simple_rmdir(), instead of d_invalidate() before it. This is how vfs_rmdir() and vfs_unlink() do it, and the way we used to. --- fs/sysfs/inode.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 73633052e993..2b914285eeaf 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,9 +136,10 @@ 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; @@ -571,8 +573,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 +633,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); } -- cgit v1.2.3 From 2ce5e0bca93f06683b40fbae3b5b4031dd02b2cc Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Thu, 21 Nov 2002 05:01:54 -0600 Subject: Allow subsystem to have attributes, too. This is really handy for subsystems that have any attributes they want to export, esp. if they have just a few, since they don't have to define all of the infrastructure for creating and tearing down the attributes for the high level type that they are. - define struct subsys_attribute for declaring attributes of subsystems themselves. - define subsys_create_file() and subsys_remove_file(). - define subsys_sysfs_ops for forwarding sysfs reads and writes to the subsystem attribute callbacks. - Set the sysfs_ops to be the subsystem ones if the kobject doesn't belong to a subsystem itself (meaning that it is a subsystem). --- fs/sysfs/inode.c | 44 +++++++++++++++++++++++++++++++++++++++++++- include/linux/kobject.h | 9 +++++++++ lib/kobject.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 2b914285eeaf..684038810f77 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -145,6 +145,43 @@ static int sysfs_symlink(struct inode * dir, struct dentry *dentry, const char * 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. @@ -265,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. 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); -- cgit v1.2.3