Make find_nameval strip .text. from both names.
[ksplice.git] / ksplice-apply.in
blob6a11ebc4f41ebb5a8f126dbbcd4acf59b453ef25
1 #!/usr/bin/perl
3 # Copyright (C) 2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License, version 2.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
16 # 02110-1301, USA.
18 use strict;
19 use warnings;
20 use lib 'KSPLICE_DATA_DIR';
21 use Ksplice;
23 my ($help, $wantversion, $debug) = (0, 0, 0);
24 GetOptions("help|?" => \$help,
25 "version" => \$wantversion,
26 "verbose|v:+" => \$Verbose::level,
27 "debug=i" => \$debug) or pod2usage(1);
29 if($wantversion) {
30 print $version_str;
31 exit(0);
33 pod2usage(1) if($help || scalar(@ARGV) != 1);
35 my $file = abs_path($ARGV[0]);
37 my $tmpdir = tempdir('ksplice-tmp-XXXXXX', TMPDIR => 1, CLEANUP => 1);
38 chdir($tmpdir);
39 my $ksplice = unpack_update($file);
40 chdir($ksplice);
42 my $nounload = runstr("lsmod") =~ m/- $/m;
44 (my $kid = $ksplice) =~s|ksplice[-_]([^-_]+)|$1|;
45 my $update = "ksplice_$kid";
46 if(update_loaded($kid)) {
47 my $stage = get_stage($kid);
48 if ($stage eq "applied") {
49 print STDERR "Ksplice update $kid already applied.\n";
50 exit(0);
52 die "Reversed Ksplice module $update already loaded!" if ($stage eq "reversed");
55 if (-e "ksplice-$kid.ko") {
56 if (runstr("lsmod") =~ m/^ksplice_$kid\s+/) {
57 die "Ksplice core module ksplice_$kid already loaded.";
59 if (!load_module("ksplice-$kid.ko", "debug=$debug")) {
60 die "Error loading Ksplice core for update $kid";
63 else {
64 runstr_err(qw(modprobe -q ksplice)) eq "" || die;
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 die "Module $target to be patched not loaded";
75 foreach my $helper (glob('ksplice-*-helper.ko')) {
76 (my $primary = $helper) =~ s/\-helper\.ko$/.ko/;
77 if(!load_module($primary)) {
78 die "Error loading primary module $primary";
80 if(!load_module($helper)) {
81 my ($debugfile, $debugout) = get_debug_output("init_$kid");
82 print STDERR "Error loading helper module $helper\n";
83 (my $module = $primary) =~ s/-/_/g;
84 $module =~ s/\.ko//;
85 cleanup_modules();
86 print $debugout;
87 print("Debugging output saved to $debugfile\n");
88 die;
92 set_debug_level($kid, $debug);
93 set_stage($kid, "applied");
94 my $stage = get_stage($kid);
95 if($stage ne 'applied') {
96 my ($debugfile, $debugout) = get_debug_output($kid);
97 my $abort_cause = get_abort_cause($kid);
98 cleanup_modules();
99 print STDERR "Error applying Ksplice update $kid:\n";
100 print $debugout;
101 print_error($abort_cause);
102 print("Debugging output saved to $debugfile\n");
103 die;
105 mkpath("/var/run/ksplice/updates/$kid");
106 copy("patch", "/var/run/ksplice/updates/$kid/patch");
107 foreach my $helper (glob('ksplice-*-helper.ko')) {
108 $helper =~ s/-/_/g;
109 $helper =~ s/\.ko$//;
110 die if (!$nounload && runval_raw("rmmod $helper") != 0);
112 print "Done!\n";
113 exit(0);
115 my @modules_loaded = qw();
117 sub load_module {
118 my ($module, @params) = @_;
119 if (runval_raw("insmod", $module, @params) != 0) {
120 return 0;
122 $module =~ s/\.ko//;
123 $module =~ s/-/_/g;
124 push @modules_loaded, $module;
125 return 1;
128 sub cleanup_modules {
129 foreach my $module (reverse(@modules_loaded)) {
130 die if (!$nounload && runval_raw("rmmod", $module) != 0);
134 sub print_error {
135 my ($error) = @_;
136 my %errors = (
137 "no_match" => <<'END',
138 Ksplice has aborted the upgrade because Ksplice has been unable to match the
139 object code produced by your current compiler and assembler against the running
140 kernel's object code. If you provided the exact kernel source to the running
141 kernel, then it appears that your current compiler and/or assembler are
142 behaving differently from the compiler and assembler used to build the running
143 kernel. If possible, please use the exact compiler and assembler that were
144 used to build the running kernel. If you are using exactly the same compiler
145 and assembler, feel free to report a bug to PACKAGE_BUGREPORT.
147 "code_busy" => <<'END',
148 Ksplice has aborted the upgrade because it appears that the code that you are
149 trying to patch is continuously in use by the system. More specifically,
150 Ksplice has been unable to find a moment when one or more of the to-be-patched
151 functions is not on a thread's kernel stack.
153 "bad_system_map" => <<'END',
154 Ksplice has aborted the upgrade because it appears that the System.map file
155 provided to ksplice-create does not match the running kernel.
157 "failed_to_find" => <<'END',
158 Ksplice has aborted the upgrade because it was unable to resolve some
159 of the symbols used in the update.
161 "already_reversed" => <<'END',
162 The Ksplice update you are attempting to apply has already been
163 applied and reversed. You need to unload the Ksplice modules related
164 to this update before you can reapply this update.
166 "UNKNOWN" => <<'END',
167 The Ksplice kernel interface has returned an error string that
168 ksplice-apply does not understand. This is probably the result of
169 using a version of ksplice-apply that is older than the version of the
170 Ksplice kernel module source.
172 "none" => <<'END',
173 Ksplice has aborted the upgrade for unknown reasons.
176 $error = "UNKNOWN" if (!exists $errors{$error});
177 print STDERR "\n$errors{$error}\n";
180 =head1 NAME
182 ksplice-apply - Apply an on-disk Ksplice update to the running kernel
184 =head1 SYNOPSIS
186 B<ksplice-apply> I<UPDATE_TARBALL>
188 =head1 DESCRIPTION
190 B<ksplice-apply> takes as input a Ksplice update tarball, as generated by
191 L<ksplice-create(8)>, and it applies the update to the running binary kernel.
193 Specifically, B<ksplice-apply> does the following:
195 =over
197 =item 1.
199 Inserts the "primary" module into the kernel.
201 =item 2.
203 Inserts the "helper" module into the kernel (doing so applies the
204 update).
206 =item 3.
208 Removes the "helper" module from the kernel (that module is not needed
209 after the update has been applied).
211 =back
213 The update tarball used with B<ksplice-apply> must have been generated for the
214 running kernel's version.
216 =head1 OPTIONS
218 =over 8
220 =item B<--debug=>I<DEBUG_LEVEL>
222 Applies the update with debugging output enabled. Recommended only for
223 debugging. I<DEBUG_LEVEL> should be an integer between 0 and 4. B<--debug=4>
224 provides the most debugging information.
226 =over
228 =item Z<> B<0>
230 No debugging output.
232 =item Z<> B<1>
234 Provides basic (pre-run matching and kernel stack check) debugging output.
236 =item Z<> B<2>
238 Also provides full kernel stack check debugging output.
240 =item Z<> B<3>
242 Also provides full pre-run matching debugging output.
244 =item Z<> B<4>
246 Also provides full Ksplice relocation debugging output.
248 =back
250 =back
252 =head1 SEE ALSO
254 L<ksplice-create(8)>, L<ksplice-view(8)>, L<ksplice-undo(8)>
256 =head1 COPYRIGHT
258 Copyright (C) 2008 Jeffrey Brian Arnold <jbarnold@mit.edu>.
260 This is free software and documentation. You can redistribute and/or modify it
261 under the terms of the GNU General Public License, version 2.
263 =cut