diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/bin.c | 68 | ||||
-rw-r--r-- | fs/sysfs/file.c | 5 | ||||
-rw-r--r-- | fs/sysfs/group.c | 59 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 8 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 2 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 2 |
6 files changed, 102 insertions, 42 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 4e321f7353fa..a4759833d62d 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -179,30 +179,14 @@ static void bin_vma_open(struct vm_area_struct *vma) | |||
179 | struct bin_buffer *bb = file->private_data; | 179 | struct bin_buffer *bb = file->private_data; |
180 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 180 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
181 | 181 | ||
182 | if (!bb->vm_ops || !bb->vm_ops->open) | 182 | if (!bb->vm_ops) |
183 | return; | ||
184 | |||
185 | if (!sysfs_get_active(attr_sd)) | ||
186 | return; | ||
187 | |||
188 | bb->vm_ops->open(vma); | ||
189 | |||
190 | sysfs_put_active(attr_sd); | ||
191 | } | ||
192 | |||
193 | static void bin_vma_close(struct vm_area_struct *vma) | ||
194 | { | ||
195 | struct file *file = vma->vm_file; | ||
196 | struct bin_buffer *bb = file->private_data; | ||
197 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | ||
198 | |||
199 | if (!bb->vm_ops || !bb->vm_ops->close) | ||
200 | return; | 183 | return; |
201 | 184 | ||
202 | if (!sysfs_get_active(attr_sd)) | 185 | if (!sysfs_get_active(attr_sd)) |
203 | return; | 186 | return; |
204 | 187 | ||
205 | bb->vm_ops->close(vma); | 188 | if (bb->vm_ops->open) |
189 | bb->vm_ops->open(vma); | ||
206 | 190 | ||
207 | sysfs_put_active(attr_sd); | 191 | sysfs_put_active(attr_sd); |
208 | } | 192 | } |
@@ -214,13 +198,15 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
214 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 198 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
215 | int ret; | 199 | int ret; |
216 | 200 | ||
217 | if (!bb->vm_ops || !bb->vm_ops->fault) | 201 | if (!bb->vm_ops) |
218 | return VM_FAULT_SIGBUS; | 202 | return VM_FAULT_SIGBUS; |
219 | 203 | ||
220 | if (!sysfs_get_active(attr_sd)) | 204 | if (!sysfs_get_active(attr_sd)) |
221 | return VM_FAULT_SIGBUS; | 205 | return VM_FAULT_SIGBUS; |
222 | 206 | ||
223 | ret = bb->vm_ops->fault(vma, vmf); | 207 | ret = VM_FAULT_SIGBUS; |
208 | if (bb->vm_ops->fault) | ||
209 | ret = bb->vm_ops->fault(vma, vmf); | ||
224 | 210 | ||
225 | sysfs_put_active(attr_sd); | 211 | sysfs_put_active(attr_sd); |
226 | return ret; | 212 | return ret; |
@@ -236,13 +222,12 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
236 | if (!bb->vm_ops) | 222 | if (!bb->vm_ops) |
237 | return VM_FAULT_SIGBUS; | 223 | return VM_FAULT_SIGBUS; |
238 | 224 | ||
239 | if (!bb->vm_ops->page_mkwrite) | ||
240 | return 0; | ||
241 | |||
242 | if (!sysfs_get_active(attr_sd)) | 225 | if (!sysfs_get_active(attr_sd)) |
243 | return VM_FAULT_SIGBUS; | 226 | return VM_FAULT_SIGBUS; |
244 | 227 | ||
245 | ret = bb->vm_ops->page_mkwrite(vma, vmf); | 228 | ret = 0; |
229 | if (bb->vm_ops->page_mkwrite) | ||
230 | ret = bb->vm_ops->page_mkwrite(vma, vmf); | ||
246 | 231 | ||
247 | sysfs_put_active(attr_sd); | 232 | sysfs_put_active(attr_sd); |
248 | return ret; | 233 | return ret; |
@@ -256,13 +241,15 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr, | |||
256 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 241 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
257 | int ret; | 242 | int ret; |
258 | 243 | ||
259 | if (!bb->vm_ops || !bb->vm_ops->access) | 244 | if (!bb->vm_ops) |
260 | return -EINVAL; | 245 | return -EINVAL; |
261 | 246 | ||
262 | if (!sysfs_get_active(attr_sd)) | 247 | if (!sysfs_get_active(attr_sd)) |
263 | return -EINVAL; | 248 | return -EINVAL; |
264 | 249 | ||
265 | ret = bb->vm_ops->access(vma, addr, buf, len, write); | 250 | ret = -EINVAL; |
251 | if (bb->vm_ops->access) | ||
252 | ret = bb->vm_ops->access(vma, addr, buf, len, write); | ||
266 | 253 | ||
267 | sysfs_put_active(attr_sd); | 254 | sysfs_put_active(attr_sd); |
268 | return ret; | 255 | return ret; |
@@ -276,13 +263,15 @@ static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new) | |||
276 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 263 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
277 | int ret; | 264 | int ret; |
278 | 265 | ||
279 | if (!bb->vm_ops || !bb->vm_ops->set_policy) | 266 | if (!bb->vm_ops) |
280 | return 0; | 267 | return 0; |
281 | 268 | ||
282 | if (!sysfs_get_active(attr_sd)) | 269 | if (!sysfs_get_active(attr_sd)) |
283 | return -EINVAL; | 270 | return -EINVAL; |
284 | 271 | ||
285 | ret = bb->vm_ops->set_policy(vma, new); | 272 | ret = 0; |
273 | if (bb->vm_ops->set_policy) | ||
274 | ret = bb->vm_ops->set_policy(vma, new); | ||
286 | 275 | ||
287 | sysfs_put_active(attr_sd); | 276 | sysfs_put_active(attr_sd); |
288 | return ret; | 277 | return ret; |
@@ -296,13 +285,15 @@ static struct mempolicy *bin_get_policy(struct vm_area_struct *vma, | |||
296 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 285 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
297 | struct mempolicy *pol; | 286 | struct mempolicy *pol; |
298 | 287 | ||
299 | if (!bb->vm_ops || !bb->vm_ops->get_policy) | 288 | if (!bb->vm_ops) |
300 | return vma->vm_policy; | 289 | return vma->vm_policy; |
301 | 290 | ||
302 | if (!sysfs_get_active(attr_sd)) | 291 | if (!sysfs_get_active(attr_sd)) |
303 | return vma->vm_policy; | 292 | return vma->vm_policy; |
304 | 293 | ||
305 | pol = bb->vm_ops->get_policy(vma, addr); | 294 | pol = vma->vm_policy; |
295 | if (bb->vm_ops->get_policy) | ||
296 | pol = bb->vm_ops->get_policy(vma, addr); | ||
306 | 297 | ||
307 | sysfs_put_active(attr_sd); | 298 | sysfs_put_active(attr_sd); |
308 | return pol; | 299 | return pol; |
@@ -316,13 +307,15 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from, | |||
316 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 307 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
317 | int ret; | 308 | int ret; |
318 | 309 | ||
319 | if (!bb->vm_ops || !bb->vm_ops->migrate) | 310 | if (!bb->vm_ops) |
320 | return 0; | 311 | return 0; |
321 | 312 | ||
322 | if (!sysfs_get_active(attr_sd)) | 313 | if (!sysfs_get_active(attr_sd)) |
323 | return 0; | 314 | return 0; |
324 | 315 | ||
325 | ret = bb->vm_ops->migrate(vma, from, to, flags); | 316 | ret = 0; |
317 | if (bb->vm_ops->migrate) | ||
318 | ret = bb->vm_ops->migrate(vma, from, to, flags); | ||
326 | 319 | ||
327 | sysfs_put_active(attr_sd); | 320 | sysfs_put_active(attr_sd); |
328 | return ret; | 321 | return ret; |
@@ -331,7 +324,6 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from, | |||
331 | 324 | ||
332 | static const struct vm_operations_struct bin_vm_ops = { | 325 | static const struct vm_operations_struct bin_vm_ops = { |
333 | .open = bin_vma_open, | 326 | .open = bin_vma_open, |
334 | .close = bin_vma_close, | ||
335 | .fault = bin_fault, | 327 | .fault = bin_fault, |
336 | .page_mkwrite = bin_page_mkwrite, | 328 | .page_mkwrite = bin_page_mkwrite, |
337 | .access = bin_access, | 329 | .access = bin_access, |
@@ -377,6 +369,14 @@ static int mmap(struct file *file, struct vm_area_struct *vma) | |||
377 | if (bb->mmapped && bb->vm_ops != vma->vm_ops) | 369 | if (bb->mmapped && bb->vm_ops != vma->vm_ops) |
378 | goto out_put; | 370 | goto out_put; |
379 | 371 | ||
372 | /* | ||
373 | * It is not possible to successfully wrap close. | ||
374 | * So error if someone is trying to use close. | ||
375 | */ | ||
376 | rc = -EINVAL; | ||
377 | if (vma->vm_ops && vma->vm_ops->close) | ||
378 | goto out_put; | ||
379 | |||
380 | rc = 0; | 380 | rc = 0; |
381 | bb->mmapped = 1; | 381 | bb->mmapped = 1; |
382 | bb->vm_ops = vma->vm_ops; | 382 | bb->vm_ops = vma->vm_ops; |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1beaa739d0a6..da3fefe91a8f 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -340,7 +340,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
340 | char *p; | 340 | char *p; |
341 | 341 | ||
342 | p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file)); | 342 | p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file)); |
343 | if (p) | 343 | if (!IS_ERR(p)) |
344 | memmove(last_sysfs_file, p, strlen(p) + 1); | 344 | memmove(last_sysfs_file, p, strlen(p) + 1); |
345 | 345 | ||
346 | /* need attr_sd for attr and ops, its parent for kobj */ | 346 | /* need attr_sd for attr and ops, its parent for kobj */ |
@@ -593,7 +593,8 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); | |||
593 | * @mode: file permissions. | 593 | * @mode: file permissions. |
594 | * | 594 | * |
595 | */ | 595 | */ |
596 | int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | 596 | int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, |
597 | mode_t mode) | ||
597 | { | 598 | { |
598 | struct sysfs_dirent *sd; | 599 | struct sysfs_dirent *sd; |
599 | struct iattr newattrs; | 600 | struct iattr newattrs; |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 23c1e598792a..442f34ff1af8 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
@@ -148,6 +148,65 @@ void sysfs_remove_group(struct kobject * kobj, | |||
148 | sysfs_put(sd); | 148 | sysfs_put(sd); |
149 | } | 149 | } |
150 | 150 | ||
151 | /** | ||
152 | * sysfs_merge_group - merge files into a pre-existing attribute group. | ||
153 | * @kobj: The kobject containing the group. | ||
154 | * @grp: The files to create and the attribute group they belong to. | ||
155 | * | ||
156 | * This function returns an error if the group doesn't exist or any of the | ||
157 | * files already exist in that group, in which case none of the new files | ||
158 | * are created. | ||
159 | */ | ||
160 | int sysfs_merge_group(struct kobject *kobj, | ||
161 | const struct attribute_group *grp) | ||
162 | { | ||
163 | struct sysfs_dirent *dir_sd; | ||
164 | int error = 0; | ||
165 | struct attribute *const *attr; | ||
166 | int i; | ||
167 | |||
168 | if (grp) | ||
169 | dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name); | ||
170 | else | ||
171 | dir_sd = sysfs_get(kobj->sd); | ||
172 | if (!dir_sd) | ||
173 | return -ENOENT; | ||
174 | |||
175 | for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr)) | ||
176 | error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR); | ||
177 | if (error) { | ||
178 | while (--i >= 0) | ||
179 | sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name); | ||
180 | } | ||
181 | sysfs_put(dir_sd); | ||
182 | |||
183 | return error; | ||
184 | } | ||
185 | EXPORT_SYMBOL_GPL(sysfs_merge_group); | ||
186 | |||
187 | /** | ||
188 | * sysfs_unmerge_group - remove files from a pre-existing attribute group. | ||
189 | * @kobj: The kobject containing the group. | ||
190 | * @grp: The files to remove and the attribute group they belong to. | ||
191 | */ | ||
192 | void sysfs_unmerge_group(struct kobject *kobj, | ||
193 | const struct attribute_group *grp) | ||
194 | { | ||
195 | struct sysfs_dirent *dir_sd; | ||
196 | struct attribute *const *attr; | ||
197 | |||
198 | if (grp) | ||
199 | dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name); | ||
200 | else | ||
201 | dir_sd = sysfs_get(kobj->sd); | ||
202 | if (dir_sd) { | ||
203 | for (attr = grp->attrs; *attr; ++attr) | ||
204 | sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); | ||
205 | sysfs_put(dir_sd); | ||
206 | } | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(sysfs_unmerge_group); | ||
209 | |||
151 | 210 | ||
152 | EXPORT_SYMBOL_GPL(sysfs_create_group); | 211 | EXPORT_SYMBOL_GPL(sysfs_create_group); |
153 | EXPORT_SYMBOL_GPL(sysfs_update_group); | 212 | EXPORT_SYMBOL_GPL(sysfs_update_group); |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 0835a3b70e03..cffb1fd8ba33 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -122,7 +122,7 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
122 | goto out; | 122 | goto out; |
123 | 123 | ||
124 | /* this ignores size changes */ | 124 | /* this ignores size changes */ |
125 | generic_setattr(inode, iattr); | 125 | setattr_copy(inode, iattr); |
126 | 126 | ||
127 | out: | 127 | out: |
128 | mutex_unlock(&sysfs_mutex); | 128 | mutex_unlock(&sysfs_mutex); |
@@ -312,15 +312,15 @@ struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd) | |||
312 | * The sysfs_dirent serves as both an inode and a directory entry for sysfs. | 312 | * The sysfs_dirent serves as both an inode and a directory entry for sysfs. |
313 | * To prevent the sysfs inode numbers from being freed prematurely we take a | 313 | * To prevent the sysfs inode numbers from being freed prematurely we take a |
314 | * reference to sysfs_dirent from the sysfs inode. A | 314 | * reference to sysfs_dirent from the sysfs inode. A |
315 | * super_operations.delete_inode() implementation is needed to drop that | 315 | * super_operations.evict_inode() implementation is needed to drop that |
316 | * reference upon inode destruction. | 316 | * reference upon inode destruction. |
317 | */ | 317 | */ |
318 | void sysfs_delete_inode(struct inode *inode) | 318 | void sysfs_evict_inode(struct inode *inode) |
319 | { | 319 | { |
320 | struct sysfs_dirent *sd = inode->i_private; | 320 | struct sysfs_dirent *sd = inode->i_private; |
321 | 321 | ||
322 | truncate_inode_pages(&inode->i_data, 0); | 322 | truncate_inode_pages(&inode->i_data, 0); |
323 | clear_inode(inode); | 323 | end_writeback(inode); |
324 | sysfs_put(sd); | 324 | sysfs_put(sd); |
325 | } | 325 | } |
326 | 326 | ||
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 281c0c9bc39f..f2af22574c50 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -29,7 +29,7 @@ struct kmem_cache *sysfs_dir_cachep; | |||
29 | static const struct super_operations sysfs_ops = { | 29 | static const struct super_operations sysfs_ops = { |
30 | .statfs = simple_statfs, | 30 | .statfs = simple_statfs, |
31 | .drop_inode = generic_delete_inode, | 31 | .drop_inode = generic_delete_inode, |
32 | .delete_inode = sysfs_delete_inode, | 32 | .evict_inode = sysfs_evict_inode, |
33 | }; | 33 | }; |
34 | 34 | ||
35 | struct sysfs_dirent sysfs_root = { | 35 | struct sysfs_dirent sysfs_root = { |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6a13105b5594..d9be60a2e956 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -198,7 +198,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) | |||
198 | * inode.c | 198 | * inode.c |
199 | */ | 199 | */ |
200 | struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); | 200 | struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); |
201 | void sysfs_delete_inode(struct inode *inode); | 201 | void sysfs_evict_inode(struct inode *inode); |
202 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); | 202 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); |
203 | int sysfs_permission(struct inode *inode, int mask); | 203 | int sysfs_permission(struct inode *inode, int mask); |
204 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | 204 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); |