dynup/kpatch — pull request #360 by flaming-toast (2014-08-13 16:13:21+00:00)
Title: kpatch-patch-hook: fix incorrect old_offsets for loadable modules

This PR attempts to fix issue #356.

To summarize the changeset:
1) A sysfs hook will be created if the module is not loaded by the time the patch module is loaded. This hook will be called by `kpatch_module_notify`.

sysfs file creation was taken out of `patch_make_funcs_list` and put into a separate function named `patch_create_func_sysfs`. `kpmod.add_sysfs_func` will be set to point to this function if we need to delay sysfs initialization. I feel like this is a bit hacky, but I used a hook because I wanted to preserve existing scope boundaries as much as possible, without porting any of the local structs and functions used solely in kpatch-patch-hook during sysfs initialization (for example, `kpatch_func_object` used in kobject creation is local to kpatch-patch-hook only, and we wouldn't have access to that in the core module if we wanted to create the sysfs files then and there.)

2) `kpatch_func_obj`, the struct that contains the kobject and is local only to patch module, is set to point to the `kpatch_func` struct instead of the `kpatch_patch_func` struct (which is local to the patch module). I did this so that the core module could call the sysfs hook and pass to it a `kpatch_func` struct, as it does *not* have access to the `kpatch_patch_func` struct. (`kpatch_func` and `kpatch_patch_func` both contain the same information, so I think this change should be safe)

3) Lastly, if the module is already loaded, `patch_make_funcs_list` will now resolve old_addr using `kpatch_find_module_symbol`. I had to export it to make it available to the patch module...

Tested on Ubuntu 14.04 and Arch with the ext4 patch in #356 and the btrfs patch below (both compiled as modules). `old_addr` and `new_addr` were verified by cross-checking with `/proc/kallsyms`.
```
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 7869936..890f8f9 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -92,6 +92,7 @@ static int can_modify_feature(struct btrfs_feature_attr *fa)
static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
struct kobj_attribute *a, char *buf)
{
+ pr_info("btrfs_feature_attr_show");
int val = 0;
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
```

If anyone thinks I should take a different approach, I'm all ears.This is an initial version of the fix and I suspect there are mistakes and better ways of solving this issue, so feedback is more than welcome.