Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/efivarfs: add concurrent update tests

The delete on last close functionality can now only be tested properly
by using multiple threads to hold open the variable files and testing
what happens as they complete.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

authored by

James Bottomley and committed by
Ard Biesheuvel
87e6cd7c fd3aa3d5

+134
+134
tools/testing/selftests/efivarfs/efivarfs.sh
··· 227 227 exit $ret 228 228 } 229 229 230 + setup_test_multiple() 231 + { 232 + ## 233 + # we're going to do multi-threaded tests, so create a set of 234 + # pipes for synchronization. We use pipes 1..3 to start the 235 + # stalled shell job and pipes 4..6 as indicators that the job 236 + # has started. If you need more than 3 jobs the two +3's below 237 + # need increasing 238 + ## 239 + 240 + declare -ag p 241 + 242 + # empty is because arrays number from 0 but jobs number from 1 243 + p[0]="" 244 + 245 + for f in 1 2 3 4 5 6; do 246 + p[$f]=/tmp/efivarfs_pipe${f} 247 + mknod ${p[$f]} p 248 + done 249 + 250 + declare -g var=$efivarfs_mount/test_multiple-$test_guid 251 + 252 + cleanup() { 253 + for f in ${p[@]}; do 254 + rm -f ${f} 255 + done 256 + if [ -e $var ]; then 257 + file_cleanup $var 258 + fi 259 + } 260 + trap cleanup exit 261 + 262 + waitstart() { 263 + cat ${p[$[$1+3]]} > /dev/null 264 + } 265 + 266 + waitpipe() { 267 + echo 1 > ${p[$[$1+3]]} 268 + cat ${p[$1]} > /dev/null 269 + } 270 + 271 + endjob() { 272 + echo 1 > ${p[$1]} 273 + wait -n %$1 274 + } 275 + } 276 + 277 + test_multiple_zero_size() 278 + { 279 + ## 280 + # check for remove on last close, set up three threads all 281 + # holding the variable (one write and two reads) and then 282 + # close them sequentially (waiting for completion) and check 283 + # the state of the variable 284 + ## 285 + 286 + { waitpipe 1; echo 1; } > $var 2> /dev/null & 287 + waitstart 1 288 + # zero length file should exist 289 + [ -e $var ] || exit 1 290 + # second and third delayed close 291 + { waitpipe 2; } < $var & 292 + waitstart 2 293 + { waitpipe 3; } < $var & 294 + waitstart 3 295 + # close first fd 296 + endjob 1 297 + # var should only be deleted on last close 298 + [ -e $var ] || exit 1 299 + # close second fd 300 + endjob 2 301 + [ -e $var ] || exit 1 302 + # file should go on last close 303 + endjob 3 304 + [ ! -e $var ] || exit 1 305 + } 306 + 307 + test_multiple_create() 308 + { 309 + ## 310 + # set multiple threads to access the variable but delay 311 + # the final write to check the close of 2 and 3. The 312 + # final write should succeed in creating the variable 313 + ## 314 + { waitpipe 1; printf '\x07\x00\x00\x00\x54'; } > $var & 315 + waitstart 1 316 + [ -e $var -a ! -s $var ] || exit 1 317 + { waitpipe 2; } < $var & 318 + waitstart 2 319 + { waitpipe 3; } < $var & 320 + waitstart 3 321 + # close second and third fds 322 + endjob 2 323 + # var should only be created (have size) on last close 324 + [ -e $var -a ! -s $var ] || exit 1 325 + endjob 3 326 + [ -e $var -a ! -s $var ] || exit 1 327 + # close first fd 328 + endjob 1 329 + # variable should still exist 330 + [ -s $var ] || exit 1 331 + file_cleanup $var 332 + } 333 + 334 + test_multiple_delete_on_write() { 335 + ## 336 + # delete the variable on final write; seqencing similar 337 + # to test_multiple_create() 338 + ## 339 + printf '\x07\x00\x00\x00\x54' > $var 340 + chattr -i $var 341 + { waitpipe 1; printf '\x07\x00\x00\x00'; } > $var & 342 + waitstart 1 343 + [ -e $var -a -s $var ] || exit 1 344 + { waitpipe 2; } < $var & 345 + waitstart 2 346 + { waitpipe 3; } < $var & 347 + waitstart 3 348 + # close first fd; write should set variable size to zero 349 + endjob 1 350 + # var should only be deleted on last close 351 + [ -e $var -a ! -s $var ] || exit 1 352 + endjob 2 353 + [ -e $var ] || exit 1 354 + # close last fd 355 + endjob 3 356 + # variable should now be removed 357 + [ ! -e $var ] || exit 1 358 + } 359 + 230 360 check_prereqs 231 361 232 362 rc=0 ··· 370 240 run_test test_valid_filenames 371 241 run_test test_invalid_filenames 372 242 run_test test_no_set_size 243 + setup_test_multiple 244 + run_test test_multiple_zero_size 245 + run_test test_multiple_create 246 + run_test test_multiple_delete_on_write 373 247 374 248 exit $rc