.sysfs_ops = &kobj_sysfs_ops,
 };
 
-static void klp_free_funcs(struct klp_object *obj)
+static void __klp_free_funcs(struct klp_object *obj, bool nops_only)
 {
        struct klp_func *func, *tmp_func;
 
        klp_for_each_func_safe(obj, func, tmp_func) {
+               if (nops_only && !func->nop)
+                       continue;
+
+               list_del(&func->node);
+
                /* Might be called from klp_init_patch() error path. */
                if (func->kobj_added) {
                        kobject_put(&func->kobj);
        }
 }
 
-static void klp_free_objects(struct klp_patch *patch)
+static void __klp_free_objects(struct klp_patch *patch, bool nops_only)
 {
        struct klp_object *obj, *tmp_obj;
 
        klp_for_each_object_safe(patch, obj, tmp_obj) {
-               klp_free_funcs(obj);
+               __klp_free_funcs(obj, nops_only);
+
+               if (nops_only && !obj->dynamic)
+                       continue;
+
+               list_del(&obj->node);
 
                /* Might be called from klp_init_patch() error path. */
                if (obj->kobj_added) {
        }
 }
 
+static void klp_free_objects(struct klp_patch *patch)
+{
+       __klp_free_objects(patch, false);
+}
+
+static void klp_free_objects_dynamic(struct klp_patch *patch)
+{
+       __klp_free_objects(patch, true);
+}
+
 /*
  * This function implements the free operations that can be called safely
  * under klp_mutex.
        }
 }
 
+/*
+ * This function removes the dynamically allocated 'nop' functions.
+ *
+ * We could be pretty aggressive. NOPs do not change the existing
+ * behavior except for adding unnecessary delay by the ftrace handler.
+ *
+ * It is safe even when the transition was forced. The ftrace handler
+ * will see a valid ops->func_stack entry thanks to RCU.
+ *
+ * We could even free the NOPs structures. They must be the last entry
+ * in ops->func_stack. Therefore unregister_ftrace_function() is called.
+ * It does the same as klp_synchronize_transition() to make sure that
+ * nobody is inside the ftrace handler once the operation finishes.
+ *
+ * IMPORTANT: It must be called right after removing the replaced patches!
+ */
+void klp_discard_nops(struct klp_patch *new_patch)
+{
+       klp_unpatch_objects_dynamic(klp_transition_patch);
+       klp_free_objects_dynamic(klp_transition_patch);
+}
+
 /*
  * Remove parts of patches that touch a given kernel module. The list of
  * patches processed might be limited. When limit is NULL, all patches
 
        return ret;
 }
 
-void klp_unpatch_object(struct klp_object *obj)
+static void __klp_unpatch_object(struct klp_object *obj, bool nops_only)
 {
        struct klp_func *func;
 
-       klp_for_each_func(obj, func)
+       klp_for_each_func(obj, func) {
+               if (nops_only && !func->nop)
+                       continue;
+
                if (func->patched)
                        klp_unpatch_func(func);
+       }
 
-       obj->patched = false;
+       if (obj->dynamic || !nops_only)
+               obj->patched = false;
+}
+
+
+void klp_unpatch_object(struct klp_object *obj)
+{
+       __klp_unpatch_object(obj, false);
 }
 
 int klp_patch_object(struct klp_object *obj)
        return 0;
 }
 
-void klp_unpatch_objects(struct klp_patch *patch)
+static void __klp_unpatch_objects(struct klp_patch *patch, bool nops_only)
 {
        struct klp_object *obj;
 
        klp_for_each_object(patch, obj)
                if (obj->patched)
-                       klp_unpatch_object(obj);
+                       __klp_unpatch_object(obj, nops_only);
+}
+
+void klp_unpatch_objects(struct klp_patch *patch)
+{
+       __klp_unpatch_objects(patch, false);
+}
+
+void klp_unpatch_objects_dynamic(struct klp_patch *patch)
+{
+       __klp_unpatch_objects(patch, true);
 }