Remove the old show_attribute and store_attribute methods and update the documentation. Also replace the two C samples with a single new one in the proper samples directory where people expect to find it.
Unified · Split
| @@ -1,5 +1,3 @@ | ||
| 1 | −subdir-y := configfs | |
| 2 | − | |
| 3 | 1 | # List of programs to build |
| 4 | 2 | hostprogs-y := dnotify_test |
| 5 | 3 | |
| @@ -1,3 +0,0 @@ | ||
| 1 | −ifneq ($(CONFIG_CONFIGFS_FS),) | |
| 2 | −obj-m += configfs_example_explicit.o configfs_example_macros.o | |
| 3 | −endif | |
| @@ -160,12 +160,6 @@ among other things. For that, it needs a type. · 159 unmodified lines | ||
| 160 | 160 | |
| 161 | 161 | struct configfs_item_operations { |
| 162 | 162 | void (*release)(struct config_item *); |
| 163 | − ssize_t (*show_attribute)(struct config_item *, | |
| 164 | − struct configfs_attribute *, | |
| 165 | − char *); | |
| 166 | − ssize_t (*store_attribute)(struct config_item *, | |
| 167 | − struct configfs_attribute *, | |
| 168 | − const char *, size_t); | |
| 169 | 163 | int (*allow_link)(struct config_item *src, |
| 170 | 164 | struct config_item *target); |
| 171 | 165 | int (*drop_link)(struct config_item *src, |
| @@ -183,9 +177,7 @@ The most basic function of a config_item_type is to define what · 11 unmodified lines | ||
| 183 | 177 | operations can be performed on a config_item. All items that have been |
| 184 | 178 | allocated dynamically will need to provide the ct_item_ops->release() |
| 185 | 179 | method. This method is called when the config_item's reference count |
| 186 | −reaches zero. Items that wish to display an attribute need to provide | |
| 187 | −the ct_item_ops->show_attribute() method. Similarly, storing a new | |
| 188 | −attribute value uses the store_attribute() method. | |
| 180 | +reaches zero. | |
| 189 | 181 | |
| 190 | 182 | [struct configfs_attribute] |
| 191 | 183 | |
| @@ -193,6 +185,8 @@ attribute value uses the store_attribute() method. · 1 unmodified line | ||
| 193 | 185 | char *ca_name; |
| 194 | 186 | struct module *ca_owner; |
| 195 | 187 | umode_t ca_mode; |
| 188 | + ssize_t (*show)(struct config_item *, char *); | |
| 189 | + ssize_t (*store)(struct config_item *, const char *, size_t); | |
| 196 | 190 | }; |
| 197 | 191 | |
| 198 | 192 | When a config_item wants an attribute to appear as a file in the item's |
| @@ -202,10 +196,10 @@ config_item_type->ct_attrs. When the item appears in configfs, the · 3 unmodified lines | ||
| 202 | 196 | attribute file will appear with the configfs_attribute->ca_name |
| 203 | 197 | filename. configfs_attribute->ca_mode specifies the file permissions. |
| 204 | 198 | |
| 205 | −If an attribute is readable and the config_item provides a | |
| 206 | −ct_item_ops->show_attribute() method, that method will be called | |
| 207 | −whenever userspace asks for a read(2) on the attribute. The converse | |
| 208 | −will happen for write(2). | |
| 199 | +If an attribute is readable and provides a ->show method, that method will | |
| 200 | +be called whenever userspace asks for a read(2) on the attribute. If an | |
| 201 | +attribute is writable and provides a ->store method, that method will be | |
| 202 | +be called whenever userspace asks for a write(2) on the attribute. | |
| 209 | 203 | |
| 210 | 204 | [struct config_group] |
| 211 | 205 | |
| @@ -311,20 +305,10 @@ the subsystem must be ready for it. · 99 unmodified lines | ||
| 311 | 305 | [An Example] |
| 312 | 306 | |
| 313 | 307 | The best example of these basic concepts is the simple_children |
| 314 | −subsystem/group and the simple_child item in configfs_example_explicit.c | |
| 315 | −and configfs_example_macros.c. It shows a trivial object displaying and | |
| 316 | −storing an attribute, and a simple group creating and destroying these | |
| 317 | −children. | |
| 318 | − | |
| 319 | −The only difference between configfs_example_explicit.c and | |
| 320 | −configfs_example_macros.c is how the attributes of the childless item | |
| 321 | −are defined. The childless item has extended attributes, each with | |
| 322 | −their own show()/store() operation. This follows a convention commonly | |
| 323 | −used in sysfs. configfs_example_explicit.c creates these attributes | |
| 324 | −by explicitly defining the structures involved. Conversely | |
| 325 | −configfs_example_macros.c uses some convenience macros from configfs.h | |
| 326 | −to define the attributes. These macros are similar to their sysfs | |
| 327 | −counterparts. | |
| 308 | +subsystem/group and the simple_child item in | |
| 309 | +samples/configfs/configfs_sample.c. It shows a trivial object displaying | |
| 310 | +and storing an attribute, and a simple group creating and destroying | |
| 311 | +these children. | |
| 328 | 312 | |
| 329 | 313 | [Hierarchy Navigation and the Subsystem Mutex] |
| 330 | 314 | |
| @@ -1,483 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * vim: noexpandtab ts=8 sts=0 sw=8: | |
| 3 | − * | |
| 4 | − * configfs_example_explicit.c - This file is a demonstration module | |
| 5 | − * containing a number of configfs subsystems. It explicitly defines | |
| 6 | − * each structure without using the helper macros defined in | |
| 7 | − * configfs.h. | |
| 8 | − * | |
| 9 | − * This program is free software; you can redistribute it and/or | |
| 10 | − * modify it under the terms of the GNU General Public | |
| 11 | − * License as published by the Free Software Foundation; either | |
| 12 | − * version 2 of the License, or (at your option) any later version. | |
| 13 | − * | |
| 14 | − * This program is distributed in the hope that it will be useful, | |
| 15 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 17 | − * General Public License for more details. | |
| 18 | − * | |
| 19 | − * You should have received a copy of the GNU General Public | |
| 20 | − * License along with this program; if not, write to the | |
| 21 | − * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 22 | − * Boston, MA 021110-1307, USA. | |
| 23 | − * | |
| 24 | − * Based on sysfs: | |
| 25 | − * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel | |
| 26 | − * | |
| 27 | − * configfs Copyright (C) 2005 Oracle. All rights reserved. | |
| 28 | − */ | |
| 29 | − | |
| 30 | −#include <linux/init.h> | |
| 31 | −#include <linux/module.h> | |
| 32 | −#include <linux/slab.h> | |
| 33 | − | |
| 34 | −#include <linux/configfs.h> | |
| 35 | − | |
| 36 | − | |
| 37 | − | |
| 38 | −/* | |
| 39 | − * 01-childless | |
| 40 | − * | |
| 41 | − * This first example is a childless subsystem. It cannot create | |
| 42 | − * any config_items. It just has attributes. | |
| 43 | − * | |
| 44 | − * Note that we are enclosing the configfs_subsystem inside a container. | |
| 45 | − * This is not necessary if a subsystem has no attributes directly | |
| 46 | − * on the subsystem. See the next example, 02-simple-children, for | |
| 47 | − * such a subsystem. | |
| 48 | − */ | |
| 49 | − | |
| 50 | −struct childless { | |
| 51 | − struct configfs_subsystem subsys; | |
| 52 | − int showme; | |
| 53 | − int storeme; | |
| 54 | −}; | |
| 55 | − | |
| 56 | −struct childless_attribute { | |
| 57 | − struct configfs_attribute attr; | |
| 58 | − ssize_t (*show)(struct childless *, char *); | |
| 59 | − ssize_t (*store)(struct childless *, const char *, size_t); | |
| 60 | −}; | |
| 61 | − | |
| 62 | −static inline struct childless *to_childless(struct config_item *item) | |
| 63 | −{ | |
| 64 | − return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL; | |
| 65 | −} | |
| 66 | − | |
| 67 | −static ssize_t childless_showme_read(struct childless *childless, | |
| 68 | − char *page) | |
| 69 | −{ | |
| 70 | − ssize_t pos; | |
| 71 | − | |
| 72 | − pos = sprintf(page, "%d\n", childless->showme); | |
| 73 | − childless->showme++; | |
| 74 | − | |
| 75 | − return pos; | |
| 76 | −} | |
| 77 | − | |
| 78 | −static ssize_t childless_storeme_read(struct childless *childless, | |
| 79 | − char *page) | |
| 80 | −{ | |
| 81 | − return sprintf(page, "%d\n", childless->storeme); | |
| 82 | −} | |
| 83 | − | |
| 84 | −static ssize_t childless_storeme_write(struct childless *childless, | |
| 85 | − const char *page, | |
| 86 | − size_t count) | |
| 87 | −{ | |
| 88 | − unsigned long tmp; | |
| 89 | − char *p = (char *) page; | |
| 90 | − | |
| 91 | − tmp = simple_strtoul(p, &p, 10); | |
| 92 | − if ((*p != '\0') && (*p != '\n')) | |
| 93 | − return -EINVAL; | |
| 94 | − | |
| 95 | − if (tmp > INT_MAX) | |
| 96 | − return -ERANGE; | |
| 97 | − | |
| 98 | − childless->storeme = tmp; | |
| 99 | − | |
| 100 | − return count; | |
| 101 | −} | |
| 102 | − | |
| 103 | −static ssize_t childless_description_read(struct childless *childless, | |
| 104 | − char *page) | |
| 105 | −{ | |
| 106 | − return sprintf(page, | |
| 107 | −"[01-childless]\n" | |
| 108 | −"\n" | |
| 109 | −"The childless subsystem is the simplest possible subsystem in\n" | |
| 110 | −"configfs. It does not support the creation of child config_items.\n" | |
| 111 | −"It only has a few attributes. In fact, it isn't much different\n" | |
| 112 | −"than a directory in /proc.\n"); | |
| 113 | −} | |
| 114 | − | |
| 115 | −static struct childless_attribute childless_attr_showme = { | |
| 116 | − .attr = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO }, | |
| 117 | − .show = childless_showme_read, | |
| 118 | −}; | |
| 119 | −static struct childless_attribute childless_attr_storeme = { | |
| 120 | − .attr = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR }, | |
| 121 | − .show = childless_storeme_read, | |
| 122 | − .store = childless_storeme_write, | |
| 123 | −}; | |
| 124 | −static struct childless_attribute childless_attr_description = { | |
| 125 | − .attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO }, | |
| 126 | − .show = childless_description_read, | |
| 127 | −}; | |
| 128 | − | |
| 129 | −static struct configfs_attribute *childless_attrs[] = { | |
| 130 | − &childless_attr_showme.attr, | |
| 131 | − &childless_attr_storeme.attr, | |
| 132 | − &childless_attr_description.attr, | |
| 133 | − NULL, | |
| 134 | −}; | |
| 135 | − | |
| 136 | −static ssize_t childless_attr_show(struct config_item *item, | |
| 137 | − struct configfs_attribute *attr, | |
| 138 | − char *page) | |
| 139 | −{ | |
| 140 | − struct childless *childless = to_childless(item); | |
| 141 | − struct childless_attribute *childless_attr = | |
| 142 | − container_of(attr, struct childless_attribute, attr); | |
| 143 | − ssize_t ret = 0; | |
| 144 | − | |
| 145 | − if (childless_attr->show) | |
| 146 | − ret = childless_attr->show(childless, page); | |
| 147 | − return ret; | |
| 148 | −} | |
| 149 | − | |
| 150 | −static ssize_t childless_attr_store(struct config_item *item, | |
| 151 | − struct configfs_attribute *attr, | |
| 152 | − const char *page, size_t count) | |
| 153 | −{ | |
| 154 | − struct childless *childless = to_childless(item); | |
| 155 | − struct childless_attribute *childless_attr = | |
| 156 | − container_of(attr, struct childless_attribute, attr); | |
| 157 | − ssize_t ret = -EINVAL; | |
| 158 | − | |
| 159 | − if (childless_attr->store) | |
| 160 | − ret = childless_attr->store(childless, page, count); | |
| 161 | − return ret; | |
| 162 | −} | |
| 163 | − | |
| 164 | −static struct configfs_item_operations childless_item_ops = { | |
| 165 | − .show_attribute = childless_attr_show, | |
| 166 | − .store_attribute = childless_attr_store, | |
| 167 | −}; | |
| 168 | − | |
| 169 | −static struct config_item_type childless_type = { | |
| 170 | − .ct_item_ops = &childless_item_ops, | |
| 171 | − .ct_attrs = childless_attrs, | |
| 172 | − .ct_owner = THIS_MODULE, | |
| 173 | −}; | |
| 174 | − | |
| 175 | −static struct childless childless_subsys = { | |
| 176 | − .subsys = { | |
| 177 | − .su_group = { | |
| 178 | − .cg_item = { | |
| 179 | − .ci_namebuf = "01-childless", | |
| 180 | − .ci_type = &childless_type, | |
| 181 | − }, | |
| 182 | − }, | |
| 183 | − }, | |
| 184 | −}; | |
| 185 | − | |
| 186 | − | |
| 187 | −/* ----------------------------------------------------------------- */ | |
| 188 | − | |
| 189 | −/* | |
| 190 | − * 02-simple-children | |
| 191 | − * | |
| 192 | − * This example merely has a simple one-attribute child. Note that | |
| 193 | − * there is no extra attribute structure, as the child's attribute is | |
| 194 | − * known from the get-go. Also, there is no container for the | |
| 195 | − * subsystem, as it has no attributes of its own. | |
| 196 | − */ | |
| 197 | − | |
| 198 | −struct simple_child { | |
| 199 | − struct config_item item; | |
| 200 | − int storeme; | |
| 201 | −}; | |
| 202 | − | |
| 203 | −static inline struct simple_child *to_simple_child(struct config_item *item) | |
| 204 | −{ | |
| 205 | − return item ? container_of(item, struct simple_child, item) : NULL; | |
| 206 | −} | |
| 207 | − | |
| 208 | −static struct configfs_attribute simple_child_attr_storeme = { | |
| 209 | − .ca_owner = THIS_MODULE, | |
| 210 | − .ca_name = "storeme", | |
| 211 | − .ca_mode = S_IRUGO | S_IWUSR, | |
| 212 | −}; | |
| 213 | − | |
| 214 | −static struct configfs_attribute *simple_child_attrs[] = { | |
| 215 | − &simple_child_attr_storeme, | |
| 216 | − NULL, | |
| 217 | −}; | |
| 218 | − | |
| 219 | −static ssize_t simple_child_attr_show(struct config_item *item, | |
| 220 | − struct configfs_attribute *attr, | |
| 221 | − char *page) | |
| 222 | −{ | |
| 223 | − ssize_t count; | |
| 224 | − struct simple_child *simple_child = to_simple_child(item); | |
| 225 | − | |
| 226 | − count = sprintf(page, "%d\n", simple_child->storeme); | |
| 227 | − | |
| 228 | − return count; | |
| 229 | −} | |
| 230 | − | |
| 231 | −static ssize_t simple_child_attr_store(struct config_item *item, | |
| 232 | − struct configfs_attribute *attr, | |
| 233 | − const char *page, size_t count) | |
| 234 | −{ | |
| 235 | − struct simple_child *simple_child = to_simple_child(item); | |
| 236 | − unsigned long tmp; | |
| 237 | − char *p = (char *) page; | |
| 238 | − | |
| 239 | − tmp = simple_strtoul(p, &p, 10); | |
| 240 | − if (!p || (*p && (*p != '\n'))) | |
| 241 | − return -EINVAL; | |
| 242 | − | |
| 243 | − if (tmp > INT_MAX) | |
| 244 | − return -ERANGE; | |
| 245 | − | |
| 246 | − simple_child->storeme = tmp; | |
| 247 | − | |
| 248 | − return count; | |
| 249 | −} | |
| 250 | − | |
| 251 | −static void simple_child_release(struct config_item *item) | |
| 252 | −{ | |
| 253 | − kfree(to_simple_child(item)); | |
| 254 | −} | |
| 255 | − | |
| 256 | −static struct configfs_item_operations simple_child_item_ops = { | |
| 257 | − .release = simple_child_release, | |
| 258 | − .show_attribute = simple_child_attr_show, | |
| 259 | − .store_attribute = simple_child_attr_store, | |
| 260 | −}; | |
| 261 | − | |
| 262 | −static struct config_item_type simple_child_type = { | |
| 263 | − .ct_item_ops = &simple_child_item_ops, | |
| 264 | − .ct_attrs = simple_child_attrs, | |
| 265 | − .ct_owner = THIS_MODULE, | |
| 266 | −}; | |
| 267 | − | |
| 268 | − | |
| 269 | −struct simple_children { | |
| 270 | − struct config_group group; | |
| 271 | −}; | |
| 272 | − | |
| 273 | −static inline struct simple_children *to_simple_children(struct config_item *item) | |
| 274 | −{ | |
| 275 | − return item ? container_of(to_config_group(item), struct simple_children, group) : NULL; | |
| 276 | −} | |
| 277 | − | |
| 278 | −static struct config_item *simple_children_make_item(struct config_group *group, const char *name) | |
| 279 | −{ | |
| 280 | − struct simple_child *simple_child; | |
| 281 | − | |
| 282 | − simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL); | |
| 283 | − if (!simple_child) | |
| 284 | − return ERR_PTR(-ENOMEM); | |
| 285 | − | |
| 286 | − config_item_init_type_name(&simple_child->item, name, | |
| 287 | − &simple_child_type); | |
| 288 | − | |
| 289 | − simple_child->storeme = 0; | |
| 290 | − | |
| 291 | − return &simple_child->item; | |
| 292 | −} | |
| 293 | − | |
| 294 | −static struct configfs_attribute simple_children_attr_description = { | |
| 295 | − .ca_owner = THIS_MODULE, | |
| 296 | − .ca_name = "description", | |
| 297 | − .ca_mode = S_IRUGO, | |
| 298 | −}; | |
| 299 | − | |
| 300 | −static struct configfs_attribute *simple_children_attrs[] = { | |
| 301 | − &simple_children_attr_description, | |
| 302 | − NULL, | |
| 303 | −}; | |
| 304 | − | |
| 305 | −static ssize_t simple_children_attr_show(struct config_item *item, | |
| 306 | − struct configfs_attribute *attr, | |
| 307 | − char *page) | |
| 308 | −{ | |
| 309 | − return sprintf(page, | |
| 310 | −"[02-simple-children]\n" | |
| 311 | −"\n" | |
| 312 | −"This subsystem allows the creation of child config_items. These\n" | |
| 313 | −"items have only one attribute that is readable and writeable.\n"); | |
| 314 | −} | |
| 315 | − | |
| 316 | −static void simple_children_release(struct config_item *item) | |
| 317 | −{ | |
| 318 | − kfree(to_simple_children(item)); | |
| 319 | −} | |
| 320 | − | |
| 321 | −static struct configfs_item_operations simple_children_item_ops = { | |
| 322 | − .release = simple_children_release, | |
| 323 | − .show_attribute = simple_children_attr_show, | |
| 324 | −}; | |
| 325 | − | |
| 326 | −/* | |
| 327 | − * Note that, since no extra work is required on ->drop_item(), | |
| 328 | − * no ->drop_item() is provided. | |
| 329 | − */ | |
| 330 | −static struct configfs_group_operations simple_children_group_ops = { | |
| 331 | − .make_item = simple_children_make_item, | |
| 332 | −}; | |
| 333 | − | |
| 334 | −static struct config_item_type simple_children_type = { | |
| 335 | − .ct_item_ops = &simple_children_item_ops, | |
| 336 | − .ct_group_ops = &simple_children_group_ops, | |
| 337 | − .ct_attrs = simple_children_attrs, | |
| 338 | − .ct_owner = THIS_MODULE, | |
| 339 | −}; | |
| 340 | − | |
| 341 | −static struct configfs_subsystem simple_children_subsys = { | |
| 342 | − .su_group = { | |
| 343 | − .cg_item = { | |
| 344 | − .ci_namebuf = "02-simple-children", | |
| 345 | − .ci_type = &simple_children_type, | |
| 346 | − }, | |
| 347 | − }, | |
| 348 | −}; | |
| 349 | − | |
| 350 | − | |
| 351 | −/* ----------------------------------------------------------------- */ | |
| 352 | − | |
| 353 | −/* | |
| 354 | − * 03-group-children | |
| 355 | − * | |
| 356 | − * This example reuses the simple_children group from above. However, | |
| 357 | − * the simple_children group is not the subsystem itself, it is a | |
| 358 | − * child of the subsystem. Creation of a group in the subsystem creates | |
| 359 | − * a new simple_children group. That group can then have simple_child | |
| 360 | − * children of its own. | |
| 361 | − */ | |
| 362 | − | |
| 363 | −static struct config_group *group_children_make_group(struct config_group *group, const char *name) | |
| 364 | −{ | |
| 365 | − struct simple_children *simple_children; | |
| 366 | − | |
| 367 | − simple_children = kzalloc(sizeof(struct simple_children), | |
| 368 | − GFP_KERNEL); | |
| 369 | − if (!simple_children) | |
| 370 | − return ERR_PTR(-ENOMEM); | |
| 371 | − | |
| 372 | − config_group_init_type_name(&simple_children->group, name, | |
| 373 | − &simple_children_type); | |
| 374 | − | |
| 375 | − return &simple_children->group; | |
| 376 | −} | |
| 377 | − | |
| 378 | −static struct configfs_attribute group_children_attr_description = { | |
| 379 | − .ca_owner = THIS_MODULE, | |
| 380 | − .ca_name = "description", | |
| 381 | − .ca_mode = S_IRUGO, | |
| 382 | −}; | |
| 383 | − | |
| 384 | −static struct configfs_attribute *group_children_attrs[] = { | |
| 385 | − &group_children_attr_description, | |
| 386 | − NULL, | |
| 387 | −}; | |
| 388 | − | |
| 389 | −static ssize_t group_children_attr_show(struct config_item *item, | |
| 390 | − struct configfs_attribute *attr, | |
| 391 | − char *page) | |
| 392 | −{ | |
| 393 | − return sprintf(page, | |
| 394 | −"[03-group-children]\n" | |
| 395 | −"\n" | |
| 396 | −"This subsystem allows the creation of child config_groups. These\n" | |
| 397 | −"groups are like the subsystem simple-children.\n"); | |
| 398 | −} | |
| 399 | − | |
| 400 | −static struct configfs_item_operations group_children_item_ops = { | |
| 401 | − .show_attribute = group_children_attr_show, | |
| 402 | −}; | |
| 403 | − | |
| 404 | −/* | |
| 405 | − * Note that, since no extra work is required on ->drop_item(), | |
| 406 | − * no ->drop_item() is provided. | |
| 407 | − */ | |
| 408 | −static struct configfs_group_operations group_children_group_ops = { | |
| 409 | − .make_group = group_children_make_group, | |
| 410 | −}; | |
| 411 | − | |
| 412 | −static struct config_item_type group_children_type = { | |
| 413 | − .ct_item_ops = &group_children_item_ops, | |
| 414 | − .ct_group_ops = &group_children_group_ops, | |
| 415 | − .ct_attrs = group_children_attrs, | |
| 416 | − .ct_owner = THIS_MODULE, | |
| 417 | −}; | |
| 418 | − | |
| 419 | −static struct configfs_subsystem group_children_subsys = { | |
| 420 | − .su_group = { | |
| 421 | − .cg_item = { | |
| 422 | − .ci_namebuf = "03-group-children", | |
| 423 | − .ci_type = &group_children_type, | |
| 424 | − }, | |
| 425 | − }, | |
| 426 | −}; | |
| 427 | − | |
| 428 | −/* ----------------------------------------------------------------- */ | |
| 429 | − | |
| 430 | −/* | |
| 431 | − * We're now done with our subsystem definitions. | |
| 432 | − * For convenience in this module, here's a list of them all. It | |
| 433 | − * allows the init function to easily register them. Most modules | |
| 434 | − * will only have one subsystem, and will only call register_subsystem | |
| 435 | − * on it directly. | |
| 436 | − */ | |
| 437 | −static struct configfs_subsystem *example_subsys[] = { | |
| 438 | − &childless_subsys.subsys, | |
| 439 | − &simple_children_subsys, | |
| 440 | − &group_children_subsys, | |
| 441 | − NULL, | |
| 442 | −}; | |
| 443 | − | |
| 444 | −static int __init configfs_example_init(void) | |
| 445 | −{ | |
| 446 | − int ret; | |
| 447 | − int i; | |
| 448 | − struct configfs_subsystem *subsys; | |
| 449 | − | |
| 450 | − for (i = 0; example_subsys[i]; i++) { | |
| 451 | − subsys = example_subsys[i]; | |
| 452 | − | |
| 453 | − config_group_init(&subsys->su_group); | |
| 454 | − mutex_init(&subsys->su_mutex); | |
| 455 | − ret = configfs_register_subsystem(subsys); | |
| 456 | − if (ret) { | |
| 457 | − printk(KERN_ERR "Error %d while registering subsystem %s\n", | |
| 458 | − ret, | |
| 459 | − subsys->su_group.cg_item.ci_namebuf); | |
| 460 | − goto out_unregister; | |
| 461 | − } | |
| 462 | − } | |
| 463 | − | |
| 464 | − return 0; | |
| 465 | − | |
| 466 | −out_unregister: | |
| 467 | − for (i--; i >= 0; i--) | |
| 468 | − configfs_unregister_subsystem(example_subsys[i]); | |
| 469 | − | |
| 470 | − return ret; | |
| 471 | −} | |
| 472 | − | |
| 473 | −static void __exit configfs_example_exit(void) | |
| 474 | −{ | |
| 475 | − int i; | |
| 476 | − | |
| 477 | − for (i = 0; example_subsys[i]; i++) | |
| 478 | − configfs_unregister_subsystem(example_subsys[i]); | |
| 479 | −} | |
| 480 | − | |
| 481 | −module_init(configfs_example_init); | |
| 482 | −module_exit(configfs_example_exit); | |
| 483 | −MODULE_LICENSE("GPL"); | |
| @@ -65,7 +65,6 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf · 64 unmodified lines | ||
| 65 | 65 | { |
| 66 | 66 | struct configfs_attribute * attr = to_attr(dentry); |
| 67 | 67 | struct config_item * item = to_item(dentry->d_parent); |
| 68 | − struct configfs_item_operations * ops = buffer->ops; | |
| 69 | 68 | int ret = 0; |
| 70 | 69 | ssize_t count; |
| 71 | 70 | |
| @@ -74,10 +73,7 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf · 2 unmodified lines | ||
| 74 | 73 | if (!buffer->page) |
| 75 | 74 | return -ENOMEM; |
| 76 | 75 | |
| 77 | − if (ops->show_attribute) | |
| 78 | − count = ops->show_attribute(item, attr, buffer->page); | |
| 79 | − else | |
| 80 | − count = attr->show(item, buffer->page); | |
| 76 | + count = attr->show(item, buffer->page); | |
| 81 | 77 | |
| 82 | 78 | buffer->needs_read_fill = 0; |
| 83 | 79 | BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE); |
| @@ -175,10 +171,7 @@ flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size · 91 unmodified lines | ||
| 175 | 171 | { |
| 176 | 172 | struct configfs_attribute * attr = to_attr(dentry); |
| 177 | 173 | struct config_item * item = to_item(dentry->d_parent); |
| 178 | − struct configfs_item_operations * ops = buffer->ops; | |
| 179 | 174 | |
| 180 | − if (ops->store_attribute) | |
| 181 | − return ops->store_attribute(item, attr, buffer->page, count); | |
| 182 | 175 | return attr->store(item, buffer->page, count); |
| 183 | 176 | } |
| 184 | 177 | |
| @@ -243,8 +236,7 @@ static int check_perm(struct inode * inode, struct file * file) · 58 unmodified lines | ||
| 243 | 236 | * and we must have a store method. |
| 244 | 237 | */ |
| 245 | 238 | if (file->f_mode & FMODE_WRITE) { |
| 246 | − if (!(inode->i_mode & S_IWUGO) || | |
| 247 | − (!ops->store_attribute && !attr->store)) | |
| 239 | + if (!(inode->i_mode & S_IWUGO) || !attr->store) | |
| 248 | 240 | goto Eaccess; |
| 249 | 241 | |
| 250 | 242 | } |
| @@ -254,8 +246,7 @@ static int check_perm(struct inode * inode, struct file * file) · 3 unmodified lines | ||
| 254 | 246 | * must be a show method for it. |
| 255 | 247 | */ |
| 256 | 248 | if (file->f_mode & FMODE_READ) { |
| 257 | − if (!(inode->i_mode & S_IRUGO) || | |
| 258 | − (!ops->show_attribute && !attr->show)) | |
| 249 | + if (!(inode->i_mode & S_IRUGO) || !attr->show) | |
| 259 | 250 | goto Eaccess; |
| 260 | 251 | } |
| 261 | 252 | |
| @@ -154,86 +154,6 @@ static struct configfs_attribute _pfx##attr_##_name = { \ · 153 unmodified lines | ||
| 154 | 154 | .store = _pfx##_name##_store, \ |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | −/* | |
| 158 | − * Users often need to create attribute structures for their configurable | |
| 159 | − * attributes, containing a configfs_attribute member and function pointers | |
| 160 | − * for the show() and store() operations on that attribute. If they don't | |
| 161 | − * need anything else on the extended attribute structure, they can use | |
| 162 | − * this macro to define it The argument _item is the name of the | |
| 163 | − * config_item structure. | |
| 164 | − */ | |
| 165 | −#define CONFIGFS_ATTR_STRUCT(_item) \ | |
| 166 | −struct _item##_attribute { \ | |
| 167 | − struct configfs_attribute attr; \ | |
| 168 | − ssize_t (*show)(struct _item *, char *); \ | |
| 169 | − ssize_t (*store)(struct _item *, const char *, size_t); \ | |
| 170 | −} | |
| 171 | − | |
| 172 | −/* | |
| 173 | − * With the extended attribute structure, users can use this macro | |
| 174 | − * (similar to sysfs' __ATTR) to make defining attributes easier. | |
| 175 | − * An example: | |
| 176 | − * #define MYITEM_ATTR(_name, _mode, _show, _store) \ | |
| 177 | − * struct myitem_attribute childless_attr_##_name = \ | |
| 178 | − * __CONFIGFS_ATTR(_name, _mode, _show, _store) | |
| 179 | − */ | |
| 180 | −#define __CONFIGFS_ATTR(_name, _mode, _show, _store) \ | |
| 181 | −{ \ | |
| 182 | − .attr = { \ | |
| 183 | − .ca_name = __stringify(_name), \ | |
| 184 | − .ca_mode = _mode, \ | |
| 185 | − .ca_owner = THIS_MODULE, \ | |
| 186 | − }, \ | |
| 187 | − .show = _show, \ | |
| 188 | − .store = _store, \ | |
| 189 | −} | |
| 190 | −/* Here is a readonly version, only requiring a show() operation */ | |
| 191 | −#define __CONFIGFS_ATTR_RO(_name, _show) \ | |
| 192 | −{ \ | |
| 193 | − .attr = { \ | |
| 194 | − .ca_name = __stringify(_name), \ | |
| 195 | − .ca_mode = 0444, \ | |
| 196 | − .ca_owner = THIS_MODULE, \ | |
| 197 | − }, \ | |
| 198 | − .show = _show, \ | |
| 199 | −} | |
| 200 | − | |
| 201 | −/* | |
| 202 | − * With these extended attributes, the simple show_attribute() and | |
| 203 | − * store_attribute() operations need to call the show() and store() of the | |
| 204 | − * attributes. This is a common pattern, so we provide a macro to define | |
| 205 | − * them. The argument _item is the name of the config_item structure. | |
| 206 | − * This macro expects the attributes to be named "struct <name>_attribute" | |
| 207 | − * and the function to_<name>() to exist; | |
| 208 | − */ | |
| 209 | −#define CONFIGFS_ATTR_OPS(_item) \ | |
| 210 | −static ssize_t _item##_attr_show(struct config_item *item, \ | |
| 211 | − struct configfs_attribute *attr, \ | |
| 212 | − char *page) \ | |
| 213 | −{ \ | |
| 214 | − struct _item *_item = to_##_item(item); \ | |
| 215 | − struct _item##_attribute *_item##_attr = \ | |
| 216 | − container_of(attr, struct _item##_attribute, attr); \ | |
| 217 | − ssize_t ret = 0; \ | |
| 218 | − \ | |
| 219 | − if (_item##_attr->show) \ | |
| 220 | − ret = _item##_attr->show(_item, page); \ | |
| 221 | − return ret; \ | |
| 222 | −} \ | |
| 223 | −static ssize_t _item##_attr_store(struct config_item *item, \ | |
| 224 | − struct configfs_attribute *attr, \ | |
| 225 | − const char *page, size_t count) \ | |
| 226 | −{ \ | |
| 227 | − struct _item *_item = to_##_item(item); \ | |
| 228 | − struct _item##_attribute *_item##_attr = \ | |
| 229 | − container_of(attr, struct _item##_attribute, attr); \ | |
| 230 | − ssize_t ret = -EINVAL; \ | |
| 231 | − \ | |
| 232 | − if (_item##_attr->store) \ | |
| 233 | − ret = _item##_attr->store(_item, page, count); \ | |
| 234 | − return ret; \ | |
| 235 | −} | |
| 236 | − | |
| 237 | 157 | /* |
| 238 | 158 | * If allow_link() exists, the item can symlink(2) out to other |
| 239 | 159 | * items. If the item is a group, it may support mkdir(2). |
| @@ -250,8 +170,6 @@ static ssize_t _item##_attr_store(struct config_item *item, \ · 10 unmodified lines | ||
| 250 | 170 | */ |
| 251 | 171 | struct configfs_item_operations { |
| 252 | 172 | void (*release)(struct config_item *); |
| 253 | − ssize_t (*show_attribute)(struct config_item *, struct configfs_attribute *,char *); | |
| 254 | − ssize_t (*store_attribute)(struct config_item *,struct configfs_attribute *,const char *, size_t); | |
| 255 | 173 | int (*allow_link)(struct config_item *src, struct config_item *target); |
| 256 | 174 | int (*drop_link)(struct config_item *src, struct config_item *target); |
| 257 | 175 | }; |
| @@ -70,4 +70,10 @@ config SAMPLE_LIVEPATCH · 69 unmodified lines | ||
| 70 | 70 | Builds a sample live patch that replaces the procfs handler |
| 71 | 71 | for /proc/cmdline to print "this has been live patched". |
| 72 | 72 | |
| 73 | +config SAMPLE_CONFIGFS | |
| 74 | + tristate "Build configfs patching sample -- loadable modules only" | |
| 75 | + depends on CONFIGFS_FS && m | |
| 76 | + help | |
| 77 | + Builds a sample configfs interface. | |
| 78 | + | |
| 73 | 79 | endif # SAMPLES |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | # Makefile for Linux samples code |
| 2 | 2 | |
| 3 | 3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ |
| 4 | − hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ | |
| 4 | + hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ | |
| 5 | + configfs/ | |
| @@ -0,0 +1,2 @@ | ||
| 1 | + | |
| 2 | +obj-$(CONFIG_SAMPLE_CONFIGFS) += configfs_sample.o | |
| @@ -54,18 +54,13 @@ struct childless { · 53 unmodified lines | ||
| 54 | 54 | |
| 55 | 55 | static inline struct childless *to_childless(struct config_item *item) |
| 56 | 56 | { |
| 57 | − return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL; | |
| 57 | + return item ? container_of(to_configfs_subsystem(to_config_group(item)), | |
| 58 | + struct childless, subsys) : NULL; | |
| 58 | 59 | } |
| 59 | 60 | |
| 60 | −CONFIGFS_ATTR_STRUCT(childless); | |
| 61 | −#define CHILDLESS_ATTR(_name, _mode, _show, _store) \ | |
| 62 | −struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store) | |
| 63 | −#define CHILDLESS_ATTR_RO(_name, _show) \ | |
| 64 | −struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR_RO(_name, _show); | |
| 65 | − | |
| 66 | −static ssize_t childless_showme_read(struct childless *childless, | |
| 67 | − char *page) | |
| 61 | +static ssize_t childless_showme_show(struct config_item *item, char *page) | |
| 68 | 62 | { |
| 63 | + struct childless *childless = to_childless(item); | |
| 69 | 64 | ssize_t pos; |
| 70 | 65 | |
| 71 | 66 | pos = sprintf(page, "%d\n", childless->showme); |
| @@ -74,16 +69,15 @@ static ssize_t childless_showme_read(struct childless *childless, · 2 unmodified lines | ||
| 74 | 69 | return pos; |
| 75 | 70 | } |
| 76 | 71 | |
| 77 | −static ssize_t childless_storeme_read(struct childless *childless, | |
| 78 | − char *page) | |
| 72 | +static ssize_t childless_storeme_show(struct config_item *item, char *page) | |
| 79 | 73 | { |
| 80 | − return sprintf(page, "%d\n", childless->storeme); | |
| 74 | + return sprintf(page, "%d\n", to_childless(item)->storeme); | |
| 81 | 75 | } |
| 82 | 76 | |
| 83 | −static ssize_t childless_storeme_write(struct childless *childless, | |
| 84 | − const char *page, | |
| 85 | − size_t count) | |
| 77 | +static ssize_t childless_storeme_store(struct config_item *item, | |
| 78 | + const char *page, size_t count) | |
| 86 | 79 | { |
| 80 | + struct childless *childless = to_childless(item); | |
| 87 | 81 | unsigned long tmp; |
| 88 | 82 | char *p = (char *) page; |
| 89 | 83 | |
| @@ -99,8 +93,7 @@ static ssize_t childless_storeme_write(struct childless *childless, · 9 unmodified lines | ||
| 99 | 93 | return count; |
| 100 | 94 | } |
| 101 | 95 | |
| 102 | −static ssize_t childless_description_read(struct childless *childless, | |
| 103 | − char *page) | |
| 96 | +static ssize_t childless_description_show(struct config_item *item, char *page) | |
| 104 | 97 | { |
| 105 | 98 | return sprintf(page, |
| 106 | 99 | "[01-childless]\n" |
| @@ -111,26 +104,18 @@ static ssize_t childless_description_read(struct childless *childless, · 4 unmodified lines | ||
| 111 | 104 | "than a directory in /proc.\n"); |
| 112 | 105 | } |
| 113 | 106 | |
| 114 | −CHILDLESS_ATTR_RO(showme, childless_showme_read); | |
| 115 | −CHILDLESS_ATTR(storeme, S_IRUGO | S_IWUSR, childless_storeme_read, | |
| 116 | − childless_storeme_write); | |
| 117 | −CHILDLESS_ATTR_RO(description, childless_description_read); | |
| 107 | +CONFIGFS_ATTR_RO(childless_, showme); | |
| 108 | +CONFIGFS_ATTR(childless_, storeme); | |
| 109 | +CONFIGFS_ATTR_RO(childless_, description); | |
| 118 | 110 | |
| 119 | 111 | static struct configfs_attribute *childless_attrs[] = { |
| 120 | − &childless_attr_showme.attr, | |
| 121 | − &childless_attr_storeme.attr, | |
| 122 | − &childless_attr_description.attr, | |
| 112 | + &childless_attr_showme, | |
| 113 | + &childless_attr_storeme, | |
| 114 | + &childless_attr_description, | |
| 123 | 115 | NULL, |
| 124 | 116 | }; |
| 125 | 117 | |
| 126 | −CONFIGFS_ATTR_OPS(childless); | |
| 127 | −static struct configfs_item_operations childless_item_ops = { | |
| 128 | − .show_attribute = childless_attr_show, | |
| 129 | − .store_attribute = childless_attr_store, | |
| 130 | −}; | |
| 131 | − | |
| 132 | 118 | static struct config_item_type childless_type = { |
| 133 | − .ct_item_ops = &childless_item_ops, | |
| 134 | 119 | .ct_attrs = childless_attrs, |
| 135 | 120 | .ct_owner = THIS_MODULE, |
| 136 | 121 | }; |
| @@ -168,32 +153,13 @@ static inline struct simple_child *to_simple_child(struct config_item *item) · 31 unmodified lines | ||
| 168 | 153 | return item ? container_of(item, struct simple_child, item) : NULL; |
| 169 | 154 | } |
| 170 | 155 | |
| 171 | −static struct configfs_attribute simple_child_attr_storeme = { | |
| 172 | − .ca_owner = THIS_MODULE, | |
| 173 | − .ca_name = "storeme", | |
| 174 | − .ca_mode = S_IRUGO | S_IWUSR, | |
| 175 | −}; | |
| 176 | − | |
| 177 | −static struct configfs_attribute *simple_child_attrs[] = { | |
| 178 | − &simple_child_attr_storeme, | |
| 179 | − NULL, | |
| 180 | −}; | |
| 181 | − | |
| 182 | −static ssize_t simple_child_attr_show(struct config_item *item, | |
| 183 | − struct configfs_attribute *attr, | |
| 184 | − char *page) | |
| 156 | +static ssize_t simple_child_storeme_show(struct config_item *item, char *page) | |
| 185 | 157 | { |
| 186 | − ssize_t count; | |
| 187 | − struct simple_child *simple_child = to_simple_child(item); | |
| 188 | − | |
| 189 | − count = sprintf(page, "%d\n", simple_child->storeme); | |
| 190 | − | |
| 191 | − return count; | |
| 158 | + return sprintf(page, "%d\n", to_simple_child(item)->storeme); | |
| 192 | 159 | } |
| 193 | 160 | |
| 194 | −static ssize_t simple_child_attr_store(struct config_item *item, | |
| 195 | − struct configfs_attribute *attr, | |
| 196 | − const char *page, size_t count) | |
| 161 | +static ssize_t simple_child_storeme_store(struct config_item *item, | |
| 162 | + const char *page, size_t count) | |
| 197 | 163 | { |
| 198 | 164 | struct simple_child *simple_child = to_simple_child(item); |
| 199 | 165 | unsigned long tmp; |
| @@ -211,6 +177,13 @@ static ssize_t simple_child_attr_store(struct config_item *item, · 11 unmodified lines | ||
| 211 | 177 | return count; |
| 212 | 178 | } |
| 213 | 179 | |
| 180 | +CONFIGFS_ATTR(simple_child_, storeme); | |
| 181 | + | |
| 182 | +static struct configfs_attribute *simple_child_attrs[] = { | |
| 183 | + &simple_child_attr_storeme, | |
| 184 | + NULL, | |
| 185 | +}; | |
| 186 | + | |
| 214 | 187 | static void simple_child_release(struct config_item *item) |
| 215 | 188 | { |
| 216 | 189 | kfree(to_simple_child(item)); |
| @@ -218,8 +191,6 @@ static void simple_child_release(struct config_item *item) · 1 unmodified line | ||
| 218 | 191 | |
| 219 | 192 | static struct configfs_item_operations simple_child_item_ops = { |
| 220 | 193 | .release = simple_child_release, |
| 221 | − .show_attribute = simple_child_attr_show, | |
| 222 | − .store_attribute = simple_child_attr_store, | |
| 223 | 194 | }; |
| 224 | 195 | |
| 225 | 196 | static struct config_item_type simple_child_type = { |
| @@ -235,10 +206,12 @@ struct simple_children { · 9 unmodified lines | ||
| 235 | 206 | |
| 236 | 207 | static inline struct simple_children *to_simple_children(struct config_item *item) |
| 237 | 208 | { |
| 238 | − return item ? container_of(to_config_group(item), struct simple_children, group) : NULL; | |
| 209 | + return item ? container_of(to_config_group(item), | |
| 210 | + struct simple_children, group) : NULL; | |
| 239 | 211 | } |
| 240 | 212 | |
| 241 | −static struct config_item *simple_children_make_item(struct config_group *group, const char *name) | |
| 213 | +static struct config_item *simple_children_make_item(struct config_group *group, | |
| 214 | + const char *name) | |
| 242 | 215 | { |
| 243 | 216 | struct simple_child *simple_child; |
| 244 | 217 | |
| @@ -254,20 +227,8 @@ static struct config_item *simple_children_make_item(struct config_group *group, · 9 unmodified lines | ||
| 254 | 227 | return &simple_child->item; |
| 255 | 228 | } |
| 256 | 229 | |
| 257 | −static struct configfs_attribute simple_children_attr_description = { | |
| 258 | − .ca_owner = THIS_MODULE, | |
| 259 | − .ca_name = "description", | |
| 260 | − .ca_mode = S_IRUGO, | |
| 261 | −}; | |
| 262 | − | |
| 263 | −static struct configfs_attribute *simple_children_attrs[] = { | |
| 264 | − &simple_children_attr_description, | |
| 265 | − NULL, | |
| 266 | −}; | |
| 267 | − | |
| 268 | −static ssize_t simple_children_attr_show(struct config_item *item, | |
| 269 | − struct configfs_attribute *attr, | |
| 270 | − char *page) | |
| 230 | +static ssize_t simple_children_description_show(struct config_item *item, | |
| 231 | + char *page) | |
| 271 | 232 | { |
| 272 | 233 | return sprintf(page, |
| 273 | 234 | "[02-simple-children]\n" |
| @@ -276,6 +237,13 @@ static ssize_t simple_children_attr_show(struct config_item *item, · 2 unmodified lines | ||
| 276 | 237 | "items have only one attribute that is readable and writeable.\n"); |
| 277 | 238 | } |
| 278 | 239 | |
| 240 | +CONFIGFS_ATTR_RO(simple_children_, description); | |
| 241 | + | |
| 242 | +static struct configfs_attribute *simple_children_attrs[] = { | |
| 243 | + &simple_children_attr_description, | |
| 244 | + NULL, | |
| 245 | +}; | |
| 246 | + | |
| 279 | 247 | static void simple_children_release(struct config_item *item) |
| 280 | 248 | { |
| 281 | 249 | kfree(to_simple_children(item)); |
| @@ -283,7 +251,6 @@ static void simple_children_release(struct config_item *item) · 1 unmodified line | ||
| 283 | 251 | |
| 284 | 252 | static struct configfs_item_operations simple_children_item_ops = { |
| 285 | 253 | .release = simple_children_release, |
| 286 | − .show_attribute = simple_children_attr_show, | |
| 287 | 254 | }; |
| 288 | 255 | |
| 289 | 256 | /* |
| @@ -323,7 +290,8 @@ static struct configfs_subsystem simple_children_subsys = { · 33 unmodified lines | ||
| 323 | 290 | * children of its own. |
| 324 | 291 | */ |
| 325 | 292 | |
| 326 | −static struct config_group *group_children_make_group(struct config_group *group, const char *name) | |
| 293 | +static struct config_group *group_children_make_group( | |
| 294 | + struct config_group *group, const char *name) | |
| 327 | 295 | { |
| 328 | 296 | struct simple_children *simple_children; |
| 329 | 297 | |
| @@ -338,20 +306,8 @@ static struct config_group *group_children_make_group(struct config_group *group · 8 unmodified lines | ||
| 338 | 306 | return &simple_children->group; |
| 339 | 307 | } |
| 340 | 308 | |
| 341 | −static struct configfs_attribute group_children_attr_description = { | |
| 342 | − .ca_owner = THIS_MODULE, | |
| 343 | − .ca_name = "description", | |
| 344 | − .ca_mode = S_IRUGO, | |
| 345 | −}; | |
| 346 | − | |
| 347 | −static struct configfs_attribute *group_children_attrs[] = { | |
| 348 | − &group_children_attr_description, | |
| 349 | − NULL, | |
| 350 | −}; | |
| 351 | − | |
| 352 | −static ssize_t group_children_attr_show(struct config_item *item, | |
| 353 | − struct configfs_attribute *attr, | |
| 354 | − char *page) | |
| 309 | +static ssize_t group_children_description_show(struct config_item *item, | |
| 310 | + char *page) | |
| 355 | 311 | { |
| 356 | 312 | return sprintf(page, |
| 357 | 313 | "[03-group-children]\n" |
| @@ -360,8 +316,11 @@ static ssize_t group_children_attr_show(struct config_item *item, · 2 unmodified lines | ||
| 360 | 316 | "groups are like the subsystem simple-children.\n"); |
| 361 | 317 | } |
| 362 | 318 | |
| 363 | −static struct configfs_item_operations group_children_item_ops = { | |
| 364 | − .show_attribute = group_children_attr_show, | |
| 319 | +CONFIGFS_ATTR_RO(group_children_, description); | |
| 320 | + | |
| 321 | +static struct configfs_attribute *group_children_attrs[] = { | |
| 322 | + &group_children_attr_description, | |
| 323 | + NULL, | |
| 365 | 324 | }; |
| 366 | 325 | |
| 367 | 326 | /* |
| @@ -373,7 +332,6 @@ static struct configfs_group_operations group_children_group_ops = { · 5 unmodified lines | ||
| 373 | 332 | }; |
| 374 | 333 | |
| 375 | 334 | static struct config_item_type group_children_type = { |
| 376 | − .ct_item_ops = &group_children_item_ops, | |
| 377 | 335 | .ct_group_ops = &group_children_group_ops, |
| 378 | 336 | .ct_attrs = group_children_attrs, |
| 379 | 337 | .ct_owner = THIS_MODULE, |