summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/configfs/configfs.txt57
-rw-r--r--MAINTAINERS3
-rw-r--r--fs/configfs/configfs_internal.h14
-rw-r--r--fs/configfs/dir.c18
-rw-r--r--fs/configfs/file.c255
-rw-r--r--fs/configfs/inode.c2
-rw-r--r--include/linux/configfs.h50
7 files changed, 376 insertions, 23 deletions
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
index af68efdbbfad..e5fe521eea1d 100644
--- a/Documentation/filesystems/configfs/configfs.txt
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -51,15 +51,27 @@ configfs tree is always there, whether mounted on /config or not.
51An item is created via mkdir(2). The item's attributes will also 51An item is created via mkdir(2). The item's attributes will also
52appear at this time. readdir(3) can determine what the attributes are, 52appear at this time. readdir(3) can determine what the attributes are,
53read(2) can query their default values, and write(2) can store new 53read(2) can query their default values, and write(2) can store new
54values. Like sysfs, attributes should be ASCII text files, preferably 54values. Don't mix more than one attribute in one attribute file.
55with only one value per file. The same efficiency caveats from sysfs 55
56apply. Don't mix more than one attribute in one attribute file. 56There are two types of configfs attributes:
57 57
58Like sysfs, configfs expects write(2) to store the entire buffer at 58* Normal attributes, which similar to sysfs attributes, are small ASCII text
59once. When writing to configfs attributes, userspace processes should 59files, with a maximum size of one page (PAGE_SIZE, 4096 on i386). Preferably
60first read the entire file, modify the portions they wish to change, and 60only one value per file should be used, and the same caveats from sysfs apply.
61then write the entire buffer back. Attribute files have a maximum size 61Configfs expects write(2) to store the entire buffer at once. When writing to
62of one page (PAGE_SIZE, 4096 on i386). 62normal configfs attributes, userspace processes should first read the entire
63file, modify the portions they wish to change, and then write the entire
64buffer back.
65
66* Binary attributes, which are somewhat similar to sysfs binary attributes,
67but with a few slight changes to semantics. The PAGE_SIZE limitation does not
68apply, but the whole binary item must fit in single kernel vmalloc'ed buffer.
69The write(2) calls from user space are buffered, and the attributes'
70write_bin_attribute method will be invoked on the final close, therefore it is
71imperative for user-space to check the return code of close(2) in order to
72verify that the operation finished successfully.
73To avoid a malicious user OOMing the kernel, there's a per-binary attribute
74maximum buffer value.
63 75
64When an item needs to be destroyed, remove it with rmdir(2). An 76When an item needs to be destroyed, remove it with rmdir(2). An
65item cannot be destroyed if any other item has a link to it (via 77item cannot be destroyed if any other item has a link to it (via
@@ -171,6 +183,7 @@ among other things. For that, it needs a type.
171 struct configfs_item_operations *ct_item_ops; 183 struct configfs_item_operations *ct_item_ops;
172 struct configfs_group_operations *ct_group_ops; 184 struct configfs_group_operations *ct_group_ops;
173 struct configfs_attribute **ct_attrs; 185 struct configfs_attribute **ct_attrs;
186 struct configfs_bin_attribute **ct_bin_attrs;
174 }; 187 };
175 188
176The most basic function of a config_item_type is to define what 189The most basic function of a config_item_type is to define what
@@ -201,6 +214,32 @@ be called whenever userspace asks for a read(2) on the attribute. If an
201attribute is writable and provides a ->store method, that method will be 214attribute is writable and provides a ->store method, that method will be
202be called whenever userspace asks for a write(2) on the attribute. 215be called whenever userspace asks for a write(2) on the attribute.
203 216
217[struct configfs_bin_attribute]
218
219 struct configfs_attribute {
220 struct configfs_attribute cb_attr;
221 void *cb_private;
222 size_t cb_max_size;
223 };
224
225The binary attribute is used when the one needs to use binary blob to
226appear as the contents of a file in the item's configfs directory.
227To do so add the binary attribute to the NULL-terminated array
228config_item_type->ct_bin_attrs, and the item appears in configfs, the
229attribute file will appear with the configfs_bin_attribute->cb_attr.ca_name
230filename. configfs_bin_attribute->cb_attr.ca_mode specifies the file
231permissions.
232The cb_private member is provided for use by the driver, while the
233cb_max_size member specifies the maximum amount of vmalloc buffer
234to be used.
235
236If binary attribute is readable and the config_item provides a
237ct_item_ops->read_bin_attribute() method, that method will be called
238whenever userspace asks for a read(2) on the attribute. The converse
239will happen for write(2). The reads/writes are bufferred so only a
240single read/write will occur; the attributes' need not concern itself
241with it.
242
204[struct config_group] 243[struct config_group]
205 244
206A config_item cannot live in a vacuum. The only way one can be created 245A config_item cannot live in a vacuum. The only way one can be created
diff --git a/MAINTAINERS b/MAINTAINERS
index e99a7b328c7f..0788854baadb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2938,7 +2938,8 @@ F: drivers/usb/atm/cxacru.c
2938 2938
2939CONFIGFS 2939CONFIGFS
2940M: Joel Becker <jlbec@evilplan.org> 2940M: Joel Becker <jlbec@evilplan.org>
2941T: git git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/configfs.git 2941M: Christoph Hellwig <hch@lst.de>
2942T: git git://git.infradead.org/users/hch/configfs.git
2942S: Supported 2943S: Supported
2943F: fs/configfs/ 2944F: fs/configfs/
2944F: include/linux/configfs.h 2945F: include/linux/configfs.h
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index b65d1ef532d5..ccc31fa6f1a7 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -53,13 +53,14 @@ struct configfs_dirent {
53#define CONFIGFS_ROOT 0x0001 53#define CONFIGFS_ROOT 0x0001
54#define CONFIGFS_DIR 0x0002 54#define CONFIGFS_DIR 0x0002
55#define CONFIGFS_ITEM_ATTR 0x0004 55#define CONFIGFS_ITEM_ATTR 0x0004
56#define CONFIGFS_ITEM_BIN_ATTR 0x0008
56#define CONFIGFS_ITEM_LINK 0x0020 57#define CONFIGFS_ITEM_LINK 0x0020
57#define CONFIGFS_USET_DIR 0x0040 58#define CONFIGFS_USET_DIR 0x0040
58#define CONFIGFS_USET_DEFAULT 0x0080 59#define CONFIGFS_USET_DEFAULT 0x0080
59#define CONFIGFS_USET_DROPPING 0x0100 60#define CONFIGFS_USET_DROPPING 0x0100
60#define CONFIGFS_USET_IN_MKDIR 0x0200 61#define CONFIGFS_USET_IN_MKDIR 0x0200
61#define CONFIGFS_USET_CREATING 0x0400 62#define CONFIGFS_USET_CREATING 0x0400
62#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) 63#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR)
63 64
64extern struct mutex configfs_symlink_mutex; 65extern struct mutex configfs_symlink_mutex;
65extern spinlock_t configfs_dirent_lock; 66extern spinlock_t configfs_dirent_lock;
@@ -72,6 +73,8 @@ extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *,
72extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct inode *)); 73extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct inode *));
73 74
74extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); 75extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
76extern int configfs_create_bin_file(struct config_item *,
77 const struct configfs_bin_attribute *);
75extern int configfs_make_dirent(struct configfs_dirent *, 78extern int configfs_make_dirent(struct configfs_dirent *,
76 struct dentry *, void *, umode_t, int); 79 struct dentry *, void *, umode_t, int);
77extern int configfs_dirent_is_ready(struct configfs_dirent *); 80extern int configfs_dirent_is_ready(struct configfs_dirent *);
@@ -88,7 +91,7 @@ extern void configfs_release_fs(void);
88extern struct rw_semaphore configfs_rename_sem; 91extern struct rw_semaphore configfs_rename_sem;
89extern const struct file_operations configfs_dir_operations; 92extern const struct file_operations configfs_dir_operations;
90extern const struct file_operations configfs_file_operations; 93extern const struct file_operations configfs_file_operations;
91extern const struct file_operations bin_fops; 94extern const struct file_operations configfs_bin_file_operations;
92extern const struct inode_operations configfs_dir_inode_operations; 95extern const struct inode_operations configfs_dir_inode_operations;
93extern const struct inode_operations configfs_root_inode_operations; 96extern const struct inode_operations configfs_root_inode_operations;
94extern const struct inode_operations configfs_symlink_inode_operations; 97extern const struct inode_operations configfs_symlink_inode_operations;
@@ -119,6 +122,13 @@ static inline struct configfs_attribute * to_attr(struct dentry * dentry)
119 return ((struct configfs_attribute *) sd->s_element); 122 return ((struct configfs_attribute *) sd->s_element);
120} 123}
121 124
125static inline struct configfs_bin_attribute *to_bin_attr(struct dentry *dentry)
126{
127 struct configfs_attribute *attr = to_attr(dentry);
128
129 return container_of(attr, struct configfs_bin_attribute, cb_attr);
130}
131
122static inline struct config_item *configfs_get_config_item(struct dentry *dentry) 132static inline struct config_item *configfs_get_config_item(struct dentry *dentry)
123{ 133{
124 struct config_item * item = NULL; 134 struct config_item * item = NULL;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index a7a1b218f308..7ae97e83f121 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -255,6 +255,12 @@ static void configfs_init_file(struct inode * inode)
255 inode->i_fop = &configfs_file_operations; 255 inode->i_fop = &configfs_file_operations;
256} 256}
257 257
258static void configfs_init_bin_file(struct inode *inode)
259{
260 inode->i_size = 0;
261 inode->i_fop = &configfs_bin_file_operations;
262}
263
258static void init_symlink(struct inode * inode) 264static void init_symlink(struct inode * inode)
259{ 265{
260 inode->i_op = &configfs_symlink_inode_operations; 266 inode->i_op = &configfs_symlink_inode_operations;
@@ -423,7 +429,9 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
423 spin_unlock(&configfs_dirent_lock); 429 spin_unlock(&configfs_dirent_lock);
424 430
425 error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, 431 error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
426 configfs_init_file); 432 (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) ?
433 configfs_init_bin_file :
434 configfs_init_file);
427 if (error) { 435 if (error) {
428 configfs_put(sd); 436 configfs_put(sd);
429 return error; 437 return error;
@@ -583,6 +591,7 @@ static int populate_attrs(struct config_item *item)
583{ 591{
584 struct config_item_type *t = item->ci_type; 592 struct config_item_type *t = item->ci_type;
585 struct configfs_attribute *attr; 593 struct configfs_attribute *attr;
594 struct configfs_bin_attribute *bin_attr;
586 int error = 0; 595 int error = 0;
587 int i; 596 int i;
588 597
@@ -594,6 +603,13 @@ static int populate_attrs(struct config_item *item)
594 break; 603 break;
595 } 604 }
596 } 605 }
606 if (t->ct_bin_attrs) {
607 for (i = 0; (bin_attr = t->ct_bin_attrs[i]) != NULL; i++) {
608 error = configfs_create_bin_file(item, bin_attr);
609 if (error)
610 break;
611 }
612 }
597 613
598 if (error) 614 if (error)
599 detach_attrs(item); 615 detach_attrs(item);
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index d39099ea7df7..3687187c8ea5 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -28,6 +28,7 @@
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/mutex.h> 30#include <linux/mutex.h>
31#include <linux/vmalloc.h>
31#include <asm/uaccess.h> 32#include <asm/uaccess.h>
32 33
33#include <linux/configfs.h> 34#include <linux/configfs.h>
@@ -48,6 +49,10 @@ struct configfs_buffer {
48 struct configfs_item_operations * ops; 49 struct configfs_item_operations * ops;
49 struct mutex mutex; 50 struct mutex mutex;
50 int needs_read_fill; 51 int needs_read_fill;
52 bool read_in_progress;
53 bool write_in_progress;
54 char *bin_buffer;
55 int bin_buffer_size;
51}; 56};
52 57
53 58
@@ -123,6 +128,87 @@ out:
123 return retval; 128 return retval;
124} 129}
125 130
131/**
132 * configfs_read_bin_file - read a binary attribute.
133 * @file: file pointer.
134 * @buf: buffer to fill.
135 * @count: number of bytes to read.
136 * @ppos: starting offset in file.
137 *
138 * Userspace wants to read a binary attribute file. The attribute
139 * descriptor is in the file's ->d_fsdata. The target item is in the
140 * directory's ->d_fsdata.
141 *
142 * We check whether we need to refill the buffer. If so we will
143 * call the attributes' attr->read() twice. The first time we
144 * will pass a NULL as a buffer pointer, which the attributes' method
145 * will use to return the size of the buffer required. If no error
146 * occurs we will allocate the buffer using vmalloc and call
147 * attr->read() again passing that buffer as an argument.
148 * Then we just copy to user-space using simple_read_from_buffer.
149 */
150
151static ssize_t
152configfs_read_bin_file(struct file *file, char __user *buf,
153 size_t count, loff_t *ppos)
154{
155 struct configfs_buffer *buffer = file->private_data;
156 struct dentry *dentry = file->f_path.dentry;
157 struct config_item *item = to_item(dentry->d_parent);
158 struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
159 ssize_t retval = 0;
160 ssize_t len = min_t(size_t, count, PAGE_SIZE);
161
162 mutex_lock(&buffer->mutex);
163
164 /* we don't support switching read/write modes */
165 if (buffer->write_in_progress) {
166 retval = -ETXTBSY;
167 goto out;
168 }
169 buffer->read_in_progress = 1;
170
171 if (buffer->needs_read_fill) {
172 /* perform first read with buf == NULL to get extent */
173 len = bin_attr->read(item, NULL, 0);
174 if (len <= 0) {
175 retval = len;
176 goto out;
177 }
178
179 /* do not exceed the maximum value */
180 if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) {
181 retval = -EFBIG;
182 goto out;
183 }
184
185 buffer->bin_buffer = vmalloc(len);
186 if (buffer->bin_buffer == NULL) {
187 retval = -ENOMEM;
188 goto out;
189 }
190 buffer->bin_buffer_size = len;
191
192 /* perform second read to fill buffer */
193 len = bin_attr->read(item, buffer->bin_buffer, len);
194 if (len < 0) {
195 retval = len;
196 vfree(buffer->bin_buffer);
197 buffer->bin_buffer_size = 0;
198 buffer->bin_buffer = NULL;
199 goto out;
200 }
201
202 buffer->needs_read_fill = 0;
203 }
204
205 retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer,
206 buffer->bin_buffer_size);
207out:
208 mutex_unlock(&buffer->mutex);
209 return retval;
210}
211
126 212
127/** 213/**
128 * fill_write_buffer - copy buffer from userspace. 214 * fill_write_buffer - copy buffer from userspace.
@@ -209,10 +295,80 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
209 return len; 295 return len;
210} 296}
211 297
212static int check_perm(struct inode * inode, struct file * file) 298/**
299 * configfs_write_bin_file - write a binary attribute.
300 * @file: file pointer
301 * @buf: data to write
302 * @count: number of bytes
303 * @ppos: starting offset
304 *
305 * Writing to a binary attribute file is similar to a normal read.
306 * We buffer the consecutive writes (binary attribute files do not
307 * support lseek) in a continuously growing buffer, but we don't
308 * commit until the close of the file.
309 */
310
311static ssize_t
312configfs_write_bin_file(struct file *file, const char __user *buf,
313 size_t count, loff_t *ppos)
314{
315 struct configfs_buffer *buffer = file->private_data;
316 struct dentry *dentry = file->f_path.dentry;
317 struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
318 void *tbuf = NULL;
319 ssize_t len;
320
321 mutex_lock(&buffer->mutex);
322
323 /* we don't support switching read/write modes */
324 if (buffer->read_in_progress) {
325 len = -ETXTBSY;
326 goto out;
327 }
328 buffer->write_in_progress = 1;
329
330 /* buffer grows? */
331 if (*ppos + count > buffer->bin_buffer_size) {
332
333 if (bin_attr->cb_max_size &&
334 *ppos + count > bin_attr->cb_max_size) {
335 len = -EFBIG;
336 }
337
338 tbuf = vmalloc(*ppos + count);
339 if (tbuf == NULL) {
340 len = -ENOMEM;
341 goto out;
342 }
343
344 /* copy old contents */
345 if (buffer->bin_buffer) {
346 memcpy(tbuf, buffer->bin_buffer,
347 buffer->bin_buffer_size);
348 vfree(buffer->bin_buffer);
349 }
350
351 /* clear the new area */
352 memset(tbuf + buffer->bin_buffer_size, 0,
353 *ppos + count - buffer->bin_buffer_size);
354 buffer->bin_buffer = tbuf;
355 buffer->bin_buffer_size = *ppos + count;
356 }
357
358 len = simple_write_to_buffer(buffer->bin_buffer,
359 buffer->bin_buffer_size, ppos, buf, count);
360 if (len > 0)
361 *ppos += len;
362out:
363 mutex_unlock(&buffer->mutex);
364 return len;
365}
366
367static int check_perm(struct inode * inode, struct file * file, int type)
213{ 368{
214 struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent); 369 struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent);
215 struct configfs_attribute * attr = to_attr(file->f_path.dentry); 370 struct configfs_attribute * attr = to_attr(file->f_path.dentry);
371 struct configfs_bin_attribute *bin_attr = NULL;
216 struct configfs_buffer * buffer; 372 struct configfs_buffer * buffer;
217 struct configfs_item_operations * ops = NULL; 373 struct configfs_item_operations * ops = NULL;
218 int error = 0; 374 int error = 0;
@@ -220,6 +376,9 @@ static int check_perm(struct inode * inode, struct file * file)
220 if (!item || !attr) 376 if (!item || !attr)
221 goto Einval; 377 goto Einval;
222 378
379 if (type & CONFIGFS_ITEM_BIN_ATTR)
380 bin_attr = to_bin_attr(file->f_path.dentry);
381
223 /* Grab the module reference for this attribute if we have one */ 382 /* Grab the module reference for this attribute if we have one */
224 if (!try_module_get(attr->ca_owner)) { 383 if (!try_module_get(attr->ca_owner)) {
225 error = -ENODEV; 384 error = -ENODEV;
@@ -236,9 +395,14 @@ static int check_perm(struct inode * inode, struct file * file)
236 * and we must have a store method. 395 * and we must have a store method.
237 */ 396 */
238 if (file->f_mode & FMODE_WRITE) { 397 if (file->f_mode & FMODE_WRITE) {
239 if (!(inode->i_mode & S_IWUGO) || !attr->store) 398 if (!(inode->i_mode & S_IWUGO))
399 goto Eaccess;
400
401 if ((type & CONFIGFS_ITEM_ATTR) && !attr->store)
240 goto Eaccess; 402 goto Eaccess;
241 403
404 if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->write)
405 goto Eaccess;
242 } 406 }
243 407
244 /* File needs read support. 408 /* File needs read support.
@@ -246,7 +410,13 @@ static int check_perm(struct inode * inode, struct file * file)
246 * must be a show method for it. 410 * must be a show method for it.
247 */ 411 */
248 if (file->f_mode & FMODE_READ) { 412 if (file->f_mode & FMODE_READ) {
249 if (!(inode->i_mode & S_IRUGO) || !attr->show) 413 if (!(inode->i_mode & S_IRUGO))
414 goto Eaccess;
415
416 if ((type & CONFIGFS_ITEM_ATTR) && !attr->show)
417 goto Eaccess;
418
419 if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->read)
250 goto Eaccess; 420 goto Eaccess;
251 } 421 }
252 422
@@ -260,6 +430,8 @@ static int check_perm(struct inode * inode, struct file * file)
260 } 430 }
261 mutex_init(&buffer->mutex); 431 mutex_init(&buffer->mutex);
262 buffer->needs_read_fill = 1; 432 buffer->needs_read_fill = 1;
433 buffer->read_in_progress = 0;
434 buffer->write_in_progress = 0;
263 buffer->ops = ops; 435 buffer->ops = ops;
264 file->private_data = buffer; 436 file->private_data = buffer;
265 goto Done; 437 goto Done;
@@ -277,12 +449,7 @@ static int check_perm(struct inode * inode, struct file * file)
277 return error; 449 return error;
278} 450}
279 451
280static int configfs_open_file(struct inode * inode, struct file * filp) 452static int configfs_release(struct inode *inode, struct file *filp)
281{
282 return check_perm(inode,filp);
283}
284
285static int configfs_release(struct inode * inode, struct file * filp)
286{ 453{
287 struct config_item * item = to_item(filp->f_path.dentry->d_parent); 454 struct config_item * item = to_item(filp->f_path.dentry->d_parent);
288 struct configfs_attribute * attr = to_attr(filp->f_path.dentry); 455 struct configfs_attribute * attr = to_attr(filp->f_path.dentry);
@@ -303,6 +470,47 @@ static int configfs_release(struct inode * inode, struct file * filp)
303 return 0; 470 return 0;
304} 471}
305 472
473static int configfs_open_file(struct inode *inode, struct file *filp)
474{
475 return check_perm(inode, filp, CONFIGFS_ITEM_ATTR);
476}
477
478static int configfs_open_bin_file(struct inode *inode, struct file *filp)
479{
480 return check_perm(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
481}
482
483static int configfs_release_bin_file(struct inode *inode, struct file *filp)
484{
485 struct configfs_buffer *buffer = filp->private_data;
486 struct dentry *dentry = filp->f_path.dentry;
487 struct config_item *item = to_item(dentry->d_parent);
488 struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
489 ssize_t len = 0;
490 int ret;
491
492 buffer->read_in_progress = 0;
493
494 if (buffer->write_in_progress) {
495 buffer->write_in_progress = 0;
496
497 len = bin_attr->write(item, buffer->bin_buffer,
498 buffer->bin_buffer_size);
499
500 /* vfree on NULL is safe */
501 vfree(buffer->bin_buffer);
502 buffer->bin_buffer = NULL;
503 buffer->bin_buffer_size = 0;
504 buffer->needs_read_fill = 1;
505 }
506
507 ret = configfs_release(inode, filp);
508 if (len < 0)
509 return len;
510 return ret;
511}
512
513
306const struct file_operations configfs_file_operations = { 514const struct file_operations configfs_file_operations = {
307 .read = configfs_read_file, 515 .read = configfs_read_file,
308 .write = configfs_write_file, 516 .write = configfs_write_file,
@@ -311,6 +519,14 @@ const struct file_operations configfs_file_operations = {
311 .release = configfs_release, 519 .release = configfs_release,
312}; 520};
313 521
522const struct file_operations configfs_bin_file_operations = {
523 .read = configfs_read_bin_file,
524 .write = configfs_write_bin_file,
525 .llseek = NULL, /* bin file is not seekable */
526 .open = configfs_open_bin_file,
527 .release = configfs_release_bin_file,
528};
529
314/** 530/**
315 * configfs_create_file - create an attribute file for an item. 531 * configfs_create_file - create an attribute file for an item.
316 * @item: item we're creating for. 532 * @item: item we're creating for.
@@ -332,3 +548,24 @@ int configfs_create_file(struct config_item * item, const struct configfs_attrib
332 return error; 548 return error;
333} 549}
334 550
551/**
552 * configfs_create_bin_file - create a binary attribute file for an item.
553 * @item: item we're creating for.
554 * @attr: atrribute descriptor.
555 */
556
557int configfs_create_bin_file(struct config_item *item,
558 const struct configfs_bin_attribute *bin_attr)
559{
560 struct dentry *dir = item->ci_dentry;
561 struct configfs_dirent *parent_sd = dir->d_fsdata;
562 umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG;
563 int error = 0;
564
565 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_NORMAL);
566 error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode,
567 CONFIGFS_ITEM_BIN_ATTR);
568 mutex_unlock(&dir->d_inode->i_mutex);
569
570 return error;
571}
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index eae87575e681..0cc810e9dccc 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -218,7 +218,7 @@ const unsigned char * configfs_get_name(struct configfs_dirent *sd)
218 if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK)) 218 if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK))
219 return sd->s_dentry->d_name.name; 219 return sd->s_dentry->d_name.name;
220 220
221 if (sd->s_type & CONFIGFS_ITEM_ATTR) { 221 if (sd->s_type & (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR)) {
222 attr = sd->s_element; 222 attr = sd->s_element;
223 return attr->ca_name; 223 return attr->ca_name;
224 } 224 }
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index 758a029011b1..f7300d023dbe 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -51,6 +51,7 @@ struct module;
51struct configfs_item_operations; 51struct configfs_item_operations;
52struct configfs_group_operations; 52struct configfs_group_operations;
53struct configfs_attribute; 53struct configfs_attribute;
54struct configfs_bin_attribute;
54struct configfs_subsystem; 55struct configfs_subsystem;
55 56
56struct config_item { 57struct config_item {
@@ -84,6 +85,7 @@ struct config_item_type {
84 struct configfs_item_operations *ct_item_ops; 85 struct configfs_item_operations *ct_item_ops;
85 struct configfs_group_operations *ct_group_ops; 86 struct configfs_group_operations *ct_group_ops;
86 struct configfs_attribute **ct_attrs; 87 struct configfs_attribute **ct_attrs;
88 struct configfs_bin_attribute **ct_bin_attrs;
87}; 89};
88 90
89/** 91/**
@@ -154,6 +156,54 @@ static struct configfs_attribute _pfx##attr_##_name = { \
154 .store = _pfx##_name##_store, \ 156 .store = _pfx##_name##_store, \
155} 157}
156 158
159struct file;
160struct vm_area_struct;
161
162struct configfs_bin_attribute {
163 struct configfs_attribute cb_attr; /* std. attribute */
164 void *cb_private; /* for user */
165 size_t cb_max_size; /* max core size */
166 ssize_t (*read)(struct config_item *, void *, size_t);
167 ssize_t (*write)(struct config_item *, const void *, size_t);
168};
169
170#define CONFIGFS_BIN_ATTR(_pfx, _name, _priv, _maxsz) \
171static struct configfs_bin_attribute _pfx##attr_##_name = { \
172 .cb_attr = { \
173 .ca_name = __stringify(_name), \
174 .ca_mode = S_IRUGO | S_IWUSR, \
175 .ca_owner = THIS_MODULE, \
176 }, \
177 .cb_private = _priv, \
178 .cb_max_size = _maxsz, \
179 .read = _pfx##_name##_read, \
180 .write = _pfx##_name##_write, \
181}
182
183#define CONFIGFS_BIN_ATTR_RO(_pfx, _name, _priv, _maxsz) \
184static struct configfs_attribute _pfx##attr_##_name = { \
185 .cb_attr = { \
186 .ca_name = __stringify(_name), \
187 .ca_mode = S_IRUGO, \
188 .ca_owner = THIS_MODULE, \
189 }, \
190 .cb_private = _priv, \
191 .cb_max_size = _maxsz, \
192 .read = _pfx##_name##_read, \
193}
194
195#define CONFIGFS_BIN_ATTR_WO(_pfx, _name, _priv, _maxsz) \
196static struct configfs_attribute _pfx##attr_##_name = { \
197 .cb_attr = { \
198 .ca_name = __stringify(_name), \
199 .ca_mode = S_IWUSR, \
200 .ca_owner = THIS_MODULE, \
201 }, \
202 .cb_private = _priv, \
203 .cb_max_size = _maxsz, \
204 .write = _pfx##_name##_write, \
205}
206
157/* 207/*
158 * If allow_link() exists, the item can symlink(2) out to other 208 * If allow_link() exists, the item can symlink(2) out to other
159 * items. If the item is a group, it may support mkdir(2). 209 * items. If the item is a group, it may support mkdir(2).