mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
sysfs: Fix locking and factor out sysfs_sd_setattr
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. Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
4be3df28be
commit
35df63c46c
2 changed files with 32 additions and 20 deletions
|
@ -65,30 +65,14 @@ static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
|
|||
return attrs;
|
||||
}
|
||||
|
||||
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 sysfs_inode_attrs *sd_attrs;
|
||||
struct iattr *iattrs;
|
||||
unsigned int ia_valid = iattr->ia_valid;
|
||||
int error;
|
||||
|
||||
if (!sd)
|
||||
return -EINVAL;
|
||||
|
||||
sd_attrs = sd->s_iattr;
|
||||
|
||||
error = inode_change_ok(inode, iattr);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
|
||||
|
||||
error = inode_setattr(inode, iattr);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!sd_attrs) {
|
||||
/* setting attributes for the first time, allocate now */
|
||||
sd_attrs = sysfs_init_inode_attrs(sd);
|
||||
|
@ -111,12 +95,39 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
|
|||
iattrs->ia_ctime = iattr->ia_ctime;
|
||||
if (ia_valid & ATTR_MODE) {
|
||||
umode_t mode = iattr->ia_mode;
|
||||
|
||||
if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
|
||||
mode &= ~S_ISGID;
|
||||
iattrs->ia_mode = sd->s_mode = 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -155,6 +155,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_setxattr(struct dentry *dentry, const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
|
|
Loading…
Reference in a new issue