Skip to content

Commit d5934e7

Browse files
djbwPeter Zijlstra
authored andcommitted
cleanup: Add usage and style documentation
When proposing that PCI grow some new cleanup helpers for pci_dev_put() and pci_dev_{lock,unlock} [1], Bjorn had some fundamental questions about expectations and best practices. Upon reviewing an updated changelog with those details he recommended adding them to documentation in the header file itself. Add that documentation and link it into the rendering for Documentation/core-api/. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/171175585714.2192972.12661675876300167762.stgit@dwillia2-xfh.jf.intel.com
1 parent 7886a61 commit d5934e7

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

Documentation/core-api/cleanup.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
===========================
4+
Scope-based Cleanup Helpers
5+
===========================
6+
7+
.. kernel-doc:: include/linux/cleanup.h
8+
:doc: scope-based cleanup helpers

Documentation/core-api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Library functionality that is used throughout the kernel.
3535

3636
kobject
3737
kref
38+
cleanup
3839
assoc_array
3940
xarray
4041
maple_tree

include/linux/cleanup.h

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,142 @@
44

55
#include <linux/compiler.h>
66

7+
/**
8+
* DOC: scope-based cleanup helpers
9+
*
10+
* The "goto error" pattern is notorious for introducing subtle resource
11+
* leaks. It is tedious and error prone to add new resource acquisition
12+
* constraints into code paths that already have several unwind
13+
* conditions. The "cleanup" helpers enable the compiler to help with
14+
* this tedium and can aid in maintaining LIFO (last in first out)
15+
* unwind ordering to avoid unintentional leaks.
16+
*
17+
* As drivers make up the majority of the kernel code base, here is an
18+
* example of using these helpers to clean up PCI drivers. The target of
19+
* the cleanups are occasions where a goto is used to unwind a device
20+
* reference (pci_dev_put()), or unlock the device (pci_dev_unlock())
21+
* before returning.
22+
*
23+
* The DEFINE_FREE() macro can arrange for PCI device references to be
24+
* dropped when the associated variable goes out of scope::
25+
*
26+
* DEFINE_FREE(pci_dev_put, struct pci_dev *, if (_T) pci_dev_put(_T))
27+
* ...
28+
* struct pci_dev *dev __free(pci_dev_put) =
29+
* pci_get_slot(parent, PCI_DEVFN(0, 0));
30+
*
31+
* The above will automatically call pci_dev_put() if @dev is non-NULL
32+
* when @dev goes out of scope (automatic variable scope). If a function
33+
* wants to invoke pci_dev_put() on error, but return @dev (i.e. without
34+
* freeing it) on success, it can do::
35+
*
36+
* return no_free_ptr(dev);
37+
*
38+
* ...or::
39+
*
40+
* return_ptr(dev);
41+
*
42+
* The DEFINE_GUARD() macro can arrange for the PCI device lock to be
43+
* dropped when the scope where guard() is invoked ends::
44+
*
45+
* DEFINE_GUARD(pci_dev, struct pci_dev *, pci_dev_lock(_T), pci_dev_unlock(_T))
46+
* ...
47+
* guard(pci_dev)(dev);
48+
*
49+
* The lifetime of the lock obtained by the guard() helper follows the
50+
* scope of automatic variable declaration. Take the following example::
51+
*
52+
* func(...)
53+
* {
54+
* if (...) {
55+
* ...
56+
* guard(pci_dev)(dev); // pci_dev_lock() invoked here
57+
* ...
58+
* } // <- implied pci_dev_unlock() triggered here
59+
* }
60+
*
61+
* Observe the lock is held for the remainder of the "if ()" block not
62+
* the remainder of "func()".
63+
*
64+
* Now, when a function uses both __free() and guard(), or multiple
65+
* instances of __free(), the LIFO order of variable definition order
66+
* matters. GCC documentation says:
67+
*
68+
* "When multiple variables in the same scope have cleanup attributes,
69+
* at exit from the scope their associated cleanup functions are run in
70+
* reverse order of definition (last defined, first cleanup)."
71+
*
72+
* When the unwind order matters it requires that variables be defined
73+
* mid-function scope rather than at the top of the file. Take the
74+
* following example and notice the bug highlighted by "!!"::
75+
*
76+
* LIST_HEAD(list);
77+
* DEFINE_MUTEX(lock);
78+
*
79+
* struct object {
80+
* struct list_head node;
81+
* };
82+
*
83+
* static struct object *alloc_add(void)
84+
* {
85+
* struct object *obj;
86+
*
87+
* lockdep_assert_held(&lock);
88+
* obj = kzalloc(sizeof(*obj), GFP_KERNEL);
89+
* if (obj) {
90+
* LIST_HEAD_INIT(&obj->node);
91+
* list_add(obj->node, &list):
92+
* }
93+
* return obj;
94+
* }
95+
*
96+
* static void remove_free(struct object *obj)
97+
* {
98+
* lockdep_assert_held(&lock);
99+
* list_del(&obj->node);
100+
* kfree(obj);
101+
* }
102+
*
103+
* DEFINE_FREE(remove_free, struct object *, if (_T) remove_free(_T))
104+
* static int init(void)
105+
* {
106+
* struct object *obj __free(remove_free) = NULL;
107+
* int err;
108+
*
109+
* guard(mutex)(&lock);
110+
* obj = alloc_add();
111+
*
112+
* if (!obj)
113+
* return -ENOMEM;
114+
*
115+
* err = other_init(obj);
116+
* if (err)
117+
* return err; // remove_free() called without the lock!!
118+
*
119+
* no_free_ptr(obj);
120+
* return 0;
121+
* }
122+
*
123+
* That bug is fixed by changing init() to call guard() and define +
124+
* initialize @obj in this order::
125+
*
126+
* guard(mutex)(&lock);
127+
* struct object *obj __free(remove_free) = alloc_add();
128+
*
129+
* Given that the "__free(...) = NULL" pattern for variables defined at
130+
* the top of the function poses this potential interdependency problem
131+
* the recommendation is to always define and assign variables in one
132+
* statement and not group variable definitions at the top of the
133+
* function when __free() is used.
134+
*
135+
* Lastly, given that the benefit of cleanup helpers is removal of
136+
* "goto", and that the "goto" statement can jump between scopes, the
137+
* expectation is that usage of "goto" and cleanup helpers is never
138+
* mixed in the same function. I.e. for a given routine, convert all
139+
* resources that need a "goto" cleanup to scope-based cleanup, or
140+
* convert none of them.
141+
*/
142+
7143
/*
8144
* DEFINE_FREE(name, type, free):
9145
* simple helper macro that defines the required wrapper for a __free()

0 commit comments

Comments
 (0)