fix: Dynamic snapshot sizing to prevent I/O errors
Problem: Fixed 500MB snapshot size was too small for large/active LVs, causing I/O errors when snapshot space was exhausted during backup. Solution: Calculate appropriate snapshot size based on LV size: - Use 10% of LV size for snapshot space - Minimum 1GB to handle reasonable activity - Shows snapshot size in logs for transparency Example: - 20GB LV → 2GB snapshot - 100GB LV → 10GB snapshot - 500MB LV → 1GB snapshot (minimum) This prevents snapshot overflow and resulting I/O errors during backup. Changes: - GUI: Calculate snapshot size before creating - CLI: Same dynamic sizing logic - Both show calculated snapshot size in output - Handles both single LV and VG backup modes
This commit is contained in:
@@ -298,10 +298,21 @@ case "$MODE" in
|
|||||||
SNAPSHOT_NAME="${LV_NAME}_borg_snap"
|
SNAPSHOT_NAME="${LV_NAME}_borg_snap"
|
||||||
SNAPSHOT_PATH="/dev/$VG_NAME/$SNAPSHOT_NAME"
|
SNAPSHOT_PATH="/dev/$VG_NAME/$SNAPSHOT_NAME"
|
||||||
|
|
||||||
|
# Get LV size to determine appropriate snapshot size
|
||||||
|
LV_SIZE_BYTES=$(lvs --noheadings -o lv_size --units b "$SOURCE" | tr -d ' ' | sed 's/B$//')
|
||||||
|
# Use 10% of LV size or minimum 1GB for snapshot
|
||||||
|
SNAPSHOT_SIZE_BYTES=$((LV_SIZE_BYTES / 10))
|
||||||
|
if [ $SNAPSHOT_SIZE_BYTES -lt 1073741824 ]; then
|
||||||
|
SNAPSHOT_SIZE_BYTES=1073741824 # 1GB minimum
|
||||||
|
fi
|
||||||
|
SNAPSHOT_SIZE_GB=$((SNAPSHOT_SIZE_BYTES / 1073741824))
|
||||||
|
SNAPSHOT_SIZE="${SNAPSHOT_SIZE_GB}G"
|
||||||
|
|
||||||
info "This will backup LV to Borg repository"
|
info "This will backup LV to Borg repository"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${YELLOW}Source LV: $SOURCE${NC}"
|
echo -e "${YELLOW}Source LV: $SOURCE${NC}"
|
||||||
echo -e "${YELLOW}Repository: $TARGET${NC}"
|
echo -e "${YELLOW}Repository: $TARGET${NC}"
|
||||||
|
echo -e "${BLUE}Snapshot size: $SNAPSHOT_SIZE${NC}"
|
||||||
if [ "$NEW_REPO" = true ]; then
|
if [ "$NEW_REPO" = true ]; then
|
||||||
echo -e "${BLUE}Will create new repository${NC}"
|
echo -e "${BLUE}Will create new repository${NC}"
|
||||||
else
|
else
|
||||||
@@ -328,7 +339,7 @@ case "$MODE" in
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
log "Creating snapshot of source LV"
|
log "Creating snapshot of source LV"
|
||||||
lvcreate -L1G -s -n "$SNAPSHOT_NAME" "$SOURCE" || error "Failed to create snapshot"
|
lvcreate -L"$SNAPSHOT_SIZE" -s -n "$SNAPSHOT_NAME" "$SOURCE" || error "Failed to create snapshot"
|
||||||
|
|
||||||
# Create Borg archive
|
# Create Borg archive
|
||||||
ARCHIVE_NAME="lv_${LV_NAME}_$(date +%Y%m%d_%H%M%S)"
|
ARCHIVE_NAME="lv_${LV_NAME}_$(date +%Y%m%d_%H%M%S)"
|
||||||
@@ -398,9 +409,19 @@ case "$MODE" in
|
|||||||
SNAPSHOT_PATH="/dev/$SOURCE/$SNAPSHOT_NAME"
|
SNAPSHOT_PATH="/dev/$SOURCE/$SNAPSHOT_NAME"
|
||||||
LV_PATH="/dev/$SOURCE/$LV_NAME"
|
LV_PATH="/dev/$SOURCE/$LV_NAME"
|
||||||
|
|
||||||
|
# Get LV size to determine appropriate snapshot size
|
||||||
|
LV_SIZE_BYTES=$(lvs --noheadings -o lv_size --units b "$LV_PATH" | tr -d ' ' | sed 's/B$//')
|
||||||
|
# Use 10% of LV size or minimum 1GB for snapshot
|
||||||
|
SNAPSHOT_SIZE_BYTES=$((LV_SIZE_BYTES / 10))
|
||||||
|
if [ $SNAPSHOT_SIZE_BYTES -lt 1073741824 ]; then
|
||||||
|
SNAPSHOT_SIZE_BYTES=1073741824 # 1GB minimum
|
||||||
|
fi
|
||||||
|
SNAPSHOT_SIZE_GB=$((SNAPSHOT_SIZE_BYTES / 1073741824))
|
||||||
|
SNAPSHOT_SIZE="${SNAPSHOT_SIZE_GB}G"
|
||||||
|
|
||||||
log "Processing LV: $LV_NAME"
|
log "Processing LV: $LV_NAME"
|
||||||
log "Creating snapshot: $SNAPSHOT_NAME"
|
log "Creating snapshot: $SNAPSHOT_NAME (size: $SNAPSHOT_SIZE)"
|
||||||
lvcreate -L500M -s -n "$SNAPSHOT_NAME" "$LV_PATH" || {
|
lvcreate -L"$SNAPSHOT_SIZE" -s -n "$SNAPSHOT_NAME" "$LV_PATH" || {
|
||||||
warn "Failed to create snapshot for $LV_NAME"
|
warn "Failed to create snapshot for $LV_NAME"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -518,8 +518,19 @@ class SimpleBackupGUI:
|
|||||||
snapshot_name = f"{lv_name}_borg_snap"
|
snapshot_name = f"{lv_name}_borg_snap"
|
||||||
self.current_snapshot = f"/dev/{vg_name}/{snapshot_name}"
|
self.current_snapshot = f"/dev/{vg_name}/{snapshot_name}"
|
||||||
|
|
||||||
self.log(f"Creating snapshot: {snapshot_name}")
|
# Get LV size to determine appropriate snapshot size
|
||||||
success, output = self.run_command(f"lvcreate -L1G -s -n {snapshot_name} {source_lv}")
|
success, lv_size_output = self.run_command(f"lvs --noheadings -o lv_size --units b {source_lv}", show_output=False)
|
||||||
|
if success:
|
||||||
|
lv_size_bytes = int(lv_size_output.strip().replace('B', ''))
|
||||||
|
# Use 10% of LV size or minimum 1GB for snapshot
|
||||||
|
snapshot_size_bytes = max(lv_size_bytes // 10, 1024**3) # Min 1GB
|
||||||
|
snapshot_size_gb = snapshot_size_bytes // (1024**3)
|
||||||
|
snapshot_size = f"{snapshot_size_gb}G"
|
||||||
|
else:
|
||||||
|
snapshot_size = "2G" # Default fallback
|
||||||
|
|
||||||
|
self.log(f"Creating snapshot: {snapshot_name} (size: {snapshot_size})")
|
||||||
|
success, output = self.run_command(f"lvcreate -L{snapshot_size} -s -n {snapshot_name} {source_lv}")
|
||||||
if not success:
|
if not success:
|
||||||
raise Exception(f"Failed to create snapshot: {output}")
|
raise Exception(f"Failed to create snapshot: {output}")
|
||||||
|
|
||||||
@@ -609,9 +620,20 @@ class SimpleBackupGUI:
|
|||||||
snapshot_path = f"/dev/{source_vg}/{snapshot_name}"
|
snapshot_path = f"/dev/{source_vg}/{snapshot_name}"
|
||||||
lv_path = f"/dev/{source_vg}/{lv_name}"
|
lv_path = f"/dev/{source_vg}/{lv_name}"
|
||||||
|
|
||||||
|
# Get LV size to determine appropriate snapshot size
|
||||||
|
success, lv_size_output = self.run_command(f"lvs --noheadings -o lv_size --units b {lv_path}", show_output=False)
|
||||||
|
if success:
|
||||||
|
lv_size_bytes = int(lv_size_output.strip().replace('B', ''))
|
||||||
|
# Use 10% of LV size or minimum 1GB for snapshot
|
||||||
|
snapshot_size_bytes = max(lv_size_bytes // 10, 1024**3) # Min 1GB
|
||||||
|
snapshot_size_gb = snapshot_size_bytes // (1024**3)
|
||||||
|
snapshot_size = f"{snapshot_size_gb}G"
|
||||||
|
else:
|
||||||
|
snapshot_size = "2G" # Default fallback
|
||||||
|
|
||||||
self.log(f"Processing LV: {lv_name}")
|
self.log(f"Processing LV: {lv_name}")
|
||||||
self.log(f"Creating snapshot: {snapshot_name}")
|
self.log(f"Creating snapshot: {snapshot_name} (size: {snapshot_size})")
|
||||||
success, output = self.run_command(f"lvcreate -L500M -s -n {snapshot_name} {lv_path}")
|
success, output = self.run_command(f"lvcreate -L{snapshot_size} -s -n {snapshot_name} {lv_path}")
|
||||||
if not success:
|
if not success:
|
||||||
self.log(f"Warning: Failed to create snapshot for {lv_name}: {output}")
|
self.log(f"Warning: Failed to create snapshot for {lv_name}: {output}")
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user