From htejun@gmail.com Sat Apr 28 06:40:02 2007 From: Tejun Heo Date: Sat, 28 Apr 2007 22:39:42 +0900 Subject: [PATCH 13/21] sysfs: make sysfs_dirent->s_element a union To: gregkh@suse.de, dmitry.torokhov@gmail.com, cornelia.huck@de.ibm.com, oneukum@suse.de, rpurdie@rpsys.net, stern@rowland.harvard.edu, maneesh@in.ibm.com, akpm@linux-foundation.org, linux-kernel@vger.kernel.org, htejun@gmail.com Cc: Tejun Heo Message-ID: <11777675822788-git-send-email-htejun@gmail.com> Make sd->s_element a union of sysfs_elem_{dir|symlink|attr|bin_attr} and rename it to s_elem. This is to achieve... * some level of type checking : changing symlink to point to sysfs_dirent instead of kobject is much safer and less painful now. * easier / standardized dereferencing * allow sysfs_elem_* to contain more than one entry Where possible, pointer is obtained by directly deferencing from sd instead of going through other entities. This reduces dependencies to dentry, inode and kobject. to_attr() and to_bin_attr() are unused now and removed. This is in preparation of object reference simplification. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/bin.c | 18 ++++++++++------- fs/sysfs/dir.c | 31 +++++++++++++---------------- fs/sysfs/file.c | 19 +++++++++-------- fs/sysfs/inode.c | 2 - fs/sysfs/mount.c | 1 fs/sysfs/symlink.c | 23 +++------------------ fs/sysfs/sysfs.h | 56 +++++++++++++++++++++++++++++------------------------ 7 files changed, 71 insertions(+), 79 deletions(-) --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -23,7 +23,8 @@ static int fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) { - struct bin_attribute * attr = to_bin_attr(dentry); + struct sysfs_dirent *attr_sd = dentry->d_fsdata; + struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; struct kobject * kobj = to_kobj(dentry->d_parent); if (!attr->read) @@ -65,7 +66,8 @@ read(struct file *file, char __user *use static int flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) { - struct bin_attribute *attr = to_bin_attr(dentry); + struct sysfs_dirent *attr_sd = dentry->d_fsdata; + struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; struct kobject *kobj = to_kobj(dentry->d_parent); if (!attr->write) @@ -101,9 +103,9 @@ static ssize_t write(struct file *file, static int mmap(struct file *file, struct vm_area_struct *vma) { - struct dentry *dentry = file->f_path.dentry; - struct bin_attribute *attr = to_bin_attr(dentry); - struct kobject *kobj = to_kobj(dentry->d_parent); + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; + struct kobject *kobj = to_kobj(file->f_path.dentry->d_parent); if (!attr->mmap) return -EINVAL; @@ -114,7 +116,8 @@ static int mmap(struct file *file, struc static int open(struct inode * inode, struct file * file) { struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); - struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; int error = -EINVAL; if (!kobj || !attr) @@ -150,7 +153,8 @@ static int open(struct inode * inode, st static int release(struct inode * inode, struct file * file) { struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent); - struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; u8 * buffer = file->private_data; kobject_put(kobj); --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -51,11 +51,8 @@ void release_sysfs_dirent(struct sysfs_d repeat: parent_sd = sd->s_parent; - if (sd->s_type & SYSFS_KOBJ_LINK) { - struct sysfs_symlink * sl = sd->s_element; - kobject_put(sl->target_kobj); - kfree(sl); - } + if (sd->s_type & SYSFS_KOBJ_LINK) + kobject_put(sd->s_elem.symlink.target_kobj); if (sd->s_type & SYSFS_COPY_NAME) kfree(sd->s_name); kfree(sd->s_iattr); @@ -83,8 +80,7 @@ static struct dentry_operations sysfs_de .d_iput = sysfs_d_iput, }; -struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, - umode_t mode, int type) +struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) { char *dup_name = NULL; struct sysfs_dirent *sd = NULL; @@ -108,7 +104,6 @@ struct sysfs_dirent *sysfs_new_dirent(co INIT_LIST_HEAD(&sd->s_sibling); sd->s_name = name; - sd->s_element = element; sd->s_mode = mode; sd->s_type = type; @@ -148,7 +143,7 @@ int sysfs_dirent_exist(struct sysfs_dire struct sysfs_dirent * sd; list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { - if (sd->s_element) { + if (sd->s_type) { if (strcmp(sd->s_name, new)) continue; else @@ -203,9 +198,10 @@ static int create_dir(struct kobject *ko goto out_dput; error = -ENOMEM; - sd = sysfs_new_dirent(name, kobj, mode, SYSFS_DIR); + sd = sysfs_new_dirent(name, mode, SYSFS_DIR); if (!sd) goto out_drop; + sd->s_elem.dir.kobj = kobj; sysfs_attach_dirent(sd, parent->d_fsdata, dentry); error = sysfs_create(dentry, mode, init_dir); @@ -278,10 +274,10 @@ static int sysfs_attach_attr(struct sysf int error = 0; if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) { - bin_attr = sd->s_element; + bin_attr = sd->s_elem.bin_attr.bin_attr; attr = &bin_attr->attr; } else { - attr = sd->s_element; + attr = sd->s_elem.attr.attr; init = init_file; } @@ -386,7 +382,7 @@ static void __sysfs_remove_dir(struct de mutex_lock(&dentry->d_inode->i_mutex); parent_sd = dentry->d_fsdata; list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { - if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED)) + if (!sd->s_type || !(sd->s_type & SYSFS_NOT_PINNED)) continue; list_del_init(&sd->s_sibling); sysfs_drop_dentry(sd, dentry); @@ -538,7 +534,7 @@ static int sysfs_dir_open(struct inode * struct sysfs_dirent * sd; mutex_lock(&dentry->d_inode->i_mutex); - sd = sysfs_new_dirent("_DIR_", NULL, 0, 0); + sd = sysfs_new_dirent("_DIR_", 0, 0); if (sd) sysfs_attach_dirent(sd, parent_sd, NULL); mutex_unlock(&dentry->d_inode->i_mutex); @@ -605,7 +601,7 @@ static int sysfs_readdir(struct file * f next = list_entry(p, struct sysfs_dirent, s_sibling); - if (!next->s_element) + if (!next->s_type) continue; name = next->s_name; @@ -653,7 +649,7 @@ static loff_t sysfs_dir_lseek(struct fil struct sysfs_dirent *next; next = list_entry(p, struct sysfs_dirent, s_sibling); - if (next->s_element) + if (next->s_type) n--; p = p->next; } @@ -720,9 +716,10 @@ struct dentry *sysfs_create_shadow_dir(s if (!shadow) goto nomem; - sd = sysfs_new_dirent("_SHADOW_", kobj, inode->i_mode, SYSFS_DIR); + sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR); if (!sd) goto nomem; + sd->s_elem.dir.kobj = kobj; /* point to parent_sd but don't attach to it */ sd->s_parent = sysfs_get(parent_sd); sysfs_attach_dirent(sd, NULL, shadow); --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -88,7 +88,6 @@ remove_from_collection(struct sysfs_buff static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) { struct sysfs_dirent * sd = dentry->d_fsdata; - struct attribute * attr = to_attr(dentry); struct kobject * kobj = to_kobj(dentry->d_parent); struct sysfs_ops * ops = buffer->ops; int ret = 0; @@ -100,7 +99,7 @@ static int fill_read_buffer(struct dentr return -ENOMEM; buffer->event = atomic_read(&sd->s_event); - count = ops->show(kobj,attr,buffer->page); + count = ops->show(kobj, sd->s_elem.attr.attr, buffer->page); BUG_ON(count > (ssize_t)PAGE_SIZE); if (count >= 0) { buffer->needs_read_fill = 0; @@ -228,11 +227,11 @@ fill_write_buffer(struct sysfs_buffer * static int flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) { - struct attribute * attr = to_attr(dentry); + struct sysfs_dirent *attr_sd = dentry->d_fsdata; struct kobject * kobj = to_kobj(dentry->d_parent); struct sysfs_ops * ops = buffer->ops; - return ops->store(kobj,attr,buffer->page,count); + return ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count); } @@ -277,7 +276,8 @@ out: static int sysfs_open_file(struct inode *inode, struct file *file) { struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); - struct attribute * attr = to_attr(file->f_path.dentry); + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; + struct attribute *attr = attr_sd->s_elem.attr.attr; struct sysfs_buffer_collection *set; struct sysfs_buffer * buffer; struct sysfs_ops * ops = NULL; @@ -370,15 +370,15 @@ static int sysfs_open_file(struct inode static int sysfs_release(struct inode * inode, struct file * filp) { struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); - struct attribute * attr = to_attr(filp->f_path.dentry); - struct module * owner = attr->owner; + struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; + struct attribute *attr = attr_sd->s_elem.attr.attr; struct sysfs_buffer * buffer = filp->private_data; if (buffer) remove_from_collection(buffer, inode); kobject_put(kobj); /* After this point, attr should not be accessed. */ - module_put(owner); + module_put(attr->owner); if (buffer) { if (buffer->page) @@ -483,11 +483,12 @@ int sysfs_add_file(struct dentry * dir, goto out_unlock; } - sd = sysfs_new_dirent(attr->name, (void *)attr, mode, type); + sd = sysfs_new_dirent(attr->name, mode, type); if (!sd) { error = -ENOMEM; goto out_unlock; } + sd->s_elem.attr.attr = (void *)attr; sysfs_attach_dirent(sd, parent_sd, NULL); out_unlock: --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -255,7 +255,7 @@ int sysfs_hash_and_remove(struct dentry parent_sd = dir->d_fsdata; mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { - if (!sd->s_element) + if (!sd->s_type) continue; if (!strcmp(sd->s_name, name)) { list_del_init(&sd->s_sibling); --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -31,7 +31,6 @@ static struct sysfs_dirent sysfs_root = .s_count = ATOMIC_INIT(1), .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling), .s_children = LIST_HEAD_INIT(sysfs_root.s_children), - .s_element = NULL, .s_type = SYSFS_ROOT, .s_ino = 1, .s_iattr = NULL, --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -48,30 +48,15 @@ static void fill_object_path(struct kobj static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target) { struct sysfs_dirent * parent_sd = parent->d_fsdata; - struct sysfs_symlink * sl; struct sysfs_dirent * sd; - int error; - error = -ENOMEM; - sl = kzalloc(sizeof(*sl), GFP_KERNEL); - if (!sl) - goto err_out; - - sl->target_kobj = kobject_get(target); - - sd = sysfs_new_dirent(name, sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); + sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); if (!sd) - goto err_out; - sysfs_attach_dirent(sd, parent_sd, NULL); + return -ENOMEM; + sd->s_elem.symlink.target_kobj = kobject_get(target); + sysfs_attach_dirent(sd, parent_sd, NULL); return 0; - - err_out: - if (sl) { - kobject_put(sl->target_kobj); - kfree(sl); - } - return error; } /** --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -1,10 +1,33 @@ +struct sysfs_elem_dir { + struct kobject * kobj; +}; + +struct sysfs_elem_symlink { + struct kobject * target_kobj; +}; + +struct sysfs_elem_attr { + struct attribute * attr; +}; + +struct sysfs_elem_bin_attr { + struct bin_attribute * bin_attr; +}; + struct sysfs_dirent { atomic_t s_count; struct sysfs_dirent * s_parent; struct list_head s_sibling; struct list_head s_children; const char * s_name; - void * s_element; + + union { + struct sysfs_elem_dir dir; + struct sysfs_elem_symlink symlink; + struct sysfs_elem_attr attr; + struct sysfs_elem_bin_attr bin_attr; + } s_elem; + int s_type; umode_t s_mode; ino_t s_ino; @@ -22,8 +45,8 @@ extern int sysfs_create(struct dentry *, extern void release_sysfs_dirent(struct sysfs_dirent * sd); extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); -extern struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, - umode_t mode, int type); +extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, + int type); extern void sysfs_attach_dirent(struct sysfs_dirent *sd, struct sysfs_dirent *parent_sd, struct dentry *dentry); @@ -46,10 +69,6 @@ extern const struct file_operations bin_ extern const struct inode_operations sysfs_dir_inode_operations; extern const struct inode_operations sysfs_symlink_inode_operations; -struct sysfs_symlink { - struct kobject * target_kobj; -}; - struct sysfs_buffer { struct list_head associates; size_t count; @@ -69,19 +88,7 @@ struct sysfs_buffer_collection { static inline struct kobject * to_kobj(struct dentry * dentry) { struct sysfs_dirent * sd = dentry->d_fsdata; - return ((struct kobject *) sd->s_element); -} - -static inline struct attribute * to_attr(struct dentry * dentry) -{ - struct sysfs_dirent * sd = dentry->d_fsdata; - return ((struct attribute *) sd->s_element); -} - -static inline struct bin_attribute * to_bin_attr(struct dentry * dentry) -{ - struct sysfs_dirent * sd = dentry->d_fsdata; - return ((struct bin_attribute *) sd->s_element); + return sd->s_elem.dir.kobj; } static inline struct kobject *sysfs_get_kobject(struct dentry *dentry) @@ -91,11 +98,10 @@ static inline struct kobject *sysfs_get_ spin_lock(&dcache_lock); if (!d_unhashed(dentry)) { struct sysfs_dirent * sd = dentry->d_fsdata; - if (sd->s_type & SYSFS_KOBJ_LINK) { - struct sysfs_symlink * sl = sd->s_element; - kobj = kobject_get(sl->target_kobj); - } else - kobj = kobject_get(sd->s_element); + if (sd->s_type & SYSFS_KOBJ_LINK) + kobj = kobject_get(sd->s_elem.symlink.target_kobj); + else + kobj = kobject_get(sd->s_elem.dir.kobj); } spin_unlock(&dcache_lock);