doc: add shadow variable example to patch author guide

Add shadow variable examples and text.
This commit is contained in:
Joe Lawrence 2017-03-14 16:43:44 -04:00
parent d7aae34a0d
commit d90b9afbd9

View File

@ -149,9 +149,63 @@ to prevent patch B from writing to X, if A is already loaded.
### Use a shadow variable
If you need to add a field to an existing data structure, or even many existing
data structures, you can use the `kpatch_shadow_*()` functions.
data structures, you can use the `kpatch_shadow_*()` functions:
Example needed (see shadow-newpid.patch in the integration tests directory).
* `kpatch_shadow_alloc` - allocates a new shadow variable associated with a
given object.
* `kpatch_shadow_get` - find and return a pointer to a shadow variable
* `kpatch_shadow_free` - find and free a shadow variable
Example: The `shadow-newpid.patch` integration test demonstrates the usage of
these functions.
A shadow PID variable is allocated in `do_fork()` : it is associated with the
current `struct task_struct *p` value, given a string lookup key of "newpid",
sized accordingly, and allocated as per `GFP_KERNEL` flag rules.
`kpatch_shadow_alloc` returns a pointer to the shadow variable, so we can
dereference and make assignments as usual. In this patch chunk, the shadow
`newpid` is allocated then assigned to a rolling `ctr` counter value:
```
+ int *newpid;
+ static int ctr = 0;
+
+ newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid),
+ GFP_KERNEL);
+ if (newpid)
+ *newpid = ctr++;
```
A shadow variable may also be accessed via `kpatch_shadow_get`. Here the
patch modifies `task_context_switch_counts()` to fetch the shadow variable
associated with the current `struct task_struct *p` object and a "newpid" tag.
As in the previous patch chunk, the shadow variable pointer may be accessed
as an ordinary pointer type:
```
+ int *newpid;
+
seq_put_decimal_ull(m, "voluntary_ctxt_switches:\t", p->nvcsw);
seq_put_decimal_ull(m, "\nnonvoluntary_ctxt_switches:\t", p->nivcsw);
seq_putc(m, '\n');
+
+ newpid = kpatch_shadow_get(p, "newpid");
+ if (newpid)
+ seq_printf(m, "newpid:\t%d\n", *newpid);
```
A shadow variable is freed by calling `kpatch_shadow_free` and providing
the object / string key combination. Once freed, the shadow variable is not
safe to access:
```
exit_task_work(tsk);
exit_thread(tsk);
+ kpatch_shadow_free(tsk, "newpid");
+
/*
* Flush inherited counters to the parent - before the parent
* gets woken up by child-exit notifications.
```
Data semantic changes
---------------------