Skip to content

Commit

Permalink
Merge pull request #2966 from freenas/NAS-101303-11.2
Browse files Browse the repository at this point in the history
NAS-101303 / 11.2 / fix(middlewared/zfs): handle ENOENT on snapshot query (by william-gr)
  • Loading branch information
william-gr committed Apr 29, 2019
2 parents e055e57 + 37a548d commit e6bef45
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions src/middlewared/middlewared/plugins/zfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,12 @@ class Config:
@filterable
def query(self, filters=None, options=None):
# Special case for faster listing of snapshot names (#53149)
if options and options.get('select') == ['name']:
if (
options and options.get('select') == ['name'] and (
not filters or
filter_getattrs(filters).issubset({'name', 'pool'})
)
):
# Using zfs list -o name is dozens of times faster than py-libzfs
cmd = ['zfs', 'list', '-H', '-o', 'name', '-t', 'snapshot']
order_by = options.get('order_by')
Expand All @@ -403,21 +408,30 @@ def query(self, filters=None, options=None):
)
if cp.returncode != 0:
raise CallError(f'Failed to retrieve snapshots: {cp.stderr}')
snaps = [{'name': i} for i in cp.stdout.strip().split('\n')]
snaps = [
{'name': i, 'pool': i.split('/', 1)[0]}
for i in cp.stdout.strip().split('\n')
]
if filters:
return filter_list(snaps, filters, options)
return snaps
with libzfs.ZFS() as zfs:
# Handle `id` filter to avoid getting all snapshots first
snapshots = []
if filters and len(filters) == 1 and list(filters[0][:2]) == ['id', '=']:
try:
snapshots = [zfs.get_snapshot(filters[0][2]).__getstate__()]
snapshots.append(zfs.get_snapshot(filters[0][2]).__getstate__())
except libzfs.ZFSException as e:
if e.code != libzfs.Error.NOENT:
raise
snapshots = []
else:
snapshots = [i.__getstate__() for i in list(zfs.snapshots)]
for i in zfs.snapshots:
try:
snapshots.append(i.__getstate__())
except libzfs.ZFSException as e:
# snapshot may have been deleted while this is running
if e.code != libzfs.Error.NOENT:
raise
# FIXME: awful performance with hundreds/thousands of snapshots
return filter_list(snapshots, filters, options)

Expand Down

0 comments on commit e6bef45

Please sign in to comment.