Skip to content

Commit b10ad23

Browse files
author
Dmitry Monakhov
committed
add generic/585
Quotasync may livelock if others tasks generate enough dirty dquots in parallel This test case pefrorm fchown to produce dirty quotas This test known to detect livelock non-journaled quota for kernels prior to v5.4
1 parent b2b1f60 commit b10ad23

File tree

5 files changed

+205
-1
lines changed

5 files changed

+205
-1
lines changed

src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
2828
attr-list-by-handle-cursor-test listxattr dio-interleaved t_dir_type \
2929
dio-invalidate-cache stat_test t_encrypted_d_revalidate \
3030
attr_replace_test swapon mkswap t_attr_corruption t_open_tmpfiles \
31-
fscrypt-crypt-util bulkstat_null_ocount
31+
fscrypt-crypt-util bulkstat_null_ocount chowner
3232

3333
SUBDIRS = log-writes perf
3434

src/chowner.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
//
3+
// Copyright (c) 2019 YANDEX LLC. All Rights Reserved.
4+
// Author: Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
5+
6+
#include <unistd.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <time.h>
10+
#include <sys/time.h>
11+
#include <fcntl.h>
12+
#include <limits.h>
13+
14+
char *progname;
15+
16+
void usage(void)
17+
{
18+
printf("Usage %s: [-b uid] [-e uid] [-g] [-P] [-t timeout] FNAME\n", progname);
19+
printf("\t\t -b: begin of uid range\n");
20+
printf("\t\t -e: length of uid range\n");
21+
printf("\t\t -g: change group uid\n");
22+
printf("\t\t -t: loop timeout\n");
23+
printf("\t\t -P: Do not run chowner loop, only prepare files\n");
24+
exit(1);
25+
}
26+
int main(int argc, char *const *argv)
27+
{
28+
char *filename;
29+
int fd;
30+
int c;
31+
uid_t begin = 2000;
32+
uid_t end = 12000;
33+
unsigned int timeout = 10;
34+
struct timeval start, now, delta = { 0, 0 };
35+
uid_t uid;
36+
gid_t gid = getegid();
37+
int do_group = 0;
38+
int do_prepare = 0;
39+
40+
progname = argv[0];
41+
while ((c = getopt(argc, argv, "b:e:gPt:")) != -1) {
42+
switch (c) {
43+
case 'b':
44+
begin = atoi(optarg);
45+
break;
46+
case 'e':
47+
end = atoi(optarg);
48+
break;
49+
case 'g':
50+
do_group = 1;
51+
break;
52+
case 'P':
53+
do_prepare = 1;
54+
break;
55+
case 't':
56+
timeout = atoi(optarg);
57+
break;
58+
default:
59+
usage();
60+
}
61+
}
62+
if (optind == argc-1)
63+
filename = argv[optind];
64+
else
65+
usage();
66+
if (do_prepare) {
67+
char path[PATH_MAX];
68+
for (uid = begin; uid < end;uid++) {
69+
sprintf(path, "%s.%d", filename, uid);
70+
fd = open(path, O_RDWR|O_CREAT, 0666);
71+
if (fd < 0) {
72+
perror("open");
73+
exit(1);
74+
}
75+
if (do_group)
76+
gid = uid;
77+
if (fchown(fd, uid, gid)) {
78+
perror("chown");
79+
exit(1);
80+
}
81+
close(fd);
82+
}
83+
return 0;
84+
}
85+
fd = open(filename, O_RDWR|O_CREAT, 0666);
86+
if (fd < 0) {
87+
perror("open");
88+
exit(1);
89+
}
90+
gettimeofday(&start, NULL);
91+
92+
while (1) {
93+
for (uid = begin; uid < end;uid++) {
94+
if (do_group)
95+
gid = uid;
96+
if (fchown(fd, uid, gid)) {
97+
perror("chown");
98+
exit(1);
99+
}
100+
}
101+
gettimeofday(&now, NULL);
102+
timersub(&now, &start, &delta);
103+
if (delta.tv_sec >= timeout)
104+
break;
105+
}
106+
return 0;
107+
}

