brcm2708: update linux 4.4 patches to latest version
[openwrt/staging/wigyori.git] / target / linux / brcm2708 / patches-4.4 / 0177-configfs-implement-binary-attributes.patch
1 From 76827059f7092a0d871db592abdfd287e4d4cb60 Mon Sep 17 00:00:00 2001
2 From: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
3 Date: Thu, 22 Oct 2015 23:30:04 +0300
4 Subject: [PATCH] configfs: implement binary attributes
5
6 ConfigFS lacked binary attributes up until now. This patch
7 introduces support for binary attributes in a somewhat similar
8 manner of sysfs binary attributes albeit with changes that
9 fit the configfs usage model.
10
11 Problems that configfs binary attributes fix are everything that
12 requires a binary blob as part of the configuration of a resource,
13 such as bitstream loading for FPGAs, DTBs for dynamically created
14 devices etc.
15
16 Look at Documentation/filesystems/configfs/configfs.txt for internals
17 and howto use them.
18
19 This patch is against linux-next as of today that contains
20 Christoph's configfs rework.
21
22 Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
23 [hch: folded a fix from Geert Uytterhoeven <geert+renesas@glider.be>]
24 [hch: a few tiny updates based on review feedback]
25 Signed-off-by: Christoph Hellwig <hch@lst.de>
26 ---
27 Documentation/filesystems/configfs/configfs.txt | 57 +++++-
28 fs/configfs/configfs_internal.h | 14 +-
29 fs/configfs/dir.c | 18 +-
30 fs/configfs/file.c | 255 +++++++++++++++++++++++-
31 fs/configfs/inode.c | 2 +-
32 include/linux/configfs.h | 50 +++++
33 6 files changed, 374 insertions(+), 22 deletions(-)
34
35 --- a/Documentation/filesystems/configfs/configfs.txt
36 +++ b/Documentation/filesystems/configfs/configfs.txt
37 @@ -51,15 +51,27 @@ configfs tree is always there, whether m
38 An item is created via mkdir(2). The item's attributes will also
39 appear at this time. readdir(3) can determine what the attributes are,
40 read(2) can query their default values, and write(2) can store new
41 -values. Like sysfs, attributes should be ASCII text files, preferably
42 -with only one value per file. The same efficiency caveats from sysfs
43 -apply. Don't mix more than one attribute in one attribute file.
44 -
45 -Like sysfs, configfs expects write(2) to store the entire buffer at
46 -once. When writing to configfs attributes, userspace processes should
47 -first read the entire file, modify the portions they wish to change, and
48 -then write the entire buffer back. Attribute files have a maximum size
49 -of one page (PAGE_SIZE, 4096 on i386).
50 +values. Don't mix more than one attribute in one attribute file.
51 +
52 +There are two types of configfs attributes:
53 +
54 +* Normal attributes, which similar to sysfs attributes, are small ASCII text
55 +files, with a maximum size of one page (PAGE_SIZE, 4096 on i386). Preferably
56 +only one value per file should be used, and the same caveats from sysfs apply.
57 +Configfs expects write(2) to store the entire buffer at once. When writing to
58 +normal configfs attributes, userspace processes should first read the entire
59 +file, modify the portions they wish to change, and then write the entire
60 +buffer back.
61 +
62 +* Binary attributes, which are somewhat similar to sysfs binary attributes,
63 +but with a few slight changes to semantics. The PAGE_SIZE limitation does not
64 +apply, but the whole binary item must fit in single kernel vmalloc'ed buffer.
65 +The write(2) calls from user space are buffered, and the attributes'
66 +write_bin_attribute method will be invoked on the final close, therefore it is
67 +imperative for user-space to check the return code of close(2) in order to
68 +verify that the operation finished successfully.
69 +To avoid a malicious user OOMing the kernel, there's a per-binary attribute
70 +maximum buffer value.
71
72 When an item needs to be destroyed, remove it with rmdir(2). An
73 item cannot be destroyed if any other item has a link to it (via
74 @@ -171,6 +183,7 @@ among other things. For that, it needs
75 struct configfs_item_operations *ct_item_ops;
76 struct configfs_group_operations *ct_group_ops;
77 struct configfs_attribute **ct_attrs;
78 + struct configfs_bin_attribute **ct_bin_attrs;
79 };
80
81 The most basic function of a config_item_type is to define what
82 @@ -201,6 +214,32 @@ be called whenever userspace asks for a
83 attribute is writable and provides a ->store method, that method will be
84 be called whenever userspace asks for a write(2) on the attribute.
85
86 +[struct configfs_bin_attribute]
87 +
88 + struct configfs_attribute {
89 + struct configfs_attribute cb_attr;
90 + void *cb_private;
91 + size_t cb_max_size;
92 + };
93 +
94 +The binary attribute is used when the one needs to use binary blob to
95 +appear as the contents of a file in the item's configfs directory.
96 +To do so add the binary attribute to the NULL-terminated array
97 +config_item_type->ct_bin_attrs, and the item appears in configfs, the
98 +attribute file will appear with the configfs_bin_attribute->cb_attr.ca_name
99 +filename. configfs_bin_attribute->cb_attr.ca_mode specifies the file
100 +permissions.
101 +The cb_private member is provided for use by the driver, while the
102 +cb_max_size member specifies the maximum amount of vmalloc buffer
103 +to be used.
104 +
105 +If binary attribute is readable and the config_item provides a
106 +ct_item_ops->read_bin_attribute() method, that method will be called
107 +whenever userspace asks for a read(2) on the attribute. The converse
108 +will happen for write(2). The reads/writes are bufferred so only a
109 +single read/write will occur; the attributes' need not concern itself
110 +with it.
111 +
112 [struct config_group]
113
114 A config_item cannot live in a vacuum. The only way one can be created
115 --- a/fs/configfs/configfs_internal.h
116 +++ b/fs/configfs/configfs_internal.h
117 @@ -53,13 +53,14 @@ struct configfs_dirent {
118 #define CONFIGFS_ROOT 0x0001
119 #define CONFIGFS_DIR 0x0002
120 #define CONFIGFS_ITEM_ATTR 0x0004
121 +#define CONFIGFS_ITEM_BIN_ATTR 0x0008
122 #define CONFIGFS_ITEM_LINK 0x0020
123 #define CONFIGFS_USET_DIR 0x0040
124 #define CONFIGFS_USET_DEFAULT 0x0080
125 #define CONFIGFS_USET_DROPPING 0x0100
126 #define CONFIGFS_USET_IN_MKDIR 0x0200
127 #define CONFIGFS_USET_CREATING 0x0400
128 -#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR)
129 +#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR)
130
131 extern struct mutex configfs_symlink_mutex;
132 extern spinlock_t configfs_dirent_lock;
133 @@ -72,6 +73,8 @@ extern struct inode * configfs_new_inode
134 extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct inode *));
135
136 extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
137 +extern int configfs_create_bin_file(struct config_item *,
138 + const struct configfs_bin_attribute *);
139 extern int configfs_make_dirent(struct configfs_dirent *,
140 struct dentry *, void *, umode_t, int);
141 extern int configfs_dirent_is_ready(struct configfs_dirent *);
142 @@ -88,7 +91,7 @@ extern void configfs_release_fs(void);
143 extern struct rw_semaphore configfs_rename_sem;
144 extern const struct file_operations configfs_dir_operations;
145 extern const struct file_operations configfs_file_operations;
146 -extern const struct file_operations bin_fops;
147 +extern const struct file_operations configfs_bin_file_operations;
148 extern const struct inode_operations configfs_dir_inode_operations;
149 extern const struct inode_operations configfs_root_inode_operations;
150 extern const struct inode_operations configfs_symlink_inode_operations;
151 @@ -119,6 +122,13 @@ static inline struct configfs_attribute
152 return ((struct configfs_attribute *) sd->s_element);
153 }
154
155 +static inline struct configfs_bin_attribute *to_bin_attr(struct dentry *dentry)
156 +{
157 + struct configfs_attribute *attr = to_attr(dentry);
158 +
159 + return container_of(attr, struct configfs_bin_attribute, cb_attr);
160 +}
161 +
162 static inline struct config_item *configfs_get_config_item(struct dentry *dentry)
163 {
164 struct config_item * item = NULL;
165 --- a/fs/configfs/dir.c
166 +++ b/fs/configfs/dir.c
167 @@ -255,6 +255,12 @@ static void configfs_init_file(struct in
168 inode->i_fop = &configfs_file_operations;
169 }
170
171 +static void configfs_init_bin_file(struct inode *inode)
172 +{
173 + inode->i_size = 0;
174 + inode->i_fop = &configfs_bin_file_operations;
175 +}
176 +
177 static void init_symlink(struct inode * inode)
178 {
179 inode->i_op = &configfs_symlink_inode_operations;
180 @@ -423,7 +429,9 @@ static int configfs_attach_attr(struct c
181 spin_unlock(&configfs_dirent_lock);
182
183 error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
184 - configfs_init_file);
185 + (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) ?
186 + configfs_init_bin_file :
187 + configfs_init_file);
188 if (error) {
189 configfs_put(sd);
190 return error;
191 @@ -583,6 +591,7 @@ static int populate_attrs(struct config_
192 {
193 struct config_item_type *t = item->ci_type;
194 struct configfs_attribute *attr;
195 + struct configfs_bin_attribute *bin_attr;
196 int error = 0;
197 int i;
198
199 @@ -594,6 +603,13 @@ static int populate_attrs(struct config_
200 break;
201 }
202 }
203 + if (t->ct_bin_attrs) {
204 + for (i = 0; (bin_attr = t->ct_bin_attrs[i]) != NULL; i++) {
205 + error = configfs_create_bin_file(item, bin_attr);
206 + if (error)
207 + break;
208 + }
209 + }
210
211 if (error)
212 detach_attrs(item);
213 --- a/fs/configfs/file.c
214 +++ b/fs/configfs/file.c
215 @@ -28,6 +28,7 @@
216 #include <linux/module.h>
217 #include <linux/slab.h>
218 #include <linux/mutex.h>
219 +#include <linux/vmalloc.h>
220 #include <asm/uaccess.h>
221
222 #include <linux/configfs.h>
223 @@ -48,6 +49,10 @@ struct configfs_buffer {
224 struct configfs_item_operations * ops;
225 struct mutex mutex;
226 int needs_read_fill;
227 + bool read_in_progress;
228 + bool write_in_progress;
229 + char *bin_buffer;
230 + int bin_buffer_size;
231 };
232
233
234 @@ -123,6 +128,87 @@ out:
235 return retval;
236 }
237
238 +/**
239 + * configfs_read_bin_file - read a binary attribute.
240 + * @file: file pointer.
241 + * @buf: buffer to fill.
242 + * @count: number of bytes to read.
243 + * @ppos: starting offset in file.
244 + *
245 + * Userspace wants to read a binary attribute file. The attribute
246 + * descriptor is in the file's ->d_fsdata. The target item is in the
247 + * directory's ->d_fsdata.
248 + *
249 + * We check whether we need to refill the buffer. If so we will
250 + * call the attributes' attr->read() twice. The first time we
251 + * will pass a NULL as a buffer pointer, which the attributes' method
252 + * will use to return the size of the buffer required. If no error
253 + * occurs we will allocate the buffer using vmalloc and call
254 + * attr->read() again passing that buffer as an argument.
255 + * Then we just copy to user-space using simple_read_from_buffer.
256 + */
257 +
258 +static ssize_t
259 +configfs_read_bin_file(struct file *file, char __user *buf,
260 + size_t count, loff_t *ppos)
261 +{
262 + struct configfs_buffer *buffer = file->private_data;
263 + struct dentry *dentry = file->f_path.dentry;
264 + struct config_item *item = to_item(dentry->d_parent);
265 + struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
266 + ssize_t retval = 0;
267 + ssize_t len = min_t(size_t, count, PAGE_SIZE);
268 +
269 + mutex_lock(&buffer->mutex);
270 +
271 + /* we don't support switching read/write modes */
272 + if (buffer->write_in_progress) {
273 + retval = -ETXTBSY;
274 + goto out;
275 + }
276 + buffer->read_in_progress = 1;
277 +
278 + if (buffer->needs_read_fill) {
279 + /* perform first read with buf == NULL to get extent */
280 + len = bin_attr->read(item, NULL, 0);
281 + if (len <= 0) {
282 + retval = len;
283 + goto out;
284 + }
285 +
286 + /* do not exceed the maximum value */
287 + if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) {
288 + retval = -EFBIG;
289 + goto out;
290 + }
291 +
292 + buffer->bin_buffer = vmalloc(len);
293 + if (buffer->bin_buffer == NULL) {
294 + retval = -ENOMEM;
295 + goto out;
296 + }
297 + buffer->bin_buffer_size = len;
298 +
299 + /* perform second read to fill buffer */
300 + len = bin_attr->read(item, buffer->bin_buffer, len);
301 + if (len < 0) {
302 + retval = len;
303 + vfree(buffer->bin_buffer);
304 + buffer->bin_buffer_size = 0;
305 + buffer->bin_buffer = NULL;
306 + goto out;
307 + }
308 +
309 + buffer->needs_read_fill = 0;
310 + }
311 +
312 + retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer,
313 + buffer->bin_buffer_size);
314 +out:
315 + mutex_unlock(&buffer->mutex);
316 + return retval;
317 +}
318 +
319
320 /**
321 * fill_write_buffer - copy buffer from userspace.
322 @@ -209,10 +295,80 @@ configfs_write_file(struct file *file, c
323 return len;
324 }
325
326 -static int check_perm(struct inode * inode, struct file * file)
327 +/**
328 + * configfs_write_bin_file - write a binary attribute.
329 + * @file: file pointer
330 + * @buf: data to write
331 + * @count: number of bytes
332 + * @ppos: starting offset
333 + *
334 + * Writing to a binary attribute file is similar to a normal read.
335 + * We buffer the consecutive writes (binary attribute files do not
336 + * support lseek) in a continuously growing buffer, but we don't
337 + * commit until the close of the file.
338 + */
339 +
340 +static ssize_t
341 +configfs_write_bin_file(struct file *file, const char __user *buf,
342 + size_t count, loff_t *ppos)
343 +{
344 + struct configfs_buffer *buffer = file->private_data;
345 + struct dentry *dentry = file->f_path.dentry;
346 + struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
347 + void *tbuf = NULL;
348 + ssize_t len;
349 +
350 + mutex_lock(&buffer->mutex);
351 +
352 + /* we don't support switching read/write modes */
353 + if (buffer->read_in_progress) {
354 + len = -ETXTBSY;
355 + goto out;
356 + }
357 + buffer->write_in_progress = 1;
358 +
359 + /* buffer grows? */
360 + if (*ppos + count > buffer->bin_buffer_size) {
361 +
362 + if (bin_attr->cb_max_size &&
363 + *ppos + count > bin_attr->cb_max_size) {
364 + len = -EFBIG;
365 + }
366 +
367 + tbuf = vmalloc(*ppos + count);
368 + if (tbuf == NULL) {
369 + len = -ENOMEM;
370 + goto out;
371 + }
372 +
373 + /* copy old contents */
374 + if (buffer->bin_buffer) {
375 + memcpy(tbuf, buffer->bin_buffer,
376 + buffer->bin_buffer_size);
377 + vfree(buffer->bin_buffer);
378 + }
379 +
380 + /* clear the new area */
381 + memset(tbuf + buffer->bin_buffer_size, 0,
382 + *ppos + count - buffer->bin_buffer_size);
383 + buffer->bin_buffer = tbuf;
384 + buffer->bin_buffer_size = *ppos + count;
385 + }
386 +
387 + len = simple_write_to_buffer(buffer->bin_buffer,
388 + buffer->bin_buffer_size, ppos, buf, count);
389 + if (len > 0)
390 + *ppos += len;
391 +out:
392 + mutex_unlock(&buffer->mutex);
393 + return len;
394 +}
395 +
396 +static int check_perm(struct inode * inode, struct file * file, int type)
397 {
398 struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent);
399 struct configfs_attribute * attr = to_attr(file->f_path.dentry);
400 + struct configfs_bin_attribute *bin_attr = NULL;
401 struct configfs_buffer * buffer;
402 struct configfs_item_operations * ops = NULL;
403 int error = 0;
404 @@ -220,6 +376,9 @@ static int check_perm(struct inode * ino
405 if (!item || !attr)
406 goto Einval;
407
408 + if (type & CONFIGFS_ITEM_BIN_ATTR)
409 + bin_attr = to_bin_attr(file->f_path.dentry);
410 +
411 /* Grab the module reference for this attribute if we have one */
412 if (!try_module_get(attr->ca_owner)) {
413 error = -ENODEV;
414 @@ -236,9 +395,14 @@ static int check_perm(struct inode * ino
415 * and we must have a store method.
416 */
417 if (file->f_mode & FMODE_WRITE) {
418 - if (!(inode->i_mode & S_IWUGO) || !attr->store)
419 + if (!(inode->i_mode & S_IWUGO))
420 goto Eaccess;
421
422 + if ((type & CONFIGFS_ITEM_ATTR) && !attr->store)
423 + goto Eaccess;
424 +
425 + if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->write)
426 + goto Eaccess;
427 }
428
429 /* File needs read support.
430 @@ -246,7 +410,13 @@ static int check_perm(struct inode * ino
431 * must be a show method for it.
432 */
433 if (file->f_mode & FMODE_READ) {
434 - if (!(inode->i_mode & S_IRUGO) || !attr->show)
435 + if (!(inode->i_mode & S_IRUGO))
436 + goto Eaccess;
437 +
438 + if ((type & CONFIGFS_ITEM_ATTR) && !attr->show)
439 + goto Eaccess;
440 +
441 + if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->read)
442 goto Eaccess;
443 }
444
445 @@ -260,6 +430,8 @@ static int check_perm(struct inode * ino
446 }
447 mutex_init(&buffer->mutex);
448 buffer->needs_read_fill = 1;
449 + buffer->read_in_progress = 0;
450 + buffer->write_in_progress = 0;
451 buffer->ops = ops;
452 file->private_data = buffer;
453 goto Done;
454 @@ -277,12 +449,7 @@ static int check_perm(struct inode * ino
455 return error;
456 }
457
458 -static int configfs_open_file(struct inode * inode, struct file * filp)
459 -{
460 - return check_perm(inode,filp);
461 -}
462 -
463 -static int configfs_release(struct inode * inode, struct file * filp)
464 +static int configfs_release(struct inode *inode, struct file *filp)
465 {
466 struct config_item * item = to_item(filp->f_path.dentry->d_parent);
467 struct configfs_attribute * attr = to_attr(filp->f_path.dentry);
468 @@ -303,6 +470,47 @@ static int configfs_release(struct inode
469 return 0;
470 }
471
472 +static int configfs_open_file(struct inode *inode, struct file *filp)
473 +{
474 + return check_perm(inode, filp, CONFIGFS_ITEM_ATTR);
475 +}
476 +
477 +static int configfs_open_bin_file(struct inode *inode, struct file *filp)
478 +{
479 + return check_perm(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
480 +}
481 +
482 +static int configfs_release_bin_file(struct inode *inode, struct file *filp)
483 +{
484 + struct configfs_buffer *buffer = filp->private_data;
485 + struct dentry *dentry = filp->f_path.dentry;
486 + struct config_item *item = to_item(dentry->d_parent);
487 + struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
488 + ssize_t len = 0;
489 + int ret;
490 +
491 + buffer->read_in_progress = 0;
492 +
493 + if (buffer->write_in_progress) {
494 + buffer->write_in_progress = 0;
495 +
496 + len = bin_attr->write(item, buffer->bin_buffer,
497 + buffer->bin_buffer_size);
498 +
499 + /* vfree on NULL is safe */
500 + vfree(buffer->bin_buffer);
501 + buffer->bin_buffer = NULL;
502 + buffer->bin_buffer_size = 0;
503 + buffer->needs_read_fill = 1;
504 + }
505 +
506 + ret = configfs_release(inode, filp);
507 + if (len < 0)
508 + return len;
509 + return ret;
510 +}
511 +
512 +
513 const struct file_operations configfs_file_operations = {
514 .read = configfs_read_file,
515 .write = configfs_write_file,
516 @@ -311,6 +519,14 @@ const struct file_operations configfs_fi
517 .release = configfs_release,
518 };
519
520 +const struct file_operations configfs_bin_file_operations = {
521 + .read = configfs_read_bin_file,
522 + .write = configfs_write_bin_file,
523 + .llseek = NULL, /* bin file is not seekable */
524 + .open = configfs_open_bin_file,
525 + .release = configfs_release_bin_file,
526 +};
527 +
528 /**
529 * configfs_create_file - create an attribute file for an item.
530 * @item: item we're creating for.
531 @@ -332,3 +548,24 @@ int configfs_create_file(struct config_i
532 return error;
533 }
534
535 +/**
536 + * configfs_create_bin_file - create a binary attribute file for an item.
537 + * @item: item we're creating for.
538 + * @attr: atrribute descriptor.
539 + */
540 +
541 +int configfs_create_bin_file(struct config_item *item,
542 + const struct configfs_bin_attribute *bin_attr)
543 +{
544 + struct dentry *dir = item->ci_dentry;
545 + struct configfs_dirent *parent_sd = dir->d_fsdata;
546 + umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG;
547 + int error = 0;
548 +
549 + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_NORMAL);
550 + error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode,
551 + CONFIGFS_ITEM_BIN_ATTR);
552 + mutex_unlock(&dir->d_inode->i_mutex);
553 +
554 + return error;
555 +}
556 --- a/fs/configfs/inode.c
557 +++ b/fs/configfs/inode.c
558 @@ -218,7 +218,7 @@ const unsigned char * configfs_get_name(
559 if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK))
560 return sd->s_dentry->d_name.name;
561
562 - if (sd->s_type & CONFIGFS_ITEM_ATTR) {
563 + if (sd->s_type & (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR)) {
564 attr = sd->s_element;
565 return attr->ca_name;
566 }
567 --- a/include/linux/configfs.h
568 +++ b/include/linux/configfs.h
569 @@ -51,6 +51,7 @@ struct module;
570 struct configfs_item_operations;
571 struct configfs_group_operations;
572 struct configfs_attribute;
573 +struct configfs_bin_attribute;
574 struct configfs_subsystem;
575
576 struct config_item {
577 @@ -84,6 +85,7 @@ struct config_item_type {
578 struct configfs_item_operations *ct_item_ops;
579 struct configfs_group_operations *ct_group_ops;
580 struct configfs_attribute **ct_attrs;
581 + struct configfs_bin_attribute **ct_bin_attrs;
582 };
583
584 /**
585 @@ -154,6 +156,54 @@ static struct configfs_attribute _pfx##a
586 .store = _pfx##_name##_store, \
587 }
588
589 +struct file;
590 +struct vm_area_struct;
591 +
592 +struct configfs_bin_attribute {
593 + struct configfs_attribute cb_attr; /* std. attribute */
594 + void *cb_private; /* for user */
595 + size_t cb_max_size; /* max core size */
596 + ssize_t (*read)(struct config_item *, void *, size_t);
597 + ssize_t (*write)(struct config_item *, const void *, size_t);
598 +};
599 +
600 +#define CONFIGFS_BIN_ATTR(_pfx, _name, _priv, _maxsz) \
601 +static struct configfs_bin_attribute _pfx##attr_##_name = { \
602 + .cb_attr = { \
603 + .ca_name = __stringify(_name), \
604 + .ca_mode = S_IRUGO | S_IWUSR, \
605 + .ca_owner = THIS_MODULE, \
606 + }, \
607 + .cb_private = _priv, \
608 + .cb_max_size = _maxsz, \
609 + .read = _pfx##_name##_read, \
610 + .write = _pfx##_name##_write, \
611 +}
612 +
613 +#define CONFIGFS_BIN_ATTR_RO(_pfx, _name, _priv, _maxsz) \
614 +static struct configfs_attribute _pfx##attr_##_name = { \
615 + .cb_attr = { \
616 + .ca_name = __stringify(_name), \
617 + .ca_mode = S_IRUGO, \
618 + .ca_owner = THIS_MODULE, \
619 + }, \
620 + .cb_private = _priv, \
621 + .cb_max_size = _maxsz, \
622 + .read = _pfx##_name##_read, \
623 +}
624 +
625 +#define CONFIGFS_BIN_ATTR_WO(_pfx, _name, _priv, _maxsz) \
626 +static struct configfs_attribute _pfx##attr_##_name = { \
627 + .cb_attr = { \
628 + .ca_name = __stringify(_name), \
629 + .ca_mode = S_IWUSR, \
630 + .ca_owner = THIS_MODULE, \
631 + }, \
632 + .cb_private = _priv, \
633 + .cb_max_size = _maxsz, \
634 + .write = _pfx##_name##_write, \
635 +}
636 +
637 /*
638 * If allow_link() exists, the item can symlink(2) out to other
639 * items. If the item is a group, it may support mkdir(2).