From 471bd7b78bd56c580e91e00a0f656ca922ab3b3c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:22 -0500 Subject: [PATCH] sysfs, kernfs: add sysfs_dirent->s_attr.size sysfs sets the size of regular files unconditionally at PAGE_SIZE and takes the size of bin files from bin_attribute. The latter is a pretty bad interface which forces bin_attribute users to create a separate copy of bin_attribute for each instance of the file - e.g. pci resource files. Add sysfs_dirent->s_attr.size so that the size can be specified separately. This unifies inode init paths of ATTR and BIN_ATTR identical and allows for generic size handling for kernfs. Unfortunately, this grows the size of sysfs_dirent by sizeof(loff_t). Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 6 ++++++ fs/sysfs/inode.c | 8 +------- fs/sysfs/sysfs.h | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index cbebc33..0b0cec8 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -923,6 +923,7 @@ int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, const struct kernfs_ops *ops; struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; + loff_t size; int rc; if (type == SYSFS_KOBJ_ATTR) { @@ -943,6 +944,8 @@ int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, ops = &sysfs_file_kfops_wo; else ops = &sysfs_file_kfops_empty; + + size = PAGE_SIZE; } else { struct bin_attribute *battr = (void *)attr; @@ -954,6 +957,8 @@ int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, ops = &sysfs_bin_kfops_wo; else ops = &sysfs_file_kfops_empty; + + size = battr->size; } sd = sysfs_new_dirent(attr->name, mode, type); @@ -961,6 +966,7 @@ int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd, return -ENOMEM; sd->s_attr.ops = ops; + sd->s_attr.size = size; sd->s_ns = ns; sd->priv = (void *)attr; sysfs_dirent_init_lockdep(sd); diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 4c463da..037a892 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -254,8 +254,6 @@ int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) { - struct bin_attribute *bin_attr; - inode->i_private = sysfs_get(sd); inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; @@ -271,12 +269,8 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) inode->i_fop = &sysfs_dir_operations; break; case SYSFS_KOBJ_ATTR: - inode->i_size = PAGE_SIZE; - inode->i_fop = &kernfs_file_operations; - break; case SYSFS_KOBJ_BIN_ATTR: - bin_attr = sd->priv; - inode->i_size = bin_attr->size; + inode->i_size = sd->s_attr.size; inode->i_fop = &kernfs_file_operations; break; case SYSFS_KOBJ_LINK: diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index c05e0dd..d40e85e 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -29,6 +29,7 @@ struct sysfs_elem_symlink { struct sysfs_elem_attr { const struct kernfs_ops *ops; struct sysfs_open_dirent *open; + loff_t size; }; struct sysfs_inode_attrs { -- 2.7.4