]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/configfs/file.c
configfs: new object reprsenting tree fragments
[mirror_ubuntu-bionic-kernel.git] / fs / configfs / file.c
CommitLineData
7063fbf2
JB
1/* -*- mode: c; c-basic-offset: 8; -*-
2 * vim: noexpandtab sw=8 ts=8 sts=0:
3 *
4 * file.c - operations for regular (text) files.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 021110-1307, USA.
20 *
21 * Based on sysfs:
22 * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
23 *
24 * configfs Copyright (C) 2005 Oracle. All rights reserved.
25 */
26
27#include <linux/fs.h>
28#include <linux/module.h>
7063fbf2 29#include <linux/slab.h>
6d748924 30#include <linux/mutex.h>
03607ace 31#include <linux/vmalloc.h>
7c0f6ba6 32#include <linux/uaccess.h>
7063fbf2
JB
33
34#include <linux/configfs.h>
35#include "configfs_internal.h"
36
b23cdde4
JB
37/*
38 * A simple attribute can only be 4096 characters. Why 4k? Because the
39 * original code limited it to PAGE_SIZE. That's a bad idea, though,
40 * because an attribute of 16k on ia64 won't work on x86. So we limit to
41 * 4k, our minimum common page size.
42 */
43#define SIMPLE_ATTR_SIZE 4096
7063fbf2
JB
44
45struct configfs_buffer {
46 size_t count;
47 loff_t pos;
48 char * page;
49 struct configfs_item_operations * ops;
6d748924 50 struct mutex mutex;
7063fbf2 51 int needs_read_fill;
03607ace
PA
52 bool read_in_progress;
53 bool write_in_progress;
54 char *bin_buffer;
55 int bin_buffer_size;
33f5f3e6
AV
56 int cb_max_size;
57 struct config_item *item;
58 struct module *owner;
59 union {
60 struct configfs_attribute *attr;
61 struct configfs_bin_attribute *bin_attr;
62 };
7063fbf2
JB
63};
64
65
33f5f3e6 66static int fill_read_buffer(struct configfs_buffer * buffer)
7063fbf2 67{
7063fbf2
JB
68 ssize_t count;
69
70 if (!buffer->page)
71 buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
72 if (!buffer->page)
73 return -ENOMEM;
74
33f5f3e6
AV
75 count = buffer->attr->show(buffer->item, buffer->page);
76 if (count < 0)
77 return count;
78 if (WARN_ON_ONCE(count > (ssize_t)SIMPLE_ATTR_SIZE))
79 return -EIO;
870823e6 80
33f5f3e6
AV
81 buffer->needs_read_fill = 0;
82 buffer->count = count;
83 return 0;
7063fbf2
JB
84}
85
7063fbf2
JB
86/**
87 * configfs_read_file - read an attribute.
88 * @file: file pointer.
89 * @buf: buffer to fill.
90 * @count: number of bytes to read.
91 * @ppos: starting offset in file.
92 *
93 * Userspace wants to read an attribute file. The attribute descriptor
94 * is in the file's ->d_fsdata. The target item is in the directory's
95 * ->d_fsdata.
96 *
97 * We call fill_read_buffer() to allocate and fill the buffer from the
98 * item's show() method exactly once (if the read is happening from
99 * the beginning of the file). That should fill the entire buffer with
100 * all the data the item has to offer for that attribute.
101 * We then call flush_read_buffer() to copy the buffer to userspace
102 * in the increments specified.
103 */
104
105static ssize_t
106configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
107{
33f5f3e6 108 struct configfs_buffer *buffer = file->private_data;
7063fbf2
JB
109 ssize_t retval = 0;
110
6d748924 111 mutex_lock(&buffer->mutex);
7063fbf2 112 if (buffer->needs_read_fill) {
33f5f3e6
AV
113 retval = fill_read_buffer(buffer);
114 if (retval)
7063fbf2
JB
115 goto out;
116 }
4779efca 117 pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
8e24eea7 118 __func__, count, *ppos, buffer->page);
92f4c701
AM
119 retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
120 buffer->count);
7063fbf2 121out:
6d748924 122 mutex_unlock(&buffer->mutex);
7063fbf2
JB
123 return retval;
124}
125
03607ace
PA
126/**
127 * configfs_read_bin_file - read a binary attribute.
128 * @file: file pointer.
129 * @buf: buffer to fill.
130 * @count: number of bytes to read.
131 * @ppos: starting offset in file.
132 *
133 * Userspace wants to read a binary attribute file. The attribute
134 * descriptor is in the file's ->d_fsdata. The target item is in the
135 * directory's ->d_fsdata.
136 *
137 * We check whether we need to refill the buffer. If so we will
138 * call the attributes' attr->read() twice. The first time we
139 * will pass a NULL as a buffer pointer, which the attributes' method
140 * will use to return the size of the buffer required. If no error
141 * occurs we will allocate the buffer using vmalloc and call
142 * attr->read() again passing that buffer as an argument.
143 * Then we just copy to user-space using simple_read_from_buffer.
144 */
145
146static ssize_t
147configfs_read_bin_file(struct file *file, char __user *buf,
148 size_t count, loff_t *ppos)
149{
150 struct configfs_buffer *buffer = file->private_data;
03607ace
PA
151 ssize_t retval = 0;
152 ssize_t len = min_t(size_t, count, PAGE_SIZE);
153
154 mutex_lock(&buffer->mutex);
155
156 /* we don't support switching read/write modes */
157 if (buffer->write_in_progress) {
158 retval = -ETXTBSY;
159 goto out;
160 }
3f6928c3 161 buffer->read_in_progress = true;
03607ace
PA
162
163 if (buffer->needs_read_fill) {
164 /* perform first read with buf == NULL to get extent */
33f5f3e6 165 len = buffer->bin_attr->read(buffer->item, NULL, 0);
03607ace
PA
166 if (len <= 0) {
167 retval = len;
168 goto out;
169 }
170
171 /* do not exceed the maximum value */
33f5f3e6 172 if (buffer->cb_max_size && len > buffer->cb_max_size) {
03607ace
PA
173 retval = -EFBIG;
174 goto out;
175 }
176
177 buffer->bin_buffer = vmalloc(len);
178 if (buffer->bin_buffer == NULL) {
179 retval = -ENOMEM;
180 goto out;
181 }
182 buffer->bin_buffer_size = len;
183
184 /* perform second read to fill buffer */
33f5f3e6
AV
185 len = buffer->bin_attr->read(buffer->item,
186 buffer->bin_buffer, len);
03607ace
PA
187 if (len < 0) {
188 retval = len;
189 vfree(buffer->bin_buffer);
190 buffer->bin_buffer_size = 0;
191 buffer->bin_buffer = NULL;
192 goto out;
193 }
194
195 buffer->needs_read_fill = 0;
196 }
197
198 retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer,
199 buffer->bin_buffer_size);
200out:
201 mutex_unlock(&buffer->mutex);
202 return retval;
203}
204
7063fbf2
JB
205
206/**
207 * fill_write_buffer - copy buffer from userspace.
208 * @buffer: data buffer for file.
3d0f89bb 209 * @buf: data from user.
7063fbf2
JB
210 * @count: number of bytes in @userbuf.
211 *
212 * Allocate @buffer->page if it hasn't been already, then
213 * copy the user-supplied buffer into it.
214 */
215
216static int
217fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size_t count)
218{
219 int error;
220
221 if (!buffer->page)
ff05d1c4 222 buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0);
7063fbf2
JB
223 if (!buffer->page)
224 return -ENOMEM;
225
b23cdde4
JB
226 if (count >= SIMPLE_ATTR_SIZE)
227 count = SIMPLE_ATTR_SIZE - 1;
7063fbf2
JB
228 error = copy_from_user(buffer->page,buf,count);
229 buffer->needs_read_fill = 1;
ff05d1c4
JB
230 /* if buf is assumed to contain a string, terminate it by \0,
231 * so e.g. sscanf() can scan the string easily */
232 buffer->page[count] = 0;
7063fbf2
JB
233 return error ? -EFAULT : count;
234}
235
7063fbf2 236static int
33f5f3e6 237flush_write_buffer(struct configfs_buffer *buffer, size_t count)
7063fbf2 238{
33f5f3e6 239 return buffer->attr->store(buffer->item, buffer->page, count);
7063fbf2
JB
240}
241
242
243/**
244 * configfs_write_file - write an attribute.
245 * @file: file pointer
246 * @buf: data to write
247 * @count: number of bytes
248 * @ppos: starting offset
249 *
250 * Similar to configfs_read_file(), though working in the opposite direction.
251 * We allocate and fill the data from the user in fill_write_buffer(),
252 * then push it to the config_item in flush_write_buffer().
253 * There is no easy way for us to know if userspace is only doing a partial
254 * write, so we don't support them. We expect the entire buffer to come
255 * on the first write.
256 * Hint: if you're writing a value, first read the file, modify only the
257 * the value you're changing, then write entire buffer back.
258 */
259
260static ssize_t
261configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
262{
33f5f3e6 263 struct configfs_buffer *buffer = file->private_data;
3d0f89bb 264 ssize_t len;
7063fbf2 265
6d748924 266 mutex_lock(&buffer->mutex);
3d0f89bb
JB
267 len = fill_write_buffer(buffer, buf, count);
268 if (len > 0)
33f5f3e6 269 len = flush_write_buffer(buffer, len);
3d0f89bb
JB
270 if (len > 0)
271 *ppos += len;
6d748924 272 mutex_unlock(&buffer->mutex);
3d0f89bb 273 return len;
7063fbf2
JB
274}
275
03607ace
PA
276/**
277 * configfs_write_bin_file - write a binary attribute.
278 * @file: file pointer
279 * @buf: data to write
280 * @count: number of bytes
281 * @ppos: starting offset
282 *
283 * Writing to a binary attribute file is similar to a normal read.
284 * We buffer the consecutive writes (binary attribute files do not
285 * support lseek) in a continuously growing buffer, but we don't
286 * commit until the close of the file.
287 */
288
289static ssize_t
290configfs_write_bin_file(struct file *file, const char __user *buf,
291 size_t count, loff_t *ppos)
292{
293 struct configfs_buffer *buffer = file->private_data;
03607ace
PA
294 void *tbuf = NULL;
295 ssize_t len;
296
297 mutex_lock(&buffer->mutex);
298
299 /* we don't support switching read/write modes */
300 if (buffer->read_in_progress) {
301 len = -ETXTBSY;
302 goto out;
303 }
3f6928c3 304 buffer->write_in_progress = true;
03607ace
PA
305
306 /* buffer grows? */
307 if (*ppos + count > buffer->bin_buffer_size) {
308
33f5f3e6
AV
309 if (buffer->cb_max_size &&
310 *ppos + count > buffer->cb_max_size) {
03607ace 311 len = -EFBIG;
42857cf5 312 goto out;
03607ace
PA
313 }
314
315 tbuf = vmalloc(*ppos + count);
316 if (tbuf == NULL) {
317 len = -ENOMEM;
318 goto out;
319 }
320
321 /* copy old contents */
322 if (buffer->bin_buffer) {
323 memcpy(tbuf, buffer->bin_buffer,
324 buffer->bin_buffer_size);
325 vfree(buffer->bin_buffer);
326 }
327
328 /* clear the new area */
329 memset(tbuf + buffer->bin_buffer_size, 0,
330 *ppos + count - buffer->bin_buffer_size);
331 buffer->bin_buffer = tbuf;
332 buffer->bin_buffer_size = *ppos + count;
333 }
334
335 len = simple_write_to_buffer(buffer->bin_buffer,
336 buffer->bin_buffer_size, ppos, buf, count);
03607ace
PA
337out:
338 mutex_unlock(&buffer->mutex);
339 return len;
340}
341
33f5f3e6 342static int __configfs_open_file(struct inode *inode, struct file *file, int type)
7063fbf2 343{
33f5f3e6
AV
344 struct dentry *dentry = file->f_path.dentry;
345 struct configfs_attribute *attr;
346 struct configfs_buffer *buffer;
347 int error;
7063fbf2 348
33f5f3e6
AV
349 error = -ENOMEM;
350 buffer = kzalloc(sizeof(struct configfs_buffer), GFP_KERNEL);
351 if (!buffer)
352 goto out;
7063fbf2 353
33f5f3e6
AV
354 error = -EINVAL;
355 buffer->item = configfs_get_config_item(dentry->d_parent);
356 if (!buffer->item)
357 goto out_free_buffer;
358
359 attr = to_attr(dentry);
360 if (!attr)
361 goto out_put_item;
362
363 if (type & CONFIGFS_ITEM_BIN_ATTR) {
364 buffer->bin_attr = to_bin_attr(dentry);
365 buffer->cb_max_size = buffer->bin_attr->cb_max_size;
366 } else {
367 buffer->attr = attr;
368 }
03607ace 369
33f5f3e6 370 buffer->owner = attr->ca_owner;
7063fbf2 371 /* Grab the module reference for this attribute if we have one */
33f5f3e6
AV
372 error = -ENODEV;
373 if (!try_module_get(buffer->owner))
374 goto out_put_item;
7063fbf2 375
33f5f3e6
AV
376 error = -EACCES;
377 if (!buffer->item->ci_type)
378 goto out_put_module;
379
380 buffer->ops = buffer->item->ci_type->ct_item_ops;
7063fbf2
JB
381
382 /* File needs write support.
383 * The inode's perms must say it's ok,
384 * and we must have a store method.
385 */
386 if (file->f_mode & FMODE_WRITE) {
03607ace 387 if (!(inode->i_mode & S_IWUGO))
33f5f3e6 388 goto out_put_module;
03607ace 389 if ((type & CONFIGFS_ITEM_ATTR) && !attr->store)
33f5f3e6
AV
390 goto out_put_module;
391 if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->write)
392 goto out_put_module;
7063fbf2
JB
393 }
394
395 /* File needs read support.
396 * The inode's perms must say it's ok, and we there
397 * must be a show method for it.
398 */
399 if (file->f_mode & FMODE_READ) {
03607ace 400 if (!(inode->i_mode & S_IRUGO))
33f5f3e6 401 goto out_put_module;
03607ace 402 if ((type & CONFIGFS_ITEM_ATTR) && !attr->show)
33f5f3e6
AV
403 goto out_put_module;
404 if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->read)
405 goto out_put_module;
7063fbf2
JB
406 }
407
6d748924 408 mutex_init(&buffer->mutex);
559c9ac3 409 buffer->needs_read_fill = 1;
3f6928c3
TM
410 buffer->read_in_progress = false;
411 buffer->write_in_progress = false;
559c9ac3 412 file->private_data = buffer;
33f5f3e6 413 return 0;
7063fbf2 414
33f5f3e6
AV
415out_put_module:
416 module_put(buffer->owner);
417out_put_item:
418 config_item_put(buffer->item);
419out_free_buffer:
420 kfree(buffer);
421out:
7063fbf2
JB
422 return error;
423}
424
03607ace 425static int configfs_release(struct inode *inode, struct file *filp)
7063fbf2 426{
33f5f3e6
AV
427 struct configfs_buffer *buffer = filp->private_data;
428
429 if (buffer->item)
430 config_item_put(buffer->item);
431 module_put(buffer->owner);
432 if (buffer->page)
433 free_page((unsigned long)buffer->page);
434 mutex_destroy(&buffer->mutex);
435 kfree(buffer);
7063fbf2
JB
436 return 0;
437}
438
03607ace
PA
439static int configfs_open_file(struct inode *inode, struct file *filp)
440{
33f5f3e6 441 return __configfs_open_file(inode, filp, CONFIGFS_ITEM_ATTR);
03607ace
PA
442}
443
444static int configfs_open_bin_file(struct inode *inode, struct file *filp)
445{
33f5f3e6 446 return __configfs_open_file(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
03607ace
PA
447}
448
33f5f3e6 449static int configfs_release_bin_file(struct inode *inode, struct file *file)
03607ace 450{
33f5f3e6 451 struct configfs_buffer *buffer = file->private_data;
03607ace 452
3f6928c3 453 buffer->read_in_progress = false;
03607ace
PA
454
455 if (buffer->write_in_progress) {
3f6928c3 456 buffer->write_in_progress = false;
03607ace 457
33f5f3e6
AV
458 /* result of ->release() is ignored */
459 buffer->bin_attr->write(buffer->item, buffer->bin_buffer,
03607ace
PA
460 buffer->bin_buffer_size);
461
462 /* vfree on NULL is safe */
463 vfree(buffer->bin_buffer);
464 buffer->bin_buffer = NULL;
465 buffer->bin_buffer_size = 0;
466 buffer->needs_read_fill = 1;
467 }
468
33f5f3e6
AV
469 configfs_release(inode, file);
470 return 0;
03607ace
PA
471}
472
473
4b6f5d20 474const struct file_operations configfs_file_operations = {
7063fbf2
JB
475 .read = configfs_read_file,
476 .write = configfs_write_file,
477 .llseek = generic_file_llseek,
478 .open = configfs_open_file,
479 .release = configfs_release,
480};
481
03607ace
PA
482const struct file_operations configfs_bin_file_operations = {
483 .read = configfs_read_bin_file,
484 .write = configfs_write_bin_file,
485 .llseek = NULL, /* bin file is not seekable */
486 .open = configfs_open_bin_file,
487 .release = configfs_release_bin_file,
488};
489
7063fbf2
JB
490/**
491 * configfs_create_file - create an attribute file for an item.
492 * @item: item we're creating for.
493 * @attr: atrribute descriptor.
494 */
495
496int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr)
497{
28444a2b
AV
498 struct dentry *dir = item->ci_dentry;
499 struct configfs_dirent *parent_sd = dir->d_fsdata;
500 umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
501 int error = 0;
7063fbf2 502
5955102c 503 inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL);
28444a2b 504 error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode,
ecb0c8cd 505 CONFIGFS_ITEM_ATTR, parent_sd->s_frag);
5955102c 506 inode_unlock(d_inode(dir));
28444a2b
AV
507
508 return error;
7063fbf2
JB
509}
510
03607ace
PA
511/**
512 * configfs_create_bin_file - create a binary attribute file for an item.
513 * @item: item we're creating for.
514 * @attr: atrribute descriptor.
515 */
516
517int configfs_create_bin_file(struct config_item *item,
518 const struct configfs_bin_attribute *bin_attr)
519{
520 struct dentry *dir = item->ci_dentry;
521 struct configfs_dirent *parent_sd = dir->d_fsdata;
522 umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG;
523 int error = 0;
524
5955102c 525 inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL);
03607ace 526 error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode,
ecb0c8cd 527 CONFIGFS_ITEM_BIN_ATTR, parent_sd->s_frag);
5955102c 528 inode_unlock(dir->d_inode);
03607ace
PA
529
530 return error;
531}