fstests: transport two ext4 tests from LTP

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.

[1] https://marc.info/?l=linux-fsdevel&m=157190623919681&w=2

Signed-off-by: Sun Yong <yosun@suse.com>
Reviewed-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
This commit is contained in:
Yong Sun
2020-02-27 18:35:07 +08:00
committed by Eryu Guan
parent 83e2828dcf
commit 54c62ab0d0
11 changed files with 601 additions and 0 deletions
+3
View File
@@ -119,6 +119,8 @@
/src/swapon /src/swapon
/src/t_access_root /src/t_access_root
/src/t_attr_corruption /src/t_attr_corruption
/src/t_create_long_dirs
/src/t_create_short_dirs
/src/t_dir_offset /src/t_dir_offset
/src/t_dir_offset2 /src/t_dir_offset2
/src/t_dir_type /src/t_dir_type
@@ -126,6 +128,7 @@
/src/t_ext4_dax_inline_corruption /src/t_ext4_dax_inline_corruption
/src/t_ext4_dax_journal_corruption /src/t_ext4_dax_journal_corruption
/src/t_futimens /src/t_futimens
/src/t_get_file_time
/src/t_getcwd /src/t_getcwd
/src/t_holes /src/t_holes
/src/t_immutable /src/t_immutable
+139
View File
@@ -0,0 +1,139 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2009 FUJITSU LIMITED
* Author: Li Zefan <lizf@cn.fujitsu.com>
*/
#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"
/* NCHARS = 10 + 26 + 26 = 62 */
#define NAME_LEN 255
#define NCHARS 62
#define MAX_LEN1 62
#define MAX_LEN2 (62 * 62)
#define MAX_LEN3 (62 * 62 * 62)
/* 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;
}
}
}
}
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;
}
+142
View File
@@ -0,0 +1,142 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2009 FUJITSU LIMITED
* Author: Li Zefan <lizf@cn.fujitsu.com>
*/
#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"
/* 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)
/* valid characters for a directory name */
char chars[] = "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
/* to store the generated directory name */
char name[10];
int names;
int parent_fd;
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[])
{
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 failed");
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;
}
+53
View File
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2009 FUJITSU LIMITED
* Author: Li Zefan <lizf@cn.fujitsu.com>
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
/*
* Usage: t_get_file_time <filename> <atime|mtime|ctime> <sec|nsec>
*/
int main(int argc, char *argv[])
{
time_t t;
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;
}
Executable
+56
View File
@@ -0,0 +1,56 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2020 SUSE Linux Products GmbH. All Rights Reserved.
#
# FS QA Test No. 043
#
# 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.*
}
# 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_get_file_time"
echo "Silence is golden"
echo "Start test timestamps with 128 inode size one device $SCRATCH_DEV" >$seqres.full
_scratch_mkfs -I 128 >> $seqres.full 2>&1
_scratch_mount
touch "${SCRATCH_MNT}/tmp_file"
atime=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file atime nsec`
mtime=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file mtime nsec`
ctime=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file ctime nsec`
if [ $atime -ne 0 -o $mtime -ne 0 -o $ctime -ne 0 ]; then
echo "nsec should be zero when extended timestamps are disabled"
echo "atime: $atime, mtime: $mtime, ctime: $ctime"
fi
status=0
exit
+2
View File
@@ -0,0 +1,2 @@
QA output created by 043
Silence is golden
Executable
+88
View File
@@ -0,0 +1,88 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2020 SUSE Linux Products GmbH. All Rights Reserved.
#
# FS QA Test No. 044
#
# 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.*
}
# 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_get_file_time"
echo "Silence is golden"
echo "Test timestamps with 256 inode size one device $SCRATCH_DEV" >$seqres.full
_scratch_mkfs -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_PROG {'print $1'}`
nsec=`echo $cur_time | $AWK_PROG {'print $2'}`
sec_atime=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file atime sec`
sec_mtime=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file mtime sec`
sec_ctime=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file ctime sec`
nsec_atime=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file atime nsec`
nsec_mtime=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file mtime nsec`
nsec_ctime=`$here/src/t_get_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, cur_time[ns]: $nsec)"
fi
# Check difference between file time and current time
_within_tolerance "sec_atime" $sec_atime $sec 1
_within_tolerance "sec_mtime" $sec_mtime $sec 1
_within_tolerance "sec_ctime" $sec_ctime $sec 1
_scratch_unmount >> $seqres.full 2>&1
# Test mount to ext3 then mount back to ext4 and check timestamp again
_mount -t ext3 `_scratch_mount_options $*` || _fail "ext3 mount failed"
_scratch_unmount >> $seqres.full 2>&1
_scratch_mount
nsec_atime2=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file atime nsec`
nsec_mtime2=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file mtime nsec`
nsec_ctime2=`$here/src/t_get_file_time $SCRATCH_MNT/tmp_file ctime nsec`
[ $nsec_atime -ne $nsec_atime2 ] && echo "File nanosecond timestamp atime has changed unexpected from $nsec_atime to $nsec_atime2"
[ $nsec_mtime -ne $nsec_mtime2 ] && echo "File nanosecond timestamp mtime has changed unexpected from $nsec_mtime to $nsec_mtime2"
[ $nsec_ctime -ne $nsec_ctime2 ] && echo "File nanosecond timestamp ctime has changed unexpected from $nsec_ctime to $nsec_ctime2"
status=0
exit
+2
View File
@@ -0,0 +1,2 @@
QA output created by 044
Silence is golden
Executable
+111
View File
@@ -0,0 +1,111 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2020 SUSE Linux Products GmbH. All Rights Reserved.
#
# FS QA Test No. 045
#
# Test subdirectory limit of ext4.
# We create more than 65000 subdirectories on the ext4 filesystem.
#
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
_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 ext4
_supported_os Linux
_require_scratch
_require_test_program "t_create_short_dirs"
_require_test_program "t_create_long_dirs"
_require_dumpe2fs "$DUMPE2FS_PROG" 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
workout()
{
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" >> $seqres.full
_scratch_mkfs "-O extent,dir_nlink,dir_index -I 256" >> $seqres.full 2>&1
_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_PROG -h $SCRATCH_DEV 2>> $seqres.full | grep '^Filesystem features' | grep -q dir_nlink
if [ $? -ne 0 ]; then
echo "Feature dir_nlink is not set, please check $seqres.full for detail"
return
fi
}
# main
DIR_NUM=65537
DIR_LEN=( $SHORT_DIR $LONG_DIR )
PARENT_DIR="$SCRATCH_MNT/subdir"
for ((i = 0; i < 2; i++)); do
workout $DIR_NUM ${DIR_LEN[$i]} $PARENT_DIR
done
status=0
exit
+2
View File
@@ -0,0 +1,2 @@
QA output created by 045
Silence is golden
+3
View File
@@ -44,6 +44,9 @@
040 dangerous_fuzzers 040 dangerous_fuzzers
041 dangerous_fuzzers 041 dangerous_fuzzers
042 auto quick 042 auto quick
043 auto quick
044 auto quick
045 auto dir
271 auto rw quick 271 auto rw quick
301 aio auto ioctl rw stress defrag 301 aio auto ioctl rw stress defrag
302 aio auto ioctl rw stress defrag 302 aio auto ioctl rw stress defrag