Skip to content

Commit 0aa86b1

Browse files
committed
Merge branch 'develop' into add-api-server
2 parents 1b48574 + 951f89a commit 0aa86b1

6 files changed

Lines changed: 34 additions & 45 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515

1616
### Changed ♻️
1717

18+
- Uses CoW when it's enabled and supported between source and destination on snapshot restore
19+
1820
### Removed 🗑️ ⚠️
1921

2022
### Internal 🔧

rawfile/rawfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def node_driver_preflight_checks(task_manager: task_manager.TaskManager):
6363
volume_manager.migrate_all_volume_schemas()
6464
task_manager.migrate_tasks_file_path()
6565
consts.COW_SUPPORT_MAP = {
66-
name: is_cow_supported(pool.path)
66+
name: is_cow_supported(pool.path, pool.path)
6767
for name, pool in config.csi_driver.storage_pools.items()
6868
}
6969

rawfile/utils/rawfile.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def update_permissions(volume_id: str, storage_pool: str) -> None:
103103
if not _img_dir.exists():
104104
return
105105
_img_dir.chmod(D_PERMS)
106-
## set permissions recursively on all files and dirs under the volume path
106+
# set permissions recursively on all files and dirs under the volume path
107107
# we go 3 levels deep to cover most cases (img file, snapshots, temp snapshots, etc.)
108108
for each in chain(
109109
_img_dir.glob("**/*"), _img_dir.glob("**/**/*"), _img_dir.glob("**/**/**/*")
@@ -217,7 +217,7 @@ def be_symlink(path, to):
217217
path.symlink_to(to)
218218

219219

220-
def is_cow_supported(dir: Path) -> bool:
220+
def is_cow_supported(source_dir: Path, destination_dir: Path) -> bool:
221221
"""Check if the filesystem at the given directory supports copy-on-write (COW) operations.
222222
223223
This function attempts to create a temporary file in the specified directory,
@@ -230,11 +230,11 @@ def is_cow_supported(dir: Path) -> bool:
230230
Returns:
231231
bool: True if COW is supported, False otherwise.
232232
"""
233-
test_file = dir / ".cow_test_file"
234-
clone_file = dir / ".cow_test_clone"
233+
test_file = source_dir / ".cow_test_file"
234+
clone_file = destination_dir / ".cow_test_clone"
235235
try:
236236
with open(test_file, "wb") as f:
237-
f.write(b"test")
237+
f.write(b"COW Support Test")
238238
f.flush()
239239
os.fsync(f.fileno())
240240
run(f"cp --reflink=always {test_file} {clone_file}")

rawfile/utils/snapshot_manager.py

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
from os import fsync
1+
import os
22
from pathlib import Path
33
import time
44
from dataclasses import dataclass
5+
import consts
56
from utils.commands import run
67
from config import config
78
from utils.errors import FsFreezeNotSupportedOnBlockVolumes, SnapshotCreateVolumeInUse
89
from utils.lock import VolLock
910
from utils.rawfile import (
1011
attached_loops,
1112
img_file,
13+
is_cow_supported,
1214
metadata,
13-
patch_metadata,
1415
snapshots_dir,
1516
)
1617
from glob import glob
@@ -72,15 +73,6 @@ def create_snapshot(
7273

7374
creation_time = time.time()
7475
Path(f"{snap_path}.creating").unlink(missing_ok=True)
75-
meta = metadata(volume_id)
76-
reflink_attached = list(set(meta.get("reflink_attached", [])))
77-
if copy_on_write:
78-
reflink_attached.append(name)
79-
patch_metadata(
80-
volume_id,
81-
meta.get("storage_pool", config.csi_driver.default_pool),
82-
{"reflink_attached": reflink_attached},
83-
)
8476
return Snapshot(
8577
name=name,
8678
volume_id=volume_id,
@@ -110,30 +102,26 @@ def delete_snapshot(self, volume_id: str, name: str, temporary: bool = False):
110102
Path(f"{snap_path}.creating"),
111103
):
112104
path.unlink(missing_ok=True)
113-
meta = metadata(volume_id)
114-
reflink_attached = list(set(meta.get("reflink_attached", [])))
115-
if name in reflink_attached:
116-
reflink_attached.remove(name)
117-
patch_metadata(
118-
volume_id,
119-
meta["storage_pool"],
120-
{"reflink_attached": reflink_attached},
121-
)
122105

123106
def restore_snapshot(
124107
self, volume_id: str, name: str, destination: Path, temporary: bool = False
125108
):
126109
"""Restore a snapshot"""
127-
chunk_size = 1024 * 1024
110+
volume_meta = metadata(volume_id)
128111
snap_path = self._get_snapshot_path(volume_id, name, temporary)
129-
with open(snap_path, "rb") as src, open(destination, "wb") as dst:
130-
while True:
131-
buf = src.read(chunk_size)
132-
if not buf:
133-
break
134-
dst.write(buf)
135-
dst.flush()
136-
fsync(dst.fileno())
112+
copy_on_write_param = volume_meta.get("copy_on_write", None)
113+
copy_on_write = (
114+
copy_on_write_param
115+
if copy_on_write_param is not None
116+
else consts.COW_SUPPORT_MAP.get(
117+
volume_meta.get("storage_pool", None), False
118+
)
119+
) and is_cow_supported(Path(os.path.dirname(snap_path)), destination)
120+
reflink = "always" if copy_on_write else "never"
121+
cmd = (
122+
f"cp --sparse=auto --reflink={reflink} {snap_path} {destination.as_posix()}"
123+
)
124+
run(cmd, check=True)
137125

138126
def list_snapshots(
139127
self,

rawfile/utils/volume_manager.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,9 @@ def rmdir(path: Path):
181181
temp_snapshots = list(snapshots_dir(volume_id, temporary=True).glob("*"))
182182
total_snapshots = len(snapshots) + len(temp_snapshots)
183183
meta = metadata_or(volume_id)
184-
if len(meta.get("reflink_attached", [])) > 0:
184+
if total_snapshots > 0:
185185
logger.warning(
186-
"Volume has COW Snapshots attached, skipping destroy, will be destoyed when all snapshots are removed",
187-
volume_id=volume_id,
188-
snapshots=total_snapshots,
189-
)
190-
return
191-
elif total_snapshots > 0:
192-
logger.warning(
193-
"Volume has Snapshots(without COW) attached, will only remove volume data",
186+
"Volume has Snapshots attached, will only remove volume data",
194187
volume_id=volume_id,
195188
snapshots=total_snapshots,
196189
)

rawfile/volume_schema.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import sys
22
from typing import Final
33

4-
LATEST_SCHEMA_VERSION: Final[int] = 6
4+
LATEST_SCHEMA_VERSION: Final[int] = 7
55

66

77
def migrate_0_to_1(data: dict) -> dict:
@@ -44,6 +44,12 @@ def migrate_5_to_6(data: dict) -> dict:
4444
return data
4545

4646

47+
def migrate_6_to_7(data: dict) -> dict:
48+
data["schema_version"] = 7
49+
data.pop("reflink_attached", None)
50+
return data
51+
52+
4753
def migrate_to(data: dict, version: int) -> dict:
4854
current = data.get("schema_version", 0)
4955
if current > version:

0 commit comments

Comments
 (0)