Skip to content

Commit

Permalink
improve pool import with disabled or indeterminate quota state #1987
Browse files Browse the repository at this point in the history
Add sensitivity / heed warnings re a quota disabled state (often only
displayed for a short period and accompanied by otherwise normal quota
enabled behaviour) and additionally make our 'btrfs qgroup assign'
wrapper fail elegantly in this interim / indeterminate quota state.

Addressed issue could in rare situations also block share creation.

Summary:

- Enhance qgroup_max() re qgroup disabled warnings.
- Enhance are_quotas_enabled() re qgroup disabled warnings.
- Don’t fail import / share creation for failure to quota group assign:
log as error and continue.
  • Loading branch information
phillxnet committed Nov 13, 2018
1 parent 71f6657 commit 0c0a690
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions src/rockstor/fs/btrfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -932,11 +932,24 @@ def are_quotas_enabled(mnt_pt):
Simple wrapper around 'btrfs qgroup show -f --raw mnt_pt' intended
as a fast determiner of True / False status of quotas enabled
:param mnt_pt: Mount point of btrfs filesystem
:return: True on rc = 0 False otherwise.
:return: True on rc = 0 and (err = '' or err = rescan recommended warning),
False otherwise.
"""
o, e, rc = run_command([BTRFS, 'qgroup', 'show', '-f', '--raw', mnt_pt])
if rc == 0:
if rc == 0 and (e[0] == '' or e[0] == 'WARNING: qgroup data inconsistent, '
'rescan recommended'):
return True
# Note on above e[0] clauses:
# Catch rare but observed rc == 0 when quotas disabled, e.g.:
# btrfs qgroup show -f --raw /mnt2/rock-pool
# WARNING: quota disabled, qgroup data may be out of date
# qgroupid rfer excl
# -------- ---- ----
# 0/5 0 0
#
# echo $?
# 0
# We are called in a try except block: caller assumes False on Exception.
return False


Expand Down Expand Up @@ -981,7 +994,7 @@ def qgroup_max(mnt_pt):
try:
o, e, rc = run_command([BTRFS, 'qgroup', 'show', mnt_pt], log=True)
except CommandException as e:
# disabled quotas will result in o = [''], rc = 1 and e[0] =
# disabled quotas can result in o = [''], rc = 1 and e[0] =
emsg = "ERROR: can't list qgroups: quotas not enabled"
# this is non fatal so we catch this specific error and info log it.
if e.err[0] == emsg:
Expand All @@ -991,7 +1004,13 @@ def qgroup_max(mnt_pt):
return -1
# otherwise we raise an exception as normal.
raise
# if no exception was raised find the max 2015/qgroup
# Catch quota disabled WARNING (no associated Exception) and info log.
if e[0] == "WARNING: quota disabled, qgroup data may be out of date":
logger.info('Mount Point: {} has Quotas disabled WARNING, skipping '
'qgroup show.'.format(mnt_pt))
# and return our default res
return -1
# if no exception, and no caught WARNING, find the max 2015/qgroup
res = 0
for l in o:
if (re.match('%s/' % QID, l) is not None):
Expand Down Expand Up @@ -1156,6 +1175,19 @@ def qgroup_assign(qid, pqid, mnt_pt):
logger.info('Read-only fs ({}), skipping qgroup assign: '
'child ({}), parent ({}).'.format(mnt_pt, qid, pqid))
return e.out, e.err, e.rc
# Under some indeterminate quota states the following error occurs:
emsg2 = 'ERROR: unable to assign quota group: Invalid argument'
# This can results in a failed import if not caught and given quotas
# are non critical we catch and error log rather than hard failing.
# TODO: This is a broad error message and it's inclusion should be
# TODO: re-assessed after major btrfs version increases: post quotas
# TODO: considered more stable.
if e.err[0] == emsg2:
logger.error('"{}" received on fs ({}), skipping qgroup assign: '
'child ({}), parent ({}). This may be related to an '
'undetermined quota state.'.format(emsg2, mnt_pt,
qid, pqid))
return e.out, e.err, e.rc
wmsg = 'WARNING: quotas may be inconsistent, rescan needed'
if e.err[0] == wmsg:
# schedule a rescan if one is not currently running.
Expand Down

0 comments on commit 0c0a690

Please sign in to comment.