Blame view
fs/sysfs/bin.c
10.7 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
6d66f5cd2 sysfs: add copyri... |
2 |
* fs/sysfs/bin.c - sysfs binary file implementation |
1da177e4c Linux-2.6.12-rc2 |
3 4 5 6 |
* * Copyright (c) 2003 Patrick Mochel * Copyright (c) 2003 Matthew Wilcox * Copyright (c) 2004 Silicon Graphics, Inc. |
6d66f5cd2 sysfs: add copyri... |
7 8 9 10 11 12 |
* Copyright (c) 2007 SUSE Linux Products GmbH * Copyright (c) 2007 Tejun Heo <teheo@suse.de> * * This file is released under the GPLv2. * * Please see Documentation/filesystems/sysfs.txt for more information. |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 16 17 18 |
*/ #undef DEBUG #include <linux/errno.h> #include <linux/fs.h> |
995982ca7 sysfs_remove_bin_... |
19 |
#include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
20 21 22 |
#include <linux/kobject.h> #include <linux/module.h> #include <linux/slab.h> |
869512ab5 sysfs: cleanup se... |
23 |
#include <linux/mutex.h> |
e0edd3c65 sysfs: don't bloc... |
24 |
#include <linux/mm.h> |
1da177e4c Linux-2.6.12-rc2 |
25 26 27 28 |
#include <asm/uaccess.h> #include "sysfs.h" |
e0edd3c65 sysfs: don't bloc... |
29 30 31 32 33 34 35 36 |
/* * There's one bin_buffer for each open file. * * filp->private_data points to bin_buffer and * sysfs_dirent->s_bin_attr.buffers points to a the bin_buffer s * sysfs_dirent->s_bin_attr.buffers is protected by sysfs_bin_lock */ static DEFINE_MUTEX(sysfs_bin_lock); |
eb3616535 sysfs: implement ... |
37 |
struct bin_buffer { |
e0edd3c65 sysfs: don't bloc... |
38 39 40 |
struct mutex mutex; void *buffer; int mmapped; |
f0f37e2f7 const: mark struc... |
41 |
const struct vm_operations_struct *vm_ops; |
e0edd3c65 sysfs: don't bloc... |
42 43 |
struct file *file; struct hlist_node list; |
eb3616535 sysfs: implement ... |
44 |
}; |
1da177e4c Linux-2.6.12-rc2 |
45 |
static int |
2c3c8bea6 sysfs: add struct... |
46 |
fill_read(struct file *file, char *buffer, loff_t off, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
47 |
{ |
2c3c8bea6 sysfs: add struct... |
48 |
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
b1fc3d614 sysfs: make s_ele... |
49 50 |
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
0ab66088c sysfs: implement ... |
51 52 53 |
int rc; /* need attr_sd for attr, its parent for kobj */ |
e72ceb8cc sysfs: Remove sys... |
54 |
if (!sysfs_get_active(attr_sd)) |
0ab66088c sysfs: implement ... |
55 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
56 |
|
0ab66088c sysfs: implement ... |
57 58 |
rc = -EIO; if (attr->read) |
2c3c8bea6 sysfs: add struct... |
59 |
rc = attr->read(file, kobj, attr, buffer, off, count); |
1da177e4c Linux-2.6.12-rc2 |
60 |
|
e72ceb8cc sysfs: Remove sys... |
61 |
sysfs_put_active(attr_sd); |
0ab66088c sysfs: implement ... |
62 63 |
return rc; |
1da177e4c Linux-2.6.12-rc2 |
64 65 66 |
} static ssize_t |
93e3cd827 sysfs: fix error ... |
67 |
read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) |
1da177e4c Linux-2.6.12-rc2 |
68 |
{ |
eb3616535 sysfs: implement ... |
69 |
struct bin_buffer *bb = file->private_data; |
2c3c8bea6 sysfs: add struct... |
70 |
int size = file->f_path.dentry->d_inode->i_size; |
1da177e4c Linux-2.6.12-rc2 |
71 |
loff_t offs = *off; |
93e3cd827 sysfs: fix error ... |
72 |
int count = min_t(size_t, bytes, PAGE_SIZE); |
b31ca3f5d sysfs: fix deadlock |
73 |
char *temp; |
1da177e4c Linux-2.6.12-rc2 |
74 |
|
4503efd08 sysfs: fix proble... |
75 76 |
if (!bytes) return 0; |
1da177e4c Linux-2.6.12-rc2 |
77 78 79 80 81 82 |
if (size) { if (offs > size) return 0; if (offs + count > size) count = size - offs; } |
b31ca3f5d sysfs: fix deadlock |
83 84 85 |
temp = kmalloc(count, GFP_KERNEL); if (!temp) return -ENOMEM; |
eb3616535 sysfs: implement ... |
86 |
mutex_lock(&bb->mutex); |
2c3c8bea6 sysfs: add struct... |
87 |
count = fill_read(file, bb->buffer, offs, count); |
b31ca3f5d sysfs: fix deadlock |
88 89 90 91 |
if (count < 0) { mutex_unlock(&bb->mutex); goto out_free; } |
1da177e4c Linux-2.6.12-rc2 |
92 |
|
b31ca3f5d sysfs: fix deadlock |
93 94 95 96 97 |
memcpy(temp, bb->buffer, count); mutex_unlock(&bb->mutex); if (copy_to_user(userbuf, temp, count)) { |
eb3616535 sysfs: implement ... |
98 |
count = -EFAULT; |
b31ca3f5d sysfs: fix deadlock |
99 |
goto out_free; |
eb3616535 sysfs: implement ... |
100 |
} |
1da177e4c Linux-2.6.12-rc2 |
101 |
|
93e3cd827 sysfs: fix error ... |
102 103 |
pr_debug("offs = %lld, *off = %lld, count = %d ", offs, *off, count); |
1da177e4c Linux-2.6.12-rc2 |
104 105 |
*off = offs + count; |
b31ca3f5d sysfs: fix deadlock |
106 107 |
out_free: kfree(temp); |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 111 |
return count; } static int |
2c3c8bea6 sysfs: add struct... |
112 |
flush_write(struct file *file, char *buffer, loff_t offset, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
113 |
{ |
2c3c8bea6 sysfs: add struct... |
114 |
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
b1fc3d614 sysfs: make s_ele... |
115 116 |
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
0ab66088c sysfs: implement ... |
117 118 119 |
int rc; /* need attr_sd for attr, its parent for kobj */ |
e72ceb8cc sysfs: Remove sys... |
120 |
if (!sysfs_get_active(attr_sd)) |
0ab66088c sysfs: implement ... |
121 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
122 |
|
0ab66088c sysfs: implement ... |
123 124 |
rc = -EIO; if (attr->write) |
2c3c8bea6 sysfs: add struct... |
125 |
rc = attr->write(file, kobj, attr, buffer, offset, count); |
1da177e4c Linux-2.6.12-rc2 |
126 |
|
e72ceb8cc sysfs: Remove sys... |
127 |
sysfs_put_active(attr_sd); |
0ab66088c sysfs: implement ... |
128 129 |
return rc; |
1da177e4c Linux-2.6.12-rc2 |
130 |
} |
93e3cd827 sysfs: fix error ... |
131 132 |
static ssize_t write(struct file *file, const char __user *userbuf, size_t bytes, loff_t *off) |
1da177e4c Linux-2.6.12-rc2 |
133 |
{ |
eb3616535 sysfs: implement ... |
134 |
struct bin_buffer *bb = file->private_data; |
2c3c8bea6 sysfs: add struct... |
135 |
int size = file->f_path.dentry->d_inode->i_size; |
1da177e4c Linux-2.6.12-rc2 |
136 |
loff_t offs = *off; |
93e3cd827 sysfs: fix error ... |
137 |
int count = min_t(size_t, bytes, PAGE_SIZE); |
b31ca3f5d sysfs: fix deadlock |
138 |
char *temp; |
1da177e4c Linux-2.6.12-rc2 |
139 |
|
4503efd08 sysfs: fix proble... |
140 141 |
if (!bytes) return 0; |
1da177e4c Linux-2.6.12-rc2 |
142 143 144 145 146 147 |
if (size) { if (offs > size) return 0; if (offs + count > size) count = size - offs; } |
1c8542c7b sysfs: use memdup... |
148 149 150 |
temp = memdup_user(userbuf, count); if (IS_ERR(temp)) return PTR_ERR(temp); |
1da177e4c Linux-2.6.12-rc2 |
151 |
|
b31ca3f5d sysfs: fix deadlock |
152 153 154 |
mutex_lock(&bb->mutex); memcpy(bb->buffer, temp, count); |
2c3c8bea6 sysfs: add struct... |
155 |
count = flush_write(file, bb->buffer, offs, count); |
b31ca3f5d sysfs: fix deadlock |
156 |
mutex_unlock(&bb->mutex); |
1da177e4c Linux-2.6.12-rc2 |
157 158 |
if (count > 0) *off = offs + count; |
eb3616535 sysfs: implement ... |
159 |
|
d5ce5b40b Free the memory a... |
160 |
kfree(temp); |
1da177e4c Linux-2.6.12-rc2 |
161 162 |
return count; } |
e0edd3c65 sysfs: don't bloc... |
163 164 165 166 167 |
static void bin_vma_open(struct vm_area_struct *vma) { struct file *file = vma->vm_file; struct bin_buffer *bb = file->private_data; struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
38f49a513 sysfs: only acces... |
168 |
if (!bb->vm_ops) |
e0edd3c65 sysfs: don't bloc... |
169 |
return; |
e72ceb8cc sysfs: Remove sys... |
170 |
if (!sysfs_get_active(attr_sd)) |
e0edd3c65 sysfs: don't bloc... |
171 |
return; |
38f49a513 sysfs: only acces... |
172 173 |
if (bb->vm_ops->open) bb->vm_ops->open(vma); |
e0edd3c65 sysfs: don't bloc... |
174 |
|
e72ceb8cc sysfs: Remove sys... |
175 |
sysfs_put_active(attr_sd); |
e0edd3c65 sysfs: don't bloc... |
176 |
} |
e0edd3c65 sysfs: don't bloc... |
177 178 179 180 181 182 |
static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct file *file = vma->vm_file; struct bin_buffer *bb = file->private_data; struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; int ret; |
38f49a513 sysfs: only acces... |
183 |
if (!bb->vm_ops) |
e0edd3c65 sysfs: don't bloc... |
184 |
return VM_FAULT_SIGBUS; |
e72ceb8cc sysfs: Remove sys... |
185 |
if (!sysfs_get_active(attr_sd)) |
e0edd3c65 sysfs: don't bloc... |
186 |
return VM_FAULT_SIGBUS; |
38f49a513 sysfs: only acces... |
187 188 189 |
ret = VM_FAULT_SIGBUS; if (bb->vm_ops->fault) ret = bb->vm_ops->fault(vma, vmf); |
e0edd3c65 sysfs: don't bloc... |
190 |
|
e72ceb8cc sysfs: Remove sys... |
191 |
sysfs_put_active(attr_sd); |
e0edd3c65 sysfs: don't bloc... |
192 193 |
return ret; } |
851a039cc mm: page_mkwrite ... |
194 |
static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
e0edd3c65 sysfs: don't bloc... |
195 196 197 198 199 |
{ struct file *file = vma->vm_file; struct bin_buffer *bb = file->private_data; struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; int ret; |
095160aee sysfs: fix some b... |
200 |
if (!bb->vm_ops) |
851a039cc mm: page_mkwrite ... |
201 |
return VM_FAULT_SIGBUS; |
e0edd3c65 sysfs: don't bloc... |
202 |
|
e72ceb8cc sysfs: Remove sys... |
203 |
if (!sysfs_get_active(attr_sd)) |
851a039cc mm: page_mkwrite ... |
204 |
return VM_FAULT_SIGBUS; |
e0edd3c65 sysfs: don't bloc... |
205 |
|
38f49a513 sysfs: only acces... |
206 207 208 |
ret = 0; if (bb->vm_ops->page_mkwrite) ret = bb->vm_ops->page_mkwrite(vma, vmf); |
e0edd3c65 sysfs: don't bloc... |
209 |
|
e72ceb8cc sysfs: Remove sys... |
210 |
sysfs_put_active(attr_sd); |
e0edd3c65 sysfs: don't bloc... |
211 212 213 214 215 216 217 218 219 220 |
return ret; } static int bin_access(struct vm_area_struct *vma, unsigned long addr, void *buf, int len, int write) { struct file *file = vma->vm_file; struct bin_buffer *bb = file->private_data; struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; int ret; |
38f49a513 sysfs: only acces... |
221 |
if (!bb->vm_ops) |
e0edd3c65 sysfs: don't bloc... |
222 |
return -EINVAL; |
e72ceb8cc sysfs: Remove sys... |
223 |
if (!sysfs_get_active(attr_sd)) |
e0edd3c65 sysfs: don't bloc... |
224 |
return -EINVAL; |
38f49a513 sysfs: only acces... |
225 226 227 |
ret = -EINVAL; if (bb->vm_ops->access) ret = bb->vm_ops->access(vma, addr, buf, len, write); |
e0edd3c65 sysfs: don't bloc... |
228 |
|
e72ceb8cc sysfs: Remove sys... |
229 |
sysfs_put_active(attr_sd); |
e0edd3c65 sysfs: don't bloc... |
230 231 |
return ret; } |
095160aee sysfs: fix some b... |
232 233 234 235 236 237 238 |
#ifdef CONFIG_NUMA static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new) { struct file *file = vma->vm_file; struct bin_buffer *bb = file->private_data; struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; int ret; |
38f49a513 sysfs: only acces... |
239 |
if (!bb->vm_ops) |
095160aee sysfs: fix some b... |
240 |
return 0; |
e72ceb8cc sysfs: Remove sys... |
241 |
if (!sysfs_get_active(attr_sd)) |
095160aee sysfs: fix some b... |
242 |
return -EINVAL; |
38f49a513 sysfs: only acces... |
243 244 245 |
ret = 0; if (bb->vm_ops->set_policy) ret = bb->vm_ops->set_policy(vma, new); |
095160aee sysfs: fix some b... |
246 |
|
e72ceb8cc sysfs: Remove sys... |
247 |
sysfs_put_active(attr_sd); |
095160aee sysfs: fix some b... |
248 249 250 251 252 253 254 255 256 257 |
return ret; } static struct mempolicy *bin_get_policy(struct vm_area_struct *vma, unsigned long addr) { struct file *file = vma->vm_file; struct bin_buffer *bb = file->private_data; struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct mempolicy *pol; |
38f49a513 sysfs: only acces... |
258 |
if (!bb->vm_ops) |
095160aee sysfs: fix some b... |
259 |
return vma->vm_policy; |
e72ceb8cc sysfs: Remove sys... |
260 |
if (!sysfs_get_active(attr_sd)) |
095160aee sysfs: fix some b... |
261 |
return vma->vm_policy; |
38f49a513 sysfs: only acces... |
262 263 264 |
pol = vma->vm_policy; if (bb->vm_ops->get_policy) pol = bb->vm_ops->get_policy(vma, addr); |
095160aee sysfs: fix some b... |
265 |
|
e72ceb8cc sysfs: Remove sys... |
266 |
sysfs_put_active(attr_sd); |
095160aee sysfs: fix some b... |
267 268 269 270 271 272 273 274 275 276 |
return pol; } static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from, const nodemask_t *to, unsigned long flags) { struct file *file = vma->vm_file; struct bin_buffer *bb = file->private_data; struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; int ret; |
38f49a513 sysfs: only acces... |
277 |
if (!bb->vm_ops) |
095160aee sysfs: fix some b... |
278 |
return 0; |
e72ceb8cc sysfs: Remove sys... |
279 |
if (!sysfs_get_active(attr_sd)) |
095160aee sysfs: fix some b... |
280 |
return 0; |
38f49a513 sysfs: only acces... |
281 282 283 |
ret = 0; if (bb->vm_ops->migrate) ret = bb->vm_ops->migrate(vma, from, to, flags); |
095160aee sysfs: fix some b... |
284 |
|
e72ceb8cc sysfs: Remove sys... |
285 |
sysfs_put_active(attr_sd); |
095160aee sysfs: fix some b... |
286 287 288 |
return ret; } #endif |
f0f37e2f7 const: mark struc... |
289 |
static const struct vm_operations_struct bin_vm_ops = { |
e0edd3c65 sysfs: don't bloc... |
290 |
.open = bin_vma_open, |
e0edd3c65 sysfs: don't bloc... |
291 292 293 |
.fault = bin_fault, .page_mkwrite = bin_page_mkwrite, .access = bin_access, |
095160aee sysfs: fix some b... |
294 295 296 297 298 |
#ifdef CONFIG_NUMA .set_policy = bin_set_policy, .get_policy = bin_get_policy, .migrate = bin_migrate, #endif |
e0edd3c65 sysfs: don't bloc... |
299 |
}; |
1da177e4c Linux-2.6.12-rc2 |
300 301 |
static int mmap(struct file *file, struct vm_area_struct *vma) { |
eb3616535 sysfs: implement ... |
302 |
struct bin_buffer *bb = file->private_data; |
3e5190380 sysfs: make sysfs... |
303 |
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
b1fc3d614 sysfs: make s_ele... |
304 305 |
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
eb3616535 sysfs: implement ... |
306 |
int rc; |
1da177e4c Linux-2.6.12-rc2 |
307 |
|
eb3616535 sysfs: implement ... |
308 |
mutex_lock(&bb->mutex); |
0ab66088c sysfs: implement ... |
309 310 |
/* need attr_sd for attr, its parent for kobj */ |
e0edd3c65 sysfs: don't bloc... |
311 |
rc = -ENODEV; |
e72ceb8cc sysfs: Remove sys... |
312 |
if (!sysfs_get_active(attr_sd)) |
e0edd3c65 sysfs: don't bloc... |
313 |
goto out_unlock; |
0ab66088c sysfs: implement ... |
314 315 |
rc = -EINVAL; |
e0edd3c65 sysfs: don't bloc... |
316 317 |
if (!attr->mmap) goto out_put; |
0ab66088c sysfs: implement ... |
318 |
|
2c3c8bea6 sysfs: add struct... |
319 |
rc = attr->mmap(file, kobj, attr, vma); |
e0edd3c65 sysfs: don't bloc... |
320 321 |
if (rc) goto out_put; |
0ab66088c sysfs: implement ... |
322 |
|
095160aee sysfs: fix some b... |
323 324 325 326 327 328 |
/* * PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup() * to satisfy versions of X which crash if the mmap fails: that * substitutes a new vm_file, and we don't then want bin_vm_ops. */ if (vma->vm_file != file) |
e0edd3c65 sysfs: don't bloc... |
329 |
goto out_put; |
e0edd3c65 sysfs: don't bloc... |
330 |
rc = -EINVAL; |
095160aee sysfs: fix some b... |
331 |
if (bb->mmapped && bb->vm_ops != vma->vm_ops) |
e0edd3c65 sysfs: don't bloc... |
332 |
goto out_put; |
e0edd3c65 sysfs: don't bloc... |
333 |
|
a6849fa1f sysfs: Fail bin f... |
334 335 336 337 338 339 340 |
/* * It is not possible to successfully wrap close. * So error if someone is trying to use close. */ rc = -EINVAL; if (vma->vm_ops && vma->vm_ops->close) goto out_put; |
e0edd3c65 sysfs: don't bloc... |
341 342 |
rc = 0; bb->mmapped = 1; |
095160aee sysfs: fix some b... |
343 344 |
bb->vm_ops = vma->vm_ops; vma->vm_ops = &bin_vm_ops; |
e0edd3c65 sysfs: don't bloc... |
345 |
out_put: |
e72ceb8cc sysfs: Remove sys... |
346 |
sysfs_put_active(attr_sd); |
e0edd3c65 sysfs: don't bloc... |
347 |
out_unlock: |
eb3616535 sysfs: implement ... |
348 349 350 |
mutex_unlock(&bb->mutex); return rc; |
1da177e4c Linux-2.6.12-rc2 |
351 352 353 354 |
} static int open(struct inode * inode, struct file * file) { |
3e5190380 sysfs: make sysfs... |
355 |
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
b1fc3d614 sysfs: make s_ele... |
356 |
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; |
eb3616535 sysfs: implement ... |
357 |
struct bin_buffer *bb = NULL; |
0ab66088c sysfs: implement ... |
358 |
int error; |
1da177e4c Linux-2.6.12-rc2 |
359 |
|
078ce6409 sysfs: make bin a... |
360 |
/* binary file operations requires both @sd and its parent */ |
e72ceb8cc sysfs: Remove sys... |
361 |
if (!sysfs_get_active(attr_sd)) |
0ab66088c sysfs: implement ... |
362 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
363 |
|
1da177e4c Linux-2.6.12-rc2 |
364 365 |
error = -EACCES; if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap)) |
7b595756e sysfs: kill unnec... |
366 |
goto err_out; |
1da177e4c Linux-2.6.12-rc2 |
367 |
if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap)) |
7b595756e sysfs: kill unnec... |
368 |
goto err_out; |
1da177e4c Linux-2.6.12-rc2 |
369 370 |
error = -ENOMEM; |
eb3616535 sysfs: implement ... |
371 372 |
bb = kzalloc(sizeof(*bb), GFP_KERNEL); if (!bb) |
7b595756e sysfs: kill unnec... |
373 |
goto err_out; |
1da177e4c Linux-2.6.12-rc2 |
374 |
|
eb3616535 sysfs: implement ... |
375 376 |
bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!bb->buffer) |
7b595756e sysfs: kill unnec... |
377 |
goto err_out; |
eb3616535 sysfs: implement ... |
378 379 |
mutex_init(&bb->mutex); |
e0edd3c65 sysfs: don't bloc... |
380 |
bb->file = file; |
eb3616535 sysfs: implement ... |
381 |
file->private_data = bb; |
e0edd3c65 sysfs: don't bloc... |
382 383 384 |
mutex_lock(&sysfs_bin_lock); hlist_add_head(&bb->list, &attr_sd->s_bin_attr.buffers); mutex_unlock(&sysfs_bin_lock); |
078ce6409 sysfs: make bin a... |
385 |
/* open succeeded, put active references */ |
e72ceb8cc sysfs: Remove sys... |
386 |
sysfs_put_active(attr_sd); |
0ab66088c sysfs: implement ... |
387 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
388 |
|
7b595756e sysfs: kill unnec... |
389 |
err_out: |
e72ceb8cc sysfs: Remove sys... |
390 |
sysfs_put_active(attr_sd); |
0ab66088c sysfs: implement ... |
391 |
kfree(bb); |
1da177e4c Linux-2.6.12-rc2 |
392 393 394 395 396 |
return error; } static int release(struct inode * inode, struct file * file) { |
eb3616535 sysfs: implement ... |
397 |
struct bin_buffer *bb = file->private_data; |
1da177e4c Linux-2.6.12-rc2 |
398 |
|
e0edd3c65 sysfs: don't bloc... |
399 400 401 |
mutex_lock(&sysfs_bin_lock); hlist_del(&bb->list); mutex_unlock(&sysfs_bin_lock); |
eb3616535 sysfs: implement ... |
402 403 |
kfree(bb->buffer); kfree(bb); |
1da177e4c Linux-2.6.12-rc2 |
404 405 |
return 0; } |
4b6f5d20b [PATCH] Make most... |
406 |
const struct file_operations bin_fops = { |
1da177e4c Linux-2.6.12-rc2 |
407 408 409 410 411 412 413 |
.read = read, .write = write, .mmap = mmap, .llseek = generic_file_llseek, .open = open, .release = release, }; |
e0edd3c65 sysfs: don't bloc... |
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
void unmap_bin_file(struct sysfs_dirent *attr_sd) { struct bin_buffer *bb; struct hlist_node *tmp; if (sysfs_type(attr_sd) != SYSFS_KOBJ_BIN_ATTR) return; mutex_lock(&sysfs_bin_lock); hlist_for_each_entry(bb, tmp, &attr_sd->s_bin_attr.buffers, list) { struct inode *inode = bb->file->f_path.dentry->d_inode; unmap_mapping_range(inode->i_mapping, 0, 0, 1); } mutex_unlock(&sysfs_bin_lock); } |
1da177e4c Linux-2.6.12-rc2 |
433 434 435 436 |
/** * sysfs_create_bin_file - create binary file for object. * @kobj: object. * @attr: attribute descriptor. |
1da177e4c Linux-2.6.12-rc2 |
437 |
*/ |
66ecb92be Driver core: bin_... |
438 439 |
int sysfs_create_bin_file(struct kobject *kobj, const struct bin_attribute *attr) |
1da177e4c Linux-2.6.12-rc2 |
440 |
{ |
608e266a2 sysfs: make kobj ... |
441 |
BUG_ON(!kobj || !kobj->sd || !attr); |
1da177e4c Linux-2.6.12-rc2 |
442 |
|
608e266a2 sysfs: make kobj ... |
443 |
return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR); |
1da177e4c Linux-2.6.12-rc2 |
444 445 446 447 448 449 450 |
} /** * sysfs_remove_bin_file - remove binary file for object. * @kobj: object. * @attr: attribute descriptor. |
1da177e4c Linux-2.6.12-rc2 |
451 |
*/ |
66ecb92be Driver core: bin_... |
452 453 |
void sysfs_remove_bin_file(struct kobject *kobj, const struct bin_attribute *attr) |
1da177e4c Linux-2.6.12-rc2 |
454 |
{ |
3ff195b01 sysfs: Implement ... |
455 |
sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name); |
1da177e4c Linux-2.6.12-rc2 |
456 457 458 459 |
} EXPORT_SYMBOL_GPL(sysfs_create_bin_file); EXPORT_SYMBOL_GPL(sysfs_remove_bin_file); |