mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
xfstests 240: test non-aligned AIO hole-filling
This replicates file corruption we've seen with qemu-kvm when we use if=virtio,cache=none,aio=native for IO to a sparse ext4- or xfs-hosted file, and the partitions/filesystems within that file image are not block-aligned. (think sector 63 here...) This results in AIO IOs not aligned to the filesystem blocks. This test modifies aiodio_sparse2.c to add an option to start the file IO at an offset. When we do 4k writes to a 16k file in 2 threads, starting at offset 512, we get 0s interspersed in the file where they should not be: 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000200 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................| * 00001000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00001200 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................| .... Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Reviewed-by: Dave Chinner <dchinner@redhat.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
#! /bin/bash
|
||||
# FS QA Test No. 240
|
||||
#
|
||||
# Test that non-block-aligned aio+dio into holes does not leave
|
||||
# zero'd out portions of the file
|
||||
#
|
||||
# QEMU IO to a file-backed device with misaligned partitions
|
||||
# can send this sort of IO
|
||||
#
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright (c) 2010 Red Hat, Inc. All Rights Reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it would be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#-----------------------------------------------------------------------
|
||||
#
|
||||
# creator
|
||||
owner=sandeen@sandeen.net
|
||||
|
||||
seq=`basename $0`
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here=`pwd`
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
cd /
|
||||
rm -f $tmp.*
|
||||
}
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fs generic
|
||||
_supported_os Linux
|
||||
|
||||
echo "Silence is golden."
|
||||
|
||||
# real QA test starts here
|
||||
rm -f $seq.full
|
||||
|
||||
rm -f $TEST_DIR/aiodio_sparse
|
||||
|
||||
# 2 threads, 4k writes, 16k filesize, stride throug file by 4k, start at 512 offset
|
||||
$here/src/aio-dio-regress/aiodio_sparse2 -i 2 -w 4k -s 16k -n 4k -o 512 "$TEST_DIR/aiodio_sparse"
|
||||
|
||||
status=$?
|
||||
exit
|
||||
@@ -353,3 +353,4 @@ deprecated
|
||||
237 auto quick acl
|
||||
238 auto quick metadata ioctl
|
||||
239 auto aio rw
|
||||
240 auto aio quick rw
|
||||
|
||||
@@ -66,7 +66,8 @@ sig_term_func(int i, siginfo_t *si, void *p)
|
||||
/*
|
||||
* do async DIO writes to a sparse file
|
||||
*/
|
||||
void aiodio_sparse(char *filename, int align, int writesize, int filesize, int num_aio, int step, int sparse, int direct, int keep)
|
||||
void aiodio_sparse(char *filename, int align, int writesize, int startoffset, int filesize,
|
||||
int num_aio, int step, int sparse, int direct, int keep)
|
||||
{
|
||||
int fd;
|
||||
void *bufptr;
|
||||
@@ -110,7 +111,7 @@ void aiodio_sparse(char *filename, int align, int writesize, int filesize, int n
|
||||
/*
|
||||
* allocate the iocbs array and iocbs with buffers
|
||||
*/
|
||||
offset = 0;
|
||||
offset = startoffset;
|
||||
for (i = 0; i < num_aio; i++) {
|
||||
void *bufptr;
|
||||
|
||||
@@ -220,9 +221,11 @@ void aiodio_sparse(char *filename, int align, int writesize, int filesize, int n
|
||||
exit(1);
|
||||
|
||||
bufptr = malloc(writesize);
|
||||
for (offset = 0; offset < filesize; offset += step) {
|
||||
for (offset = startoffset; offset < filesize; offset += step) {
|
||||
unsigned char *badbuf;
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr, "seek to %ld and read %d\n", offset, writesize);
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
if (read(fd, bufptr, writesize) < writesize) {
|
||||
fprintf(stderr, "short read() at offset %lld\n",
|
||||
@@ -274,7 +277,7 @@ void dirty_freeblocks(char *filename, int size)
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr, "usage: dio_sparse [-n step] [-s filesize]"
|
||||
" [-w writesize] [-r readsize] filename\n");
|
||||
" [-w writesize] [-o startoffset] [-r readsize] filename\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -305,7 +308,7 @@ long long scale_by_kmg(long long value, char scale)
|
||||
|
||||
/*
|
||||
* usage:
|
||||
* aiodio_sparse [-r readsize] [-w writesize] [-n step] [-a align] [-i num_aio] filename
|
||||
* aiodio_sparse [-r readsize] [-w writesize] [-o startoffset] [-n step] [-a align] [-i num_aio] filename
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@@ -314,6 +317,7 @@ int main(int argc, char **argv)
|
||||
long alignment = 512;
|
||||
int readsize = 65536;
|
||||
int writesize = 65536;
|
||||
int startoffset = 0;
|
||||
int filesize = 100*1024*1024;
|
||||
int num_aio = 16;
|
||||
int step = 5*1024*1024;
|
||||
@@ -321,7 +325,7 @@ int main(int argc, char **argv)
|
||||
extern char *optarg;
|
||||
extern int optind, optopt, opterr;
|
||||
|
||||
while ((c = getopt(argc, argv, "dr:w:n:a:s:i:DkS")) != -1) {
|
||||
while ((c = getopt(argc, argv, "dr:w:n:o:a:s:i:DkS")) != -1) {
|
||||
char *endp;
|
||||
switch (c) {
|
||||
case 'D':
|
||||
@@ -360,6 +364,10 @@ int main(int argc, char **argv)
|
||||
step = strtol(optarg, &endp, 0);
|
||||
step = (int)scale_by_kmg((long long)step, *endp);
|
||||
break;
|
||||
case 'o':
|
||||
startoffset = strtol(optarg, &endp, 0);
|
||||
startoffset = (int)scale_by_kmg((long long)startoffset, *endp);
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
break;
|
||||
@@ -378,7 +386,7 @@ int main(int argc, char **argv)
|
||||
* Parent write to a hole in a file using async direct i/o
|
||||
*/
|
||||
|
||||
aiodio_sparse(filename, alignment, writesize, filesize, num_aio, step, sparse, direct, keep);
|
||||
aiodio_sparse(filename, alignment, writesize, startoffset, filesize, num_aio, step, sparse, direct, keep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user