B OpenNebula/one#7719: lock LVM backup metadata ops

Wrap LVM backup snapshot and cleanup metadata commands with the per-VG
lock used by the datastore LVM helper. Keep export conversion outside the
lock so long-running qemu-img copies do not serialize unrelated LVM work.

(cherry picked from commit 42cff86578d5ad46c3f2ccc23bc1e5766ed87553)
This commit is contained in:
Ruben S. Montero committed 2026-06-23 16:32:25 +02:00
1 parent 1cbac037d2
commit d197e6d5eb
2 files changed
+41 -9

No files matched your search

+28 -2
View File
@@ -83,9 +83,13 @@ module MAD
LVMWrapper.lvmsync(sh)
end
def self.with_lvm_lock(vgname)
def self.lock_path(vgname)
lockname = vgname.gsub(/[^A-Za-z0-9_.-]/, '_')
lockpath = File.join(LOCK_DIR, "tm-onelvm-#{lockname}.lock")
File.join(LOCK_DIR, "tm-onelvm-#{lockname}.lock")
end
def self.with_lvm_lock(vgname)
lockpath = lock_path(vgname)
FileUtils.mkdir_p(LOCK_DIR)
@@ -108,6 +112,28 @@ module MAD
LVMWrapper.with_lvm_lock(vgname, &block)
end
def self.with_lvm_lock_sh(vgname, sh)
lockpath = lock_path(vgname)
<<~EOF
(
mkdir -p '#{LOCK_DIR}'
umask 0027
exec 9> '#{lockpath}'
if ! flock -w #{LOCK_TIMEOUT} 9; then
echo "Could not acquire exclusive lock on #{lockpath}" >&2
exit 1
fi
#{sh.strip.hd_indent}
)
EOF
end
def with_lvm_lock_sh(vgname, sh)
LVMWrapper.with_lvm_lock_sh(vgname, sh)
end
end
# TODO: join with tm_mad/lib/tm_action.rb
+13 -7
View File
@@ -137,8 +137,10 @@ module TransferManager
snapshot = "#{@lvname}_one_backup"
orig = path(snapshot)
snap_cmd << "sudo lvcreate -s -n #{snapshot} #{qual(@lvname)}\n"
snap_clup << "sudo lvremove -y #{qual(snapshot)}\n"
snap_cmd << lvm_lock_sh(
"sudo lvcreate -s -n #{snapshot} #{qual(@lvname)}"
)
snap_clup << lvm_lock_sh("sudo lvremove -y #{qual(snapshot)}")
else
# Full, live, non-thin: UNSUPPORTED
return
@@ -149,7 +151,7 @@ module TransferManager
end
expo_cmd << ds.cmd_confinement(<<~EOF, backup_dir)
sudo lvchange -K -ay #{orig}
#{lvm_lock_sh("sudo lvchange -K -ay #{orig}").strip}
qemu-img convert -m 4 -O qcow2 #{orig} #{ddst}
EOF
elsif @vm_backup_config[:last_increment] == -1
@@ -161,7 +163,7 @@ module TransferManager
snap_curr = "#{@lvname}_#{INC_SNAP_PREFIX}#{incid}"
snap_path = path(snap_curr)
snap_cmd << <<~EOF
snap_cmd << lvm_lock_sh(<<~EOF)
sudo lvremove -y #{qual(snap_curr)} || true
sudo lvcreate -s -n #{snap_curr} #{qual(@lvname)}
#{@pool.adjust_sh if @pool}
@@ -172,7 +174,7 @@ module TransferManager
qemu-img convert -m 4 -O qcow2 #{snap_path} #{dexp}
EOF
snap_clup << "sudo lvchange -K -an #{snap_path}\n"
snap_clup << lvm_lock_sh("sudo lvchange -K -an #{snap_path}")
else
# Incremental backup
return unless @is_thin
@@ -182,7 +184,7 @@ module TransferManager
snap_curr = "#{@lvname}_#{INC_SNAP_PREFIX}#{incid}"
snap_prev = "#{@lvname}_#{INC_SNAP_PREFIX}#{@vm_backup_config[:last_increment]}"
snap_cmd << <<~EOF
snap_cmd << lvm_lock_sh(<<~EOF)
sudo lvchange --refresh #{qual(@poolname)}
sudo lvremove -y #{qual(snap_curr)} || true
sudo lvcreate -s -n #{snap_curr} #{qual(@lvname)}
@@ -195,7 +197,7 @@ module TransferManager
backup_dir
)
snap_clup << "sudo lvremove -y #{qual(snap_prev)}\n"
snap_clup << lvm_lock_sh("sudo lvremove -y #{qual(snap_prev)}")
end
# rubocop:enable Style/GuardClause
@@ -227,6 +229,10 @@ module TransferManager
[restore_cmds, cleanup_cmd]
end
def lvm_lock_sh(sh)
MAD::LVMWrapper.with_lvm_lock_sh(@vgname, sh)
end
####################################################################
## CLASS METHODS