Skip to content

Commit

Permalink
FatPkg/EnhancedFatDxe: Ensure traverse of subtasks is delete-safe
Browse files Browse the repository at this point in the history
Within function FatQueueTask(), the traverse of FAT subtasks for
executing the disk read/write is not delete-safe.

For the below case:

FatDiskIo(): When non-blocking access, creates subtasks and creates
event (FatOnAccessComplete, NOTIFY level) when subtasks finish.

FatQueueTask(): Traverses the subtasks and submits them one by one at
Tpl lower than NOTIFY.

Disk R/W completes really quick.

FatOnAccessComplete(): Removes the finished subtask, causing the
traverse in FatQueueTask() broken.

This commits will refine the subtask traverse in FatQueueTask() to be
delete-safe.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
  • Loading branch information
hwu25 committed Apr 18, 2018
1 parent 104bbee commit 2551014
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions FatPkg/EnhancedFatDxe/Misc.c
Expand Up @@ -132,6 +132,7 @@ FatQueueTask (
{
EFI_STATUS Status;
LIST_ENTRY *Link;
LIST_ENTRY *NextLink;
FAT_SUBTASK *Subtask;

//
Expand All @@ -149,9 +150,17 @@ FatQueueTask (
EfiReleaseLock (&FatTaskLock);

Status = EFI_SUCCESS;
for ( Link = GetFirstNode (&Task->Subtasks)
; !IsNull (&Task->Subtasks, Link)
; Link = GetNextNode (&Task->Subtasks, Link)
//
// Use NextLink to store the next link of the list, because Link might be remove from the
// doubly-linked list and get freed in the end of current loop.
//
// Also, list operation APIs like IsNull() and GetNextNode() are avoided during the loop, since
// they may check the validity of doubly-linked lists by traversing them. These APIs cannot
// handle list elements being removed during the traverse.
//
for ( Link = GetFirstNode (&Task->Subtasks), NextLink = GetNextNode (&Task->Subtasks, Link)
; Link != &Task->Subtasks
; Link = NextLink, NextLink = Link->ForwardLink
) {
Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);
if (Subtask->Write) {
Expand Down

0 comments on commit 2551014

Please sign in to comment.