mirror of
https://github.com/versity/scoutfs.git
synced 2026-06-09 21:22:36 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| affb91e3d8 |
+10
-18
@@ -980,7 +980,7 @@ static bool lock_flags_invalid(int flags)
|
||||
*/
|
||||
static int lock_key_range(struct super_block *sb, enum scoutfs_lock_mode mode, int flags,
|
||||
struct scoutfs_key *start, struct scoutfs_key *end,
|
||||
u64 ino, struct scoutfs_lock **ret_lock)
|
||||
struct scoutfs_lock **ret_lock)
|
||||
{
|
||||
DECLARE_LOCK_INFO(sb, linfo);
|
||||
struct scoutfs_lock *lock;
|
||||
@@ -1028,8 +1028,6 @@ static int lock_key_range(struct super_block *sb, enum scoutfs_lock_mode mode, i
|
||||
/* the fast path where we can use the granted mode */
|
||||
if (lock_modes_match(lock->mode, mode)) {
|
||||
lock_inc_count(lock->users, mode);
|
||||
lock->last_user_pid[mode] = task_pid_nr(current);
|
||||
lock->last_user_ino[mode] = ino;
|
||||
*ret_lock = lock;
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -1110,7 +1108,7 @@ int scoutfs_lock_ino(struct super_block *sb, enum scoutfs_lock_mode mode, int fl
|
||||
end.sk_zone = SCOUTFS_FS_ZONE;
|
||||
end.ski_ino = cpu_to_le64(ino | SCOUTFS_LOCK_INODE_GROUP_MASK);
|
||||
|
||||
return lock_key_range(sb, mode, flags, &start, &end, ino, ret_lock);
|
||||
return lock_key_range(sb, mode, flags, &start, &end, ret_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1240,7 +1238,7 @@ int scoutfs_lock_rename(struct super_block *sb, enum scoutfs_lock_mode mode, int
|
||||
.sk_type = SCOUTFS_RENAME_TYPE,
|
||||
};
|
||||
|
||||
return lock_key_range(sb, mode, flags, &key, &key, 0, lock);
|
||||
return lock_key_range(sb, mode, flags, &key, &key, lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1288,7 +1286,7 @@ int scoutfs_lock_inode_index(struct super_block *sb, enum scoutfs_lock_mode mode
|
||||
|
||||
scoutfs_lock_get_index_item_range(type, major, ino, &start, &end);
|
||||
|
||||
return lock_key_range(sb, mode, 0, &start, &end, ino, ret_lock);
|
||||
return lock_key_range(sb, mode, 0, &start, &end, ret_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1315,7 +1313,7 @@ int scoutfs_lock_orphan(struct super_block *sb, enum scoutfs_lock_mode mode, int
|
||||
end.sko_ino = cpu_to_le64(U64_MAX);
|
||||
end.sk_type = SCOUTFS_ORPHAN_TYPE;
|
||||
|
||||
return lock_key_range(sb, mode, flags, &start, &end, ino, lock);
|
||||
return lock_key_range(sb, mode, flags, &start, &end, lock);
|
||||
}
|
||||
|
||||
int scoutfs_lock_xattr_totl(struct super_block *sb, enum scoutfs_lock_mode mode, int flags,
|
||||
@@ -1326,7 +1324,7 @@ int scoutfs_lock_xattr_totl(struct super_block *sb, enum scoutfs_lock_mode mode,
|
||||
|
||||
scoutfs_totl_set_range(&start, &end);
|
||||
|
||||
return lock_key_range(sb, mode, flags, &start, &end, 0, lock);
|
||||
return lock_key_range(sb, mode, flags, &start, &end, lock);
|
||||
}
|
||||
|
||||
int scoutfs_lock_xattr_indx(struct super_block *sb, enum scoutfs_lock_mode mode, int flags,
|
||||
@@ -1337,7 +1335,7 @@ int scoutfs_lock_xattr_indx(struct super_block *sb, enum scoutfs_lock_mode mode,
|
||||
|
||||
scoutfs_xattr_indx_get_range(&start, &end);
|
||||
|
||||
return lock_key_range(sb, mode, flags, &start, &end, 0, lock);
|
||||
return lock_key_range(sb, mode, flags, &start, &end, lock);
|
||||
}
|
||||
|
||||
int scoutfs_lock_quota(struct super_block *sb, enum scoutfs_lock_mode mode, int flags,
|
||||
@@ -1348,7 +1346,7 @@ int scoutfs_lock_quota(struct super_block *sb, enum scoutfs_lock_mode mode, int
|
||||
|
||||
scoutfs_quota_get_lock_range(&start, &end);
|
||||
|
||||
return lock_key_range(sb, mode, flags, &start, &end, 0, lock);
|
||||
return lock_key_range(sb, mode, flags, &start, &end, lock);
|
||||
}
|
||||
|
||||
void scoutfs_unlock(struct super_block *sb, struct scoutfs_lock *lock, enum scoutfs_lock_mode mode)
|
||||
@@ -1465,7 +1463,7 @@ static void lock_tseq_show(struct seq_file *m, struct scoutfs_tseq_entry *ent)
|
||||
struct scoutfs_lock *lock =
|
||||
container_of(ent, struct scoutfs_lock, tseq_entry);
|
||||
|
||||
seq_printf(m, "start "SK_FMT" end "SK_FMT" refresh_gen %llu mode %d waiters: rd %u wr %u wo %u users: rd %u wr %u wo %u ino: rd %llu wr %llu wo %llu pid: rd %d wr %d wo %d\n",
|
||||
seq_printf(m, "start "SK_FMT" end "SK_FMT" refresh_gen %llu mode %d waiters: rd %u wr %u wo %u users: rd %u wr %u wo %u\n",
|
||||
SK_ARG(&lock->start), SK_ARG(&lock->end),
|
||||
lock->refresh_gen, lock->mode,
|
||||
lock->waiters[SCOUTFS_LOCK_READ],
|
||||
@@ -1473,13 +1471,7 @@ static void lock_tseq_show(struct seq_file *m, struct scoutfs_tseq_entry *ent)
|
||||
lock->waiters[SCOUTFS_LOCK_WRITE_ONLY],
|
||||
lock->users[SCOUTFS_LOCK_READ],
|
||||
lock->users[SCOUTFS_LOCK_WRITE],
|
||||
lock->users[SCOUTFS_LOCK_WRITE_ONLY],
|
||||
lock->last_user_ino[SCOUTFS_LOCK_READ],
|
||||
lock->last_user_ino[SCOUTFS_LOCK_WRITE],
|
||||
lock->last_user_ino[SCOUTFS_LOCK_WRITE_ONLY],
|
||||
lock->last_user_pid[SCOUTFS_LOCK_READ],
|
||||
lock->last_user_pid[SCOUTFS_LOCK_WRITE],
|
||||
lock->last_user_pid[SCOUTFS_LOCK_WRITE_ONLY]);
|
||||
lock->users[SCOUTFS_LOCK_WRITE_ONLY]);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -42,8 +42,6 @@ struct scoutfs_lock {
|
||||
enum scoutfs_lock_mode invalidating_mode;
|
||||
unsigned int waiters[SCOUTFS_LOCK_NR_MODES];
|
||||
unsigned int users[SCOUTFS_LOCK_NR_MODES];
|
||||
pid_t last_user_pid[SCOUTFS_LOCK_NR_MODES];
|
||||
u64 last_user_ino[SCOUTFS_LOCK_NR_MODES];
|
||||
|
||||
struct scoutfs_tseq_entry tseq_entry;
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
== set up file
|
||||
== exercise read, write, and write-only modes
|
||||
== verify FS-zone lock recorded read and write ino+pid
|
||||
== verify orphan-zone lock recorded write-only ino+pid
|
||||
== contend on a single inode with concurrent read and write loops
|
||||
== verify both rd and wr slots populated by concurrent contention
|
||||
+84
-78
@@ -90,7 +90,7 @@ done
|
||||
|
||||
# set some T_ defaults
|
||||
T_TRACE_DUMP="0"
|
||||
T_TRACE_PRINTK="0"
|
||||
T_TRACE_PRINTK=""
|
||||
T_PORT_START="19700"
|
||||
T_LOOP_ITER="1"
|
||||
|
||||
@@ -137,6 +137,9 @@ while true; do
|
||||
test -n "$2" || die "-l must have a nr iterations argument"
|
||||
test "$2" -eq "$2" 2>/dev/null || die "-l <nr> argument must be an integer"
|
||||
T_LOOP_ITER="$2"
|
||||
|
||||
# when looping, break after first failure
|
||||
T_ABORT="1"
|
||||
shift
|
||||
;;
|
||||
-M)
|
||||
@@ -399,31 +402,44 @@ if [ -n "$T_INSMOD" ]; then
|
||||
cmd insmod "$T_MODULE"
|
||||
fi
|
||||
|
||||
if [ -n "$T_TRACE_MULT" ]; then
|
||||
# orig_trace_size=$(cat /sys/kernel/debug/tracing/buffer_size_kb)
|
||||
orig_trace_size=1408
|
||||
mult_trace_size=$((orig_trace_size * T_TRACE_MULT))
|
||||
msg "increasing trace buffer size from $orig_trace_size KiB to $mult_trace_size KiB"
|
||||
echo $mult_trace_size > /sys/kernel/debug/tracing/buffer_size_kb
|
||||
fi
|
||||
start_tracing() {
|
||||
if [ -n "$T_TRACE_MULT" ]; then
|
||||
orig_trace_size=1408
|
||||
mult_trace_size=$((orig_trace_size * T_TRACE_MULT))
|
||||
msg "increasing trace buffer size from $orig_trace_size KiB to $mult_trace_size KiB"
|
||||
echo $mult_trace_size > /sys/kernel/debug/tracing/buffer_size_kb
|
||||
fi
|
||||
|
||||
nr_globs=${#T_TRACE_GLOB[@]}
|
||||
if [ $nr_globs -gt 0 ]; then
|
||||
echo 0 > /sys/kernel/debug/tracing/events/scoutfs/enable
|
||||
nr_globs=${#T_TRACE_GLOB[@]}
|
||||
if [ $nr_globs -gt 0 ]; then
|
||||
echo 0 > /sys/kernel/debug/tracing/events/scoutfs/enable
|
||||
|
||||
for g in "${T_TRACE_GLOB[@]}"; do
|
||||
for e in /sys/kernel/debug/tracing/events/scoutfs/$g/enable; do
|
||||
if test -w "$e"; then
|
||||
echo 1 > "$e"
|
||||
else
|
||||
die "-t glob '$g' matched no scoutfs events"
|
||||
fi
|
||||
for g in "${T_TRACE_GLOB[@]}"; do
|
||||
for e in /sys/kernel/debug/tracing/events/scoutfs/$g/enable; do
|
||||
if test -w "$e"; then
|
||||
echo 1 > "$e"
|
||||
else
|
||||
die "-t glob '$g' matched no scoutfs events"
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
nr_events=$(cat /sys/kernel/debug/tracing/set_event | wc -l)
|
||||
msg "enabled $nr_events trace events from $nr_globs -t globs"
|
||||
fi
|
||||
nr_events=$(cat /sys/kernel/debug/tracing/set_event | wc -l)
|
||||
msg "enabled $nr_events trace events from $nr_globs -t globs"
|
||||
fi
|
||||
}
|
||||
|
||||
stop_tracing() {
|
||||
if [ -n "$T_TRACE_GLOB" -o -n "$T_TRACE_PRINTK" ]; then
|
||||
msg "saving traces and disabling tracing"
|
||||
echo 0 > /sys/kernel/debug/tracing/events/scoutfs/enable
|
||||
echo 0 > /sys/kernel/debug/tracing/options/trace_printk
|
||||
cat /sys/kernel/debug/tracing/trace | gzip > "$T_RESULTS/traces.gz"
|
||||
if [ -n "$orig_trace_size" ]; then
|
||||
echo $orig_trace_size > /sys/kernel/debug/tracing/buffer_size_kb
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -n "$T_TRACE_PRINTK" ]; then
|
||||
echo "$T_TRACE_PRINTK" > /sys/kernel/debug/tracing/options/trace_printk
|
||||
@@ -603,24 +619,26 @@ passed=0
|
||||
skipped=0
|
||||
failed=0
|
||||
skipped_permitted=0
|
||||
for t in $tests; do
|
||||
# tests has basenames from sequence, get path and name
|
||||
t="tests/$t"
|
||||
test_name=$(basename "$t" | sed -e 's/.sh$//')
|
||||
for iter in $(seq 1 $T_LOOP_ITER); do
|
||||
|
||||
# get stats from previous pass
|
||||
last="$T_RESULTS/last-passed-test-stats"
|
||||
stats=$(grep -s "^$test_name " "$last" | cut -d " " -f 2-)
|
||||
test -n "$stats" && stats="last: $stats"
|
||||
printf " %-30s $stats" "$test_name"
|
||||
start_tracing
|
||||
|
||||
# mark in dmesg as to what test we are running
|
||||
echo "run scoutfs test $test_name" > /dev/kmsg
|
||||
for t in $tests; do
|
||||
# tests has basenames from sequence, get path and name
|
||||
t="tests/$t"
|
||||
test_name=$(basename "$t" | sed -e 's/.sh$//')
|
||||
|
||||
# let the test get at its extra files
|
||||
T_EXTRA="$T_TESTS/extra/$test_name"
|
||||
# get stats from previous pass
|
||||
last="$T_RESULTS/last-passed-test-stats"
|
||||
stats=$(grep -s "^$test_name " "$last" | cut -d " " -f 2-)
|
||||
test -n "$stats" && stats="last: $stats"
|
||||
printf " %-30s $stats" "$test_name"
|
||||
|
||||
for iter in $(seq 1 $T_LOOP_ITER); do
|
||||
# mark in dmesg as to what test we are running
|
||||
echo "run scoutfs test $test_name" > /dev/kmsg
|
||||
|
||||
# let the test get at its extra files
|
||||
T_EXTRA="$T_TESTS/extra/$test_name"
|
||||
|
||||
# create a temporary dir and file path for the test
|
||||
T_TMPDIR="$T_RESULTS/tmp/$test_name"
|
||||
@@ -710,55 +728,43 @@ for t in $tests; do
|
||||
sts=$T_FAIL_STATUS
|
||||
fi
|
||||
|
||||
# stop looping if we didn't pass
|
||||
if [ "$sts" != "$T_PASS_STATUS" ]; then
|
||||
break;
|
||||
# show and record the result of the test
|
||||
if [ "$sts" == "$T_PASS_STATUS" ]; then
|
||||
echo " passed: $stats"
|
||||
((passed++))
|
||||
# save stats for passed test
|
||||
grep -s -v "^$test_name " "$last" > "$last.tmp"
|
||||
echo "$test_name $stats" >> "$last.tmp"
|
||||
mv -f "$last.tmp" "$last"
|
||||
elif [ "$sts" == "$T_SKIP_PERMITTED_STATUS" ]; then
|
||||
echo " [ skipped (permitted): $message ]"
|
||||
echo "$test_name skipped (permitted) $message " >> "$T_RESULTS/skip.log"
|
||||
((skipped_permitted++))
|
||||
elif [ "$sts" == "$T_SKIP_STATUS" ]; then
|
||||
echo " [ skipped: $message ]"
|
||||
echo "$test_name $message" >> "$T_RESULTS/skip.log"
|
||||
((skipped++))
|
||||
elif [ "$sts" == "$T_FAIL_STATUS" ]; then
|
||||
echo " [ failed: $message ]"
|
||||
echo "$test_name $message" >> "$T_RESULTS/fail.log"
|
||||
((failed++))
|
||||
|
||||
if [ -n "$T_ABORT" ]; then
|
||||
stop_tracing
|
||||
die "aborting after first failure"
|
||||
fi
|
||||
fi
|
||||
|
||||
# record results for TAP format output
|
||||
t_tap_progress $test_name $sts
|
||||
((testcount++))
|
||||
done
|
||||
|
||||
# show and record the result of the test
|
||||
if [ "$sts" == "$T_PASS_STATUS" ]; then
|
||||
echo " passed: $stats"
|
||||
((passed++))
|
||||
# save stats for passed test
|
||||
grep -s -v "^$test_name " "$last" > "$last.tmp"
|
||||
echo "$test_name $stats" >> "$last.tmp"
|
||||
mv -f "$last.tmp" "$last"
|
||||
elif [ "$sts" == "$T_SKIP_PERMITTED_STATUS" ]; then
|
||||
echo " [ skipped (permitted): $message ]"
|
||||
echo "$test_name skipped (permitted) $message " >> "$T_RESULTS/skip.log"
|
||||
((skipped_permitted++))
|
||||
elif [ "$sts" == "$T_SKIP_STATUS" ]; then
|
||||
echo " [ skipped: $message ]"
|
||||
echo "$test_name $message" >> "$T_RESULTS/skip.log"
|
||||
((skipped++))
|
||||
elif [ "$sts" == "$T_FAIL_STATUS" ]; then
|
||||
echo " [ failed: $message ]"
|
||||
echo "$test_name $message" >> "$T_RESULTS/fail.log"
|
||||
((failed++))
|
||||
|
||||
test -n "$T_ABORT" && die "aborting after first failure"
|
||||
fi
|
||||
|
||||
# record results for TAP format output
|
||||
t_tap_progress $test_name $sts
|
||||
((testcount++))
|
||||
|
||||
stop_tracing
|
||||
done
|
||||
|
||||
msg "all tests run: $passed passed, $skipped skipped, $skipped_permitted skipped (permitted), $failed failed"
|
||||
|
||||
|
||||
if [ -n "$T_TRACE_GLOB" -o -n "$T_TRACE_PRINTK" ]; then
|
||||
msg "saving traces and disabling tracing"
|
||||
echo 0 > /sys/kernel/debug/tracing/events/scoutfs/enable
|
||||
echo 0 > /sys/kernel/debug/tracing/options/trace_printk
|
||||
cat /sys/kernel/debug/tracing/trace > "$T_RESULTS/traces"
|
||||
if [ -n "$orig_trace_size" ]; then
|
||||
echo $orig_trace_size > /sys/kernel/debug/tracing/buffer_size_kb
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$skipped" == 0 -a "$failed" == 0 ]; then
|
||||
msg "all tests passed"
|
||||
unmount_all
|
||||
|
||||
@@ -32,7 +32,6 @@ totl-merge-read.sh
|
||||
quota-invalidate-race.sh
|
||||
totl-delta-inject.sh
|
||||
lock-refleak.sh
|
||||
lock-pid-ino.sh
|
||||
lock-shrink-consistency.sh
|
||||
lock-shrink-read-race.sh
|
||||
lock-pr-cw-conflict.sh
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
#
|
||||
# verify debugfs client_locks reports per-mode last-user PID and inode.
|
||||
#
|
||||
|
||||
t_require_commands stat touch awk rm
|
||||
|
||||
FILE="$T_D0/file"
|
||||
|
||||
echo "== set up file"
|
||||
touch "$FILE"
|
||||
INO=$(stat -c %i "$FILE")
|
||||
GROUP_START=$(( INO & ~1023 ))
|
||||
|
||||
echo "== exercise read, write, and write-only modes"
|
||||
t_quiet stat "$FILE"
|
||||
echo data > "$FILE"
|
||||
rm -f "$FILE"
|
||||
|
||||
echo "== verify FS-zone lock recorded read and write ino+pid"
|
||||
ERR=$(awk -v group="$GROUP_START" -v ino="$INO" '
|
||||
$2 == "16." group ".0.0.0.0" {
|
||||
if ($25 != ino || $32 <= 0)
|
||||
print "read mode: ino=" $25 " pid=" $32 " want ino=" ino " pid>0"
|
||||
if ($27 != ino || $34 <= 0)
|
||||
print "write mode: ino=" $27 " pid=" $34 " want ino=" ino " pid>0"
|
||||
found = 1
|
||||
}
|
||||
END { if (!found) print "no FS-zone client_locks line for group " group }
|
||||
' < "$(t_debugfs_path)/client_locks")
|
||||
[ -n "$ERR" ] && t_fail "$ERR"
|
||||
|
||||
echo "== verify orphan-zone lock recorded write-only ino+pid"
|
||||
ERR=$(awk -v ino="$INO" '
|
||||
$2 == "8.0.4.0.0.0" {
|
||||
if ($29 != ino || $36 <= 0)
|
||||
print "write-only mode: ino=" $29 " pid=" $36 " want ino=" ino " pid>0"
|
||||
found = 1
|
||||
}
|
||||
END { if (!found) print "no orphan-zone client_locks line" }
|
||||
' < "$(t_debugfs_path)/client_locks")
|
||||
[ -n "$ERR" ] && t_fail "$ERR"
|
||||
|
||||
echo "== contend on a single inode with concurrent read and write loops"
|
||||
FILE2="$T_D0/file2"
|
||||
touch "$FILE2"
|
||||
INO2=$(stat -c %i "$FILE2")
|
||||
GROUP2=$(( INO2 & ~1023 ))
|
||||
|
||||
for i in $(seq 1 5); do t_quiet stat "$FILE2"; done &
|
||||
RPID=$!
|
||||
for i in $(seq 1 5); do echo $i > "$FILE2"; done &
|
||||
WPID=$!
|
||||
wait $RPID $WPID
|
||||
|
||||
echo "== verify both rd and wr slots populated by concurrent contention"
|
||||
ERR=$(awk -v group="$GROUP2" -v ino="$INO2" '
|
||||
$2 == "16." group ".0.0.0.0" {
|
||||
if ($25 != ino || $32 <= 0)
|
||||
print "concurrent read: ino=" $25 " pid=" $32 " want ino=" ino " pid>0"
|
||||
if ($27 != ino || $34 <= 0)
|
||||
print "concurrent write: ino=" $27 " pid=" $34 " want ino=" ino " pid>0"
|
||||
found = 1
|
||||
}
|
||||
END { if (!found) print "no FS-zone client_locks line for group " group }
|
||||
' < "$(t_debugfs_path)/client_locks")
|
||||
[ -n "$ERR" ] && t_fail "$ERR"
|
||||
|
||||
t_pass
|
||||
Reference in New Issue
Block a user