Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] configfs: User-driven configuration filesystem

Configfs, a file system for userspace-driven kernel object configuration.
The OCFS2 stack makes extensive use of this for propagation of cluster
configuration information into kernel.

Signed-off-by: Joel Becker <joel.becker@oracle.com>

+3575
+2
Documentation/filesystems/00-INDEX
··· 12 12 - description of the CIFS filesystem 13 13 coda.txt 14 14 - description of the CODA filesystem. 15 + configfs/ 16 + - directory containing configfs documentation and example code. 15 17 cramfs.txt 16 18 - info on the cram filesystem for small storage (ROMs etc) 17 19 devfs/
+434
Documentation/filesystems/configfs/configfs.txt
··· 1 + 2 + configfs - Userspace-driven kernel object configuation. 3 + 4 + Joel Becker <joel.becker@oracle.com> 5 + 6 + Updated: 31 March 2005 7 + 8 + Copyright (c) 2005 Oracle Corporation, 9 + Joel Becker <joel.becker@oracle.com> 10 + 11 + 12 + [What is configfs?] 13 + 14 + configfs is a ram-based filesystem that provides the converse of 15 + sysfs's functionality. Where sysfs is a filesystem-based view of 16 + kernel objects, configfs is a filesystem-based manager of kernel 17 + objects, or config_items. 18 + 19 + With sysfs, an object is created in kernel (for example, when a device 20 + is discovered) and it is registered with sysfs. Its attributes then 21 + appear in sysfs, allowing userspace to read the attributes via 22 + readdir(3)/read(2). It may allow some attributes to be modified via 23 + write(2). The important point is that the object is created and 24 + destroyed in kernel, the kernel controls the lifecycle of the sysfs 25 + representation, and sysfs is merely a window on all this. 26 + 27 + A configfs config_item is created via an explicit userspace operation: 28 + mkdir(2). It is destroyed via rmdir(2). The attributes appear at 29 + mkdir(2) time, and can be read or modified via read(2) and write(2). 30 + As with sysfs, readdir(3) queries the list of items and/or attributes. 31 + symlink(2) can be used to group items together. Unlike sysfs, the 32 + lifetime of the representation is completely driven by userspace. The 33 + kernel modules backing the items must respond to this. 34 + 35 + Both sysfs and configfs can and should exist together on the same 36 + system. One is not a replacement for the other. 37 + 38 + [Using configfs] 39 + 40 + configfs can be compiled as a module or into the kernel. You can access 41 + it by doing 42 + 43 + mount -t configfs none /config 44 + 45 + The configfs tree will be empty unless client modules are also loaded. 46 + These are modules that register their item types with configfs as 47 + subsystems. Once a client subsystem is loaded, it will appear as a 48 + subdirectory (or more than one) under /config. Like sysfs, the 49 + configfs tree is always there, whether mounted on /config or not. 50 + 51 + An item is created via mkdir(2). The item's attributes will also 52 + appear at this time. readdir(3) can determine what the attributes are, 53 + read(2) can query their default values, and write(2) can store new 54 + values. Like sysfs, attributes should be ASCII text files, preferably 55 + with only one value per file. The same efficiency caveats from sysfs 56 + apply. Don't mix more than one attribute in one attribute file. 57 + 58 + Like sysfs, configfs expects write(2) to store the entire buffer at 59 + once. When writing to configfs attributes, userspace processes should 60 + first read the entire file, modify the portions they wish to change, and 61 + then write the entire buffer back. Attribute files have a maximum size 62 + of one page (PAGE_SIZE, 4096 on i386). 63 + 64 + When an item needs to be destroyed, remove it with rmdir(2). An 65 + item cannot be destroyed if any other item has a link to it (via 66 + symlink(2)). Links can be removed via unlink(2). 67 + 68 + [Configuring FakeNBD: an Example] 69 + 70 + Imagine there's a Network Block Device (NBD) driver that allows you to 71 + access remote block devices. Call it FakeNBD. FakeNBD uses configfs 72 + for its configuration. Obviously, there will be a nice program that 73 + sysadmins use to configure FakeNBD, but somehow that program has to tell 74 + the driver about it. Here's where configfs comes in. 75 + 76 + When the FakeNBD driver is loaded, it registers itself with configfs. 77 + readdir(3) sees this just fine: 78 + 79 + # ls /config 80 + fakenbd 81 + 82 + A fakenbd connection can be created with mkdir(2). The name is 83 + arbitrary, but likely the tool will make some use of the name. Perhaps 84 + it is a uuid or a disk name: 85 + 86 + # mkdir /config/fakenbd/disk1 87 + # ls /config/fakenbd/disk1 88 + target device rw 89 + 90 + The target attribute contains the IP address of the server FakeNBD will 91 + connect to. The device attribute is the device on the server. 92 + Predictably, the rw attribute determines whether the connection is 93 + read-only or read-write. 94 + 95 + # echo 10.0.0.1 > /config/fakenbd/disk1/target 96 + # echo /dev/sda1 > /config/fakenbd/disk1/device 97 + # echo 1 > /config/fakenbd/disk1/rw 98 + 99 + That's it. That's all there is. Now the device is configured, via the 100 + shell no less. 101 + 102 + [Coding With configfs] 103 + 104 + Every object in configfs is a config_item. A config_item reflects an 105 + object in the subsystem. It has attributes that match values on that 106 + object. configfs handles the filesystem representation of that object 107 + and its attributes, allowing the subsystem to ignore all but the 108 + basic show/store interaction. 109 + 110 + Items are created and destroyed inside a config_group. A group is a 111 + collection of items that share the same attributes and operations. 112 + Items are created by mkdir(2) and removed by rmdir(2), but configfs 113 + handles that. The group has a set of operations to perform these tasks 114 + 115 + A subsystem is the top level of a client module. During initialization, 116 + the client module registers the subsystem with configfs, the subsystem 117 + appears as a directory at the top of the configfs filesystem. A 118 + subsystem is also a config_group, and can do everything a config_group 119 + can. 120 + 121 + [struct config_item] 122 + 123 + struct config_item { 124 + char *ci_name; 125 + char ci_namebuf[UOBJ_NAME_LEN]; 126 + struct kref ci_kref; 127 + struct list_head ci_entry; 128 + struct config_item *ci_parent; 129 + struct config_group *ci_group; 130 + struct config_item_type *ci_type; 131 + struct dentry *ci_dentry; 132 + }; 133 + 134 + void config_item_init(struct config_item *); 135 + void config_item_init_type_name(struct config_item *, 136 + const char *name, 137 + struct config_item_type *type); 138 + struct config_item *config_item_get(struct config_item *); 139 + void config_item_put(struct config_item *); 140 + 141 + Generally, struct config_item is embedded in a container structure, a 142 + structure that actually represents what the subsystem is doing. The 143 + config_item portion of that structure is how the object interacts with 144 + configfs. 145 + 146 + Whether statically defined in a source file or created by a parent 147 + config_group, a config_item must have one of the _init() functions 148 + called on it. This initializes the reference count and sets up the 149 + appropriate fields. 150 + 151 + All users of a config_item should have a reference on it via 152 + config_item_get(), and drop the reference when they are done via 153 + config_item_put(). 154 + 155 + By itself, a config_item cannot do much more than appear in configfs. 156 + Usually a subsystem wants the item to display and/or store attributes, 157 + among other things. For that, it needs a type. 158 + 159 + [struct config_item_type] 160 + 161 + struct configfs_item_operations { 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 + int (*allow_link)(struct config_item *src, 170 + struct config_item *target); 171 + int (*drop_link)(struct config_item *src, 172 + struct config_item *target); 173 + }; 174 + 175 + struct config_item_type { 176 + struct module *ct_owner; 177 + struct configfs_item_operations *ct_item_ops; 178 + struct configfs_group_operations *ct_group_ops; 179 + struct configfs_attribute **ct_attrs; 180 + }; 181 + 182 + The most basic function of a config_item_type is to define what 183 + operations can be performed on a config_item. All items that have been 184 + allocated dynamically will need to provide the ct_item_ops->release() 185 + 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. 189 + 190 + [struct configfs_attribute] 191 + 192 + struct configfs_attribute { 193 + char *ca_name; 194 + struct module *ca_owner; 195 + mode_t ca_mode; 196 + }; 197 + 198 + When a config_item wants an attribute to appear as a file in the item's 199 + configfs directory, it must define a configfs_attribute describing it. 200 + It then adds the attribute to the NULL-terminated array 201 + config_item_type->ct_attrs. When the item appears in configfs, the 202 + attribute file will appear with the configfs_attribute->ca_name 203 + filename. configfs_attribute->ca_mode specifies the file permissions. 204 + 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). 209 + 210 + [struct config_group] 211 + 212 + A config_item cannot live in a vaccum. The only way one can be created 213 + is via mkdir(2) on a config_group. This will trigger creation of a 214 + child item. 215 + 216 + struct config_group { 217 + struct config_item cg_item; 218 + struct list_head cg_children; 219 + struct configfs_subsystem *cg_subsys; 220 + struct config_group **default_groups; 221 + }; 222 + 223 + void config_group_init(struct config_group *group); 224 + void config_group_init_type_name(struct config_group *group, 225 + const char *name, 226 + struct config_item_type *type); 227 + 228 + 229 + The config_group structure contains a config_item. Properly configuring 230 + that item means that a group can behave as an item in its own right. 231 + However, it can do more: it can create child items or groups. This is 232 + accomplished via the group operations specified on the group's 233 + config_item_type. 234 + 235 + struct configfs_group_operations { 236 + struct config_item *(*make_item)(struct config_group *group, 237 + const char *name); 238 + struct config_group *(*make_group)(struct config_group *group, 239 + const char *name); 240 + int (*commit_item)(struct config_item *item); 241 + void (*drop_item)(struct config_group *group, 242 + struct config_item *item); 243 + }; 244 + 245 + A group creates child items by providing the 246 + ct_group_ops->make_item() method. If provided, this method is called from mkdir(2) in the group's directory. The subsystem allocates a new 247 + config_item (or more likely, its container structure), initializes it, 248 + and returns it to configfs. Configfs will then populate the filesystem 249 + tree to reflect the new item. 250 + 251 + If the subsystem wants the child to be a group itself, the subsystem 252 + provides ct_group_ops->make_group(). Everything else behaves the same, 253 + using the group _init() functions on the group. 254 + 255 + Finally, when userspace calls rmdir(2) on the item or group, 256 + ct_group_ops->drop_item() is called. As a config_group is also a 257 + config_item, it is not necessary for a seperate drop_group() method. 258 + The subsystem must config_item_put() the reference that was initialized 259 + upon item allocation. If a subsystem has no work to do, it may omit 260 + the ct_group_ops->drop_item() method, and configfs will call 261 + config_item_put() on the item on behalf of the subsystem. 262 + 263 + IMPORTANT: drop_item() is void, and as such cannot fail. When rmdir(2) 264 + is called, configfs WILL remove the item from the filesystem tree 265 + (assuming that it has no children to keep it busy). The subsystem is 266 + responsible for responding to this. If the subsystem has references to 267 + the item in other threads, the memory is safe. It may take some time 268 + for the item to actually disappear from the subsystem's usage. But it 269 + is gone from configfs. 270 + 271 + A config_group cannot be removed while it still has child items. This 272 + is implemented in the configfs rmdir(2) code. ->drop_item() will not be 273 + called, as the item has not been dropped. rmdir(2) will fail, as the 274 + directory is not empty. 275 + 276 + [struct configfs_subsystem] 277 + 278 + A subsystem must register itself, ususally at module_init time. This 279 + tells configfs to make the subsystem appear in the file tree. 280 + 281 + struct configfs_subsystem { 282 + struct config_group su_group; 283 + struct semaphore su_sem; 284 + }; 285 + 286 + int configfs_register_subsystem(struct configfs_subsystem *subsys); 287 + void configfs_unregister_subsystem(struct configfs_subsystem *subsys); 288 + 289 + A subsystem consists of a toplevel config_group and a semaphore. 290 + The group is where child config_items are created. For a subsystem, 291 + this group is usually defined statically. Before calling 292 + configfs_register_subsystem(), the subsystem must have initialized the 293 + group via the usual group _init() functions, and it must also have 294 + initialized the semaphore. 295 + When the register call returns, the subsystem is live, and it 296 + will be visible via configfs. At that point, mkdir(2) can be called and 297 + the subsystem must be ready for it. 298 + 299 + [An Example] 300 + 301 + The best example of these basic concepts is the simple_children 302 + subsystem/group and the simple_child item in configfs_example.c It 303 + shows a trivial object displaying and storing an attribute, and a simple 304 + group creating and destroying these children. 305 + 306 + [Hierarchy Navigation and the Subsystem Semaphore] 307 + 308 + There is an extra bonus that configfs provides. The config_groups and 309 + config_items are arranged in a hierarchy due to the fact that they 310 + appear in a filesystem. A subsystem is NEVER to touch the filesystem 311 + parts, but the subsystem might be interested in this hierarchy. For 312 + this reason, the hierarchy is mirrored via the config_group->cg_children 313 + and config_item->ci_parent structure members. 314 + 315 + A subsystem can navigate the cg_children list and the ci_parent pointer 316 + to see the tree created by the subsystem. This can race with configfs' 317 + management of the hierarchy, so configfs uses the subsystem semaphore to 318 + protect modifications. Whenever a subsystem wants to navigate the 319 + hierarchy, it must do so under the protection of the subsystem 320 + semaphore. 321 + 322 + A subsystem will be prevented from acquiring the semaphore while a newly 323 + allocated item has not been linked into this hierarchy. Similarly, it 324 + will not be able to acquire the semaphore while a dropping item has not 325 + yet been unlinked. This means that an item's ci_parent pointer will 326 + never be NULL while the item is in configfs, and that an item will only 327 + be in its parent's cg_children list for the same duration. This allows 328 + a subsystem to trust ci_parent and cg_children while they hold the 329 + semaphore. 330 + 331 + [Item Aggregation Via symlink(2)] 332 + 333 + configfs provides a simple group via the group->item parent/child 334 + relationship. Often, however, a larger environment requires aggregation 335 + outside of the parent/child connection. This is implemented via 336 + symlink(2). 337 + 338 + A config_item may provide the ct_item_ops->allow_link() and 339 + ct_item_ops->drop_link() methods. If the ->allow_link() method exists, 340 + symlink(2) may be called with the config_item as the source of the link. 341 + These links are only allowed between configfs config_items. Any 342 + symlink(2) attempt outside the configfs filesystem will be denied. 343 + 344 + When symlink(2) is called, the source config_item's ->allow_link() 345 + method is called with itself and a target item. If the source item 346 + allows linking to target item, it returns 0. A source item may wish to 347 + reject a link if it only wants links to a certain type of object (say, 348 + in its own subsystem). 349 + 350 + When unlink(2) is called on the symbolic link, the source item is 351 + notified via the ->drop_link() method. Like the ->drop_item() method, 352 + this is a void function and cannot return failure. The subsystem is 353 + responsible for responding to the change. 354 + 355 + A config_item cannot be removed while it links to any other item, nor 356 + can it be removed while an item links to it. Dangling symlinks are not 357 + allowed in configfs. 358 + 359 + [Automatically Created Subgroups] 360 + 361 + A new config_group may want to have two types of child config_items. 362 + While this could be codified by magic names in ->make_item(), it is much 363 + more explicit to have a method whereby userspace sees this divergence. 364 + 365 + Rather than have a group where some items behave differently than 366 + others, configfs provides a method whereby one or many subgroups are 367 + automatically created inside the parent at its creation. Thus, 368 + mkdir("parent) results in "parent", "parent/subgroup1", up through 369 + "parent/subgroupN". Items of type 1 can now be created in 370 + "parent/subgroup1", and items of type N can be created in 371 + "parent/subgroupN". 372 + 373 + These automatic subgroups, or default groups, do not preclude other 374 + children of the parent group. If ct_group_ops->make_group() exists, 375 + other child groups can be created on the parent group directly. 376 + 377 + A configfs subsystem specifies default groups by filling in the 378 + NULL-terminated array default_groups on the config_group structure. 379 + Each group in that array is populated in the configfs tree at the same 380 + time as the parent group. Similarly, they are removed at the same time 381 + as the parent. No extra notification is provided. When a ->drop_item() 382 + method call notifies the subsystem the parent group is going away, it 383 + also means every default group child associated with that parent group. 384 + 385 + As a consequence of this, default_groups cannot be removed directly via 386 + rmdir(2). They also are not considered when rmdir(2) on the parent 387 + group is checking for children. 388 + 389 + [Committable Items] 390 + 391 + NOTE: Committable items are currently unimplemented. 392 + 393 + Some config_items cannot have a valid initial state. That is, no 394 + default values can be specified for the item's attributes such that the 395 + item can do its work. Userspace must configure one or more attributes, 396 + after which the subsystem can start whatever entity this item 397 + represents. 398 + 399 + Consider the FakeNBD device from above. Without a target address *and* 400 + a target device, the subsystem has no idea what block device to import. 401 + The simple example assumes that the subsystem merely waits until all the 402 + appropriate attributes are configured, and then connects. This will, 403 + indeed, work, but now every attribute store must check if the attributes 404 + are initialized. Every attribute store must fire off the connection if 405 + that condition is met. 406 + 407 + Far better would be an explicit action notifying the subsystem that the 408 + config_item is ready to go. More importantly, an explicit action allows 409 + the subsystem to provide feedback as to whether the attibutes are 410 + initialized in a way that makes sense. configfs provides this as 411 + committable items. 412 + 413 + configfs still uses only normal filesystem operations. An item is 414 + committed via rename(2). The item is moved from a directory where it 415 + can be modified to a directory where it cannot. 416 + 417 + Any group that provides the ct_group_ops->commit_item() method has 418 + committable items. When this group appears in configfs, mkdir(2) will 419 + not work directly in the group. Instead, the group will have two 420 + subdirectories: "live" and "pending". The "live" directory does not 421 + support mkdir(2) or rmdir(2) either. It only allows rename(2). The 422 + "pending" directory does allow mkdir(2) and rmdir(2). An item is 423 + created in the "pending" directory. Its attributes can be modified at 424 + will. Userspace commits the item by renaming it into the "live" 425 + directory. At this point, the subsystem recieves the ->commit_item() 426 + callback. If all required attributes are filled to satisfaction, the 427 + method returns zero and the item is moved to the "live" directory. 428 + 429 + As rmdir(2) does not work in the "live" directory, an item must be 430 + shutdown, or "uncommitted". Again, this is done via rename(2), this 431 + time from the "live" directory back to the "pending" one. The subsystem 432 + is notified by the ct_group_ops->uncommit_object() method. 433 + 434 +
+474
Documentation/filesystems/configfs/configfs_example.c
··· 1 + /* 2 + * vim: noexpandtab ts=8 sts=0 sw=8: 3 + * 4 + * configfs_example.c - This file is a demonstration module containing 5 + * a number of configfs subsystems. 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public 9 + * License as published by the Free Software Foundation; either 10 + * version 2 of the License, or (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public 18 + * License along with this program; if not, write to the 19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 + * Boston, MA 021110-1307, USA. 21 + * 22 + * Based on sysfs: 23 + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 24 + * 25 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 26 + */ 27 + 28 + #include <linux/init.h> 29 + #include <linux/module.h> 30 + #include <linux/slab.h> 31 + 32 + #include <linux/configfs.h> 33 + 34 + 35 + 36 + /* 37 + * 01-childless 38 + * 39 + * This first example is a childless subsystem. It cannot create 40 + * any config_items. It just has attributes. 41 + * 42 + * Note that we are enclosing the configfs_subsystem inside a container. 43 + * This is not necessary if a subsystem has no attributes directly 44 + * on the subsystem. See the next example, 02-simple-children, for 45 + * such a subsystem. 46 + */ 47 + 48 + struct childless { 49 + struct configfs_subsystem subsys; 50 + int showme; 51 + int storeme; 52 + }; 53 + 54 + struct childless_attribute { 55 + struct configfs_attribute attr; 56 + ssize_t (*show)(struct childless *, char *); 57 + ssize_t (*store)(struct childless *, const char *, size_t); 58 + }; 59 + 60 + static inline struct childless *to_childless(struct config_item *item) 61 + { 62 + return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL; 63 + } 64 + 65 + static ssize_t childless_showme_read(struct childless *childless, 66 + char *page) 67 + { 68 + ssize_t pos; 69 + 70 + pos = sprintf(page, "%d\n", childless->showme); 71 + childless->showme++; 72 + 73 + return pos; 74 + } 75 + 76 + static ssize_t childless_storeme_read(struct childless *childless, 77 + char *page) 78 + { 79 + return sprintf(page, "%d\n", childless->storeme); 80 + } 81 + 82 + static ssize_t childless_storeme_write(struct childless *childless, 83 + const char *page, 84 + size_t count) 85 + { 86 + unsigned long tmp; 87 + char *p = (char *) page; 88 + 89 + tmp = simple_strtoul(p, &p, 10); 90 + if (!p || (*p && (*p != '\n'))) 91 + return -EINVAL; 92 + 93 + if (tmp > INT_MAX) 94 + return -ERANGE; 95 + 96 + childless->storeme = tmp; 97 + 98 + return count; 99 + } 100 + 101 + static ssize_t childless_description_read(struct childless *childless, 102 + char *page) 103 + { 104 + return sprintf(page, 105 + "[01-childless]\n" 106 + "\n" 107 + "The childless subsystem is the simplest possible subsystem in\n" 108 + "configfs. It does not support the creation of child config_items.\n" 109 + "It only has a few attributes. In fact, it isn't much different\n" 110 + "than a directory in /proc.\n"); 111 + } 112 + 113 + static struct childless_attribute childless_attr_showme = { 114 + .attr = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO }, 115 + .show = childless_showme_read, 116 + }; 117 + static struct childless_attribute childless_attr_storeme = { 118 + .attr = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR }, 119 + .show = childless_storeme_read, 120 + .store = childless_storeme_write, 121 + }; 122 + static struct childless_attribute childless_attr_description = { 123 + .attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO }, 124 + .show = childless_description_read, 125 + }; 126 + 127 + static struct configfs_attribute *childless_attrs[] = { 128 + &childless_attr_showme.attr, 129 + &childless_attr_storeme.attr, 130 + &childless_attr_description.attr, 131 + NULL, 132 + }; 133 + 134 + static ssize_t childless_attr_show(struct config_item *item, 135 + struct configfs_attribute *attr, 136 + char *page) 137 + { 138 + struct childless *childless = to_childless(item); 139 + struct childless_attribute *childless_attr = 140 + container_of(attr, struct childless_attribute, attr); 141 + ssize_t ret = 0; 142 + 143 + if (childless_attr->show) 144 + ret = childless_attr->show(childless, page); 145 + return ret; 146 + } 147 + 148 + static ssize_t childless_attr_store(struct config_item *item, 149 + struct configfs_attribute *attr, 150 + const char *page, size_t count) 151 + { 152 + struct childless *childless = to_childless(item); 153 + struct childless_attribute *childless_attr = 154 + container_of(attr, struct childless_attribute, attr); 155 + ssize_t ret = -EINVAL; 156 + 157 + if (childless_attr->store) 158 + ret = childless_attr->store(childless, page, count); 159 + return ret; 160 + } 161 + 162 + static struct configfs_item_operations childless_item_ops = { 163 + .show_attribute = childless_attr_show, 164 + .store_attribute = childless_attr_store, 165 + }; 166 + 167 + static struct config_item_type childless_type = { 168 + .ct_item_ops = &childless_item_ops, 169 + .ct_attrs = childless_attrs, 170 + .ct_owner = THIS_MODULE, 171 + }; 172 + 173 + static struct childless childless_subsys = { 174 + .subsys = { 175 + .su_group = { 176 + .cg_item = { 177 + .ci_namebuf = "01-childless", 178 + .ci_type = &childless_type, 179 + }, 180 + }, 181 + }, 182 + }; 183 + 184 + 185 + /* ----------------------------------------------------------------- */ 186 + 187 + /* 188 + * 02-simple-children 189 + * 190 + * This example merely has a simple one-attribute child. Note that 191 + * there is no extra attribute structure, as the child's attribute is 192 + * known from the get-go. Also, there is no container for the 193 + * subsystem, as it has no attributes of its own. 194 + */ 195 + 196 + struct simple_child { 197 + struct config_item item; 198 + int storeme; 199 + }; 200 + 201 + static inline struct simple_child *to_simple_child(struct config_item *item) 202 + { 203 + return item ? container_of(item, struct simple_child, item) : NULL; 204 + } 205 + 206 + static struct configfs_attribute simple_child_attr_storeme = { 207 + .ca_owner = THIS_MODULE, 208 + .ca_name = "storeme", 209 + .ca_mode = S_IRUGO | S_IWUSR, 210 + }; 211 + 212 + static struct configfs_attribute *simple_child_attrs[] = { 213 + &simple_child_attr_storeme, 214 + NULL, 215 + }; 216 + 217 + static ssize_t simple_child_attr_show(struct config_item *item, 218 + struct configfs_attribute *attr, 219 + char *page) 220 + { 221 + ssize_t count; 222 + struct simple_child *simple_child = to_simple_child(item); 223 + 224 + count = sprintf(page, "%d\n", simple_child->storeme); 225 + 226 + return count; 227 + } 228 + 229 + static ssize_t simple_child_attr_store(struct config_item *item, 230 + struct configfs_attribute *attr, 231 + const char *page, size_t count) 232 + { 233 + struct simple_child *simple_child = to_simple_child(item); 234 + unsigned long tmp; 235 + char *p = (char *) page; 236 + 237 + tmp = simple_strtoul(p, &p, 10); 238 + if (!p || (*p && (*p != '\n'))) 239 + return -EINVAL; 240 + 241 + if (tmp > INT_MAX) 242 + return -ERANGE; 243 + 244 + simple_child->storeme = tmp; 245 + 246 + return count; 247 + } 248 + 249 + static void simple_child_release(struct config_item *item) 250 + { 251 + kfree(to_simple_child(item)); 252 + } 253 + 254 + static struct configfs_item_operations simple_child_item_ops = { 255 + .release = simple_child_release, 256 + .show_attribute = simple_child_attr_show, 257 + .store_attribute = simple_child_attr_store, 258 + }; 259 + 260 + static struct config_item_type simple_child_type = { 261 + .ct_item_ops = &simple_child_item_ops, 262 + .ct_attrs = simple_child_attrs, 263 + .ct_owner = THIS_MODULE, 264 + }; 265 + 266 + 267 + static struct config_item *simple_children_make_item(struct config_group *group, const char *name) 268 + { 269 + struct simple_child *simple_child; 270 + 271 + simple_child = kmalloc(sizeof(struct simple_child), GFP_KERNEL); 272 + if (!simple_child) 273 + return NULL; 274 + 275 + memset(simple_child, 0, sizeof(struct simple_child)); 276 + 277 + config_item_init_type_name(&simple_child->item, name, 278 + &simple_child_type); 279 + 280 + simple_child->storeme = 0; 281 + 282 + return &simple_child->item; 283 + } 284 + 285 + static struct configfs_attribute simple_children_attr_description = { 286 + .ca_owner = THIS_MODULE, 287 + .ca_name = "description", 288 + .ca_mode = S_IRUGO, 289 + }; 290 + 291 + static struct configfs_attribute *simple_children_attrs[] = { 292 + &simple_children_attr_description, 293 + NULL, 294 + }; 295 + 296 + static ssize_t simple_children_attr_show(struct config_item *item, 297 + struct configfs_attribute *attr, 298 + char *page) 299 + { 300 + return sprintf(page, 301 + "[02-simple-children]\n" 302 + "\n" 303 + "This subsystem allows the creation of child config_items. These\n" 304 + "items have only one attribute that is readable and writeable.\n"); 305 + } 306 + 307 + static struct configfs_item_operations simple_children_item_ops = { 308 + .show_attribute = simple_children_attr_show, 309 + }; 310 + 311 + /* 312 + * Note that, since no extra work is required on ->drop_item(), 313 + * no ->drop_item() is provided. 314 + */ 315 + static struct configfs_group_operations simple_children_group_ops = { 316 + .make_item = simple_children_make_item, 317 + }; 318 + 319 + static struct config_item_type simple_children_type = { 320 + .ct_item_ops = &simple_children_item_ops, 321 + .ct_group_ops = &simple_children_group_ops, 322 + .ct_attrs = simple_children_attrs, 323 + }; 324 + 325 + static struct configfs_subsystem simple_children_subsys = { 326 + .su_group = { 327 + .cg_item = { 328 + .ci_namebuf = "02-simple-children", 329 + .ci_type = &simple_children_type, 330 + }, 331 + }, 332 + }; 333 + 334 + 335 + /* ----------------------------------------------------------------- */ 336 + 337 + /* 338 + * 03-group-children 339 + * 340 + * This example reuses the simple_children group from above. However, 341 + * the simple_children group is not the subsystem itself, it is a 342 + * child of the subsystem. Creation of a group in the subsystem creates 343 + * a new simple_children group. That group can then have simple_child 344 + * children of its own. 345 + */ 346 + 347 + struct simple_children { 348 + struct config_group group; 349 + }; 350 + 351 + static struct config_group *group_children_make_group(struct config_group *group, const char *name) 352 + { 353 + struct simple_children *simple_children; 354 + 355 + simple_children = kmalloc(sizeof(struct simple_children), 356 + GFP_KERNEL); 357 + if (!simple_children) 358 + return NULL; 359 + 360 + memset(simple_children, 0, sizeof(struct simple_children)); 361 + 362 + config_group_init_type_name(&simple_children->group, name, 363 + &simple_children_type); 364 + 365 + return &simple_children->group; 366 + } 367 + 368 + static struct configfs_attribute group_children_attr_description = { 369 + .ca_owner = THIS_MODULE, 370 + .ca_name = "description", 371 + .ca_mode = S_IRUGO, 372 + }; 373 + 374 + static struct configfs_attribute *group_children_attrs[] = { 375 + &group_children_attr_description, 376 + NULL, 377 + }; 378 + 379 + static ssize_t group_children_attr_show(struct config_item *item, 380 + struct configfs_attribute *attr, 381 + char *page) 382 + { 383 + return sprintf(page, 384 + "[03-group-children]\n" 385 + "\n" 386 + "This subsystem allows the creation of child config_groups. These\n" 387 + "groups are like the subsystem simple-children.\n"); 388 + } 389 + 390 + static struct configfs_item_operations group_children_item_ops = { 391 + .show_attribute = group_children_attr_show, 392 + }; 393 + 394 + /* 395 + * Note that, since no extra work is required on ->drop_item(), 396 + * no ->drop_item() is provided. 397 + */ 398 + static struct configfs_group_operations group_children_group_ops = { 399 + .make_group = group_children_make_group, 400 + }; 401 + 402 + static struct config_item_type group_children_type = { 403 + .ct_item_ops = &group_children_item_ops, 404 + .ct_group_ops = &group_children_group_ops, 405 + .ct_attrs = group_children_attrs, 406 + }; 407 + 408 + static struct configfs_subsystem group_children_subsys = { 409 + .su_group = { 410 + .cg_item = { 411 + .ci_namebuf = "03-group-children", 412 + .ci_type = &group_children_type, 413 + }, 414 + }, 415 + }; 416 + 417 + /* ----------------------------------------------------------------- */ 418 + 419 + /* 420 + * We're now done with our subsystem definitions. 421 + * For convenience in this module, here's a list of them all. It 422 + * allows the init function to easily register them. Most modules 423 + * will only have one subsystem, and will only call register_subsystem 424 + * on it directly. 425 + */ 426 + static struct configfs_subsystem *example_subsys[] = { 427 + &childless_subsys.subsys, 428 + &simple_children_subsys, 429 + &group_children_subsys, 430 + NULL, 431 + }; 432 + 433 + static int __init configfs_example_init(void) 434 + { 435 + int ret; 436 + int i; 437 + struct configfs_subsystem *subsys; 438 + 439 + for (i = 0; example_subsys[i]; i++) { 440 + subsys = example_subsys[i]; 441 + 442 + config_group_init(&subsys->su_group); 443 + init_MUTEX(&subsys->su_sem); 444 + ret = configfs_register_subsystem(subsys); 445 + if (ret) { 446 + printk(KERN_ERR "Error %d while registering subsystem %s\n", 447 + ret, 448 + subsys->su_group.cg_item.ci_namebuf); 449 + goto out_unregister; 450 + } 451 + } 452 + 453 + return 0; 454 + 455 + out_unregister: 456 + for (; i >= 0; i--) { 457 + configfs_unregister_subsystem(example_subsys[i]); 458 + } 459 + 460 + return ret; 461 + } 462 + 463 + static void __exit configfs_example_exit(void) 464 + { 465 + int i; 466 + 467 + for (i = 0; example_subsys[i]; i++) { 468 + configfs_unregister_subsystem(example_subsys[i]); 469 + } 470 + } 471 + 472 + module_init(configfs_example_init); 473 + module_exit(configfs_example_exit); 474 + MODULE_LICENSE("GPL");
+5
MAINTAINERS
··· 554 554 T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git 555 555 S: Supported 556 556 557 + CONFIGFS 558 + P: Joel Becker 559 + M: Joel Becker <joel.becker@oracle.com> 560 + S: Supported 561 + 557 562 CIRRUS LOGIC GENERIC FBDEV DRIVER 558 563 P: Jeff Garzik 559 564 M: jgarzik@pobox.com
+14
fs/Kconfig
··· 841 841 842 842 If unsure, say N. 843 843 844 + config CONFIGFS_FS 845 + tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)" 846 + depends on EXPERIMENTAL 847 + help 848 + configfs is a ram-based filesystem that provides the converse 849 + of sysfs's functionality. Where sysfs is a filesystem-based 850 + view of kernel objects, configfs is a filesystem-based manager 851 + of kernel objects, or config_items. 852 + 853 + Both sysfs and configfs can and should exist together on the 854 + same system. One is not a replacement for the other. 855 + 856 + If unsure, say N. 857 + 844 858 endmenu 845 859 846 860 menu "Miscellaneous filesystems"
+1
fs/Makefile
··· 101 101 obj-$(CONFIG_HOSTFS) += hostfs/ 102 102 obj-$(CONFIG_HPPFS) += hppfs/ 103 103 obj-$(CONFIG_DEBUG_FS) += debugfs/ 104 + obj-$(CONFIG_CONFIGFS_FS) += configfs/
+7
fs/configfs/Makefile
··· 1 + # 2 + # Makefile for the configfs virtual filesystem 3 + # 4 + 5 + obj-$(CONFIG_CONFIGFS_FS) += configfs.o 6 + 7 + configfs-objs := inode.o file.o dir.o symlink.o mount.o item.o
+142
fs/configfs/configfs_internal.h
··· 1 + /* -*- mode: c; c-basic-offset:8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * configfs_internal.h - Internal stuff for configfs 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the 18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 021110-1307, USA. 20 + * 21 + * Based on sysfs: 22 + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 23 + * 24 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 + */ 26 + 27 + #include <linux/slab.h> 28 + #include <linux/list.h> 29 + 30 + struct configfs_dirent { 31 + atomic_t s_count; 32 + struct list_head s_sibling; 33 + struct list_head s_children; 34 + struct list_head s_links; 35 + void * s_element; 36 + int s_type; 37 + umode_t s_mode; 38 + struct dentry * s_dentry; 39 + }; 40 + 41 + #define CONFIGFS_ROOT 0x0001 42 + #define CONFIGFS_DIR 0x0002 43 + #define CONFIGFS_ITEM_ATTR 0x0004 44 + #define CONFIGFS_ITEM_LINK 0x0020 45 + #define CONFIGFS_USET_DIR 0x0040 46 + #define CONFIGFS_USET_DEFAULT 0x0080 47 + #define CONFIGFS_USET_DROPPING 0x0100 48 + #define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) 49 + 50 + extern struct vfsmount * configfs_mount; 51 + 52 + extern int configfs_is_root(struct config_item *item); 53 + 54 + extern struct inode * configfs_new_inode(mode_t mode); 55 + extern int configfs_create(struct dentry *, int mode, int (*init)(struct inode *)); 56 + 57 + extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); 58 + extern int configfs_make_dirent(struct configfs_dirent *, 59 + struct dentry *, void *, umode_t, int); 60 + 61 + extern int configfs_add_file(struct dentry *, const struct configfs_attribute *, int); 62 + extern void configfs_hash_and_remove(struct dentry * dir, const char * name); 63 + 64 + extern const unsigned char * configfs_get_name(struct configfs_dirent *sd); 65 + extern void configfs_drop_dentry(struct configfs_dirent *sd, struct dentry *parent); 66 + 67 + extern int configfs_pin_fs(void); 68 + extern void configfs_release_fs(void); 69 + 70 + extern struct rw_semaphore configfs_rename_sem; 71 + extern struct super_block * configfs_sb; 72 + extern struct file_operations configfs_dir_operations; 73 + extern struct file_operations configfs_file_operations; 74 + extern struct file_operations bin_fops; 75 + extern struct inode_operations configfs_dir_inode_operations; 76 + extern struct inode_operations configfs_symlink_inode_operations; 77 + 78 + extern int configfs_symlink(struct inode *dir, struct dentry *dentry, 79 + const char *symname); 80 + extern int configfs_unlink(struct inode *dir, struct dentry *dentry); 81 + 82 + struct configfs_symlink { 83 + struct list_head sl_list; 84 + struct config_item *sl_target; 85 + }; 86 + 87 + extern int configfs_create_link(struct configfs_symlink *sl, 88 + struct dentry *parent, 89 + struct dentry *dentry); 90 + 91 + static inline struct config_item * to_item(struct dentry * dentry) 92 + { 93 + struct configfs_dirent * sd = dentry->d_fsdata; 94 + return ((struct config_item *) sd->s_element); 95 + } 96 + 97 + static inline struct configfs_attribute * to_attr(struct dentry * dentry) 98 + { 99 + struct configfs_dirent * sd = dentry->d_fsdata; 100 + return ((struct configfs_attribute *) sd->s_element); 101 + } 102 + 103 + static inline struct config_item *configfs_get_config_item(struct dentry *dentry) 104 + { 105 + struct config_item * item = NULL; 106 + 107 + spin_lock(&dcache_lock); 108 + if (!d_unhashed(dentry)) { 109 + struct configfs_dirent * sd = dentry->d_fsdata; 110 + if (sd->s_type & CONFIGFS_ITEM_LINK) { 111 + struct configfs_symlink * sl = sd->s_element; 112 + item = config_item_get(sl->sl_target); 113 + } else 114 + item = config_item_get(sd->s_element); 115 + } 116 + spin_unlock(&dcache_lock); 117 + 118 + return item; 119 + } 120 + 121 + static inline void release_configfs_dirent(struct configfs_dirent * sd) 122 + { 123 + if (!(sd->s_type & CONFIGFS_ROOT)) 124 + kfree(sd); 125 + } 126 + 127 + static inline struct configfs_dirent * configfs_get(struct configfs_dirent * sd) 128 + { 129 + if (sd) { 130 + WARN_ON(!atomic_read(&sd->s_count)); 131 + atomic_inc(&sd->s_count); 132 + } 133 + return sd; 134 + } 135 + 136 + static inline void configfs_put(struct configfs_dirent * sd) 137 + { 138 + WARN_ON(!atomic_read(&sd->s_count)); 139 + if (atomic_dec_and_test(&sd->s_count)) 140 + release_configfs_dirent(sd); 141 + } 142 +
+1102
fs/configfs/dir.c
··· 1 + /* -*- mode: c; c-basic-offset: 8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * dir.c - Operations for configfs directories. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the 18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 021110-1307, USA. 20 + * 21 + * Based on sysfs: 22 + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 23 + * 24 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 + */ 26 + 27 + #undef DEBUG 28 + 29 + #include <linux/fs.h> 30 + #include <linux/mount.h> 31 + #include <linux/module.h> 32 + #include <linux/slab.h> 33 + 34 + #include <linux/configfs.h> 35 + #include "configfs_internal.h" 36 + 37 + DECLARE_RWSEM(configfs_rename_sem); 38 + 39 + static void configfs_d_iput(struct dentry * dentry, 40 + struct inode * inode) 41 + { 42 + struct configfs_dirent * sd = dentry->d_fsdata; 43 + 44 + if (sd) { 45 + BUG_ON(sd->s_dentry != dentry); 46 + sd->s_dentry = NULL; 47 + configfs_put(sd); 48 + } 49 + iput(inode); 50 + } 51 + 52 + /* 53 + * We _must_ delete our dentries on last dput, as the chain-to-parent 54 + * behavior is required to clear the parents of default_groups. 55 + */ 56 + static int configfs_d_delete(struct dentry *dentry) 57 + { 58 + return 1; 59 + } 60 + 61 + static struct dentry_operations configfs_dentry_ops = { 62 + .d_iput = configfs_d_iput, 63 + /* simple_delete_dentry() isn't exported */ 64 + .d_delete = configfs_d_delete, 65 + }; 66 + 67 + /* 68 + * Allocates a new configfs_dirent and links it to the parent configfs_dirent 69 + */ 70 + static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * parent_sd, 71 + void * element) 72 + { 73 + struct configfs_dirent * sd; 74 + 75 + sd = kmalloc(sizeof(*sd), GFP_KERNEL); 76 + if (!sd) 77 + return NULL; 78 + 79 + memset(sd, 0, sizeof(*sd)); 80 + atomic_set(&sd->s_count, 1); 81 + INIT_LIST_HEAD(&sd->s_links); 82 + INIT_LIST_HEAD(&sd->s_children); 83 + list_add(&sd->s_sibling, &parent_sd->s_children); 84 + sd->s_element = element; 85 + 86 + return sd; 87 + } 88 + 89 + int configfs_make_dirent(struct configfs_dirent * parent_sd, 90 + struct dentry * dentry, void * element, 91 + umode_t mode, int type) 92 + { 93 + struct configfs_dirent * sd; 94 + 95 + sd = configfs_new_dirent(parent_sd, element); 96 + if (!sd) 97 + return -ENOMEM; 98 + 99 + sd->s_mode = mode; 100 + sd->s_type = type; 101 + sd->s_dentry = dentry; 102 + if (dentry) { 103 + dentry->d_fsdata = configfs_get(sd); 104 + dentry->d_op = &configfs_dentry_ops; 105 + } 106 + 107 + return 0; 108 + } 109 + 110 + static int init_dir(struct inode * inode) 111 + { 112 + inode->i_op = &configfs_dir_inode_operations; 113 + inode->i_fop = &configfs_dir_operations; 114 + 115 + /* directory inodes start off with i_nlink == 2 (for "." entry) */ 116 + inode->i_nlink++; 117 + return 0; 118 + } 119 + 120 + static int init_file(struct inode * inode) 121 + { 122 + inode->i_size = PAGE_SIZE; 123 + inode->i_fop = &configfs_file_operations; 124 + return 0; 125 + } 126 + 127 + static int init_symlink(struct inode * inode) 128 + { 129 + inode->i_op = &configfs_symlink_inode_operations; 130 + return 0; 131 + } 132 + 133 + static int create_dir(struct config_item * k, struct dentry * p, 134 + struct dentry * d) 135 + { 136 + int error; 137 + umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 138 + 139 + error = configfs_create(d, mode, init_dir); 140 + if (!error) { 141 + error = configfs_make_dirent(p->d_fsdata, d, k, mode, 142 + CONFIGFS_DIR); 143 + if (!error) { 144 + p->d_inode->i_nlink++; 145 + (d)->d_op = &configfs_dentry_ops; 146 + } 147 + } 148 + return error; 149 + } 150 + 151 + 152 + /** 153 + * configfs_create_dir - create a directory for an config_item. 154 + * @item: config_itemwe're creating directory for. 155 + * @dentry: config_item's dentry. 156 + */ 157 + 158 + static int configfs_create_dir(struct config_item * item, struct dentry *dentry) 159 + { 160 + struct dentry * parent; 161 + int error = 0; 162 + 163 + BUG_ON(!item); 164 + 165 + if (item->ci_parent) 166 + parent = item->ci_parent->ci_dentry; 167 + else if (configfs_mount && configfs_mount->mnt_sb) 168 + parent = configfs_mount->mnt_sb->s_root; 169 + else 170 + return -EFAULT; 171 + 172 + error = create_dir(item,parent,dentry); 173 + if (!error) 174 + item->ci_dentry = dentry; 175 + return error; 176 + } 177 + 178 + int configfs_create_link(struct configfs_symlink *sl, 179 + struct dentry *parent, 180 + struct dentry *dentry) 181 + { 182 + int err = 0; 183 + umode_t mode = S_IFLNK | S_IRWXUGO; 184 + 185 + err = configfs_create(dentry, mode, init_symlink); 186 + if (!err) { 187 + err = configfs_make_dirent(parent->d_fsdata, dentry, sl, 188 + mode, CONFIGFS_ITEM_LINK); 189 + if (!err) 190 + dentry->d_op = &configfs_dentry_ops; 191 + } 192 + return err; 193 + } 194 + 195 + static void remove_dir(struct dentry * d) 196 + { 197 + struct dentry * parent = dget(d->d_parent); 198 + struct configfs_dirent * sd; 199 + 200 + sd = d->d_fsdata; 201 + list_del_init(&sd->s_sibling); 202 + configfs_put(sd); 203 + if (d->d_inode) 204 + simple_rmdir(parent->d_inode,d); 205 + 206 + pr_debug(" o %s removing done (%d)\n",d->d_name.name, 207 + atomic_read(&d->d_count)); 208 + 209 + dput(parent); 210 + } 211 + 212 + /** 213 + * configfs_remove_dir - remove an config_item's directory. 214 + * @item: config_item we're removing. 215 + * 216 + * The only thing special about this is that we remove any files in 217 + * the directory before we remove the directory, and we've inlined 218 + * what used to be configfs_rmdir() below, instead of calling separately. 219 + */ 220 + 221 + static void configfs_remove_dir(struct config_item * item) 222 + { 223 + struct dentry * dentry = dget(item->ci_dentry); 224 + 225 + if (!dentry) 226 + return; 227 + 228 + remove_dir(dentry); 229 + /** 230 + * Drop reference from dget() on entrance. 231 + */ 232 + dput(dentry); 233 + } 234 + 235 + 236 + /* attaches attribute's configfs_dirent to the dentry corresponding to the 237 + * attribute file 238 + */ 239 + static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * dentry) 240 + { 241 + struct configfs_attribute * attr = sd->s_element; 242 + int error; 243 + 244 + error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, init_file); 245 + if (error) 246 + return error; 247 + 248 + dentry->d_op = &configfs_dentry_ops; 249 + dentry->d_fsdata = configfs_get(sd); 250 + sd->s_dentry = dentry; 251 + d_rehash(dentry); 252 + 253 + return 0; 254 + } 255 + 256 + static struct dentry * configfs_lookup(struct inode *dir, 257 + struct dentry *dentry, 258 + struct nameidata *nd) 259 + { 260 + struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata; 261 + struct configfs_dirent * sd; 262 + int found = 0; 263 + int err = 0; 264 + 265 + list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 266 + if (sd->s_type & CONFIGFS_NOT_PINNED) { 267 + const unsigned char * name = configfs_get_name(sd); 268 + 269 + if (strcmp(name, dentry->d_name.name)) 270 + continue; 271 + 272 + found = 1; 273 + err = configfs_attach_attr(sd, dentry); 274 + break; 275 + } 276 + } 277 + 278 + if (!found) { 279 + /* 280 + * If it doesn't exist and it isn't a NOT_PINNED item, 281 + * it must be negative. 282 + */ 283 + return simple_lookup(dir, dentry, nd); 284 + } 285 + 286 + return ERR_PTR(err); 287 + } 288 + 289 + /* 290 + * Only subdirectories count here. Files (CONFIGFS_NOT_PINNED) are 291 + * attributes and are removed by rmdir(). We recurse, taking i_sem 292 + * on all children that are candidates for default detach. If the 293 + * result is clean, then configfs_detach_group() will handle dropping 294 + * i_sem. If there is an error, the caller will clean up the i_sem 295 + * holders via configfs_detach_rollback(). 296 + */ 297 + static int configfs_detach_prep(struct dentry *dentry) 298 + { 299 + struct configfs_dirent *parent_sd = dentry->d_fsdata; 300 + struct configfs_dirent *sd; 301 + int ret; 302 + 303 + ret = -EBUSY; 304 + if (!list_empty(&parent_sd->s_links)) 305 + goto out; 306 + 307 + ret = 0; 308 + list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 309 + if (sd->s_type & CONFIGFS_NOT_PINNED) 310 + continue; 311 + if (sd->s_type & CONFIGFS_USET_DEFAULT) { 312 + down(&sd->s_dentry->d_inode->i_sem); 313 + /* Mark that we've taken i_sem */ 314 + sd->s_type |= CONFIGFS_USET_DROPPING; 315 + 316 + ret = configfs_detach_prep(sd->s_dentry); 317 + if (!ret) 318 + continue; 319 + } else 320 + ret = -ENOTEMPTY; 321 + 322 + break; 323 + } 324 + 325 + out: 326 + return ret; 327 + } 328 + 329 + /* 330 + * Walk the tree, dropping i_sem wherever CONFIGFS_USET_DROPPING is 331 + * set. 332 + */ 333 + static void configfs_detach_rollback(struct dentry *dentry) 334 + { 335 + struct configfs_dirent *parent_sd = dentry->d_fsdata; 336 + struct configfs_dirent *sd; 337 + 338 + list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 339 + if (sd->s_type & CONFIGFS_USET_DEFAULT) { 340 + configfs_detach_rollback(sd->s_dentry); 341 + 342 + if (sd->s_type & CONFIGFS_USET_DROPPING) { 343 + sd->s_type &= ~CONFIGFS_USET_DROPPING; 344 + up(&sd->s_dentry->d_inode->i_sem); 345 + } 346 + } 347 + } 348 + } 349 + 350 + static void detach_attrs(struct config_item * item) 351 + { 352 + struct dentry * dentry = dget(item->ci_dentry); 353 + struct configfs_dirent * parent_sd; 354 + struct configfs_dirent * sd, * tmp; 355 + 356 + if (!dentry) 357 + return; 358 + 359 + pr_debug("configfs %s: dropping attrs for dir\n", 360 + dentry->d_name.name); 361 + 362 + parent_sd = dentry->d_fsdata; 363 + list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { 364 + if (!sd->s_element || !(sd->s_type & CONFIGFS_NOT_PINNED)) 365 + continue; 366 + list_del_init(&sd->s_sibling); 367 + configfs_drop_dentry(sd, dentry); 368 + configfs_put(sd); 369 + } 370 + 371 + /** 372 + * Drop reference from dget() on entrance. 373 + */ 374 + dput(dentry); 375 + } 376 + 377 + static int populate_attrs(struct config_item *item) 378 + { 379 + struct config_item_type *t = item->ci_type; 380 + struct configfs_attribute *attr; 381 + int error = 0; 382 + int i; 383 + 384 + if (!t) 385 + return -EINVAL; 386 + if (t->ct_attrs) { 387 + for (i = 0; (attr = t->ct_attrs[i]) != NULL; i++) { 388 + if ((error = configfs_create_file(item, attr))) 389 + break; 390 + } 391 + } 392 + 393 + if (error) 394 + detach_attrs(item); 395 + 396 + return error; 397 + } 398 + 399 + static int configfs_attach_group(struct config_item *parent_item, 400 + struct config_item *item, 401 + struct dentry *dentry); 402 + static void configfs_detach_group(struct config_item *item); 403 + 404 + static void detach_groups(struct config_group *group) 405 + { 406 + struct dentry * dentry = dget(group->cg_item.ci_dentry); 407 + struct dentry *child; 408 + struct configfs_dirent *parent_sd; 409 + struct configfs_dirent *sd, *tmp; 410 + 411 + if (!dentry) 412 + return; 413 + 414 + parent_sd = dentry->d_fsdata; 415 + list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { 416 + if (!sd->s_element || 417 + !(sd->s_type & CONFIGFS_USET_DEFAULT)) 418 + continue; 419 + 420 + child = sd->s_dentry; 421 + 422 + configfs_detach_group(sd->s_element); 423 + child->d_inode->i_flags |= S_DEAD; 424 + 425 + /* 426 + * From rmdir/unregister, a configfs_detach_prep() pass 427 + * has taken our i_sem for us. Drop it. 428 + * From mkdir/register cleanup, there is no sem held. 429 + */ 430 + if (sd->s_type & CONFIGFS_USET_DROPPING) 431 + up(&child->d_inode->i_sem); 432 + 433 + d_delete(child); 434 + dput(child); 435 + } 436 + 437 + /** 438 + * Drop reference from dget() on entrance. 439 + */ 440 + dput(dentry); 441 + } 442 + 443 + /* 444 + * This fakes mkdir(2) on a default_groups[] entry. It 445 + * creates a dentry, attachs it, and then does fixup 446 + * on the sd->s_type. 447 + * 448 + * We could, perhaps, tweak our parent's ->mkdir for a minute and 449 + * try using vfs_mkdir. Just a thought. 450 + */ 451 + static int create_default_group(struct config_group *parent_group, 452 + struct config_group *group) 453 + { 454 + int ret; 455 + struct qstr name; 456 + struct configfs_dirent *sd; 457 + /* We trust the caller holds a reference to parent */ 458 + struct dentry *child, *parent = parent_group->cg_item.ci_dentry; 459 + 460 + if (!group->cg_item.ci_name) 461 + group->cg_item.ci_name = group->cg_item.ci_namebuf; 462 + name.name = group->cg_item.ci_name; 463 + name.len = strlen(name.name); 464 + name.hash = full_name_hash(name.name, name.len); 465 + 466 + ret = -ENOMEM; 467 + child = d_alloc(parent, &name); 468 + if (child) { 469 + d_add(child, NULL); 470 + 471 + ret = configfs_attach_group(&parent_group->cg_item, 472 + &group->cg_item, child); 473 + if (!ret) { 474 + sd = child->d_fsdata; 475 + sd->s_type |= CONFIGFS_USET_DEFAULT; 476 + } else { 477 + d_delete(child); 478 + dput(child); 479 + } 480 + } 481 + 482 + return ret; 483 + } 484 + 485 + static int populate_groups(struct config_group *group) 486 + { 487 + struct config_group *new_group; 488 + struct dentry *dentry = group->cg_item.ci_dentry; 489 + int ret = 0; 490 + int i; 491 + 492 + if (group && group->default_groups) { 493 + /* FYI, we're faking mkdir here 494 + * I'm not sure we need this semaphore, as we're called 495 + * from our parent's mkdir. That holds our parent's 496 + * i_sem, so afaik lookup cannot continue through our 497 + * parent to find us, let alone mess with our tree. 498 + * That said, taking our i_sem is closer to mkdir 499 + * emulation, and shouldn't hurt. */ 500 + down(&dentry->d_inode->i_sem); 501 + 502 + for (i = 0; group->default_groups[i]; i++) { 503 + new_group = group->default_groups[i]; 504 + 505 + ret = create_default_group(group, new_group); 506 + if (ret) 507 + break; 508 + } 509 + 510 + up(&dentry->d_inode->i_sem); 511 + } 512 + 513 + if (ret) 514 + detach_groups(group); 515 + 516 + return ret; 517 + } 518 + 519 + /* 520 + * All of link_obj/unlink_obj/link_group/unlink_group require that 521 + * subsys->su_sem is held. 522 + */ 523 + 524 + static void unlink_obj(struct config_item *item) 525 + { 526 + struct config_group *group; 527 + 528 + group = item->ci_group; 529 + if (group) { 530 + list_del_init(&item->ci_entry); 531 + 532 + item->ci_group = NULL; 533 + item->ci_parent = NULL; 534 + config_item_put(item); 535 + 536 + config_group_put(group); 537 + } 538 + } 539 + 540 + static void link_obj(struct config_item *parent_item, struct config_item *item) 541 + { 542 + /* Parent seems redundant with group, but it makes certain 543 + * traversals much nicer. */ 544 + item->ci_parent = parent_item; 545 + item->ci_group = config_group_get(to_config_group(parent_item)); 546 + list_add_tail(&item->ci_entry, &item->ci_group->cg_children); 547 + 548 + config_item_get(item); 549 + } 550 + 551 + static void unlink_group(struct config_group *group) 552 + { 553 + int i; 554 + struct config_group *new_group; 555 + 556 + if (group->default_groups) { 557 + for (i = 0; group->default_groups[i]; i++) { 558 + new_group = group->default_groups[i]; 559 + unlink_group(new_group); 560 + } 561 + } 562 + 563 + group->cg_subsys = NULL; 564 + unlink_obj(&group->cg_item); 565 + } 566 + 567 + static void link_group(struct config_group *parent_group, struct config_group *group) 568 + { 569 + int i; 570 + struct config_group *new_group; 571 + struct configfs_subsystem *subsys = NULL; /* gcc is a turd */ 572 + 573 + link_obj(&parent_group->cg_item, &group->cg_item); 574 + 575 + if (parent_group->cg_subsys) 576 + subsys = parent_group->cg_subsys; 577 + else if (configfs_is_root(&parent_group->cg_item)) 578 + subsys = to_configfs_subsystem(group); 579 + else 580 + BUG(); 581 + group->cg_subsys = subsys; 582 + 583 + if (group->default_groups) { 584 + for (i = 0; group->default_groups[i]; i++) { 585 + new_group = group->default_groups[i]; 586 + link_group(group, new_group); 587 + } 588 + } 589 + } 590 + 591 + /* 592 + * The goal is that configfs_attach_item() (and 593 + * configfs_attach_group()) can be called from either the VFS or this 594 + * module. That is, they assume that the items have been created, 595 + * the dentry allocated, and the dcache is all ready to go. 596 + * 597 + * If they fail, they must clean up after themselves as if they 598 + * had never been called. The caller (VFS or local function) will 599 + * handle cleaning up the dcache bits. 600 + * 601 + * configfs_detach_group() and configfs_detach_item() behave similarly on 602 + * the way out. They assume that the proper semaphores are held, they 603 + * clean up the configfs items, and they expect their callers will 604 + * handle the dcache bits. 605 + */ 606 + static int configfs_attach_item(struct config_item *parent_item, 607 + struct config_item *item, 608 + struct dentry *dentry) 609 + { 610 + int ret; 611 + 612 + ret = configfs_create_dir(item, dentry); 613 + if (!ret) { 614 + ret = populate_attrs(item); 615 + if (ret) { 616 + configfs_remove_dir(item); 617 + d_delete(dentry); 618 + } 619 + } 620 + 621 + return ret; 622 + } 623 + 624 + static void configfs_detach_item(struct config_item *item) 625 + { 626 + detach_attrs(item); 627 + configfs_remove_dir(item); 628 + } 629 + 630 + static int configfs_attach_group(struct config_item *parent_item, 631 + struct config_item *item, 632 + struct dentry *dentry) 633 + { 634 + int ret; 635 + struct configfs_dirent *sd; 636 + 637 + ret = configfs_attach_item(parent_item, item, dentry); 638 + if (!ret) { 639 + sd = dentry->d_fsdata; 640 + sd->s_type |= CONFIGFS_USET_DIR; 641 + 642 + ret = populate_groups(to_config_group(item)); 643 + if (ret) { 644 + configfs_detach_item(item); 645 + d_delete(dentry); 646 + } 647 + } 648 + 649 + return ret; 650 + } 651 + 652 + static void configfs_detach_group(struct config_item *item) 653 + { 654 + detach_groups(to_config_group(item)); 655 + configfs_detach_item(item); 656 + } 657 + 658 + /* 659 + * Drop the initial reference from make_item()/make_group() 660 + * This function assumes that reference is held on item 661 + * and that item holds a valid reference to the parent. Also, it 662 + * assumes the caller has validated ci_type. 663 + */ 664 + static void client_drop_item(struct config_item *parent_item, 665 + struct config_item *item) 666 + { 667 + struct config_item_type *type; 668 + 669 + type = parent_item->ci_type; 670 + BUG_ON(!type); 671 + 672 + if (type->ct_group_ops && type->ct_group_ops->drop_item) 673 + type->ct_group_ops->drop_item(to_config_group(parent_item), 674 + item); 675 + else 676 + config_item_put(item); 677 + } 678 + 679 + 680 + static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 681 + { 682 + int ret; 683 + struct config_group *group; 684 + struct config_item *item; 685 + struct config_item *parent_item; 686 + struct configfs_subsystem *subsys; 687 + struct configfs_dirent *sd; 688 + struct config_item_type *type; 689 + struct module *owner; 690 + char *name; 691 + 692 + if (dentry->d_parent == configfs_sb->s_root) 693 + return -EPERM; 694 + 695 + sd = dentry->d_parent->d_fsdata; 696 + if (!(sd->s_type & CONFIGFS_USET_DIR)) 697 + return -EPERM; 698 + 699 + parent_item = configfs_get_config_item(dentry->d_parent); 700 + type = parent_item->ci_type; 701 + subsys = to_config_group(parent_item)->cg_subsys; 702 + BUG_ON(!subsys); 703 + 704 + if (!type || !type->ct_group_ops || 705 + (!type->ct_group_ops->make_group && 706 + !type->ct_group_ops->make_item)) { 707 + config_item_put(parent_item); 708 + return -EPERM; /* What lack-of-mkdir returns */ 709 + } 710 + 711 + name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL); 712 + if (!name) { 713 + config_item_put(parent_item); 714 + return -ENOMEM; 715 + } 716 + snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name); 717 + 718 + down(&subsys->su_sem); 719 + group = NULL; 720 + item = NULL; 721 + if (type->ct_group_ops->make_group) { 722 + group = type->ct_group_ops->make_group(to_config_group(parent_item), name); 723 + if (group) { 724 + link_group(to_config_group(parent_item), group); 725 + item = &group->cg_item; 726 + } 727 + } else { 728 + item = type->ct_group_ops->make_item(to_config_group(parent_item), name); 729 + if (item) 730 + link_obj(parent_item, item); 731 + } 732 + up(&subsys->su_sem); 733 + 734 + kfree(name); 735 + if (!item) { 736 + config_item_put(parent_item); 737 + return -ENOMEM; 738 + } 739 + 740 + ret = -EINVAL; 741 + type = item->ci_type; 742 + if (type) { 743 + owner = type->ct_owner; 744 + if (try_module_get(owner)) { 745 + if (group) { 746 + ret = configfs_attach_group(parent_item, 747 + item, 748 + dentry); 749 + } else { 750 + ret = configfs_attach_item(parent_item, 751 + item, 752 + dentry); 753 + } 754 + 755 + if (ret) { 756 + down(&subsys->su_sem); 757 + if (group) 758 + unlink_group(group); 759 + else 760 + unlink_obj(item); 761 + client_drop_item(parent_item, item); 762 + up(&subsys->su_sem); 763 + 764 + config_item_put(parent_item); 765 + module_put(owner); 766 + } 767 + } 768 + } 769 + 770 + return ret; 771 + } 772 + 773 + static int configfs_rmdir(struct inode *dir, struct dentry *dentry) 774 + { 775 + struct config_item *parent_item; 776 + struct config_item *item; 777 + struct configfs_subsystem *subsys; 778 + struct configfs_dirent *sd; 779 + struct module *owner = NULL; 780 + int ret; 781 + 782 + if (dentry->d_parent == configfs_sb->s_root) 783 + return -EPERM; 784 + 785 + sd = dentry->d_fsdata; 786 + if (sd->s_type & CONFIGFS_USET_DEFAULT) 787 + return -EPERM; 788 + 789 + parent_item = configfs_get_config_item(dentry->d_parent); 790 + subsys = to_config_group(parent_item)->cg_subsys; 791 + BUG_ON(!subsys); 792 + 793 + if (!parent_item->ci_type) { 794 + config_item_put(parent_item); 795 + return -EINVAL; 796 + } 797 + 798 + ret = configfs_detach_prep(dentry); 799 + if (ret) { 800 + configfs_detach_rollback(dentry); 801 + config_item_put(parent_item); 802 + return ret; 803 + } 804 + 805 + item = configfs_get_config_item(dentry); 806 + 807 + /* Drop reference from above, item already holds one. */ 808 + config_item_put(parent_item); 809 + 810 + if (item->ci_type) 811 + owner = item->ci_type->ct_owner; 812 + 813 + if (sd->s_type & CONFIGFS_USET_DIR) { 814 + configfs_detach_group(item); 815 + 816 + down(&subsys->su_sem); 817 + unlink_group(to_config_group(item)); 818 + } else { 819 + configfs_detach_item(item); 820 + 821 + down(&subsys->su_sem); 822 + unlink_obj(item); 823 + } 824 + 825 + client_drop_item(parent_item, item); 826 + up(&subsys->su_sem); 827 + 828 + /* Drop our reference from above */ 829 + config_item_put(item); 830 + 831 + module_put(owner); 832 + 833 + return 0; 834 + } 835 + 836 + struct inode_operations configfs_dir_inode_operations = { 837 + .mkdir = configfs_mkdir, 838 + .rmdir = configfs_rmdir, 839 + .symlink = configfs_symlink, 840 + .unlink = configfs_unlink, 841 + .lookup = configfs_lookup, 842 + }; 843 + 844 + #if 0 845 + int configfs_rename_dir(struct config_item * item, const char *new_name) 846 + { 847 + int error = 0; 848 + struct dentry * new_dentry, * parent; 849 + 850 + if (!strcmp(config_item_name(item), new_name)) 851 + return -EINVAL; 852 + 853 + if (!item->parent) 854 + return -EINVAL; 855 + 856 + down_write(&configfs_rename_sem); 857 + parent = item->parent->dentry; 858 + 859 + down(&parent->d_inode->i_sem); 860 + 861 + new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); 862 + if (!IS_ERR(new_dentry)) { 863 + if (!new_dentry->d_inode) { 864 + error = config_item_set_name(item, "%s", new_name); 865 + if (!error) { 866 + d_add(new_dentry, NULL); 867 + d_move(item->dentry, new_dentry); 868 + } 869 + else 870 + d_delete(new_dentry); 871 + } else 872 + error = -EEXIST; 873 + dput(new_dentry); 874 + } 875 + up(&parent->d_inode->i_sem); 876 + up_write(&configfs_rename_sem); 877 + 878 + return error; 879 + } 880 + #endif 881 + 882 + static int configfs_dir_open(struct inode *inode, struct file *file) 883 + { 884 + struct dentry * dentry = file->f_dentry; 885 + struct configfs_dirent * parent_sd = dentry->d_fsdata; 886 + 887 + down(&dentry->d_inode->i_sem); 888 + file->private_data = configfs_new_dirent(parent_sd, NULL); 889 + up(&dentry->d_inode->i_sem); 890 + 891 + return file->private_data ? 0 : -ENOMEM; 892 + 893 + } 894 + 895 + static int configfs_dir_close(struct inode *inode, struct file *file) 896 + { 897 + struct dentry * dentry = file->f_dentry; 898 + struct configfs_dirent * cursor = file->private_data; 899 + 900 + down(&dentry->d_inode->i_sem); 901 + list_del_init(&cursor->s_sibling); 902 + up(&dentry->d_inode->i_sem); 903 + 904 + release_configfs_dirent(cursor); 905 + 906 + return 0; 907 + } 908 + 909 + /* Relationship between s_mode and the DT_xxx types */ 910 + static inline unsigned char dt_type(struct configfs_dirent *sd) 911 + { 912 + return (sd->s_mode >> 12) & 15; 913 + } 914 + 915 + static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir) 916 + { 917 + struct dentry *dentry = filp->f_dentry; 918 + struct configfs_dirent * parent_sd = dentry->d_fsdata; 919 + struct configfs_dirent *cursor = filp->private_data; 920 + struct list_head *p, *q = &cursor->s_sibling; 921 + ino_t ino; 922 + int i = filp->f_pos; 923 + 924 + switch (i) { 925 + case 0: 926 + ino = dentry->d_inode->i_ino; 927 + if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) 928 + break; 929 + filp->f_pos++; 930 + i++; 931 + /* fallthrough */ 932 + case 1: 933 + ino = parent_ino(dentry); 934 + if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) 935 + break; 936 + filp->f_pos++; 937 + i++; 938 + /* fallthrough */ 939 + default: 940 + if (filp->f_pos == 2) { 941 + list_del(q); 942 + list_add(q, &parent_sd->s_children); 943 + } 944 + for (p=q->next; p!= &parent_sd->s_children; p=p->next) { 945 + struct configfs_dirent *next; 946 + const char * name; 947 + int len; 948 + 949 + next = list_entry(p, struct configfs_dirent, 950 + s_sibling); 951 + if (!next->s_element) 952 + continue; 953 + 954 + name = configfs_get_name(next); 955 + len = strlen(name); 956 + if (next->s_dentry) 957 + ino = next->s_dentry->d_inode->i_ino; 958 + else 959 + ino = iunique(configfs_sb, 2); 960 + 961 + if (filldir(dirent, name, len, filp->f_pos, ino, 962 + dt_type(next)) < 0) 963 + return 0; 964 + 965 + list_del(q); 966 + list_add(q, p); 967 + p = q; 968 + filp->f_pos++; 969 + } 970 + } 971 + return 0; 972 + } 973 + 974 + static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) 975 + { 976 + struct dentry * dentry = file->f_dentry; 977 + 978 + down(&dentry->d_inode->i_sem); 979 + switch (origin) { 980 + case 1: 981 + offset += file->f_pos; 982 + case 0: 983 + if (offset >= 0) 984 + break; 985 + default: 986 + up(&file->f_dentry->d_inode->i_sem); 987 + return -EINVAL; 988 + } 989 + if (offset != file->f_pos) { 990 + file->f_pos = offset; 991 + if (file->f_pos >= 2) { 992 + struct configfs_dirent *sd = dentry->d_fsdata; 993 + struct configfs_dirent *cursor = file->private_data; 994 + struct list_head *p; 995 + loff_t n = file->f_pos - 2; 996 + 997 + list_del(&cursor->s_sibling); 998 + p = sd->s_children.next; 999 + while (n && p != &sd->s_children) { 1000 + struct configfs_dirent *next; 1001 + next = list_entry(p, struct configfs_dirent, 1002 + s_sibling); 1003 + if (next->s_element) 1004 + n--; 1005 + p = p->next; 1006 + } 1007 + list_add_tail(&cursor->s_sibling, p); 1008 + } 1009 + } 1010 + up(&dentry->d_inode->i_sem); 1011 + return offset; 1012 + } 1013 + 1014 + struct file_operations configfs_dir_operations = { 1015 + .open = configfs_dir_open, 1016 + .release = configfs_dir_close, 1017 + .llseek = configfs_dir_lseek, 1018 + .read = generic_read_dir, 1019 + .readdir = configfs_readdir, 1020 + }; 1021 + 1022 + int configfs_register_subsystem(struct configfs_subsystem *subsys) 1023 + { 1024 + int err; 1025 + struct config_group *group = &subsys->su_group; 1026 + struct qstr name; 1027 + struct dentry *dentry; 1028 + struct configfs_dirent *sd; 1029 + 1030 + err = configfs_pin_fs(); 1031 + if (err) 1032 + return err; 1033 + 1034 + if (!group->cg_item.ci_name) 1035 + group->cg_item.ci_name = group->cg_item.ci_namebuf; 1036 + 1037 + sd = configfs_sb->s_root->d_fsdata; 1038 + link_group(to_config_group(sd->s_element), group); 1039 + 1040 + down(&configfs_sb->s_root->d_inode->i_sem); 1041 + 1042 + name.name = group->cg_item.ci_name; 1043 + name.len = strlen(name.name); 1044 + name.hash = full_name_hash(name.name, name.len); 1045 + 1046 + err = -ENOMEM; 1047 + dentry = d_alloc(configfs_sb->s_root, &name); 1048 + if (!dentry) 1049 + goto out_release; 1050 + 1051 + d_add(dentry, NULL); 1052 + 1053 + err = configfs_attach_group(sd->s_element, &group->cg_item, 1054 + dentry); 1055 + if (!err) 1056 + dentry = NULL; 1057 + else 1058 + d_delete(dentry); 1059 + 1060 + up(&configfs_sb->s_root->d_inode->i_sem); 1061 + 1062 + if (dentry) { 1063 + dput(dentry); 1064 + out_release: 1065 + unlink_group(group); 1066 + configfs_release_fs(); 1067 + } 1068 + 1069 + return err; 1070 + } 1071 + 1072 + void configfs_unregister_subsystem(struct configfs_subsystem *subsys) 1073 + { 1074 + struct config_group *group = &subsys->su_group; 1075 + struct dentry *dentry = group->cg_item.ci_dentry; 1076 + 1077 + if (dentry->d_parent != configfs_sb->s_root) { 1078 + printk(KERN_ERR "configfs: Tried to unregister non-subsystem!\n"); 1079 + return; 1080 + } 1081 + 1082 + down(&configfs_sb->s_root->d_inode->i_sem); 1083 + down(&dentry->d_inode->i_sem); 1084 + if (configfs_detach_prep(dentry)) { 1085 + printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n"); 1086 + } 1087 + configfs_detach_group(&group->cg_item); 1088 + dentry->d_inode->i_flags |= S_DEAD; 1089 + up(&dentry->d_inode->i_sem); 1090 + 1091 + d_delete(dentry); 1092 + 1093 + up(&configfs_sb->s_root->d_inode->i_sem); 1094 + 1095 + dput(dentry); 1096 + 1097 + unlink_group(group); 1098 + configfs_release_fs(); 1099 + } 1100 + 1101 + EXPORT_SYMBOL(configfs_register_subsystem); 1102 + EXPORT_SYMBOL(configfs_unregister_subsystem);
+360
fs/configfs/file.c
··· 1 + /* -*- mode: c; c-basic-offset: 8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * file.c - operations for regular (text) files. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the 18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 021110-1307, USA. 20 + * 21 + * Based on sysfs: 22 + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 23 + * 24 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 + */ 26 + 27 + #include <linux/fs.h> 28 + #include <linux/module.h> 29 + #include <linux/dnotify.h> 30 + #include <linux/slab.h> 31 + #include <asm/uaccess.h> 32 + #include <asm/semaphore.h> 33 + 34 + #include <linux/configfs.h> 35 + #include "configfs_internal.h" 36 + 37 + 38 + struct configfs_buffer { 39 + size_t count; 40 + loff_t pos; 41 + char * page; 42 + struct configfs_item_operations * ops; 43 + struct semaphore sem; 44 + int needs_read_fill; 45 + }; 46 + 47 + 48 + /** 49 + * fill_read_buffer - allocate and fill buffer from item. 50 + * @dentry: dentry pointer. 51 + * @buffer: data buffer for file. 52 + * 53 + * Allocate @buffer->page, if it hasn't been already, then call the 54 + * config_item's show() method to fill the buffer with this attribute's 55 + * data. 56 + * This is called only once, on the file's first read. 57 + */ 58 + static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buffer) 59 + { 60 + struct configfs_attribute * attr = to_attr(dentry); 61 + struct config_item * item = to_item(dentry->d_parent); 62 + struct configfs_item_operations * ops = buffer->ops; 63 + int ret = 0; 64 + ssize_t count; 65 + 66 + if (!buffer->page) 67 + buffer->page = (char *) get_zeroed_page(GFP_KERNEL); 68 + if (!buffer->page) 69 + return -ENOMEM; 70 + 71 + count = ops->show_attribute(item,attr,buffer->page); 72 + buffer->needs_read_fill = 0; 73 + BUG_ON(count > (ssize_t)PAGE_SIZE); 74 + if (count >= 0) 75 + buffer->count = count; 76 + else 77 + ret = count; 78 + return ret; 79 + } 80 + 81 + 82 + /** 83 + * flush_read_buffer - push buffer to userspace. 84 + * @buffer: data buffer for file. 85 + * @userbuf: user-passed buffer. 86 + * @count: number of bytes requested. 87 + * @ppos: file position. 88 + * 89 + * Copy the buffer we filled in fill_read_buffer() to userspace. 90 + * This is done at the reader's leisure, copying and advancing 91 + * the amount they specify each time. 92 + * This may be called continuously until the buffer is empty. 93 + */ 94 + static int flush_read_buffer(struct configfs_buffer * buffer, char __user * buf, 95 + size_t count, loff_t * ppos) 96 + { 97 + int error; 98 + 99 + if (*ppos > buffer->count) 100 + return 0; 101 + 102 + if (count > (buffer->count - *ppos)) 103 + count = buffer->count - *ppos; 104 + 105 + error = copy_to_user(buf,buffer->page + *ppos,count); 106 + if (!error) 107 + *ppos += count; 108 + return error ? -EFAULT : count; 109 + } 110 + 111 + /** 112 + * configfs_read_file - read an attribute. 113 + * @file: file pointer. 114 + * @buf: buffer to fill. 115 + * @count: number of bytes to read. 116 + * @ppos: starting offset in file. 117 + * 118 + * Userspace wants to read an attribute file. The attribute descriptor 119 + * is in the file's ->d_fsdata. The target item is in the directory's 120 + * ->d_fsdata. 121 + * 122 + * We call fill_read_buffer() to allocate and fill the buffer from the 123 + * item's show() method exactly once (if the read is happening from 124 + * the beginning of the file). That should fill the entire buffer with 125 + * all the data the item has to offer for that attribute. 126 + * We then call flush_read_buffer() to copy the buffer to userspace 127 + * in the increments specified. 128 + */ 129 + 130 + static ssize_t 131 + configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) 132 + { 133 + struct configfs_buffer * buffer = file->private_data; 134 + ssize_t retval = 0; 135 + 136 + down(&buffer->sem); 137 + if (buffer->needs_read_fill) { 138 + if ((retval = fill_read_buffer(file->f_dentry,buffer))) 139 + goto out; 140 + } 141 + pr_debug("%s: count = %d, ppos = %lld, buf = %s\n", 142 + __FUNCTION__,count,*ppos,buffer->page); 143 + retval = flush_read_buffer(buffer,buf,count,ppos); 144 + out: 145 + up(&buffer->sem); 146 + return retval; 147 + } 148 + 149 + 150 + /** 151 + * fill_write_buffer - copy buffer from userspace. 152 + * @buffer: data buffer for file. 153 + * @userbuf: data from user. 154 + * @count: number of bytes in @userbuf. 155 + * 156 + * Allocate @buffer->page if it hasn't been already, then 157 + * copy the user-supplied buffer into it. 158 + */ 159 + 160 + static int 161 + fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size_t count) 162 + { 163 + int error; 164 + 165 + if (!buffer->page) 166 + buffer->page = (char *)get_zeroed_page(GFP_KERNEL); 167 + if (!buffer->page) 168 + return -ENOMEM; 169 + 170 + if (count > PAGE_SIZE) 171 + count = PAGE_SIZE; 172 + error = copy_from_user(buffer->page,buf,count); 173 + buffer->needs_read_fill = 1; 174 + return error ? -EFAULT : count; 175 + } 176 + 177 + 178 + /** 179 + * flush_write_buffer - push buffer to config_item. 180 + * @file: file pointer. 181 + * @buffer: data buffer for file. 182 + * 183 + * Get the correct pointers for the config_item and the attribute we're 184 + * dealing with, then call the store() method for the attribute, 185 + * passing the buffer that we acquired in fill_write_buffer(). 186 + */ 187 + 188 + static int 189 + flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count) 190 + { 191 + struct configfs_attribute * attr = to_attr(dentry); 192 + struct config_item * item = to_item(dentry->d_parent); 193 + struct configfs_item_operations * ops = buffer->ops; 194 + 195 + return ops->store_attribute(item,attr,buffer->page,count); 196 + } 197 + 198 + 199 + /** 200 + * configfs_write_file - write an attribute. 201 + * @file: file pointer 202 + * @buf: data to write 203 + * @count: number of bytes 204 + * @ppos: starting offset 205 + * 206 + * Similar to configfs_read_file(), though working in the opposite direction. 207 + * We allocate and fill the data from the user in fill_write_buffer(), 208 + * then push it to the config_item in flush_write_buffer(). 209 + * There is no easy way for us to know if userspace is only doing a partial 210 + * write, so we don't support them. We expect the entire buffer to come 211 + * on the first write. 212 + * Hint: if you're writing a value, first read the file, modify only the 213 + * the value you're changing, then write entire buffer back. 214 + */ 215 + 216 + static ssize_t 217 + configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 218 + { 219 + struct configfs_buffer * buffer = file->private_data; 220 + 221 + down(&buffer->sem); 222 + count = fill_write_buffer(buffer,buf,count); 223 + if (count > 0) 224 + count = flush_write_buffer(file->f_dentry,buffer,count); 225 + if (count > 0) 226 + *ppos += count; 227 + up(&buffer->sem); 228 + return count; 229 + } 230 + 231 + static int check_perm(struct inode * inode, struct file * file) 232 + { 233 + struct config_item *item = configfs_get_config_item(file->f_dentry->d_parent); 234 + struct configfs_attribute * attr = to_attr(file->f_dentry); 235 + struct configfs_buffer * buffer; 236 + struct configfs_item_operations * ops = NULL; 237 + int error = 0; 238 + 239 + if (!item || !attr) 240 + goto Einval; 241 + 242 + /* Grab the module reference for this attribute if we have one */ 243 + if (!try_module_get(attr->ca_owner)) { 244 + error = -ENODEV; 245 + goto Done; 246 + } 247 + 248 + if (item->ci_type) 249 + ops = item->ci_type->ct_item_ops; 250 + else 251 + goto Eaccess; 252 + 253 + /* File needs write support. 254 + * The inode's perms must say it's ok, 255 + * and we must have a store method. 256 + */ 257 + if (file->f_mode & FMODE_WRITE) { 258 + 259 + if (!(inode->i_mode & S_IWUGO) || !ops->store_attribute) 260 + goto Eaccess; 261 + 262 + } 263 + 264 + /* File needs read support. 265 + * The inode's perms must say it's ok, and we there 266 + * must be a show method for it. 267 + */ 268 + if (file->f_mode & FMODE_READ) { 269 + if (!(inode->i_mode & S_IRUGO) || !ops->show_attribute) 270 + goto Eaccess; 271 + } 272 + 273 + /* No error? Great, allocate a buffer for the file, and store it 274 + * it in file->private_data for easy access. 275 + */ 276 + buffer = kmalloc(sizeof(struct configfs_buffer),GFP_KERNEL); 277 + if (buffer) { 278 + memset(buffer,0,sizeof(struct configfs_buffer)); 279 + init_MUTEX(&buffer->sem); 280 + buffer->needs_read_fill = 1; 281 + buffer->ops = ops; 282 + file->private_data = buffer; 283 + } else 284 + error = -ENOMEM; 285 + goto Done; 286 + 287 + Einval: 288 + error = -EINVAL; 289 + goto Done; 290 + Eaccess: 291 + error = -EACCES; 292 + module_put(attr->ca_owner); 293 + Done: 294 + if (error && item) 295 + config_item_put(item); 296 + return error; 297 + } 298 + 299 + static int configfs_open_file(struct inode * inode, struct file * filp) 300 + { 301 + return check_perm(inode,filp); 302 + } 303 + 304 + static int configfs_release(struct inode * inode, struct file * filp) 305 + { 306 + struct config_item * item = to_item(filp->f_dentry->d_parent); 307 + struct configfs_attribute * attr = to_attr(filp->f_dentry); 308 + struct module * owner = attr->ca_owner; 309 + struct configfs_buffer * buffer = filp->private_data; 310 + 311 + if (item) 312 + config_item_put(item); 313 + /* After this point, attr should not be accessed. */ 314 + module_put(owner); 315 + 316 + if (buffer) { 317 + if (buffer->page) 318 + free_page((unsigned long)buffer->page); 319 + kfree(buffer); 320 + } 321 + return 0; 322 + } 323 + 324 + struct file_operations configfs_file_operations = { 325 + .read = configfs_read_file, 326 + .write = configfs_write_file, 327 + .llseek = generic_file_llseek, 328 + .open = configfs_open_file, 329 + .release = configfs_release, 330 + }; 331 + 332 + 333 + int configfs_add_file(struct dentry * dir, const struct configfs_attribute * attr, int type) 334 + { 335 + struct configfs_dirent * parent_sd = dir->d_fsdata; 336 + umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG; 337 + int error = 0; 338 + 339 + down(&dir->d_inode->i_sem); 340 + error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type); 341 + up(&dir->d_inode->i_sem); 342 + 343 + return error; 344 + } 345 + 346 + 347 + /** 348 + * configfs_create_file - create an attribute file for an item. 349 + * @item: item we're creating for. 350 + * @attr: atrribute descriptor. 351 + */ 352 + 353 + int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr) 354 + { 355 + BUG_ON(!item || !item->ci_dentry || !attr); 356 + 357 + return configfs_add_file(item->ci_dentry, attr, 358 + CONFIGFS_ITEM_ATTR); 359 + } 360 +
+162
fs/configfs/inode.c
··· 1 + /* -*- mode: c; c-basic-offset: 8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * inode.c - basic inode and dentry operations. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the 18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 021110-1307, USA. 20 + * 21 + * Based on sysfs: 22 + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 23 + * 24 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 + * 26 + * Please see Documentation/filesystems/configfs.txt for more information. 27 + */ 28 + 29 + #undef DEBUG 30 + 31 + #include <linux/pagemap.h> 32 + #include <linux/namei.h> 33 + #include <linux/backing-dev.h> 34 + 35 + #include <linux/configfs.h> 36 + #include "configfs_internal.h" 37 + 38 + extern struct super_block * configfs_sb; 39 + 40 + static struct address_space_operations configfs_aops = { 41 + .readpage = simple_readpage, 42 + .prepare_write = simple_prepare_write, 43 + .commit_write = simple_commit_write 44 + }; 45 + 46 + static struct backing_dev_info configfs_backing_dev_info = { 47 + .ra_pages = 0, /* No readahead */ 48 + .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, 49 + }; 50 + 51 + struct inode * configfs_new_inode(mode_t mode) 52 + { 53 + struct inode * inode = new_inode(configfs_sb); 54 + if (inode) { 55 + inode->i_mode = mode; 56 + inode->i_uid = 0; 57 + inode->i_gid = 0; 58 + inode->i_blksize = PAGE_CACHE_SIZE; 59 + inode->i_blocks = 0; 60 + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 61 + inode->i_mapping->a_ops = &configfs_aops; 62 + inode->i_mapping->backing_dev_info = &configfs_backing_dev_info; 63 + } 64 + return inode; 65 + } 66 + 67 + int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) 68 + { 69 + int error = 0; 70 + struct inode * inode = NULL; 71 + if (dentry) { 72 + if (!dentry->d_inode) { 73 + if ((inode = configfs_new_inode(mode))) { 74 + if (dentry->d_parent && dentry->d_parent->d_inode) { 75 + struct inode *p_inode = dentry->d_parent->d_inode; 76 + p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 77 + } 78 + goto Proceed; 79 + } 80 + else 81 + error = -ENOMEM; 82 + } else 83 + error = -EEXIST; 84 + } else 85 + error = -ENOENT; 86 + goto Done; 87 + 88 + Proceed: 89 + if (init) 90 + error = init(inode); 91 + if (!error) { 92 + d_instantiate(dentry, inode); 93 + if (S_ISDIR(mode) || S_ISLNK(mode)) 94 + dget(dentry); /* pin link and directory dentries in core */ 95 + } else 96 + iput(inode); 97 + Done: 98 + return error; 99 + } 100 + 101 + /* 102 + * Get the name for corresponding element represented by the given configfs_dirent 103 + */ 104 + const unsigned char * configfs_get_name(struct configfs_dirent *sd) 105 + { 106 + struct attribute * attr; 107 + 108 + if (!sd || !sd->s_element) 109 + BUG(); 110 + 111 + /* These always have a dentry, so use that */ 112 + if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK)) 113 + return sd->s_dentry->d_name.name; 114 + 115 + if (sd->s_type & CONFIGFS_ITEM_ATTR) { 116 + attr = sd->s_element; 117 + return attr->name; 118 + } 119 + return NULL; 120 + } 121 + 122 + 123 + /* 124 + * Unhashes the dentry corresponding to given configfs_dirent 125 + * Called with parent inode's i_sem held. 126 + */ 127 + void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent) 128 + { 129 + struct dentry * dentry = sd->s_dentry; 130 + 131 + if (dentry) { 132 + spin_lock(&dcache_lock); 133 + if (!(d_unhashed(dentry) && dentry->d_inode)) { 134 + dget_locked(dentry); 135 + __d_drop(dentry); 136 + spin_unlock(&dcache_lock); 137 + simple_unlink(parent->d_inode, dentry); 138 + } else 139 + spin_unlock(&dcache_lock); 140 + } 141 + } 142 + 143 + void configfs_hash_and_remove(struct dentry * dir, const char * name) 144 + { 145 + struct configfs_dirent * sd; 146 + struct configfs_dirent * parent_sd = dir->d_fsdata; 147 + 148 + down(&dir->d_inode->i_sem); 149 + list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 150 + if (!sd->s_element) 151 + continue; 152 + if (!strcmp(configfs_get_name(sd), name)) { 153 + list_del_init(&sd->s_sibling); 154 + configfs_drop_dentry(sd, dir); 155 + configfs_put(sd); 156 + break; 157 + } 158 + } 159 + up(&dir->d_inode->i_sem); 160 + } 161 + 162 +
+227
fs/configfs/item.c
··· 1 + /* -*- mode: c; c-basic-offset: 8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * item.c - library routines for handling generic config items 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the 18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 021110-1307, USA. 20 + * 21 + * Based on kobject: 22 + * kobject is Copyright (c) 2002-2003 Patrick Mochel 23 + * 24 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 + * 26 + * Please see the file Documentation/filesystems/configfs.txt for 27 + * critical information about using the config_item interface. 28 + */ 29 + 30 + #include <linux/string.h> 31 + #include <linux/module.h> 32 + #include <linux/stat.h> 33 + #include <linux/slab.h> 34 + 35 + #include <linux/configfs.h> 36 + 37 + 38 + static inline struct config_item * to_item(struct list_head * entry) 39 + { 40 + return container_of(entry,struct config_item,ci_entry); 41 + } 42 + 43 + /* Evil kernel */ 44 + static void config_item_release(struct kref *kref); 45 + 46 + /** 47 + * config_item_init - initialize item. 48 + * @item: item in question. 49 + */ 50 + void config_item_init(struct config_item * item) 51 + { 52 + kref_init(&item->ci_kref); 53 + INIT_LIST_HEAD(&item->ci_entry); 54 + } 55 + 56 + /** 57 + * config_item_set_name - Set the name of an item 58 + * @item: item. 59 + * @name: name. 60 + * 61 + * If strlen(name) >= CONFIGFS_ITEM_NAME_LEN, then use a 62 + * dynamically allocated string that @item->ci_name points to. 63 + * Otherwise, use the static @item->ci_namebuf array. 64 + */ 65 + 66 + int config_item_set_name(struct config_item * item, const char * fmt, ...) 67 + { 68 + int error = 0; 69 + int limit = CONFIGFS_ITEM_NAME_LEN; 70 + int need; 71 + va_list args; 72 + char * name; 73 + 74 + /* 75 + * First, try the static array 76 + */ 77 + va_start(args,fmt); 78 + need = vsnprintf(item->ci_namebuf,limit,fmt,args); 79 + va_end(args); 80 + if (need < limit) 81 + name = item->ci_namebuf; 82 + else { 83 + /* 84 + * Need more space? Allocate it and try again 85 + */ 86 + limit = need + 1; 87 + name = kmalloc(limit,GFP_KERNEL); 88 + if (!name) { 89 + error = -ENOMEM; 90 + goto Done; 91 + } 92 + va_start(args,fmt); 93 + need = vsnprintf(name,limit,fmt,args); 94 + va_end(args); 95 + 96 + /* Still? Give up. */ 97 + if (need >= limit) { 98 + kfree(name); 99 + error = -EFAULT; 100 + goto Done; 101 + } 102 + } 103 + 104 + /* Free the old name, if necessary. */ 105 + if (item->ci_name && item->ci_name != item->ci_namebuf) 106 + kfree(item->ci_name); 107 + 108 + /* Now, set the new name */ 109 + item->ci_name = name; 110 + Done: 111 + return error; 112 + } 113 + 114 + EXPORT_SYMBOL(config_item_set_name); 115 + 116 + void config_item_init_type_name(struct config_item *item, 117 + const char *name, 118 + struct config_item_type *type) 119 + { 120 + config_item_set_name(item, name); 121 + item->ci_type = type; 122 + config_item_init(item); 123 + } 124 + EXPORT_SYMBOL(config_item_init_type_name); 125 + 126 + void config_group_init_type_name(struct config_group *group, const char *name, 127 + struct config_item_type *type) 128 + { 129 + config_item_set_name(&group->cg_item, name); 130 + group->cg_item.ci_type = type; 131 + config_group_init(group); 132 + } 133 + EXPORT_SYMBOL(config_group_init_type_name); 134 + 135 + struct config_item * config_item_get(struct config_item * item) 136 + { 137 + if (item) 138 + kref_get(&item->ci_kref); 139 + return item; 140 + } 141 + 142 + /** 143 + * config_item_cleanup - free config_item resources. 144 + * @item: item. 145 + */ 146 + 147 + void config_item_cleanup(struct config_item * item) 148 + { 149 + struct config_item_type * t = item->ci_type; 150 + struct config_group * s = item->ci_group; 151 + struct config_item * parent = item->ci_parent; 152 + 153 + pr_debug("config_item %s: cleaning up\n",config_item_name(item)); 154 + if (item->ci_name != item->ci_namebuf) 155 + kfree(item->ci_name); 156 + item->ci_name = NULL; 157 + if (t && t->ct_item_ops && t->ct_item_ops->release) 158 + t->ct_item_ops->release(item); 159 + if (s) 160 + config_group_put(s); 161 + if (parent) 162 + config_item_put(parent); 163 + } 164 + 165 + static void config_item_release(struct kref *kref) 166 + { 167 + config_item_cleanup(container_of(kref, struct config_item, ci_kref)); 168 + } 169 + 170 + /** 171 + * config_item_put - decrement refcount for item. 172 + * @item: item. 173 + * 174 + * Decrement the refcount, and if 0, call config_item_cleanup(). 175 + */ 176 + void config_item_put(struct config_item * item) 177 + { 178 + if (item) 179 + kref_put(&item->ci_kref, config_item_release); 180 + } 181 + 182 + 183 + /** 184 + * config_group_init - initialize a group for use 185 + * @k: group 186 + */ 187 + 188 + void config_group_init(struct config_group *group) 189 + { 190 + config_item_init(&group->cg_item); 191 + INIT_LIST_HEAD(&group->cg_children); 192 + } 193 + 194 + 195 + /** 196 + * config_group_find_obj - search for item in group. 197 + * @group: group we're looking in. 198 + * @name: item's name. 199 + * 200 + * Lock group via @group->cg_subsys, and iterate over @group->cg_list, 201 + * looking for a matching config_item. If matching item is found 202 + * take a reference and return the item. 203 + */ 204 + 205 + struct config_item * config_group_find_obj(struct config_group * group, const char * name) 206 + { 207 + struct list_head * entry; 208 + struct config_item * ret = NULL; 209 + 210 + /* XXX LOCKING! */ 211 + list_for_each(entry,&group->cg_children) { 212 + struct config_item * item = to_item(entry); 213 + if (config_item_name(item) && 214 + !strcmp(config_item_name(item), name)) { 215 + ret = config_item_get(item); 216 + break; 217 + } 218 + } 219 + return ret; 220 + } 221 + 222 + 223 + EXPORT_SYMBOL(config_item_init); 224 + EXPORT_SYMBOL(config_group_init); 225 + EXPORT_SYMBOL(config_item_get); 226 + EXPORT_SYMBOL(config_item_put); 227 +
+159
fs/configfs/mount.c
··· 1 + /* -*- mode: c; c-basic-offset: 8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * mount.c - operations for initializing and mounting configfs. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the 18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 021110-1307, USA. 20 + * 21 + * Based on sysfs: 22 + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 23 + * 24 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 + */ 26 + 27 + #include <linux/fs.h> 28 + #include <linux/module.h> 29 + #include <linux/mount.h> 30 + #include <linux/pagemap.h> 31 + #include <linux/init.h> 32 + 33 + #include <linux/configfs.h> 34 + #include "configfs_internal.h" 35 + 36 + /* Random magic number */ 37 + #define CONFIGFS_MAGIC 0x62656570 38 + 39 + struct vfsmount * configfs_mount = NULL; 40 + struct super_block * configfs_sb = NULL; 41 + static int configfs_mnt_count = 0; 42 + 43 + static struct super_operations configfs_ops = { 44 + .statfs = simple_statfs, 45 + .drop_inode = generic_delete_inode, 46 + }; 47 + 48 + static struct config_group configfs_root_group = { 49 + .cg_item = { 50 + .ci_namebuf = "root", 51 + .ci_name = configfs_root_group.cg_item.ci_namebuf, 52 + }, 53 + }; 54 + 55 + int configfs_is_root(struct config_item *item) 56 + { 57 + return item == &configfs_root_group.cg_item; 58 + } 59 + 60 + static struct configfs_dirent configfs_root = { 61 + .s_sibling = LIST_HEAD_INIT(configfs_root.s_sibling), 62 + .s_children = LIST_HEAD_INIT(configfs_root.s_children), 63 + .s_element = &configfs_root_group.cg_item, 64 + .s_type = CONFIGFS_ROOT, 65 + }; 66 + 67 + static int configfs_fill_super(struct super_block *sb, void *data, int silent) 68 + { 69 + struct inode *inode; 70 + struct dentry *root; 71 + 72 + sb->s_blocksize = PAGE_CACHE_SIZE; 73 + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 74 + sb->s_magic = CONFIGFS_MAGIC; 75 + sb->s_op = &configfs_ops; 76 + configfs_sb = sb; 77 + 78 + inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); 79 + if (inode) { 80 + inode->i_op = &configfs_dir_inode_operations; 81 + inode->i_fop = &configfs_dir_operations; 82 + /* directory inodes start off with i_nlink == 2 (for "." entry) */ 83 + inode->i_nlink++; 84 + } else { 85 + pr_debug("configfs: could not get root inode\n"); 86 + return -ENOMEM; 87 + } 88 + 89 + root = d_alloc_root(inode); 90 + if (!root) { 91 + pr_debug("%s: could not get root dentry!\n",__FUNCTION__); 92 + iput(inode); 93 + return -ENOMEM; 94 + } 95 + config_group_init(&configfs_root_group); 96 + configfs_root_group.cg_item.ci_dentry = root; 97 + root->d_fsdata = &configfs_root; 98 + sb->s_root = root; 99 + return 0; 100 + } 101 + 102 + static struct super_block *configfs_get_sb(struct file_system_type *fs_type, 103 + int flags, const char *dev_name, void *data) 104 + { 105 + return get_sb_single(fs_type, flags, data, configfs_fill_super); 106 + } 107 + 108 + static struct file_system_type configfs_fs_type = { 109 + .owner = THIS_MODULE, 110 + .name = "configfs", 111 + .get_sb = configfs_get_sb, 112 + .kill_sb = kill_litter_super, 113 + }; 114 + 115 + int configfs_pin_fs(void) 116 + { 117 + return simple_pin_fs("configfs", &configfs_mount, 118 + &configfs_mnt_count); 119 + } 120 + 121 + void configfs_release_fs(void) 122 + { 123 + simple_release_fs(&configfs_mount, &configfs_mnt_count); 124 + } 125 + 126 + 127 + static decl_subsys(config, NULL, NULL); 128 + 129 + static int __init configfs_init(void) 130 + { 131 + int err; 132 + 133 + kset_set_kset_s(&config_subsys, kernel_subsys); 134 + err = subsystem_register(&config_subsys); 135 + if (err) 136 + return err; 137 + 138 + err = register_filesystem(&configfs_fs_type); 139 + if (err) { 140 + printk(KERN_ERR "configfs: Unable to register filesystem!\n"); 141 + subsystem_unregister(&config_subsys); 142 + } 143 + 144 + return err; 145 + } 146 + 147 + static void __exit configfs_exit(void) 148 + { 149 + unregister_filesystem(&configfs_fs_type); 150 + subsystem_unregister(&config_subsys); 151 + } 152 + 153 + MODULE_AUTHOR("Oracle"); 154 + MODULE_LICENSE("GPL"); 155 + MODULE_VERSION("0.0.1"); 156 + MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration."); 157 + 158 + module_init(configfs_init); 159 + module_exit(configfs_exit);
+281
fs/configfs/symlink.c
··· 1 + /* -*- mode: c; c-basic-offset: 8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * symlink.c - operations for configfs symlinks. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the 18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 021110-1307, USA. 20 + * 21 + * Based on sysfs: 22 + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 23 + * 24 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 + */ 26 + 27 + #include <linux/fs.h> 28 + #include <linux/module.h> 29 + #include <linux/namei.h> 30 + 31 + #include <linux/configfs.h> 32 + #include "configfs_internal.h" 33 + 34 + static int item_depth(struct config_item * item) 35 + { 36 + struct config_item * p = item; 37 + int depth = 0; 38 + do { depth++; } while ((p = p->ci_parent) && !configfs_is_root(p)); 39 + return depth; 40 + } 41 + 42 + static int item_path_length(struct config_item * item) 43 + { 44 + struct config_item * p = item; 45 + int length = 1; 46 + do { 47 + length += strlen(config_item_name(p)) + 1; 48 + p = p->ci_parent; 49 + } while (p && !configfs_is_root(p)); 50 + return length; 51 + } 52 + 53 + static void fill_item_path(struct config_item * item, char * buffer, int length) 54 + { 55 + struct config_item * p; 56 + 57 + --length; 58 + for (p = item; p && !configfs_is_root(p); p = p->ci_parent) { 59 + int cur = strlen(config_item_name(p)); 60 + 61 + /* back up enough to print this bus id with '/' */ 62 + length -= cur; 63 + strncpy(buffer + length,config_item_name(p),cur); 64 + *(buffer + --length) = '/'; 65 + } 66 + } 67 + 68 + static int create_link(struct config_item *parent_item, 69 + struct config_item *item, 70 + struct dentry *dentry) 71 + { 72 + struct configfs_dirent *target_sd = item->ci_dentry->d_fsdata; 73 + struct configfs_symlink *sl; 74 + int ret; 75 + 76 + ret = -ENOMEM; 77 + sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); 78 + if (sl) { 79 + sl->sl_target = config_item_get(item); 80 + /* FIXME: needs a lock, I'd bet */ 81 + list_add(&sl->sl_list, &target_sd->s_links); 82 + ret = configfs_create_link(sl, parent_item->ci_dentry, 83 + dentry); 84 + if (ret) { 85 + list_del_init(&sl->sl_list); 86 + config_item_put(item); 87 + kfree(sl); 88 + } 89 + } 90 + 91 + return ret; 92 + } 93 + 94 + 95 + static int get_target(const char *symname, struct nameidata *nd, 96 + struct config_item **target) 97 + { 98 + int ret; 99 + 100 + ret = path_lookup(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, nd); 101 + if (!ret) { 102 + if (nd->dentry->d_sb == configfs_sb) { 103 + *target = configfs_get_config_item(nd->dentry); 104 + if (!*target) { 105 + ret = -ENOENT; 106 + path_release(nd); 107 + } 108 + } else 109 + ret = -EPERM; 110 + } 111 + 112 + return ret; 113 + } 114 + 115 + 116 + int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 117 + { 118 + int ret; 119 + struct nameidata nd; 120 + struct config_item *parent_item; 121 + struct config_item *target_item; 122 + struct config_item_type *type; 123 + 124 + ret = -EPERM; /* What lack-of-symlink returns */ 125 + if (dentry->d_parent == configfs_sb->s_root) 126 + goto out; 127 + 128 + parent_item = configfs_get_config_item(dentry->d_parent); 129 + type = parent_item->ci_type; 130 + 131 + if (!type || !type->ct_item_ops || 132 + !type->ct_item_ops->allow_link) 133 + goto out_put; 134 + 135 + ret = get_target(symname, &nd, &target_item); 136 + if (ret) 137 + goto out_put; 138 + 139 + ret = type->ct_item_ops->allow_link(parent_item, target_item); 140 + if (!ret) 141 + ret = create_link(parent_item, target_item, dentry); 142 + 143 + config_item_put(target_item); 144 + path_release(&nd); 145 + 146 + out_put: 147 + config_item_put(parent_item); 148 + 149 + out: 150 + return ret; 151 + } 152 + 153 + int configfs_unlink(struct inode *dir, struct dentry *dentry) 154 + { 155 + struct configfs_dirent *sd = dentry->d_fsdata; 156 + struct configfs_symlink *sl; 157 + struct config_item *parent_item; 158 + struct config_item_type *type; 159 + int ret; 160 + 161 + ret = -EPERM; /* What lack-of-symlink returns */ 162 + if (!(sd->s_type & CONFIGFS_ITEM_LINK)) 163 + goto out; 164 + 165 + if (dentry->d_parent == configfs_sb->s_root) 166 + BUG(); 167 + 168 + sl = sd->s_element; 169 + 170 + parent_item = configfs_get_config_item(dentry->d_parent); 171 + type = parent_item->ci_type; 172 + 173 + list_del_init(&sd->s_sibling); 174 + configfs_drop_dentry(sd, dentry->d_parent); 175 + dput(dentry); 176 + configfs_put(sd); 177 + 178 + /* 179 + * drop_link() must be called before 180 + * list_del_init(&sl->sl_list), so that the order of 181 + * drop_link(this, target) and drop_item(target) is preserved. 182 + */ 183 + if (type && type->ct_item_ops && 184 + type->ct_item_ops->drop_link) 185 + type->ct_item_ops->drop_link(parent_item, 186 + sl->sl_target); 187 + 188 + /* FIXME: Needs lock */ 189 + list_del_init(&sl->sl_list); 190 + 191 + /* Put reference from create_link() */ 192 + config_item_put(sl->sl_target); 193 + kfree(sl); 194 + 195 + config_item_put(parent_item); 196 + 197 + ret = 0; 198 + 199 + out: 200 + return ret; 201 + } 202 + 203 + static int configfs_get_target_path(struct config_item * item, struct config_item * target, 204 + char *path) 205 + { 206 + char * s; 207 + int depth, size; 208 + 209 + depth = item_depth(item); 210 + size = item_path_length(target) + depth * 3 - 1; 211 + if (size > PATH_MAX) 212 + return -ENAMETOOLONG; 213 + 214 + pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size); 215 + 216 + for (s = path; depth--; s += 3) 217 + strcpy(s,"../"); 218 + 219 + fill_item_path(target, path, size); 220 + pr_debug("%s: path = '%s'\n", __FUNCTION__, path); 221 + 222 + return 0; 223 + } 224 + 225 + static int configfs_getlink(struct dentry *dentry, char * path) 226 + { 227 + struct config_item *item, *target_item; 228 + int error = 0; 229 + 230 + item = configfs_get_config_item(dentry->d_parent); 231 + if (!item) 232 + return -EINVAL; 233 + 234 + target_item = configfs_get_config_item(dentry); 235 + if (!target_item) { 236 + config_item_put(item); 237 + return -EINVAL; 238 + } 239 + 240 + down_read(&configfs_rename_sem); 241 + error = configfs_get_target_path(item, target_item, path); 242 + up_read(&configfs_rename_sem); 243 + 244 + config_item_put(item); 245 + config_item_put(target_item); 246 + return error; 247 + 248 + } 249 + 250 + static void *configfs_follow_link(struct dentry *dentry, struct nameidata *nd) 251 + { 252 + int error = -ENOMEM; 253 + unsigned long page = get_zeroed_page(GFP_KERNEL); 254 + 255 + if (page) { 256 + error = configfs_getlink(dentry, (char *)page); 257 + if (!error) { 258 + nd_set_link(nd, (char *)page); 259 + return (void *)page; 260 + } 261 + } 262 + 263 + nd_set_link(nd, ERR_PTR(error)); 264 + return NULL; 265 + } 266 + 267 + static void configfs_put_link(struct dentry *dentry, struct nameidata *nd, 268 + void *cookie) 269 + { 270 + if (cookie) { 271 + unsigned long page = (unsigned long)cookie; 272 + free_page(page); 273 + } 274 + } 275 + 276 + struct inode_operations configfs_symlink_inode_operations = { 277 + .follow_link = configfs_follow_link, 278 + .readlink = generic_readlink, 279 + .put_link = configfs_put_link, 280 + }; 281 +
+205
include/linux/configfs.h
··· 1 + /* -*- mode: c; c-basic-offset: 8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * configfs.h - definitions for the device driver filesystem 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public 8 + * License as published by the Free Software Foundation; either 9 + * version 2 of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 + * General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public 17 + * License along with this program; if not, write to the 18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 + * Boston, MA 021110-1307, USA. 20 + * 21 + * Based on sysfs: 22 + * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 23 + * 24 + * Based on kobject.h: 25 + * Copyright (c) 2002-2003 Patrick Mochel 26 + * Copyright (c) 2002-2003 Open Source Development Labs 27 + * 28 + * configfs Copyright (C) 2005 Oracle. All rights reserved. 29 + * 30 + * Please read Documentation/filesystems/configfs.txt before using the 31 + * configfs interface, ESPECIALLY the parts about reference counts and 32 + * item destructors. 33 + */ 34 + 35 + #ifndef _CONFIGFS_H_ 36 + #define _CONFIGFS_H_ 37 + 38 + #ifdef __KERNEL__ 39 + 40 + #include <linux/types.h> 41 + #include <linux/list.h> 42 + #include <linux/kref.h> 43 + 44 + #include <asm/atomic.h> 45 + #include <asm/semaphore.h> 46 + 47 + #define CONFIGFS_ITEM_NAME_LEN 20 48 + 49 + struct module; 50 + 51 + struct configfs_item_operations; 52 + struct configfs_group_operations; 53 + struct configfs_attribute; 54 + struct configfs_subsystem; 55 + 56 + struct config_item { 57 + char *ci_name; 58 + char ci_namebuf[CONFIGFS_ITEM_NAME_LEN]; 59 + struct kref ci_kref; 60 + struct list_head ci_entry; 61 + struct config_item *ci_parent; 62 + struct config_group *ci_group; 63 + struct config_item_type *ci_type; 64 + struct dentry *ci_dentry; 65 + }; 66 + 67 + extern int config_item_set_name(struct config_item *, const char *, ...); 68 + 69 + static inline char *config_item_name(struct config_item * item) 70 + { 71 + return item->ci_name; 72 + } 73 + 74 + extern void config_item_init(struct config_item *); 75 + extern void config_item_init_type_name(struct config_item *item, 76 + const char *name, 77 + struct config_item_type *type); 78 + extern void config_item_cleanup(struct config_item *); 79 + 80 + extern struct config_item * config_item_get(struct config_item *); 81 + extern void config_item_put(struct config_item *); 82 + 83 + struct config_item_type { 84 + struct module *ct_owner; 85 + struct configfs_item_operations *ct_item_ops; 86 + struct configfs_group_operations *ct_group_ops; 87 + struct configfs_attribute **ct_attrs; 88 + }; 89 + 90 + 91 + /** 92 + * group - a group of config_items of a specific type, belonging 93 + * to a specific subsystem. 94 + */ 95 + 96 + struct config_group { 97 + struct config_item cg_item; 98 + struct list_head cg_children; 99 + struct configfs_subsystem *cg_subsys; 100 + struct config_group **default_groups; 101 + }; 102 + 103 + 104 + extern void config_group_init(struct config_group *group); 105 + extern void config_group_init_type_name(struct config_group *group, 106 + const char *name, 107 + struct config_item_type *type); 108 + 109 + 110 + static inline struct config_group *to_config_group(struct config_item *item) 111 + { 112 + return item ? container_of(item,struct config_group,cg_item) : NULL; 113 + } 114 + 115 + static inline struct config_group *config_group_get(struct config_group *group) 116 + { 117 + return group ? to_config_group(config_item_get(&group->cg_item)) : NULL; 118 + } 119 + 120 + static inline void config_group_put(struct config_group *group) 121 + { 122 + config_item_put(&group->cg_item); 123 + } 124 + 125 + extern struct config_item *config_group_find_obj(struct config_group *, const char *); 126 + 127 + 128 + struct configfs_attribute { 129 + char *ca_name; 130 + struct module *ca_owner; 131 + mode_t ca_mode; 132 + }; 133 + 134 + 135 + /* 136 + * If allow_link() exists, the item can symlink(2) out to other 137 + * items. If the item is a group, it may support mkdir(2). 138 + * Groups supply one of make_group() and make_item(). If the 139 + * group supports make_group(), one can create group children. If it 140 + * supports make_item(), one can create config_item children. If it has 141 + * default_groups on group->default_groups, it has automatically created 142 + * group children. default_groups may coexist alongsize make_group() or 143 + * make_item(), but if the group wishes to have only default_groups 144 + * children (disallowing mkdir(2)), it need not provide either function. 145 + * If the group has commit(), it supports pending and commited (active) 146 + * items. 147 + */ 148 + struct configfs_item_operations { 149 + void (*release)(struct config_item *); 150 + ssize_t (*show_attribute)(struct config_item *, struct configfs_attribute *,char *); 151 + ssize_t (*store_attribute)(struct config_item *,struct configfs_attribute *,const char *, size_t); 152 + int (*allow_link)(struct config_item *src, struct config_item *target); 153 + int (*drop_link)(struct config_item *src, struct config_item *target); 154 + }; 155 + 156 + struct configfs_group_operations { 157 + struct config_item *(*make_item)(struct config_group *group, const char *name); 158 + struct config_group *(*make_group)(struct config_group *group, const char *name); 159 + int (*commit_item)(struct config_item *item); 160 + void (*drop_item)(struct config_group *group, struct config_item *item); 161 + }; 162 + 163 + 164 + 165 + /** 166 + * Use these macros to make defining attributes easier. See include/linux/device.h 167 + * for examples.. 168 + */ 169 + 170 + #if 0 171 + #define __ATTR(_name,_mode,_show,_store) { \ 172 + .attr = {.ca_name = __stringify(_name), .ca_mode = _mode, .ca_owner = THIS_MODULE }, \ 173 + .show = _show, \ 174 + .store = _store, \ 175 + } 176 + 177 + #define __ATTR_RO(_name) { \ 178 + .attr = { .ca_name = __stringify(_name), .ca_mode = 0444, .ca_owner = THIS_MODULE }, \ 179 + .show = _name##_show, \ 180 + } 181 + 182 + #define __ATTR_NULL { .attr = { .name = NULL } } 183 + 184 + #define attr_name(_attr) (_attr).attr.name 185 + #endif 186 + 187 + 188 + struct configfs_subsystem { 189 + struct config_group su_group; 190 + struct semaphore su_sem; 191 + }; 192 + 193 + static inline struct configfs_subsystem *to_configfs_subsystem(struct config_group *group) 194 + { 195 + return group ? 196 + container_of(group, struct configfs_subsystem, su_group) : 197 + NULL; 198 + } 199 + 200 + int configfs_register_subsystem(struct configfs_subsystem *subsys); 201 + void configfs_unregister_subsystem(struct configfs_subsystem *subsys); 202 + 203 + #endif /* __KERNEL__ */ 204 + 205 + #endif /* _CONFIGFS_H_ */