tests/generic/585

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#! /bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
# Copyright (c) 2019 YANDEX LLC. All Rights Reserved.
4+
#
5+
# FS QA Test 585
6+
#
7+
# Check livelock during quota-sync while other tasks dirty quotas in parallel.
8+
# Run fchown(2) in a loop is the fastest way to produce dirty quotas
9+
#
10+
seq=`basename $0`
11+
seqres=$RESULT_DIR/$seq
12+
echo "QA output created by $seq"
13+
14+
here=`pwd`
15+
tmp=/tmp/$$
16+
status=1 # failure is the default!
17+
trap "_cleanup; exit \$status" 0 1 2 3 15
18+
19+
_cleanup()
20+
{
21+
cd /
22+
rm -f $tmp.*
23+
}
24+
# get standard environment, filters and checks
25+
. ./common/rc
26+
. ./common/filter
27+
. ./common/quota
28+
29+
30+
begin=2000
31+
end=10000
32+
nr_proc=$((16 * LOAD_FACTOR))
33+
deadline=$((100 * TIME_FACTOR))
34+
35+
_workout()
36+
{
37+
for ((i=0; i < nr_proc; i++))
38+
do
39+
# Spread files to isolated dirs to minimize locking contention
40+
mkdir -p $SCRATCH_MNT/chowner/$i
41+
$here/src/chowner $SCRATCH_MNT/chowner/$i/test -b $begin -e $end \
42+
-t $((deadline + 10)) &
43+
pids="$pids $!"
44+
done
45+
# Let chowners warm up ...
46+
sleep 5
47+
start=$(date +%s)
48+
for ((i=0;i<3;i++))
49+
do
50+
s=$(date +%s)
51+
# In normal situation command should finish in ~1sec,
52+
# but in case of livelock it will spin until chowners exits
53+
$*
54+
e=$(date +%s)
55+
echo "loop $i: $* runtime: $((e-s))" >> $seqres.full
56+
sleep 2
57+
done
58+
end=$(date +%s)
59+
runtime=$((end-start))
60+
echo "DONE: $* total runtime: $runtime" >> $seqres.full
61+
kill -TERM $pids 2> /dev/null
62+
wait $pids
63+
64+
[ $runtime -le $deadline ] || \
65+
_fail "Live lock detected, $* runtime: $runtime, deadline: $deadline"
66+
}
67+
68+
# real QA test starts here
69+
_supported_fs generic
70+
_supported_os Linux
71+
_require_quota
72+
#_require_user
73+
_require_scratch
74+
_require_command "$KILLALL_PROG" killall
75+
76+
rm -f $seqres.full
77+
_scratch_mkfs_sized $((512 * 1024 * 1024)) >> $seqres.full 2>&1
78+
_scratch_mount "-o quota,user"
79+
chmod 777 $SCRATCH_MNT
80+
quotacheck -u $SCRATCH_MNT 2>/dev/null
81+
quotaon -v -u $SCRATCH_MNT >> $seqres.full 2>&1
82+
83+
# Preparation step: Create all files with uid in range
84+
# to cache quota in kernel memory
85+
mkdir -p $SCRATCH_MNT/q
86+
$here/src/chowner $SCRATCH_MNT/q -b $begin -e $end -P
87+
88+
_workout quotasync $SCRATCH_MNT
89+
_workout sync
90+
91+
echo "Silence is golden"
92+
# success, all done
93+
status=0
94+
exit

tests/generic/585.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
QA output created by 585
2+
Silence is golden

tests/generic/group

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,3 +587,4 @@
587587
582 auto quick encrypt
588588
583 auto quick encrypt
589589
584 auto quick encrypt
590+
585 auto quota rw stress

0 commit comments

Comments
 (0)