From: Eric W. Biederman <ebiederm@xxxxxxxxxxxx> Cleanly separate the work that is specific to setting the attributes of a sysfs_dirent from what is needed to update the attributes of a vfs inode. Additionally grab the sysfs_mutex to keep any nasties from surprising us when updating the sysfs_dirent. Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxxxxxxxx> --- fs/sysfs/inode.c | 52 ++++++++++++++++++++++++++++++---------------------- fs/sysfs/sysfs.h | 1 + 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 5020a1d..dd154cb 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -42,33 +42,12 @@ int __init sysfs_inode_init(void) return bdi_init(&sysfs_backing_dev_info); } -int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) +int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr) { - struct inode * inode = dentry->d_inode; - struct sysfs_dirent * sd = dentry->d_fsdata; struct iattr * sd_iattr; unsigned int ia_valid = iattr->ia_valid; - int error; - - if (!sd) - return -EINVAL; sd_iattr = sd->s_iattr; - - error = inode_change_ok(inode, iattr); - if (error) - return error; - - iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ - if (iattr->ia_valid & ATTR_MODE) { - if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) - iattr->ia_mode &= ~S_ISGID; - } - - error = inode_setattr(inode, iattr); - if (error) - return error; - if (!sd_iattr && (ia_valid & ~ATTR_MODE)) { /* setting attributes for the first time, allocate now */ sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL); @@ -103,6 +82,35 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) sd_iattr->ia_ctime = iattr->ia_ctime; if (ia_valid & ATTR_MODE) sd_iattr->ia_mode = iattr->ia_mode; + return 0; +} + +int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) +{ + struct inode * inode = dentry->d_inode; + struct sysfs_dirent * sd = dentry->d_fsdata; + int error; + + if (!sd) + return -EINVAL; + + error = inode_change_ok(inode, iattr); + if (error) + return error; + + iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ + if (iattr->ia_valid & ATTR_MODE) { + if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) + iattr->ia_mode &= ~S_ISGID; + } + + error = inode_setattr(inode, iattr); + if (error) + return error; + + mutex_lock(&sysfs_mutex); + error = sysfs_sd_setattr(sd, iattr); + mutex_unlock(&sysfs_mutex); return error; } diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index abf05f4..043bb13 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -146,6 +146,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) */ struct inode *sysfs_get_inode(struct sysfs_dirent *sd); void sysfs_delete_inode(struct inode *inode); +int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); int sysfs_inode_init(void); -- 1.6.1.2.350.g88cc -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html