@@ -227,6 +227,136 @@ test_no_set_size()
227227 exit $ret
228228}
229229
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+
230360check_prereqs
231361
232362rc=0
@@ -240,5 +370,9 @@ run_test test_open_unlink
240370run_test test_valid_filenames
241371run_test test_invalid_filenames
242372run_test test_no_set_size
373+ setup_test_multiple
374+ run_test test_multiple_zero_size
375+ run_test test_multiple_create
376+ run_test test_multiple_delete_on_write
243377
244378exit $rc
0 commit comments