1328970deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2fa60ce2cSMasahiro Yamada /*
37063fbf2SJoel Becker * file.c - operations for regular (text) files.
47063fbf2SJoel Becker *
57063fbf2SJoel Becker * Based on sysfs:
67063fbf2SJoel Becker * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
77063fbf2SJoel Becker *
87063fbf2SJoel Becker * configfs Copyright (C) 2005 Oracle. All rights reserved.
97063fbf2SJoel Becker */
107063fbf2SJoel Becker
117063fbf2SJoel Becker #include <linux/fs.h>
127063fbf2SJoel Becker #include <linux/module.h>
137063fbf2SJoel Becker #include <linux/slab.h>
146d748924SJohannes Berg #include <linux/mutex.h>
1503607aceSPantelis Antoniou #include <linux/vmalloc.h>
167c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
177fe1e79bSBart Van Assche #include <linux/uio.h>
187063fbf2SJoel Becker #include <linux/configfs.h>
197063fbf2SJoel Becker #include "configfs_internal.h"
207063fbf2SJoel Becker
21b23cdde4SJoel Becker /*
22b23cdde4SJoel Becker * A simple attribute can only be 4096 characters. Why 4k? Because the
23b23cdde4SJoel Becker * original code limited it to PAGE_SIZE. That's a bad idea, though,
24b23cdde4SJoel Becker * because an attribute of 16k on ia64 won't work on x86. So we limit to
25b23cdde4SJoel Becker * 4k, our minimum common page size.
26b23cdde4SJoel Becker */
27b23cdde4SJoel Becker #define SIMPLE_ATTR_SIZE 4096
287063fbf2SJoel Becker
297063fbf2SJoel Becker struct configfs_buffer {
307063fbf2SJoel Becker size_t count;
317063fbf2SJoel Becker loff_t pos;
327063fbf2SJoel Becker char * page;
337063fbf2SJoel Becker struct configfs_item_operations * ops;
346d748924SJohannes Berg struct mutex mutex;
357063fbf2SJoel Becker int needs_read_fill;
3603607aceSPantelis Antoniou bool read_in_progress;
3703607aceSPantelis Antoniou bool write_in_progress;
3803607aceSPantelis Antoniou char *bin_buffer;
3903607aceSPantelis Antoniou int bin_buffer_size;
40ff4dd081SAl Viro int cb_max_size;
41ff4dd081SAl Viro struct config_item *item;
42ff4dd081SAl Viro struct module *owner;
43ff4dd081SAl Viro union {
44ff4dd081SAl Viro struct configfs_attribute *attr;
45ff4dd081SAl Viro struct configfs_bin_attribute *bin_attr;
46ff4dd081SAl Viro };
477063fbf2SJoel Becker };
487063fbf2SJoel Becker
to_frag(struct file * file)49b0841eefSAl Viro static inline struct configfs_fragment *to_frag(struct file *file)
507063fbf2SJoel Becker {
51b0841eefSAl Viro struct configfs_dirent *sd = file->f_path.dentry->d_fsdata;
52b0841eefSAl Viro
53b0841eefSAl Viro return sd->s_frag;
54b0841eefSAl Viro }
55b0841eefSAl Viro
fill_read_buffer(struct file * file,struct configfs_buffer * buffer)56b0841eefSAl Viro static int fill_read_buffer(struct file *file, struct configfs_buffer *buffer)
57b0841eefSAl Viro {
58b0841eefSAl Viro struct configfs_fragment *frag = to_frag(file);
59b0841eefSAl Viro ssize_t count = -ENOENT;
607063fbf2SJoel Becker
617063fbf2SJoel Becker if (!buffer->page)
627063fbf2SJoel Becker buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
637063fbf2SJoel Becker if (!buffer->page)
647063fbf2SJoel Becker return -ENOMEM;
657063fbf2SJoel Becker
66b0841eefSAl Viro down_read(&frag->frag_sem);
67b0841eefSAl Viro if (!frag->frag_dead)
68ff4dd081SAl Viro count = buffer->attr->show(buffer->item, buffer->page);
69b0841eefSAl Viro up_read(&frag->frag_sem);
70b0841eefSAl Viro
71ff4dd081SAl Viro if (count < 0)
72ff4dd081SAl Viro return count;
73ff4dd081SAl Viro if (WARN_ON_ONCE(count > (ssize_t)SIMPLE_ATTR_SIZE))
74ff4dd081SAl Viro return -EIO;
753dc3afadSTal Shorer buffer->needs_read_fill = 0;
767063fbf2SJoel Becker buffer->count = count;
77ff4dd081SAl Viro return 0;
787063fbf2SJoel Becker }
797063fbf2SJoel Becker
configfs_read_iter(struct kiocb * iocb,struct iov_iter * to)807fe1e79bSBart Van Assche static ssize_t configfs_read_iter(struct kiocb *iocb, struct iov_iter *to)
817063fbf2SJoel Becker {
827fe1e79bSBart Van Assche struct file *file = iocb->ki_filp;
837063fbf2SJoel Becker struct configfs_buffer *buffer = file->private_data;
847063fbf2SJoel Becker ssize_t retval = 0;
857063fbf2SJoel Becker
866d748924SJohannes Berg mutex_lock(&buffer->mutex);
877063fbf2SJoel Becker if (buffer->needs_read_fill) {
88b0841eefSAl Viro retval = fill_read_buffer(file, buffer);
89ff4dd081SAl Viro if (retval)
907063fbf2SJoel Becker goto out;
917063fbf2SJoel Becker }
927fe1e79bSBart Van Assche pr_debug("%s: count = %zd, pos = %lld, buf = %s\n",
937fe1e79bSBart Van Assche __func__, iov_iter_count(to), iocb->ki_pos, buffer->page);
94420405ecSBart Van Assche if (iocb->ki_pos >= buffer->count)
95420405ecSBart Van Assche goto out;
96420405ecSBart Van Assche retval = copy_to_iter(buffer->page + iocb->ki_pos,
97420405ecSBart Van Assche buffer->count - iocb->ki_pos, to);
987fe1e79bSBart Van Assche iocb->ki_pos += retval;
997fe1e79bSBart Van Assche if (retval == 0)
1007fe1e79bSBart Van Assche retval = -EFAULT;
1017063fbf2SJoel Becker out:
1026d748924SJohannes Berg mutex_unlock(&buffer->mutex);
1037063fbf2SJoel Becker return retval;
1047063fbf2SJoel Becker }
1057063fbf2SJoel Becker
configfs_bin_read_iter(struct kiocb * iocb,struct iov_iter * to)1067fe1e79bSBart Van Assche static ssize_t configfs_bin_read_iter(struct kiocb *iocb, struct iov_iter *to)
10703607aceSPantelis Antoniou {
1087fe1e79bSBart Van Assche struct file *file = iocb->ki_filp;
109b0841eefSAl Viro struct configfs_fragment *frag = to_frag(file);
11003607aceSPantelis Antoniou struct configfs_buffer *buffer = file->private_data;
11103607aceSPantelis Antoniou ssize_t retval = 0;
1127fe1e79bSBart Van Assche ssize_t len;
11303607aceSPantelis Antoniou
11403607aceSPantelis Antoniou mutex_lock(&buffer->mutex);
11503607aceSPantelis Antoniou
11603607aceSPantelis Antoniou /* we don't support switching read/write modes */
11703607aceSPantelis Antoniou if (buffer->write_in_progress) {
11803607aceSPantelis Antoniou retval = -ETXTBSY;
11903607aceSPantelis Antoniou goto out;
12003607aceSPantelis Antoniou }
1213f6928c3SThomas Meyer buffer->read_in_progress = true;
12203607aceSPantelis Antoniou
12303607aceSPantelis Antoniou if (buffer->needs_read_fill) {
12403607aceSPantelis Antoniou /* perform first read with buf == NULL to get extent */
125b0841eefSAl Viro down_read(&frag->frag_sem);
126b0841eefSAl Viro if (!frag->frag_dead)
127ff4dd081SAl Viro len = buffer->bin_attr->read(buffer->item, NULL, 0);
128b0841eefSAl Viro else
129b0841eefSAl Viro len = -ENOENT;
130b0841eefSAl Viro up_read(&frag->frag_sem);
13103607aceSPantelis Antoniou if (len <= 0) {
13203607aceSPantelis Antoniou retval = len;
13303607aceSPantelis Antoniou goto out;
13403607aceSPantelis Antoniou }
13503607aceSPantelis Antoniou
13603607aceSPantelis Antoniou /* do not exceed the maximum value */
137ff4dd081SAl Viro if (buffer->cb_max_size && len > buffer->cb_max_size) {
13803607aceSPantelis Antoniou retval = -EFBIG;
13903607aceSPantelis Antoniou goto out;
14003607aceSPantelis Antoniou }
14103607aceSPantelis Antoniou
14203607aceSPantelis Antoniou buffer->bin_buffer = vmalloc(len);
14303607aceSPantelis Antoniou if (buffer->bin_buffer == NULL) {
14403607aceSPantelis Antoniou retval = -ENOMEM;
14503607aceSPantelis Antoniou goto out;
14603607aceSPantelis Antoniou }
14703607aceSPantelis Antoniou buffer->bin_buffer_size = len;
14803607aceSPantelis Antoniou
14903607aceSPantelis Antoniou /* perform second read to fill buffer */
150b0841eefSAl Viro down_read(&frag->frag_sem);
151b0841eefSAl Viro if (!frag->frag_dead)
152ff4dd081SAl Viro len = buffer->bin_attr->read(buffer->item,
153ff4dd081SAl Viro buffer->bin_buffer, len);
154b0841eefSAl Viro else
155b0841eefSAl Viro len = -ENOENT;
156b0841eefSAl Viro up_read(&frag->frag_sem);
15703607aceSPantelis Antoniou if (len < 0) {
15803607aceSPantelis Antoniou retval = len;
15903607aceSPantelis Antoniou vfree(buffer->bin_buffer);
16003607aceSPantelis Antoniou buffer->bin_buffer_size = 0;
16103607aceSPantelis Antoniou buffer->bin_buffer = NULL;
16203607aceSPantelis Antoniou goto out;
16303607aceSPantelis Antoniou }
16403607aceSPantelis Antoniou
16503607aceSPantelis Antoniou buffer->needs_read_fill = 0;
16603607aceSPantelis Antoniou }
16703607aceSPantelis Antoniou
168420405ecSBart Van Assche if (iocb->ki_pos >= buffer->bin_buffer_size)
169420405ecSBart Van Assche goto out;
170420405ecSBart Van Assche retval = copy_to_iter(buffer->bin_buffer + iocb->ki_pos,
171420405ecSBart Van Assche buffer->bin_buffer_size - iocb->ki_pos, to);
1727fe1e79bSBart Van Assche iocb->ki_pos += retval;
1737fe1e79bSBart Van Assche if (retval == 0)
1747fe1e79bSBart Van Assche retval = -EFAULT;
17503607aceSPantelis Antoniou out:
17603607aceSPantelis Antoniou mutex_unlock(&buffer->mutex);
17703607aceSPantelis Antoniou return retval;
17803607aceSPantelis Antoniou }
17903607aceSPantelis Antoniou
180*769f5267SBart Van Assche /* Fill @buffer with data coming from @from. */
fill_write_buffer(struct configfs_buffer * buffer,struct iov_iter * from)181*769f5267SBart Van Assche static int fill_write_buffer(struct configfs_buffer *buffer,
1827fe1e79bSBart Van Assche struct iov_iter *from)
1837063fbf2SJoel Becker {
1847fe1e79bSBart Van Assche int copied;
1857063fbf2SJoel Becker
1867063fbf2SJoel Becker if (!buffer->page)
187ff05d1c4SJoel Becker buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0);
1887063fbf2SJoel Becker if (!buffer->page)
1897063fbf2SJoel Becker return -ENOMEM;
1907063fbf2SJoel Becker
191*769f5267SBart Van Assche copied = copy_from_iter(buffer->page, SIMPLE_ATTR_SIZE - 1, from);
1927063fbf2SJoel Becker buffer->needs_read_fill = 1;
193ff05d1c4SJoel Becker /* if buf is assumed to contain a string, terminate it by \0,
194ff05d1c4SJoel Becker * so e.g. sscanf() can scan the string easily */
195*769f5267SBart Van Assche buffer->page[copied] = 0;
1967fe1e79bSBart Van Assche return copied ? : -EFAULT;
1977063fbf2SJoel Becker }
1987063fbf2SJoel Becker
1997063fbf2SJoel Becker static int
flush_write_buffer(struct file * file,struct configfs_buffer * buffer,size_t count)200b0841eefSAl Viro flush_write_buffer(struct file *file, struct configfs_buffer *buffer, size_t count)
2017063fbf2SJoel Becker {
202b0841eefSAl Viro struct configfs_fragment *frag = to_frag(file);
203b0841eefSAl Viro int res = -ENOENT;
204b0841eefSAl Viro
205b0841eefSAl Viro down_read(&frag->frag_sem);
206b0841eefSAl Viro if (!frag->frag_dead)
207b0841eefSAl Viro res = buffer->attr->store(buffer->item, buffer->page, count);
208b0841eefSAl Viro up_read(&frag->frag_sem);
209b0841eefSAl Viro return res;
2107063fbf2SJoel Becker }
2117063fbf2SJoel Becker
2127063fbf2SJoel Becker
21344b9a000SChristoph Hellwig /*
2147063fbf2SJoel Becker * There is no easy way for us to know if userspace is only doing a partial
21544b9a000SChristoph Hellwig * write, so we don't support them. We expect the entire buffer to come on the
21644b9a000SChristoph Hellwig * first write.
21744b9a000SChristoph Hellwig * Hint: if you're writing a value, first read the file, modify only the value
21844b9a000SChristoph Hellwig * you're changing, then write entire buffer back.
2197063fbf2SJoel Becker */
configfs_write_iter(struct kiocb * iocb,struct iov_iter * from)2207fe1e79bSBart Van Assche static ssize_t configfs_write_iter(struct kiocb *iocb, struct iov_iter *from)
2217063fbf2SJoel Becker {
2227fe1e79bSBart Van Assche struct file *file = iocb->ki_filp;
2237063fbf2SJoel Becker struct configfs_buffer *buffer = file->private_data;
224*769f5267SBart Van Assche int len;
2257063fbf2SJoel Becker
2266d748924SJohannes Berg mutex_lock(&buffer->mutex);
227*769f5267SBart Van Assche len = fill_write_buffer(buffer, from);
2283d0f89bbSJoel Becker if (len > 0)
229b0841eefSAl Viro len = flush_write_buffer(file, buffer, len);
2303d0f89bbSJoel Becker if (len > 0)
2317fe1e79bSBart Van Assche iocb->ki_pos += len;
2326d748924SJohannes Berg mutex_unlock(&buffer->mutex);
2333d0f89bbSJoel Becker return len;
2347063fbf2SJoel Becker }
2357063fbf2SJoel Becker
configfs_bin_write_iter(struct kiocb * iocb,struct iov_iter * from)2367fe1e79bSBart Van Assche static ssize_t configfs_bin_write_iter(struct kiocb *iocb,
2377fe1e79bSBart Van Assche struct iov_iter *from)
23803607aceSPantelis Antoniou {
2397fe1e79bSBart Van Assche struct file *file = iocb->ki_filp;
24003607aceSPantelis Antoniou struct configfs_buffer *buffer = file->private_data;
24103607aceSPantelis Antoniou void *tbuf = NULL;
2427fe1e79bSBart Van Assche size_t end_offset;
24303607aceSPantelis Antoniou ssize_t len;
24403607aceSPantelis Antoniou
24503607aceSPantelis Antoniou mutex_lock(&buffer->mutex);
24603607aceSPantelis Antoniou
24703607aceSPantelis Antoniou /* we don't support switching read/write modes */
24803607aceSPantelis Antoniou if (buffer->read_in_progress) {
24903607aceSPantelis Antoniou len = -ETXTBSY;
25003607aceSPantelis Antoniou goto out;
25103607aceSPantelis Antoniou }
2523f6928c3SThomas Meyer buffer->write_in_progress = true;
25303607aceSPantelis Antoniou
25403607aceSPantelis Antoniou /* buffer grows? */
2557fe1e79bSBart Van Assche end_offset = iocb->ki_pos + iov_iter_count(from);
2567fe1e79bSBart Van Assche if (end_offset > buffer->bin_buffer_size) {
2577fe1e79bSBart Van Assche if (buffer->cb_max_size && end_offset > buffer->cb_max_size) {
25803607aceSPantelis Antoniou len = -EFBIG;
25942857cf5SPhil Turnbull goto out;
26003607aceSPantelis Antoniou }
26103607aceSPantelis Antoniou
2627fe1e79bSBart Van Assche tbuf = vmalloc(end_offset);
26303607aceSPantelis Antoniou if (tbuf == NULL) {
26403607aceSPantelis Antoniou len = -ENOMEM;
26503607aceSPantelis Antoniou goto out;
26603607aceSPantelis Antoniou }
26703607aceSPantelis Antoniou
26803607aceSPantelis Antoniou /* copy old contents */
26903607aceSPantelis Antoniou if (buffer->bin_buffer) {
27003607aceSPantelis Antoniou memcpy(tbuf, buffer->bin_buffer,
27103607aceSPantelis Antoniou buffer->bin_buffer_size);
27203607aceSPantelis Antoniou vfree(buffer->bin_buffer);
27303607aceSPantelis Antoniou }
27403607aceSPantelis Antoniou
27503607aceSPantelis Antoniou /* clear the new area */
27603607aceSPantelis Antoniou memset(tbuf + buffer->bin_buffer_size, 0,
2777fe1e79bSBart Van Assche end_offset - buffer->bin_buffer_size);
27803607aceSPantelis Antoniou buffer->bin_buffer = tbuf;
2797fe1e79bSBart Van Assche buffer->bin_buffer_size = end_offset;
28003607aceSPantelis Antoniou }
28103607aceSPantelis Antoniou
282420405ecSBart Van Assche len = copy_from_iter(buffer->bin_buffer + iocb->ki_pos,
283420405ecSBart Van Assche buffer->bin_buffer_size - iocb->ki_pos, from);
284420405ecSBart Van Assche iocb->ki_pos += len;
28503607aceSPantelis Antoniou out:
28603607aceSPantelis Antoniou mutex_unlock(&buffer->mutex);
2877fe1e79bSBart Van Assche return len ? : -EFAULT;
28803607aceSPantelis Antoniou }
28903607aceSPantelis Antoniou
__configfs_open_file(struct inode * inode,struct file * file,int type)290ff4dd081SAl Viro static int __configfs_open_file(struct inode *inode, struct file *file, int type)
2917063fbf2SJoel Becker {
292ff4dd081SAl Viro struct dentry *dentry = file->f_path.dentry;
293b0841eefSAl Viro struct configfs_fragment *frag = to_frag(file);
294ff4dd081SAl Viro struct configfs_attribute *attr;
2957063fbf2SJoel Becker struct configfs_buffer *buffer;
296ff4dd081SAl Viro int error;
2977063fbf2SJoel Becker
298ff4dd081SAl Viro error = -ENOMEM;
299ff4dd081SAl Viro buffer = kzalloc(sizeof(struct configfs_buffer), GFP_KERNEL);
300ff4dd081SAl Viro if (!buffer)
301ff4dd081SAl Viro goto out;
3027063fbf2SJoel Becker
303b0841eefSAl Viro error = -ENOENT;
304b0841eefSAl Viro down_read(&frag->frag_sem);
305b0841eefSAl Viro if (unlikely(frag->frag_dead))
306b0841eefSAl Viro goto out_free_buffer;
307b0841eefSAl Viro
308ff4dd081SAl Viro error = -EINVAL;
309b0841eefSAl Viro buffer->item = to_item(dentry->d_parent);
310ff4dd081SAl Viro if (!buffer->item)
311ff4dd081SAl Viro goto out_free_buffer;
31203607aceSPantelis Antoniou
313ff4dd081SAl Viro attr = to_attr(dentry);
314ff4dd081SAl Viro if (!attr)
31514fbbc82SDaiyue Zhang goto out_free_buffer;
316ff4dd081SAl Viro
317ff4dd081SAl Viro if (type & CONFIGFS_ITEM_BIN_ATTR) {
318ff4dd081SAl Viro buffer->bin_attr = to_bin_attr(dentry);
319ff4dd081SAl Viro buffer->cb_max_size = buffer->bin_attr->cb_max_size;
320ff4dd081SAl Viro } else {
321ff4dd081SAl Viro buffer->attr = attr;
3227063fbf2SJoel Becker }
3237063fbf2SJoel Becker
324ff4dd081SAl Viro buffer->owner = attr->ca_owner;
325ff4dd081SAl Viro /* Grab the module reference for this attribute if we have one */
326ff4dd081SAl Viro error = -ENODEV;
327ff4dd081SAl Viro if (!try_module_get(buffer->owner))
32814fbbc82SDaiyue Zhang goto out_free_buffer;
329ff4dd081SAl Viro
330ff4dd081SAl Viro error = -EACCES;
331ff4dd081SAl Viro if (!buffer->item->ci_type)
332ff4dd081SAl Viro goto out_put_module;
333ff4dd081SAl Viro
334ff4dd081SAl Viro buffer->ops = buffer->item->ci_type->ct_item_ops;
3357063fbf2SJoel Becker
3367063fbf2SJoel Becker /* File needs write support.
3377063fbf2SJoel Becker * The inode's perms must say it's ok,
3387063fbf2SJoel Becker * and we must have a store method.
3397063fbf2SJoel Becker */
3407063fbf2SJoel Becker if (file->f_mode & FMODE_WRITE) {
34103607aceSPantelis Antoniou if (!(inode->i_mode & S_IWUGO))
342ff4dd081SAl Viro goto out_put_module;
34303607aceSPantelis Antoniou if ((type & CONFIGFS_ITEM_ATTR) && !attr->store)
344ff4dd081SAl Viro goto out_put_module;
345ff4dd081SAl Viro if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->write)
346ff4dd081SAl Viro goto out_put_module;
3477063fbf2SJoel Becker }
3487063fbf2SJoel Becker
3497063fbf2SJoel Becker /* File needs read support.
3507063fbf2SJoel Becker * The inode's perms must say it's ok, and we there
3517063fbf2SJoel Becker * must be a show method for it.
3527063fbf2SJoel Becker */
3537063fbf2SJoel Becker if (file->f_mode & FMODE_READ) {
35403607aceSPantelis Antoniou if (!(inode->i_mode & S_IRUGO))
355ff4dd081SAl Viro goto out_put_module;
35603607aceSPantelis Antoniou if ((type & CONFIGFS_ITEM_ATTR) && !attr->show)
357ff4dd081SAl Viro goto out_put_module;
358ff4dd081SAl Viro if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->read)
359ff4dd081SAl Viro goto out_put_module;
3607063fbf2SJoel Becker }
3617063fbf2SJoel Becker
3626d748924SJohannes Berg mutex_init(&buffer->mutex);
3637063fbf2SJoel Becker buffer->needs_read_fill = 1;
3643f6928c3SThomas Meyer buffer->read_in_progress = false;
3653f6928c3SThomas Meyer buffer->write_in_progress = false;
3667063fbf2SJoel Becker file->private_data = buffer;
367b0841eefSAl Viro up_read(&frag->frag_sem);
368ff4dd081SAl Viro return 0;
3697063fbf2SJoel Becker
370ff4dd081SAl Viro out_put_module:
371ff4dd081SAl Viro module_put(buffer->owner);
372ff4dd081SAl Viro out_free_buffer:
373b0841eefSAl Viro up_read(&frag->frag_sem);
374ff4dd081SAl Viro kfree(buffer);
375ff4dd081SAl Viro out:
3767063fbf2SJoel Becker return error;
3777063fbf2SJoel Becker }
3787063fbf2SJoel Becker
configfs_release(struct inode * inode,struct file * filp)3797063fbf2SJoel Becker static int configfs_release(struct inode *inode, struct file *filp)
3807063fbf2SJoel Becker {
3817063fbf2SJoel Becker struct configfs_buffer *buffer = filp->private_data;
3827063fbf2SJoel Becker
383ff4dd081SAl Viro module_put(buffer->owner);
3847063fbf2SJoel Becker if (buffer->page)
3857063fbf2SJoel Becker free_page((unsigned long)buffer->page);
3866d748924SJohannes Berg mutex_destroy(&buffer->mutex);
3877063fbf2SJoel Becker kfree(buffer);
3887063fbf2SJoel Becker return 0;
3897063fbf2SJoel Becker }
3907063fbf2SJoel Becker
configfs_open_file(struct inode * inode,struct file * filp)39103607aceSPantelis Antoniou static int configfs_open_file(struct inode *inode, struct file *filp)
39203607aceSPantelis Antoniou {
393ff4dd081SAl Viro return __configfs_open_file(inode, filp, CONFIGFS_ITEM_ATTR);
39403607aceSPantelis Antoniou }
39503607aceSPantelis Antoniou
configfs_open_bin_file(struct inode * inode,struct file * filp)39603607aceSPantelis Antoniou static int configfs_open_bin_file(struct inode *inode, struct file *filp)
39703607aceSPantelis Antoniou {
398ff4dd081SAl Viro return __configfs_open_file(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
39903607aceSPantelis Antoniou }
40003607aceSPantelis Antoniou
configfs_release_bin_file(struct inode * inode,struct file * file)401ff4dd081SAl Viro static int configfs_release_bin_file(struct inode *inode, struct file *file)
40203607aceSPantelis Antoniou {
403ff4dd081SAl Viro struct configfs_buffer *buffer = file->private_data;
40403607aceSPantelis Antoniou
40503607aceSPantelis Antoniou if (buffer->write_in_progress) {
406b0841eefSAl Viro struct configfs_fragment *frag = to_frag(file);
40703607aceSPantelis Antoniou
408b0841eefSAl Viro down_read(&frag->frag_sem);
409b0841eefSAl Viro if (!frag->frag_dead) {
410ff4dd081SAl Viro /* result of ->release() is ignored */
411b0841eefSAl Viro buffer->bin_attr->write(buffer->item,
412b0841eefSAl Viro buffer->bin_buffer,
41303607aceSPantelis Antoniou buffer->bin_buffer_size);
414b0841eefSAl Viro }
415b0841eefSAl Viro up_read(&frag->frag_sem);
4163c252b08SChung-Chiang Cheng }
4173c252b08SChung-Chiang Cheng
41803607aceSPantelis Antoniou vfree(buffer->bin_buffer);
41903607aceSPantelis Antoniou
420ff4dd081SAl Viro configfs_release(inode, file);
421ff4dd081SAl Viro return 0;
42203607aceSPantelis Antoniou }
42303607aceSPantelis Antoniou
42403607aceSPantelis Antoniou
4254b6f5d20SArjan van de Ven const struct file_operations configfs_file_operations = {
4267fe1e79bSBart Van Assche .read_iter = configfs_read_iter,
4277fe1e79bSBart Van Assche .write_iter = configfs_write_iter,
4287063fbf2SJoel Becker .llseek = generic_file_llseek,
4297063fbf2SJoel Becker .open = configfs_open_file,
4307063fbf2SJoel Becker .release = configfs_release,
4317063fbf2SJoel Becker };
4327063fbf2SJoel Becker
43303607aceSPantelis Antoniou const struct file_operations configfs_bin_file_operations = {
4347fe1e79bSBart Van Assche .read_iter = configfs_bin_read_iter,
4357fe1e79bSBart Van Assche .write_iter = configfs_bin_write_iter,
43603607aceSPantelis Antoniou .llseek = NULL, /* bin file is not seekable */
43703607aceSPantelis Antoniou .open = configfs_open_bin_file,
43803607aceSPantelis Antoniou .release = configfs_release_bin_file,
43903607aceSPantelis Antoniou };
44003607aceSPantelis Antoniou
4417063fbf2SJoel Becker /**
4427063fbf2SJoel Becker * configfs_create_file - create an attribute file for an item.
4437063fbf2SJoel Becker * @item: item we're creating for.
4447063fbf2SJoel Becker * @attr: atrribute descriptor.
4457063fbf2SJoel Becker */
4467063fbf2SJoel Becker
configfs_create_file(struct config_item * item,const struct configfs_attribute * attr)4477063fbf2SJoel Becker int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr)
4487063fbf2SJoel Becker {
44928444a2bSAl Viro struct dentry *dir = item->ci_dentry;
45028444a2bSAl Viro struct configfs_dirent *parent_sd = dir->d_fsdata;
45128444a2bSAl Viro umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
45228444a2bSAl Viro int error = 0;
4537063fbf2SJoel Becker
4545955102cSAl Viro inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL);
45528444a2bSAl Viro error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode,
45647320fbeSAl Viro CONFIGFS_ITEM_ATTR, parent_sd->s_frag);
4575955102cSAl Viro inode_unlock(d_inode(dir));
45828444a2bSAl Viro
45928444a2bSAl Viro return error;
4607063fbf2SJoel Becker }
4617063fbf2SJoel Becker
46203607aceSPantelis Antoniou /**
46303607aceSPantelis Antoniou * configfs_create_bin_file - create a binary attribute file for an item.
46403607aceSPantelis Antoniou * @item: item we're creating for.
465dd33f1f7SBart Van Assche * @bin_attr: atrribute descriptor.
46603607aceSPantelis Antoniou */
46703607aceSPantelis Antoniou
configfs_create_bin_file(struct config_item * item,const struct configfs_bin_attribute * bin_attr)46803607aceSPantelis Antoniou int configfs_create_bin_file(struct config_item *item,
46903607aceSPantelis Antoniou const struct configfs_bin_attribute *bin_attr)
47003607aceSPantelis Antoniou {
47103607aceSPantelis Antoniou struct dentry *dir = item->ci_dentry;
47203607aceSPantelis Antoniou struct configfs_dirent *parent_sd = dir->d_fsdata;
47303607aceSPantelis Antoniou umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG;
47403607aceSPantelis Antoniou int error = 0;
47503607aceSPantelis Antoniou
4765955102cSAl Viro inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL);
47703607aceSPantelis Antoniou error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode,
47847320fbeSAl Viro CONFIGFS_ITEM_BIN_ATTR, parent_sd->s_frag);
4795955102cSAl Viro inode_unlock(dir->d_inode);
48003607aceSPantelis Antoniou
48103607aceSPantelis Antoniou return error;
48203607aceSPantelis Antoniou }
483