OpenZFS 7248 - large block support breaks rsend_009_pos

7249 rsend_015_pos produces false failures due to race
7250 testrunner can miss options specific to individual tests in runfiles

Authored by: John Wren Kennedy <john.kennedy@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Ported-by: George Melikov <mail@gmelikov.ru>

OpenZFS-issue: https://www.illumos.org/issues/7248
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/f9a78bf
Closes #5799
This commit is contained in:
John Wren Kennedy 2016-08-30 12:01:41 -07:00 committed by Brian Behlendorf
parent ce456d483c
commit 9060917189
3 changed files with 35 additions and 43 deletions

View File

@ -563,14 +563,13 @@ tests = ['reservation_001_pos', 'reservation_002_pos', 'reservation_003_pos',
# DISABLED: # DISABLED:
# rsend_008_pos - Fails for OpenZFS on illumos # rsend_008_pos - Fails for OpenZFS on illumos
# rsend_009_pos - Fails for OpenZFS on illumos
# rsend_020_pos - ASSERTs in dump_record() # rsend_020_pos - ASSERTs in dump_record()
[tests/functional/rsend] [tests/functional/rsend]
tests = ['rsend_001_pos', 'rsend_002_pos', 'rsend_003_pos', 'rsend_004_pos', tests = ['rsend_001_pos', 'rsend_002_pos', 'rsend_003_pos', 'rsend_004_pos',
'rsend_005_pos', 'rsend_006_pos', 'rsend_007_pos', 'rsend_005_pos', 'rsend_006_pos', 'rsend_007_pos',
'rsend_009_pos',
'rsend_010_pos', 'rsend_011_pos', 'rsend_012_pos', 'rsend_010_pos', 'rsend_011_pos', 'rsend_012_pos',
'rsend_013_pos', 'rsend_014_pos', 'rsend_013_pos', 'rsend_014_pos', 'rsend_019_pos',
'rsend_019_pos',
'rsend_021_pos', 'rsend_022_pos', 'rsend_024_pos'] 'rsend_021_pos', 'rsend_022_pos', 'rsend_024_pos']
[tests/functional/scrub_mirror] [tests/functional/scrub_mirror]

View File

@ -27,7 +27,6 @@ from subprocess import PIPE
from subprocess import Popen from subprocess import Popen
from sys import argv from sys import argv
from sys import maxint from sys import maxint
from sys import exit
from threading import Timer from threading import Timer
from time import time from time import time
@ -131,8 +130,8 @@ class Cmd(object):
self.timeout = 60 self.timeout = 60
def __str__(self): def __str__(self):
return "Pathname: %s\nOutputdir: %s\nTimeout: %d\nUser: %s\n" % ( return "Pathname: %s\nOutputdir: %s\nTimeout: %d\nUser: %s\n" % \
self.pathname, self.outputdir, self.timeout, self.user) (self.pathname, self.outputdir, self.timeout, self.user)
def kill_cmd(self, proc): def kill_cmd(self, proc):
""" """
@ -311,10 +310,9 @@ class Test(Cmd):
if len(self.post_user): if len(self.post_user):
post_user = ' (as %s)' % (self.post_user) post_user = ' (as %s)' % (self.post_user)
return "Pathname: %s\nOutputdir: %s\nTimeout: %d\nPre: %s%s\nPost: " \ return "Pathname: %s\nOutputdir: %s\nTimeout: %d\nPre: %s%s\nPost: " \
"%s%s\nUser: %s\n" % ( "%s%s\nUser: %s\n" % \
self.pathname, self.outputdir, (self.pathname, self.outputdir, self.timeout, self.pre,
self.timeout, self.pre, pre_user, self.post, post_user, pre_user, self.post, post_user, self.user)
self.user)
def verify(self, logger): def verify(self, logger):
""" """
@ -343,13 +341,13 @@ class Test(Cmd):
Create Cmd instances for the pre/post scripts. If the pre script Create Cmd instances for the pre/post scripts. If the pre script
doesn't pass, skip this Test. Run the post script regardless. doesn't pass, skip this Test. Run the post script regardless.
""" """
pretest = Cmd(self.pre, outputdir=os.path.join(self.outputdir, odir = os.path.join(self.outputdir, os.path.basename(self.pre))
os.path.basename(self.pre)), timeout=self.timeout, pretest = Cmd(self.pre, outputdir=odir, timeout=self.timeout,
user=self.pre_user) user=self.pre_user)
test = Cmd(self.pathname, outputdir=self.outputdir, test = Cmd(self.pathname, outputdir=self.outputdir,
timeout=self.timeout, user=self.user) timeout=self.timeout, user=self.user)
posttest = Cmd(self.post, outputdir=os.path.join(self.outputdir, odir = os.path.join(self.outputdir, os.path.basename(self.post))
os.path.basename(self.post)), timeout=self.timeout, posttest = Cmd(self.post, outputdir=odir, timeout=self.timeout,
user=self.post_user) user=self.post_user)
cont = True cont = True
@ -387,8 +385,8 @@ class TestGroup(Test):
if len(self.post_user): if len(self.post_user):
post_user = ' (as %s)' % (self.post_user) post_user = ' (as %s)' % (self.post_user)
return "Pathname: %s\nOutputdir: %s\nTests: %s\nTimeout: %d\n" \ return "Pathname: %s\nOutputdir: %s\nTests: %s\nTimeout: %d\n" \
"Pre: %s%s\nPost: %s%s\nUser: %s\n" % ( "Pre: %s%s\nPost: %s%s\nUser: %s\n" % \
self.pathname, self.outputdir, self.tests, self.timeout, (self.pathname, self.outputdir, self.tests, self.timeout,
self.pre, pre_user, self.post, post_user, self.user) self.pre, pre_user, self.post, post_user, self.user)
def verify(self, logger): def verify(self, logger):
@ -442,11 +440,11 @@ class TestGroup(Test):
doesn't pass, skip all the tests in this TestGroup. Run the post doesn't pass, skip all the tests in this TestGroup. Run the post
script regardless. script regardless.
""" """
pretest = Cmd(self.pre, outputdir=os.path.join(self.outputdir, odir = os.path.join(self.outputdir, os.path.basename(self.pre))
os.path.basename(self.pre)), timeout=self.timeout, pretest = Cmd(self.pre, outputdir=odir, timeout=self.timeout,
user=self.pre_user) user=self.pre_user)
posttest = Cmd(self.post, outputdir=os.path.join(self.outputdir, odir = os.path.join(self.outputdir, os.path.basename(self.post))
os.path.basename(self.post)), timeout=self.timeout, posttest = Cmd(self.post, outputdir=odir, timeout=self.timeout,
user=self.post_user) user=self.post_user)
cont = True cont = True
@ -565,11 +563,9 @@ class TestRun(object):
testgroup = TestGroup(os.path.abspath(pathname)) testgroup = TestGroup(os.path.abspath(pathname))
for prop in TestGroup.props: for prop in TestGroup.props:
try: for sect in ['DEFAULT', section]:
setattr(testgroup, prop, config.get('DEFAULT', prop)) if config.has_option(sect, prop):
setattr(testgroup, prop, config.get(section, prop)) setattr(testgroup, prop, config.get(sect, prop))
except ConfigParser.NoOptionError:
pass
# Repopulate tests using eval to convert the string to a list # Repopulate tests using eval to convert the string to a list
testgroup.tests = eval(config.get(section, 'tests')) testgroup.tests = eval(config.get(section, 'tests'))
@ -579,11 +575,10 @@ class TestRun(object):
else: else:
test = Test(section) test = Test(section)
for prop in Test.props: for prop in Test.props:
try: for sect in ['DEFAULT', section]:
setattr(test, prop, config.get('DEFAULT', prop)) if config.has_option(sect, prop):
setattr(test, prop, config.get(section, prop)) setattr(test, prop, config.get(sect, prop))
except ConfigParser.NoOptionError:
pass
if test.verify(logger): if test.verify(logger):
self.tests[section] = test self.tests[section] = test
@ -598,7 +593,7 @@ class TestRun(object):
""" """
defaults = dict([(prop, getattr(options, prop)) for prop, _ in defaults = dict([(prop, getattr(options, prop)) for prop, _ in
self.defaults]) self.defaults])
config = ConfigParser.RawConfigParser(defaults) config = ConfigParser.RawConfigParser(defaults)
for test in sorted(self.tests.keys()): for test in sorted(self.tests.keys()):
@ -614,7 +609,7 @@ class TestRun(object):
except IOError: except IOError:
fail('Could not open \'%s\' for writing.' % options.template) fail('Could not open \'%s\' for writing.' % options.template)
def complete_outputdirs(self, options): def complete_outputdirs(self):
""" """
Collect all the pathnames for Tests, and TestGroups. Work Collect all the pathnames for Tests, and TestGroups. Work
backwards one pathname component at a time, to create a unique backwards one pathname component at a time, to create a unique
@ -717,8 +712,8 @@ class TestRun(object):
m, s = divmod(time() - self.starttime, 60) m, s = divmod(time() - self.starttime, 60)
h, m = divmod(m, 60) h, m = divmod(m, 60)
print '\nRunning Time:\t%02d:%02d:%02d' % (h, m, s) print '\nRunning Time:\t%02d:%02d:%02d' % (h, m, s)
print 'Percent passed:\t%.1f%%' % ( print 'Percent passed:\t%.1f%%' % ((float(Result.runresults['PASS']) /
(float(Result.runresults['PASS']) / float(Result.total)) * 100) float(Result.total)) * 100)
print 'Log directory:\t%s' % self.outputdir print 'Log directory:\t%s' % self.outputdir
@ -792,7 +787,7 @@ def options_cb(option, opt_str, value, parser):
path_options = ['runfile', 'outputdir', 'template', 'testdir'] path_options = ['runfile', 'outputdir', 'template', 'testdir']
if option.dest is 'runfile' and '-w' in parser.rargs or \ if option.dest is 'runfile' and '-w' in parser.rargs or \
option.dest is 'template' and '-c' in parser.rargs: option.dest is 'template' and '-c' in parser.rargs:
fail('-c and -w are mutually exclusive.') fail('-c and -w are mutually exclusive.')
if opt_str in parser.rargs: if opt_str in parser.rargs:
@ -859,7 +854,7 @@ def parse_args():
return options return options
def main(args): def main():
options = parse_args() options = parse_args()
testrun = TestRun(options) testrun = TestRun(options)
@ -874,11 +869,11 @@ def main(args):
else: else:
fail('Unknown command specified') fail('Unknown command specified')
testrun.complete_outputdirs(options) testrun.complete_outputdirs()
testrun.run(options) testrun.run(options)
testrun.summary() testrun.summary()
exit(0) exit(0)
if __name__ == '__main__': if __name__ == '__main__':
main(argv[1:]) main()

View File

@ -26,7 +26,7 @@
# #
# #
# Copyright (c) 2013 by Delphix. All rights reserved. # Copyright (c) 2013, 2015 by Delphix. All rights reserved.
# #
. $STF_SUITE/tests/functional/rsend/rsend.kshlib . $STF_SUITE/tests/functional/rsend/rsend.kshlib
@ -67,8 +67,7 @@ log_must zpool create spool $TESTDIR/sfile
# Test out of space on sub-filesystem # Test out of space on sub-filesystem
# #
log_must $ZFS create bpool/fs log_must $ZFS create bpool/fs
mntpnt=$(get_prop mountpoint bpool/fs) log_must $MKFILE 30M /bpool/fs/file
log_must $MKFILE 30M $mntpnt/file
log_must $ZFS snapshot bpool/fs@snap log_must $ZFS snapshot bpool/fs@snap
log_must eval "$ZFS send -R bpool/fs@snap > $BACKDIR/fs-R" log_must eval "$ZFS send -R bpool/fs@snap > $BACKDIR/fs-R"
@ -80,8 +79,7 @@ log_must ismounted spool
# #
# Test out of space on top filesystem # Test out of space on top filesystem
# #
mntpnt2=$(get_prop mountpoint bpool) log_must $MV /bpool/fs/file /bpool
log_must $MV $mntpnt/file $mntpnt2
log_must $ZFS destroy -rf bpool/fs log_must $ZFS destroy -rf bpool/fs
log_must $ZFS snapshot bpool@snap log_must $ZFS snapshot bpool@snap