€•ÙJŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ0/translations/zh_CN/livepatch/cumulative-patches”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/zh_TW/livepatch/cumulative-patches”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/it_IT/livepatch/cumulative-patches”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/ja_JP/livepatch/cumulative-patches”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/ko_KR/livepatch/cumulative-patches”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/pt_BR/livepatch/cumulative-patches”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/sp_SP/livepatch/cumulative-patches”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒ#Atomic Replace & Cumulative Patches”h]”hŒ#Atomic Replace & Cumulative Patches”…””}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒJ/var/lib/git/docbuild/linux/Documentation/livepatch/cumulative-patches.rst”h´KubhŒ paragraph”“”)”}”(hXThere might be dependencies between livepatches. If multiple patches need to do different changes to the same function(s) then we need to define an order in which the patches will be installed. And function implementations from any newer livepatch must be done on top of the older ones.”h]”hXThere might be dependencies between livepatches. If multiple patches need to do different changes to the same function(s) then we need to define an order in which the patches will be installed. And function implementations from any newer livepatch must be done on top of the older ones.”…””}”(hhÍh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh·h²hubhÌ)”}”(hŒuThis might become a maintenance nightmare. Especially when more patches modified the same function in different ways.”h]”hŒuThis might become a maintenance nightmare. Especially when more patches modified the same function in different ways.”…””}”(hhÛh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hh·h²hubhÌ)”}”(hŒãAn elegant solution comes with the feature called "Atomic Replace". It allows creation of so called "Cumulative Patches". They include all wanted changes from all older livepatches and completely replace them in one transition.”h]”hŒëAn elegant solution comes with the feature called “Atomic Replaceâ€. It allows creation of so called “Cumulative Patchesâ€. They include all wanted changes from all older livepatches and completely replace them in one transition.”…””}”(hhéh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K hh·h²hubh¶)”}”(hhh]”(h»)”}”(hŒUsage”h]”hŒUsage”…””}”(hhúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh÷h²hh³hÊh´KubhÌ)”}”(hŒ^The atomic replace can be enabled by setting "replace" flag in struct klp_patch, for example::”h]”hŒaThe atomic replace can be enabled by setting “replace†flag in struct klp_patch, for example:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh÷h²hubhŒ literal_block”“”)”}”(hŒostatic struct klp_patch patch = { .mod = THIS_MODULE, .objs = objs, .replace = true, };”h]”hŒostatic struct klp_patch patch = { .mod = THIS_MODULE, .objs = objs, .replace = true, };”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jh³hÊh´Khh÷h²hubhÌ)”}”(hŒ—All processes are then migrated to use the code only from the new patch. Once the transition is finished, all older patches are automatically disabled.”h]”hŒ—All processes are then migrated to use the code only from the new patch. Once the transition is finished, all older patches are automatically disabled.”…””}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´Khh÷h²hubhÌ)”}”(hŒqFtrace handlers are transparently removed from functions that are no longer modified by the new cumulative patch.”h]”hŒqFtrace handlers are transparently removed from functions that are no longer modified by the new cumulative patch.”…””}”(hj6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K!hh÷h²hubhÌ)”}”(hŒ²As a result, the livepatch authors might maintain sources only for one cumulative patch. It helps to keep the patch consistent while adding or removing various fixes or features.”h]”hŒ²As a result, the livepatch authors might maintain sources only for one cumulative patch. It helps to keep the patch consistent while adding or removing various fixes or features.”…””}”(hjDh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K$hh÷h²hubhÌ)”}”(hXSUsers could keep only the last patch installed on the system after the transition to has finished. It helps to clearly see what code is actually in use. Also the livepatch might then be seen as a "normal" module that modifies the kernel behavior. The only difference is that it can be updated at runtime without breaking its functionality.”h]”hXWUsers could keep only the last patch installed on the system after the transition to has finished. It helps to clearly see what code is actually in use. Also the livepatch might then be seen as a “normal†module that modifies the kernel behavior. The only difference is that it can be updated at runtime without breaking its functionality.”…””}”(hjRh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K(hh÷h²hubeh}”(h]”Œusage”ah ]”h"]”Œusage”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒFeatures”h]”hŒFeatures”…””}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjhh²hh³hÊh´K0ubhÌ)”}”(hŒThe atomic replace allows:”h]”hŒThe atomic replace allows:”…””}”(hjyh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K2hjhh²hubhŒ block_quote”“”)”}”(hX - Atomically revert some functions in a previous patch while upgrading other functions. - Remove eventual performance impact caused by core redirection for functions that are no longer patched. - Decrease user confusion about dependencies between livepatches. ”h]”hŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒVAtomically revert some functions in a previous patch while upgrading other functions. ”h]”hÌ)”}”(hŒUAtomically revert some functions in a previous patch while upgrading other functions.”h]”hŒUAtomically revert some functions in a previous patch while upgrading other functions.”…””}”(hj˜h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K4hj”ubah}”(h]”h ]”h"]”h$]”h&]”uh1j’hjubj“)”}”(hŒhRemove eventual performance impact caused by core redirection for functions that are no longer patched. ”h]”hÌ)”}”(hŒgRemove eventual performance impact caused by core redirection for functions that are no longer patched.”h]”hŒgRemove eventual performance impact caused by core redirection for functions that are no longer patched.”…””}”(hj°h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K7hj¬ubah}”(h]”h ]”h"]”h$]”h&]”uh1j’hjubj“)”}”(hŒADecrease user confusion about dependencies between livepatches. ”h]”hÌ)”}”(hŒ?Decrease user confusion about dependencies between livepatches.”h]”hŒ?Decrease user confusion about dependencies between livepatches.”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K:hjÄubah}”(h]”h ]”h"]”h$]”h&]”uh1j’hjubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1jh³hÊh´K4hj‰ubah}”(h]”h ]”h"]”h$]”h&]”uh1j‡h³hÊh´K4hjhh²hubeh}”(h]”Œfeatures”ah ]”h"]”Œfeatures”ah$]”h&]”uh1hµhh·h²hh³hÊh´K0ubh¶)”}”(hhh]”(h»)”}”(hŒ Limitations:”h]”hŒ Limitations:”…””}”(hjõh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjòh²hh³hÊh´K>ubjˆ)”}”(hXý- Once the operation finishes, there is no straightforward way to reverse it and restore the replaced patches atomically. A good practice is to set .replace flag in any released livepatch. Then re-adding an older livepatch is equivalent to downgrading to that patch. This is safe as long as the livepatches do _not_ do extra modifications in (un)patching callbacks or in the module_init() or module_exit() functions, see below. Also note that the replaced patch can be removed and loaded again only when the transition was not forced. - Only the (un)patching callbacks from the _new_ cumulative livepatch are executed. Any callbacks from the replaced patches are ignored. In other words, the cumulative patch is responsible for doing any actions that are necessary to properly replace any older patch. As a result, it might be dangerous to replace newer cumulative patches by older ones. The old livepatches might not provide the necessary callbacks. This might be seen as a limitation in some scenarios. But it makes life easier in many others. Only the new cumulative livepatch knows what fixes/features are added/removed and what special actions are necessary for a smooth transition. In any case, it would be a nightmare to think about the order of the various callbacks and their interactions if the callbacks from all enabled patches were called. - There is no special handling of shadow variables. Livepatch authors must create their own rules how to pass them from one cumulative patch to the other. Especially that they should not blindly remove them in module_exit() functions. A good practice might be to remove shadow variables in the post-unpatch callback. It is called only when the livepatch is properly disabled.”h]”jŽ)”}”(hhh]”(j“)”}”(hXOnce the operation finishes, there is no straightforward way to reverse it and restore the replaced patches atomically. A good practice is to set .replace flag in any released livepatch. Then re-adding an older livepatch is equivalent to downgrading to that patch. This is safe as long as the livepatches do _not_ do extra modifications in (un)patching callbacks or in the module_init() or module_exit() functions, see below. Also note that the replaced patch can be removed and loaded again only when the transition was not forced. ”h]”(hÌ)”}”(hŒwOnce the operation finishes, there is no straightforward way to reverse it and restore the replaced patches atomically.”h]”hŒwOnce the operation finishes, there is no straightforward way to reverse it and restore the replaced patches atomically.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K@hj ubhÌ)”}”(hX1A good practice is to set .replace flag in any released livepatch. Then re-adding an older livepatch is equivalent to downgrading to that patch. This is safe as long as the livepatches do _not_ do extra modifications in (un)patching callbacks or in the module_init() or module_exit() functions, see below.”h]”hX1A good practice is to set .replace flag in any released livepatch. Then re-adding an older livepatch is equivalent to downgrading to that patch. This is safe as long as the livepatches do _not_ do extra modifications in (un)patching callbacks or in the module_init() or module_exit() functions, see below.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KChj ubhÌ)”}”(hŒjAlso note that the replaced patch can be removed and loaded again only when the transition was not forced.”h]”hŒjAlso note that the replaced patch can be removed and loaded again only when the transition was not forced.”…””}”(hj*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KIhj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j’hjubj“)”}”(hX5Only the (un)patching callbacks from the _new_ cumulative livepatch are executed. Any callbacks from the replaced patches are ignored. In other words, the cumulative patch is responsible for doing any actions that are necessary to properly replace any older patch. As a result, it might be dangerous to replace newer cumulative patches by older ones. The old livepatches might not provide the necessary callbacks. This might be seen as a limitation in some scenarios. But it makes life easier in many others. Only the new cumulative livepatch knows what fixes/features are added/removed and what special actions are necessary for a smooth transition. In any case, it would be a nightmare to think about the order of the various callbacks and their interactions if the callbacks from all enabled patches were called. ”h]”(hÌ)”}”(hŒ†Only the (un)patching callbacks from the _new_ cumulative livepatch are executed. Any callbacks from the replaced patches are ignored.”h]”hŒ†Only the (un)patching callbacks from the _new_ cumulative livepatch are executed. Any callbacks from the replaced patches are ignored.”…””}”(hjBh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KMhj>ubhÌ)”}”(hŒIn other words, the cumulative patch is responsible for doing any actions that are necessary to properly replace any older patch.”h]”hŒIn other words, the cumulative patch is responsible for doing any actions that are necessary to properly replace any older patch.”…””}”(hjPh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KPhj>ubhÌ)”}”(hŒ”As a result, it might be dangerous to replace newer cumulative patches by older ones. The old livepatches might not provide the necessary callbacks.”h]”hŒ”As a result, it might be dangerous to replace newer cumulative patches by older ones. The old livepatches might not provide the necessary callbacks.”…””}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KShj>ubhÌ)”}”(hŒìThis might be seen as a limitation in some scenarios. But it makes life easier in many others. Only the new cumulative livepatch knows what fixes/features are added/removed and what special actions are necessary for a smooth transition.”h]”hŒìThis might be seen as a limitation in some scenarios. But it makes life easier in many others. Only the new cumulative livepatch knows what fixes/features are added/removed and what special actions are necessary for a smooth transition.”…””}”(hjlh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KVhj>ubhÌ)”}”(hŒ¤In any case, it would be a nightmare to think about the order of the various callbacks and their interactions if the callbacks from all enabled patches were called.”h]”hŒ¤In any case, it would be a nightmare to think about the order of the various callbacks and their interactions if the callbacks from all enabled patches were called.”…””}”(hjzh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K[hj>ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j’hjubj“)”}”(hXvThere is no special handling of shadow variables. Livepatch authors must create their own rules how to pass them from one cumulative patch to the other. Especially that they should not blindly remove them in module_exit() functions. A good practice might be to remove shadow variables in the post-unpatch callback. It is called only when the livepatch is properly disabled.”h]”(hÌ)”}”(hŒèThere is no special handling of shadow variables. Livepatch authors must create their own rules how to pass them from one cumulative patch to the other. Especially that they should not blindly remove them in module_exit() functions.”h]”hŒèThere is no special handling of shadow variables. Livepatch authors must create their own rules how to pass them from one cumulative patch to the other. Especially that they should not blindly remove them in module_exit() functions.”…””}”(hj’h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´K`hjŽubhÌ)”}”(hŒŒA good practice might be to remove shadow variables in the post-unpatch callback. It is called only when the livepatch is properly disabled.”h]”hŒŒA good practice might be to remove shadow variables in the post-unpatch callback. It is called only when the livepatch is properly disabled.”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hËh³hÊh´KehjŽubeh}”(h]”h ]”h"]”h$]”h&]”uh1j’hjubeh}”(h]”h ]”h"]”h$]”h&]”jâjãuh1jh³hÊh´K@hjubah}”(h]”h ]”h"]”h$]”h&]”uh1j‡h³hÊh´K@hjòh²hubeh}”(h]”Œ limitations”ah ]”h"]”Œ limitations:”ah$]”h&]”uh1hµhh·h²hh³hÊh´K>ubeh}”(h]”Œ!atomic-replace-cumulative-patches”ah ]”h"]”Œ#atomic replace & cumulative patches”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jóŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(jÍjÊjejbjïjìjÅjÂuŒ nametypes”}”(j͉je‰jï‰jʼnuh}”(jÊh·jbh÷jìjhjÂjòuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.