]> git.proxmox.com Git - mirror_edk2.git/commitdiff
FatPkg/EnhancedFatDxe: Ensure traverse of subtasks is delete-safe
authorHao Wu <hao.a.wu@intel.com>
Sat, 14 Apr 2018 03:06:13 +0000 (11:06 +0800)
committerHao Wu <hao.a.wu@intel.com>
Wed, 18 Apr 2018 07:08:14 +0000 (15:08 +0800)
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>
FatPkg/EnhancedFatDxe/Misc.c

index c035670bf78fcc831eae00bc38d2a3e23cc35e5d..af66b1d0e31792be3cd6c7f9738fc3ebc744056b 100644 (file)
@@ -132,6 +132,7 @@ FatQueueTask (
 {\r
   EFI_STATUS          Status;\r
   LIST_ENTRY          *Link;\r
 {\r
   EFI_STATUS          Status;\r
   LIST_ENTRY          *Link;\r
+  LIST_ENTRY          *NextLink;\r
   FAT_SUBTASK         *Subtask;\r
 \r
   //\r
   FAT_SUBTASK         *Subtask;\r
 \r
   //\r
@@ -149,9 +150,17 @@ FatQueueTask (
   EfiReleaseLock (&FatTaskLock);\r
 \r
   Status = EFI_SUCCESS;\r
   EfiReleaseLock (&FatTaskLock);\r
 \r
   Status = EFI_SUCCESS;\r
-  for ( Link = GetFirstNode (&Task->Subtasks)\r
-      ; !IsNull (&Task->Subtasks, Link)\r
-      ; Link = GetNextNode (&Task->Subtasks, Link)\r
+  //\r
+  // Use NextLink to store the next link of the list, because Link might be remove from the\r
+  // doubly-linked list and get freed in the end of current loop.\r
+  //\r
+  // Also, list operation APIs like IsNull() and GetNextNode() are avoided during the loop, since\r
+  // they may check the validity of doubly-linked lists by traversing them. These APIs cannot\r
+  // handle list elements being removed during the traverse.\r
+  //\r
+  for ( Link = GetFirstNode (&Task->Subtasks), NextLink = GetNextNode (&Task->Subtasks, Link)\r
+      ; Link != &Task->Subtasks\r
+      ; Link = NextLink, NextLink = Link->ForwardLink\r
       ) {\r
     Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);\r
     if (Subtask->Write) {\r
       ) {\r
     Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);\r
     if (Subtask->Write) {\r