ZTS: Fix create-o_ashift test case

The function that fills the uberblock ring buffer on every device label
has been reworked to avoid occasional failures caused by a race
condition that prevents 'zpool sync' from writing some uberblock
sequentially: this happens when the pool sync ioctl dispatch code calls
txg_wait_synced() while we're already waiting for a TXG to sync.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #6924 
Closes #6977
This commit is contained in:
LOLi 2017-12-19 19:49:33 +01:00 committed by Brian Behlendorf
parent bbffb59efc
commit c30e34faa1
2 changed files with 26 additions and 34 deletions

View File

@ -2788,10 +2788,6 @@ dump_label(const char *dev)
exit(1); exit(1);
} }
if (ioctl(fd, BLKFLSBUF) != 0)
(void) printf("failed to invalidate cache '%s' : %s\n", path,
strerror(errno));
if (fstat64_blk(fd, &statbuf) != 0) { if (fstat64_blk(fd, &statbuf) != 0) {
(void) printf("failed to stat '%s': %s\n", path, (void) printf("failed to stat '%s': %s\n", path,
strerror(errno)); strerror(errno));
@ -2799,6 +2795,10 @@ dump_label(const char *dev)
exit(1); exit(1);
} }
if (S_ISBLK(statbuf.st_mode) && ioctl(fd, BLKFLSBUF) != 0)
(void) printf("failed to invalidate cache '%s' : %s\n", path,
strerror(errno));
avl_create(&config_tree, cksum_record_compare, avl_create(&config_tree, cksum_record_compare,
sizeof (cksum_record_t), offsetof(cksum_record_t, link)); sizeof (cksum_record_t), offsetof(cksum_record_t, link));
avl_create(&uberblock_tree, cksum_record_compare, avl_create(&uberblock_tree, cksum_record_compare,

View File

@ -42,54 +42,47 @@
verify_runnable "global" verify_runnable "global"
# See issue: https://github.com/zfsonlinux/zfs/issues/6924
if is_linux; then
log_unsupported "Test case occasionally fails"
fi
function cleanup function cleanup
{ {
poolexists $TESTPOOL && destroy_pool $TESTPOOL destroy_pool $TESTPOOL
log_must rm -f $disk log_must rm -f $disk
} }
# #
# Commit the specified number of TXGs to the provided pool # Fill the uberblock ring in every <device> label: we do this by committing
# We use 'zpool sync' here because we can't force it via sync(1) like on illumos # TXGs to the provided <pool> until every slot contains a valid uberblock.
# $1 pool name # NOTE: We use 'zpool sync' here because we can't force it via sync(1) like on
# $2 number of txg syncs # illumos
# #
function txg_sync function write_device_uberblocks # <device> <pool>
{ {
typeset pool=$1 typeset device=$1
typeset -i count=$2 typeset pool=$2
typeset -i i=0;
while [ $i -lt $count ] while [ "$(zdb -quuul $device | grep -c 'invalid')" -ne 0 ]
do do
log_must sync_pool $pool true sync_pool $pool true
((i = i + 1))
done done
} }
# #
# Verify device $1 labels contains $2 valid uberblocks in every label # Verify every label on <device> contains <count> (valid) uberblocks
# $1 device
# $2 uberblocks count
# #
function verify_device_uberblocks function verify_device_uberblocks # <device> <count>
{ {
typeset device=$1 typeset device=$1
typeset ubcount=$2 typeset ubcount=$2
zdb -quuul $device | egrep '^(\s+)?Uberblock' | zdb -quuul $device | egrep '^(\s+)?Uberblock' |
egrep -v 'invalid$' | awk \ awk -v ubcount=$ubcount 'BEGIN { count=0 } { uberblocks[$0]++; }
-v ubcount=$ubcount '{ uberblocks[$0]++; } END {
END { for (i in uberblocks) { for (i in uberblocks) {
count++; if (i ~ /invalid/) { continue; }
if (uberblocks[i] != 4) { exit 1; } if (uberblocks[i] != 4) { exit 1; }
count++;
} }
if (count != ubcount) { exit 1; } }' if (count != ubcount) { exit 1; }
}'
return $? return $?
} }
@ -115,8 +108,7 @@ do
log_fail "Pool was created without setting ashift value to "\ log_fail "Pool was created without setting ashift value to "\
"$ashift (current = $pprop)" "$ashift (current = $pprop)"
fi fi
# force 128 txg sync to fill the uberblock ring write_device_uberblocks $disk $TESTPOOL
txg_sync $TESTPOOL 128
verify_device_uberblocks $disk ${ubcount[$i]} verify_device_uberblocks $disk ${ubcount[$i]}
if [[ $? -ne 0 ]] if [[ $? -ne 0 ]]
then then