diff options
Diffstat (limited to 'fs/sysfs/inode.c')
| -rw-r--r-- | fs/sysfs/inode.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 86fb230de432..76e977c300f7 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -65,30 +65,14 @@ static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) | |||
| 65 | return attrs; | 65 | return attrs; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | 68 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr) |
| 69 | { | 69 | { |
| 70 | struct inode * inode = dentry->d_inode; | ||
| 71 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
| 72 | struct sysfs_inode_attrs *sd_attrs; | 70 | struct sysfs_inode_attrs *sd_attrs; |
| 73 | struct iattr *iattrs; | 71 | struct iattr *iattrs; |
| 74 | unsigned int ia_valid = iattr->ia_valid; | 72 | unsigned int ia_valid = iattr->ia_valid; |
| 75 | int error; | ||
| 76 | |||
| 77 | if (!sd) | ||
| 78 | return -EINVAL; | ||
| 79 | 73 | ||
| 80 | sd_attrs = sd->s_iattr; | 74 | sd_attrs = sd->s_iattr; |
| 81 | 75 | ||
| 82 | error = inode_change_ok(inode, iattr); | ||
| 83 | if (error) | ||
| 84 | return error; | ||
| 85 | |||
| 86 | iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ | ||
| 87 | |||
| 88 | error = inode_setattr(inode, iattr); | ||
| 89 | if (error) | ||
| 90 | return error; | ||
| 91 | |||
| 92 | if (!sd_attrs) { | 76 | if (!sd_attrs) { |
| 93 | /* setting attributes for the first time, allocate now */ | 77 | /* setting attributes for the first time, allocate now */ |
| 94 | sd_attrs = sysfs_init_inode_attrs(sd); | 78 | sd_attrs = sysfs_init_inode_attrs(sd); |
| @@ -111,12 +95,39 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | |||
| 111 | iattrs->ia_ctime = iattr->ia_ctime; | 95 | iattrs->ia_ctime = iattr->ia_ctime; |
| 112 | if (ia_valid & ATTR_MODE) { | 96 | if (ia_valid & ATTR_MODE) { |
| 113 | umode_t mode = iattr->ia_mode; | 97 | umode_t mode = iattr->ia_mode; |
| 114 | |||
| 115 | if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) | ||
| 116 | mode &= ~S_ISGID; | ||
| 117 | iattrs->ia_mode = sd->s_mode = mode; | 98 | iattrs->ia_mode = sd->s_mode = mode; |
| 118 | } | 99 | } |
| 119 | } | 100 | } |
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) | ||
| 105 | { | ||
| 106 | struct inode *inode = dentry->d_inode; | ||
| 107 | struct sysfs_dirent *sd = dentry->d_fsdata; | ||
| 108 | int error; | ||
| 109 | |||
| 110 | if (!sd) | ||
| 111 | return -EINVAL; | ||
| 112 | |||
| 113 | error = inode_change_ok(inode, iattr); | ||
| 114 | if (error) | ||
| 115 | return error; | ||
| 116 | |||
| 117 | iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ | ||
| 118 | if (iattr->ia_valid & ATTR_MODE) { | ||
| 119 | if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) | ||
| 120 | iattr->ia_mode &= ~S_ISGID; | ||
| 121 | } | ||
| 122 | |||
| 123 | error = inode_setattr(inode, iattr); | ||
| 124 | if (error) | ||
| 125 | return error; | ||
| 126 | |||
| 127 | mutex_lock(&sysfs_mutex); | ||
| 128 | error = sysfs_sd_setattr(sd, iattr); | ||
| 129 | mutex_unlock(&sysfs_mutex); | ||
| 130 | |||
| 120 | return error; | 131 | return error; |
| 121 | } | 132 | } |
| 122 | 133 | ||
