mirror of
https://github.com/gluster/glusterfs.git
synced 2026-02-07 12:48:38 +01:00
afr: fix size of stack-allocated array (#4053)
One array allocated using alloca() was not using the right size, corrupting adjacent memory when the array was used. Also updated the related tests since they were not working correctly. The test tried to pass some data through a variable that was created in a child subshell, so the variable was empty in the parent. To implement the same functionality but supporting passing data between subshells, a new test command has been created: TEST_WITHIN. It works like TEST but if the test is not successful, it waits for some time before marking the test as bad. Once the test succeeds, whatever data the test has returned during its execution will be available in the variable TEST_OUTPUT. Fixes: #4042 Signed-off-by: Xavi Hernandez <xhernandez@gmail.com>
This commit is contained in:
@@ -90,7 +90,7 @@ acquire_mandatory_lock(glfs_t *fs, glfs_fd_t *fd)
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 100;
|
||||
|
||||
ret = glfs_fsetxattr(fd, GF_ENFORCE_MANDATORY_LOCK, "set", 8, 0);
|
||||
ret = glfs_fsetxattr(fd, GF_ENFORCE_MANDATORY_LOCK, "set", 4, 0);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("glfs_fsetxattr", errno);
|
||||
ret = -1;
|
||||
|
||||
@@ -92,7 +92,7 @@ acquire_mandatory_lock(glfs_t *fs, char *fname)
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 100;
|
||||
|
||||
ret = glfs_fsetxattr(fd, GF_ENFORCE_MANDATORY_LOCK, "set", 8, 0);
|
||||
ret = glfs_fsetxattr(fd, GF_ENFORCE_MANDATORY_LOCK, "set", 4, 0);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("glfs_fsetxattr", errno);
|
||||
ret = -1;
|
||||
|
||||
@@ -19,18 +19,20 @@ function is_gfapi_program_alive()
|
||||
|
||||
function fill_lock_info()
|
||||
{
|
||||
local -n info=$1
|
||||
local brick=$2
|
||||
local info
|
||||
local brick=$1
|
||||
pattern="ACTIVE.*client-${brick: -1}"
|
||||
|
||||
brick_sdump=$(generate_brick_statedump $V0 $H0 $brick)
|
||||
info="$(egrep "$inode" $brick_sdump -A3| egrep "$pattern" | uniq | awk '{print $1,$2,$3,S4,$5,$6,$7,$8}'|tr -d '(,), ,')"
|
||||
|
||||
echo "${info}"
|
||||
|
||||
if [ -n "$info" ]
|
||||
then
|
||||
echo "success"
|
||||
return 0
|
||||
else
|
||||
echo "failure"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -72,8 +74,10 @@ TEST kill -SIGUSR1 $client1_pid
|
||||
EXPECT "Y" is_gfapi_program_alive $client1_pid
|
||||
|
||||
# Check lock is present on brick-1 and brick-2
|
||||
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "success" fill_lock_info c1_lock_on_b1 $B0/${V0}0
|
||||
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "success" fill_lock_info c1_lock_on_b2 $B0/${V0}1
|
||||
TEST_WITHIN $PROCESS_UP_TIMEOUT fill_lock_info $B0/${V0}0
|
||||
c1_lock_on_b1="${TEST_OUTPUT}"
|
||||
TEST_WITHIN $PROCESS_UP_TIMEOUT fill_lock_info $B0/${V0}1
|
||||
c1_lock_on_b2="${TEST_OUTPUT}"
|
||||
TEST [ "$c1_lock_on_b1" == "$c1_lock_on_b2" ]
|
||||
|
||||
# Restart brick-3 and check that the lock has healed on it.
|
||||
@@ -82,7 +86,8 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2
|
||||
|
||||
# Note: We need to wait for client to re-open the fd. Otherwise client_pre_lk_v2() fails with EBADFD for remote-fd. Also wait for lock heal.
|
||||
# So we may need to check the statedump for locks multiple times.
|
||||
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "success" fill_lock_info c1_lock_on_b3 $B0/${V0}2
|
||||
TEST_WITHIN $PROCESS_UP_TIMEOUT fill_lock_info $B0/${V0}2
|
||||
c1_lock_on_b3="${TEST_OUTPUT}"
|
||||
TEST [ "$c1_lock_on_b1" == "$c1_lock_on_b3" ]
|
||||
|
||||
# Kill brick-1 and let client-2 preempt the lock on bricks 2 and 3.
|
||||
@@ -98,9 +103,12 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0
|
||||
# Check that all bricks now have locks from client 2 only.
|
||||
# Note: We need to wait for client to re-open the fd. Otherwise client_pre_lk_v2() fails with EBADFD for remote-fd. Also wait for lock heal.
|
||||
# So we may need to check the statedump for locks multiple times.
|
||||
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "success" fill_lock_info c2_lock_on_b1 $B0/${V0}0
|
||||
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "success" fill_lock_info c2_lock_on_b2 $B0/${V0}1
|
||||
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "success" fill_lock_info c2_lock_on_b3 $B0/${V0}2
|
||||
TEST_WITHIN $PROCESS_UP_TIMEOUT fill_lock_info $B0/${V0}0
|
||||
c2_lock_on_b1="${TEST_OUTPUT}"
|
||||
TEST_WITHIN $PROCESS_UP_TIMEOUT fill_lock_info $B0/${V0}1
|
||||
c2_lock_on_b2="${TEST_OUTPUT}"
|
||||
TEST_WITHIN $PROCESS_UP_TIMEOUT fill_lock_info $B0/${V0}2
|
||||
c2_lock_on_b3="${TEST_OUTPUT}"
|
||||
TEST [ "$c2_lock_on_b1" == "$c2_lock_on_b2" ]
|
||||
TEST [ "$c2_lock_on_b1" == "$c2_lock_on_b3" ]
|
||||
TEST [ "$c2_lock_on_b1" != "$c1_lock_on_b1" ]
|
||||
|
||||
@@ -172,7 +172,7 @@ wc() {
|
||||
;;
|
||||
esac
|
||||
|
||||
testcnt=`egrep '^[[:space:]]*(EXPECT|EXPECT_NOT|TEST|EXPECT_WITHIN|EXPECT_KEYWORD)[[:space:]]' $0 | wc -l`
|
||||
testcnt=`egrep '^[[:space:]]*(EXPECT|EXPECT_NOT|TEST|TEST_WITHIN|EXPECT_WITHIN|EXPECT_KEYWORD)[[:space:]]' $0 | wc -l`
|
||||
expect_tests=`egrep '^[[:space:]]*TESTS_EXPECTED_IN_LOOP[[:space:]]*' $0`
|
||||
|
||||
x_ifs=$IFS
|
||||
@@ -349,6 +349,44 @@ function _TEST()
|
||||
test_footer "$TESTLINE";
|
||||
}
|
||||
|
||||
|
||||
function _TEST_WITHIN()
|
||||
{
|
||||
local res output
|
||||
|
||||
TESTLINE=$1
|
||||
shift;
|
||||
|
||||
local timeout=$1
|
||||
shift;
|
||||
|
||||
G_LOG $TESTLINE "$@";
|
||||
test_header "$@"
|
||||
|
||||
local endtime="$(( ${timeout}000000000 + $(date +%s%N) ))"
|
||||
|
||||
# We *want* this to be globally visible.
|
||||
EW_RETRIES=0
|
||||
|
||||
output=""
|
||||
res="1"
|
||||
while [[ "$(date +%s%N)" < "$endtime" ]]; do
|
||||
output="$("${@}" 2>/dev/null)"
|
||||
res="${?}"
|
||||
if [[ "${res}" == "0" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 0.25;
|
||||
EW_RETRIES=$((EW_RETRIES+1))
|
||||
done
|
||||
|
||||
! [[ "${res}" != "0" ]]
|
||||
|
||||
test_footer "$TESTLINE"
|
||||
|
||||
TEST_OUTPUT="${output}"
|
||||
}
|
||||
|
||||
#This function should be used carefully.
|
||||
#The expected regex, given to this function, should be
|
||||
#used within ^ and $ to match exactly with the output of
|
||||
@@ -982,6 +1020,7 @@ if [ -n "$GF_INTERACTIVE" ]; then
|
||||
else
|
||||
alias TEST='_TEST $LINENO'
|
||||
fi
|
||||
alias TEST_WITHIN='_TEST_WITHIN $LINENO'
|
||||
alias EXPECT_WITHIN='_EXPECT_WITHIN $LINENO'
|
||||
alias EXPECT_KEYWORD='_EXPECT_KEYWORD $LINENO'
|
||||
alias TEST_IN_LOOP='_TEST_IN_LOOP $LINENO'
|
||||
|
||||
@@ -515,7 +515,7 @@ afr_lock_heal_do(call_frame_t *frame, afr_private_t *priv,
|
||||
wind_on[i] = 1;
|
||||
}
|
||||
|
||||
current_event_gen = alloca(priv->child_count);
|
||||
current_event_gen = alloca(priv->child_count * sizeof(*current_event_gen));
|
||||
memcpy(current_event_gen, info->child_up_event_gen,
|
||||
priv->child_count * sizeof *current_event_gen);
|
||||
AFR_ONLIST(wind_on, frame, afr_lock_heal_cbk, lk, info->fd, info->cmd,
|
||||
|
||||
Reference in New Issue
Block a user