Commit | Line | Data |
---|---|---|
98264991 MCC |
1 | ======================================================= |
2 | Configfs - Userspace-driven Kernel Object Configuration | |
3 | ======================================================= | |
7063fbf2 JB |
4 | |
5 | Joel Becker <joel.becker@oracle.com> | |
6 | ||
7 | Updated: 31 March 2005 | |
8 | ||
9 | Copyright (c) 2005 Oracle Corporation, | |
10 | Joel Becker <joel.becker@oracle.com> | |
11 | ||
12 | ||
98264991 MCC |
13 | What is configfs? |
14 | ================= | |
7063fbf2 JB |
15 | |
16 | configfs is a ram-based filesystem that provides the converse of | |
17 | sysfs's functionality. Where sysfs is a filesystem-based view of | |
18 | kernel objects, configfs is a filesystem-based manager of kernel | |
19 | objects, or config_items. | |
20 | ||
21 | With sysfs, an object is created in kernel (for example, when a device | |
22 | is discovered) and it is registered with sysfs. Its attributes then | |
23 | appear in sysfs, allowing userspace to read the attributes via | |
24 | readdir(3)/read(2). It may allow some attributes to be modified via | |
25 | write(2). The important point is that the object is created and | |
26 | destroyed in kernel, the kernel controls the lifecycle of the sysfs | |
27 | representation, and sysfs is merely a window on all this. | |
28 | ||
29 | A configfs config_item is created via an explicit userspace operation: | |
30 | mkdir(2). It is destroyed via rmdir(2). The attributes appear at | |
31 | mkdir(2) time, and can be read or modified via read(2) and write(2). | |
32 | As with sysfs, readdir(3) queries the list of items and/or attributes. | |
33 | symlink(2) can be used to group items together. Unlike sysfs, the | |
34 | lifetime of the representation is completely driven by userspace. The | |
35 | kernel modules backing the items must respond to this. | |
36 | ||
37 | Both sysfs and configfs can and should exist together on the same | |
38 | system. One is not a replacement for the other. | |
39 | ||
98264991 MCC |
40 | Using configfs |
41 | ============== | |
7063fbf2 JB |
42 | |
43 | configfs can be compiled as a module or into the kernel. You can access | |
98264991 | 44 | it by doing:: |
7063fbf2 JB |
45 | |
46 | mount -t configfs none /config | |
47 | ||
48 | The configfs tree will be empty unless client modules are also loaded. | |
49 | These are modules that register their item types with configfs as | |
50 | subsystems. Once a client subsystem is loaded, it will appear as a | |
51 | subdirectory (or more than one) under /config. Like sysfs, the | |
52 | configfs tree is always there, whether mounted on /config or not. | |
53 | ||
54 | An item is created via mkdir(2). The item's attributes will also | |
55 | appear at this time. readdir(3) can determine what the attributes are, | |
56 | read(2) can query their default values, and write(2) can store new | |
03607ace PA |
57 | values. Don't mix more than one attribute in one attribute file. |
58 | ||
59 | There are two types of configfs attributes: | |
60 | ||
61 | * Normal attributes, which similar to sysfs attributes, are small ASCII text | |
98264991 MCC |
62 | files, with a maximum size of one page (PAGE_SIZE, 4096 on i386). Preferably |
63 | only one value per file should be used, and the same caveats from sysfs apply. | |
64 | Configfs expects write(2) to store the entire buffer at once. When writing to | |
65 | normal configfs attributes, userspace processes should first read the entire | |
66 | file, modify the portions they wish to change, and then write the entire | |
67 | buffer back. | |
03607ace PA |
68 | |
69 | * Binary attributes, which are somewhat similar to sysfs binary attributes, | |
98264991 MCC |
70 | but with a few slight changes to semantics. The PAGE_SIZE limitation does not |
71 | apply, but the whole binary item must fit in single kernel vmalloc'ed buffer. | |
72 | The write(2) calls from user space are buffered, and the attributes' | |
73 | write_bin_attribute method will be invoked on the final close, therefore it is | |
74 | imperative for user-space to check the return code of close(2) in order to | |
75 | verify that the operation finished successfully. | |
76 | To avoid a malicious user OOMing the kernel, there's a per-binary attribute | |
77 | maximum buffer value. | |
7063fbf2 JB |
78 | |
79 | When an item needs to be destroyed, remove it with rmdir(2). An | |
80 | item cannot be destroyed if any other item has a link to it (via | |
81 | symlink(2)). Links can be removed via unlink(2). | |
82 | ||
98264991 MCC |
83 | Configuring FakeNBD: an Example |
84 | =============================== | |
7063fbf2 JB |
85 | |
86 | Imagine there's a Network Block Device (NBD) driver that allows you to | |
87 | access remote block devices. Call it FakeNBD. FakeNBD uses configfs | |
88 | for its configuration. Obviously, there will be a nice program that | |
89 | sysadmins use to configure FakeNBD, but somehow that program has to tell | |
90 | the driver about it. Here's where configfs comes in. | |
91 | ||
92 | When the FakeNBD driver is loaded, it registers itself with configfs. | |
98264991 | 93 | readdir(3) sees this just fine:: |
7063fbf2 JB |
94 | |
95 | # ls /config | |
96 | fakenbd | |
97 | ||
98 | A fakenbd connection can be created with mkdir(2). The name is | |
99 | arbitrary, but likely the tool will make some use of the name. Perhaps | |
98264991 | 100 | it is a uuid or a disk name:: |
7063fbf2 JB |
101 | |
102 | # mkdir /config/fakenbd/disk1 | |
103 | # ls /config/fakenbd/disk1 | |
104 | target device rw | |
105 | ||
106 | The target attribute contains the IP address of the server FakeNBD will | |
107 | connect to. The device attribute is the device on the server. | |
108 | Predictably, the rw attribute determines whether the connection is | |
98264991 | 109 | read-only or read-write:: |
7063fbf2 JB |
110 | |
111 | # echo 10.0.0.1 > /config/fakenbd/disk1/target | |
112 | # echo /dev/sda1 > /config/fakenbd/disk1/device | |
113 | # echo 1 > /config/fakenbd/disk1/rw | |
114 | ||
115 | That's it. That's all there is. Now the device is configured, via the | |
116 | shell no less. | |
117 | ||
98264991 MCC |
118 | Coding With configfs |
119 | ==================== | |
7063fbf2 JB |
120 | |
121 | Every object in configfs is a config_item. A config_item reflects an | |
122 | object in the subsystem. It has attributes that match values on that | |
123 | object. configfs handles the filesystem representation of that object | |
124 | and its attributes, allowing the subsystem to ignore all but the | |
125 | basic show/store interaction. | |
126 | ||
127 | Items are created and destroyed inside a config_group. A group is a | |
128 | collection of items that share the same attributes and operations. | |
129 | Items are created by mkdir(2) and removed by rmdir(2), but configfs | |
130 | handles that. The group has a set of operations to perform these tasks | |
131 | ||
132 | A subsystem is the top level of a client module. During initialization, | |
133 | the client module registers the subsystem with configfs, the subsystem | |
134 | appears as a directory at the top of the configfs filesystem. A | |
135 | subsystem is also a config_group, and can do everything a config_group | |
136 | can. | |
137 | ||
98264991 MCC |
138 | struct config_item |
139 | ================== | |
140 | ||
141 | :: | |
7063fbf2 JB |
142 | |
143 | struct config_item { | |
144 | char *ci_name; | |
145 | char ci_namebuf[UOBJ_NAME_LEN]; | |
146 | struct kref ci_kref; | |
147 | struct list_head ci_entry; | |
148 | struct config_item *ci_parent; | |
149 | struct config_group *ci_group; | |
150 | struct config_item_type *ci_type; | |
151 | struct dentry *ci_dentry; | |
152 | }; | |
153 | ||
154 | void config_item_init(struct config_item *); | |
155 | void config_item_init_type_name(struct config_item *, | |
156 | const char *name, | |
157 | struct config_item_type *type); | |
158 | struct config_item *config_item_get(struct config_item *); | |
159 | void config_item_put(struct config_item *); | |
160 | ||
161 | Generally, struct config_item is embedded in a container structure, a | |
162 | structure that actually represents what the subsystem is doing. The | |
163 | config_item portion of that structure is how the object interacts with | |
164 | configfs. | |
165 | ||
166 | Whether statically defined in a source file or created by a parent | |
167 | config_group, a config_item must have one of the _init() functions | |
168 | called on it. This initializes the reference count and sets up the | |
169 | appropriate fields. | |
170 | ||
171 | All users of a config_item should have a reference on it via | |
172 | config_item_get(), and drop the reference when they are done via | |
173 | config_item_put(). | |
174 | ||
175 | By itself, a config_item cannot do much more than appear in configfs. | |
176 | Usually a subsystem wants the item to display and/or store attributes, | |
177 | among other things. For that, it needs a type. | |
178 | ||
98264991 MCC |
179 | struct config_item_type |
180 | ======================= | |
181 | ||
182 | :: | |
7063fbf2 JB |
183 | |
184 | struct configfs_item_operations { | |
185 | void (*release)(struct config_item *); | |
7063fbf2 JB |
186 | int (*allow_link)(struct config_item *src, |
187 | struct config_item *target); | |
e16769d4 | 188 | void (*drop_link)(struct config_item *src, |
7063fbf2 JB |
189 | struct config_item *target); |
190 | }; | |
191 | ||
192 | struct config_item_type { | |
193 | struct module *ct_owner; | |
194 | struct configfs_item_operations *ct_item_ops; | |
195 | struct configfs_group_operations *ct_group_ops; | |
196 | struct configfs_attribute **ct_attrs; | |
03607ace | 197 | struct configfs_bin_attribute **ct_bin_attrs; |
7063fbf2 JB |
198 | }; |
199 | ||
200 | The most basic function of a config_item_type is to define what | |
201 | operations can be performed on a config_item. All items that have been | |
202 | allocated dynamically will need to provide the ct_item_ops->release() | |
203 | method. This method is called when the config_item's reference count | |
51798222 | 204 | reaches zero. |
7063fbf2 | 205 | |
98264991 MCC |
206 | struct configfs_attribute |
207 | ========================= | |
208 | ||
209 | :: | |
7063fbf2 JB |
210 | |
211 | struct configfs_attribute { | |
212 | char *ca_name; | |
213 | struct module *ca_owner; | |
43947514 | 214 | umode_t ca_mode; |
51798222 CH |
215 | ssize_t (*show)(struct config_item *, char *); |
216 | ssize_t (*store)(struct config_item *, const char *, size_t); | |
7063fbf2 JB |
217 | }; |
218 | ||
219 | When a config_item wants an attribute to appear as a file in the item's | |
220 | configfs directory, it must define a configfs_attribute describing it. | |
221 | It then adds the attribute to the NULL-terminated array | |
222 | config_item_type->ct_attrs. When the item appears in configfs, the | |
223 | attribute file will appear with the configfs_attribute->ca_name | |
224 | filename. configfs_attribute->ca_mode specifies the file permissions. | |
225 | ||
51798222 CH |
226 | If an attribute is readable and provides a ->show method, that method will |
227 | be called whenever userspace asks for a read(2) on the attribute. If an | |
228 | attribute is writable and provides a ->store method, that method will be | |
58c8e97d | 229 | called whenever userspace asks for a write(2) on the attribute. |
7063fbf2 | 230 | |
98264991 MCC |
231 | struct configfs_bin_attribute |
232 | ============================= | |
233 | ||
234 | :: | |
03607ace | 235 | |
6b5a49b4 | 236 | struct configfs_bin_attribute { |
03607ace PA |
237 | struct configfs_attribute cb_attr; |
238 | void *cb_private; | |
239 | size_t cb_max_size; | |
240 | }; | |
241 | ||
242 | The binary attribute is used when the one needs to use binary blob to | |
243 | appear as the contents of a file in the item's configfs directory. | |
244 | To do so add the binary attribute to the NULL-terminated array | |
245 | config_item_type->ct_bin_attrs, and the item appears in configfs, the | |
246 | attribute file will appear with the configfs_bin_attribute->cb_attr.ca_name | |
247 | filename. configfs_bin_attribute->cb_attr.ca_mode specifies the file | |
248 | permissions. | |
249 | The cb_private member is provided for use by the driver, while the | |
250 | cb_max_size member specifies the maximum amount of vmalloc buffer | |
251 | to be used. | |
252 | ||
253 | If binary attribute is readable and the config_item provides a | |
254 | ct_item_ops->read_bin_attribute() method, that method will be called | |
255 | whenever userspace asks for a read(2) on the attribute. The converse | |
256 | will happen for write(2). The reads/writes are bufferred so only a | |
257 | single read/write will occur; the attributes' need not concern itself | |
258 | with it. | |
259 | ||
98264991 MCC |
260 | struct config_group |
261 | =================== | |
7063fbf2 | 262 | |
4ae0edc2 | 263 | A config_item cannot live in a vacuum. The only way one can be created |
7063fbf2 | 264 | is via mkdir(2) on a config_group. This will trigger creation of a |
98264991 | 265 | child item:: |
7063fbf2 JB |
266 | |
267 | struct config_group { | |
268 | struct config_item cg_item; | |
269 | struct list_head cg_children; | |
270 | struct configfs_subsystem *cg_subsys; | |
1ae1602d CH |
271 | struct list_head default_groups; |
272 | struct list_head group_entry; | |
7063fbf2 JB |
273 | }; |
274 | ||
275 | void config_group_init(struct config_group *group); | |
276 | void config_group_init_type_name(struct config_group *group, | |
277 | const char *name, | |
278 | struct config_item_type *type); | |
279 | ||
280 | ||
281 | The config_group structure contains a config_item. Properly configuring | |
282 | that item means that a group can behave as an item in its own right. | |
283 | However, it can do more: it can create child items or groups. This is | |
284 | accomplished via the group operations specified on the group's | |
98264991 | 285 | config_item_type:: |
7063fbf2 JB |
286 | |
287 | struct configfs_group_operations { | |
f89ab861 JB |
288 | struct config_item *(*make_item)(struct config_group *group, |
289 | const char *name); | |
290 | struct config_group *(*make_group)(struct config_group *group, | |
291 | const char *name); | |
299894cc JB |
292 | void (*disconnect_notify)(struct config_group *group, |
293 | struct config_item *item); | |
7063fbf2 JB |
294 | void (*drop_item)(struct config_group *group, |
295 | struct config_item *item); | |
296 | }; | |
297 | ||
298 | A group creates child items by providing the | |
98264991 MCC |
299 | ct_group_ops->make_item() method. If provided, this method is called from |
300 | mkdir(2) in the group's directory. The subsystem allocates a new | |
7063fbf2 JB |
301 | config_item (or more likely, its container structure), initializes it, |
302 | and returns it to configfs. Configfs will then populate the filesystem | |
303 | tree to reflect the new item. | |
304 | ||
305 | If the subsystem wants the child to be a group itself, the subsystem | |
306 | provides ct_group_ops->make_group(). Everything else behaves the same, | |
307 | using the group _init() functions on the group. | |
308 | ||
309 | Finally, when userspace calls rmdir(2) on the item or group, | |
310 | ct_group_ops->drop_item() is called. As a config_group is also a | |
53cb4726 | 311 | config_item, it is not necessary for a separate drop_group() method. |
7063fbf2 JB |
312 | The subsystem must config_item_put() the reference that was initialized |
313 | upon item allocation. If a subsystem has no work to do, it may omit | |
314 | the ct_group_ops->drop_item() method, and configfs will call | |
315 | config_item_put() on the item on behalf of the subsystem. | |
316 | ||
98264991 MCC |
317 | Important: |
318 | drop_item() is void, and as such cannot fail. When rmdir(2) | |
319 | is called, configfs WILL remove the item from the filesystem tree | |
320 | (assuming that it has no children to keep it busy). The subsystem is | |
321 | responsible for responding to this. If the subsystem has references to | |
322 | the item in other threads, the memory is safe. It may take some time | |
323 | for the item to actually disappear from the subsystem's usage. But it | |
324 | is gone from configfs. | |
7063fbf2 | 325 | |
299894cc JB |
326 | When drop_item() is called, the item's linkage has already been torn |
327 | down. It no longer has a reference on its parent and has no place in | |
328 | the item hierarchy. If a client needs to do some cleanup before this | |
329 | teardown happens, the subsystem can implement the | |
330 | ct_group_ops->disconnect_notify() method. The method is called after | |
331 | configfs has removed the item from the filesystem view but before the | |
332 | item is removed from its parent group. Like drop_item(), | |
333 | disconnect_notify() is void and cannot fail. Client subsystems should | |
334 | not drop any references here, as they still must do it in drop_item(). | |
335 | ||
7063fbf2 JB |
336 | A config_group cannot be removed while it still has child items. This |
337 | is implemented in the configfs rmdir(2) code. ->drop_item() will not be | |
338 | called, as the item has not been dropped. rmdir(2) will fail, as the | |
339 | directory is not empty. | |
340 | ||
98264991 MCC |
341 | struct configfs_subsystem |
342 | ========================= | |
7063fbf2 | 343 | |
4ae0edc2 | 344 | A subsystem must register itself, usually at module_init time. This |
98264991 | 345 | tells configfs to make the subsystem appear in the file tree:: |
7063fbf2 JB |
346 | |
347 | struct configfs_subsystem { | |
348 | struct config_group su_group; | |
e6bd07ae | 349 | struct mutex su_mutex; |
7063fbf2 JB |
350 | }; |
351 | ||
352 | int configfs_register_subsystem(struct configfs_subsystem *subsys); | |
353 | void configfs_unregister_subsystem(struct configfs_subsystem *subsys); | |
354 | ||
98264991 | 355 | A subsystem consists of a toplevel config_group and a mutex. |
7063fbf2 JB |
356 | The group is where child config_items are created. For a subsystem, |
357 | this group is usually defined statically. Before calling | |
358 | configfs_register_subsystem(), the subsystem must have initialized the | |
359 | group via the usual group _init() functions, and it must also have | |
e6bd07ae | 360 | initialized the mutex. |
98264991 MCC |
361 | |
362 | When the register call returns, the subsystem is live, and it | |
7063fbf2 JB |
363 | will be visible via configfs. At that point, mkdir(2) can be called and |
364 | the subsystem must be ready for it. | |
365 | ||
98264991 MCC |
366 | An Example |
367 | ========== | |
7063fbf2 JB |
368 | |
369 | The best example of these basic concepts is the simple_children | |
51798222 CH |
370 | subsystem/group and the simple_child item in |
371 | samples/configfs/configfs_sample.c. It shows a trivial object displaying | |
372 | and storing an attribute, and a simple group creating and destroying | |
373 | these children. | |
7063fbf2 | 374 | |
98264991 MCC |
375 | Hierarchy Navigation and the Subsystem Mutex |
376 | ============================================ | |
7063fbf2 JB |
377 | |
378 | There is an extra bonus that configfs provides. The config_groups and | |
379 | config_items are arranged in a hierarchy due to the fact that they | |
380 | appear in a filesystem. A subsystem is NEVER to touch the filesystem | |
381 | parts, but the subsystem might be interested in this hierarchy. For | |
382 | this reason, the hierarchy is mirrored via the config_group->cg_children | |
383 | and config_item->ci_parent structure members. | |
384 | ||
385 | A subsystem can navigate the cg_children list and the ci_parent pointer | |
386 | to see the tree created by the subsystem. This can race with configfs' | |
e6bd07ae | 387 | management of the hierarchy, so configfs uses the subsystem mutex to |
7063fbf2 JB |
388 | protect modifications. Whenever a subsystem wants to navigate the |
389 | hierarchy, it must do so under the protection of the subsystem | |
e6bd07ae | 390 | mutex. |
7063fbf2 | 391 | |
e6bd07ae | 392 | A subsystem will be prevented from acquiring the mutex while a newly |
7063fbf2 | 393 | allocated item has not been linked into this hierarchy. Similarly, it |
e6bd07ae | 394 | will not be able to acquire the mutex while a dropping item has not |
7063fbf2 JB |
395 | yet been unlinked. This means that an item's ci_parent pointer will |
396 | never be NULL while the item is in configfs, and that an item will only | |
397 | be in its parent's cg_children list for the same duration. This allows | |
398 | a subsystem to trust ci_parent and cg_children while they hold the | |
e6bd07ae | 399 | mutex. |
7063fbf2 | 400 | |
98264991 MCC |
401 | Item Aggregation Via symlink(2) |
402 | =============================== | |
7063fbf2 JB |
403 | |
404 | configfs provides a simple group via the group->item parent/child | |
405 | relationship. Often, however, a larger environment requires aggregation | |
406 | outside of the parent/child connection. This is implemented via | |
407 | symlink(2). | |
408 | ||
409 | A config_item may provide the ct_item_ops->allow_link() and | |
410 | ct_item_ops->drop_link() methods. If the ->allow_link() method exists, | |
411 | symlink(2) may be called with the config_item as the source of the link. | |
412 | These links are only allowed between configfs config_items. Any | |
413 | symlink(2) attempt outside the configfs filesystem will be denied. | |
414 | ||
415 | When symlink(2) is called, the source config_item's ->allow_link() | |
416 | method is called with itself and a target item. If the source item | |
417 | allows linking to target item, it returns 0. A source item may wish to | |
418 | reject a link if it only wants links to a certain type of object (say, | |
419 | in its own subsystem). | |
420 | ||
421 | When unlink(2) is called on the symbolic link, the source item is | |
422 | notified via the ->drop_link() method. Like the ->drop_item() method, | |
423 | this is a void function and cannot return failure. The subsystem is | |
424 | responsible for responding to the change. | |
425 | ||
426 | A config_item cannot be removed while it links to any other item, nor | |
427 | can it be removed while an item links to it. Dangling symlinks are not | |
428 | allowed in configfs. | |
429 | ||
98264991 MCC |
430 | Automatically Created Subgroups |
431 | =============================== | |
7063fbf2 JB |
432 | |
433 | A new config_group may want to have two types of child config_items. | |
434 | While this could be codified by magic names in ->make_item(), it is much | |
435 | more explicit to have a method whereby userspace sees this divergence. | |
436 | ||
437 | Rather than have a group where some items behave differently than | |
438 | others, configfs provides a method whereby one or many subgroups are | |
439 | automatically created inside the parent at its creation. Thus, | |
48cc7ec9 | 440 | mkdir("parent") results in "parent", "parent/subgroup1", up through |
7063fbf2 JB |
441 | "parent/subgroupN". Items of type 1 can now be created in |
442 | "parent/subgroup1", and items of type N can be created in | |
443 | "parent/subgroupN". | |
444 | ||
445 | These automatic subgroups, or default groups, do not preclude other | |
446 | children of the parent group. If ct_group_ops->make_group() exists, | |
447 | other child groups can be created on the parent group directly. | |
448 | ||
1ae1602d CH |
449 | A configfs subsystem specifies default groups by adding them using the |
450 | configfs_add_default_group() function to the parent config_group | |
451 | structure. Each added group is populated in the configfs tree at the same | |
7063fbf2 JB |
452 | time as the parent group. Similarly, they are removed at the same time |
453 | as the parent. No extra notification is provided. When a ->drop_item() | |
454 | method call notifies the subsystem the parent group is going away, it | |
455 | also means every default group child associated with that parent group. | |
456 | ||
1ae1602d | 457 | As a consequence of this, default groups cannot be removed directly via |
7063fbf2 JB |
458 | rmdir(2). They also are not considered when rmdir(2) on the parent |
459 | group is checking for children. | |
460 | ||
98264991 MCC |
461 | Dependent Subsystems |
462 | ==================== | |
631d1feb JB |
463 | |
464 | Sometimes other drivers depend on particular configfs items. For | |
465 | example, ocfs2 mounts depend on a heartbeat region item. If that | |
466 | region item is removed with rmdir(2), the ocfs2 mount must BUG or go | |
467 | readonly. Not happy. | |
468 | ||
469 | configfs provides two additional API calls: configfs_depend_item() and | |
470 | configfs_undepend_item(). A client driver can call | |
471 | configfs_depend_item() on an existing item to tell configfs that it is | |
472 | depended on. configfs will then return -EBUSY from rmdir(2) for that | |
473 | item. When the item is no longer depended on, the client driver calls | |
474 | configfs_undepend_item() on it. | |
475 | ||
476 | These API cannot be called underneath any configfs callbacks, as | |
477 | they will conflict. They can block and allocate. A client driver | |
478 | probably shouldn't calling them of its own gumption. Rather it should | |
479 | be providing an API that external subsystems call. | |
480 | ||
481 | How does this work? Imagine the ocfs2 mount process. When it mounts, | |
482 | it asks for a heartbeat region item. This is done via a call into the | |
483 | heartbeat code. Inside the heartbeat code, the region item is looked | |
484 | up. Here, the heartbeat code calls configfs_depend_item(). If it | |
485 | succeeds, then heartbeat knows the region is safe to give to ocfs2. | |
486 | If it fails, it was being torn down anyway, and heartbeat can gracefully | |
487 | pass up an error. |