Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NAS-111682 / 12.0 / Improve smartd restart performance #7263

Merged
merged 2 commits into from
Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/middlewared/middlewared/common/smart/smartctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ async def get_smartctl_args(middleware, devices, disk):
return [f"/dev/{driver}{controller_id}", "-d", f"3ware,{port}"]

args = [f"/dev/{disk}"]
p = await smartctl(args + ["-i"], stderr=subprocess.STDOUT, check=False, encoding="utf8", errors="ignore")
if "Unknown USB bridge" in p.stdout:
args = args + ["-d", "sat"]
if disk.startswith("da") and not await middleware.call("system.is_enterprise_ix_hardware"):
p = await smartctl(args + ["-i"], stderr=subprocess.STDOUT, check=False, encoding="utf8", errors="ignore")
if "Unknown USB bridge" in p.stdout:
args = args + ["-d", "sat"]

return args

Expand Down
7 changes: 6 additions & 1 deletion src/middlewared/middlewared/etc_files/smartd.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
async def annotate_disk_for_smart(middleware, devices, disk):
args = await get_smartctl_args(middleware, devices, disk)
if args:
if await ensure_smart_enabled(args):
if (
# On Enterprise hardware we only use S.M.A.R.T.-enabled disks, there is no need to check for this
# every time.
await middleware.call('system.is_enterprise_ix_hardware') or
await ensure_smart_enabled(args)
):
args.extend(["-a"])
args.extend(["-d", "removable"])
return disk, dict(smartctl_args=args)
Expand Down
4 changes: 2 additions & 2 deletions src/middlewared/middlewared/plugins/disk_/disk_info_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ async def get_swap_part_type(self):
async def get_swap_devices(self):
raise NotImplementedError()

async def label_to_dev(self, label, *args):
async def label_to_dev(self, label, geom_scan=True, cache=None):
raise NotImplementedError()

@private
async def label_to_disk(self, label, *args):
async def label_to_disk(self, label, geom_scan=True, cache=None):
raise NotImplementedError()

@private
Expand Down
36 changes: 29 additions & 7 deletions src/middlewared/middlewared/plugins/disk_/disk_info_freebsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,47 @@ async def get_swap_part_type(self):
def get_swap_devices(self):
return [os.path.join('/dev', i.devname) for i in getswapinfo()]

def label_to_dev(self, label, *args):
geom_scan = args[0] if args else True
def label_to_dev_disk_cache(self):
label_to_dev = {}
for label in geom.class_by_name('LABEL').xml:
if (name := label.find('name')) is not None:
if (provider := label.find('provider/name')) is not None:
label_to_dev[provider.text] = name.text

dev_to_disk = {}
for label in geom.class_by_name('PART').xml:
if (name := label.find('name')) is not None:
if (provider := label.find('provider/name')) is not None:
dev_to_disk[provider.text] = name.text

return {
'label_to_dev': label_to_dev,
'dev_to_disk': dev_to_disk,
}

def label_to_dev(self, label, geom_scan=True, cache=None):
if label.endswith('.nop'):
label = label[:-4]
elif label.endswith('.eli'):
label = label[:-4]

if cache is not None:
return cache['label_to_dev'].get(label)

if geom_scan:
geom.scan()
klass = geom.class_by_name('LABEL')
prov = klass.xml.find(f'.//provider[name="{label}"]/../name')
if prov is not None:
return prov.text

def label_to_disk(self, label, *args):
geom_scan = args[0] if args else True
if geom_scan:
geom.scan()
dev = self.label_to_dev(label, geom_scan) or label
def label_to_disk(self, label, geom_scan=True, cache=None):
if cache is None:
if geom_scan:
geom.scan()
dev = self.label_to_dev(label, geom_scan, cache) or label
if cache is not None:
return cache['dev_to_disk'].get(dev)
part = geom.class_by_name('PART').xml.find(f'.//provider[name="{dev}"]/../name')
if part is not None:
return part.text
Expand Down
130 changes: 0 additions & 130 deletions src/middlewared/middlewared/plugins/disk_/disk_info_linux.py

This file was deleted.

4 changes: 3 additions & 1 deletion src/middlewared/middlewared/plugins/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,13 @@ def transform_topology(self, x, options=None):
options = options or {}
if isinstance(x, dict):
if options.get('device_disk', True):
if 'label_to_dev_disk_cache' not in options:
options['label_to_dev_disk_cache'] = self.middleware.call_sync('disk.label_to_dev_disk_cache')
path = x.get('path')
if path is not None:
device = disk = None
if path.startswith('/dev/'):
args = [path[5:]] + ([] if osc.IS_LINUX else [options.get('geom_scan', True)])
args = [path[5:], False, options['label_to_dev_disk_cache']]
device = self.middleware.call_sync('disk.label_to_dev', *args)
disk = self.middleware.call_sync('disk.label_to_disk', *args)
x['device'] = device
Expand Down
4 changes: 4 additions & 0 deletions src/middlewared/middlewared/plugins/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,10 @@ async def is_ix_hardware(self):
product = (await self.middleware.call('system.dmidecode_info'))['system-product-name']
return product is not None and product.startswith(('FREENAS-', 'TRUENAS-'))

@private
async def is_enterprise_ix_hardware(self):
return await self.middleware.call('truenas.get_chassis_hardware') != 'TRUENAS-UNKNOWN'

# Sync the clock
@private
def sync_clock(self):
Expand Down