[blivet:master 10/11] If btrfs creation fails, try with fewer specified options (#1109195)
mulhern
amulhern at redhat.com
Thu Jun 19 16:52:08 UTC 2014
Resolves: fed#1109195
At the point where the filesystem is being created failure because btrfs
is not comfortable with the options specified is worse than success
w/out those particular options.
Signed-off-by: mulhern <amulhern at redhat.com>
---
blivet/devices.py | 47 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/blivet/devices.py b/blivet/devices.py
index 4a485e8..4b41f3e 100644
--- a/blivet/devices.py
+++ b/blivet/devices.py
@@ -27,6 +27,7 @@ import tempfile
import abc
from decimal import Decimal
import re
+import itertools
# device backend modules
from .devicelibs import mdraid
@@ -5220,10 +5221,48 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice):
def _create(self):
log_method_call(self, self.name, status=self.status)
- btrfs.create_volume(devices=[d.path for d in self.parents],
- label=self.format.label,
- data=self.dataLevel,
- metadata=self.metaDataLevel)
+
+ options = [
+ ("label", self.format.label),
+ ("data", self.dataLevel),
+ ("metadata", self.metaDataLevel)
+ ]
+
+ log.info(
+ "attempting to create device %s with specified options %s",
+ self,
+ dict(options))
+
+ # Initially, try to create the volume with all non-None options.
+ # If that fails, try all possible combinations of non-None options.
+ # This is a workable approach because:
+ # - The options are independent
+ # - btrfs.create_volume treats None as none specified
+ # This strategy maximizes the number of specified options that are
+ # actually used in the creation of the volume.
+ # It does not prefer one combination of the same length to another;
+ # that choice is more or less random.
+ options = dict((n,v) for n, v in options if v is not None)
+ option_names = options.keys()
+ option_choices = itertools.chain(*(itertools.combinations(option_names, n) for n in range(len(option_names), -1, -1)))
+ kwargs_choices = (dict(map(lambda n: (n, options[n]), names)) for names in option_choices)
+
+ for kwargs in kwargs_choices:
+ log.info(
+ "attempting to create device %s with options %s",
+ self,
+ kwargs)
+ try:
+ btrfs.create_volume(
+ devices=[d.path for d in self.parents],
+ **kwargs)
+ except errors.BTRFSError:
+ log.info("failed to create device")
+ else:
+ log.info("created device")
+ return
+
+ raise errors.DeviceCreateError("failed to create device %s" % self)
def _postCreate(self):
super(BTRFSVolumeDevice, self)._postCreate()
--
1.9.3
More information about the anaconda-patches
mailing list