Re: [PATCH] generic/441: Another SEEK_HOLE/SEEK_DATA sanity test

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]



On Fri, Jun 23, 2017 at 12:28:59PM +0200, Andreas Gruenbacher wrote:
> On Fri, Jun 23, 2017 at 10:40 AM, Eryu Guan <eguan@xxxxxxxxxx> wrote:
> > On Fri, Jun 23, 2017 at 02:11:16AM +0200, Andreas Gruenbacher wrote:
> >> Both ext4 and xfs have a bug in the page cache scanning code for
> >> SEEK_HOLE / SEEK_DATA in unwritten extents: the start offset isn't taken
> >> into account when scanning a page, so seeking can fail on filesystems
> >> with a block size less than half of the page size.  For example, the
> >> following command fails on a filesystem with a block size of 1k:
> >>
> >>   xfs_io -f -c "falloc 0 4k" \
> >>             -c "pwrite 1k 1k" \
> >>             -c "pwrite 3k 1k" \
> >>             -c "seek -a -r 0" foo
> >>
> >> Like with generic/436, the actual tests are added to seek_sanity_test.
> >>
> >> Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx>
> >> ---
> >>  src/seek_sanity_test.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  tests/generic/441      | 64 +++++++++++++++++++++++++++++++++++++++++++
> >>  tests/generic/441.out  |  2 ++
> >>  tests/generic/group    |  1 +
> >>  4 files changed, 140 insertions(+)
> >>  create mode 100755 tests/generic/441
> >>  create mode 100644 tests/generic/441.out
> >>
> >> diff --git a/src/seek_sanity_test.c b/src/seek_sanity_test.c
> >> index c9e9366..bf323f2 100644
> >> --- a/src/seek_sanity_test.c
> >> +++ b/src/seek_sanity_test.c
> >> @@ -277,6 +277,78 @@ out:
> >>       return ret;
> >>  }
> >>
> >> +static int test17(int fd, int testnum)
> >> +{
> >> +     char *buf = NULL;
> >> +     int pagesz = sysconf(_SC_PAGE_SIZE);
> >> +     int bufsz, filsz;
> >> +     int ret = 0;
> >> +
> >> +     if (!unwritten_extents) {
> >> +             fprintf(stdout, "Test skipped\n");
> >> +             goto out;
> >> +     }
> >
> > Currently 'unwritten_extents' is not defined. I know it's from patch
> > "src/seek_sanity_test: Fix for filesystems without unwritten extent
> > support"[1] back in May, but I haven't merged it, because it used
> > SEEK_DATA to check if fs supports unwritten extent and I think it's hard
> > to tell if it's a SEEK_DATA bug or if fs really doesn't support
> > unwritten extent. We're testing SEEK_DATA/SEEK_HOLE interface in this
> > test, probably we shouldn't rely on it to setup the test.
> 
> seek_sanity_test also checks for SEEK_HOLE/SEEK_DATA support, so it's
> not a new concept to check for something in the most basic form and
> then test that feature more thoroughly.

OK.

> 
> > But again, if there're better ways to do the detection, please kindly
> > advise.
> >
> > Otherwise this test looks fine to me.
> 
> Ok, can you merge without the unwritten_extents?

I've queued all your three patches for next update, thanks!

Eryu

> 
> Thanks,
> Andreas
> 
> > Thanks,
> > Eryu
> >
> > [1] https://www.spinics.net/lists/fstests/msg06223.html
> >
> >> +
> >> +     if (pagesz < 4 * alloc_size) {
> >> +             fprintf(stdout, "Test skipped as page size (%d) is less than "
> >> +                     "four times allocation size (%d).\n",
> >> +                     pagesz, (int)alloc_size);
> >> +             goto out;
> >> +     }
> >> +     bufsz = alloc_size;
> >> +     filsz = 3 * bufsz;
> >> +
> >> +     buf = do_malloc(bufsz);
> >> +     if (!buf) {
> >> +             ret = -1;
> >> +             goto out;
> >> +     }
> >> +     memset(buf, 'a', bufsz);
> >> +
> >> +     ret = do_fallocate(fd, 0, filsz, 0);
> >> +     if (ret < 0) {
> >> +             /* Report success if fs doesn't support fallocate */
> >> +             if (errno == EOPNOTSUPP) {
> >> +                     fprintf(stdout, "Test skipped as fs doesn't support fallocate.\n");
> >> +                     ret = 0;
> >> +             }
> >> +             goto out;
> >> +     }
> >> +
> >> +     ret = do_pwrite(fd, buf, bufsz, 0);
> >> +     if (ret)
> >> +             goto out;
> >> +
> >> +     ret = do_pwrite(fd, buf, bufsz, 2 * bufsz);
> >> +     if (ret)
> >> +             goto out;
> >> +
> >> +     ret += do_lseek(testnum,  1, fd, filsz, SEEK_DATA, 0, 0);
> >> +     ret += do_lseek(testnum,  2, fd, filsz, SEEK_HOLE, 0, bufsz);
> >> +     ret += do_lseek(testnum,  3, fd, filsz, SEEK_DATA, 1, 1);
> >> +     ret += do_lseek(testnum,  4, fd, filsz, SEEK_HOLE, 1, bufsz);
> >> +     ret += do_lseek(testnum,  5, fd, filsz, SEEK_DATA, bufsz, 2 * bufsz);
> >> +     ret += do_lseek(testnum,  6, fd, filsz, SEEK_HOLE, bufsz, bufsz);
> >> +     ret += do_lseek(testnum,  7, fd, filsz, SEEK_DATA, bufsz + 1, 2 * bufsz);
> >> +     ret += do_lseek(testnum,  8, fd, filsz, SEEK_HOLE, bufsz + 1, bufsz + 1);
> >> +     ret += do_lseek(testnum,  9, fd, filsz, SEEK_DATA, 2 * bufsz, 2 * bufsz);
> >> +     ret += do_lseek(testnum, 10, fd, filsz, SEEK_HOLE, 2 * bufsz, 3 * bufsz);
> >> +     ret += do_lseek(testnum, 11, fd, filsz, SEEK_DATA, 2 * bufsz + 1, 2 * bufsz + 1);
> >> +     ret += do_lseek(testnum, 12, fd, filsz, SEEK_HOLE, 2 * bufsz + 1, 3 * bufsz);
> >> +
> >> +     filsz += bufsz;
> >> +     ret += do_fallocate(fd, 0, filsz, 0);
> >> +
> >> +     ret += do_lseek(testnum, 13, fd, filsz, SEEK_DATA, 3 * bufsz, -1);
> >> +     ret += do_lseek(testnum, 14, fd, filsz, SEEK_HOLE, 3 * bufsz, 3 * bufsz);
> >> +     ret += do_lseek(testnum, 15, fd, filsz, SEEK_DATA, 3 * bufsz + 1, -1);
> >> +     ret += do_lseek(testnum, 16, fd, filsz, SEEK_HOLE, 3 * bufsz + 1, 3 * bufsz + 1);
> >> +
> >> +out:
> >> +     do_free(buf);
> >> +     return ret;
> >> +}
> >> +
> >>  /*
> >>   * test file with unwritten extents, having non-contiguous dirty pages in
> >>   * the unwritten extent.
> >> @@ -912,6 +984,7 @@ struct testrec seek_tests[] = {
> >>         { 14, test14, "Test file with unwritten extents, small hole after pagevec dirty pages" },
> >>         { 15, test15, "Test file with unwritten extents, page after unwritten extent" },
> >>         { 16, test16, "Test file with unwritten extents, non-contiguous dirty pages" },
> >> +       { 17, test17, "Test file with unwritten extents, data-hole-data inside page" },
> >>  };
> >>
> >>  static int run_test(struct testrec *tr)
> >> diff --git a/tests/generic/441 b/tests/generic/441
> >> new file mode 100755
> >> index 0000000..295ccf4
> >> --- /dev/null
> >> +++ b/tests/generic/441
> >> @@ -0,0 +1,64 @@
> >> +#! /bin/bash
> >> +# FS QA Test 441
> >> +#
> >> +# Another SEEK_DATA/SEEK_HOLE sanity test.
> >> +#
> >> +#-----------------------------------------------------------------------
> >> +# Copyright (c) 2017 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
> >> +#-----------------------------------------------------------------------
> >> +#
> >> +
> >> +seq=`basename $0`
> >> +seqres=$RESULT_DIR/$seq
> >> +echo "QA output created by $seq"
> >> +
> >> +here=`pwd`
> >> +tmp=$$
> >> +status=1     # failure is the default!
> >> +trap "_cleanup; exit \$status" 0 1 2 3 15
> >> +
> >> +# get standard environment, filters and checks
> >> +. ./common/rc
> >> +. ./common/filter
> >> +
> >> +_supported_fs generic
> >> +_supported_os Linux
> >> +
> >> +_require_test
> >> +_require_seek_data_hole
> >> +
> >> +BASE_TEST_FILE=$TEST_DIR/seek_sanity_testfile
> >> +
> >> +_require_test_program "seek_sanity_test"
> >> +
> >> +# Disable extent zeroing for ext4 as that change where holes are created
> >> +if [ "$FSTYP" = "ext4" ]; then
> >> +     DEV=`_short_dev $TEST_DEV`
> >> +     echo 0 >/sys/fs/ext4/$DEV/extent_max_zeroout_kb
> >> +fi
> >> +
> >> +_cleanup()
> >> +{
> >> +     rm -f $tmp.* $BASE_TEST_FILE.*
> >> +}
> >> +
> >> +$here/src/seek_sanity_test -s 17 -e 17 $BASE_TEST_FILE > $seqres.full 2>&1 ||
> >> +     _fail "seek sanity check failed!"
> >> +
> >> +# success, all done
> >> +echo "Silence is golden"
> >> +status=0
> >> +exit
> >> diff --git a/tests/generic/441.out b/tests/generic/441.out
> >> new file mode 100644
> >> index 0000000..842f9c4
> >> --- /dev/null
> >> +++ b/tests/generic/441.out
> >> @@ -0,0 +1,2 @@
> >> +QA output created by 441
> >> +Silence is golden
> >> diff --git a/tests/generic/group b/tests/generic/group
> >> index ab1e9d3..5046c97 100644
> >> --- a/tests/generic/group
> >> +++ b/tests/generic/group
> >> @@ -443,3 +443,4 @@
> >>  438 auto
> >>  439 auto quick punch
> >>  440 auto quick encrypt
> >> +441 auto quick rw
> >> --
> >> 2.7.5
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe fstests" in
> >> the body of a message to majordomo@xxxxxxxxxxxxxxx
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe fstests" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux