mirror of
https://github.com/versity/scoutfs.git
synced 2026-05-01 18:35:43 +00:00
Compare commits
2 Commits
zab/test_m
...
zab/read_m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8efb30afbc | ||
|
|
df90b3eb90 |
@@ -29,7 +29,12 @@
|
||||
#include "per_task.h"
|
||||
#include "omap.h"
|
||||
|
||||
/* TODO: Direct I/O, AIO */
|
||||
/*
|
||||
* Start a high level file read. We check for offline extents in the
|
||||
* read region here so that we only check the extents once. We use the
|
||||
* dio count to prevent releasing while we're reading after we've
|
||||
* checked the extents.
|
||||
*/
|
||||
ssize_t scoutfs_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
@@ -43,30 +48,32 @@ ssize_t scoutfs_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
int ret;
|
||||
|
||||
retry:
|
||||
/* protect checked extents from release */
|
||||
mutex_lock(&inode->i_mutex);
|
||||
atomic_inc(&inode->i_dio_count);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ,
|
||||
SCOUTFS_LKF_REFRESH_INODE, inode, &inode_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (scoutfs_per_task_add_excl(&si->pt_data_lock, &pt_ent, inode_lock)) {
|
||||
/* protect checked extents from stage/release */
|
||||
mutex_lock(&inode->i_mutex);
|
||||
atomic_inc(&inode->i_dio_count);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
ret = scoutfs_data_wait_check_iov(inode, iov, nr_segs, pos,
|
||||
SEF_OFFLINE,
|
||||
SCOUTFS_IOC_DWO_READ,
|
||||
&dw, inode_lock);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
} else {
|
||||
WARN_ON_ONCE(true);
|
||||
}
|
||||
|
||||
ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
|
||||
|
||||
out:
|
||||
if (scoutfs_per_task_del(&si->pt_data_lock, &pt_ent))
|
||||
inode_dio_done(inode);
|
||||
inode_dio_done(inode);
|
||||
scoutfs_per_task_del(&si->pt_data_lock, &pt_ent);
|
||||
scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
if (scoutfs_data_wait_found(&dw)) {
|
||||
|
||||
@@ -13,6 +13,7 @@ lock-refleak.sh
|
||||
lock-shrink-consistency.sh
|
||||
lock-pr-cw-conflict.sh
|
||||
lock-revoke-getcwd.sh
|
||||
export-lookup-evict-race.sh
|
||||
createmany-parallel.sh
|
||||
createmany-large-names.sh
|
||||
createmany-rename-large-dir.sh
|
||||
@@ -21,7 +22,6 @@ stage-multi-part.sh
|
||||
stage-tmpfile.sh
|
||||
basic-posix-consistency.sh
|
||||
dirent-consistency.sh
|
||||
mkdir-rename-rmdir.sh
|
||||
lock-ex-race-processes.sh
|
||||
lock-conflicting-batch-commit.sh
|
||||
cross-mount-data-free.sh
|
||||
|
||||
32
tests/tests/export-lookup-evict-race.sh
Normal file
32
tests/tests/export-lookup-evict-race.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# test racing fh_to_dentry with evict from lock invalidation. We've
|
||||
# had deadlocks between the ordering of iget and evict when they acquire
|
||||
# cluster locks.
|
||||
#
|
||||
|
||||
t_require_commands touch stat handle_cat
|
||||
t_require_mounts 2
|
||||
|
||||
CPUS=$(getconf _NPROCESSORS_ONLN)
|
||||
NR=$((CPUS * 4))
|
||||
END=$((SECONDS + 30))
|
||||
|
||||
touch "$T_D0/file"
|
||||
ino=$(stat -c "%i" "$T_D0/file")
|
||||
|
||||
while test $SECONDS -lt $END; do
|
||||
for i in $(seq 1 $NR); do
|
||||
fs=$((RANDOM % T_NR_MOUNTS))
|
||||
eval dir="\$T_D${fs}"
|
||||
write=$((RANDOM & 1))
|
||||
|
||||
if [ "$write" == 1 ]; then
|
||||
touch "$dir/file" &
|
||||
else
|
||||
handle_cat "$dir" "$ino" &
|
||||
fi
|
||||
done
|
||||
wait
|
||||
done
|
||||
|
||||
t_pass
|
||||
@@ -1,59 +0,0 @@
|
||||
#
|
||||
# Sequentially perform operations on a dir (mkdir; rename*2; rmdir) on
|
||||
# all possible combinations of different mounts that could perform the
|
||||
# operations.
|
||||
#
|
||||
# We're testing that the tracking of the entry key in our cached dirents
|
||||
# stays consitent with the persistent entry items as they're modified
|
||||
# around the cluster.
|
||||
#
|
||||
|
||||
t_require_commands mkdir mv rmdir
|
||||
|
||||
NR_OPS=4
|
||||
|
||||
unset op_mnt
|
||||
for op in $(seq 0 $NR_OPS); do
|
||||
op_mnt[$op]=0
|
||||
done
|
||||
|
||||
if [ $T_NR_MOUNTS -gt $NR_OPS ]; then
|
||||
NR_MNTS=$NR_OPS
|
||||
else
|
||||
NR_MNTS=$T_NR_MOUNTS
|
||||
fi
|
||||
|
||||
# test until final op mount dir wraps
|
||||
while [ ${op_mnt[$NR_OPS]} == 0 ]; do
|
||||
|
||||
# sequentially perform each op from its mount dir
|
||||
for op in $(seq 0 $((NR_OPS - 1))); do
|
||||
m=${op_mnt[$op]}
|
||||
eval dir="\$T_D${m}/dir"
|
||||
|
||||
case "$op" in
|
||||
0) mkdir "$dir" ;;
|
||||
1) mv "$dir" "$dir-1" ;;
|
||||
2) mv "$dir-1" "$dir-2" ;;
|
||||
3) rmdir "$dir-2" ;;
|
||||
esac
|
||||
|
||||
if [ $? != 0 ]; then
|
||||
t_fail "${op_mnt[*]} failed at op $op"
|
||||
fi
|
||||
done
|
||||
|
||||
# advance through mnt nrs for each op
|
||||
i=0
|
||||
while [ ${op_mnt[$NR_OPS]} == 0 ]; do
|
||||
((op_mnt[$i]++))
|
||||
if [ ${op_mnt[$i]} -ge $NR_MNTS ]; then
|
||||
op_mnt[$i]=0
|
||||
((i++))
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
t_pass
|
||||
Reference in New Issue
Block a user