diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2009-11-20 19:08:50 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 14:24:53 -0500 |
commit | 35df63c46c8605d00140ec4833d2104e2e9f1acc (patch) | |
tree | 1f02d75ab4589d3c8878e38e9d45360a0c0667d4 /fs/sysfs | |
parent | 4be3df28beec5605c77a18aa2a4f987b5648f9ce (diff) |
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>
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/inode.c | 51 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 1 |
2 files changed, 32 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 | ||
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index af4c4e7482ac..a96d9678ae73 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -155,6 +155,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) | |||
155 | */ | 155 | */ |
156 | struct inode *sysfs_get_inode(struct sysfs_dirent *sd); | 156 | struct inode *sysfs_get_inode(struct sysfs_dirent *sd); |
157 | void sysfs_delete_inode(struct inode *inode); | 157 | void sysfs_delete_inode(struct inode *inode); |
158 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); | ||
158 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | 159 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); |
159 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 160 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
160 | size_t size, int flags); | 161 | size_t size, int flags); |