diff options
Diffstat (limited to 'fs/configfs/file.c')
-rw-r--r-- | fs/configfs/file.c | 280 |
1 files changed, 140 insertions, 140 deletions
diff --git a/fs/configfs/file.c b/fs/configfs/file.c index 61e4db4390a1..fb65b706cc0d 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c | |||
@@ -39,40 +39,44 @@ struct configfs_buffer { | |||
39 | bool write_in_progress; | 39 | bool write_in_progress; |
40 | char *bin_buffer; | 40 | char *bin_buffer; |
41 | int bin_buffer_size; | 41 | int bin_buffer_size; |
42 | int cb_max_size; | ||
43 | struct config_item *item; | ||
44 | struct module *owner; | ||
45 | union { | ||
46 | struct configfs_attribute *attr; | ||
47 | struct configfs_bin_attribute *bin_attr; | ||
48 | }; | ||
42 | }; | 49 | }; |
43 | 50 | ||
51 | static inline struct configfs_fragment *to_frag(struct file *file) | ||
52 | { | ||
53 | struct configfs_dirent *sd = file->f_path.dentry->d_fsdata; | ||
44 | 54 | ||
45 | /** | 55 | return sd->s_frag; |
46 | * fill_read_buffer - allocate and fill buffer from item. | 56 | } |
47 | * @dentry: dentry pointer. | 57 | |
48 | * @buffer: data buffer for file. | 58 | static int fill_read_buffer(struct file *file, struct configfs_buffer *buffer) |
49 | * | ||
50 | * Allocate @buffer->page, if it hasn't been already, then call the | ||
51 | * config_item's show() method to fill the buffer with this attribute's | ||
52 | * data. | ||
53 | * This is called only once, on the file's first read. | ||
54 | */ | ||
55 | static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buffer) | ||
56 | { | 59 | { |
57 | struct configfs_attribute * attr = to_attr(dentry); | 60 | struct configfs_fragment *frag = to_frag(file); |
58 | struct config_item * item = to_item(dentry->d_parent); | 61 | ssize_t count = -ENOENT; |
59 | int ret = 0; | ||
60 | ssize_t count; | ||
61 | 62 | ||
62 | if (!buffer->page) | 63 | if (!buffer->page) |
63 | buffer->page = (char *) get_zeroed_page(GFP_KERNEL); | 64 | buffer->page = (char *) get_zeroed_page(GFP_KERNEL); |
64 | if (!buffer->page) | 65 | if (!buffer->page) |
65 | return -ENOMEM; | 66 | return -ENOMEM; |
66 | 67 | ||
67 | count = attr->show(item, buffer->page); | 68 | down_read(&frag->frag_sem); |
68 | 69 | if (!frag->frag_dead) | |
69 | BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE); | 70 | count = buffer->attr->show(buffer->item, buffer->page); |
70 | if (count >= 0) { | 71 | up_read(&frag->frag_sem); |
71 | buffer->needs_read_fill = 0; | 72 | |
72 | buffer->count = count; | 73 | if (count < 0) |
73 | } else | 74 | return count; |
74 | ret = count; | 75 | if (WARN_ON_ONCE(count > (ssize_t)SIMPLE_ATTR_SIZE)) |
75 | return ret; | 76 | return -EIO; |
77 | buffer->needs_read_fill = 0; | ||
78 | buffer->count = count; | ||
79 | return 0; | ||
76 | } | 80 | } |
77 | 81 | ||
78 | /** | 82 | /** |
@@ -97,12 +101,13 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf | |||
97 | static ssize_t | 101 | static ssize_t |
98 | configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 102 | configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) |
99 | { | 103 | { |
100 | struct configfs_buffer * buffer = file->private_data; | 104 | struct configfs_buffer *buffer = file->private_data; |
101 | ssize_t retval = 0; | 105 | ssize_t retval = 0; |
102 | 106 | ||
103 | mutex_lock(&buffer->mutex); | 107 | mutex_lock(&buffer->mutex); |
104 | if (buffer->needs_read_fill) { | 108 | if (buffer->needs_read_fill) { |
105 | if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) | 109 | retval = fill_read_buffer(file, buffer); |
110 | if (retval) | ||
106 | goto out; | 111 | goto out; |
107 | } | 112 | } |
108 | pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", | 113 | pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", |
@@ -138,10 +143,8 @@ static ssize_t | |||
138 | configfs_read_bin_file(struct file *file, char __user *buf, | 143 | configfs_read_bin_file(struct file *file, char __user *buf, |
139 | size_t count, loff_t *ppos) | 144 | size_t count, loff_t *ppos) |
140 | { | 145 | { |
146 | struct configfs_fragment *frag = to_frag(file); | ||
141 | struct configfs_buffer *buffer = file->private_data; | 147 | struct configfs_buffer *buffer = file->private_data; |
142 | struct dentry *dentry = file->f_path.dentry; | ||
143 | struct config_item *item = to_item(dentry->d_parent); | ||
144 | struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); | ||
145 | ssize_t retval = 0; | 148 | ssize_t retval = 0; |
146 | ssize_t len = min_t(size_t, count, PAGE_SIZE); | 149 | ssize_t len = min_t(size_t, count, PAGE_SIZE); |
147 | 150 | ||
@@ -156,14 +159,19 @@ configfs_read_bin_file(struct file *file, char __user *buf, | |||
156 | 159 | ||
157 | if (buffer->needs_read_fill) { | 160 | if (buffer->needs_read_fill) { |
158 | /* perform first read with buf == NULL to get extent */ | 161 | /* perform first read with buf == NULL to get extent */ |
159 | len = bin_attr->read(item, NULL, 0); | 162 | down_read(&frag->frag_sem); |
163 | if (!frag->frag_dead) | ||
164 | len = buffer->bin_attr->read(buffer->item, NULL, 0); | ||
165 | else | ||
166 | len = -ENOENT; | ||
167 | up_read(&frag->frag_sem); | ||
160 | if (len <= 0) { | 168 | if (len <= 0) { |
161 | retval = len; | 169 | retval = len; |
162 | goto out; | 170 | goto out; |
163 | } | 171 | } |
164 | 172 | ||
165 | /* do not exceed the maximum value */ | 173 | /* do not exceed the maximum value */ |
166 | if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) { | 174 | if (buffer->cb_max_size && len > buffer->cb_max_size) { |
167 | retval = -EFBIG; | 175 | retval = -EFBIG; |
168 | goto out; | 176 | goto out; |
169 | } | 177 | } |
@@ -176,7 +184,13 @@ configfs_read_bin_file(struct file *file, char __user *buf, | |||
176 | buffer->bin_buffer_size = len; | 184 | buffer->bin_buffer_size = len; |
177 | 185 | ||
178 | /* perform second read to fill buffer */ | 186 | /* perform second read to fill buffer */ |
179 | len = bin_attr->read(item, buffer->bin_buffer, len); | 187 | down_read(&frag->frag_sem); |
188 | if (!frag->frag_dead) | ||
189 | len = buffer->bin_attr->read(buffer->item, | ||
190 | buffer->bin_buffer, len); | ||
191 | else | ||
192 | len = -ENOENT; | ||
193 | up_read(&frag->frag_sem); | ||
180 | if (len < 0) { | 194 | if (len < 0) { |
181 | retval = len; | 195 | retval = len; |
182 | vfree(buffer->bin_buffer); | 196 | vfree(buffer->bin_buffer); |
@@ -226,25 +240,17 @@ fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size | |||
226 | return error ? -EFAULT : count; | 240 | return error ? -EFAULT : count; |
227 | } | 241 | } |
228 | 242 | ||
229 | |||
230 | /** | ||
231 | * flush_write_buffer - push buffer to config_item. | ||
232 | * @dentry: dentry to the attribute | ||
233 | * @buffer: data buffer for file. | ||
234 | * @count: number of bytes | ||
235 | * | ||
236 | * Get the correct pointers for the config_item and the attribute we're | ||
237 | * dealing with, then call the store() method for the attribute, | ||
238 | * passing the buffer that we acquired in fill_write_buffer(). | ||
239 | */ | ||
240 | |||
241 | static int | 243 | static int |
242 | flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count) | 244 | flush_write_buffer(struct file *file, struct configfs_buffer *buffer, size_t count) |
243 | { | 245 | { |
244 | struct configfs_attribute * attr = to_attr(dentry); | 246 | struct configfs_fragment *frag = to_frag(file); |
245 | struct config_item * item = to_item(dentry->d_parent); | 247 | int res = -ENOENT; |
246 | 248 | ||
247 | return attr->store(item, buffer->page, count); | 249 | down_read(&frag->frag_sem); |
250 | if (!frag->frag_dead) | ||
251 | res = buffer->attr->store(buffer->item, buffer->page, count); | ||
252 | up_read(&frag->frag_sem); | ||
253 | return res; | ||
248 | } | 254 | } |
249 | 255 | ||
250 | 256 | ||
@@ -268,13 +274,13 @@ flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size | |||
268 | static ssize_t | 274 | static ssize_t |
269 | configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 275 | configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) |
270 | { | 276 | { |
271 | struct configfs_buffer * buffer = file->private_data; | 277 | struct configfs_buffer *buffer = file->private_data; |
272 | ssize_t len; | 278 | ssize_t len; |
273 | 279 | ||
274 | mutex_lock(&buffer->mutex); | 280 | mutex_lock(&buffer->mutex); |
275 | len = fill_write_buffer(buffer, buf, count); | 281 | len = fill_write_buffer(buffer, buf, count); |
276 | if (len > 0) | 282 | if (len > 0) |
277 | len = flush_write_buffer(file->f_path.dentry, buffer, len); | 283 | len = flush_write_buffer(file, buffer, len); |
278 | if (len > 0) | 284 | if (len > 0) |
279 | *ppos += len; | 285 | *ppos += len; |
280 | mutex_unlock(&buffer->mutex); | 286 | mutex_unlock(&buffer->mutex); |
@@ -299,8 +305,6 @@ configfs_write_bin_file(struct file *file, const char __user *buf, | |||
299 | size_t count, loff_t *ppos) | 305 | size_t count, loff_t *ppos) |
300 | { | 306 | { |
301 | struct configfs_buffer *buffer = file->private_data; | 307 | struct configfs_buffer *buffer = file->private_data; |
302 | struct dentry *dentry = file->f_path.dentry; | ||
303 | struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); | ||
304 | void *tbuf = NULL; | 308 | void *tbuf = NULL; |
305 | ssize_t len; | 309 | ssize_t len; |
306 | 310 | ||
@@ -316,8 +320,8 @@ configfs_write_bin_file(struct file *file, const char __user *buf, | |||
316 | /* buffer grows? */ | 320 | /* buffer grows? */ |
317 | if (*ppos + count > buffer->bin_buffer_size) { | 321 | if (*ppos + count > buffer->bin_buffer_size) { |
318 | 322 | ||
319 | if (bin_attr->cb_max_size && | 323 | if (buffer->cb_max_size && |
320 | *ppos + count > bin_attr->cb_max_size) { | 324 | *ppos + count > buffer->cb_max_size) { |
321 | len = -EFBIG; | 325 | len = -EFBIG; |
322 | goto out; | 326 | goto out; |
323 | } | 327 | } |
@@ -349,31 +353,51 @@ out: | |||
349 | return len; | 353 | return len; |
350 | } | 354 | } |
351 | 355 | ||
352 | static int check_perm(struct inode * inode, struct file * file, int type) | 356 | static int __configfs_open_file(struct inode *inode, struct file *file, int type) |
353 | { | 357 | { |
354 | struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent); | 358 | struct dentry *dentry = file->f_path.dentry; |
355 | struct configfs_attribute * attr = to_attr(file->f_path.dentry); | 359 | struct configfs_fragment *frag = to_frag(file); |
356 | struct configfs_bin_attribute *bin_attr = NULL; | 360 | struct configfs_attribute *attr; |
357 | struct configfs_buffer * buffer; | 361 | struct configfs_buffer *buffer; |
358 | struct configfs_item_operations * ops = NULL; | 362 | int error; |
359 | int error = 0; | ||
360 | 363 | ||
361 | if (!item || !attr) | 364 | error = -ENOMEM; |
362 | goto Einval; | 365 | buffer = kzalloc(sizeof(struct configfs_buffer), GFP_KERNEL); |
366 | if (!buffer) | ||
367 | goto out; | ||
363 | 368 | ||
364 | if (type & CONFIGFS_ITEM_BIN_ATTR) | 369 | error = -ENOENT; |
365 | bin_attr = to_bin_attr(file->f_path.dentry); | 370 | down_read(&frag->frag_sem); |
371 | if (unlikely(frag->frag_dead)) | ||
372 | goto out_free_buffer; | ||
366 | 373 | ||
367 | /* Grab the module reference for this attribute if we have one */ | 374 | error = -EINVAL; |
368 | if (!try_module_get(attr->ca_owner)) { | 375 | buffer->item = to_item(dentry->d_parent); |
369 | error = -ENODEV; | 376 | if (!buffer->item) |
370 | goto Done; | 377 | goto out_free_buffer; |
378 | |||
379 | attr = to_attr(dentry); | ||
380 | if (!attr) | ||
381 | goto out_put_item; | ||
382 | |||
383 | if (type & CONFIGFS_ITEM_BIN_ATTR) { | ||
384 | buffer->bin_attr = to_bin_attr(dentry); | ||
385 | buffer->cb_max_size = buffer->bin_attr->cb_max_size; | ||
386 | } else { | ||
387 | buffer->attr = attr; | ||
371 | } | 388 | } |
372 | 389 | ||
373 | if (item->ci_type) | 390 | buffer->owner = attr->ca_owner; |
374 | ops = item->ci_type->ct_item_ops; | 391 | /* Grab the module reference for this attribute if we have one */ |
375 | else | 392 | error = -ENODEV; |
376 | goto Eaccess; | 393 | if (!try_module_get(buffer->owner)) |
394 | goto out_put_item; | ||
395 | |||
396 | error = -EACCES; | ||
397 | if (!buffer->item->ci_type) | ||
398 | goto out_put_module; | ||
399 | |||
400 | buffer->ops = buffer->item->ci_type->ct_item_ops; | ||
377 | 401 | ||
378 | /* File needs write support. | 402 | /* File needs write support. |
379 | * The inode's perms must say it's ok, | 403 | * The inode's perms must say it's ok, |
@@ -381,13 +405,11 @@ static int check_perm(struct inode * inode, struct file * file, int type) | |||
381 | */ | 405 | */ |
382 | if (file->f_mode & FMODE_WRITE) { | 406 | if (file->f_mode & FMODE_WRITE) { |
383 | if (!(inode->i_mode & S_IWUGO)) | 407 | if (!(inode->i_mode & S_IWUGO)) |
384 | goto Eaccess; | 408 | goto out_put_module; |
385 | |||
386 | if ((type & CONFIGFS_ITEM_ATTR) && !attr->store) | 409 | if ((type & CONFIGFS_ITEM_ATTR) && !attr->store) |
387 | goto Eaccess; | 410 | goto out_put_module; |
388 | 411 | if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->write) | |
389 | if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->write) | 412 | goto out_put_module; |
390 | goto Eaccess; | ||
391 | } | 413 | } |
392 | 414 | ||
393 | /* File needs read support. | 415 | /* File needs read support. |
@@ -396,92 +418,72 @@ static int check_perm(struct inode * inode, struct file * file, int type) | |||
396 | */ | 418 | */ |
397 | if (file->f_mode & FMODE_READ) { | 419 | if (file->f_mode & FMODE_READ) { |
398 | if (!(inode->i_mode & S_IRUGO)) | 420 | if (!(inode->i_mode & S_IRUGO)) |
399 | goto Eaccess; | 421 | goto out_put_module; |
400 | |||
401 | if ((type & CONFIGFS_ITEM_ATTR) && !attr->show) | 422 | if ((type & CONFIGFS_ITEM_ATTR) && !attr->show) |
402 | goto Eaccess; | 423 | goto out_put_module; |
403 | 424 | if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->read) | |
404 | if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->read) | 425 | goto out_put_module; |
405 | goto Eaccess; | ||
406 | } | 426 | } |
407 | 427 | ||
408 | /* No error? Great, allocate a buffer for the file, and store it | ||
409 | * it in file->private_data for easy access. | ||
410 | */ | ||
411 | buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL); | ||
412 | if (!buffer) { | ||
413 | error = -ENOMEM; | ||
414 | goto Enomem; | ||
415 | } | ||
416 | mutex_init(&buffer->mutex); | 428 | mutex_init(&buffer->mutex); |
417 | buffer->needs_read_fill = 1; | 429 | buffer->needs_read_fill = 1; |
418 | buffer->read_in_progress = false; | 430 | buffer->read_in_progress = false; |
419 | buffer->write_in_progress = false; | 431 | buffer->write_in_progress = false; |
420 | buffer->ops = ops; | ||
421 | file->private_data = buffer; | 432 | file->private_data = buffer; |
422 | goto Done; | 433 | up_read(&frag->frag_sem); |
434 | return 0; | ||
423 | 435 | ||
424 | Einval: | 436 | out_put_module: |
425 | error = -EINVAL; | 437 | module_put(buffer->owner); |
426 | goto Done; | 438 | out_put_item: |
427 | Eaccess: | 439 | config_item_put(buffer->item); |
428 | error = -EACCES; | 440 | out_free_buffer: |
429 | Enomem: | 441 | up_read(&frag->frag_sem); |
430 | module_put(attr->ca_owner); | 442 | kfree(buffer); |
431 | Done: | 443 | out: |
432 | if (error && item) | ||
433 | config_item_put(item); | ||
434 | return error; | 444 | return error; |
435 | } | 445 | } |
436 | 446 | ||
437 | static int configfs_release(struct inode *inode, struct file *filp) | 447 | static int configfs_release(struct inode *inode, struct file *filp) |
438 | { | 448 | { |
439 | struct config_item * item = to_item(filp->f_path.dentry->d_parent); | 449 | struct configfs_buffer *buffer = filp->private_data; |
440 | struct configfs_attribute * attr = to_attr(filp->f_path.dentry); | 450 | |
441 | struct module * owner = attr->ca_owner; | 451 | module_put(buffer->owner); |
442 | struct configfs_buffer * buffer = filp->private_data; | 452 | if (buffer->page) |
443 | 453 | free_page((unsigned long)buffer->page); | |
444 | if (item) | 454 | mutex_destroy(&buffer->mutex); |
445 | config_item_put(item); | 455 | kfree(buffer); |
446 | /* After this point, attr should not be accessed. */ | ||
447 | module_put(owner); | ||
448 | |||
449 | if (buffer) { | ||
450 | if (buffer->page) | ||
451 | free_page((unsigned long)buffer->page); | ||
452 | mutex_destroy(&buffer->mutex); | ||
453 | kfree(buffer); | ||
454 | } | ||
455 | return 0; | 456 | return 0; |
456 | } | 457 | } |
457 | 458 | ||
458 | static int configfs_open_file(struct inode *inode, struct file *filp) | 459 | static int configfs_open_file(struct inode *inode, struct file *filp) |
459 | { | 460 | { |
460 | return check_perm(inode, filp, CONFIGFS_ITEM_ATTR); | 461 | return __configfs_open_file(inode, filp, CONFIGFS_ITEM_ATTR); |
461 | } | 462 | } |
462 | 463 | ||
463 | static int configfs_open_bin_file(struct inode *inode, struct file *filp) | 464 | static int configfs_open_bin_file(struct inode *inode, struct file *filp) |
464 | { | 465 | { |
465 | return check_perm(inode, filp, CONFIGFS_ITEM_BIN_ATTR); | 466 | return __configfs_open_file(inode, filp, CONFIGFS_ITEM_BIN_ATTR); |
466 | } | 467 | } |
467 | 468 | ||
468 | static int configfs_release_bin_file(struct inode *inode, struct file *filp) | 469 | static int configfs_release_bin_file(struct inode *inode, struct file *file) |
469 | { | 470 | { |
470 | struct configfs_buffer *buffer = filp->private_data; | 471 | struct configfs_buffer *buffer = file->private_data; |
471 | struct dentry *dentry = filp->f_path.dentry; | ||
472 | struct config_item *item = to_item(dentry->d_parent); | ||
473 | struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); | ||
474 | ssize_t len = 0; | ||
475 | int ret; | ||
476 | 472 | ||
477 | buffer->read_in_progress = false; | 473 | buffer->read_in_progress = false; |
478 | 474 | ||
479 | if (buffer->write_in_progress) { | 475 | if (buffer->write_in_progress) { |
476 | struct configfs_fragment *frag = to_frag(file); | ||
480 | buffer->write_in_progress = false; | 477 | buffer->write_in_progress = false; |
481 | 478 | ||
482 | len = bin_attr->write(item, buffer->bin_buffer, | 479 | down_read(&frag->frag_sem); |
483 | buffer->bin_buffer_size); | 480 | if (!frag->frag_dead) { |
484 | 481 | /* result of ->release() is ignored */ | |
482 | buffer->bin_attr->write(buffer->item, | ||
483 | buffer->bin_buffer, | ||
484 | buffer->bin_buffer_size); | ||
485 | } | ||
486 | up_read(&frag->frag_sem); | ||
485 | /* vfree on NULL is safe */ | 487 | /* vfree on NULL is safe */ |
486 | vfree(buffer->bin_buffer); | 488 | vfree(buffer->bin_buffer); |
487 | buffer->bin_buffer = NULL; | 489 | buffer->bin_buffer = NULL; |
@@ -489,10 +491,8 @@ static int configfs_release_bin_file(struct inode *inode, struct file *filp) | |||
489 | buffer->needs_read_fill = 1; | 491 | buffer->needs_read_fill = 1; |
490 | } | 492 | } |
491 | 493 | ||
492 | ret = configfs_release(inode, filp); | 494 | configfs_release(inode, file); |
493 | if (len < 0) | 495 | return 0; |
494 | return len; | ||
495 | return ret; | ||
496 | } | 496 | } |
497 | 497 | ||
498 | 498 | ||
@@ -527,7 +527,7 @@ int configfs_create_file(struct config_item * item, const struct configfs_attrib | |||
527 | 527 | ||
528 | inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL); | 528 | inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL); |
529 | error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, | 529 | error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, |
530 | CONFIGFS_ITEM_ATTR); | 530 | CONFIGFS_ITEM_ATTR, parent_sd->s_frag); |
531 | inode_unlock(d_inode(dir)); | 531 | inode_unlock(d_inode(dir)); |
532 | 532 | ||
533 | return error; | 533 | return error; |
@@ -549,7 +549,7 @@ int configfs_create_bin_file(struct config_item *item, | |||
549 | 549 | ||
550 | inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL); | 550 | inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL); |
551 | error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode, | 551 | error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode, |
552 | CONFIGFS_ITEM_BIN_ATTR); | 552 | CONFIGFS_ITEM_BIN_ATTR, parent_sd->s_frag); |
553 | inode_unlock(dir->d_inode); | 553 | inode_unlock(dir->d_inode); |
554 | 554 | ||
555 | return error; | 555 | return error; |