mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
generic: mmap and copy file data with page overlapping
Mmap 2 pages of file, write 64 bytes to the first and second pages,
copy the data from the first page and then second page to the second
page offset with $pagesize - 64. Verify the data at the end.
+-----------------------+
| (copy) |
| V
+---------------+---------------+------------
|AAAA| ........ |AAAA| ... |AAAA|AAAA|
+---------------+---------------+------------
| ^
| (copy) |
+------------+
This's also a regression test cover kernel commit: 4f06dd92b5d0
("fuse: fix write deadlock")
Signed-off-by: Zorro Lang <zlang@redhat.com>
Reviewed-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
This commit is contained in:
@@ -142,6 +142,7 @@
|
|||||||
/src/t_mmap_stale_pmd
|
/src/t_mmap_stale_pmd
|
||||||
/src/t_mmap_write_ro
|
/src/t_mmap_write_ro
|
||||||
/src/t_mmap_writev
|
/src/t_mmap_writev
|
||||||
|
/src/t_mmap_writev_overlap
|
||||||
/src/t_mtab
|
/src/t_mtab
|
||||||
/src/t_ofd_locks
|
/src/t_ofd_locks
|
||||||
/src/t_open_tmpfiles
|
/src/t_open_tmpfiles
|
||||||
|
|||||||
+2
-1
@@ -17,7 +17,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
|
|||||||
t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
|
t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
|
||||||
t_ext4_dax_journal_corruption t_ext4_dax_inline_corruption \
|
t_ext4_dax_journal_corruption t_ext4_dax_inline_corruption \
|
||||||
t_ofd_locks t_mmap_collision mmap-write-concurrent \
|
t_ofd_locks t_mmap_collision mmap-write-concurrent \
|
||||||
t_get_file_time t_create_short_dirs t_create_long_dirs t_enospc
|
t_get_file_time t_create_short_dirs t_create_long_dirs t_enospc \
|
||||||
|
t_mmap_writev_overlap
|
||||||
|
|
||||||
LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
|
LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
|
||||||
preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
|
preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 RedHat Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* mmap a file, alloc blocks, reading&writing blocks with overlapping. For example:
|
||||||
|
*
|
||||||
|
* |<--- block --->|<--- block --->|
|
||||||
|
* len len
|
||||||
|
* +---------------+---------------+
|
||||||
|
* |AAAA| ........ |AAAA| ........ |
|
||||||
|
* +---------------+---------------+
|
||||||
|
* | |
|
||||||
|
* | `------------+
|
||||||
|
* `-----------------------+ |
|
||||||
|
* | |
|
||||||
|
* V V
|
||||||
|
* +---------------+---------------+----+
|
||||||
|
* |AAAA| ........ |AAAA| ... |AAAA|AAAA|
|
||||||
|
* +---------------+---------------+----+
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void usage(char *progname)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [-b blocksize ] [-c count] [-l length] filename\n"
|
||||||
|
"\tmmap $count * $blocksize bytes memory, pwritev $length bytes in each block. blocksize=4096, count=2, length=12 by default.\n"
|
||||||
|
"e.g: %s -b 4096 -c 2 -l 12 filename\n",
|
||||||
|
progname, progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *filename = NULL;
|
||||||
|
size_t bsize = 4096;
|
||||||
|
size_t count = 2;
|
||||||
|
size_t length = 12;
|
||||||
|
int fd, i, c;
|
||||||
|
void *base;
|
||||||
|
char *buf, *cmp_buf;
|
||||||
|
struct iovec *iov;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while ((c = getopt(argc, argv, "b:l:c:")) != -1) {
|
||||||
|
char *endp;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'b':
|
||||||
|
bsize = strtoul(optarg, &endp, 0);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
count = strtoul(optarg, &endp, 0);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
length = strtoul(optarg, &endp, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind == argc - 1)
|
||||||
|
filename = argv[optind];
|
||||||
|
else
|
||||||
|
usage(argv[0]);
|
||||||
|
|
||||||
|
if (length >= bsize) {
|
||||||
|
printf("-l length must be less than -b blocksize\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(filename, O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
fprintf(stderr, "open %s failed:%s\n", filename, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
base = mmap(NULL, bsize * count, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (base == MAP_FAILED) {
|
||||||
|
fprintf(stderr, "mmap failed %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write each of blocks */
|
||||||
|
buf = malloc(length);
|
||||||
|
memset(buf, 0xAA, length);
|
||||||
|
for (i=0; i<count; i++) {
|
||||||
|
ret = pwrite(fd, buf, length, i * bsize);
|
||||||
|
if (ret == -1) {
|
||||||
|
fprintf(stderr, "pwrite failed %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy from the beginning of each blocks ... */
|
||||||
|
iov = malloc(sizeof(struct iovec) * count);
|
||||||
|
for (i=0; i<count; i++) {
|
||||||
|
iov[i].iov_base = base + i * bsize;
|
||||||
|
iov[i].iov_len = length;
|
||||||
|
}
|
||||||
|
/* ... Write to the last block with offset ($bsize - $length) */
|
||||||
|
ret = pwritev(fd, iov, count, bsize * count - length);
|
||||||
|
if (ret == -1) {
|
||||||
|
fprintf(stderr, "pwritev failed %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify data */
|
||||||
|
cmp_buf = malloc(length);
|
||||||
|
for (i=0; i<count; i++) {
|
||||||
|
ret = pread(fd, cmp_buf, length, bsize * count + (i - 1) * length);
|
||||||
|
if (ret == -1) {
|
||||||
|
fprintf(stderr, "pread failed %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (memcmp(buf, cmp_buf, length))
|
||||||
|
printf("Find corruption\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap(base, bsize * count);
|
||||||
|
free(buf);
|
||||||
|
free(cmp_buf);
|
||||||
|
free(iov);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Executable
+57
@@ -0,0 +1,57 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# Copyright (c) 2021 Red Hat Inc. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# FS QA Test 638
|
||||||
|
#
|
||||||
|
# This case mmaps several pages of a file, alloc pages, copy data with pages
|
||||||
|
# overlapping, e.g:
|
||||||
|
# +-----------------------+
|
||||||
|
# | (copy) |
|
||||||
|
# | V
|
||||||
|
# +---------------+---------------+------------
|
||||||
|
# |AAAA| ........ |AAAA| ... |AAAA|AAAA|
|
||||||
|
# +---------------+---------------+------------
|
||||||
|
# | ^
|
||||||
|
# | (copy) |
|
||||||
|
# +------------+
|
||||||
|
#
|
||||||
|
# This's a regression test cover kernel commit:
|
||||||
|
# 4f06dd92b5d0 ("fuse: fix write deadlock")
|
||||||
|
#
|
||||||
|
seq=`basename $0`
|
||||||
|
seqres=$RESULT_DIR/$seq
|
||||||
|
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
|
||||||
|
|
||||||
|
# remove previous $seqres.full before test
|
||||||
|
rm -f $seqres.full
|
||||||
|
|
||||||
|
# real QA test starts here
|
||||||
|
_supported_fs generic
|
||||||
|
_require_test
|
||||||
|
_require_test_program "t_mmap_writev_overlap"
|
||||||
|
|
||||||
|
pagesize=`getconf PAGE_SIZE`
|
||||||
|
testfile=$TEST_DIR/mmap-writev-overlap
|
||||||
|
$XFS_IO_PROG -f -c "truncate 0" $testfile
|
||||||
|
$here/src/t_mmap_writev_overlap -b $pagesize -c 2 -l 64 $testfile
|
||||||
|
|
||||||
|
echo "Silence is golden"
|
||||||
|
# success, all done
|
||||||
|
status=0
|
||||||
|
exit
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
QA output created by 638
|
||||||
|
Silence is golden
|
||||||
@@ -640,3 +640,4 @@
|
|||||||
635 auto quick atime bigtime shutdown
|
635 auto quick atime bigtime shutdown
|
||||||
636 auto quick swap
|
636 auto quick swap
|
||||||
637 auto quick dir
|
637 auto quick dir
|
||||||
|
638 auto quick rw
|
||||||
|
|||||||
Reference in New Issue
Block a user