On Tue, Apr 16, 2019 at 11:24:50PM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > With the new copy on write functionality it's possible to reserve so > much COW space for a file that we end up overflowing i_delayed_blks. > The only user-visible effect of this is to cause totally wrong i_blocks > output in stat, so check for that. .... > > + umount $loop_mount > /dev/null 2>&1 > + rm -rf $tmp.* > +} > + > +# get standard environment, filters and checks > +. ./common/rc > +. ./common/reflink > + > +# real QA test starts here > +_supported_os Linux > +_supported_fs xfs > +_require_scratch_reflink > +_require_loop > +_require_xfs_debug > + > +echo "Format and mount" > +_scratch_mkfs > "$seqres.full" 2>&1 > +_scratch_mount > +_require_fs_space $SCRATCH_MNT 2400000 # 100T fs requires ~2.4GB of space > + > +loop_file=$SCRATCH_MNT/a.img > +loop_mount=$SCRATCH_MNT/a > +truncate -s 100T $loop_file > +$MKFS_XFS_PROG $MKFS_OPTIONS -f $loop_file >> $seqres.full Hmm - that's going to create a 2GB log and zero it, meaning on slow devices this is going to take some time. lodev=$(_create_loop_device $file) _mkfs_dev -l size=128m $lodev > +mkdir $loop_mount > +mount -o loop -t xfs $loop_file $loop_mount > + > +echo "Create crazy huge file" > +touch "${loop_mount}/a" > +blksz="$(stat -f -c '%S' "${loop_mount}")" > +MAXEXTLEN=2097151 # cowextsize can't be more than MAXEXTLEN > +extsize="$(( ((2 ** 32) - 1) / blksz ))" > +test "${extsize}" -gt "${MAXEXTLEN}" && extsize="${MAXEXTLEN}" > +extsize_bytes="$(( extsize * blksz ))" This is overkill, yes? When is extsize_bytes not equal to MAXEXTLEN * blksz on this 100TB filesystem? > +# Set the largest cowextsize we can > +$XFS_IO_PROG -c "cowextsize ${extsize_bytes}" "${loop_mount}/a" > +set_cowextsize="$($XFS_IO_PROG -c 'cowextsize' "${loop_mount}/a" | sed -e 's/^.\([0-9]*\).*$/\1/g')" > +test "${set_cowextsize}" -eq 0 && _fail "could not set cowextsize?" Run the test anyway, even if the cowextsize setting fails. WHo knows what random crap will fall out.... > +statB="$(stat -c '%B' "${loop_mount}/a")" > + > +# Write a single byte every cowextsize bytes so that we minimize the space > +# required to create maximally sized cow reservations > +nr="$(( ((2 ** 32) / extsize) + 100 ))" What's the magic 2^32 here? > +seq 0 "${nr}" | tac | while read n; do seq ${nr} -1 0 | while read n; do > + off="$((n * extsize * blksz))" > + $XFS_IO_PROG -c "pwrite ${off} 1" "${loop_mount}/a" > /dev/null > +done > + > +echo "Reflink crazy huge file" > +cp --reflink=always "${loop_mount}/a" "${loop_mount}/b" > + > +echo "COW crazy huge file" > +# Try to create enough maximally sized cow reservations to overflow > +# i_delayed_blks > +seq 0 "${nr}" | tac | while read n; do > + off="$((n * extsize * blksz))" > + $XFS_IO_PROG -c "pwrite ${off} 1" "${loop_mount}/a" > /dev/null > +done > + > +echo "Check crazy huge file" > +blocks="$(stat -c '%b' "${loop_mount}/a")" > +fsblocks="$((blocks * statB / blksz))" > + > +# Make sure we got enough COW reservations to overflow a 32-bit counter. > +$XFS_IO_PROG -c 'bmap -clpv' "${loop_mount}/a" > $tmp.extents > +echo "COW EXTENT STATE" >> $seqres.full > +cat $tmp.extents >> $seqres.full > +cat > $tmp.awk << ENDL > +{ > + if (\$3 == "delalloc") { > + x += \$4; > + } else if (\$3 == "hole") { > + ; > + } else { > + x += \$6; > + } > +} > +END { > + printf("%d\\n", x / ($blksz / 512)); > +} > +ENDL Write that as a filter function and use tee to direct it to seqres.full and the filter function at the same time? > +cat $tmp.awk >> $seqres.full > +cowblocks="$(awk -f $tmp.awk $tmp.extents)" > +echo "cowblocks is ${cowblocks}" >> $seqres.full > +if [ "${cowblocks}" -lt "$((2 ** 32))" ]; then > + echo "cowblocks (${cowblocks}) should be more than 2^32!" > +fi > + > +# And finally, see if i_delayed_blks overflowed. > +echo "stat blocks is ${fsblocks}" >> $seqres.full > +if [ "${fsblocks}" -lt "$((2 ** 32))" ]; then > + echo "stat blocks (${fsblocks}) should be more than 2^32!" > + if [ "${cowblocks}" -lt "$((2 ** 32))" ]; then > + echo "cowblocks (${cowblocks}) is more than 2^32, your system has overflowed!!!" > + fi > +fi _within_tolerance? CHeers, Dave. -- Dave Chinner david@xxxxxxxxxxxxx