From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) by mx.groups.io with SMTP id smtpd.web10.11603.1629557301845862376 for ; Sat, 21 Aug 2021 07:48:22 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20161025 header.b=B5YXVMWd; spf=pass (domain: gmail.com, ip: 209.85.221.49, mailfrom: pedro.falcato@gmail.com) Received: by mail-wr1-f49.google.com with SMTP id e5so2017373wrp.8 for ; Sat, 21 Aug 2021 07:48:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=z6Z2+XUwsi8yPgb0sMhehTGCL/wcnseWHb+tEBojKQU=; b=B5YXVMWdeJHp+fIu0v1BaBj27LmHH/2B+R7VshzBXi0U9ckXqsKqal9FzlKf5SZxyx L/zSM1Y55zCh7AlkS7Ldqv8zQsps1zjEmU6+VZo6DW0fcvgY/ghEB6UyRDlMgKOc7Ngv b2/RxB2zKqqEhFIkAWQ/btWMLjOi2uYwRhFVUl1ll8Y0ToSPzeWbR2+UoDUDOrWBfVZY +OoLZc0BI8BkxLYO/9i28dWNuNdLSPgnm0U7jJSckztXBf+pyqqrXI84Y5g0o6oaZkO1 yRacCgXPOe7+wi2Xdo1sepk4gEwalpzJAhRjSschc0nPoGHcwvGyHR1DD7oqpqc45OUB yECw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=z6Z2+XUwsi8yPgb0sMhehTGCL/wcnseWHb+tEBojKQU=; b=SQHaGsUPZl7su4RKPSO1IiO16LEJF6U5FuhRUTsJ5rVPSLr826MKOOQ/uPu/BEfM2w p8ZHZCzj3QSDhc9a1DshmjRBT86r5oh+3n74BSGp7/IN8GLEg4uAcIaJRdmR0FGPu0GJ 8YywqULKhNaTSxgU8Yl8cGjsfhk3FQqLOKQqtSwmtsKivSXxZWfmd9yH10nfAYvRJOpW SyBziVnikVamxyyHFz8DKO/5CZ78EPcaTa5YHF+fSKw92KnI3BNxO3NPC9r8pu5NwVu4 SOk1G+7U1QoeToiok3Agyko3FR/qa5mLG92FQuJ/DC660dtH8ppKkm9aazWTGTWlNMrh f9Pw== X-Gm-Message-State: AOAM531idOnmlZBPmxj1PKpzQsJDGxR4qgzkKXkfqZT/EsdDLlUkFdrv Ye8PldQSUUcq2FPTKDFAOU8gal5vK14nccWR X-Google-Smtp-Source: ABdhPJwAVbZKKZ/SBy3YSLaFI/LUK1Af0Bt8Naoz+LxwiRt6GgFsix/q/4iW91UR9VpdZU7ciMX3OQ== X-Received: by 2002:a05:6000:1a86:: with SMTP id f6mr4291989wry.345.1629557300224; Sat, 21 Aug 2021 07:48:20 -0700 (PDT) Return-Path: Received: from PC-PEDRO.lan (bl8-253-151.dsl.telepac.pt. [85.241.253.151]) by smtp.gmail.com with ESMTPSA id j17sm9118036wrt.69.2021.08.21.07.48.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 21 Aug 2021 07:48:19 -0700 (PDT) From: "Pedro Falcato" To: devel@edk2.groups.io Cc: Pedro Falcato , Leif Lindholm , Michael D Kinney , Bret Barkelew Subject: [edk2-platforms PATCH v2 3/5] Ext4Pkg: Add a directory entry tree. Date: Sat, 21 Aug 2021 15:47:08 +0100 Message-Id: <20210821144711.39546-4-pedro.falcato@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210821144711.39546-1-pedro.falcato@gmail.com> References: <20210821144711.39546-1-pedro.falcato@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable This helps us track directories and directory entries, which helps us getting a general idea of how the filesystem looks. In the future, it might serve as a directory cache. Right now, it only lets us know which name "." and ".." may refer to, which fixes a EFI_FILE_PROTOCOL::GetInfo() bug that got triggered by ShellPkg, in some MdePkg code. Cc: Leif Lindholm Cc: Michael D Kinney Cc: Bret Barkelew Signed-off-by: Pedro Falcato --- Features/Ext4Pkg/Ext4Dxe/Directory.c | 238 +++++++++++++++++++++----- Features/Ext4Pkg/Ext4Dxe/Ext4Disk.h | 3 + Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h | 67 +++++++- Features/Ext4Pkg/Ext4Dxe/File.c | 24 +-- Features/Ext4Pkg/Ext4Dxe/Inode.c | 3 +- Features/Ext4Pkg/Ext4Dxe/Partition.c | 7 + Features/Ext4Pkg/Ext4Dxe/Superblock.c | 23 ++- 7 files changed, 301 insertions(+), 64 deletions(-) diff --git a/Features/Ext4Pkg/Ext4Dxe/Directory.c b/Features/Ext4Pkg/Ext4Dx= e/Directory.c index c85c4df6d5c5..7d1b2dcfe524 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Directory.c +++ b/Features/Ext4Pkg/Ext4Dxe/Directory.c @@ -194,13 +194,8 @@ Ext4OpenDirent ( )=0D {=0D EFI_STATUS Status;=0D - CHAR16 FileNameBuf[EXT4_NAME_MAX + 1];=0D + CHAR16 FileName[EXT4_NAME_MAX + 1];=0D EXT4_FILE *File;=0D - CHAR16 *FileName;=0D - UINTN DestMax;=0D -=0D - FileName =3D FileNameBuf;=0D - DestMax =3D ARRAY_SIZE (FileNameBuf);=0D =0D File =3D AllocateZeroPool (sizeof (EXT4_FILE));=0D =0D @@ -209,23 +204,32 @@ Ext4OpenDirent ( goto Error;=0D }=0D =0D - Status =3D Ext4GetUcs2DirentName (Entry, FileNameBuf);=0D + Status =3D Ext4GetUcs2DirentName (Entry, FileName);=0D =0D if (EFI_ERROR (Status)) {=0D goto Error;=0D }=0D =0D - if (StrCmp (FileNameBuf, L".") =3D=3D 0) {=0D - // We're using the parent directory's name=0D - FileName =3D Directory->FileName;=0D - DestMax =3D StrLen (FileName) + 1;=0D - }=0D + if (StrCmp (FileName, L".") =3D=3D 0) {=0D + // We're using the parent directory's dentry=0D + File->Dentry =3D Directory->Dentry;=0D =0D - File->FileName =3D AllocateZeroPool (StrSize (FileName));=0D + ASSERT (File->Dentry !=3D NULL);=0D =0D - if (!File->FileName) {=0D - Status =3D EFI_OUT_OF_RESOURCES;=0D - goto Error;=0D + Ext4RefDentry (File->Dentry);=0D + } else if (StrCmp (FileName, L"..") =3D=3D 0) {=0D + // Using the parent's parent's dentry=0D + File->Dentry =3D Directory->Dentry->Parent;=0D +=0D + ASSERT (File->Dentry !=3D NULL);=0D +=0D + Ext4RefDentry (File->Dentry);=0D + } else {=0D + File->Dentry =3D Ext4CreateDentry (FileName, Directory->Dentry);=0D +=0D + if (!File->Dentry) {=0D + goto Error;=0D + }=0D }=0D =0D Status =3D Ext4InitExtentsMap (File);=0D @@ -234,9 +238,6 @@ Ext4OpenDirent ( goto Error;=0D }=0D =0D - // This should not fail.=0D - StrCpyS (File->FileName, DestMax, FileName);=0D -=0D File->InodeNum =3D Entry->inode;=0D =0D Ext4SetupFile (File, Partition);=0D @@ -255,8 +256,8 @@ Ext4OpenDirent ( =0D Error:=0D if (File !=3D NULL) {=0D - if (File->FileName !=3D NULL) {=0D - FreePool (File->FileName);=0D + if (File->Dentry !=3D NULL) {=0D + Ext4UnrefDentry (File->Dentry);=0D }=0D =0D if (File->ExtentsMap !=3D NULL) {=0D @@ -333,52 +334,47 @@ Ext4OpenVolume ( OUT EFI_FILE_PROTOCOL **Root=0D )=0D {=0D - EXT4_INODE *RootInode;=0D - EFI_STATUS Status;=0D - EXT4_FILE *RootDir;=0D + EXT4_INODE *RootInode;=0D + EFI_STATUS Status;=0D + EXT4_FILE *RootDir;=0D + EXT4_PARTITION *Partition;=0D =0D - // 2 is always the root inode number in ext4=0D - Status =3D Ext4ReadInode ((EXT4_PARTITION *)This, 2, &RootInode);=0D + Partition =3D (EXT4_PARTITION *)This;=0D +=0D + Status =3D Ext4ReadInode (Partition, EXT4_ROOT_INODE_NR, &RootInode);=0D =0D if (EFI_ERROR (Status)) {=0D - DEBUG ((DEBUG_ERROR, "[ext4] Could not open root inode - status %x\n",= Status));=0D + DEBUG ((DEBUG_ERROR, "[ext4] Could not open root inode - error %r\n", = Status));=0D return Status;=0D }=0D =0D RootDir =3D AllocateZeroPool (sizeof (EXT4_FILE));=0D =0D - if (!RootDir) {=0D + if (RootDir =3D=3D NULL) {=0D FreePool (RootInode);=0D return EFI_OUT_OF_RESOURCES;=0D }=0D =0D - // The filename will be "\"(null terminated of course)=0D - RootDir->FileName =3D AllocateZeroPool (2 * sizeof (CHAR16));=0D -=0D - if (!RootDir->FileName) {=0D - FreePool (RootDir);=0D - FreePool (RootInode);=0D - return EFI_OUT_OF_RESOURCES;=0D - }=0D -=0D - RootDir->FileName[0] =3D L'\\';=0D -=0D RootDir->Inode =3D RootInode;=0D - RootDir->InodeNum =3D 2;=0D + RootDir->InodeNum =3D EXT4_ROOT_INODE_NR;=0D =0D Status =3D Ext4InitExtentsMap (RootDir);=0D =0D if (EFI_ERROR (Status)) {=0D - FreePool (RootDir->FileName);=0D FreePool (RootInode);=0D FreePool (RootDir);=0D return EFI_OUT_OF_RESOURCES;=0D }=0D =0D - Ext4SetupFile (RootDir, (EXT4_PARTITION *)This);=0D + Ext4SetupFile (RootDir, Partition);=0D *Root =3D &RootDir->Protocol;=0D =0D - InsertTailList (&((EXT4_PARTITION *)This)->OpenFiles, &RootDir->OpenFile= sListNode);=0D + InsertTailList (&Partition->OpenFiles, &RootDir->OpenFilesListNode);=0D +=0D + ASSERT (Partition->RootDentry !=3D NULL);=0D + RootDir->Dentry =3D Partition->RootDentry;=0D +=0D + Ext4RefDentry (RootDir->Dentry);=0D =0D return EFI_SUCCESS;=0D }=0D @@ -525,3 +521,159 @@ Ext4ReadDir ( Out:=0D return Status;=0D }=0D +=0D +/**=0D + Removes a dentry from the other's list.=0D +=0D + @param[in out] Parent Pointer to the parent EXT4_DENTR= Y.=0D + @param[in out] ToBeRemoved Pointer to the child EXT4_DENTRY= .=0D +**/=0D +STATIC=0D +VOID=0D +Ext4RemoveDentry (=0D + IN OUT EXT4_DENTRY *Parent,=0D + IN OUT EXT4_DENTRY *ToBeRemoved=0D + )=0D +{=0D + EXT4_DENTRY *D;=0D + LIST_ENTRY *Entry;=0D + LIST_ENTRY *NextEntry;=0D +=0D + BASE_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Parent->Children) {=0D + D =3D EXT4_DENTRY_FROM_DENTRY_LIST (Entry);=0D +=0D + if (D =3D=3D ToBeRemoved) {=0D + RemoveEntryList (Entry);=0D + return;=0D + }=0D + }=0D +=0D + DEBUG ((DEBUG_ERROR, "[ext4] Ext4RemoveDentry did not find the asked-for= dentry\n"));=0D +}=0D +=0D +/**=0D + Adds a dentry to the other's list.=0D +=0D + The dentry that is added to the other one's list gets ->Parent set to P= arent,=0D + and the parent gets its reference count incremented.=0D +=0D + @param[in out] Parent Pointer to the parent EXT4_DENTR= Y.=0D + @param[in out] ToBeAdded Pointer to the child EXT4_DENTRY= .=0D +**/=0D +STATIC=0D +VOID=0D +Ext4AddDentry (=0D + IN OUT EXT4_DENTRY *Parent,=0D + IN OUT EXT4_DENTRY *ToBeAdded=0D + )=0D +{=0D + ToBeAdded->Parent =3D Parent;=0D + InsertTailList (&Parent->Children, &ToBeAdded->ListNode);=0D + Ext4RefDentry (Parent);=0D +}=0D +=0D +/**=0D + Creates a new dentry object.=0D +=0D + @param[in] Name Name of the dentry.=0D + @param[in out opt] Parent Parent dentry, if it's not NULL.=0D +=0D + @return The new allocated and initialised dentry.=0D + The ref count will be set to 1.=0D +**/=0D +EXT4_DENTRY *=0D +Ext4CreateDentry (=0D + IN CONST CHAR16 *Name,=0D + IN OUT EXT4_DENTRY *Parent OPTIONAL=0D + )=0D +{=0D + EXT4_DENTRY *Dentry;=0D + EFI_STATUS Status;=0D +=0D + Dentry =3D AllocateZeroPool (sizeof (EXT4_DENTRY));=0D +=0D + if (Dentry =3D=3D NULL) {=0D + return NULL;=0D + }=0D +=0D + Dentry->RefCount =3D 1;=0D +=0D + // This StrCpyS should not fail.=0D + Status =3D StrCpyS (Dentry->Name, ARRAY_SIZE (Dentry->Name), Name);=0D +=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + InitializeListHead (&Dentry->Children);=0D +=0D + if (Parent !=3D NULL) {=0D + Ext4AddDentry (Parent, Dentry);=0D + }=0D +=0D + DEBUG ((DEBUG_FS, "[ext4] Created dentry %s\n", Name));=0D +=0D + return Dentry;=0D +}=0D +=0D +/**=0D + Increments the ref count of the dentry.=0D +=0D + @param[in out] Dentry Pointer to a valid EXT4_DENTRY.=0D +**/=0D +VOID=0D +Ext4RefDentry (=0D + IN OUT EXT4_DENTRY *Dentry=0D + )=0D +{=0D + UINTN OldRef;=0D +=0D + OldRef =3D Dentry->RefCount;=0D +=0D + Dentry->RefCount++;=0D +=0D + // I'm not sure if this (Refcount overflow) is a valid concern,=0D + // but it's better to be safe than sorry.=0D + ASSERT (OldRef < Dentry->RefCount);=0D +}=0D +=0D +/**=0D + Deletes the dentry.=0D +=0D + @param[in out] Dentry Pointer to a valid EXT4_DENTRY.=0D +**/=0D +STATIC=0D +VOID=0D +Ext4DeleteDentry (=0D + IN OUT EXT4_DENTRY *Dentry=0D + )=0D +{=0D + if (Dentry->Parent) {=0D + Ext4RemoveDentry (Dentry->Parent, Dentry);=0D + Ext4UnrefDentry (Dentry->Parent);=0D + }=0D +=0D + DEBUG ((DEBUG_FS, "[ext4] Deleted dentry %s\n", Dentry->Name));=0D + FreePool (Dentry);=0D +}=0D +=0D +/**=0D + Decrements the ref count of the dentry.=0D + If the ref count is 0, it's destroyed.=0D +=0D + @param[in out] Dentry Pointer to a valid EXT4_DENTRY.=0D +=0D + @retval True if it was destroyed, false if it's alive.=0D +**/=0D +BOOLEAN=0D +Ext4UnrefDentry (=0D + IN OUT EXT4_DENTRY *Dentry=0D + )=0D +{=0D + Dentry->RefCount--;=0D +=0D + if (Dentry->RefCount =3D=3D 0) {=0D + Ext4DeleteDentry (Dentry);=0D + return TRUE;=0D + }=0D +=0D + return FALSE;=0D +}=0D diff --git a/Features/Ext4Pkg/Ext4Dxe/Ext4Disk.h b/Features/Ext4Pkg/Ext4Dxe= /Ext4Disk.h index b387ebcd36a6..070eb5a9c827 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Ext4Disk.h +++ b/Features/Ext4Pkg/Ext4Dxe/Ext4Disk.h @@ -451,4 +451,7 @@ typedef struct { typedef UINT64 EXT4_BLOCK_NR;=0D typedef UINT32 EXT4_INO_NR;=0D =0D +// 2 is always the root inode number in ext4=0D +#define EXT4_ROOT_INODE_NR 2=0D +=0D #endif=0D diff --git a/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h b/Features/Ext4Pkg/Ext4Dxe/= Ext4Dxe.h index 1aafc60ab57d..db938c25244d 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h +++ b/Features/Ext4Pkg/Ext4Dxe/Ext4Dxe.h @@ -55,6 +55,7 @@ Ext4OpenPartition ( );=0D =0D typedef struct _Ext4File EXT4_FILE;=0D +typedef struct _Ext4_Dentry EXT4_DENTRY;=0D =0D typedef struct _Ext4_PARTITION {=0D EFI_SIMPLE_FILE_SYSTEM_PROTOCOL Interface;=0D @@ -81,8 +82,68 @@ typedef struct _Ext4_PARTITION { UINT32 InitialSeed;=0D =0D LIST_ENTRY OpenFiles;=0D +=0D + EXT4_DENTRY *RootDentry;=0D } EXT4_PARTITION;=0D =0D +/**=0D + This structure represents a directory entry inside our directory entry = tree.=0D + For now, it will be used as a way to track file names inside our openin= g code,=0D + but it may very well be used as a directory cache in the future.=0D + Because it's not being used as a directory cache right now,=0D + an EXT4_DENTRY structure is not necessarily unique name-wise in the lis= t of=0D + children. Therefore, the dentry tree does not accurately reflect the fi= lesystem=0D + structure.=0D + */=0D +struct _Ext4_Dentry {=0D + UINTN RefCount;=0D + CHAR16 Name[EXT4_NAME_MAX + 1];=0D + EXT4_INO_NR Inode;=0D + struct _Ext4_Dentry *Parent;=0D + LIST_ENTRY Children;=0D + LIST_ENTRY ListNode;=0D +};=0D +=0D +#define EXT4_DENTRY_FROM_DENTRY_LIST(Node) BASE_CR (Node, EXT4_DENTRY, Li= stNode)=0D +=0D +/**=0D + Creates a new dentry object.=0D +=0D + @param[in] Name Name of the dentry.=0D + @param[in out opt] Parent Parent dentry, if it's not NULL.=0D +=0D + @return The new allocated and initialised dentry.=0D + The ref count will be set to 1.=0D +**/=0D +EXT4_DENTRY *=0D +Ext4CreateDentry (=0D + IN CONST CHAR16 *Name,=0D + IN OUT EXT4_DENTRY *Parent OPTIONAL=0D + );=0D +=0D +/**=0D + Increments the ref count of the dentry.=0D +=0D + @param[in out] Dentry Pointer to a valid EXT4_DENTRY.=0D +**/=0D +VOID=0D +Ext4RefDentry (=0D + IN OUT EXT4_DENTRY *Dentry=0D + );=0D +=0D +/**=0D + Decrements the ref count of the dentry.=0D + If the ref count is 0, it's destroyed.=0D +=0D + @param[in out] Dentry Pointer to a valid EXT4_DENTRY.=0D +=0D + @retval True if it was destroyed, false if it's alive.=0D +**/=0D +BOOLEAN=0D +Ext4UnrefDentry (=0D + IN OUT EXT4_DENTRY *Dentry=0D + );=0D +=0D /**=0D Opens and parses the superblock.=0D =0D @@ -126,7 +187,7 @@ Ext4OpenSuperblock ( @param[in] Partition Pointer to the opened ext4 partition.=0D @return The media ID associated with the partition.=0D **/=0D -#define EXT4_MEDIA_ID(Partition) Partition->BlockIo->Media->MediaId=0D +#define EXT4_MEDIA_ID(Partition) Partition->BlockIo->Media->MediaId=0D =0D /**=0D Reads from the partition's disk using the DISK_IO protocol.=0D @@ -299,11 +360,13 @@ struct _Ext4File { UINT64 Position;=0D =0D EXT4_PARTITION *Partition;=0D - CHAR16 *FileName;=0D =0D ORDERED_COLLECTION *ExtentsMap;=0D =0D LIST_ENTRY OpenFilesListNode;=0D +=0D + // Owning reference to this file's directory entry.=0D + EXT4_DENTRY *Dentry;=0D };=0D =0D #define EXT4_FILE_FROM_OPEN_FILES_NODE(Node) BASE_CR (Node, EXT4_FILE, Op= enFilesListNode)=0D diff --git a/Features/Ext4Pkg/Ext4Dxe/File.c b/Features/Ext4Pkg/Ext4Dxe/Fil= e.c index a3eff2b48a07..021d10b1edfb 100644 --- a/Features/Ext4Pkg/Ext4Dxe/File.c +++ b/Features/Ext4Pkg/Ext4Dxe/File.c @@ -207,7 +207,7 @@ Ext4Open ( =0D FileName +=3D Length;=0D =0D - if (StrCmp(PathSegment, L".") =3D=3D 0) {=0D + if (StrCmp (PathSegment, L".") =3D=3D 0) {=0D // Opens of "." are a no-op=0D continue;=0D }=0D @@ -272,7 +272,7 @@ Ext4Open ( =0D *NewHandle =3D &Current->Protocol;=0D =0D - DEBUG ((DEBUG_FS, "Opened filename %s\n", Current->FileName));=0D + DEBUG ((DEBUG_FS, "[ext4] Opened filename %s\n", Current->Dentry->Name))= ;=0D return EFI_SUCCESS;=0D }=0D =0D @@ -312,9 +312,9 @@ Ext4CloseInternal ( =0D DEBUG ((DEBUG_FS, "[ext4] Closed file %p (inode %lu)\n", File, File->Ino= deNum));=0D RemoveEntryList (&File->OpenFilesListNode);=0D - FreePool (File->FileName);=0D FreePool (File->Inode);=0D Ext4FreeExtentsMap (File);=0D + Ext4UnrefDentry (File->Dentry);=0D FreePool (File);=0D return EFI_SUCCESS;=0D }=0D @@ -522,11 +522,11 @@ Ext4GetFileInfo ( UINTN NeededLength;=0D CONST CHAR16 *FileName;=0D =0D - if (File->InodeNum =3D=3D 2) {=0D + if (File->InodeNum =3D=3D EXT4_ROOT_INODE_NR) {=0D // Root inode gets a filename of "", regardless of how it was opened.= =0D FileName =3D L"";=0D } else {=0D - FileName =3D File->FileName;=0D + FileName =3D File->Dentry->Name;=0D }=0D =0D FileNameLen =3D StrLen (FileName);=0D @@ -717,15 +717,6 @@ Ext4DuplicateFile ( =0D CopyMem (File->Inode, Original->Inode, Partition->InodeSize);=0D =0D - File->FileName =3D AllocateZeroPool (StrSize (Original->FileName));=0D - if (File->FileName =3D=3D NULL) {=0D - FreePool (File->Inode);=0D - FreePool (File);=0D - return NULL;=0D - }=0D -=0D - StrCpyS (File->FileName, StrLen (Original->FileName) + 1, Original->File= Name);=0D -=0D File->Position =3D 0;=0D Ext4SetupFile (File, Partition);=0D File->InodeNum =3D Original->InodeNum;=0D @@ -733,12 +724,15 @@ Ext4DuplicateFile ( =0D Status =3D Ext4InitExtentsMap (File);=0D if (EFI_ERROR (Status)) {=0D - FreePool (File->FileName);=0D FreePool (File->Inode);=0D FreePool (File);=0D return NULL;=0D }=0D =0D + File->Dentry =3D Original->Dentry;=0D +=0D + Ext4RefDentry (File->Dentry);=0D +=0D InsertTailList (&Partition->OpenFiles, &File->OpenFilesListNode);=0D =0D return File;=0D diff --git a/Features/Ext4Pkg/Ext4Dxe/Inode.c b/Features/Ext4Pkg/Ext4Dxe/In= ode.c index 982b19c763d0..63cecec1f7cf 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Inode.c +++ b/Features/Ext4Pkg/Ext4Dxe/Inode.c @@ -89,7 +89,6 @@ Ext4Read ( IN OUT UINTN *Length=0D )=0D {=0D - DEBUG ((DEBUG_FS, "[ext4] Ext4Read(%s, Offset %lu, Length %lu)\n", File-= >FileName, Offset, *Length));=0D EXT4_INODE *Inode;=0D UINT64 InodeSize;=0D UINT64 CurrentSeek;=0D @@ -116,6 +115,8 @@ Ext4Read ( RemainingRead =3D *Length;=0D BeenRead =3D 0;=0D =0D + DEBUG ((DEBUG_FS, "[ext4] Ext4Read(%s, Offset %lu, Length %lu)\n", File-= >Dentry->Name, Offset, *Length));=0D +=0D if (Offset > InodeSize) {=0D return EFI_DEVICE_ERROR;=0D }=0D diff --git a/Features/Ext4Pkg/Ext4Dxe/Partition.c b/Features/Ext4Pkg/Ext4Dx= e/Partition.c index 2258bac76a4f..afa0392024ec 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Partition.c +++ b/Features/Ext4Pkg/Ext4Dxe/Partition.c @@ -108,6 +108,7 @@ Ext4UnmountAndFreePartition ( LIST_ENTRY *Entry;=0D LIST_ENTRY *NextEntry;=0D EXT4_FILE *File;=0D + BOOLEAN DeletedRootDentry;=0D =0D Partition->Unmounting =3D TRUE;=0D Ext4CloseInternal (Partition->Root);=0D @@ -118,6 +119,12 @@ Ext4UnmountAndFreePartition ( Ext4CloseInternal (File);=0D }=0D =0D + DeletedRootDentry =3D Ext4UnrefDentry (Partition->RootDentry);=0D +=0D + if (!DeletedRootDentry) {=0D + DEBUG ((DEBUG_ERROR, "[ext4] Failed to delete root dentry - resource l= eak present.\n"));=0D + }=0D +=0D FreePool (Partition->BlockGroups);=0D FreePool (Partition);=0D =0D diff --git a/Features/Ext4Pkg/Ext4Dxe/Superblock.c b/Features/Ext4Pkg/Ext4D= xe/Superblock.c index 8231831115fa..c321d8c3d86d 100644 --- a/Features/Ext4Pkg/Ext4Dxe/Superblock.c +++ b/Features/Ext4Pkg/Ext4Dxe/Superblock.c @@ -167,8 +167,11 @@ Ext4OpenSuperblock ( // accidentally opening an ext2/3/4 filesystem we don't understand, whic= h would be disasterous.=0D =0D if (Partition->FeaturesIncompat & ~gSupportedIncompatFeat) {=0D - DEBUG ((DEBUG_ERROR, "[ext4] Unsupported features %lx\n",=0D - Partition->FeaturesIncompat & ~gSupportedIncompatFeat));=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "[ext4] Unsupported features %lx\n",=0D + Partition->FeaturesIncompat & ~gSupportedIncompatFeat=0D + ));=0D return EFI_UNSUPPORTED;=0D }=0D =0D @@ -247,7 +250,7 @@ Ext4OpenSuperblock ( =0D Partition->BlockGroups =3D Ext4AllocAndReadBlocks (Partition, NrBlocks, = Partition->BlockSize =3D=3D 1024 ? 2 : 1);=0D =0D - if (!Partition->BlockGroups) {=0D + if (Partition->BlockGroups =3D=3D NULL) {=0D return EFI_OUT_OF_RESOURCES;=0D }=0D =0D @@ -255,13 +258,27 @@ Ext4OpenSuperblock ( Desc =3D Ext4GetBlockGroupDesc (Partition, Index);=0D if (!Ext4VerifyBlockGroupDescChecksum (Partition, Desc, Index)) {=0D DEBUG ((DEBUG_ERROR, "[ext4] Block group descriptor %u has an invali= d checksum\n", Index));=0D + FreePool (Partition->BlockGroups);=0D return EFI_VOLUME_CORRUPTED;=0D }=0D }=0D =0D + // RootDentry will serve as the basis of our directory entry tree.=0D + Partition->RootDentry =3D Ext4CreateDentry (L"\\", NULL);=0D +=0D + if (Partition->RootDentry =3D=3D NULL) {=0D + FreePool (Partition->BlockGroups);=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D // Note that the cast below is completely safe, because EXT4_FILE is a s= pecialisation of EFI_FILE_PROTOCOL=0D Status =3D Ext4OpenVolume (&Partition->Interface, (EFI_FILE_PROTOCOL **)= &Partition->Root);=0D =0D + if (EFI_ERROR (Status)) {=0D + Ext4UnrefDentry (Partition->RootDentry);=0D + FreePool (Partition->BlockGroups);=0D + }=0D +=0D return Status;=0D }=0D =0D --=20 2.33.0