[PATCH 1/3] Handle nested btrfs subvolumes correctly. (#1016959)
David Lehman
dlehman at redhat.com
Fri Nov 15 14:32:00 UTC 2013
Subvolumes are nested. That is to say that removing subvolume foo
will also remove subvolumes foo/bar and foo/bar/baz.
---
blivet/devicelibs/btrfs.py | 9 ++++++---
blivet/devices.py | 14 ++++++++++++--
blivet/devicetree.py | 17 ++++++++++++++++-
3 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/blivet/devicelibs/btrfs.py b/blivet/devicelibs/btrfs.py
index 2f0cee4..eba27f7 100644
--- a/blivet/devicelibs/btrfs.py
+++ b/blivet/devicelibs/btrfs.py
@@ -98,15 +98,18 @@ def create_snapshot(source, dest):
def scan_device(path):
return btrfs(["device", "scan", path])
+_subvol_list_regex = r'ID (\d+) gen \d+ parent (\d+) top level \d+ path (.+)\n'
+
# get a list of subvolumes from a mounted btrfs filesystem
def list_subvolumes(mountpoint):
if not os.path.ismount(mountpoint):
raise ValueError("volume not mounted")
- args = ["subvol", "list", mountpoint]
+ args = ["subvol", "list", "-p", mountpoint]
buf = btrfs(args, capture=True)
vols = []
- for group in re.findall(r'ID (\d+) gen \d+ top level \d+ path (.+)\n', buf):
- vols.append({"id": int(group[0]), "path": group[1]})
+ for group in re.findall(_subvol_list_regex, buf):
+ vols.append({"id": int(group[0]), "parent": int(group[1]),
+ "path": group[2]})
return vols
diff --git a/blivet/devices.py b/blivet/devices.py
index 8426339..725a917 100644
--- a/blivet/devices.py
+++ b/blivet/devices.py
@@ -4351,6 +4351,7 @@ class BTRFSDevice(StorageDevice):
class BTRFSVolumeDevice(BTRFSDevice):
_type = "btrfs volume"
+ vol_id = 5
def __init__(self, *args, **kwargs):
self.dataLevel = kwargs.pop("dataLevel", None)
@@ -4378,7 +4379,7 @@ class BTRFSVolumeDevice(BTRFSDevice):
label=label,
volUUID=self.uuid,
device=self.path,
- mountopts="subvolid=0")
+ mountopts="subvolid=" + self.vol_id)
self.originalFormat = copy.copy(self.format)
def _setFormat(self, format):
@@ -4534,7 +4535,16 @@ class BTRFSSubVolumeDevice(BTRFSDevice):
@property
def volume(self):
- return self.parents[0]
+ parent = self.parents[0]
+ vol = None
+ while True:
+ if not isinstance(parent, BTRFSSubVolumeDevice):
+ vol = parent
+ break
+
+ parent = parent.parents[0]
+
+ return vol
def setupParents(self, orig=False):
""" Run setup method of all parent devices. """
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
index 2cde0ff..0311e42 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -1590,14 +1590,29 @@ class DeviceTree(object):
for subvol_dict in btrfs_dev.listSubVolumes():
vol_id = subvol_dict["id"]
vol_path = subvol_dict["path"]
+ parent_id = subvol_dict["parent"]
if vol_path in [sv.name for sv in btrfs_dev.subvolumes]:
continue
+
+ # look up the parent subvol
+ parent = None
+ subvols = [btrfs_dev] + btrfs_dev.subvolumes
+ for sv in subvols:
+ if sv.vol_id == parent_id:
+ parent = sv
+ break
+
+ if parent is None:
+ log.error("failed to find parent (%d) for subvol %s"
+ % (parent_id, vol_path))
+ raise DeviceTreeError("could not find parent for subvol")
+
fmt = getFormat("btrfs", device=btrfs_dev.path, exists=True,
mountopts="subvol=%s" % vol_path)
subvol = BTRFSSubVolumeDevice(vol_path,
vol_id=vol_id,
format=fmt,
- parents=[btrfs_dev],
+ parents=[parent],
exists=True)
self._addDevice(subvol)
--
1.8.1.4
More information about the anaconda-patches
mailing list