mirror of https://github.com/schoebel/mars
marsadm: fix external races on resize
This commit is contained in:
parent
8888571b2c
commit
1f2680dd62
|
@ -6045,6 +6045,88 @@ reference "sec:Scripting-HOWTO"
|
||||||
.
|
.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Subsection
|
||||||
|
Online Resizing during Operation
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Standard
|
||||||
|
You should have LVM or some other means of increasing the physical size
|
||||||
|
of your disk (e.g.
|
||||||
|
via firmware of some RAID controllers).
|
||||||
|
The network must be healthy.
|
||||||
|
Do the following steps:
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Enumerate
|
||||||
|
Increase your local disks (usually
|
||||||
|
\family typewriter
|
||||||
|
/dev/vg/mydata
|
||||||
|
\family default
|
||||||
|
)
|
||||||
|
\emph on
|
||||||
|
everywhere
|
||||||
|
\emph default
|
||||||
|
in the whole cluster.
|
||||||
|
In order to avoid wasting space, increase them
|
||||||
|
\emph on
|
||||||
|
uniformly
|
||||||
|
\emph default
|
||||||
|
to the same size (when possible).
|
||||||
|
The
|
||||||
|
\family typewriter
|
||||||
|
lvresize
|
||||||
|
\family default
|
||||||
|
tool is documented elsewhere.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Enumerate
|
||||||
|
Check that all MARS switches are on.
|
||||||
|
If not, say
|
||||||
|
\family typewriter
|
||||||
|
marsadm up mydata
|
||||||
|
\family default
|
||||||
|
everywhere.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Enumerate
|
||||||
|
At the primary:
|
||||||
|
\family typewriter
|
||||||
|
marsadm resize mydata
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Enumerate
|
||||||
|
If you have intermediate layers such as iSCSI, you may need some
|
||||||
|
\family typewriter
|
||||||
|
iscsiadm
|
||||||
|
\family default
|
||||||
|
update or other command.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Enumerate
|
||||||
|
Now you may increase your filesystem.
|
||||||
|
This is specific for the filesystem type and documented elsewhere.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Standard
|
||||||
|
\noindent
|
||||||
|
\begin_inset Graphics
|
||||||
|
filename images/lightbulb_brightlit_benj_.png
|
||||||
|
lyxscale 12
|
||||||
|
scale 7
|
||||||
|
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Hint: the secondaries will start syncing the increased new part of the underlyin
|
||||||
|
g primary disk.
|
||||||
|
In many cases, this is not really needed, because the new junk data just
|
||||||
|
does not care.
|
||||||
|
If you are sure and if you know what you are doing, you may use
|
||||||
|
\family typewriter
|
||||||
|
marsadm fake-sync mydata
|
||||||
|
\family default
|
||||||
|
to abort such unnecessary traffic.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Section
|
\begin_layout Section
|
||||||
The State of MARS
|
The State of MARS
|
||||||
\begin_inset CommandInset label
|
\begin_inset CommandInset label
|
||||||
|
@ -23328,28 +23410,37 @@ status open
|
||||||
\begin_layout Plain Layout
|
\begin_layout Plain Layout
|
||||||
|
|
||||||
\size scriptsize
|
\size scriptsize
|
||||||
Precondition: all disks in the cluster participating in
|
Precondition: The local host must be primary.
|
||||||
|
All disks in the cluster participating in
|
||||||
\family typewriter
|
\family typewriter
|
||||||
$res
|
$res
|
||||||
\family default
|
\family default
|
||||||
must be physically larger than the logical resource size (e.g.
|
must be physically larger than the logical resource size (e.g, by use of
|
||||||
by use of
|
|
||||||
\family typewriter
|
\family typewriter
|
||||||
lvm
|
lvm
|
||||||
\family default
|
\family default
|
||||||
|
; can be checked by macros
|
||||||
|
\family typewriter
|
||||||
|
%disk-size{}
|
||||||
|
\family default
|
||||||
|
and
|
||||||
|
\family typewriter
|
||||||
|
%resource-size{}
|
||||||
|
\family default
|
||||||
).
|
).
|
||||||
When the optional
|
When the optional
|
||||||
\family typewriter
|
\family typewriter
|
||||||
$size
|
$size
|
||||||
\family default
|
\family default
|
||||||
argument is present, it must be smaller than the minimum of all physical
|
argument is present, it must be smaller than the minimum of all physical
|
||||||
sizes, but larger than the current logical size.
|
sizes, but larger than the current logical size of the resource.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Plain Layout
|
\begin_layout Plain Layout
|
||||||
|
|
||||||
\size scriptsize
|
\size scriptsize
|
||||||
Postcondition: at the (future) primary (if any), the logical size of
|
Postcondition: the logical size of
|
||||||
\family typewriter
|
\family typewriter
|
||||||
/dev/mars/$dev_name
|
/dev/mars/$dev_name
|
||||||
\family default
|
\family default
|
||||||
|
|
|
@ -422,6 +422,13 @@ sub check_res {
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub _get_mars_size {
|
||||||
|
my ($cmd, $res) = @_;
|
||||||
|
my $dev_name = get_link("$mars/resource-$res/device-$host");
|
||||||
|
my $info = "/sys/devices/virtual/block/mars!$dev_name/size";
|
||||||
|
return `cat $info` * 512;
|
||||||
|
}
|
||||||
|
|
||||||
sub check_sizes {
|
sub check_sizes {
|
||||||
my ($res, $peer) = @_;
|
my ($res, $peer) = @_;
|
||||||
my $logical_size = get_link("$mars/resource-$res/size");
|
my $logical_size = get_link("$mars/resource-$res/size");
|
||||||
|
@ -2192,8 +2199,13 @@ sub invalidate_res_phase3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub resize_res {
|
my %resize_device_size;
|
||||||
|
my %resize_old_size;
|
||||||
|
my %resize_new_size;
|
||||||
|
|
||||||
|
sub resize_phase0 {
|
||||||
my ($cmd, $res, $size_arg) = @_;
|
my ($cmd, $res, $size_arg) = @_;
|
||||||
|
ldie "mars kernel module is not loaded. This is needed for communication with some other hosts!\n" if !is_module_loaded();
|
||||||
my $new_size = 0;
|
my $new_size = 0;
|
||||||
if ($size_arg) {
|
if ($size_arg) {
|
||||||
$new_size = get_size($size_arg);
|
$new_size = get_size($size_arg);
|
||||||
|
@ -2201,39 +2213,70 @@ sub resize_res {
|
||||||
lprint "new size: $new_size bytes\n";
|
lprint "new size: $new_size bytes\n";
|
||||||
}
|
}
|
||||||
check_primary(@_);
|
check_primary(@_);
|
||||||
|
my $my_size = get_link("$mars/resource-$res/actsize-$host");
|
||||||
my @actsizes = glob("$mars/resource-$res/actsize-*");
|
my @actsizes = glob("$mars/resource-$res/actsize-*");
|
||||||
ldie "resource $res has no actsize-* symlinks\n" unless @actsizes;
|
ldie "resource $res has no actsize-* symlinks\n" unless @actsizes;
|
||||||
my $lnk = "$mars/resource-$res/size";
|
my $lnk = "$mars/resource-$res/size";
|
||||||
my $old_size = get_link($lnk);
|
my $old_size = get_link($lnk);
|
||||||
my $min_size = 0;
|
my $possible_size = 0;
|
||||||
foreach my $actsize (@actsizes) {
|
foreach my $actsize (@actsizes) {
|
||||||
my $this_size = get_link($actsize);
|
my $this_size = get_link($actsize);
|
||||||
if (!$min_size || $this_size < $min_size) {
|
if (!$possible_size || $this_size < $possible_size) {
|
||||||
$min_size = $this_size;
|
$possible_size = $this_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lprint "old_size=$old_size\n";
|
lprint "old_size=$old_size\n";
|
||||||
lprint "min_size=$min_size\n";
|
lprint "possible_size=$possible_size\n";
|
||||||
$new_size = $min_size if !$new_size;
|
$new_size = $possible_size if !$new_size;
|
||||||
lprint "new_size=$new_size\n";
|
lprint "new_size=$new_size\n";
|
||||||
ldie "new size $new_size is higher than the minimum size of all volumes $min_size" if $new_size > $min_size; # no override with --force possible
|
ldie "new size $new_size is higher than the possible size (minimum of all volumes) $possible_size" if $new_size > $possible_size; # no override with --force possible
|
||||||
# for now, disallow decreasing until some bugs are fixed
|
# disallow decreasing
|
||||||
ldie "only increases of the size are possible!\n" if $new_size < $old_size;
|
ldie "only increases of the size are possible!\n" if $new_size < $old_size;
|
||||||
ldie "only increases of the size are possible without --force\n" if $new_size <= $old_size && !$force;
|
my $waste = $my_size - $new_size;
|
||||||
foreach my $switch (glob("$mars/resource-$res/todo-*/sync")) {
|
lwarn "You are wasting $waste bytes locally\n" if $my_size > $new_size;
|
||||||
my $this_switch = get_link($switch);
|
# remember values
|
||||||
ldie "sync on '$switch' is switched on -- use marsadm pause-sync to stop\n" unless !$this_switch;
|
$resize_device_size{$res} = _get_mars_size(@_);
|
||||||
}
|
$resize_old_size{$res} = $old_size;
|
||||||
my @syncsizes = glob("$mars/resource-$res/syncstatus-$host");
|
lwarn "internal mismatch between actual device size and resource size: $resize_device_size{$res} != $resize_old_size{$res}\n" unless $resize_device_size{$res} == $resize_old_size{$res};
|
||||||
foreach my $syncsize (@syncsizes) {
|
$resize_new_size{$res} = $new_size;
|
||||||
my $this_size = get_link($syncsize);
|
return 0;
|
||||||
ldie "sync on $syncsize has not yet finished: $this_size != $old_size (DANGEROUS FIX: if you know what you are doing, marsadm fake-sync can 'fix' it -- but this may need a full-sync afterwards)\n" unless $this_size == $old_size;
|
}
|
||||||
}
|
|
||||||
foreach my $syncsize (@syncsizes) {
|
sub resize_phase1 {
|
||||||
my $this_size = get_link($syncsize);
|
my ($cmd, $res) = @_;
|
||||||
set_link($new_size, $syncsize);
|
my $old_size = $resize_old_size{$res} or ldie "bad internal size value\n";
|
||||||
}
|
my $new_size = $resize_new_size{$res} or ldie "bad internal size value\n";
|
||||||
|
# for safety, check again
|
||||||
|
ldie "only increases of the size are possible!\n" if $new_size < $old_size;
|
||||||
|
check_primary(@_);
|
||||||
|
# Mark the primary data / its size as authoritative
|
||||||
|
my $act_lnk = "$mars/resource-$res/syncstatus-$host";
|
||||||
|
set_link($new_size, $act_lnk);
|
||||||
|
finish_links(); # Chance for errors to pop up
|
||||||
|
# Now set the new resource size
|
||||||
|
my $lnk = "$mars/resource-$res/size";
|
||||||
set_link($new_size, $lnk);
|
set_link($new_size, $lnk);
|
||||||
|
finish_links();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub resize_phase2 {
|
||||||
|
my ($cmd, $res) = @_;
|
||||||
|
my $old_size = $resize_old_size{$res} or ldie "bad internal size value\n";
|
||||||
|
my $new_size = $resize_new_size{$res} or ldie "bad internal size value\n";
|
||||||
|
for (;;) {
|
||||||
|
my $new_device_size = _get_mars_size(@_);
|
||||||
|
if ($new_device_size == $resize_new_size{$res}) {
|
||||||
|
lprint "Device size is now $new_device_size.\n";
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
lprint "Device size $new_device_size has not yet reached the new size $resize_new_size{$res}.\n";
|
||||||
|
if ($new_device_size != $resize_device_size{$res}) {
|
||||||
|
lwarn "The size has changed, but did not reach the correct value.";
|
||||||
|
lwarn "Assuming some rounding problems (which may occur at some device types)\n";
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
sleep_timeout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub role_cmd {
|
sub role_cmd {
|
||||||
|
@ -4561,7 +4604,12 @@ my %cmd_table =
|
||||||
"When successful, /dev/mars/\$res at the primary will be increased",
|
"When successful, /dev/mars/\$res at the primary will be increased",
|
||||||
"in size. In addition, all secondaries will start an incremental",
|
"in size. In addition, all secondaries will start an incremental",
|
||||||
"fast full-sync to get the enlarged parts from the primary.",
|
"fast full-sync to get the enlarged parts from the primary.",
|
||||||
\&resize_res,
|
\&resize_phase0,
|
||||||
|
"check preconditions",
|
||||||
|
\&resize_phase1,
|
||||||
|
"set new size",
|
||||||
|
\&resize_phase2,
|
||||||
|
"wait for change",
|
||||||
],
|
],
|
||||||
"check-resize" => \&ignore_cmd,
|
"check-resize" => \&ignore_cmd,
|
||||||
"create-md" => \&senseless_cmd,
|
"create-md" => \&senseless_cmd,
|
||||||
|
|
Loading…
Reference in New Issue