On Wed, Nov 27, 2019 at 04:03:45PM +0800, Sun Yong wrote: > Hi Darrick, Eryu, > > Thank you so much for both of your review and helpful suggestions. > Some days before I had sent a > v4(https://patchwork.kernel.org/patch/11241473/) which solved wrap > issue, but no need to review that version in case there has some issue > to fix. I'll take all suggestions by Darrick in next version, or split > it into separate patches, and let you know when I finished. Oh, silly me, I didn't see the v3 and v4 attached to the v1 submission thread; I saw (in mutt threaded mode fwiw) that the v2 patch was the newest thread. When you send v5, could you please start it as a new thread? --D > Thanks, > Yong > > Darrick J. Wong <darrick.wong@xxxxxxxxxx> 于2019年11月27日周三 上午12:06写道: > > > > On Mon, Nov 04, 2019 at 03:30:55PM +0800, Sun Yong wrote: > > > Recently LTP upstream removed some ext4 tests[1]. And two of them is > > > still valid to keep. So I transport those two tests here. > > > > > > ext4-nsec-timestamps, which is used to test nanosec timestamps of > > > ext4, rewrite into ext4/043 and 044. > > > ext4-subdir-limit, which is used to test subdirectory limit of ext4, > > > rewrite into ext4/045. > > > > Might be a good idea to split these into separate patches... > > > > > [1] https://marc.info/?l=linux-fsdevel&m=157190623919681&w=2 > > > > > > Signed-off-by: Sun Yong <yosun@xxxxxxxx> > > > --- > > > v2: Correct copyright information > > > --- > > > diff --git a/src/Makefile b/src/Makefile > > > index ce6d8610..387293d1 100644 > > > --- a/src/Makefile > > > +++ b/src/Makefile > > > @@ -16,7 +16,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \ > > > holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd \ > > > t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \ > > > t_ext4_dax_journal_corruption t_ext4_dax_inline_corruption \ > > > - t_ofd_locks t_locks_execve t_mmap_collision mmap-write-concurrent > > > + t_ofd_locks t_locks_execve t_mmap_collision mmap-write-concurrent \ > > > + t_ext4_file_time t_create_short_dirs t_create_long_dirs > > > > > > LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \ > > > preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \ > > > diff --git a/src/t_create_long_dirs.c b/src/t_create_long_dirs.c > > > new file mode 100644 > > > index 00000000..76a886aa > > > --- /dev/null > > > +++ b/src/t_create_long_dirs.c > > > @@ -0,0 +1,155 @@ > > > +/******************************************************************************/ > > > +/* > > > */ > > > > Don't wrap, like Eryu asked. > > > > > +/* Copyright (c) 2009 FUJITSU LIMITED > > > */ > > > +/* > > > */ > > > +/* 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; either version 2 of the License, or > > > */ > > > +/* (at your option) any later version. > > > > SPDX headers instead of GPL boilerplate, please. > > > > > */ > > > +/* > > > */ > > > +/* This program is distributed in the hope that it will 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 to the Free Software > > > */ > > > +/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > > > 02110-1301 USA */ > > > +/* > > > */ > > > +/* Author: Li Zefan <lizf@xxxxxxxxxxxxxx> > > > */ > > > +/* > > > */ > > > +/******************************************************************************/ > > > + > > > +#define _POSIX_C_SOURCE 200809L > > > +#include <unistd.h> > > > +#include <stdlib.h> > > > +#include <stdio.h> > > > +#include <stdlib.h> > > > +#include <time.h> > > > +#include <fcntl.h> > > > +#include <sys/types.h> > > > +#include <sys/stat.h> > > > +#include "config.h" > > > + > > > +#define NAME_LEN 255 > > > +#define NCHARS 62 > > > +#define MAX_LEN1 62 > > > +#define MAX_LEN2 (62 * 62) > > > +#define MAX_LEN3 (62 * 62 * 62) > > > > 62? > > > > Oh, 26 + 26 + 10. > > > > > + > > > +/* valid characters for the directory name */ > > > +char chars[NCHARS + 1] = > > > + "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; > > > + > > > +/* to store the generated directory name */ > > > +char name[NAME_LEN + 1]; > > > +int names; > > > +int parent_fd; > > > + > > > +/* > > > + * init_name - initialize the directory name > > > + * > > > + * Generate a randomized directory name, and then we generate more > > > + * directory names based on it. > > > + */ > > > +void init_name(void) > > > +{ > > > + int i; > > > + > > > + srand(time(NULL)); > > > + > > > + for (i = 0; i < NAME_LEN; i++) > > > + name[i] = chars[rand() % 62]; > > > +} > > > + > > > +void create_dir(void) > > > +{ > > > + if (mkdirat(parent_fd, name, S_IRWXU)) { > > > + perror("mkdir"); > > > + exit(1); > > > + } > > > +} > > > + > > > +/* > > > + * create_dirs - create @names directory names > > > + * @n: how many names to be created > > > + * > > > + * if n <= 62, we need to modify 1 char of the name > > > + * if n <= 62*62, we need to modify 2 chars > > > + * if n <= 62*62*62, we need to modify 3 chars > > > + */ > > > +void create_dirs(int n) > > > +{ > > > + int i, j, k; > > > + int depth; > > > + > > > + if (n <= MAX_LEN1) > > > + depth = 1; > > > + else if (n <= MAX_LEN2) > > > + depth = 2; > > > + else > > > + depth = 3; > > > + > > > + for (i = 0; i < NCHARS; i++) { > > > + name[0] = chars[i]; > > > + if (depth == 1) { > > > + create_dir(); > > > + if (--n == 0) > > > + return; > > > + continue; > > > + } > > > + > > > + for (j = 0; j < NCHARS; j++) { > > > + name[1] = chars[j]; > > > + if (depth == 2) { > > > + create_dir(); > > > + if (--n == 0) > > > + return; > > > + continue; > > > + } > > > + > > > + for (k = 0; k < NCHARS; k++) { > > > + name[2] = chars[k]; > > > + create_dir(); > > > + if (--n == 0) > > > + return; > > > + } > > > + } > > > + } > > > +} > > > > I would've thought you could just do: > > > > for (i = 0; i < n; i++) { > > snprintf(name, sizeof(name) - 1, "%0*d", depth, n); > > mkdirat(dir, name, ...); > > } > > > > instead of this nested loopy thing, since the goal is to end up with a > > subdirectory containing somewhere between 1 and 238328 names in it, > > right? > > > > Unless there's some speedup that nested looping gets us? > > > > > + > > > +void usage() > > > +{ > > > + fprintf(stderr, "Usage: create_long_dirs nr_dirs parent_dir\n"); > > > +} > > > + > > > +/* > > > + * Create long-name directories > > > + * @argv[1]: directory number > > > + * @argv[2]: parent directory > > > + */ > > > +int main(int argc, char *argv[]) > > > +{ > > > + if (argc != 3) { > > > + usage(); > > > + return 1; > > > + } > > > + > > > + names = atoi(argv[1]); > > > + if (names > MAX_LEN3 || names <= 0) { > > > + usage(); > > > + return 1; > > > + } > > > + > > > + parent_fd = open(argv[2], O_RDONLY); > > > + if (parent_fd == -1) { > > > + perror("open parent dir failed"); > > > + return 1; > > > + } > > > + > > > + init_name(); > > > + > > > + create_dirs(names); > > > + > > > + return 0; > > > +} > > > diff --git a/src/t_create_short_dirs.c b/src/t_create_short_dirs.c > > > new file mode 100644 > > > index 00000000..c5733b9d > > > --- /dev/null > > > +++ b/src/t_create_short_dirs.c > > > @@ -0,0 +1,158 @@ > > > +/******************************************************************************/ > > > +/* > > > */ > > > +/* Copyright (c) 2009 FUJITSU LIMITED > > > */ > > > +/* > > > */ > > > +/* 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; either version 2 of the License, or > > > */ > > > +/* (at your option) any later version. > > > */ > > > +/* > > > */ > > > +/* This program is distributed in the hope that it will 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 to the Free Software > > > */ > > > +/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > > > 02110-1301 USA */ > > > +/* > > > */ > > > +/* Author: Li Zefan <lizf@xxxxxxxxxxxxxx> > > > */ > > > +/* > > > */ > > > +/******************************************************************************/ > > > + > > > +#define _POSIX_C_SOURCE 200809L > > > +#include <unistd.h> > > > +#include <stdlib.h> > > > +#include <stdio.h> > > > +#include <errno.h> > > > +#include <fcntl.h> > > > +#include <sys/stat.h> > > > +#include <sys/types.h> > > > +#include "config.h" > > > + > > > +/* valid characters for a directory name */ > > > +char chars[] = > > > "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; > > > + > > > +/* to store the generated directory name */ > > > +char name[10]; > > > +int names; > > > +int parent_fd; > > > + > > > +/* NCHARS = 10 + 26 + 26 = 62 */ > > > +#define NCHARS 62 > > > +#define MAX_LEN1 62 > > > +#define MAX_LEN2 (62 * 62) > > > +#define MAX_LEN3 (62 * 62 * 62) > > > +#define MAX_NAMES (MAX_LEN1 + MAX_LEN2 + MAX_LEN3) > > > + > > > +void create_dir(void) > > > +{ > > > + if (mkdirat(parent_fd, name, S_IRWXU)) { > > > + perror("mkdir"); > > > + exit(1); > > > + } > > > +} > > > + > > > +/* > > > + * create_1 - create length-1 directory names > > > + * @n: how name names to be created > > > + */ > > > +void create_1(int n) > > > +{ > > > + int i; > > > + > > > + name[1] = '\0'; > > > + for (i = 0; i < NCHARS; i++) { > > > + name[0] = chars[i]; > > > + create_dir(); > > > + if (--n == 0) > > > + return; > > > + } > > > +} > > > + > > > +/* > > > + * create_2 - generate length-2 directory names > > > + * @n: how many names to be created > > > + */ > > > +void create_2(int n) > > > +{ > > > + int i, j; > > > + > > > + name[2] = '\0'; > > > + for (i = 0; i < NCHARS; i++) { > > > + name[0] = chars[i]; > > > + for (j = 0; j < NCHARS; j++) { > > > + name[1] = chars[j]; > > > + create_dir(); > > > + if (--n == 0) > > > + return; > > > + } > > > + } > > > +} > > > + > > > +/* > > > + * create_3 - generate length-3 directory names > > > + * @n: how many names to be created > > > + */ > > > +void create_3(int n) > > > +{ > > > + int i, j, k; > > > + > > > + name[3] = '\0'; > > > + for (i = 0; i < NCHARS; i++) { > > > + name[0] = chars[i]; > > > + for (j = 0; j < NCHARS; j++) { > > > + name[1] = chars[j]; > > > + for (k = 0; k < NCHARS; k++) { > > > + name[2] = chars[k]; > > > + create_dir(); > > > + if (--n == 0) > > > + return; > > > + } > > > + } > > > + } > > > +} > > > + > > > +void usage() > > > +{ > > > + fprintf(stderr, "Usage: create_short_dirs nr_dirs parent_dir\n"); > > > +} > > > + > > > +/* > > > + * Create short-name directoriess > > > + * @argv[1]: director number > > > + * @argv[2]: the parent directory > > > + */ > > > +int main(int argc, char *argv[]) > > > > How does this program differ from the other one? > > > > > +{ > > > + if (argc != 3) { > > > + usage(); > > > + return 1; > > > + } > > > + > > > + names = atoi(argv[1]); > > > + if (names > MAX_NAMES || names <= 0) { > > > + usage(); > > > + return 1; > > > + } > > > + > > > + parent_fd = open(argv[2], O_RDONLY); > > > + if (parent_fd == -1) { > > > + perror("open parent dir"); > > > + return 1; > > > + } > > > + > > > + create_1(names); > > > + if (names <= MAX_LEN1) > > > + return 0; > > > + > > > + names -= MAX_LEN1; > > > + create_2(names); > > > + if (names <= MAX_LEN2) > > > + return 0; > > > + > > > + names -= MAX_LEN2; > > > + create_3(names); > > > + > > > + return 0; > > > +} > > > diff --git a/src/t_ext4_file_time.c b/src/t_ext4_file_time.c > > > new file mode 100644 > > > index 00000000..a10adb3d > > > --- /dev/null > > > +++ b/src/t_ext4_file_time.c > > > @@ -0,0 +1,69 @@ > > > +/******************************************************************************/ > > > +/* > > > */ > > > +/* Copyright (c) 2009 FUJITSU LIMITED > > > */ > > > +/* > > > */ > > > +/* 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; either version 2 of the License, or > > > */ > > > +/* (at your option) any later version. > > > */ > > > +/* > > > */ > > > +/* This program is distributed in the hope that it will 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 to the Free Software > > > */ > > > +/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > > > 02110-1301 USA */ > > > +/* > > > */ > > > +/* Author: Li Zefan <lizf@xxxxxxxxxxxxxx> > > > */ > > > +/* > > > */ > > > +/******************************************************************************/ > > > + > > > +#include <sys/types.h> > > > +#include <sys/stat.h> > > > +#include <unistd.h> > > > +#include <stdio.h> > > > +#include <string.h> > > > + > > > +/* > > > + * Usage: file_time <filename> <atime|mtime|ctime> <sec|nsec> > > > + */ > > > +int main(int argc, char *argv[]) > > > +{ > > > + time_t t; > > > > Is this program going to fail on 32-bit systems? > > > > > + struct stat st; > > > + > > > + if (argc != 4) { > > > + fprintf(stderr, "Wrong argument num!\n"); > > > + return 1; > > > + } > > > + > > > + if (stat(argv[1], &st) != 0) { > > > + perror("stat failed"); > > > + return 1; > > > + } > > > + > > > + if (strcmp(argv[3], "sec") == 0) { > > > + if (strcmp(argv[2], "atime") == 0) > > > + t = st.st_atime; > > > + else if (strcmp(argv[2], "mtime") == 0) > > > + t = st.st_mtime; > > > + else > > > + t = st.st_ctime; > > > + } else if (strcmp(argv[3], "nsec") == 0) { > > > + if (strcmp(argv[2], "atime") == 0) > > > + t = st.st_atim.tv_nsec; > > > + else if (strcmp(argv[2], "mtime") == 0) > > > + t = st.st_mtim.tv_nsec; > > > + else > > > + t = st.st_ctim.tv_nsec; > > > + } else { > > > + fprintf(stderr, "Wrong argument: %s\n", argv[3]); > > > + return 1; > > > + } > > > + > > > + printf("%lu\n", t); > > > + > > > + return 0; > > > +} > > > diff --git a/tests/ext4/043 b/tests/ext4/043 > > > new file mode 100755 > > > index 00000000..b6e5df9f > > > --- /dev/null > > > +++ b/tests/ext4/043 > > > @@ -0,0 +1,64 @@ > > > +#! /bin/bash > > > +# SPDX-License-Identifier: GPL-2.0 > > > +# Copyright (c) 2019 SUSE Linux Products GmbH. All Rights Reserved. > > > +# > > > +# FS QA Test No. 043 > > > +# > > > +# Transfer from ltp/testcases/kernel/fs/ext4-new-features/ext4_nsec_timestamps > > > +# Test file timestamps is second with 128 inode size > > > > (Huh?) > > > > OH, "Test file timestamps are only precise to seconds with 128-byte inodes." > > > > > +# > > > +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.* > > > + _scratch_cleanup_files > > > +} > > > + > > > +# 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 ext3 ext4 > > > +_supported_os Linux > > > + > > > +_require_scratch > > > +_require_test_program "t_ext4_file_time" > > > +_require_command "$TUNE2FS_PROG" tune2fs > > > + > > > +echo "Silence is golden" > > > + > > > +echo "Start test timestamps with 128 inode size one device > > > $SCRATCH_DEV" >$seqres.full > > > +_scratch_mkfs_ext4 -I 128 >> $seqres.full 2>&1 > > > +tune2fs -O extents $SCRATCH_DEV >>$seqres.full 2>&1 > > > > $TUNE2FS_PROG > > > > Also, why turn on extents? > > > > > +_scratch_mount > > > + > > > +touch "${SCRATCH_MNT}/tmp_file" > > > + > > > +atime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file atime nsec` > > > +mtime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file mtime nsec` > > > +ctime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file ctime nsec` > > > + > > > +if [ $atime -ne 0 -o $mtime -ne 0 -o $ctime -ne 0 ]; then > > > + echo "Timestamp is not second(atime: $atime, mtime: $mtime, > > > ctime: $ctime)" >> $seqres.full > > > > OH, this test checks for nonzero value in the nsec fields when ext4 > > doesn't support the extended timestamp fields. > > > > > + _scratch_unmount >> $seqres.full 2>&1 > > > > No need to unmount at the end of the test; fstests will do that for you. > > For that matter all you need here is: > > > > if [ $atime -ne 0 .... ]; then > > echo "nsec should be zero when extended timestamps are disabled" > > echo "atime: $atime..." > > fi > > > > Without any of the "_scratch_unmount" or "exit". If we fail the if test > > and emit the message, the change in golden output will be sufficient for > > fstests to mark the test failed. > > > > > + exit > > > +fi > > > +echo "Ext4 nanosecond timestamps test with 128 inode size pass" >> $seqres.full > > > +_scratch_unmount >> $seqres.full 2>&1 > > > + > > > +# no BUG_ON, all done > > > > BUG_ON? What are you talking about? Is there a fix commit that goes > > with this? > > > > Also, if this will crash recent kernels then this should be in the > > dangerous group, not auto. > > > > > +status=0 > > > +exit > > > diff --git a/tests/ext4/043.out b/tests/ext4/043.out > > > new file mode 100644 > > > index 00000000..f90f0a57 > > > --- /dev/null > > > +++ b/tests/ext4/043.out > > > @@ -0,0 +1,2 @@ > > > +QA output created by 043 > > > +Silence is golden > > > diff --git a/tests/ext4/044 b/tests/ext4/044 > > > new file mode 100755 > > > index 00000000..3e899f5a > > > --- /dev/null > > > +++ b/tests/ext4/044 > > > @@ -0,0 +1,112 @@ > > > +#! /bin/bash > > > +# SPDX-License-Identifier: GPL-2.0 > > > +# Copyright (c) 2019 SUSE Linux Products GmbH. All Rights Reserved. > > > +# > > > +# FS QA Test No. 044 > > > +# > > > +# Transfer from ltp/testcases/kernel/fs/ext4-new-features/ext4_nsec_timestamps > > > +# Test file timestamps is nanosecond with 256 inode size > > > > "Test file timestamps are precise to nanoseconds with 256-byte inodes." > > > > > +# > > > +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.* > > > + _scratch_cleanup_files > > > > Don't bother erasing the scratch fs files, the next _scratch_mkfs will > > do that for you. > > > > > +} > > > + > > > +# get standard environment, filters and checks > > > +. ./common/rc > > > +. ./common/filter > > > > I don't think we need filter here...? > > > > > + > > > +# remove previous $seqres.full before test > > > +rm -f $seqres.full > > > + > > > +# real QA test starts here > > > +_supported_fs ext3 ext4 > > > +_supported_os Linux > > > +_require_scratch > > > +_require_test_program "t_ext4_file_time" > > > + > > > +echo "Silence is golden" > > > + > > > +echo "Test timestamps with 256 inode size one device $SCRATCH_DEV" > > > >$seqres.full > > > +_scratch_mkfs_ext4 -t ext3 -I 256 >> $seqres.full 2>&1 > > > +_scratch_mount > > > + > > > +# Create file > > > +touch "${SCRATCH_MNT}/tmp_file" > > > +sleep 1 > > > + > > > +# Change atime, ctime and mtime of the file > > > +touch "${SCRATCH_MNT}/tmp_file" > > > + > > > +cur_time=`date '+%s %N'` > > > +sec=`echo $cur_time | awk {'print $1'}` > > > +nsec=`echo $cur_time | awk {'print $2'}` > > > + > > > +sec_atime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file atime sec` > > > +sec_mtime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file mtime sec` > > > +sec_ctime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file ctime sec` > > > +nsec_atime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file atime nsec` > > > +nsec_mtime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file mtime nsec` > > > +nsec_ctime=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file ctime nsec` > > > + > > > +# Test nanosecond > > > +if [ $nsec_atime -eq 0 -a $nsec_mtime -eq 0 -a $nsec_ctime -eq 0 ]; then > > > + echo "The timestamp is not nanosecond(nsec_atime: $nsec_atime, \ > > > + nsec_mtime: $nsec_mtime, nsec_ctime: $nsec_ctime)" >> > > > $seqres.full > > > + _scratch_unmount >> $seqres.full 2>&1 > > > + exit > > > +fi > > > + > > > +diff1=$(( $sec_atime - $sec )) > > > +diff2=$(( $sec_mtime - $sec )) > > > +diff3=$(( $sec_ctime - $sec )) > > > + > > > +# Test difference between file time and current time > > > +if [ $diff1 -gt 1 -o $diff2 -gt 1 -o $diff2 -gt 1 ]; then > > > + echo "The timestamp is wrong, it must be earlier than the > > > current time we got. \ > > > + (sec_atime: $sec_atime, sec_mtime: $sec_mtime, > > > sec_ctime: $sec_ctime, \ > > > + cur_time[s]: $sec)" >> $seqres.full > > > + _scratch_unmount >> $seqres.full 2>&1 > > > + exit > > > +fi > > > +_scratch_unmount >> $seqres.full 2>&1 > > > + > > > +# Test mount to ext3 and then mount back to ext4 > > > +mount -t ext3 $SCRATCH_DEV $SCRATCH_MNT > > > > Hm... what /is/ the rule about changing filesystem types? Do we just > > open-code _try_scratch_mount to force ext3 here? > > > > _mount -t ext3 `_scratch_mount_options $*` || _fail "ext3 mount failed" > > > > > +if [ $? -ne 0 ]; then > > > + echo "$SCRATCH_DEV fail in mounting to ext3" >> $seqres.full > > > + _scratch_unmount >> $seqres.full 2>&1 > > > + exit > > > +fi > > > +_scratch_unmount >> $seqres.full 2>&1 > > > +_scratch_mount > > > + > > > +nsec_atime2=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file atime nsec` > > > +nsec_mtime2=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file mtime nsec` > > > +nsec_ctime2=`$here/src/t_ext4_file_time $SCRATCH_MNT/tmp_file ctime nsec` > > > + > > > +if [ $nsec_atime -ne $nsec_atime2 -o $nsec_ctime -ne $nsec_ctime2 -o \ > > > + $nsec_mtime -ne $nsec_mtime2 ]; then > > > + echo "File nanosecond timestamp has changed \ > > > + unexpected. Before[atime mtime ctime]: $nsec_atime \ > > > + nsec_mtime $nsec_ctime, After[atime mtime ctime]: \ > > > + $nsec_atime2 $nsec_mtime2 $nsec_ctime2)" >> > > > $seqres.full > > > + _scratch_unmount >> $seqres.full 2>&1 > > > + exit > > > > If you really want to bail out early, do it with _fail, i.e. > > > > _fail "File nanosecond timestamp has changed..." > > > > Please consider doing all these checks individually, not in one huge if > > statement. > > > > > +fi > > > +_scratch_unmount >> $seqres.full 2>&1 > > > + > > > +# no BUG_ON, all done > > > +status=0 > > > +exit > > > diff --git a/tests/ext4/044.out b/tests/ext4/044.out > > > new file mode 100644 > > > index 00000000..12a61dc4 > > > --- /dev/null > > > +++ b/tests/ext4/044.out > > > @@ -0,0 +1,2 @@ > > > +QA output created by 044 > > > +Silence is golden > > > diff --git a/tests/ext4/045 b/tests/ext4/045 > > > new file mode 100755 > > > index 00000000..c70baa97 > > > --- /dev/null > > > +++ b/tests/ext4/045 > > > @@ -0,0 +1,148 @@ > > > +#! /bin/bash > > > +# SPDX-License-Identifier: GPL-2.0 > > > +# Copyright (c) 2019 SUSE Linux Products GmbH. All Rights Reserved. > > > +# > > > +# FS QA Test No. 045 > > > +# > > > +# Transfer from > > > ltp/testcases/kernel/fs/ext4-new-features/ext4_subdir_limit_test > > > +# > > > +# Test subdirectory limit of ext4. > > > +# We create more than 32000 subdirectorys on the ext4 filesystem. > > > > "subdirectories" > > > > > +# > > > +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 > > > + > > > +SHORT_DIR=1 > > > +LONG_DIR=2 > > > +FAIL=1 > > > +PASS=0 > > > +prev_block_size=0 > > > +prev_result=$FAIL > > > + > > > +_cleanup() > > > +{ > > > + cd / > > > + rm -f $tmp.* > > > + _scratch_cleanup_files > > > +} > > > + > > > +# 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 ext4 > > > +_supported_os Linux > > > + > > > +_require_scratch > > > +_require_test_program "t_create_short_dirs" > > > +_require_test_program "t_create_long_dirs" > > > +_require_command "$TUNE2FS_PROG" tune2fs > > > +_require_command "$E2FSCK_PROG" e2fsck > > > +_require_dumpe2fs > > > + > > > +echo "Silence is golden" > > > + > > > +# Run a test case > > > +# $1: Number of directories to create > > > +# $2: create short dir or long dir > > > +# $3: parent directory > > > +# $4: filesystem block size > > > +_workout() > > > > Local functions should not be prefixed with "_"; those are reserved for > > common/ library functions. > > > > > +{ > > > + local dir_name_len= > > > + if [ $2 -eq $SHORT_DIR ]; then > > > + dir_name_len="short name" > > > + else > > > + dir_name_len="long name" > > > + fi > > > + > > > + echo "Num of dirs to create: $1, Dir name len: $dir_name_len, " \ > > > + "Parent dir: $3, Block size: $4" >> $seqres.full 2>&1 > > > + > > > + # Only mkfs if block size has been changed, or previous case failed > > > + if [ $prev_result -ne $PASS -o $4 -ne $prev_block_size ]; then > > > + $MKFS_EXT4_PROG -F -b $4 -I 256 $SCRATCH_DEV >> $seqres.full 2>&1 > > > > _scratch_mkfs -b $4 -I 256 ? > > > > > + prev_block_size=$4 > > > + tune2fs -O extents $SCRATCH_DEV >> $seqres.full 2>&1 > > > > $TUNE2FS_PROG, do not call tune2fs directly. > > > > Also, why don't you just format the fs with extents turned on in the > > first place? > > > > > + fi > > > + prev_result=$FAIL > > > + > > > + _scratch_mount > > > + > > > + # create directories > > > + mkdir -p $3 2> /dev/null > > > + > > > + if [ $2 -eq $SHORT_DIR ]; then > > > + $here/src/t_create_short_dirs $1 $3 > > > + else > > > + $here/src/t_create_long_dirs $1 $3 > > > + fi > > > + > > > + if [ $? -ne 0 ]; then > > > + nr_dirs=`ls $3 | wc -l` > > > + echo "Failed to create directories - $nr_dirs" > > > + _scratch_unmount > > > + return > > > + fi > > > + > > > + # delete directories > > > + cd $3 > > > + ls | xargs rmdir > > > + if [ $? -ne 0 ]; then > > > + echo "Failed to remove directories in $3" > > > + cd - > /dev/null > > > + _scratch_unmount > > > + return > > > + fi > > > + cd - > /dev/null > > > + _scratch_unmount > > > + > > > + # check dir_nlink is set > > > + dumpe2fs $SCRATCH_DEV 2> /dev/null | grep '^Filesystem features' > > > > $DUMPE2FS_PROG > > > > > | grep -q dir_nlink > > > + if [ $? -ne 0 ]; then > > > + echo "Feature dir_nlink is not set, please check $seqres.full > > > for detail" > > > + return > > > + fi > > > + > > > + # run fsck to make sure the filesystem has no errors > > > + $E2FSCK_PROG -fy $SCRATCH_DEV >> $seqres.full 2>&1 > > > + if [ $? -ne 0 ]; then > > > + echo "fsck: the filesystem has errors, please check > > > $seqres.full for detail" > > > > _check_scratch_fs? > > > > > + return > > > + fi > > > + > > > + prev_result=$PASS > > > +} > > > + > > > +# main > > > +DIR_LEN=( $SHORT_DIR $LONG_DIR ) > > > +PARENT_DIR=( "$SCRATCH_MNT" "$SCRATCH_MNT/sub" ) > > > +BLOCK_SIZE=( 1024 2048 4096 ) > > > + > > > +for ((i = 0; i < 3; i++)); do > > > + for ((j = 0; j < 2; j++)); do > > > + for ((k = 0; k < 2; k++)); do > > > + if [ ${DIR_LEN[$k]} -eq $LONG_DIR -a \ > > > + ${BLOCK_SIZE[$i]} -eq 1024 ]; then > > > + continue > > > + fi > > > + _workout 65537 ${DIR_LEN[$k]} ${PARENT_DIR[$j]} ${BLOCK_SIZE[$i]} > > > + done > > > + done > > > +done > > > + > > > +_scratch_unmount >> $seqres.full 2>&1 > > > + > > > +# no BUG_ON, all done > > > +status=0 > > > +exit > > > diff --git a/tests/ext4/045.out b/tests/ext4/045.out > > > new file mode 100644 > > > index 00000000..66276cfa > > > --- /dev/null > > > +++ b/tests/ext4/045.out > > > @@ -0,0 +1,2 @@ > > > +QA output created by 045 > > > +Silence is golden > > > diff --git a/tests/ext4/group b/tests/ext4/group > > > index 9dfc0d35..8419cdea 100644 > > > --- a/tests/ext4/group > > > +++ b/tests/ext4/group > > > @@ -45,6 +45,9 @@ > > > 040 dangerous_fuzzers > > > 041 dangerous_fuzzers > > > 042 auto quick > > > +043 auto quick > > > +044 auto quick > > > +045 auto > > > > "dir" group too? > > > > --D > > > > > 271 auto rw quick > > > 301 aio auto ioctl rw stress defrag > > > 302 aio auto ioctl rw stress defrag