Split check_address_for_conflict into check_address and check_record.
[ksplice.git] / ksplice-apply.in
blobf171dfb4ac4a6c9d1fde4a5b428598d32b5a7a26
1 #!/usr/bin/perl
3 # Copyright (C) 2007-2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
4 # Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
5 # Tim Abbott <tabbott@mit.edu>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License, version 2.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
18 # 02110-1301, USA.
20 use strict;
21 use warnings;
22 use lib 'KSPLICE_DATA_DIR';
23 use Ksplice;
25 my ($help, $wantversion, $debug) = (0, 0, 0);
26 GetOptions("help|?" => \$help,
27 "version" => \$wantversion,
28 "verbose|v:+" => \$Verbose::level,
29 "debug=i" => \$debug) or pod2usage(1);
31 if($wantversion) {
32 print $version_str;
33 exit(0);
35 pod2usage(1) if($help || scalar(@ARGV) != 1);
37 my $file = abs_path($ARGV[0]);
39 my $tmpdir = tempdir('ksplice-tmp-XXXXXX', TMPDIR => 1, CLEANUP => 1);
40 chdir($tmpdir);
41 my $ksplice = unpack_update($file);
42 chdir($ksplice);
44 my $nounload = runstr("lsmod") =~ m/- $/m;
46 (my $kid = $ksplice) =~s|ksplice[-_]([^-_]+)|$1|;
47 my $update = "ksplice_$kid";
48 if(update_loaded($kid)) {
49 my $stage = get_stage($kid);
50 if ($stage eq "applied") {
51 print STDERR "Ksplice update $kid already applied.\n";
52 exit(0);
54 die "Reversed Ksplice module $update already loaded!" if ($stage eq "reversed");
57 runstr_err(qw(modprobe -q ksplice)) eq "" || die;
58 if (-e "ksplice-$kid.ko") {
59 if (runstr("lsmod") =~ m/^ksplice_$kid\s+/) {
60 die "Ksplice core module ksplice_$kid already loaded.";
62 if (!load_module("ksplice-$kid.ko", "debug=$debug")) {
63 die "Error loading Ksplice core for update $kid";
67 foreach my $helper (glob('ksplice-*-helper.ko')) {
68 (my $primary = $helper) =~ s/\-helper\.ko$/.ko/;
69 die unless(-e $primary && -e $helper);
70 (my $target = $primary) =~ s/^ksplice-[^_]+_(.*)\.ko/$1/;
71 if ($target ne 'vmlinux' && runstr("lsmod") !~ m/^${target}\s/m) {
72 cleanup_modules();
73 die "Module $target to be patched not loaded";
76 foreach my $helper (glob('ksplice-*-helper.ko')) {
77 (my $primary = $helper) =~ s/\-helper\.ko$/.ko/;
78 if(!load_module($primary)) {
79 die "Error loading primary module $primary";
81 if(!load_module($helper)) {
82 my ($debugfile, $debugout) = get_debug_output("init_$kid");
83 print STDERR "Error loading helper module $helper\n";
84 (my $module = $primary) =~ s/-/_/g;
85 $module =~ s/\.ko//;
86 cleanup_modules();
87 print $debugout;
88 print("Debugging output saved to $debugfile\n");
89 die;
93 set_debug_level($kid, $debug);
94 set_stage($kid, "applied");
95 my $stage = get_stage($kid);
96 if($stage ne 'applied') {
97 my ($debugfile, $debugout) = get_debug_output($kid);
98 my $abort_cause = get_abort_cause($kid);
99 my $conflicts = get_conflicts($kid);
100 cleanup_modules();
101 print STDERR "Error applying Ksplice update $kid:\n";
102 print $debugout;
103 print_error($abort_cause);
104 if ($abort_cause eq 'code_busy') {
105 print $conflicts;
107 print("Debugging output saved to $debugfile\n");
108 die;
110 mkpath("/var/run/ksplice/updates/$kid");
111 copy("patch", "/var/run/ksplice/updates/$kid/patch");
112 foreach my $helper (glob('ksplice-*-helper.ko')) {
113 $helper =~ s/-/_/g;
114 $helper =~ s/\.ko$//;
115 runval('rmmod', $helper) if(!$nounload);
117 print "Done!\n";
118 exit(0);
120 my @modules_loaded = qw();
122 sub load_module {
123 my ($module, @params) = @_;
124 if (runval_raw("insmod", $module, @params) != 0) {
125 child_error();
126 return 0;
128 $module =~ s/\.ko//;
129 $module =~ s/-/_/g;
130 push @modules_loaded, $module;
131 return 1;
134 sub cleanup_modules {
135 foreach my $module (reverse(@modules_loaded)) {
136 runval("rmmod", $module) if(!$nounload);
140 sub print_error {
141 my ($error) = @_;
142 my %errors = (
143 "no_match" => <<'END',
144 Ksplice has aborted the upgrade because Ksplice has been unable to match the
145 object code produced by your current compiler and assembler against the running
146 kernel's object code. If you provided the exact kernel source to the running
147 kernel, then it appears that your current compiler and/or assembler are
148 behaving differently from the compiler and assembler used to build the running
149 kernel. If possible, please use the exact compiler and assembler that were
150 used to build the running kernel. If you are using exactly the same compiler
151 and assembler, feel free to report a bug to PACKAGE_BUGREPORT.
153 "code_busy" => <<'END',
154 Ksplice has aborted the upgrade because it appears that the code that you are
155 trying to patch is continuously in use by the system. More specifically,
156 Ksplice has been unable to find a moment when one or more of the to-be-patched
157 functions is not on a thread's kernel stack.
159 "bad_system_map" => <<'END',
160 Ksplice has aborted the upgrade because it appears that the System.map file
161 provided to ksplice-create does not match the running kernel.
163 "failed_to_find" => <<'END',
164 Ksplice has aborted the upgrade because it was unable to resolve some
165 of the symbols used in the update.
167 "already_reversed" => <<'END',
168 The Ksplice update you are attempting to apply has already been
169 applied and reversed. You need to unload the Ksplice modules related
170 to this update before you can reapply this update.
172 "missing_export" => <<'END',
173 Ksplice was unable to find some of the structures needed to make the
174 adjustments to the kernel's exported symbols made by the patch.
176 "unexpected_running_task" => <<'END',
177 Ksplice has aborted the upgrade because a task was running while it
178 was attempting to check that the code changed by the update was not
179 busy.
181 "out_of_memory" => <<'END',
182 Ksplice has aborted the upgrade because the kernel ran out of memory.
184 "unexpected" => <<'END',
185 Ksplice has aborted because of an unexpected error.
187 "UNKNOWN" => <<'END',
188 The Ksplice kernel interface has returned an error string that
189 ksplice-apply does not understand. This is probably the result of
190 using a version of ksplice-apply that is older than the version of the
191 Ksplice kernel module source.
193 "ok" => <<'END',
194 Ksplice has aborted the upgrade for unknown reasons.
197 $error = "UNKNOWN" if (!exists $errors{$error});
198 print STDERR "\n$errors{$error}\n";
201 =head1 NAME
203 ksplice-apply - Apply an on-disk Ksplice update to the running kernel
205 =head1 SYNOPSIS
207 B<ksplice-apply> I<UPDATE_TARBALL>
209 =head1 DESCRIPTION
211 B<ksplice-apply> takes as input a Ksplice update tarball, as generated by
212 L<ksplice-create(8)>, and it applies the update to the running binary kernel.
214 Specifically, B<ksplice-apply> does the following:
216 =over
218 =item 1.
220 Inserts the "primary" module into the kernel.
222 =item 2.
224 Inserts the "helper" module into the kernel (doing so applies the
225 update).
227 =item 3.
229 Removes the "helper" module from the kernel (that module is not needed
230 after the update has been applied).
232 =back
234 The update tarball used with B<ksplice-apply> must have been generated for the
235 running kernel's version.
237 =head1 OPTIONS
239 =over 8
241 =item B<--debug=>I<DEBUG_LEVEL>
243 Applies the update with debugging output enabled. Recommended only for
244 debugging. I<DEBUG_LEVEL> should be an integer between 0 and 4. B<--debug=4>
245 provides the most debugging information.
247 =over
249 =item Z<> B<0>
251 No debugging output.
253 =item Z<> B<1>
255 Provides basic (pre-run matching and kernel stack check) debugging output.
257 =item Z<> B<2>
259 Also provides full kernel stack check debugging output.
261 =item Z<> B<3>
263 Also provides full pre-run matching debugging output.
265 =item Z<> B<4>
267 Also provides full Ksplice relocation debugging output.
269 =back
271 =back
273 =head1 SEE ALSO
275 L<ksplice-create(8)>, L<ksplice-view(8)>, L<ksplice-undo(8)>
277 =head1 COPYRIGHT
279 Copyright (C) 2007-2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
280 Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
281 Tim Abbott <tabbott@mit.edu>
283 This is free software and documentation. You can redistribute and/or modify it
284 under the terms of the GNU General Public License, version 2.
286 =cut