@@ -227,6 +227,136 @@ test_no_set_size()
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
@@ -240,5 +370,9 @@ run_test test_open_unlink
240
370
run_test test_valid_filenames
241
371
run_test test_invalid_filenames
242
372
run_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
243
377
244
378
exit $rc
0 commit comments