1
0
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:
Xavi Hernandez
2023-03-27 15:53:28 +02:00
committed by GitHub
parent 13bc0e9e58
commit 3a5b8cd94d
5 changed files with 61 additions and 14 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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" ]

View File

@@ -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'

View File

@@ -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,